Forum: Compiler & IDEs Watchdogs beim MEGA32


von Siegfried Müller (Gast)


Lesenswert?

Wie wird eigentlich der Watchdog beim ATMEGA32 in C verwendet?

Ich habe mal ein wenig im Tutorial herumgeschaut, aber dort wurde mir 
die Funktionsweise noch nicht ganz klar. Aus den Informationen habe ich 
geschlossen, dass man am Anfang einmal wdt_enable(WDTO_2S); schreiben 
muss, um den Watchdog einzuschalten. Muss man das vor dem Befehl sei(); 
machen oder danach (ich benutze noch timer-interrupts)? Dann dachte ich 
mir, dass ich den Watchdog in jedem Timerzyklus zurücksetze mit 
wdt_reset();. Aber irgendwie klappt das nicht.

Habe nämlich das Problem, dass mein Mikrocontroller aus für mich 
unerklärlichen Gründen nach unregelmäßiger Laufzeit abstützt. Wenn ich 
sei(); aus meinem Programm herauskommentiere und nur in der 
Hauptschleife eine LED toggle, gehts.

Im Programm ist sonst nur noch der 16-bit Timer verwendet und die 
serielle Schnittstelle ohne Empfangsinterrupt. Kann mir jemand 
weiterhelfen, also zunächst mit dem Watchdog und ggf. noch mit dem 
Abstürzproblem?

von Lutz (Gast)


Lesenswert?

"Absturzprobleme" nur bei sei() enabled lassen üblicherweise 2 Ursachen 
vermuten:
1.) Der Watchdog macht das, was er soll: Er schlägt zu, wenn er nicht 
rechtzeitig wieder resetted wurde. Absichtlich wohl eher selten, ist 
eher das Ergebnis einer deutlich längeren Laufzeit in Unterprogrammen, 
Interrupthandlern etc.. Wenn das wie bei Dir in unregelmäßigen Abständen 
passiert, hört sich das Plausibel an. Irgendwo wird mal etwas länger als 
sonst gebraucht und schwups ...

2.) Es wird irgendwo ein anderer Interrupt aktiviert und bei sei() ohne 
zugehörigem aktivierten ISR-Handler gibt es einen reset. Auch das kann 
bei unregelmäßigen Resets die Ursache sein; irgendwann kommt mal ein 
Interrupt, den Du nicht geplant hast. Das läßt sich durch leere 
Interrupthandler oder einen "Allescatcher"
1
#include <avr/interrupt.h>
2
3
ISR(BADISR_vect)
4
{
5
    // user code here
6
}
ja mal von Dir ausschließen. Die avr-libc
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html 
ist 'ne feine Sache.

von Siegfried Müller (Gast)


Lesenswert?

Dank Lutz für die Tipps - werde ich morgen mal testen. Aber dazu habe 
ich doch noch ein paar Fragen: Unter Absturz verstehe ich ein 
stehenbleiben, d.h. in meinem Toggle-LED-Programm bleibt die Led an. 
Passiert so etwas bei einem Reset? Dachte eigentlich immer, dass bei 
einem Reset der µC neugestartet wird, also das Programm von vorne 
beginnt.

Fängt der "Allescatcher" alle Interrupts ab, d.h. auch die, die ich 
definiert habe, oder nur die übrigen?

Was genau meinst du mit "deutlich längerer Laufzeit in Unterprogrammen"?

von Lutz (Gast)


Lesenswert?

>Unter Absturz verstehe ich ein stehenbleiben, d.h. in meinem
>Toggle-LED-Programm bleibt die Led an.
gut zu wissen

>Passiert so etwas bei einem Reset? Dachte eigentlich immer, dass
>bei einem Reset der µC neugestartet wird, also das Programm von
>vorne beginnt.
Nein. Wie Du schon schriebst, bei einem Reset fängt das Programm von 
vorne an. Zuerst wird natürlich der µC in seinen Resetzustand (Register 
haben dann die "initial values") versetzt, und der steht im Datenblatt 
(jedenfalls kein normaler Port steht auf 1). Jetzt hängt es natürlich 
von Deinem Programm und dem Verlauf ab, ob es von außen überhaupt zu 
unterscheiden ist ob der µC wirklich "stehen bleibt" (das würde auf eine 
versehentliche Endlosschleife schließen lassen) oder nach dem reset 
anscheinend sofort wieder den gleichen Fehler macht und an gleicher 
Stelle resettet (was dann, je nach Frequenz/Dauer eines Resetzyklus, 
auch wie Dauerleuchten einer LED aussehen kann).
>Fängt der "Allescatcher" alle Interrupts ab, d.h. auch die,
>die ich definiert habe, oder nur die übrigen?
Er fängt nur die von Dir nicht definierten Interrupts ab. Es gibt auch 
noch empty interrupt-Handler
EMPTY_INTERRUPT(ADC_vect);
die mußt Du aber für jeden einzelnen Interrupt definieren (hier z.B. 
ADC), die machen gar nix an Funktion. Aber les Dir das mal in Ruhe in 
dem Link durch; da kommst Du eh nicht drum rum.
>Was genau meinst du mit "deutlich längerer Laufzeit in Unterprogrammen"?
Unterprogramme ist natürlich syntaktisch verkehrt, ich meine Funktionen. 
Du kannst ja z.B. auf irgendwas in den Funktionen reagieren, z.B. bei 
Timerinterrupt lese Port_sowieso ein. Wenn der Wert x ist, mache das, 
wenn y, jenes etc. Und da kann theoretisch ja mal was kommen, was länger 
dauert als Du dachtest. Nicht unbedingt in einer Abfrage, aber 
irgendeine wilde Kombination. Und ein Takt zu spät reicht dem watchdog 
...

von Siegfried Müller (Gast)


Lesenswert?

>Und ein Takt zu spät reicht dem watchdog
Ach so, mit Watchdog meintest du das. Habe ich denn den Watchdog richtig 
verwendet, bzw. ist mein Verständnis davon aus meinem ersten Posting 
richtig?

>das würde auf eine versehentliche Endlosschleife schließen lassen
Das dachte ich auch, weshalb ich in alle while-Schleifen einen 
Abbruch-Zähler eingebaut habe, der eine zusätzliche Bedingung darstellt. 
Nachdem das aber nicht ging, habe ich mal alle Schleifen auskommentiert 
und das Programm sehr stark reduziert, was leider nicht zum Erfolg 
führte.

von Lutz (Gast)


Lesenswert?

>Habe ich denn den Watchdog richtig verwendet, bzw. ist mein
>Verständnis davon aus meinem ersten Posting richtig?
Grundsätzlich ja. Der Watchdog sollte (wie so ziemlich jede 
"Peripherie", hier aber nicht zwingend) vor dem aktivieren konfiguriert 
sein; in diesem Fall also wdt_enable(Zeit) und dann erst sei(). sei() 
darf aber auch nicht zu spät nach dem Aktivieren kommen, denn die Zeit 
des watchdog beginnt natürlich mit wdt_enable() zu Laufen! Wenn Du z.B. 
mit wdt_enable(WDTO_2S) 2 Sekunden einstellst, dann alles mögliche 
machst und der wdt_reset() zu spät kommt, hast Du nach sei() natürlich 
gleich schon Feierabend. Die Zeit kannst allerdings nur Du bestimmen, da 
nur Du Dein Programm kennst und wie lange es auch im worst case braucht 
(die schon beschriebenen Funktionen, die mal längern dauern könnten und 
mal nicht), bis der nächste wdt_reset() aufgerufen wird.
Es gibt laut Datenblatt ja mehrere Werte (steht aber auch in de Doku der 
avr-libc wie im Link), die man einstellen kann, bis der watchdog 
zuschnappt.
Vielleicht solltest Du Dein Programm mal im Debugger bzw. Simulator 
(z.B. AVR-Studio, sofern Du Windowsbelastet bist) durchgehen und mal 
verfolgen, was dort so passiert.
Viel Erfolg und schönes Wochenende.

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.