Forum: Mikrocontroller und Digitale Elektronik Programmabsturz mit Watchdog erkennen?


von Thomas S. (thomass)


Lesenswert?

Hallo Leute,

ich habe hier ein Programm geschrieben das in verschiedene Teile 
unterteil ist. Jeder Teil läuft unabhängig voneinander.
Wird also ein Teil des Programms nicht mehr durchlaufen funktioniert der 
Rest immer noch.

Nun möchte ich etwas programmieren damit ich erkennen kann ob ein 
Unterprogramm nicht mehr bearbeitet wird und dann einen Reset auslösen.

Was ich schon gemacht habe das ich eine Variable hochzählen lasse bei 
jedem Unterprogrammduchlauf. Wird ein Unterprogramm nicht mehr 
durchlaufen wird die Variable nicht mehr hochgezählt und der Watchdog 
ausgelöst.
Ungefähr so
1
//Unterprogramme sind nicht in der Main Schleife
2
//Unterprog 1
3
// ...
4
if(counter == 0)
5
   counter = 1;
6
// ...
7
//Unterprog 2
8
// ...
9
if(counter == 1)
10
   counter = 2;
11
// ...
12
//Unterprog 3
13
// ...
14
if(counter == 2)
15
   counter = 3;
16
// ...
17
//Unterprog 4
18
// ...
19
if(counter == 3)
20
   counter = 4;
21
// ...
22
23
// in Main
24
25
if(timer > 500) // 500 ms
26
  wdt_enable(WDTO_15MS);
27
if(counter == 4)  // es wurden alle Unterprogramme korrekt durchlaufen
28
  timer = 0;
29
// ISR
30
31
ISR (Timer 1)  // Interrupt im 1ms Takt
32
{
33
  timer++;
34
}

Das funktioniert recht zuverlässig, doch scheind mir die Programmierung 
etwas umständlich.
Ich habe leider nichts gefunden wie man solch einen Watchdog korrekt 
programmiert.
Ein kleiner Code wäre nicht schlecht.

Es soll nur erkannt werden ob das Programm noch korrekt läuft.

Danke schon mal

Thomas

von Klaus (Gast)


Lesenswert?

Normalerweise startest Du den Watchdog-Timer zu beginn deines Programms 
und setzt Ihn dann in der main-Schleife immer wieder mit wdt_reset() 
zurück.

Setzt Du ihn nicht zurück, startet der Controller neu.
1
void init() {
2
  ...
3
  wdt_enable(WDTO_15MS);
4
}
5
6
void main() {
7
 init()
8
 while(1)
9
 //deine Befehle (Dauer: höchstens 15ms, sonst folgt ein Reset durch den WDT
10
 wdt_reset(); //WDT auf 0 zurücksetzen.
11
12
 //weitere Befehle
13
 wdt_reset();
14
}

von Klaus (Gast)


Lesenswert?

Entschuldige, ich habe ein paar Klammern vergessen:
1
void init() {
2
  ...
3
  wdt_enable(WDTO_15MS);
4
}
5
6
void main() {
7
 init()
8
 while(1)
9
 {
10
    //deine Befehle (Dauer: höchstens 15ms, sonst folgt ein Reset durch den WDT
11
    wdt_reset(); //WDT auf 0 zurücksetzen.
12
13
    //weitere Befehle
14
    wdt_reset();
15
  }
16
}

von Thomas S. (thomass)


Lesenswert?

Hallo Klaus,

wenn ich jedoch in der Main Schleife den Watchdog zurücksetze dann sehe 
ich nur das meine main durchlaufen wird.
Ich kommuniziere zB. mit einem externen Gerät lese noch eine 
Tasterturmatrix aus und diverse Schalterstellungen nun habe ich es so 
gemacht das alles unabhängig läuft.
Tasterabfragen alle 30ms und die UART Kommunikation Anfrage warten auf 
ACK-Antwort alle 100ms.
Tritt nun ein Fehler bei der UART Kommunikation auf und das Programm 
wartet auf Antwort und diese wird jedoch nicht empfangen so liegt ein 
Fehler bei der Kommunikation vor und diese Fehler habe ich zwar 
Softwareseitig abgefangen jedoch kann es immer zu Fehlern kommen die 
nicht vorhergesehen wurden.
Ich verwende keine wait etc. sondern alles funktioniert per Interrupts.
Somit wird die while(1) Scheife immer durchlaufen ob ein Unterprogramm 
korrekt abgearbeitet wird oder nicht.

Ich möcht nur sicher gehn das alles korrekt durchlaufen wird und falls 
einmal ein Unterprogramm einen Fehler hat ein RESET durchgeführt wird.

Thomas

von spess53 (Gast)


Lesenswert?

Hi

Dann must du dir einen eigenen Watchdog bauen. Für jedes deiner zu 
überwachenden Programmteile eine Varible definieren. Die wird im 
Programmteil mit einem Wert geladen und in einem Timerinterrupt 
heruntergezählt. Wenn die Variable Null wird hast du einen Time-Out. 
Fertig.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Thomas S. schrieb:

> Ich verwende keine wait etc. sondern alles funktioniert per Interrupts.
> Somit wird die while(1) Scheife immer durchlaufen ob ein Unterprogramm
> korrekt abgearbeitet wird oder nicht.

Nicht immer.
Wenn dein Programm in einem Interrupt in einer Endlosschliefe hängt, 
kommt normalerweise auch die Hauptschleife nicht mehr zum Zug.
Da hilft dann nur noch ein Hardwarewatchdog.

von Marcus K. (marcusk)


Lesenswert?

> Tritt nun ein Fehler bei der UART Kommunikation auf und das Programm
> wartet auf Antwort und diese wird jedoch nicht empfangen so liegt ein
> Fehler bei der Kommunikation vor und diese Fehler habe ich zwar
> Softwareseitig abgefangen jedoch kann es immer zu Fehlern kommen die
> nicht vorhergesehen wurden.
das macht gute software entwicklung ebend so schwer, es sollte keine 
fehler geben die nicht vorgesehen sind. Was sollen denn das für Fehler 
sein?

Stack überlauf -> danach ist eh alles aus, da hilft nur der Watchdog
Schleife die nicht beenden wird->Programmierfehler sollte sich finden 
lassen

von Thomas S. (thomass)


Lesenswert?

Marcus Kunze schrieb:
>
> Stack überlauf -> danach ist eh alles aus, da hilft nur der Watchdog
> Schleife die nicht beenden wird->Programmierfehler sollte sich finden
> lassen

Es ist so das ich mein Gerät nun ca 1.5 Jahre läuft, ich habe mir einen 
Watchdog  gebaut der ausgelöst wird sobald nicht alle Programmteile 
inerhalb von 1 Sekunde durchlaufen werden.
Ich habe mir eine Variable incrementiert und in den EEPROM geschrieben 
befor ich den Watchdog ausgeführt habe.
Somit konnt ich per Displaysteuerung auslesen wieviele Watchdogs 
ausgeführt wurden.
35 Fehler in 1.5 Jahren ist meiner Meinung nicht so schlecht zumal ich 
nur hobbymässig programmiere.
Da ich zur Zeit an einer Erweiterung bastle ist mir der Watchdog 
aufgefallen und daher wollte ich wissen ob es noch weitere Wege gibt 
aber anscheinend nicht.

@ spess53,

wie Du es beschreibst habe ich es auch gemacht. Schien mir nur etwas 
umständlich.

Danke für alle Antworten

Thomas

von wachhund (Gast)


Lesenswert?

watchdog ist nicht dazu gedacht logische programmierfehler zu 
beseitigen.

von Thomas S. (thomass)


Lesenswert?

wachhund schrieb:
> watchdog ist nicht dazu gedacht logische programmierfehler zu
> beseitigen.

Wenn ein Programm teilweise 3 Monate läuft ohne Fehler kann man ja nicht 
von "logischen Programmierfehlern" sprechen.
Watchdog ist genau hierfür gedacht um zu verhindern das ein Programm 
hängen bleibt.Dies kann auch äußere Einflüsse haben nicht nur 
Programmierfehler.

Thomas

von Ste N. (steno)


Lesenswert?

Hallo Thomas,

ich mache das immer so. In einer globalen Variable werden die einzelnen 
Bits je einem Interrupt zugeordnet. Wird ein Interrupt aufgerufen wird 
das entsprechende Bit gelöscht. In der Main wird nun die Variable 
ständig abgefragt und bei 0 der WDT und die Variable zurückgesetzt. Der 
WDT muß nur lang genug sein, damit auch die langsamste Interruptquelle 
zum Zuge kommen kann. Das geht schnell und benötigt vor allem in den 
Interrupts keine If-Then-Abfragen. Auch den Timer, wie in deinem 
Beispiel, kannst Du dir so sparen.

Viele Grüße,
Steffen

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.