Проблема с ком-портом на контроллерах типа ADAM-5510M или бага в RDC R8800. |
Ответить |
Автор | |
Новичок Присоединился: 09 Сентябрь 2005 Категория: Russian Federation Online Status: Offline Публикации: 8 |
Опубликовано: 13 Сентябрь 2005 17:37 |
Проблема При инициировании приемо-передачи данных от центрального компьютера контроллеру, программа в контроллере, написанная полностью на ассемблере и не содержащая чужого кода, повисала. Время, через которое происходило зависание зависило от двух факторов: частоты приемо-передачи и НЕКОЕГО СЛУЧАЙНОГО ФАКТОРА. То есть при зафиксированной частоте приемо-передачи, время, через которое система могла зависнуть, варьировалось от секунд до нескольких минут. Анализ и решение вкратце Система зависала из-за порчи системных данных моим обработчиком прерывания от ком-порта. Порча данных происходила из-за того, что сегмент данных в момент работы моего обработчика не соответствовал сегменту, с которым работает (должна работать) моя программа. Несоответствие сегмента данных происходило из-за того, что параллельно с моей программой каждые 55 мс вызывался обработчик прерывания от таймера 0, написанный фирмой Advantech, в котором разрешались вложенные прерывания до восстановления регистра сегмента данных. Во время работы обработчика прерывания от таймера 0 после разрешения прерываний происходило прерывание от ком-порта и включался мой обработчик, который имел дело с некорректным сегментом данных, т.к. последний не был еще восстановлен. Однако, такая проблема актуальна только для процессоров RDC R8800, т.к. Amd188Em точно следуют своей спецификации, в которой сказано, что после разрешения прерываний выполняется как минимум еще одна инструкция, которая в нашем случае как раз и должна успевать восстановить регистр сегмента данных. Поэтому на контроллерах ADAM-5510, в которых стоит Amd188Em данная проблема отсутствует. Процессоры же RDC R8800, которые стоят в контроллерах ADAM-5510M, ADAM-5510E данную спецификацию НАРУШАЮТ, тем самым не являясь полным аналогом Amd188Em. Поскольку изменить обработчик фирмы Advantech невозможно (обработчик защищен от записи), то существует несколько решений:
ПРИ ИСПОЛЬЗОВАНИИ СТАНДАРТНЫХ БИБЛИОТЕК ПРОБЛЕМА ОТСУТСТВУЕТ, т.к. стандартный обработчик от ком-порта принудительно устанавливает требуемый сегмент данных. ПРИ ПРОГРАММИРОВАНИИ БЕЗ ИСПОЛЬЗОВАНИЯ БИБЛИОТЕК ПРОБЛЕМА - некорректное поведение инструкции sti и соответственно стандартного обработчика прерывания от таймера 0, входящего в состав операционной системы - РАСПРОСТРАНЯЕТСЯ НА ВСЕ ОБРАБОТЧИКИ ПРЕРЫВАНИЯ И НЕ ОБЯЗАТЕЛЬНО МОЖЕТ БЫТЬ СВЯЗАНА С КОМ-ПОРТОМ. Основные выводы 1. Инструкция STI процессора RDC R8800 НАРУШАЕТ СПЕЦИФИКАЦИЮ Amd188Em. 2. Стандартный обработчик прерывания от таймера 0, входящий в состав ОС фирмы Advantech не учитывает данный факт и может приводить к некорректному поведению пользовательских программ, которые полагаются на корректное значение регистра сегмента данных ds. Вопросы к аудитории и экспертам 1) Сталкивался ли кто-либо с подобным? 2) Есть ли у кого-либо замечания по поводу написанного (возможно я что-то не так понимаю или где-то ошибаюсь)? В случае необходимости могу выслать полностью исходники на ассемблере + документацию. Программа в com-формате занимает 2.5 кБ. Замечания В процессе сужения области поиска на контроллере ADAM-5510E из-за очередного зависания контроллер приказал долго жить - теперь после его включения при загрузке появляется надпись "Sector not found. Error finding drive A. Abort, Retry, Fail?" Все остальные испытания были продолжены на контроллере ADAM-5510M. Поэтому как только в процессе анализа проблемы стало ясно, что зависания происходят из-за некорректного сегмента данных, зависания были заменены на включение индикатора COMM, чтобы не испортить еще один контроллер, а именно: если сегмент данных в обработчике прерывания от ком-порта не соответствовал корректному, включался индикатор COMM, после чего сегмент данных устанавливался в корректное значение принудительным образом. Более подробно 1. Программа системы управления была максимально сокращена до минимально необходимой части, были оставлены: обработчик прерывания от ком-порта; В результате тестовая программа также зависала через случайный промежуток времени. 2. После последовательного сужения области поиска было найдено, что система перестает виснуть (1.5 часа работала без сбоя, после чего была мною остановлена), если в обработчике прерывания от ком-порта принудительно устанавливать регистр сегмента данных в корректное значение. Мой обработчик прерывания от ком-порта использует внутренние данные, расположенные в том же сегменте, что и код, т.е. ds = cs, где При этом мой обработчик НИКАК НЕ НАСТРАИВАЛ РЕГИСТР СЕГМЕНТА ДАННЫХ, полагая, что он совпадает с регистром сегмента кода. Данное предположение работает до тех пор, ПОКА НЕТ ЧУЖОГО РАБОТАЮЩЕГО КОДА. Отсюда был сделан вывод, что кто-то изменяет регистр сегмента данных перед вызовом моего обработчика. 3. Были проанализированы управляющие регистры для всех источников прерывания, и выяснено, что одновременно с моей программой работают 2 таймера: таймер 0 и таймер 2. Таймер 2 является опорным для таймера 0, срабатывая каждые 258 мкс. При этом прерывание для таймера 2 не генерится (соответственно отсутствует обработчик). Обработчик прерывания от таймера 0 вызывается каждые 55 мс (213 * 258 мкс) и обновляет так называемый регистр тиков таймера, а также вызывает пользовательский обработчик таймера 1Ch (DOS), в котором прописана одна инструкция iret. (Пользователь DOSа может переопределить обработчик 1Ch). После дизассемблирования дампа области памяти, где находится обработчик прерывания от таймера 0, было получено:
Из приведенного кода видно, что регистр сегмента данных восстанавливается ПОСЛЕ ТОГО КАК РАЗРЕШАЮТСЯ ВЛОЖЕННЫЕ ПРЕРЫВАНИЯ! ОДНАКО НИ ОДИН ОБРАБОТЧИК ПРЕРЫВАНИЯ НЕ МОЖЕТ БЫТЬ ВЫЗВАН СРАЗУ ПОСЛЕ ИНСТРУКЦИИ STI СОГЛАСНО ДОКУМЕНТАЦИИ НА МИКРОПРОЦЕССОР. Т.к. на контроллере ADAM-5510 стоит микропроцессор AMD188EM, то там 4. Для начала, чтобы убедиться в том, что сегмент данных портится обработчиком прерывания от таймера, при старте был отключен таймер 0. Зависания прекратились. Далее, чтобы убедиться в том, что крах (точнее начало краха) происходит именно там, где указано выше в листинге, в обработчик прерывания от ком-порта были добавлены инструкции (выключение таймера 0 при старте программы при этом было убрано): если ds изменился (ds <> cs), то сделать ds корректным (ds = cs) В главном цикле, в случае появления флага краха, в терминал выводились _ds, _cs:_ip В результате испытания, через случайный промежуток времени система "повисла" - зажгла индикатор COMM (повисание не произошло, т.к. ds устанавливался в корректное значение принудительно), а в терминале был выведен адрес ТОЧКИ КРАХА, т.е. того места с которого был вызван обработчик прерывания от ком-порта. ds оказался равным 0040, а точка краха пришлась на инструкцию pop ds, т.е. перед тем как выполнить инструкцию pop ds в обработчике прерывания от таймера 0, обработчик прервался и был вызван мой обработчик от ком-порта, который уже имел дело с некорректным ds. При некорректном ds любое изменение переменной программы (например, заполнение буфера получаемыми данными, ведение счетчика принятых данных и т.д.) происходит не в том сегменте данных, т.е. происходит порча данных в системной области, т.к. ds указывает на системные данные. В результате система повисает. Данные испытания проводились многократно. Система всегда "зависала" именно в вышеуказанной точке краха. Дополнения (уточнения) 1. Вся программа была написана на ассемблере и транслировалась в com-формат. 2. ТОЧКА КРАХА является условным названием, т.к. очевидно, что в данной точке никакого краха или зависания не происходит, а лишь начинается "дорога к смерти", поскольку регистр ds еще не восстановлен. Повиснет система гораздо позже - все зависит от того, куда записываются данные в обработчике прерывания от ком-порта, и насколько важные данные они затрут. 3. Данная проблема отсутствует на ADAMах-5510, т.к. там стоят микроконтроллеры Amd188Em, которые (к счастью) соответствуют документации (по крайней мере в том, что касается инструкции STI). 4. Данная проблема актуальна также и для ADAM-5510E, т.к. там то же ядро, что и в ADAM-5510M. |
|
Ответить |
Переход на форум | Права доступа на форуме Вы не можете публиковать новые темы в этом форуме Вы не можете отвечать на сообщения в этом форуме Вы не можете удалять Ваши сообщения на этом форуме Вы не можете редактировать Ваши сообщения на этом форуме Вы не можете создавать голосования на этом форуме Вы не можете выражать своё мнение в голосованиях на этом форуме |