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.
1
case140:
2
{
3
uint16_tsv;// Stack vorher
4
uint16_tsn;// Stack nachher
5
uint16_tuiCounter=0;
6
7
sv=SP;// Stackpointer vorher merken
8
9
// hier die EIGENTLICHE Funktion, ist aber auskommentiert
So, und wenn der Kram Durchgelaufen ist erhalte ich auf meinem LCD die
Meldung:
1
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
scheidet also aus
sprintf_P wird aber sonst überall STÄNDIG verwendet und läuft prima.
nur in diesem
1
case140:
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
~~~~
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.
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:
1
case140:
2
{
3
uint16_tsv;// Stack vorher
4
uint16_tsn;// Stack nachher
5
uint16_tuiCounter=0;
6
7
sv=SP;// Stackpointer vorher merken
8
9
// hier die EIGENTLICHE Funktion, wieder reinnehmen
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
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:
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.
@ 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.
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!