3.27. Watchdog időzítő

A watchdog időzítő egy olyan hardver, amely újraindítja a mikrokontrollert, ha a futó szkript valaha is abbahagyja annak rendszeres megpiszkálását. A szkript onnan „eteti” a watchdogot, ahol tudja, hogy egészséges kód fut; ha egy hiba, egy lefagyás vagy egy váratlan kivétel valaha is megakadályozza a kamerát abban, hogy a watchdogot a beállított időkorláton belül megetesse, a chip újraindítja magát, és a szkript elölről kezdődik.

Egy olyan telepített eszközön, ahol nincs a közelben ember, aki ki-be kapcsolná, ez jelenti a különbséget egy átmeneti hiba között, amely másodperceken belül helyreáll, és egy téglává vált eszköz között, amely szervizhívást igényel.

A graph of a watchdog counter over time. The counter starts at the timeout value, drops linearly toward zero, and is reloaded to the timeout each time the script calls feed(). After three successful feed() calls, a fourth interval has no feed() and the counter reaches zero, triggering an MCU reset.

A watchdog-számláló az időkorlátjáról számol visszafelé. Minden feed() újratölti; ha eléri a nullát, a chip újraindul.

3.27.1. A machine.WDT osztály

A machine.WDT engedélyezi a watchdogot, és egyetlen metódust tesz elérhetővé, a feed() metódust. Egyszer elindítva a watchdog nem állítható le – az egyetlen kiút az ütemezett etetése vagy az, hogy hagyod, hogy újraindítsa a chipet:

from machine import WDT

wdt = WDT(timeout=2000)    # reset if not fed within 2 seconds

while True:
    do_work()
    wdt.feed()

A timeout ezredmásodpercben van megadva. A megfelelő érték attól függ, mennyi ideig tart a fő ciklus leghosszabb jogos iterációja, kényelmes ráhagyással – egy 100 ms-os ciklusnak 2 s-os időkorláttal bőven van mozgástere egy lassú iterációhoz, anélkül hogy fölösleges újraindítások történnének.

3.27.2. Hol hívd meg a feed()-et

Az, hogy a feed() hol helyezkedik el, a kritikus tervezési döntés; a watchdog csak a kód azon részeinek hibáit fogja meg, amelyek nem futnak le az etetések között.

  • Hívd meg a fő ciklusból, a tetején vagy az alján. A leggyakoribb minta. A watchdog elkap mindent, ami lefagyasztja a fő ciklust – egy holtpontot, egy végtelen while-t, egy soha vissza nem térő perifériát – és visszaindítja a chipet a ciklusba.

  • Ne hívd meg megszakításkezelőből. A watchdog lényege, hogy a normál kódútvonal lefagyásait fogja el. Egy ISR, amely attól függetlenül lefut, hogy a fő ciklus elakadt-e, folyamatosan etetne egy watchdogot, amelynek ki kellene váltania az újraindítást.

  • Ne hívd meg egy hosszú blokkoló művelet belsejéből. Egy hálózati kérés vagy érzékelő-leolvasás, amely tíz másodpercig tart, pontosan az a fajta lefagyás, amelyet a watchdognak el kellene kapnia. Ha a feed() hívást belerakod, az kijátssza a védelmet.

Egy iránymutatás, amely a legtöbb programnál működik: etesd egyszer fő ciklus iterációnként, az időkorlátot a várt ciklusidő többszörösére állítva. Ha egyetlen iteráció jogosan tovább tart, mint az időkorlát – mondjuk egy szándékos kalibrációs fázis –, strukturáld azt a fázist kisebb darabok sorozataként, közöttük feed() hívásokkal, vagy a belépés előtt változtasd meg az időkorlátot a timeout_ms() segítségével (ahol támogatott).

3.27.3. Elérhetőség

A watchdog a legtöbb OpenMV kamerán elérhető, de nem mindegyiken – a hardver minden alkatrészen jelen van, de a Python API még nincs mindenhol bekötve. Nézd meg a OpenMV kártyák oldalt, vagy próbálj meg létrehozni egy WDT példányt, és kapd el az AttributeError hibát, ha nem támogatott.

Még azokon a kamerákon is, ahol a WDT nem érhető el, egy terepre telepített eszköz használhat egy szoftveres megfelelőt – egy különálló feladatot vagy fő ciklus lépést, amely figyeli az előrehaladást, és kiváltja a machine.reset() függvényt, ha bármi elakadtnak tűnik. Ez kevésbé robusztus, mint egy hardveres watchdog (egy elakadt megszakításkezelő a szoftveres figyelőt is leránthatja), de ugyanazokat az eseteket fedi le alkalmazásszinten.