Forum: Mikrocontroller und Digitale Elektronik Stackanalyse ATMega


von Heinz K. (hagejot)


Lesenswert?

Hallo zusammen!

Ich versuche gerade, die Ursache für sporadische Abstürze (1/Woche oder 
weniger) eines ATMega168P-Sytems zu finden und wollte mit folgendem 
Watchdog-Programm eine Sicherung des Stackinhalts ins EEPROM 
durchführen:
1
uint16_t WD_events EEMEM;
2
uint16_t stack_loc EEMEM;
3
uint16_t WD_stack[100] EEMEM;
4
5
6
main()
7
{
8
   Init_Watchdog();
9
   sei();
10
   ....
11
]
12
13
14
ISR(WDT_vect)
15
{
16
    uint16_t stckptr;
17
18
    stckptr = SP;
19
    eeprom_write_block (&stckptr, WD_stack, sizeof(WD_stack));
20
21
     
22
    eeprom_write_word (&WD_events, (eeprom_read_word (&WD_events) + 1))
23
                                            //erhöhe Ereigniszähler
24
    eeprom_write_word (&stack_loc, stckptr);
25
}

Leider habe ich in der .lss-Datei gesehen, dass der Compiler 
(Atmel-Studio 6.2) beim Eintritt in die Interrupt-Routine eine 
Push-Orgie durchführt, bevor der Stackpointer kopiert werden kann.

Dadurch wird eine Stackanalyse zur Qual.

Deshalb meine Frage an euch:

Gibt es ein (möglichst einfaches) Verfahren, den Wert des Stackpointers 
beim Eintritt in die Watchdog-ISR zur weiteren Auswertung zu sichern?

Vielen Dank!


Mit freundlichen Grüssen

Heinz

von Karl H. (kbuchegg)


Lesenswert?

Heinz K. schrieb:

> Leider habe ich in der .lss-Datei gesehen, dass der Compiler
> (Atmel-Studio 6.2) beim Eintritt in die Interrupt-Routine eine
> Push-Orgie durchführt, bevor der Stackpointer kopiert werden kann.

Die aber (in einer gegebenen ISR) immer gleiche viele Push umfasst.
Kennst du die Anzahl erst mal (LSS File studieren), dann ist es 
eigentlich trivial, den ausgelesenen Wert vom SP entsprechend im 
Programm zu korrigieren bzw hier
1
    eeprom_write_block (&stckptr, WD_stack, sizeof(WD_stack));
die SRAM Adresse ab der ins EEPROM kopiert wird, entsprechend zu 
korrigieren.

> Dadurch wird eine Stackanalyse zur Qual.

... wodurch auch das kein Problem mehr ist.

von Heinz K. (hagejot)


Lesenswert?

Nicht mal Zeit zum Kaffeeholen hat man... ;-)

Vielen Dank!

Heinz

von Jay (Gast)


Lesenswert?

Den Grund warum der Compiler mit dem push/pop anfängt kennst du auch? 
Sobald er die Verwendung der Register nicht mehr verfolgen kann, z.B. 
wegen eines einen Funktionsaufrufs, schiebt er alle Register auf den 
Stack, denn sie könnten durch den Funktionsaufruf geändert werden.

von c-hater (Gast)


Lesenswert?

Jay schrieb:

> Den Grund warum der Compiler mit dem push/pop anfängt kennst du auch?
> Sobald er die Verwendung der Register nicht mehr verfolgen kann, z.B.
> wegen eines einen Funktionsaufrufs

Warum sollte ein einfacher Funktionsaufruf den Compiler zwingend daran 
hindern, die Registerverwendung verfolgen zu können? Dafür gibt es 
keinen harten technischen Grund.

Das wäre höchstens dann der Fall, wenn die Funktion in einem anderen 
Codemodul liegt oder es sich um einen indirekten Funktionsaufruf 
handelt, dann (und nur dann) kann sich der Compiler natürlich nicht mehr 
sicher sein.

Solange es aber um eine direkt aufgerufene Funktion im gleichen 
Codemodul handelt und diese ihrerseits nur Funktionen im eigenen 
Codemodul direkt aufruft usw., könnte der Compiler das sehr wohl 
verfolgen. Wenn er will, bzw. seine Macher ihm die Fähigkeit dazu 
eingehaucht haben.

Es gibt aber natürlich Grenzen, weil es im Prinzip ja ein unendliches 
Problem ist, wie man sehr schnell merkt, wenn es eine Rekursion im 
Callstack gibt, z.B. wegen einer absichtlich rekursiv designten 
Funktion.

Man braucht in diesem Zusammenhang aber garnicht versuchen, Rekursionen 
zu detektieren (was exponentiell aufwendig wäre), man bricht statt 
dessen die vorausschauende Verfolgung einfach stumpf dann ab, wenn die 
Register ausgehen und kehrt zähneknirschend zur normalen Methode der 
Codegenerierung zurück. Führt hingegen die Vorschau ohne Unterlauf des 
Registerfiles auf den initialen Aufruflevel zurück, dann ist sicher, 
dass der gesamte betrachtete Code massiv optimiert werden kann, dann hat 
sich der Aufwand für die Vorschau gelohnt.

Denn der Mehraufwand einer solchen Vorschau muß nur einmal, und zwar zur 
Compilezeit, erbracht werden, der Gewinn hingegen klingelt zur Laufzeit 
in der Kasse, bezüglich der Rechenleistung bei jedem Aufruf einer 
derartig optimierten ISR, bezüglich der Latenz sogar bei jedem Aufruf 
jeder ISR im System, ganz egal, ob sie auf diese Weise optimiert 
werden konnte oder nicht.

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.