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
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.
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.
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
> "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?
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
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.
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
-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".
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
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
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
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.
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.
>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