Forum: Mikrocontroller und Digitale Elektronik Watchdog reset


von Tom (Gast)


Lesenswert?

Hallo Leute,

eine kurze frage: Wie setz ich den Watchdog im Programm zurück? Ich
programmiere in C.

Reicht ein:

WDR = 0;

..oder benötige ich da auch irgend einen genau spezifizierten
Programmablauf?

Grüße

Tom

von Tom (Gast)


Lesenswert?

Hallo nochmal,

So in der Art sollte das Einstellen des Watchdogs doch funktionieren
oder?
Übergabewerte:
- watchdog_presc -> Wertebereich 0x0 - 0x9 -> entspricht 2k-1024k
  clock cycles
- watchdog_mode -> Wertebereich 0x0 - 0x3:
                   0x0 = stopped, 0x1 = isr, 0x2 = System reset,
                   0x3 = isr & system reset

void watchdog_config(unsigned char watchdog_presc, unsigned char
watchdog_mode)
{
 switch(watchdog_mode)
 {
 case 0x0:  WDTCSR |= (1<<WDCE) | (1<<WDE);
                WDTCSR = 0x0;
                break;
 case 0x1:  WDTCSR |= (1<<WDCE) | (1<<WDE);
                WDTCSR = (watchdog_presc&0x7) |  \
                         ((watchdog_presc&0x8)<<2) | (1<<WDIE);
                break;
 case 0x2:  WDTCSR |= (1<<WDCE) | (1<<WDE);
                WDTCSR = (watchdog_presc&0x7) |\
                         ((watchdog_presc&0x8)<<2) | (1<<WDE);
                break;
 case 0x3:  WDTCSR |= (1<<WDCE) | (1<<WDE);
                WDTCSR = (watchdog_presc&0x7) |\
                         ((watchdog_presc&0x8)<<2) | (1<<WDIE) | \
                         (1<<WDE);
                break;
 default:   WDTCSR |= (1<<WDCE) | (1<<WDE);
                WDTCSR = 0x0;
 }
}

nur wie läuft das mit dem Rücksetzen ab?!?
Einfach "WDR = 0;"?

von johnny.m (Gast)


Lesenswert?

> "WDR = 0;"

Was soll das sein? 'wdr' ist ein Assembler-Befehl. Dem kann man
keinen Wert zuweisen. Entweder, Du fügst den wdr-Befehl per
Inline-Assembler ein (da Du nicht erzählst, welchen C-Compiler Du
benutzt, kann ich natürlich nicht konkret sagen, wie es in Deinem Fall
auszusehen hat) oder Du benutzt eine Bibliotheksfunktion bzw. -Makro.

In AVR-GCC-C läuft das entweder direkt über

asm volatile ("wdr"); //Inline-Assembler

oder mit

#include<avr/wdt.h>
//...
wdt_reset();

wobei das Makro wdt_reset() auch nix anderes macht, als den
Assembler-Befehl wdr inline einzusetzen.

In CodeVision gehts z.B. mit #asm("wdr")

von Tom (Gast)


Lesenswert?

Hallo Jonny,

danke für deine Antwort! Ich benutze AVR-GCC-C. Genau das war es was
mir gefehlt hat. Kenn mich mit assembler leider net wirkl aus :).

Eine Frage hätte ich noch dazu:
Ich habe schon einen inline-Assembler Sleep-Befehl. Bei dem sind zwei
"::" am Ende. Kannst du mir erklären, was das bedeutet?

asm volatile ("sleep"::);   //:: am ende == ??

Grüße

von johnny.m (Gast)


Lesenswert?

Lt. AVR-libc-Doku
(http://www.nongnu.org/avr-libc/user-manual/inline_asm.html) muss bei
Inline-Assembler immer die Parameter-Liste, deren erforderliche Teile
(Input- und Output-Parameter) durch Doppelpunkte getrennt werden,
angegeben werden, auch wenn sie leer ist. Die angesprochene Doku
scheint sich allerdings auf eine ältere Version zu beziehen. Aktuell
kann man bei parameterlosen Befehlen wie sleep, wdr, nop usw. die
Doppelpunkte weglassen. Wenn man sie trotzdem macht ist auch nicht
schlimm...

Vielleicht ist ja einer der WINAVR-Experten grade irgendwo hier in der
Gegend (Hallo Jörg Wunsch, kannst Du uns hören?) und kann das
kommentieren (ab welcher Version, warum usw..)

Gruß

Johnny

von Tom (Gast)


Lesenswert?

Danke für die Info!

Der funktionierende Code lautet: (net dass des oben wer rauskopiert u
es funzt net ;)

void watchdog_config(unsigned char watchdog_presc, unsigned char
watchdog_mode)
{
cli();
unsigned char temp = 0x0;
temp = (watchdog_presc & 0x7)| ((watchdog_presc&0x8)<<2);

switch(watchdog_mode)
{

case 0x0:  asm volatile ("wdr"::); //Watchdog reset
    MCUSR &= ~(1<<WDRF);    //Flag zurücksetzen
                WD_CONTROL |= (1<<WD_CHANGE) | (1<<WD_ENABLE);
    WD_CONTROL = 0;
    break;
case 0x1:  asm volatile ("wdr"::); //Watchdog reset
    WD_CONTROL |= (1<<WD_CHANGE) | (1<<WD_ENABLE);
    WD_CONTROL = temp | (1<<WD_ISR);
    break;
case 0x2:  asm volatile ("wdr"::); //Watchdog reset
    WD_CONTROL |= (1<<WD_CHANGE) | (1<<WD_ENABLE);
    WD_CONTROL = temp | (1<<WD_ENABLE);
    break;
case 0x3:  asm volatile ("wdr"::); //Watchdog reset
    WD_CONTROL |= (1<<WD_CHANGE) | (1<<WD_ENABLE);
    WD_CONTROL = temp | (1<<WD_ISR) | (1<<WD_ENABLE);
    break;
default:   asm volatile ("wdr"::); //Watchdog reset
    WD_CONTROL |= (1<<WD_CHANGE) | (1<<WD_ENABLE);
    WD_CONTROL = 0x0;
}
sei();
}

von johnny.m (Gast)


Lesenswert?

Schau mal in die avr/wdt.h. Da gibts mehrere Funktionen, die im Prinzip
genau das machen, was Du da programmiert hast.

Gruß

Johnny (bitte mit 'h')

von Tom (Gast)


Lesenswert?

Ja ich weiss...ich programmiere es nur immer gern selber, anstatt fremde
libraries einzufügen :). Trägt wenigstens ein bissl zum Verständnis
bei.:)

Grüße

von Walter (Gast)


Lesenswert?

"Schau mal in die avr/wdt.h. Da gibts mehrere Funktionen, die im Prinzip
genau das machen, was Du da programmiert hast."

aber nicht ganz, z.B. den Watchdog als interrupt einstellen gibts da 
nicht

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.