mikrocontroller.net

Forum: Compiler & IDEs Stackproblem ATMEGA128 und GCC


Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, liebe Gemeinde,

ich habe hier ein Problem in einem größeren SW-Projekt, das mich in den 
Wahnsinn treibt. Sonntagabend arbeiten...
- System ist auf einem ATMEGA128 mit 64k ext. RAM aufgebaut
- AVR-GCC und AVRStudio 4.14

Mein Debug/Testprogramm besteht aus einer Menge kleiner Funktionen, die
durch Bytes aufgerufen werden, die via Bluetooth und UART1 vom PC 
kommen, nach dem Motto

switch (token)
{
case TUDIES:
    ...dies tun
break;
case TUDAS:
    ...das tun
break;
...etcetc
}

Soweit, so gut. 70kB Code laufen einwandfrei. Plötzlich aber........
schmiert mir der AVR bei einer neu eingebauten Funktion ab.
Nach langer Suche ohne erkennbaren Fehler habe ich ein Stackproblem 
lokalisiert. Habe Stück für Stück alles auskommentiert bis...

Um Euch nicht zu verwirren, habe ich allen auskommentierten Code 
weggelassen, und hier nur die 'abgestrippte' Routine mit dem Stackcheck 
gepostet.
      case 140:
        {
        uint16_t sv; // Stack vorher
        uint16_t sn; // Stack nachher
        uint16_t uiCounter=0;  
      
        sv=SP;  // Stackpointer vorher merken        
        
        // hier die EIGENTLICHE Funktion, ist aber auskommentiert
        
        sprintf_P(cString,PSTR("\n%d Zeichen gelesen"),uiCounter);
        LCD240_PutString (cString);
      
        sn=SP; // Stackpointer nachher merken
        
        sprintf_P (cString,PSTR("\nStackDiff: %d Byte"),sn-sv);
        LCD240_PutString (cString);
        }
      break;

So, und wenn der Kram Durchgelaufen ist erhalte ich auf meinem LCD die 
Meldung:
StackDiff: -6Byte

Deshalb schmiert die Kiste ab. Da DARF keine Differenz sein.
Was verbiegt mir hier den Stackpointer?
Irgendwelche Stack-Checker hier, die sowas mal gehabt haben?

Es liegt scheinbar an der sprintf_P Funktion, denn wenn ich die 
rausnehme und durch
        //sprintf_P(cString,PSTR("\n%d Zeichen gelesen"),uiCounter);
        strcpy(cString,"Test");
        LCD240_PutString (cString);
ersetze, kriege ich artig:
StackDiff: 0 Byte
LCD240_PutString
 scheidet also aus
sprintf_P wird aber sonst überall STÄNDIG verwendet und läuft prima.
nur in diesem
case 140:
 läufts nicht.
Das ist doch nicht normal, oder?
Bin ich blind oder brauche ich einen Exorzist?

Irgendwelche Anregungen für nen gehetzten Entwickler, was das sein 
könnte?

Gruß

Andi
~~~~

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Paulin wrote:

> Deshalb schmiert die Kiste ab. Da DARF keine Differenz sein.

Das kannst du mit dieser Bestimmtheit erst behaupten, wenn du dir
auch den generierten Assemblercode angesehen hast.  Es ist
durchaus nicht unüblich, das relativ aufwändige Aufräumen des
Stacks (man müsste ja 6 x POP aufrufen oder Verrenkungen mit dem
Stackpointer machen) bis zum Austritt aus der Funktion zu
verzögen.

Während die überwiegende Anzahl der Funktionsaufrufe beim AVR-GCC
die Parameter in Registern übergibt, geht das bei der printf-Familie
für die variable Parameterliste nicht, diese Parameter werden immer
auf dem Stack übergeben.  Damit ist diese Funktion natürlich ein
Kandidat, Stackprobleme sichtbar zu machen, die man sonst u. U. nicht
sieht.

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, thanks. Ist aber komischerweise nur in diesem 'case 140:' so.

Ich schmeiß mal ALLE Optimierungen raus, dann müsste es... 
vielleicht.... tbc....

Autor: Michael D. (andromeda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Em...

Was mir auffällt ist, dass Du den Funktionsaufruf durch den Aufruf von 
sprintf usw. ersetzt . Das halte ich, in dem Zusammenhang für nicht 
zielführend. Ich verstehe Dich so, das im normalen Code diese printfs 
nicht auftauchen. Das der Überlauf durch die hier auskommentierte 
Funktion erzeugt wird. Richtig?

Wie schon Jörg Wunsch schrieb sind unbalanzierte Stacks durchaus nicht 
wirklich ungewöhnlich. Auch eine Mögliche Nicht-Optimierung sollte daran 
im Prinzip nichts ändern. (Was nicht ausschliesst, das es in diesem Fall 
eine Veränderung bewirkt).

Die Frage wäre doch vielmehr, ob der Stack unmittelbar nach dem 
Funktionsaufruf unbalanziert ist. Das aber könnte man doch eher mit:
      case 140:
        {
        uint16_t sv; // Stack vorher
        uint16_t sn; // Stack nachher
        uint16_t uiCounter=0;  
      
        sv=SP;  // Stackpointer vorher merken        
        
        // hier die EIGENTLICHE Funktion, wieder reinnehmen
        sn=SP; // Stackpointer nachher merken
     
        sprintf_P(cString,PSTR("\n%d Zeichen gelesen"),uiCounter);
        LCD240_PutString (cString);

        sprintf_P (cString,PSTR("\nStackDiff: %d Byte"),sn-sv);
        LCD240_PutString (cString);
        }
      break;

herausfinden. Meinst Du nicht auch?

Das setzt aber voraus, das die Funktion keine variable Parameterliste 
hat.

Vielleicht hast Du das ja schon berücksichtigt, aber möglicherweise 
hilft Dir das doch weiter.

Gruss

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also... ich hab die Optimierung rausgenommen, daraufhin
bekomme ich geliefert:
"StackDiff: 0 Byte"

Schön, aaaaaaaaaber, das wars nicht. Kiste schmiert immer noch ab. Jetzt 
wirds echt schwer.......
@ Michael D. (andromeda) :
Nein, ich habe die

"// hier die EIGENTLICHE Funktion, ist aber auskommentiert"

in meinem Problemkind WIRKLICH auskommentiert. Es geht echt nur um den 
geposteten Code. Das ist ja das Bescheuerte an der Sache....

@A. K. (prx):
Glaub nicht:
Data:       2204 bytes (53.8% Full)
(.data + .bss + .noinit)
Hab noch fast 2k frei....

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Paulin wrote:

> Also... ich hab die Optimierung rausgenommen, daraufhin
> bekomme ich geliefert:
> "StackDiff: 0 Byte"

Logisch, dann wird diese Optimierung ja auch nicht gemacht.

> Schön, aaaaaaaaaber, das wars nicht. Kiste schmiert immer noch ab.

Was zu befürchten war. :-/

Du benutzt nicht aus Versehen auch noch sprintf irgendwo in einer
ISR?  Kann sein, dass diese Funktionen irgendwo Fallen bezüglich
ihrer Reentranz haben könnten.

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Jörg: Nein, aber es passiert was anderes: Während diese Minifunktion 
läuft, bekommt mein System vom PC noch 100 Byte Testdaten via Bluetooth 
reingeschoben.
Das istn Mordsprotokoll und ständig klimpern die UART-Interrupts. 10 
Byte Overhead für ein Byte Nutzlast. Und DA hakts. Glaub ich. Wenn ich 
nämlich den PC NUR das Funktionstoken senden lasse, ohne die 100 
Testbytes (im Hintergrund) bleibt die Kiste STABIL!.

Schätze, ich war nicht schlecht (stackcheck), aber auf der falschen 
Spur. Es ist nicht der Stack, es ist irgendwo beim "ISR(USART1_RX_vect) 
" und seinen Ausläufern.......

Ich suche morgen weiter, mir fallen jetzt die Augen raus. Vielleicht 
muss ich einige Variable 'volatile' machen oder irgendsowas........ habe 
fertig.
Mittwoch ist Messe.... und nix geht mehr. 's war immer so....

Melde mich morgen wieder.
Jörg, Pirx, Andromeda, .....danke Euch mal.

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, wenn der Stack vor und nach einem Funktionsaufruf unausgeglichen 
ist, ist das schon ein Alarmsignal. Konnte ich nicht wissen, dass der 
Optimierer einem auch noch den Arsch wegoptimiert, wenn man nicht gerade 
draufsitzt *ggg

Aber es war wirklich kein Stackproblem, ganz anders.... das 
Handshakesignal für das Bluetooth-Modul hat sich verklemmt - Daraufhin 
war die Kiste SCHEINBAR tot.

Läuft soweit - Danke Euch mal recht herzlich!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.