ATMEGA128 Watchdog Fehler finden?

Gast #4944656
Lesenswert?

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 #4944667
Lesenswert?

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) #4944718
Lesenswert?

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 #4945089
Lesenswert?

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?
#4945350
Lesenswert?

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.
#4945371
Lesenswert?

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) #4945406
Lesenswert?

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) #4945448
Lesenswert?

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 #4945455
Lesenswert?

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);
(Firma: Vescomp) #4945482
Lesenswert?

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 #4945565
Lesenswert?

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.
#4946204
Lesenswert?

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 #4949413
Lesenswert?

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!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren