ATMEGA128 Watchdog Fehler finden?

Gast #4944656
Hallo,

ich hab ein Problem mit dem Watchdog des ATMega128. Das Problem ist das 
der WD tlw. nach Tagen erst zuschlägt. Hab das MCUCSR ausgewertet und 
festgestellt das es tatsächlich ein WD Reset war. Die Frage ist nur wie 
finde ich am besten das Problem im Programm?? Hat jemand eine Idee wie 
ich vorgehen könnte?

Der WD ist auf 2sec eingestellt und wird immer am Ende einer While 
Schleife gelöscht.


Gruss Patrick
Gast
genau das ist die Frage .. wo ist der letzte Moment, ich hab den WD 
Reset auch schon im Programm verstreut, an Stellen an denen ich dachte 
es wäre vorteilhaft.. leider hatte das keine Verbesserung gebracht. Die 
Verlängerung auf 2sec hatte auch nix gebracht, an irgendeiner Stelle 
hängt sich das Programm auf und die würde ich gerne finden. Ich hab nur 
noch keine Idee wie
(Firma: Vescomp)
Patrick schrieb:
> Verlängerung auf 2sec hatte auch nix gebracht, an irgendeiner Stelle
> hängt sich das Programm auf und die würde ich gerne finden. Ich hab nur
> noch keine Idee wie

 Eine volatile bei jedem WDR hochzählen und (mit ZeilenNr.) ausgeben
 oder ins Eeprom schreiben.

 n ist OK, zwischen n und n+1 ist der Übeltäter.

 P.S.
 Volatile dient dazu zu sehen wie lange das Ganze gedauert hat...
Gast
Marc V. schrieb:
> Patrick schrieb:
>> Verlängerung auf 2sec hatte auch nix gebracht, an irgendeiner Stelle
>> hängt sich das Programm auf und die würde ich gerne finden. Ich hab nur
>> noch keine Idee wie
>
>  Eine volatile bei jedem WDR hochzählen und (mit ZeilenNr.) ausgeben
>  oder ins Eeprom schreiben.
>
>  n ist OK, zwischen n und n+1 ist der Übeltäter.
>
>  P.S.
>  Volatile dient dazu zu sehen wie lange das Ganze gedauert hat...

Ok eine Idee, hast du ein Bsp. wie ich das mache?
Du kannst statt des Watchdogreset den Watchdoginterrupt nehmen und dort 
z.B. über die UART den SP und einen RAM-Dump ausgeben oder in einem 
EEPROM speichern.
Aller Code darin muß inline sein, d.h. darf keine Funktionen aufrufen 
und keine Stackvariablen anlegen, weil ja der Stack in den Wald zeigen 
könnte.
Am besten schreibt man das in Assembler.

Solche Fehler, die nur selten auftreten, deuten darauf hin, daß 
irgendein Pointer Dir den Stack zerschießt, weil außerhalb des 
Datenformats geschrieben wird.
Statt auf den Fehler zu warten, kann es daher sinnvoller sein, den Code 
auf solche Stellen abzuklopfen.
Es ist auch sinnvoll sein Programm in Zeitschlitze zu packen, Stichwort 
Echtzeit. Dann hast du den absoluten Überblick wann was in deinem 
Programm abgearbeitet wird, Hier mal ein Auszug:
1
if ( Flags.Gui ){
2
      Flags.Gui = OFF;
3
      Gui();
4
    }
5
    //////////////////////////////////////////////////////////////////////////
6
    if ( Flags.LCD_Update ){
7
      Flags.LCD_Update = OFF;
8
      Update_LCD();
9
    }
10
    //////////////////////////////////////////////////////////////////////////
11
    if ( Flags.Calc_Values ){
12
      static uint8_t TemperaturDelay = 0;
13
      Flags.Calc_Values = OFF;
14
      uint16_t Temp = 0;
15
           ...
16
    //////////////////////////////////////////////////////////////////////////
17
    if ( Flags.ReInit_LCD ){
18
      Flags.ReInit_LCD = OFF;
19
      Init_LCD();
20
       }
Mehr Überblick geht fast nicht. Ich bin absoluter Gegner von "ich 
schreib alles untereinander weg, passt schon..."
(Firma: Vescomp)
Ingo L. schrieb:
> Programm abgearbeitet wird, Hier mal ein Auszug:
1
     if ( Flags.LCD_Update ){
2
       Flags.LCD_Update = OFF;   // <-----------
3
       Update_LCD();
4
     }

 Das macht man normalerweise in umgekehrter Reihenfolge:
1
     if ( Flags.LCD_Update ){
2
       Update_LCD();
3
       Flags.LCD_Update = OFF;   // <-----------
4
     }

 Hat aber mit seinem konkretem Problem nichts zu tun, nur mit der
 Art, wie Programme überhaupt geschrieben werden sollen - und da
 gebe ich dir und peda Recht - besser vorher nachdenken als nachher
 Haare raufen...
(Firma: Vescomp)
Peter D. schrieb:
> z.B. über die UART den SP und einen RAM-Dump ausgeben oder in einem
> EEPROM speichern.

 Kann helfen, muss aber nicht...

 Wenn ein Array deklariert wird und ein Pointer auf dieses Array
 gleich hinterher, dann packt es der Compiler auch so ins RAM.
 Werden Arraygrenzen verletzt, wird auch sofort der Arraypointer
 ins Nirwana gelenkt und der Zirkus geht los.
 Falls in einem loop reingeschrieben wird, kann es sein, dass der
 Arraypointer genau auf loopcounter zeigt und dann wird es echt
 lustig - der ganze RAM kann mit Fantasiewerten überschrieben werden.

 Was ich sagen will, ist folgendes:
 Ein Dump muss nicht unbedingt etwas sinnvolles zeigen, kommt darauf
 an, welcher Mist vorher gebaut wurde.

 Eine variable und ZeilenNr. im Eeprom oder über UART rausgegeben,
 hilft da aber schon weiter, auch wenn ich so etwas nicht gerade
 debuggen nenne...


> Statt auf den Fehler zu warten, kann es daher sinnvoller sein, den Code
> auf solche Stellen abzuklopfen.

 Dem kann ich nur zustimmen.
Gast
Das das Problem mit einem Pointer zusammenhängt habe ich auch schon in 
Erwägung gezogen, es gibt in dem Programm aber nur einen einzigen 
Pointer der dazu verwendet wird einen Frame über den UART versenden:

1
void SendFTmsg(int8_t *pMsg, unsigned long dwToWrite)

der Aufruf erfolgt dann so:
1
SendFTmsg(cTxBuf, 9);
Ein RAM-Dump zeigt auch nur, wo der Fehler zuschlägt. Das ist aber fast 
nie die Funktion, die den Fehler verursacht.
Ich fülle auch gerne den Stack beim Init mit 0x77. Dann kann man im 
RAM-Dump sehen, wieviel Stack noch Reserve war.
(Firma: Vescomp)
Patrick schrieb:
> Das das Problem mit einem Pointer zusammenhängt habe ich auch schon in
> Erwägung gezogen, es gibt in dem Programm aber nur einen einzigen
> Pointer der dazu verwendet wird einen Frame über den UART versenden:

 Das Problem kann mit vielem zusammenhängen, nicht nur mit Pointer.

 Es können blockierende Routinen, Deadlocks u.ä. sein, z.B.

 Ohne Code kann dir das aber niemand genau sagen und da es sich um
 eine M128 handelt, würde ich dir empfehlen, sich keine Mühe zu
 machen, deinen Programm mit 123KB Code überhaupt hier hochzuladen...
Gast
Ich hab mir das angeschaut den WD statt MCU Reset als Interrupt zu 
verwenden, wäre nicht schlecht aber leider kann das mein ATMega128 
nicht, es gibt keine Möglichkeit mit dem WDTCR Register auf Interrupt 
umzuschalten.
Hi

Dann sollte es aber möglich sein, beim RESET (Int-Vector 0) das WDF 
(WatchDog-Flag) auszulesen.
Wenn Dieses gesetzt ist, hat der WatchDog den Reset ausgelöst.

'Riecht' nach Stacküberlauf, denke mir aber, daß nicht (nur) in 
Assembler geschrieben wurde, die benutzte Sprache wurde aber noch nicht 
genannt oder wurde von mir übersehen.

Selber, Assembler, simuliere ich die Einzelfunktionen und schaue, ob der 
StackPointer wieder zur Start-Position zurück findet (also PUSHs und 
POPs gleich oft vorhanden sind ... teilweise lasse ich mir auch 
Return-Werte auf dem Stack zurück, aber eine andere Geschichte).

Zum Eingrenzen des Fehler:
Erstelle Dir einen Ring-Puffer (10 Byte im RAM oder Programmspeicher 
sollten reichen).
Vor jeder aufzurufenden Funktion schreibst Du in diesen Ringspeicher 
eine Zahl (die Nummer der Funktion).
Wenn der WatchDog zugeschlagen hat, gibst Du diese 10 'Zahlen' immer 
wieder per UART o.Ä. aus - so hast Du eine Chance, die Reihenfolge der 
letzten 10 Funktionen zu sehen und kannst Diese 'von Hand' 
durch-simulieren.

Die Funktionen, Die Dir den Ringspeicher vollschreiben (und den 
entsprechenden Pointer versetzen), brauchen sich selber nicht in den 
Ringspeicher eintragen ;)

MfG
Gast
Hallo,

ich glaube den Fehler gefunden zu haben. Vorweg es scheint kein Problem 
mit der Software zu sein auch wenn der WD ausgelöst wird. Es war die 
Spg. Versorgung des uC, trotz BrownOut Überwachung wird zuvor der WD 
ausgelöst. Warum das passiert und nicht der BrownOut zuschlägt hab ich 
nicht herausgefunden, aber nach dem ändern der Versorgung ist das 
Problem nicht wieder aufgetreten.

Danke mal für die Tipps!
Gast
Hallo, es war doch nicht die Spg.Versorgung. Der Fehler war das es einen 
Interrupt gab für den keine ISR vorhanden war.
1
ISR(BADISR_vect)
2
{
3
  
4
}

und alles war gut :-)

Gruss Patrick
Patrick schrieb:
> ISR(BADISR_vect)
> {
>
> }
>
> und alles war gut :-)

Oh Gott, wirf Hirn.

Das ist ungefähr so, als wenn es durchs Dach regnet und Du keinen 
Dachdecker rufst, sondern Dich mit dem Regenschirm ins Zimmer setzt.

Ein Fehler, den man ignoriert, fällt einem immer wieder auf die Nase.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.