Hallo zusammen, ich benutze einen AT90CAN128 und habe ein Problem mit dem Watchdog. Falls das Programm hängen bleibt soll der Mikrocontroller sich neu starten. Bei der Initialisierung aktiviere ich den Watchdog mit 250ms Timeout: wdt_enable(WDTO_250MS); // Watchdog Timeout = 250ms Da ich in der Hauptschleife einige Delays habe würde ich den Watchdog Reset gerne in einem Interrupt ausführen. wdt_reset(); Der Grund wieso ich den WDT-Reset in einem Interrupt ausführn ist weil während den geplanten Delays in der Hauptschleife kein Timeout ausgelöst werden darf. (Globale Interrupts während Delays immer aktiviert) Nun das ganze funktioniert eigentlich. Wenn ich das Programm mit einem Taster in eine Endlosschleife bringe (nur zu Testzwecken) resetet der Controller. Leider resetet er dann auch noch weiter nachdem ich den Taster nicht mehr drücke. Kann mir keinen Reim darauf bilden. Hat jemand eine Idee wo mein Fehler liegt? Danke für Tipps. Gruss Dominik
Was soll das Triggern im Interrupt bringen? Damit kanst du nur überprüfen ob dein Timerinterrupt noch arbeitet. Mach eine Hauptschleife im Programm die ziklisch abgearbeitet wird und am Ende dieser den Trigger. Delays kann man auch realiesieren ohne den ganzen Programmablauf zu stoppen.
Dominik W. schrieb: > Hat jemand eine Idee wo mein Fehler liegt? Möglicherweise gelangt das Programm nach einem Watchdog-Reset nicht mehr schnell genug an die Stelle, wo der Watchdog erstmals wieder getriggert wird. Watchdog im Interrupt sollte man besser bleiben lassen, denn ein Interrupt kann auch unbehelligt weiter laufen, wenn das Hauptprogramm schon lange abgestürzt ist. Hier und dort wird in Application Notes schon mal empfohlen, den Watchdog im Interrupt zurück zu setzen. Dann sind die Schreiber der Application Notes ahnungslos, und reiten den Anwender ins Verderben. Das diskutierten wir kürzlich noch bei einem STM32, weil es dort angeblich so empfohlen wurde.
Wenn du deinen WDT in der Timer-ISR rücksetzt, stellst du damit nur sicher, dass sich diese ISR nicht aufhängt. Wenn im Hauptprogramm irgendwas schief läuft und der Controller sich in einer Schleife befindet, aus der er nicht rauskommt, hilft der WDT da überhaupt nichts... Ingo
Wenn der Watchdog eingeschaltet ist, bleibt er an, solange die Stromversorgung eingeschaltet ist. Auch ein Reset schaltet ihn nicht ab (was ich seltsam finde). Darum solltest Du ganz am Anfange des Programms zuerst den Watchdog abschalten, dann die Initialisierungsroutinen durchlaufen, und ihn dann wieder einschalten. Oder Du sorgst dafür, dass die Initialisierungsroutinen den Watchdog schnell genug zurück setzt. Zum Beispiel, indem Du die Initialisierung in mehrere kleine Schritte terlegst, die nicht zu lange dauern. Etwas so:
1 | int main(){ |
2 | watchdog_einschalten; |
3 | watchdog_reset; |
4 | init_teil1; |
5 | watchdog_reset; |
6 | init_teil2; |
7 | watchdog_reset; |
8 | init_teil3; |
9 | while (1) { |
10 | watchdog_reset; |
11 | eingänge_anfragen; |
12 | ereignisse_behandeln; |
13 | }
|
14 | }
|
Eine gedrückt gehaltene Taste sollte keine Endlos-Warteschleife auslösen. Da hast Du offensichtlich ein Programm-Konzept gewählt, dass mit Watchdogs nicht vereinbar ist. Hier im Forum gibt es schon reichlich Beispiele, wie man Tasten ohne Endlos-schleifen abfragt und entprellt. Programme mit Watchdog sollten nur eine einzige Endlosschleife haben, und das ist das Hauptprogramm. Alles Andere sollten nur Reaktionen auf Ereignisse sein. In diesem Sinne wäre das Drücken der Taste ein Ereignis und das Loslassen wäre ein zweites Ereignis.
1 | uint8_t taste_jetzt; |
2 | uint8_t taste_vorher; |
3 | |
4 | int main(){ |
5 | while (1) { |
6 | taste_jetzt=taste_abfragen(); |
7 | if(taste_jetzt==1 und taste_vorher==0) { |
8 | // Taste wurde gerade gedrückt
|
9 | tuwas; |
10 | }
|
11 | else if(taste_jetzt==0 und taste_vorher==1) { |
12 | // taste wurde gerade losgelassen
|
13 | tuwas_anderes; |
14 | }
|
15 | taste_vorher=taste_jetzt; |
16 | }
|
17 | }
|
Entprellung habe ich hier mal ausgelassen, damit es nicht unübersichtlich wird. Auch Zeitliche Ereignisse müsstest Du so behandeln. Wenn z.B. nach dem Drücken des Taster eine LED kurz 5s lang an gehen soll, dann geht das so:
1 | uint8_t taste_jetzt; |
2 | uint8_t taste_vorher; |
3 | uint16_t volatile systemzeit; // z.B Timer der jede Sekunde hochzählt |
4 | uint16_t led_aus_zeit; |
5 | |
6 | int main(){ |
7 | while (1) { |
8 | taste_jetzt=taste_abfragen(); |
9 | |
10 | if(taste_jetzt==1 und taste_vorher==0) { |
11 | // Taste wurde gerade gedrückt
|
12 | schalte_led_an; |
13 | led_aus_zeit=systemzeit+5; |
14 | }
|
15 | |
16 | if (systemzeit>led_aus_zeit) { |
17 | // LED soll jetzt wieder aus gehen
|
18 | schalte_led_aus; |
19 | }
|
20 | |
21 | taste_vorher=taste_jetzt; |
22 | }
|
23 | }
|
Die Systemzeit wäre eine Variable, die von einem Timer-Interrupt jede Sekunde um 1 erhöht wird. Die ISR habe ich der Übersicht halber hier ausgelassen. Ich denke, so kriegst Du das hin.
> Watchdog im Interrupt sollte man besser bleiben lassen, > denn ein Interrupt kann auch unbehelligt weiter laufen, > wenn das Hauptprogramm schon lange abgestürzt ist. Ich wage sogar zu behaupten, dass dies fast immer zutrifft. Deswegen ist es Sinnlos.
Nen WD-Reset braucht man eigentlich nur, wenn man das logische, bzw. timingmässige Zusammenspiel der Codesegmente nicht wirklich versteht. Ansonsten sollte man jeden Zweig so programmieren, daß ein Ausbremsen durch Input-Aktionen bzw. ein Aufhängen ausgeschlossen ist, oder zumindest über eine ERROR-Routine abgefangen und lokalisiert wird. Dann kann man ggf. auch gezielt debuggen und entschärfen. Sauberer Code hängt sich nirgendwo auf. Statt warten, und/oder unnötig in Schleifen pollen, kann man gezielt INTs nutzen, um spontan auf einen prioritären Event zu reagieren... D.h. es ist besser man reagiert nur auf Flankenwechsel, statt auf Pegelzustände.
> D.h. es ist besser man reagiert nur auf Flankenwechsel
Sag ich ja. Und wenn man sich dran gehalten hat, ist es auch leicht, den
Watchdog-Reset an einer Sinvollen Stelle unter zu bringen.
Praktisch habe ich allerdings die Erfahrung gemacht, dass
Mikrocontroller (egal welche Modellreihe) absolut stabil laufen, sofern
Schaltung und Programm fehlerfrei sind. Dann braucht man keinen
Watchdog.
Wenn ein Mikrocontroller sich aufhängt, hat man irgendwo etwas falsch
gemacht.
Schutz gegen Aussetzer in der Stromversorgung erreicht man besser durch
den Brown-Out Detektor.
Michael Sch. schrieb: > Nen WD-Reset braucht man eigentlich nur, wenn man das logische, bzw. > timingmässige Zusammenspiel der Codesegmente nicht wirklich versteht. Wenn man ein perfekter Programmierer ist, der alle möglichen und insbesondere auch die vermeintlich unmöglichen Situationen vorhersieht, und sich die verbaute Hardware ebenfalls in allen nur erdenklichen Lebenslagen perfekt verhält, dann braucht man keinen Watchdog. Aber wie oft findet man eine solche Konstellation schon?
Die Erkenntnis, dass der Rechner sich ab und zu resettet, hilft allerdings nicht, den Programmfehler zu finden. Ganz im Gegenteil. Dazu kommt, dass das ganze System für den Fall ausgelegt sein muss. Wenn mit beim Reset das Garagentor auf den Kopf knallt, freue ich mich nicht. Oder wenn die Uhr im Laufe einiger Wochen immer ungenauer wird, weil der Antriebsmotor ab und zu kurz stehen bleibt, dann bin ich nicht zufrieden. Oder wenn mein Handy hin und wieder eigenmächtig Gespräche unterbricht, habe ich keinen Spass. Oder wenn Im Büro die Lichter ausgehen, weil die Lichtsteuerung sich zurückgesetzt hat, herrscht Unruhe im Büro.
Stefan Frings schrieb: > Die Erkenntnis, dass der Rechner sich ab und zu resettet, hilft > allerdings nicht, den Programmfehler zu finden. Ganz im Gegenteil. Es behauptet m.W. niemand, dass ein Watchdog das Allheilmittel für alle Lebenslagen ist. Es ist ein Notnagel, mehr nicht. Wie oben schon gesagt, perfekte Technik ist mir auch lieber.
Beispiel für Watchdog: Man baut eine Heizungssteuerung. Ein Brenner, der tagelang durchläuft weil sich die Steuerung verhakt hat, fördert zwar die Wirtschaft, ist aber nicht im Interesse des Bewohners. Der will, dass (1) nichts abbrennt und (2) nichts einfriert. Wenn sich die Steuerung durch einen Watchdog resettet, dann bricht vielleicht eine Aktion ab, aber die erwähnten Kriterien lassen sich mit hoher Wahrscheinlichkeit einhalten. Einer Fehlersuche steht das nicht unbedingt im Weg, wenn man dran gedacht hat, die Aktivitäten und Sensorinformationen zu protokollieren. Ein nicht ganz perfekte Lösung mit Notnagel für seltene unvorhergesehene Fälle ist mir jedenfalls lieber, als eine angeblich perfekte Lösung, bei der widrigenfalls ein Neubau ansteht. Denn erfahrungsgemäss zeichnen sich perfekte Lösungen nur dadurch aus, dass man den Problemfall entweder noch nicht hatte oder unter den Teppich kehrte. Was nicht heisst, dass der Einsatz des Notnagels zu Regel werden sollte.
Danke für die vielen Ideen und Tipps. Wahrscheinlich hat Stefan Frings mit seiner Annahme recht das der Watchdog bei der Initialisierung zuerst (wieder) abgeschaltet werden muss. @Stefan Frings: Ein Taster führt natürlich nicht zu einer Endlosschleife. Ich habe das absichtlich programmiert um den Watchdog zu testen! Das macht sonst keinen Sinn. Delays sollte man natürlich nicht über die Hauptschleife lösen, sondern über Timer. Bei mir ist es etwas speziell. Bei einem normalen Durchlauf gibt es keine Delays. Nur bei speziellen Vorgängen wie Relais schliessen und anschliessend Spannung überprüfen. Ich werde mir nochmal überlegen wie ich den Watchdog bei mir implementiere. Danke nochmal für die Antworten. Gruss Dominik
Das System funktioniert übrigens prima und sollte so programmiert sein das es sich nicht aufhängen kann. Trotzdem es sind fast 3000 Zeilen Code. Es handelt sich um die Steuerung von einem 30kW Elektrokart (Eigenbau). Der Watchdog soll einfach zusätzlich Sicherheit bringen. Wahrscheinlich wäre es sinnvoll alle zeitlichen Vorgänge (Relais schliessen, Vorladen, etc) mithilfe von Timern zu lösen und dann einen WDT_Reset in er Hauptschleife zu implementieren.
Dominik W. schrieb: > Der Watchdog soll einfach > zusätzlich Sicherheit bringen. Das Problem ist aber, dass du genau dieses mit einem Watchdog-Reset im Timer-Interrupt aushebelst. > Wahrscheinlich wäre es sinnvoll alle zeitlichen Vorgänge (Relais > schliessen, Vorladen, etc) mithilfe von Timern zu lösen und dann einen > WDT_Reset in er Hauptschleife zu implementieren. Jetzt geht die Reise in die richtige Richtung!
Hallo, die Idee, auch die ISR darauf zu prüfen, ob sie noch ausgeführt wird, ist ja keineswegs falsch, auch wenn das hier manche verächtlich als Dummheit abtun (gehört hier wohl zum "guten" Stil, Lösungen anderer als Idiotie zu bezeichnen). Nur muss eben die Hauptschleife auch und vor allem abgesichert werden, also bräuchte man 2 Watchdogs, was es meines Wissens nirgends gibt. Ich löse das daher mit Flags, die in main gesetzt und in den ISRs zurückgesetzt werden, passiert das nicht, wird ebenfalls ein Neustart ausgelöst. Somit wird main durch den Watchdog und die ISRs durch main gecheckt. Übrigens ist es überhaupt kein Problem, in main delays zu verwenden, man muss nur dafür eine allgemeingültige und natürlich sauber programmierte delay-Routine verwenden, in der ausreichend oft der Watchdog getriggert wird. Gruss Reinhard
Danke Reinhard. Die ISR sind bei mir ebenfalls sehr wichtig. Ich werde das auch mit Flags lösen. Dann mal an die Arbeit. :)
Michael Sch. schrieb: > Nen WD-Reset braucht man eigentlich nur, wenn man das logische, bzw. > timingmässige Zusammenspiel der Codesegmente nicht wirklich versteht. Du vergißt äußere Einflüsse auf den Prozessor, wie z.B. Höhenstrahlung
Michael Sch. schrieb: > Nen WD-Reset braucht man eigentlich nur, wenn man das logische, bzw. > timingmässige Zusammenspiel der Codesegmente nicht wirklich versteht. Das ist die Stellungnahme von jemandem, der sich selbst für unfehlbar hält, und seine eigene Software für von vornherein fehlerfrei. Kommentar überflüssig. Gruss Reinhard
Hi >...und seine eigene Software für von vornherein fehlerfrei. Nicht von vorn herein. Aber irgendwann muß sie es sein. Und erst dann kann man sie über den Einsatz des Watchdogs Gedanken machen. Dominik W. (Gast) schrieb: >Falls das Programm hängen bleibt soll der Mikrocontroller sich neu >starten. Ein Programm bleibt nicht einfach so hängen. Das hat immer einen Grund. Und diesen Grund muss man finden und beseitigen, nicht mit einem Watchdog kaschieren. MfG Spess
Der Watchdog wird oft hoffnungslos überschätzt und seine Programmierung unterschätzt. Wenn z.B. auf eine 8Bit-Variable 16bittig zugegriffen wird, wird die nachfolgende Variable mit Mumpitz geladen und Dein MC rechnet mit Mumpitz weiter. Den Watchdog interessiert das in keinster Weise. Oder eine fehlende atomare Kapselung. Usw. usw. ... Ein Watchdog schützt also nicht gegen schlampiges Programmieren. Ein Watchdog ist nur sinnvoll bei erhöhten Sicherheitsanforderungen. Aber dann ist es witzlos, ihn irgendwie einzufügen. Man implementiert ihn erst, nachdem die Applikation fertig programmiert ist. Er ist quasi eine vollkommen eigenständige Aufgabe, die nochmal eine komplette Planung benötigt. Überlegt man nicht sorgfältig, welche Fehler auftreten können und wie man sie mit dem Watchdog erkennen könnte, kann man sich die Arbeit mit dem Watchdog auch gleich ganz sparen. Er hat dann in etwa die zusätzliche Sicherheit, wie ein eingefügtes NOP.
Peter Dannegger schrieb: > Oder eine fehlende atomare Kapselung. Das kommt ja noch hinzu, z.B. beim Siemens/Infineon SAB80C517A oder C515. Die Watchdog-Sequenz besteht aus zwei Befehlen, die nicht auseinander gerissen werden dürfen, auch kein NOP oder was anderes dazwischen sein darf. Also: Vor der Sequenz Interrupts global sperren, und nachher wieder frei geben. Wie bei größeren Variablen, die im Interrupt und im Hauptprogramm verwendet werden. In mancher Software ist es wohl reiner Zufall, daß da nichts passiert. Womit man wieder beim Thema bugfreie Software ist. Die kann ja z.B. ein Jahr lang auf dem Prüfstand einwandfrei spielen. Das heißt aber eben nicht auch bugfrei, wenn sich zufällig mal nichts ins Gehege kommt. Na ja, es gibt verschiedenes, der eingebaute Watchdog ist so ein gutes Mittelding, hilft bei erhöhten Sicherheitsanforderungen auch nicht. Meine SAB80C517A haben erstaunlicherweise sogar noch einen Oszillator-Watchdog auf dem Chip. Der hält den Chip an, und fährt die Ports in einen definierten Zustand, wenn der Quarz aus fällt, bspw. in stark vibrierenden Anwendungen. Das Programm startet erst wieder, wenn sich der Quarztakt stabilisiert hat. Oder auch nicht, wenn man das per Software selbst bestimmt. Die Dinger wurden eine Weile mal massenweise in Autos verbaut. Dann habe ich hier auch noch einen externen Watchdog liegen, der an zwei µC-Pins kommt. Der hat ein internes RC-Glied für die Zeitkonstante, was sehr sicher ist, eine Art retriggerbares Monoflop. In alter Literatur habe ich immer wieder solche Beispiele und Schaltbilder.
Dominik W. schrieb: > Falls das Programm hängen bleibt soll der Mikrocontroller sich neu > starten. Dafür ist ein Watchdog da. > Da ich in der Hauptschleife einige Delays habe würde ich den Watchdog > Reset gerne in einem Interrupt ausführen. Schwachsinn. Damit kann der Watchdog genau das nicht mehr leisten, wofür er da ist: die Auswirkungen von unvorhergesehenen Softwarefehlern zu begrenzen. Du hast ein Softwaredesignproblem. Lange delays haben (außer für Lehr- und Testzwecke) nirgendwo irgendetwas zu suchen, auch nicht in der Hauptscheife. So einfach ist das. Also behebe dein Designproblem und du hast auch kein Problem mehr mit dem Watchdog.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.