mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Programmabsturz mit Watchdog erkennen?


Autor: Thomas S. (thomass)
Datum:

Bewertung
0 lesenswert
nicht 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
//Unterprogramme sind nicht in der Main Schleife
//Unterprog 1
// ...
if(counter == 0)
   counter = 1;
// ...
//Unterprog 2
// ...
if(counter == 1)
   counter = 2;
// ...
//Unterprog 3
// ...
if(counter == 2)
   counter = 3;
// ...
//Unterprog 4
// ...
if(counter == 3)
   counter = 4;
// ...

// in Main

if(timer > 500) // 500 ms
  wdt_enable(WDTO_15MS);
if(counter == 4)  // es wurden alle Unterprogramme korrekt durchlaufen
  timer = 0;
// ISR

ISR (Timer 1)  // Interrupt im 1ms Takt
{
  timer++;
}

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

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
void init() {
  ...
  wdt_enable(WDTO_15MS);
}

void main() {
 init()
 while(1)
 //deine Befehle (Dauer: höchstens 15ms, sonst folgt ein Reset durch den WDT
 wdt_reset(); //WDT auf 0 zurücksetzen.

 //weitere Befehle
 wdt_reset();
}


Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entschuldige, ich habe ein paar Klammern vergessen:
void init() {
  ...
  wdt_enable(WDTO_15MS);
}

void main() {
 init()
 while(1)
 {
    //deine Befehle (Dauer: höchstens 15ms, sonst folgt ein Reset durch den WDT
    wdt_reset(); //WDT auf 0 zurücksetzen.

    //weitere Befehle
    wdt_reset();
  }
}

Autor: Thomas S. (thomass)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Marcus Kunze (marcusk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thomas S. (thomass)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: wachhund (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
watchdog ist nicht dazu gedacht logische programmierfehler zu 
beseitigen.

Autor: Thomas S. (thomass)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Steffen N. (steno)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.