Forum: Compiler & IDEs Problem mit Watchdog Interrupt initialisierung


von AVR-Anfänger (Gast)


Lesenswert?

Hallo zusammen,

ich bin seit gestern daran zu verzweifeln meinen Watchdog in den 
Interrupt Modus zu bringen. aktuell habe ich folgenden Code:

am Anfang des Programms:
1
  if(MCUSR & _BV(WDRF)){            
2
    MCUSR &= ~_BV(WDRF);                     WDTCSR |= (_BV(WDCE) | _BV(WDE));   
3
    WDTCSR = 0x00;                      
4
  }

direkt danach:
1
  cli();
2
  WDTCSR |= (1<<WDCE)|(1<<WDE);        
3
  WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);    
4
  //WDTCSR |= 0b01011111;
5
  //WDTCSR |= 0b00010111;
6
  //WDTCSR &= 0b11100111;
7
  sei();

In der Routine selbst mache ich nichts außer einer Uart ausgabe.

ich habe im Debugger die einzelnen Bits verfolgt, und es wird nie die 
Zeit eingestellt bzw das WDE Bit gelöscht! Im Debugging selber kann ich 
händisch über die Oberfläche die Bits setzen und der Interrupt 
funktioniert ohne Probleme. Habt ihr eine Idee woran es liegen könnte?

Das Fusebit WDTON ist nicht gesetzt und ich verwende einen ATmega2560.

von AVR-Anfänger (Gast)


Lesenswert?

keiner eine Idee?

von Ingo L. (corrtexx)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #4056700:
> WDTCSR |= (1<<WDCE)|(1<<WDE);
>   WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);
Was soll das auch? Du aktivierst den WDT in der ersten Zeile und löscht 
ihn sofort in der zweiten Zeile!

AVR-Anfänger schrieb im Beitrag #4056700:
> Das Fusebit WDTON ist nicht gesetzt und ich verwende einen ATmega2560.
Du musst auch das WDTON-Fuse setzen soweit ich mich erinnere.

Mach mal bitte ne genauere Erklärung was du willst und was du hast.

: Bearbeitet durch User
von AVR-Anfänger (Gast)


Lesenswert?

Ingo Less schrieb:
> AVR-Anfänger schrieb im Beitrag #4056700:
>> WDTCSR |= (1<<WDCE)|(1<<WDE);
>>   WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);
> Was soll das auch? Du aktivierst den WDT in der ersten Zeile und löscht
> ihn sofort in der zweiten Zeile!
>

das wird im Datenblatt so vorgeschrieben, um den Watchdog nicht 
ausversehen zu konfigurieren. Ich habe es jedenfalls so verstanden....

> AVR-Anfänger schrieb im Beitrag #4056700:
>> Das Fusebit WDTON ist nicht gesetzt und ich verwende einen ATmega2560.
> Du musst auch das WDTON-Fuse setzen soweit ich mich erinnere.
>
Mit dem WDTON Bit wird der Watchdog Hartdwaremäßig im Reset Modus 
gehalten oder?

> Mach mal bitte ne genauere Erklärung was du willst und was du hast.

Ich möchte den Watchdog im Interruptmodus nutzen, um das Aufhängen des 
Programmes zu verhindern, beispielsweise wenn ein Sensor nicht reagiert.

von Ingo L. (corrtexx)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #4058289:
> Ich möchte den Watchdog im Interruptmodus nutzen, um das Aufhängen des
> Programmes zu verhindern
Wie denn genau? Mir scheint fast du steuerst auf eine falsche Lösung 
drauf zu. Aber ohne eine genauere Beschreibung oder mal den Code kann 
man dir nicht helfen. Ich habe nämlich immernoch nicht ganz begriffen 
was du eigentlich machen willst.

von Oliver S. (oliverso)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #4058289:
> das wird im Datenblatt so vorgeschrieben, um den Watchdog nicht
> ausversehen zu konfigurieren. Ich habe es jedenfalls so verstanden....

WDE muß in beiden Schritten gesetzt sein. Nur WDCE ist einmal 1 und 
einmal 0.

Oliver

von AVR-Anfänger (Gast)


Lesenswert?

Beispielsweise um die Kommunikation zwischen zwei Boards zu überwachen, 
als Timeout quasi. Antwortet das 2. Board innerhalb einer bestimmten 
Zeit nicht, soll der Watchdog auslösen.

ok soweit?

von AVR-Anfänger (Gast)


Lesenswert?

@Oliver, eher so:
1
  WDTCSR |= (1<<WDE)|(1<<WDCE);        
2
  WDTCSR = (1<<WDE)|(1<<WDCE)|(1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);    
3
  WDTCSR = (1<<WDCE)|(1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);

von Peter D. (peda)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #4058339:
> Antwortet das 2. Board innerhalb einer bestimmten
> Zeit nicht

Dann setzt man eine Timeout-Handler auf, der von einem Timerinterrupt 
getriggert wird.

von AVR-Anfänger (Gast)


Lesenswert?

Auch eine Möglichkeit, aber ich würde trotzdem gerne den Watchdog 
benutzen :/

von Peter D. (peda)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #4058452:
> aber ich würde trotzdem gerne den Watchdog
> benutzen :/

Dann mußt Du da durch.

Ich wollte Dir nur die übliche Methode aufzeigen. Einen Timer hat man ja 
eh oft laufen. Da ist es das einfachste, einen oder auch mehrere 
Timeouts mit reinzuhängen. Und man muß sich nicht mit Timed-Access und 
anderen Schnulli rumplagen und riskiert keinen versehentlichen Reset.

Vielleicht stehen ja in der wdt.h passende Macros.

von Oliver S. (oliverso)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #4058350:
> @Oliver, eher so:
...

Eher so:
1
  
2
WDTCSR |= (1<<WDE)|(1<<WDCE); // WDE und WDCE setzen
3
WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); // WDIE aktiviert Interrupt, WDCE muß 0 sein

Mit WDE lag ich falsch, das muß nur gesetzt bleiben, wenn man auch den 
WD-Reset aktivieren will. WDCE muß beim 2. Zugriff 0 sein.
Da du den Interrupt nutzen willst, muß auch WDIE gesetzt werden.

Oliver

von Ingo L. (corrtexx)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #4058339:
> Beispielsweise um die Kommunikation zwischen zwei Boards zu überwachen,
> als Timeout quasi. Antwortet das 2. Board innerhalb einer bestimmten
> Zeit nicht, soll der Watchdog auslösen.
Ich glaube das ist die ungeschickteste Möglichkeit ein Timeout zu 
überwachen, ich würd es auch wie Peter machen. Das ist der richtige Weg, 
zumal man so ein Timeout deutlich präziser einstellen kann als mit dem 
doch recht groben Prescalern des WDT...

Aber, Oliver hat dir ja schon erzählt wie man den WDT einstellt, dann 
man los!

: Bearbeitet durch User
von Thomas E. (thomase)


Lesenswert?

1
#include <avr/wdt.h>
2
3
4
#ifdef WDTO_15MS
5
  #undef WDTO_15MS
6
#endif
7
8
#ifdef WDTO_30MS
9
  #undef WDTO_30MS
10
#endif
11
12
#ifdef WDTO_60MS
13
  #undef WDTO_60MS
14
#endif
15
16
#ifdef WDTO_120MS
17
  #undef WDTO_120MS
18
#endif
19
20
#ifdef WDTO_250MS
21
  #undef WDTO_250MS
22
#endif
23
24
#ifdef WDTO_500MS
25
  #undef WDTO_500MS
26
#endif
27
28
#ifdef WDTO_1S
29
  #undef WDTO_1S
30
#endif
31
#ifdef WDTO_2S
32
  #undef WDTO_2S
33
#endif
34
#ifdef WDTO_4S
35
  #undef WDTO_4S
36
#endif
37
#ifdef WDTO_8S
38
  #undef WDTO_8S
39
#endif
40
41
#define WDTO_16MS WDTO_15MS
42
43
#define WDTO_15MS   0
44
#define WDTO_30MS   (1 << WDP0)
45
#define WDTO_32MS   (1 << WDP0)
46
#define WDTO_60MS   (1 << WDP1)
47
#define WDTO_64MS   (1 << WDP1)
48
#define WDTO_120MS  ((1 << WDP1) | (1 << WDP0))
49
#define WDTO_125MS  ((1 << WDP1) | (1 << WDP0))
50
#define WDTO_250MS  (1 << WDP2)
51
#define WDTO_500MS  ((1 << WDP2) | (1 << WDP0))
52
#define WDTO_1S     ((1 << WDP2) | (1 << WDP1))
53
#define WDTO_2S     ((1 << WDP2) | (1 << WDP1) | (1 << WDP0))
54
#define WDTO_4S     (1 << WDP3)
55
#define WDTO_8S     ((1 << WDP3) | (1 << WDP0))
56
57
#define WDP_ALL  ((1 << WDP3) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0))
58
59
#ifdef WDTCR
60
  #define WDTCSR WDTCR
61
#endif
62
63
#ifdef WDTIE
64
  #define WDIE WDTIE
65
  #define WDIF WDTIF
66
#endif
67
68
#define WATCHDOG_RESET  1
69
#define WATCHDOG_TIMER  2
70
71
72
#define InitWdtTimer(mode, wdttime) do\
73
{\
74
  if(mode == WATCHDOG_RESET)\
75
  {\
76
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
77
    MCUSR &= ~(1 << WDRF);\
78
    unsigned char temp = (1 << WDE) | wdttime;\
79
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
80
    WDTCSR = temp;\
81
  }\
82
  if(mode == WATCHDOG_TIMER)\
83
  {\
84
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
85
    MCUSR &= ~(1 << WDRF);\
86
    unsigned char temp = (1 << WDIE) | wdttime;\
87
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
88
    WDTCSR = temp;\
89
  }\
90
  if(mode == WATCHDOG_RESET + WATCHDOG_TIMER)\
91
  {\
92
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
93
    MCUSR &= ~(1 << WDRF);\
94
    unsigned char temp = (1 << WDE) | (1 << WDIE) | wdttime;\
95
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
96
    WDTCSR = temp;\
97
  }\
98
}while(0

Bei einigen älteren AVRs geht es auch einfacher. Mit dieser Methode 
funktioniert es bei allen. Ergänzend zur wdt.h sind auch die längeren 
Timeouts enthalten, die der Atmega8 und die anderen Altlasten nicht 
kennen.

mfg.

von AVR-Anfänger (Gast)


Lesenswert?

@ Thomas Eckmann,

ich habe gerade versucht deinen Code einzubinden und auszuprobieren, 
aber der Watchdog lässt sich immernoch nicht im Interrupt Modus 
aktivieren...ich wird noch verrückt...

von Oliver S. (oliverso)


Lesenswert?

Debbugst du einen realen AVR, oder den Simulator im Studio?

Oliver

von Amateur (Gast)


Lesenswert?

Eine Sequenz wie:
WDTCSR |= ...
WDTCSR  = ...
ist grundsätzlich Unsinn.

Denn egal was Du in der ersten Zeile auch machst, in der zweiten Zeile 
wird es überschrieben.

Wenn es schon zwei Zeilen sein müssen, dann aber
WDTCSR |= ...
WDTCSR |= ...

von AVR-Anfänger (Gast)


Lesenswert?

@Oliver: live im AVR

@ Amateur
Amateur schrieb:
> Eine Sequenz wie:
> WDTCSR |= ...
> WDTCSR  = ...
> ist grundsätzlich Unsinn.
>
> Denn egal was Du in der ersten Zeile auch machst, in der zweiten Zeile
> wird es überschrieben.
>
> Wenn es schon zwei Zeilen sein müssen, dann aber
> WDTCSR |= ...
> WDTCSR |= ...

so wird es aber im Datenblatt des AVR vorgezeigt(seite 66 ATmega2560) :/

von Oliver S. (oliverso)


Lesenswert?

Amateur schrieb:
> ist grundsätzlich Unsinn.

In dem Fall ist es genau richtig.
Datenblatt lesen oder Dieter Nuhr...

Oliver

von Peter D. (peda)


Lesenswert?


von AVR-Anfänger (Gast)


Lesenswert?

Hallo,

also das Problem scheint der ATmega2560 gewesen zu sein.. ich habe das 
ganze nochmal mit einem 644p versucht, da hat es wunderbar geklappt :/

von Oliver S. (oliverso)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #4067849:
> also das Problem scheint der ATmega2560 gewesen zu sein

Na, dann beschwer dich mal bei Atmel darüber, daß die M2560er mit 
defektem Watchdog ausliefern.


Oliver

von AVR-Anfänger (Gast)


Lesenswert?

Mit der Vermutung da etwas Ironie heraus zu lesen will ich hinzufügen, 
dass das Board mit dem 2560 ein Bastelboard ist. Wer weiß wo der 
schonmal einen Schaden genommen hat..

von Uwe S. (de0508)


Lesenswert?

Hallo,

es liegt sicherlich nicht am Watchdog, sondern am Programm.

Nur selten habe ich ml einen AVR µC Pin zerstören können.
Das ist aber dann meine Schuld und ich konnte es nachvollziehen.
Ein AVR µC wurde bei einem Selbstbauseminar mal mit 9V versorgt und 
hatte es überstanden, im Datenblatt ist zu lesen <7V an Vcc.

Die Inhalte aus den Atmel µC Datenblättern sind nicht immer einfach zu 
lesen, da manche Sachverhalte durch weitere Zeile im Datenblatt ergänzt 
bzw. eingschränkt werden.

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.