Сторожевой таймер в надежных встраиваемых системах

Сторожевой таймер (watchdog timer, WDT) - механизм безопасности, который позволяет вернуть систему в рабочий режим в случае сбоя. По этой причине сторожевой таймер должен быть грамотно разработан и реализован.
2157
В избранное

Небольшая ошибка в сложной встроенной системе может привести к ее сбою или, что еще хуже, к работе в опасном режиме. Ошибки - не единственная проблема. Совершенное разработанное и проверенное устройство, на котором выполняется идеальный протестированный код, все равно может выйти из строя. Сторожевой таймер (watchdog timer, WDT) - это механизм безопасности, который позволяет вернуть систему в рабочий режим в случае сбоя. По этой причине сторожевой таймер должен быть грамотно разработан и реализован.

Как правило, WTD состоит из счетчика и тактирующего устройства. Значение счетчика по сигналам тактового устройства постоянно уменьшается. Когда оно достигает нуля, генерируется короткий импульс, который сбрасывает и перезапускает систему.

Приложению необходимо периодически, до срабатывания таймера, обновлять значение счетчика, иначе WTD вызовет перезагрузку системы. После обновления счетчика его значение вновь продолжит уменьшаться. Проще говоря, WDT постоянно «следит» за выполнением кода и перезагружает систему, если программное обеспечение зависает или больше не выполняет правильную последовательность кода. Перезагрузка значения WDT с помощью программного обеспечения называется “kicking the watchdog” (перезапуск сторожевого таймера).

Особенности разработки с применением сторожевых таймеров

  • Источник тактовых импульсов для WDT должен быть независимым, в том смысле, что он не должен тактироваться от системного генератора. В случае, если основной тактовый генератор штатно останавливается, например, при переходе системы в режим сна, сторожевой таймер не будет работать.
  • После завершения инициализации WDT программное обеспечение не должно иметь возможности остановить таймер или изменить значения его управляющих регистров, что позволило бы ошибочному коду остановить его. Некоторые микроконтроллеры обладают такой функцией защиты.
  • После сброса от сторожевого таймера система должна вернуться в предшествовавшее этому событию состояние вне зависимости от того, что привело к срабатыванию таймера.
  • Последовательность перезапуска сторожевого таймера должна гарантировать, что все подключенные периферийные устройства также будут возвращены в состояние, предшествовавшее перезапуску.

Типы сторожевых таймеров

WDT могут быть разделены на две больших категории – внешние сторожевые таймеры (рисунок 1) и внутренние, или встроенные (рисунок 2). Подавляющее большинство современных микроконтроллеров имеют встроенные сторожевые таймеры. Производители также предлагают специализированные микросхемы сторожевых таймеров.

Выход внешнего WDT подключается к выводу сброса контроллера. Один или несколько выводов контроллера используются для перезапуска сторожевого таймера.

Рис. 1. Внешний сторожевой таймер Рис. 2. Внутренний сторожевой таймер
Рис. 1. Внешний сторожевой таймер Рис. 2. Внутренний сторожевой таймер

Проблемы, возникающие при отсутствии сторожевого таймера

В 1994 году для наблюдения за Луной и астероидом 1620 Geo был запущен зонд «Клементина». После нескольких месяцев работы программный сбой привел к включению контрольного двигателя на 11 минут, что привело к большому расходу топлива и вращению аппарата со скоростью 80 об/мин. Управление было в конечном итоге восстановлено, но слишком поздно для успешного завершения миссии.

Даже если код был тщательно спроектирован и реализован, ошибка всегда возможна. Если устройство тестируется на устойчивость к электромагнитным помехам, высоковольтный импульс может привести к модификации программного счетчика или указателя стека. Космические лучи также опасны для цифровой техники и могут привести к искажению содержимого регистров процессора.

В результате переполнения буфера или взаимной блокировки процессов работа программного обеспечения может привести к зависанию системы в бесконечном цикле. В небольших системах достаточно легко обнаружить источник ошибки, но в больших встроенных системах сделать это не так просто. Как правило, используя сторожевой таймер, мы можем быть уверены, что система не зависнет навсегда.

Системное программное обеспечение также не должно зацикливаться на длительный период. Общим решением является сброс системы, и в этом поможет сторожевой таймер.

Структура систем, использующих сторожевой таймер

Программа в ходе своего выполнения постоянно должна обновлять сторожевой таймер. В некоторых случаях для обновления значения сторожевого таймера необходимо передать ему специальную последовательность байтов. Это снижает вероятность появления ошибки, способной обновить сторожевой таймер.

После переполнения WDT активирует линию сброса процессора. В некоторых процессорах и контроллерах перед сбросом системы генерируется отдельное прерывание, своеобразное предупреждение от сторожевого таймера о предстоящем сбросе. Благодаря этому мы можем сохранить полезную информацию наподобие значения регистра статуса в энергонезависимой памяти для последующего анализа после рестарта системы. Путем анализа журналов сброса можно выявить основную причину сброса, и, возможно, причину сбоя.

Сторожевой таймер также может быть использован для вывода устройства из спящего режима или режима ожидания. В спящем режиме срабатывание сторожевого таймера не сбрасывает систему, а просто переводит ее в активный режим.

Для надежной разработки внедрение сторожевого таймера является обязательным.

Период срабатывания сторожевого таймера

Для корректного выбора интервала срабатывания сторожевого таймера необходимо четкое понимание о возможных длительностях программных циклов. Вариации количества возникающих прерываний или дополнительное время, необходимое обработчику прерывания, могут изменять типичную длительность программного цикла. Программные временные задержки также могут увеличивать длительность программного цикла. В приложении с длительными задержками в различных местах между участками кода управление сторожевым таймером может столкнуться с проблемами.

В некоторых критичных задачах важна длительность времени восстановления после сброса, инициированного сторожевым таймером. В таких системах интервал срабатывания сторожевого таймера должен быть выбран очень тщательно. После сброса от сторожевого таймера система должна восстановиться как можно быстрее. К примеру, в случае кардиостимулятора работа должна быть восстановлена за интервал, меньший, чем длительность интервала между ударами сердца. Инициализация после сброса от сторожевого таймера должна быть короче, чем инициализация при включении.

Очень короткие временные интервалы сторожевого таймера могут приводить к лишним перезапускам системы. Если система не критична по времени, интервал сброса лучше выбирать в пределах нескольких секунд.

Сторожевой таймер в однопоточном приложении

Обычно обновление/ перезапуск сторожевого таймера происходит в конце основного цикла, перед уходом на новый круг (рисунок 3).

Типовая схема обновления сторожевого таймера в основном программном цикле приложения

Рис. 3. Типовая схема обновления сторожевого таймера в основном программном цикле приложения

В однопоточном приложении мы можем использовать, к примеру, автомато-теоретический подход, как показано в кодовой вставке ниже. В основном цикле в каждом из состояний проверяется переменная состояния и, в случае совпадения, ее значение изменяется на значение следующего состояния. В том случае, если значение переменной состояния равно трем, происходит обновление сторожевого таймера и возврат к начальному состоянию. Если до истечения интервала сторожевого таймера переменная состояния не равна трем, это значит, что последовательность выполнения кода нарушена и система будет перезагружена по срабатыванию таймера.

—————-CODE——————
main ()
{
for( ; ; )
{
if(State == 0) State = 0x01;
. . .
. . .
if(State == 1)State = 0x02;
. . .
. . .
if(State == 2)State = 0x03;
. . .
. . .
If(State== 0x03)
{
Kickthewatchdog
State= 0;
}
}
}
—————-CODE——————

В некоторых микроконтроллерах интервал встроенного сторожевого таймера не превышает нескольких тысяч миллисекунд. И, если длительность основного программного цикла превышает этот интервал - необходимо учитывать это при разработке программного обеспечения.

К примеру, если длительность основного цикла составляет 500 мс, а максимальный интервал сторожевого таймера – 100 мс, то нет возможности перезапускать его в основном цикле. В данном случае можно настроить один из основных таймеров процессора/ микроконтроллера на срабатывание, к примеру, каждые 50 мс и определить флаг, показывающий, что выполнение программы идет штатно, который будет проверен в конце основного цикла.

—————-CODE——————
main ( )
{
for ( ; ; )
{
. . .
. . .
State= ALIVE;
}
}
—————-CODE——————

Каждые 50 мс по срабатыванию основного таймера проверяется флаг состояния, инкрементируется счетчик. Обновление таймера происходит только в том случае, если система находится в известном состоянии. Если значение счетчика превысило десять (прошло более 500 мс), обработчик при следующем прерывании проверяет флаг состояния, и если он соответствует нормальному исполнению кода, то считается, что программа выполняется корректно. В противном случае выставляется состояние «неизвестное», обновления сторожевого таймера при следующем вызове не будет и система будет перезапущена по истечению интервала сторожевого таймера.

—————-CODE——————
ISR() //50ms free running
{
Count++;
If(Count > 10) //10x50ms
{
Count = 0;

If(State == ALIVE)
{
State = RESET;
}
else
{
State = UNKNOWN;
}
}

If (State != UNKNOWN)
{
Kick the watchdog
}
}
—————-CODE——————

Не стоит доверять обновление сторожевого таймера, без проверки каких-либо условий, обработчику прерываний или отдельной задаче ОСРВ, так как в случае ошибки в основной ветке кода обработка прерываний или выполнение других задач ОСРВ может продолжиться, и условия срабатывания сторожевого таймера никогда не наступят. Такой подход не рекомендуется, так как нет гарантии, что работает основной код.

Сторожевой таймер в приложениях на базе ОСРВ

В многозадачной среде наблюдается множество независимых программных циклов, называемых задачами. Планировщик управляет выполнением задач с учетом их приоритета. Для того чтобы убедиться, что задачи работают штатно, каждая из них должна вносить свой вклад в принятие решения о перезапуске сторожевого таймера.

Одним из способов реализации механизма управления сторожевым таймером является создание отдельной задачи, отслеживающей выполнение остальных, и только она - так называемая «сторожевая задача», или задача сторожевого таймера, - получает возможность управления сторожевым таймером.

Рассмотрим подход, в котором существует слово статуса, и каждый бит этого слова ассоциируется с отдельной задачей. К примеру, в нашей системе запущены три задачи, и каждая из задач будет устанавливать отведенный ей бит в слове статуса в конце своего программного цикла.

Когда задача сторожевого таймера активна, она проверяет, установлены ли задачами их биты (если да - то все три задачи функционируют штатно). Задача обновляет сторожевой таймер и сбрасывает биты состояния других задач в слове статуса. В данном случае приоритет сторожевой задачи должен быть ниже, чем у основных прикладных задач. По завершении своего цикла сторожевая задача переходит в режим ожидания, длительность которого должна быть меньше, чем период сторожевого таймера.

Подход, представленный на рисунке 4, будет работать в том случае, если длительности циклов всех задач будут меньше и длительности периода сторожевого таймера, и периодичности срабатывания задачи сторожевого таймера. Однако в случае, если хотя бы одна из задач не укладывается в этот период по каким-либо причинам (переход в спящее состояние, ожидание события, обработка прерываний), даже при штатном исполнении сторожевая задача, обнаружив неустановленный бит, не обновит таймер, и произойдет перезапуск всей системы.

Более предпочтительным решением является использование метода передачи сообщений, когда каждая задача блокируется в очереди сообщений (рисунок 5). Задача сторожевого таймера будет отправлять сообщения всем задачам и переходить в спящий режим на определенный промежуток времени (меньший, чем период тайм-аута таймера).

Реализация сторожевого таймера в ОСРВ, вариант 1

Рис. 4. Реализация сторожевого таймера в ОСРВ, вариант 1

Реализация сторожевого таймера в ОСРВ, вариант 2

Рис. 5. Реализация сторожевого таймера в ОСРВ, вариант 2

После поступления сообщения в очередь прикладная задача, в соответствии со своим приоритетом, получит управление. Задача считывает сообщение, и, если она была разбужена задачей сторожевого таймера, выставит соответствующий бит в слове статуса. При пробуждении задачи сторожевого таймера происходит проверка активных битов слова статуса задач. Если все они в наличии, сторожевой таймер сбрасывается и слово статуса обнуляется. При таком подходе задача сторожевого таймера должна иметь больший приоритет по сравнению с прикладными задачами. Выбор приоритета сторожевой задачи весьма важен и зависит от общей архитектуры системы.

Журнал: electronicsforu.com

Сравнение позиций

  • ()