Hallo, folgendes Setup: AVR Studio 4.18.700 AVR Dragon ATmega128 Folgendes Problem: Nach zufälliger Zeit (sofort bis nach ein paar Minuten) werden keine Interrupts mehr ausgeführt. Das Interrupt Enable Flag im SREG Register bleibt ungesetzt. Der Controller läuft aber noch (LED an Pin blinkt weiterhin). Der Timer läuft auch noch (Wert ist bei jedem Halt anders). Das heraus zu finden hat schon einige Zeit gedauert, jetzt komme ich aber nicht weiter. Ich finde einfach nicht heraus, wo mir das Flag zuletzt gelöscht wird. Kann ich vielleicht irgendwie beim Debuggen direkt auf das SREG Register triggern? Evtl. über Debug->New Breakpoint? Andere Ideen? Über Hilfe würde ich mich freuen. Danke. Schöne Grüße John
Das Flag kannst nur Du löschen oder ein gerade laufender Interrupt. Möglicherweise wird ein Interrupt nicht mehr verlassen bzw. startet sofort neu, so dass andere Interrupte nicht mehr zum Zug kommen.
Ich habe versucht im Code nachzuvollziehen, wann da was schief laufen könnte. Aber ich hatte die Hoffnung der Debugger könnte mir dabei helfen. Dadurch, dass die LED weiter blinkt, glaube ich nicht, dass er irgendwo endlos fest hängt. Setze ich das Flag wieder, laufen die Interrupts auch wieder für unbestimmte Zeit, bis das Flag wieder hängen bleibt. Mich wundert diese undefinierte Zeitspanne. Was ich im Verdacht habe, sind meine Funktionen zum Deaktivieren der Interrupts für bestimmte Aktionen, aber bisher hatte ich eigentlich keine Probleme damit. useStop und OldSreg sind volatile!
1 | //stop interrupts, if not already stopped
|
2 | void stopInt() { |
3 | if (useStop) { |
4 | useStop=0; |
5 | OldSreg = SREG; |
6 | cli(); |
7 | }
|
8 | }
|
9 | |
10 | //---------------------------------------------------------
|
11 | //restores old interrupt configuration
|
12 | void enabInt() { |
13 | SREG=OldSreg; |
14 | useStop=1; |
15 | }
|
Wenn es dir in einer ISR den Stack zerschiesst (warum auch immer), wird am Ende ein falscher SREG-Wert gepoppt. Viel Spaß beim Suchen. Oliver
Oliver schrieb: > Wenn es dir in einer ISR den Stack zerschiesst (warum auch immer), wird > am Ende ein falscher SREG-Wert gepoppt. Danach wird aber das I-Bit durch den RETI wieder gesetzt. ;-) Nein, direkt im Debugger überwachen kann man das nicht. Dummerweise kann dir auch ein wild gewordener Zeigerzugriff das SREG zerschießen, da es ja ein IO-Register ist wie alle anderen. Schreiben der Adresse 0x5F bügelt dann das SREG ... den Fall könntest du vermutlich mit einem data breakpoint im JTAG ICE noch erwischen, allerdings auch nur den: wenn das SREG mittels separater Befehle oder via OUT modi- fiziert wird, dann schlägt der data breakpoint jedoch nicht zu.
Es hat vermutlich auch etwas mit einer Kompileränderung zu tun. Das Problem besteht seit einem Umstieg von WinAVR 2008 06 10 auf 2010 01 10.
> OldSreg = SREG; > SREG=OldSreg; Da könnte dir durch einen Stacküberlauf einfach OldSreg zerschossen werden.
Schau Dir mal die atomic.h an. Die garantiert, daß bei jedem Austritt der gewünschte Interruptstatus hergestellt ist. Peter
John schrieb: > Was ich im Verdacht habe, sind meine Funktionen zum Deaktivieren der > Interrupts für bestimmte Aktionen Eventuell übersehe ich ja was, aber du machst dir da meiner Meinung nach viel zu viel (fehlerträchtigen) Aufwand. Was spricht dagegen einfach
1 | cli(); |
2 | sei(); |
zu benutzen? Die Interrupts stört es nicht "mehrfach" deaktiviert zu werden und du sparst dir das "sichern" von SREG, wo du ggf. auch noch ein paar Flags mitnimmst und dir später wieder überschreibst was möglicherweise dann andere Probleme aufwirft.
du könntest zu debug-Zwecken Ausgaben vor und nach die Interruptroutinen setzen um zu beobachten nach welchem Interrupt das Problem auftritt. z.B. An den Anfang der Interrupt-Routine1 läßt du einen LED 1x kurz blinken am Ende der Routine 1x lang so weist du dann wo das Programm aussteigt und kannst es im Simulator nochmals durchspielen. Eine andere Möglichkeit wäre in der Hauptschleife den Stackpointer zu vergleichen. Angenommen der Stack ist 1024 Byte groß, programmierst du einen Vergleich wenn Stack>1000 Programm stoppen, also kurz vor dem Überlauf. Ich denke aber ganz einfach das deine Interruptroutinen nicht wieder beendet werden sondern das du einfach weiter verzweigst und irgendwann läuft der Stack über und dein Programm macht dort weiter wo es gar nicht gewollt ist.
Danke für die Vorschläge. Bisher war der Stackpointer beim Anhalten mit dem Debugger immer sehr groß (0x10F5), was ja auf einen sehr kleinen Stack schließen lässt. Eigentlich kommt er mir zu klein vor. Allerdings kann sich das ja dynamisch kurzzeitig auch ändern. Ich habe noch herausgefunden, dass es ohne meine Displayroutinen stabil zu laufen scheint. Aber den weiteren Zusammenhang konnte ich noch nicht erkennen. Gruß John
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.