Forum: Mikrocontroller und Digitale Elektronik "Absturzstelle" ermitteln


von Andy (Gast)


Lesenswert?

Hallo,

Ich habe das Problem, dass mein (ziemlich großes) Programm hin und 
wieder abstürzt und von vorne beginnt (reset). Gibt es eine Möglichkeit, 
den Ort des Absturzes festzustellen, ohne dass ich alles durchsteppen 
muss?
Ich verwende den Mega168 mit AVR-Studio (aktuelle Version) + 
JTAGICE-mkII im debugWIRE-Modus.

THX und lg
Andy

von Karl H. (kbuchegg)


Lesenswert?

So ein Absturz kann viele Ursachen haben, zb ein aktivierter Interrupt 
für den es keinen Handler gibt.

Aber du kannst ja mal folgendes versuchen.
An 'strategisch günstigen' Stellen, schreibst du jeweils eine andere 
Zahl an eine bestimmte Stelle im EEPROM. Nach dem Absturz liest du das 
EEPROM aus und die Zahl verrät dir, was der µC zuletzt gemacht hat 
(natürlich darf er dann nicht mehr hochfahren bzw. die musst diese 
Mitschreiben abstellen). Auf die Art kannst du mit ein bischen Glück den 
Code eingrenzen.

(Wenn du eine UART hast, kannst du dasselbe ja auch mit Ausgaben auf ein 
Terminal machen. Das Program protokolliert dann an einem Terminal mit, 
was es gerade tut)

Besonderes Augenmerk muss man natürlich darauf legen, dass sich durch 
dieses Logging das Timing des Programs verändert. Das kann ein Problem 
sein. Daher sollte man da auch nicht elendslange Texte ausgeben lassen, 
sondern nur kurze Kennungen. Die können ruhig kryptisch sein, solange 
sie dir als Entwickler nur den Hinweis geben, wo das Programm gerade 
war/ist.

von Peter D. (peda)


Lesenswert?

Andy schrieb:
> Ich habe das Problem, dass mein (ziemlich großes) Programm hin und
> wieder abstürzt und von vorne beginnt (reset). Gibt es eine Möglichkeit,
> den Ort des Absturzes festzustellen, ohne dass ich alles durchsteppen
> muss?
> Ich verwende den Mega168 mit AVR-Studio (aktuelle Version) +
> JTAGICE-mkII im debugWIRE-Modus.

Wo ist das Problem, wenn Du nen Debugger hast?
Setze einfach nen Brechpunkt an 0x0000.
Und dann schau Dir den SP an, wohin der zeigt und das MCUSR, obs 
wirklich ein Reset war.


Peter


P.S.:
Du hast selbstverständlich auch nen BADISR_vect Handler aufgesetzt.

von Simon K. (simon) Benutzerseite


Lesenswert?

Karl Heinz Methode geht auch relativ gut über einen UART, falls 
vorhanden.

von Andy (Gast)


Lesenswert?

Danke für die Antworten. Hab mir schon sowas in der Richtung gedacht!
Noch was: Gibt es eine Möglichkeit, die ISR beim Debuggen auszuschalten. 
Der Timer soll aber trotzdem weiterlaufen und den Code beim Überlauf 
ausführen. Ich will nur nicht, dass bei jedem 2. Step der Debugger in 
die Timer-Routine hüpft.

THX Andy

von Hc Z. (mizch)


Lesenswert?

avarice kennt --ignore-intr.  Keine Ahnung, ob dass passt, denn Du hast 
nicht gesagt, womit Du debuggst.

von Hc Z. (mizch)


Lesenswert?

Oh, hast Du doch.  Dann passt der Tipp mit avarice nicht.

von Ben (Gast)


Lesenswert?

> "Absturzstelle" ermitteln
da wo's brennt und viele verstreute teile rumliegen ;)

ich hab bei meinen projekten immer irgendwo eine LED am controller, die 
man für solche tests gut gebrauchen kann. vielleicht gibts bei dir sowas 
auch? die idee mit dem UART ist aber auch gut, der controller muß es 
aber dann trotz crash noch schaffen diese daten zu senden.

ein reset ist aber eher untypisch für einen crash, meistens hängt der 
controller einfach. oder wird er vom watchdog zurückgesetzt?

und in welchen zeitlichen abständen crasht der controller. läuft das 
proggi erst tagelang durch bis es dann irgendwann mal crasht oder 
passiert das quasi sofort?

von Uwe (Gast)


Lesenswert?

Hi!
>Programm hin und wieder abstürzt und von vorne beginnt (reset)
Ich bevorzuge eigentlich auch die UART Metode.
Um die Debugzeiten kurz zu halten einfach einer Variable an def. Stellen
einen def. Wert übergeben und bei Reset über UART ausgeben.
255 Prüfwerte passen in ein einziges Byte, da kommt man schon recht 
weit.
Die Stackadressen sind auch sehr aufschlussreich.(push/pop lässt 
grüssen).
Einfach mit ausgeben.(natürlich vor einem Init erstmal retten)


Viel Erfolg, Uwe

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Ben schrieb:
> die idee mit dem UART ist aber auch gut, der controller muß es
> aber dann trotz crash noch schaffen diese daten zu senden.

Es geht doch nicht darum, die Daten trotz crash noch zu senden, sondern 
zu sehen, was kurz vor dem crash ausgeführt wurde.

> ein reset ist aber eher untypisch für einen crash, meistens hängt der
> controller einfach. oder wird er vom watchdog zurückgesetzt?

Außer es ist ein nicht initialisierter Int-Vektor, der angesprungen 
wird.
Der Program Counter läuft dann durch eine Reihe NOPs zum Programmanfang 
und alles sieht nach einem Reset aus.

Spontanes hängen gibt es nur, wenn zufälltig eine Endlosschleife 
entstanden ist oder du eine programmiert hast, aus der nichts rausführt.

Oft rennt der Prozessor auch in nicht initialisierten (also mit 
zufälligen Daten gefüllt) Flash-Bereich. Da kommt es dann drauf an, wie 
der Prozessor das interpretiert (zB als Sprung nach 0x0000).

Ich weiß jetzt nicht, ob man an den SP des AVR drankommt. Wenn ja, 
diesen (und den Zellinhalt auf dem dieser zeigt) bei einem Reset (also 
am Programmanfang) auf den UART ausgeben. Wenn es ein echter Reset ist, 
steht der SP auf der größten RAM-Adresse (weiß ich auch nicht ganz 
genau), ansonsten irgendwo anders. Der Zellinhalt ist die Adresse, von 
der aus der "Reset" ausgelöst wird.

von Sebastian (Gast)


Lesenswert?

UART oder LED dran, und schauen wo die LED stehen bleibt...

von Andy (Gast)


Lesenswert?

Danke für eure Antworten - habt mir sehr geholfen. Ich werd das mal mit 
der UART probieren.

Weiß sonst irgendjemand, ob man das Ausführen der ISR während des 
Debuggens abschalten kann (nur das zwingende durchsteppen - Funktion 
soll erhalten bleiben)?

lg

von Frankl (Gast)


Lesenswert?

Auch wenn der Stack überläuft sieht es nach Neustart aus.

von oszi40 (Gast)


Lesenswert?

-Sind HW-Fehler 100% ausgeschlossen? RAM=?

-WENN der SW-Fehler näher bekannt wäre, könntE man evtl. auch versuchen 
ein Programm schreiben "was sich selber hilft".

von Andy (Gast)


Lesenswert?

Hab den Fehler schon gefunden. Ich bin an der Grenze des Speichers 
angelangt und habe anscheinend irgendwas überschrieben. Wenn ich ein 
paar Funktionen und Variablen rausnehme, läuft das Prog einwandfrei.
Wie gesagt, jetzt würd mich noch das Deaktivieren der ISR beim Debuggen 
interessieren.

lg

von Andy (Gast)


Lesenswert?

OK, aber ganz versteh ich mein Problem noch nicht! Wenn ich ein paar 
Variablen weglasse, dann hab ich bei Data 73% des Speichers belegt und 
das Programm funktioniert. Schließe ich jedoch diese Variablen wieder 
mit ein, so hab ich bei Data 80% belegt und das Programm funktioniert 
nicht (Symptome wie oben - reset ca alle 2sek.). Das komische ist aber, 
dass diese Variablen gar nicht benutzt werden. Was ist da los?

lg

von Bernhard R. (barnyhh)


Lesenswert?

Andy schrieb

>> OK, aber ganz versteh ich mein Problem noch nicht! Wenn ich ein paar
>> Variablen weglasse, dann hab ich bei Data 73% des Speichers belegt und
>> das Programm funktioniert. Schließe ich jedoch diese Variablen wieder
>> mit ein, so hab ich bei Data 80% belegt und das Programm funktioniert
>> nicht (Symptome wie oben - reset ca alle 2sek.). Das komische ist aber,
>> dass diese Variablen gar nicht benutzt werden. Was ist da los?
>>
>> lg

Stack-Overflow! Willkommen im Club!

Bernhard

von Andy (Gast)


Lesenswert?

Und was passiert da? Ich hab doch noch 20% frei??

lg

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Du hast keine 20% frei, sondern 80% von Variablen belegt. Der Stack 
braucht je nach Komplexheit des Programms auch noch Platz.

Was dabei passiert, ist einfach. Der Stack überschreibt Deine Variablen 
und fängt irgendwann wieder von oben an. Dann überschreibt sich der 
Stack selber. Funktionsrücksprünge führen an falsche Stellen. Lokale 
Variablen stimmen nicht mehr. Auch überschreiben Deine Variablen 
wiederum den Stack.

von Ben (Gast)


Lesenswert?

das letzte ist das was ich glaube, seine variablen überschreiben den 
stack. der nächste ret oder iret schießt das ding dann ins nirvana.

übrigens ist das mit dem UART daten senden gar nicht so simpel. der µC 
core ist deutlich schneller als der UART und er crasht daher auch 
deutlich schneller. beim crash/reset kann der UART dann zurückgesetzt 
werden obwohl noch nicht alles übertragen war, vor allem wenn man 
mehrere zeichen interrupt-gesteuert übertragen wollte. für eine absolut 
genaue auswertung müßte man den abschluß des sendens abwarten bevor man 
das programm fortsetzt.

bei meinen programmen hab ich auch keine uninitialisierten ints. 
unbenutzte ints setz ich auf eine fehlerausgabe - im einfachsten fall 
halt einen LED-blinker oder so. dann weiß man wenigstens was passiert 
ist.

von Lutz (Gast)


Lesenswert?

>hab ich bei Data 73% des Speichers belegt
>Ich hab doch noch 20% frei??
>Du hast keine 20% frei, sondern 80% von Variablen belegt.
Sagt Data nicht eher was über den Flash aus? Es läuft wohl eher der RAM 
über. Selbst wenn Du nur 3 % Flash belegt hast, kann Dir zur Laufzeit 
der RAM ausgehen (Rekursive Aufrufe, Nested Interrupts, riesige 
Variablen wie ein Array etc.). Der Stack ist ja im RAM.

Aber wie Peter ganz am Anfang schon schrieb:
1.) Du hast JTAG
2.) Nutze MCUSR um die Richtung des Problems zu finden (Watchdog, 
Brownout etc.)
und checke auf nicht abgefangene Interrupts bzw. verhindere sie mit 
einem "Allescatcher" a la BADISR_vect Handler

von Andy (Gast)


Lesenswert?

Hi,
Hat vielleicht noch jemand eine Ahnung, ob sich die ISR beim Debuggen 
deaktivieren lassen??

lg

von krishna (Gast)


Lesenswert?

cli einbauen

von Andy (Gast)


Lesenswert?

Wie soll das genau funktionieren??

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.