Każdy, kto miał do czynienia z elektroniką wie, że jeśli urządzenie przestało działać, należy je zresetować. W niektórych systemach robienie tego ręcznie nie jest możliwe. Przyczyną może być trudny, czy wręcz niemożliwy, dostęp dla operatora np. w przypadku sondy kosmicznej. Są też przypadki, gdy czas potrzebny na zauważenie usterki i ręczny reset jest zbyt długi np. w przypadku aparatury medycznej podtrzymującej życie. W takich sytuacjach z pomocą przychodzi nam watchdog timer.

Zasada działania

Watchdog to dosyć prosty mechanizm, którego zadanie to przywrócenie systemu do działania po zawieszeniu programu. Jest to timer, który zlicza od pewnej zadanej wielkości w dół. W momencie, kiedy dojdzie do zera, powoduje reset CPU. Aby uniknąć resetu aplikacja co pewien czas powinna ustawiać timer z powrotem na początkową wartość. Czynność ta jest nazywania karmieniem (feeding), albo kopaniem (kicking) watchdoga.

Dlaczego jest potrzebny?

Najgłośniejszym przypadkiem błędu, któremu mogło zapobiec użycie watchdoga jest  misja sondy kosmicznej Clementine z 1994 roku. NASA sterowała silnikami sondy wydając polecenia z Ziemi. Na skutek źle obsłużonego floating point exception sonda na 20 minut przestała odbierać komendy. W tym czasie jeden z silników pozostał włączony wprawiając sondę w ruch obrotowy. Po 20 minutach zadziałał software’owy timeout i przywrócono łączność.  Niestety okazało się, że prawie całe paliwo zostało wypalone i sonda nie jest w stanie zrealizować dalszych celów misji. Gdyby sonda była wyposażona w watchdoga, łączność zostałaby przywrócona dużo szybciej.

NASA wyciągnęła wnioski z tego błędu. Kilka lat później podczas misji Pathfinder system zarządzany przez RTOSa trafił na deadlocka. Tym razem watchdog już był obecny i zresetował system. Umożliwiło to zachowanie łączności, zdalne wgranie fixa na urządzenie znajdujące się na Marsie i kontynuowanie misji.

Opis buga na Pathfinderze:

https://www.rapitasystems.com/blog/what-really-happened-to-the-software-on-the-mars-pathfinder-spacecraft

http://www.cs.cornell.edu/courses/cs614/1999sp/papers/pathfinder.html

Watchdog w mikrokontrolerach

W dzisiejszych czasach większość mikrokontrolerów posiada wbudowany watchdog, a czasem nawet kilka rodzajów. Aby WDG spełniał swoje zadanie, czyli reagował na nieodwracalne błędy, moduł hardwareowy powinien posiadać kilka kluczowych funkcji:

  • Niezależne od CPU źródło taktowania – jeżeli WDG jest taktowany zegarem procesora, to w przypadku jego zatrzymania, reset nigdy nie nastąpi. Watchdog najczęściej jest taktowany niezależnym układem RC (tak jest np z IWDG – independent watchdog – w STM32F401. Ten procesor ma jeszcze WWDG – window watchdog – on jest już taktowany zegarem CPU).
  • Po skonfigurowaniu nie można go wyłączyć – musi być cały czas karmiony. Dzięki temu, kiedy w przypadku błędu CPU zacznie wykonywać losowe instrukcje zapobiegniemy przypadkowemu wyłączeniu watchdoga.
  • Sekwencja karmienia WDG powinna być trudna do przypadkowego wywołania – podobnie jak w poprzednim przypadku, nie chcemy aby błędnie działający program przypadkowo obszedł nasze zabezpieczenia. We wspomnianym wyżej STM32F401 do przeładowania watchdoga wystarczy zapisanie do odpowiedniego rejestru wartości 0xAAAA. Wartość ta jest często wykorzystywana w testach pamięci, więc szansa na przypadkowy zapis jest stosunkowo duża. Dużo lepszym zabezpieczeniem jest np. wymaganie zapisu od razu po sobie sekwencji dwóch różnych wartości.
  • Timeout WDG powinien zawsze kończyć się resetem – w niektórych procesorach timeout watchdoga powoduje wywołanie przerwania np. NMI (Non-Maskable Interrupt). Takie zachowanie jest w porządku pod warunkiem, że po określonym czasie i tak nastąpi reset procesora. W przeciwnym razie cała idea watchdoga zostaje zaburzona. Podczas obsługi NMI należy pamiętać, że ewentualne logowanie przyczyny powinno być na tyle krótkie, aby zdążyć przed resetem. Dlatego komunikacja z zewnętrzną pamięcią tutaj odpada.

Watchdog zewnętrzny

Istnieją również oddzielne układy scalone realizujące funkcję watchdoga. Mogą one być wykorzystane, gdy procesor nie posiada takiej opcji, albo gdy normy bezpieczeństwa wymagają dodatkowych zabezpieczeń. Karmienie watchdoga polega wtedy na wystawianiu odpowiedniego przebiegu czasowego na pinie. Ważne tutaj jest, żeby przebieg spełniał na tyle restrykcyjne warunki, żeby nie mógł być wygenerowany przypadkowo. Przykładowy przebieg prezentuje poniższy rysunek.

Obsługa watchdoga

W najprostszym przypadku, gdy nasz program w pętli głównej wywołuje poszczególne procedury, powinniśmy na początku tej pętli umieścić karmienie watchdoga. Wtedy jeśli program normalnie działa – po każdej iteracji pętli ustawi timer WDG. Jeżeli któraś z procedur się zawiesi, funkcja watchdoga się nie wywoła, co spowoduje reset procesora.

Ważne jest, aby obsługę watchdoga umieścić w pętli głównej, a nie na przykład w obsłudze przerwania. W takim wypadku przerwanie może zadziałać nawet, gdy główny program się zawiesi i reset nigdy nie zostanie wykonany.

Dobór czasu watchdoga

Watchdog zwykle posiada preskaler pozwalający skonfigurować timeout od ustawienia do resetu. Czas timeoutu dobieramy do ograniczeń czasowych naszej aplikacji. Musimy przeanalizować jaki jest maksymalny spodziewany czas wykonywania programu pomiędzy dwoma wywołaniami obsługi WDG. Wymagania stawiane systemowi mogą precyzować maksymalny dozwolony czas od powstania błędu do obsługi. Dobierając czas resetu WDG należy również wziąć pod uwagę czas potrzebny na inicjalizację systemu po resecie.

Wpływ na debugowanie

Domyślne działanie większości procesorów podczas debugowania z włączonym watchdogiem jest takie, że jeśli procesor zatrzyma się na breakpoincie, zostanie on zresetowany przez układ WDG. Czasem można skonfigurować go tak, aby breakpoint debugowy wyłączał watchdoga. Jednak jest to niebezpieczne podejście. Co jeśli takie ustawienie trafi do kodu produkcyjnego? Nie powinniśmy w tak ważnej kwestii bazować tylko na pamięci. Załączanie watchdoga powinno być sprawdzane na testach przed wydaniem wersji produkcyjnej.

Watchdog zapewnia ciągłość pracy systemu w przypadku błędu, ale jednocześnie jest symptomem niepoprawnego działania. Podczas developmentu resetowanie przez watchdog może maskować istnienie pewnych rzadko ujawniających się błędów. Wydaje nam się, że system działa płynnie, ale po prostu po błędzie się resetuje i wraca do pracy. Wersja developerska po prostu by się zawiesiła od razu nas alarmując. Dlatego reset powinien być w jakiś sposób logowany.

Wpływ na inicjalizację

Watchdog może być prekonfigurowany – wtedy działa od razu po starcie systemu i nie musimy go włączać. W przeciwnym wypadku działa od momentu zainicjalizowania. Oznacza to, że jeżeli system zawiesi się przed uruchomieniem watchdoga – system się nie zresetuje. Musimy mieć to na uwadze projektując system o ciągłej dostępności.

Podczas inicjalizacji często są wykonywane testy startupowe. Jeżeli są one wystarczająco długie, mogą spowodować reset WDG. Dlatego niektóre moduły WDG dozwalają dłuższy czas pierwszej obsługi. Watchdog może być również testowany w trakcie takiego zestawu testów startupowych. Najczęściej test ten polega na wejściu w nieskończoną pętlę i sprawdzeniu, czy system się zresetuje. Procesor najczęściej udostępnia informację o przyczynie resetu. Możemy więc rozróżnić reset przy power-upie i reset spowodowany watchdogiem.

Podsumowanie

W tym artykule zebrałem podstawowe informacje dotyczące watchdoga.Wytłumaczyłem jak działa, jakie powinien posiadać funkcje, jak go obsługiwać w pętli głównej oraz jakie sprawia problemy przy debugowaniu. Pokazałem również w jaki sposób wpływa na powodzenie misji kosmicznych 😀 Celowo pominąłem bardzo złożony temat jakim jest watchdog dla systemów wielowątkowych.  Będzie to temat na oddzielny artykuł.