Watchdog reset

Gast #346237
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;"?
Gast #346238
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")
Gast #346239
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
Gast #346240
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
Gast #346241
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();
}
Gast #455603
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren