- Watchdog részletes működése
- A WDTCSR regiszter, az MCUSR regiszter és a WDTON fuse bit hatásai a működésre
- A Watchdog üzemmódjai
- Időtúllépések lehetséges értékei
- WDTCSR regiszter bitjei
——————————————————————————-
Általában könnyű olyan programot írni, ami algoritmus hibából, vagy egy előre nem tervezett adat miatt végtelen ciklusba kerül. A végtelen ciklust onnan ismerhetjük fel, hogy a vezérlőnk nem csinál semmit, azaz lefagy. Okozhatja ezt a jelenséget egy rosszul működő periféria is. Több programot sikerült már elkövetnem, melyek évek óta üzemelnek a lakásban különféle kényelmi funkciókat biztosítva. Bár a programok roppant egyszerűek, érthetetlen okból évi egy-két alkalommal előfordulnak lefagyások. Gyanakszom sok esetben külső zavarokra, esetleg tápegység hibára is, de lényegében a hibát képtelen vagyok megtalálni. De nem is akarom, mert pont ezekre az esetekre jó a Watchdog. Mert hogyan is javítom a lefagyást alapesetben: megnyomom a reset gombot, és hónapokig megy minden tovább! Hát ezt csinálja a Watchdog is, csak automatikusan magától. Létezik programkönyvtár, amit felhasználhatunk a megvalósítás során. Azonban külső programkönyvtárak használata nélkül is könnyen használatba vehetjük a Watchdog-ot. Mindössze egyetlen regisztert kell megismernünk ehhez.
Lássuk először az ATMega328 és hasonló vezérlőkbe beépített Watchdog funkcióit:
- Különálló lapkára integrált oszcillátor áll rendelkezésre, ami tápfeszültség meglétekor biztosan működik és ez működteti a watcdog-ot.
- Háromféle üzemmódra állítható be a Watchdog:
– Interrupt hívása beállított időtúllépés esetén
– MCU alaphelyzetbe állítása (reset) beállított időtúllépés esetén
– Interrupt hívás, majd MCU alaphelyzetbe állítása beállított időtúllépés esetén - Többféle időtúllépési idő 16 ms és 8 mp között
- A vezérlő biztosíték (fuses) bitjeinek egyikével (WDTON) kényszeríthető a rendszervisszaállítás (reset) mód.
Áttekintés
Az ATmega48PA/88PA/168PA/328P továbbfejlesztett Watchdog időzítővel (WDT) rendelkezik. A WDT egy különálló, lapkára integrált 128 kHz-es oszcillátort tartalmaz, valamint egy számlálót ami beállított érték elérésekor megszakítást vagy reset jelet generál. Normál üzemmódban szükséges, hogy a felhasználói program WDR – Watchdog Timer Reset – utasítással rendszeresen újraindítsa a számlálót, mielőtt az elérne egy előre beállított értéket. Egy folyamatosan jól működő felhasználói program ezt képes rendszeresen megtenni, így a számláló soha nem éri el a beállított értéket és nem kerül sor megszakításra illetve reset-re. Ha azonban a felhasználói program „lefagyás” vagy más jellegű hibás működés miatt nem állítja alaphelyzetbe a számlálót, az eléri a beállított értéket, és megszakítás és/vagy reset generálódik, és az MCU újraindul, mintha megnyomtuk volna a reset gombot.
A fentiekben leírt működést megvalósító áramkör blokkvázlata:
Megszakítás módban a WDT megszakítást ad, amikor az időzítő lejár. Ez a megszakítás használható a készülék alvó üzemmódból való felébresztésére, valamint általános rendszeridőzítőként is. Ilyen például az egyes műveletekhez engedélyezett maximális idő korlátozása, megszakítást adva, ha a művelet a vártnál hosszabb ideig futott. Rendszer-visszaállítási módban (reset) a WDT alaphelyzetbe állítja a vezérlőt, ha az időzítő lejár. Ezt általában arra használják, hogy megakadályozzák a rendszer lefagyását hibás kód esetén. A harmadik mód, a megszakítás és a rendszer-visszaállítás mód egyesíti a két módot úgy, hogy először megszakítást ad, majd rendszer-visszaállítási módba vált. Ez az üzemmód például lehetővé teszi a biztonságos leállítást azáltal, hogy a rendszer alaphelyzetbe állítása előtt elmenti a kritikus paramétereket.
A Watchdog beállításaihoz egyetlen WDTCSR nevű regiszter beállítására van szükség. Ebben a regiszterben található a WDIE bit melynek beállítása (1) esetén a Watchdog számláló megszakítást generálhat, ha egyébként a globális megszakítások is engedélyezve vannak a vezérlő SREG regiszterében. Valamint a WDTCSR regiszterben található a WDE bit, mely pedig ha egy, akkor rendszer visszaállítást (reset-et) generálhat a Watchdog számláló.
A Watchdog beállításához még egy regiszternek van köze. Az MCUSR regiszterből lekérdezhető, hogy egy esetleges rendszer visszaállítást melyik áramkör okozta. Amennyiben ennek a regiszternek a WDRF bitje egy, akkor a reset-et a Watchdog áramkör okozta. Egy újra indulás után a felhasználói programnak a lehető leghamarabb el kell olvasnia ezt a regisztert, és miután azonosította a reset okát, alaphelyzetbe kell állítania a jelzőbiteket.
Ha a vezérlő biztosítékbitjeiben (fuses) a (WDTON) biztosíték programozott (azaz az alábbi táblázat szerinti logikai 0 értéket vesz fel), a Watchdog időzítő a rendszerre kényszeríti Reset módot. Programozatlan (WDTON) fuse bittel (azaz logikai 1 értéket képvisel az alábbi táblázatban) a rendszer-visszaállítási mód bitje (WDE) és a megszakítási mód bitje (WDIE) 1-re, illetve 0-ra állítható. Ahhoz, hogy a program biztonságát megtarthassuk, a Watchdog beállítást egy időzített lépéssorozattal kell végrehajtani:
- Ugyanabban a műveletben egyet kell írni a Watchdog change enable bitbe (WDCE) és WDE-be. A WDE bitbe egyet kell írni, függetlenül a WDE bit előző értékétől. Ezt követően 4 órajel ciklus múlva a WDCE bitet a rendszer törli.
- A következő négy órajelcikluson belül be kell írni a WDE és a Watchdog előosztó biteket (WDP) igény szerint, de a WDCE bit törlésével. Ezt egy műveletben kell elvégezni.
Watchdog időzítő konfigurációja:
A fuse bitek beállításakor a programozott állapot a logikai 0 állapotnak felel meg, míg a programozatlan bit a logikai 1-nek
A következő példakód egy C függvényt mutat be a Watchdog időzítő kikapcsolásához. A példa feltételezi, hogy rendelkezünk a globális megszakítást végző függvénnyel, valamint a Watchdog számláló törlését végző függvénnyel. Fontos, hogy a beállítások alatt nem keletkezhet semmilyen megszakítás.
void WDT_off(void) { __disable_interrupt(); //globálisan tiltunk minden megszakítást __Watchdog_reset(); //töröljük a Watchdog számlálót MCUSR &= ~(1<<WDRF); // WDRF törlése az MCUSR-ben WDTCSR |= (1<<WDCE) | (1<<WDE); //WDCE és WDE egybe állítása, előosztó bitek megtartásával WDTCSR = 0x00; //WDT kikapcsolása __enable_interrupt(); //globális megszakítás engedélyezés }
Megjegyzés: Ha a Watchdog véletlenül engedélyezve van, és az eszköz valamilyen más okból alaphelyzetbe áll, akkor a Watchdog időzítő engedélyezve marad. Ha a kód nincs beállítva a Watchdog kezelésére, ez az időtúllépési visszaállítás végtelen ciklusához vezet. Ennek elkerülése érdekében az alkalmazásszoftvernek mindig törölnie kell a MCUSR regsizter WDRF bitjét és a WDTCSR regiszter WDE bitjét az inicializálási rutinban, még akkor is, ha a Watchdog nincs használatban.
A következő példakód egy beállítást mutat be a Watchdog Timer időtúllépési értékének módosításához, és a Watchdog beállításához:
void WDT_Prescaler_Change(void) { __disable_interrupt(); //globálisan tiltunk minden megszakítást __Watchdog_reset(); //töröljük a Watchdog számlálót WDTCSR |= (1<<WDCE) | (1<<WDE); //Időtullépési érték beállításának engedélyezése és //rendszer visszaállítás engedélyezése WDTCSR = (1<<WDE) | (1<<WDP2) | (1<<WDP0); //Watchdog számláló időtullépési értékének beállítása //64K ciklus (~0,5 s) */ __enable_interrupt(); //globális megszakítás engedélyezés }
Megjegyzés: A Watchdog időzítőt alaphelyzetbe kell állítani a WDP bitek bármilyen módosítása előtt, mivel a WDP bitek módosítása időtúllépést eredményezhet, ha rövidebb időtúllépési időszakra változtatjuk a bitek értékeit.
WDTCSR – Watchdog időzítő vezérlő regiszter
- 7. bit – WDIF: Watchdog megszakítás jelző. Ez a bit akkor kerül beállításra, amikor időtúllépés történik a Watchdog Timerben, és a Watchdog Timer megszakításra van beállítva. A WDIF-et a hardver törli a megfelelő megszakításkezelő vektor végrehajtásakor. Alternatív megoldásként a WDIF törléséhez nullát kell írni a regiszter ezen bitjére. Ha a vezérlő SREG regiszterében a megszakítás globálisan engedélyezve van, és WDIE (6. bit) bit is be van állítva, a Watchdog időtúllépési megszakítása végrehajtásra kerül a jelző bebillenésekor.
- 6. bit – WDIE: Watchdog megszakítás engedélyezése. Ha ezt a bitet egybe írjuk, és a vezérlő SREG regiszterében a megszakítások engedélyezve vannak, akkor a Watchdog megszakítás engedélyezve van.
Ha a WDE bit nincs beállítva, de a WDIE bit be van állítva, időtúllépés esetén a megszakítás végrehajtásra kerül.
Ha WDE is be van állítva, a Watchdog időzítő megszakítás és rendszer-visszaállítás módban van. Ekkor a Watchdog Timer első időtúllépése WDIF-et állít be. A megfelelő megszakításvektor végrehajtásakor a hardver automatikusan törli a WDIE-t és a WDIF-et (a Watchdog rendszer-visszaállítási módba lép). Ez a Watchdog Timer biztonságának megőrzéséhez szükséges a megszakítás használata közben. Ahhoz, hogy megszakítási és rendszer-visszaállítási módban maradjon, a WDIE-t minden megszakítás után be kell állítani. Ezt azonban nem szabad magán a megszakítási szolgáltatási rutinon belül megtenni, mivel ez veszélyeztetheti a Watchdog rendszer-visszaállítási mód biztonsági funkcióját. Ha a megszakítás nem történik meg a következő időtúllépés előtt, a rendszer visszaállítja a rendszert. - 4. bit – WDCE: Watchdog módosítás engedélyezése. Ez a bit időzített szekvenciákban használatos a WDE és az előosztó bitek módosításához. A WDE-bit törléséhez és/vagy az előosztó bitek módosításához be kell állítani a WDCE-t. Miután ez megtörtént, a hardver négy órajelciklus után automatikusan törli a WDCE-t.
- 3. bit – WDE: Watchdog rendszer visszaállításának engedélyezése. A WDE-t a WDRF bírálja felül az MCUSR-ben. Ez azt jelenti, hogy a WDE mindig be van állítva, amikor a WDRF-ben be van állítva. A WDE törléséhez először a WDRF-et kell törölni. Ez a funkció biztosítja a többszörös alaphelyzetbe állítást a hibát okozó körülmények között, és a biztonságos indítást a hiba után.
- 5. bit, 2..0 bitek – WDP3..WDP0: Watchdog időzítő előosztó bitek. A WDP3..WDT0 bit határozza meg a Watchdog Timer számlálójának előosztó értékeit. A különböző előosztó értékeket és a hozzájuk tartozó időtúllépési időket az alábbi táblázat mutatja:
A WDP3..WDP0 további lehetséges értékei fenntartottak!