Forum: Mikrocontroller und Digitale Elektronik Debuggen: SREG Register überwachen?


von John (Gast)


Lesenswert?

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

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

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.

von John (Gast)


Lesenswert?

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
}

von Oliver (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von John (Gast)


Lesenswert?

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.

von holger (Gast)


Lesenswert?

>  OldSreg = SREG;
>  SREG=OldSreg;

Da könnte dir durch einen Stacküberlauf einfach OldSreg
zerschossen werden.

von Peter D. (peda)


Lesenswert?

Schau Dir mal die atomic.h an.

Die garantiert, daß bei jedem Austritt der gewünschte Interruptstatus 
hergestellt ist.


Peter

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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.

von Thomas (kosmos)


Lesenswert?

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.

von John (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.