SLEEP - Modi und Watchdog

Hero_123

Mitglied
17. Sep. 2010
183
3
18
Sprachen
  1. ANSI C
Hallo

Ich habe eine Frage zum Watchdog und den Sleep-Modi des AVR (ATMega8): wenn ich den Sleep-Modus verwende und den Watchdog zur Überwachung - fkt das?

Anbei ein Code-Schnipsel:
Code:
#include <avr/io.>
#include <avr/interrupt.h>    /* fuer die Interrupts */
##include <avr/wdt.h>        /* fuer den Watchdog */
#include <string.h>
#include <stdlib.h>

static volatile char event = 0;

/* initialisieren des INTERRUPTS  INT0 */
static void init_INT0(void) {
    DDRD &= ~(1 << DDD2);        /* PD2 als Eingang => ISR INT0 */
    PORTD |= (1 << PD2);        /* PullUp Widerstand PD2 aktivieren */
    MCUCR |= (1 << ISC01);        /* ISC01 setzen */
    MCUCR |= (1 << ISC00);        /* ISC00 setzen */
    GICR |= (1 << INT0);        /* Interrupt INT0 aktivieren PD2 */
}

/* INT0 Funktion */
ISR(INT0_vect) {
    if(event == 0) {
        PORTD |= 0x80;            /* LED AN wenn PD2 nicht betaetigt */
    }
    event = 1;                    /* gesetzt, wenn PD2 betaetigt */
}

void main(void){
    unint8_t s_REG;                /* Speicher fuer das SREG */
    init_INT0();
    set_sleep_mode(SLEEP_MODE_IDLE);    /* IDLE Modus verwenden */
    
    wdt_enable(WDTO_30MS);    /*Start WDT 30ms-kein RESET in 30ms => RESET */
    
    while(1){
        s_REG = SREG;            /* sicher das SREG */
        cli();                    /* sperre die Interrupts */
        while(event == 0){        /* warte auf event */
            sleep_enable();        /* aktiviere sleep Modus */
            SREG = s_REG;        /* = sei() */
            sleep_cpu();        /* sleep Modus betreten */   
            sleep_disable();
            s_REG = SREG;        /* sicher das SREG */
            cli();                /* sperre die Interrupts */           
        }
        SREG = s_REG;            /* = sei() restore I-Bit */
        /* weiterer Code */       
        wdt_reset();                        /* Reset des Watchdogtimers  */
    }   
}

Würde der Watchdog nach den ca 30ms "zuschlagen", solange sich das Programm in der "while(event ==0)" - Schleife befindet (also kein Taster betätigt wird)?

mfg

Hero_123
 
War es nicht so, dass der Watchdog nicht in jedem Sleep Mode läuft? Glaube da war mal was... In einigen wird der Takt für den Watchdog abgeschaltet.
In den jeweiligen Sleep Modus, wo der Takt noch erzeugt wird, sollte das eigentlich funktionieren.
 
In einigen wird der Takt für den Watchdog abgeschaltet
Ich kenns eher andersrum - wenn der WD enabled ist, wird der WD-Oszillator auch im SLEEP nicht abgeschaltet.

Schaut doch einfach mal in das Datenblatt des verwendeten Controllers, ob der WD-(Interrupt) da Wakeup-Source ist...
 
Kann natürlich auch sein. Ich glaube es gab Typen da war es anders herum? Aber wie lotadac schon sagte, schau mal ins Datenblatt.
 
Vorsicht beim Speichern und Wiedererstellen des SREG Registers! Du willst nur Interrupts aktivieren/deaktivieren, dazu sind die Befehle CLI und SEI da.
Der Watchdog (sofern aktiviert) läuft immer! Sonst wäre er sinnlos. In der Tat muss man sogar um ihn abzuschalten oder zu verändern (die Zeit) bestimmte Timings einhalten, sonst wird der Versuch verworfen, wenn nicht in x Taktzyklen abgeschlossen.
sleep_enable und sleep_disable... Sagt mir jetzt nichts, ist wohl so ein C Ding. Normalerweise ist disable per-se unnötig, da Sleep ja unterbrochen wird sobald ein Interrupt auftritt (der scharf geschaltet ist). Ein disable könnte höchstens den Sleep Befehl außer Kraft setzen.
 
Ich kenns eher andersrum - wenn der WD enabled ist, wird der WD-Oszillator auch im SLEEP nicht abgeschaltet.
Aus dem aktuellen Datenblatt des Mega8 → Power Management and Sleep Modes → Minimizing Power Consumption → Watchdog Timer :
If the Watchdog Timer is not needed in the application, this module should be turned off. If the Watchdog Timer is enabled, it will be enabled in all sleep modes, and hence, always consume power. In the deeper sleep modes, this will contribute significantly to the total current consumption. Refer to “Watchdog Timer” on page 43 for details on how to configure the Watchdog Timer.
In der Tat muss man sogar um ihn abzuschalten oder zu verändern (die Zeit) bestimmte Timings einhalten, sonst wird der Versuch verworfen, wenn nicht in x Taktzyklen abgeschlossen.
Zum Aktivieren reicht es, WDE in WDTCR zu setzen. Zum Deaktivieren bzw ändern des WD-Vorteilers muß erst (gleichzeitig) WDE und WDCE in WDTCR gesetzt werden, und dann innerhalb von vier Takten WDE und die Vorteilerbits wie gewünscht (ohne WDCE) geschrieben werden.

Wenn die Watchdog-Always-on-Fuse aktiviert ist, kann der WD (wie der Name sagt) nicht deaktiviert werden - hier kann so also nur der Vorteiler geändert werden.

P.S.: da's hier um den Mega8 geht - dessen WD besitzt keinen Interrupt sondern kann nur einen Reset auslösen. Ab dem Mega48/88/168/328 als Nachfolger besitzt der WD 'ne Interrupt-Fähigkeit.
Er kann dann entweder einen IRQ triggern, oder (normal) einen Reset auslösen, oder beim ersten Eintritt den IRQ auslösen, und danach automatisch auf Reset für den nächsten Überlauf umschalten (also Fail-Safe, wenn die WD-ISR auch fehlschlägt...)

P.P.S.: Um die vier Takte sicher einzuhalten, sollten irgendwelche IRQs unterdrückt werden.
Es ist allerdings davon auszugehen, daß Hochsprachen entsprechende Routinen mitbringen, die die Bits korrekt, auch das Timing betreffend, manipulieren. Aber Hero ist ja immer an den Hintergründen interessiert;)
 
Zuletzt bearbeitet:
Hallo LotadaC, hallo Janiiix3, hallo TommyB

Vielen Dank für Eure Hilfe :)

Ich habe z.Zt. nur begrenzten Zugang zum Internet, deshalb die etwas späte Reaktion :rolleyes:, auch habe ich mein "Entwicklungsbord" nicht mit dabei.

@LotadaC :
Ich werde das, was im Datenblatt des ATMega8 ab S/43 ff, Ausgabe 2486AA–AVR–02/2013 steht, implementieren und testen.

Aber Hero ist ja immer an den Hintergründen interessiert;)

Stimmt! Was nützt es mir, wenn ich mir irgendwelchen Code aus dem Internet zusammenkopiere und nicht weiß, was da passiert, auch wenn der Code funktionieren sollte ;).

mfg

Hero_123
 
Hallo

Update - es funktioniert, man muss im sleep-mode (natürlich!) den WD resetten & disablen ;) und dann - wenn der sleep-mode beendet ist, den WD wieder "reaktivieren" - siehe auch #7 ...

mfg

Hero_123
 
Es kommt auf dein Programm drauf an. Wenn genügend Interrupts (beispielsweise durch Timer oder ADC) den Controller aus dem Schlaf reißen brauchst du es nicht, sonst definitiv ja :)
 
Hallo TommyB

Es kommt auf dein Programm drauf an. Wenn genügend Interrupts (beispielsweise durch Timer oder ADC) den Controller aus dem Schlaf reißen brauchst du es nicht, sonst definitiv ja :)
Was brauche ich nicht?

Bei meinem kleinen Programm wird der IDLE Mode (sleep mode idle) verwendet, der Watchdog Timer (WD) ist auf 30 ms eingestellt => wenn der ATMega8 "schläft", ist ja der WD trotzdem aktiv, deshalb muss er beim Betreten des Sleep-Abschnittes resettet und disabled werden (sonst schlägt der WD ja nach spätestens 30ms gnadenlos zu).
Aus dem sleep mode wird der ATMega8 durch den externen INT0 geholt (irgendwann, muss ja nicht innerhalb der WD-Überwachungszeit sein) und da wird der WD wieder aktiviert.

anbei eine kurzer(!) Code Ausschnitt



CodeBox C

static volatile char event = 0;

/* INT0 Funktion */
ISR(INT0_vect) {
    if(event == 0) {
    }
    event = 1;
}

int main(void){
/* Code... */

wdt_enable(WDTO_30MS);    /* Start WDT 30ms-kein RESET in 30ms => RESET */
while(1) {
        s_SREG = SREG;            /* speicher das SREG => Interrupt */
        cli();                    /* sperre die Interrupts */
        while(event == 0) {        /* schlafen legen ATMega8 */

            if(!s_WDT_ab) {        /* WD nicht abgeschaltet */
                wdt_reset();    /* WD resetten */
                wdt_disable();     /*WD disablen */
                s_WDT_ab = 1;
                s_WDT_zu = 1;    /* zuschalten WD */
            }
            sleep_enable();
            SREG = s_SREG;        /* Freigabe der Interrupts === sei() */
            sleep_cpu();
            sleep_disable();
            s_SREG = SREG;        /* speicher das SREG => Interrupt */
            cli();                /* sperre die Interrupts */
        }
        SREG = s_SREG;            /* Freigabe der Interrupts === sei() */
        if(s_WDT_zu) {                /* zuschalten WD */
            wdt_enable(WDTO_30MS);    /*Start WDT 30ms-kein RESET in 30ms => RESET */
            /*    WDTCR |= (1<<WDE);     Turn on WDT */
            s_WDT_zu = 0;
            s_WDT_ab = 0;
            PORT_OFF(PORTD, PD7);    /* kein sleep mehr */
        }
/* hier kommt weiterer Code */
wdt_reset();                    /* Reset des Watchdog Timers  */


mfg

Hero_123
 
Zuletzt bearbeitet:
Der Watchdog ist (in seiner Grundfunktion) sowas wie ein Totmannschalter. Wenn der Hund nicht irgendwann zurückgepfiffen wird, schnappt er zu, und der Controller resetted.
In Deinem Sleep wird halt nicht gepfiffen - irgendwann schnappt der Hund zu. Deswegen schaltest während des Sleep den Hund ab.

Thomas meinte: Das muß aber nicht immer beim Sleep gemacht werden, es käme auf das Programm an: wenn diverse Wakeup-Quellen sicherstellen, daß der Controller nie solange schläft...

Grundsätzlich ist (meiner Meinung nach) der WD aber nicht dazu gedacht Programmierfehler abzufangen (da sollte man lieber die Ursachen statt der Symptome behandeln), sondern eher, um igendwelche Extremzustände der Peripherie abzusichern (Verbindung bei serieller Kommunikation (I²C, SPI) reißt ab, Timeout, extern erwartetes Event tritt nicht ein. Oder um Sicherzustellen, daß mein Controller ein bestimmtes erwartetes Timing einhällt...
 
Hallo LotadaC

Thomas meinte: Das muß aber nicht immer beim Sleep gemacht werden, es käme auf das Programm an: wenn diverse Wakeup-Quellen sicherstellen, daß der Controller nie solange schläft...
Das ist mir schon klar (steht ja auch so im Datenblatt) ;)

Grundsätzlich ist (meiner Meinung nach) der WD aber nicht dazu gedacht Programmierfehler abzufangen (da sollte man lieber die Ursachen statt der Symptome behandeln), sondern eher, um igendwelche Extremzustände der Peripherie abzusichern (Verbindung bei serieller Kommunikation (I²C, SPI) reißt ab, Timeout, extern erwartetes Event tritt nicht ein. Oder um Sicherzustellen, daß mein Controller ein bestimmtes erwartetes Timing einhällt...
Stimmt :good3:

mfg

Hero_123
 
Richtig, so war es gemeint. Wenn du, sagen wir, mal einen Timer laufen hast der alle 500ms einen Interrupt feuert, dein Watchdog auf 2 Sekunden eingestellt ist, dann brauchst du es nicht, sonst natürlich schon... Wobei es drauf ankommt. Meine Taschenlampen werden, wenn sie ausgeschaltet sind, also der Timer nicht läuft, ständig vom Hund gebissen. Die paar wenige Taktzyklen die das Init braucht, das fällt nicht auf.

Und doch, genau dazu ist der WD da. Das impliziert aber keinesfalls dass man sich auf ihn verlassen sollte. Man misst Strom ja auch nicht mit Sicherungen. Das Programm sollte immer sauber arbeiten und der WD ist nur für den absoluten Notfall da. Es gibt auch Statusbits was für ein Ereignis den Controller resettet hat, auch der Watchdog. Ich weiß jetzt nur nicht ob jeder AVR das hat. Wenn man noch Pins über hat: LED dran und beim Starten setzen. Ist die WDR Lampe an: DeveloperOutOfCoffeeException.
 
Hallo TommyB

:good2:

mfg

Hero_123
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)