Цитата
А кто как организует код программы, чтобы программа детектировала (обнаруживала) случайные переходы из одной точки программы в другую, вызванные воздействием помехонесущего электромагнитного поля
Детектировать случайный переход из одной точки программы в другую своевременно и безболезненно для текущей выполняющейся программы невозможно. Стало быть вопрос лишь в масштабах последствий такого сбоя (по убыванию):
1. Нарушение памяти программ.
2. Нарушение содержимого регистров / памяти данных - в последствии к "подвисанию" неверной работе части программы.
3. Порча незначительных данных например пакета защищенного кодом защиты. (плохо конечно, но с этим можно смириться).
4. Чисто везение, прыжек в участок кода - который ничего не испортил (например из финализации одной функции в финализацию другой с подобными параметрами). Везение рассматривать не будем.
Итого лечить надо только 1 и 2.
Первое лечится с помощью дублирования кода программы. Определяется и устраняется эта ошибка при очередной перезагрузке устройства. Как правило после такого сбоя устройство перезагружается по WDT.
Второе - система продолжает работать но часть функций отказала. Лечится перезагрузкой, перезагрузка делается опять с помощью WDT.
Вопрос в том где и как сбрасывать WDT чтобы последствия сбоя были 100% устранены. Решить этот вопрос можно например введя мониторинг статуса каждой задачи. Если используется RTOS, то сделать это достаточно просто - idle task (задача с самым низким приоритетом) периодически оцнивает состояние каждой задачи, если все задачи в порядке - WDT сбрасывается. Состояние же каждой задачи должно определяться индивидуально, для каждой задачи свой отдельный таймаут.
Пусть имеется некое устройство, которое занимается опросом некоторых датчиков по одному интерфейсу, и отправляет результаты - по другому. Тогда работу этого устройства можно разбить на 5 задач:
1. idle (занимается контролем WDT)
2. обслуживание передачи по интерфейсу датчиков.
3. обслуживание приема по интерфейсу датчиков.
4. обслуживание передачи по интерфейсу хоста.
5. обслуживание приема по интерфейсу хоста.
Статус первой задачи всегда Ок (коль уж в нее попали, то стало быть она работает).
Статус 2-й задачи переходит в состояние Alert если счетчик отправленных пакетов не изменяется в течение заданного таймаута.
Статус 3-й задачи определяется таймаутом "за n секунд не принято ни одного байта"
Статус 4-й задачи определяется аналогично 2-й
и наконец статус 5-й - аналогично 3-й.
Если хотя бы одна задача не в порядке, то в задаче 1 запрещаем прерывания и подвешиваем систему циклом
while( K * WDT_CYCLE)
__no_operation();
где
WDT_CYCLE - константа, соответвующая количеству циклов эквивалентное интервалу WDT.
K - коэффициен >1, для гарантии сброса МК.
Если вдруг получается так, что мы выходим из этого цикла. Тогда WDT вероятно тоже сбойнул - пытаемся:
1. Выполнить аппаратный сброс (если заранее предусмотрели управление внешней схемой сброса).
2. Выполнить прыжек по RESET вектору (т.к. хуже уже все равно не будет).
PS: До сих пор, против "случайных прыжков" этих программных мер мне хватало с головой.