Hallo, ich starte noch mit AVRs, und zuerst entroste ich meine alten C-Kenntnisse. Als Übung portiere ich gerade einen kleinen Basic-Interpreter von vorher Java auf jetzt C (für den avr-gcc). Ich verwende AVRStudio4 und WinAVR (aktuelle Versionen), einen ATMega168 und den AVR-Dragon zum debuggen. Dabei ist mir etwas komisches aufgefallen: Eine meiner globalen Variablen (vom typ char [32], außerhalb aller Funktionen deklariert) wurde während des Programmlaufs teilweise überschrieben, und zwar sowohl im AVRDebugger als auch per DebugWire im Prozessor. Das passierte immer während eines bestimmten verschachtelten Funktionsaufrufs. Der Compiler war auf 'schwache Optimiering' eingestellt. Wenn ich die Optimierung ganz ausschaltete, dann wurde nichts überschrieben, nur bei eingeschalteter Optimierung passierte das. Erst nachdem ich die globale Variable zusätzlich als 'static' deklariert hatte, wurde sie gar nicht mehr überschrieben, also auch bei eingeschalteter Optimierung nicht. Auch nicht überschreiben wurde sie, wenn ich den ATMega128 wählte, also mit und ohne Optimierung (aber den habe ich halt nicht real sondern nur als Debugger-Simulation). Ich dachte ich schreibe das mal hier, eventuell hat noch jemand ein ähnliches Problem, und ein einfaches 'static' könnte helfen. Oder ist das eventuell schon allgemein bekannt, und ich sollte besser meine Klappe halten ;) soweit, Grüße Ralf
Nein ist nicht Pflicht. Das wäre auch ein ziemlich grosser Klops! Hast du die Variable in zwei oder mehr Quellcodedateien deklariert (angelegt)? Sie darf nur in einer Quellcodedatei deklariert werden; in den anderen Quellcodedateien wird sie nur als extern definiert. Achte mal auf Linkerwarnungen bzw. schalte Linkerwarnungen ein.
Ahja - wie voll ist dein SRAM auf dem AVR? Rennt vielleicht schon der Stack im Variablenbereich Amok? Ein "bestimmter verschachtelter Funktionsaufruf" hört sich danach an...
> Wenn ich die Optimierung ganz ausschaltete, dann wurde nichts > überschrieben, nur bei eingeschalteter Optimierung passierte das. Du hast irgendeinen anderen Fehler im Program. Was du siehst, sind die Symptome und nicht die Ursache.
@Stefan(1): der ganze Code ist nur in einer einzigen Datei. @Stefan(2): jo, das SRAM ist schon mächtig voll, das könnte es sein. Mich wundert dann aber, dass ein 'static' das Problem behebt. @Karl heinz Buchegger: kann gut sein. Ein anderes Problem macht die Fehlersuche aber etwas kompliziert: Mein Debugger im AVRStudio liefert für Funktionsparameter bei eingeschalteter Optimierung manchmal falsche Werte. Hier ein Codeschnipsel zu dem FalscheWerteProblem, bei dem das bei mir im Debugger so ist wie gesagt, siehe Kommentar hinter 'testFunc' (hat aber nix mit dem Topic des Threads zu tun): <c> #include <stdint.h> #include <stdlib.h> typedef size_t length_t; typedef struct { char* sbbuf; length_t sblen; length_t len; } SB; void SB_init (SB* sb, char* sbbuf, length_t len) { sb->sbbuf = sbbuf; sb->sblen = len; sb->len = 0; } char* testFunc (char* buf, length_t len) //--- Wenn Optimierung an ist (-s1), dann --- //--- zeigt der AVRStudio4-Debugger hier --- //--- für len einen falschen Wert an --- { SB sb; SB_init (&sb, buf, len); return itoa (sb.sblen, buf, 10); } static char* result = 0; int main (void) { char buf [0x20]; result = testFunc ((char*) &buf, 0x20); while (1==1); return 0; } </c> Grüße Ralf
1 | ...
|
2 | {
|
3 | SB sb; |
4 | SB_init (&sb, buf, len); |
5 | return itoa (sb.sblen, buf, 10); |
6 | }
|
Klassiker. Geht schief, weil sb nach dem return illegal wird.
Da ist der AVR-GCC fehlerhaft: Wenn die gleiche globale Variable in verschiedenen Objekten definiert ist, nimmt er stillschweigend an, daß sie auch dieselbe sein soll und überlagert sie alle. Ich bin da auch schon mal drauf reingefallen. Andere Compiler meckern dagegen und wollen es richtig gemacht haben: Also die Variable gefälligst nur einmal definieren und dann per *.h-File als extern deklarieren. Eine statische Variable existiert nur in einem Objekt und kann daher nicht überlagert werden. Peter
Nee doch nicht. Habe Argumente verwexelt ;-) Aber hier knallt's
1 | int main (void) |
2 | {
|
3 | char buf [0x20]; |
4 | result = testFunc ((char*) &buf, 0x20); |
5 | while (1==1); |
6 | return 0; |
7 | }
|
richtig:
1 | int main (void) |
2 | {
|
3 | char buf [0x20]; |
4 | result = testFunc ((char*) buf, 0x20); // bzw. &buf[0] |
5 | while (1==1); |
6 | return 0; |
7 | }
|
Tip: Sei geizig mit den Casts. Wenn der Compiler meckert hat es oft einen Grund. In diesem Falle hätte der Funktionsaufruf ohne (cahr*) Cast das Problem aufgedeckt.
> Aber hier knallt's > >
1 | > result = testFunc ((char*) &buf, 0x20); |
2 | >
|
> > richtig: > >
1 | > result = testFunc ((char*) buf, 0x20); // bzw. &buf[0] |
2 | >
|
uff, ... da hast Du wahrscheinlich gerade auch mein erstes Problem gelöst. Denn die Konstruktion mit der falschen Adresse (oben) habe ich gleich einigemale im Programm. Grüße Ralf
> Fehlersuche aber etwas kompliziert: Mein Debugger im AVRStudio liefert > für Funktionsparameter bei eingeschalteter Optimierung manchmal falsche > Werte. Ich sehe was du meinst. > //--- Wenn Optimierung an ist (-s1), dann --- > //--- zeigt der AVRStudio4-Debugger hier --- > //--- für len einen falschen Wert an --- Es ist nicht ungewöhnlich, dass Debugger ausser Tritt kommen, wenn Optimierungen eingeschaltet sind. Der Debugger geht von einer Annahme aus: Jedes Statement im Source Code macht genau das was drauf steht. Und dann kommt der Optimizer und dreht im Programm alles mögliche um. Konkret erwartet der Debugger das 2. Argument zu der Funktion in den Registern R24:R25. Tatsächlich hat der Optimizer aber dafür gesorgt, dass der 2te Parameter in den Registern R22:R23 übergeben wird. Und damit zeigt natürlich der Debugger was falsches an. Wenn du aber das Pgm durchsteppst und am Ende der Funktion mal die strcut SB sb untersuchst, stellst du fest dass ihre Werte stimmen. Moral -> Debugger und Optimizer vertragen sich nicht gut.
> Aber hier knallt's
Macht für den gcc keinen Unterschied.
Der gcc ist schlau genug zu verstehen, was mit
der Adresse eines Arrays gemeint ist.
Die Datentypen stimmen nicht, daher die Warning.
Das Endergebnis sieht aber völlig gleich aus.
@all danke für die prompte Hilfe. wenn ich mit meinem Basic-Interpreter-Dings wieder mal nicht weiterkomme, werde ich natürlich wieder hier bei Euch fragen, ... das habt Ihr jetzt davon ;)) Grüße Ralf
Peter Dannegger wrote:
> Da ist der AVR-GCC fehlerhaft:
Sei vorsichtig mit deinen Worten: dieses Verhalten ist ausdrücklich
vom Standard zugelassen. Wenn du deine Klappe nicht hälst, such ich
mir die Stelle raus und werf damit nach dir. :-)
Kann man übrigens mit -fno-common ausschalten, wenn man das nicht
haben will.
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.