Hallo, ich habe da ein Problem mit dem GCC Compiler im Zusammenhang mit Volatile-deklarierten Variablen und Code-Optimierung. Interesant ist die Zeile: 'while(cinw_ptr == cinr_ptr);' in der Funktion 'ReadComDaten'. Während dieser While-Schleife wird auf das Eintreffen eines neuen Bytes vom COM-Port gewartet. Dieses wird per Interruptroutine empfangen und in einen Empfangspuffer eingetragen. Dabei wird der Zeiger 'cinr_ptr' um 1 erhöht, woran man dann erkennen kann das ein neues Byte angekommen ist. Das Problem ist, das die Variablen 'cinw_ptr' und 'cinr_ptr' zwar global als Volatile deklariert sind, der Compiler es aber so übersetzt das die Variablen in Register geladen werden und dann nur noch mit diesen gearbeitet wird und nicht mehr mit den eigentlichen Variablen. (siehe unten) Ich dachte eigentlich das mit 'Volatile'-Variablen genau das verhindert werden soll. Vielleicht hat jemand eine Idee, was da schief läuft. MfG Bernd C-Code: volatile uchar *cinw_ptr, *cinr_ptr, *coutw_ptr, *coutr_ptr; uchar ReadComData(void) { uchar data; while(cinw_ptr == cinr_ptr); // warten auf ein neues Byte ... data = *cinr_ptr; cinr_ptr++; .... weiterer Code ..... } Daraus macht der Compiler, mit Optimierung -Os: uchar ReadComData(void) // (warte und) lese Zeichen vom Com-Port { 2ba: 80 91 62 00 lds r24, 0x0062 2be: 90 91 63 00 lds r25, 0x0063 2c2: e0 91 60 00 lds r30, 0x0060 2c6: f0 91 61 00 lds r31, 0x0061 uchar data; while(cinw_ptr == cinr_ptr); // warte auf Zeichen 2ca: 8e 17 cp r24, r30 2cc: 9f 07 cpc r25, r31 2ce: e9 f3 breq .-6 ; 0x2ca weiterer Code ....
Hi ich bin mir absolut unsicher aber ich würde mal behaupten das sich das volatile nicht auf den Pointer selbst sondern auf die Adresse bezieht wohin der Pointer zeigt. Matthias
> while(cinw_ptr == cinr_ptr);
Warum denkst Du sollte sich der Wert des Pointers ändern, bloss weil
das Byte auf das er zeigt sich ändert?
Wie das heutige c't ja schon sagt, wir leben in der Sternchen-Ära,
also bitte ein paar hübsche Sternchen in dieses Statement einstreuen.
Matthias hat recht. Korrekt: char *volatile cinw_ptr, *volatile cinr_ptr, *volatile coutw_ptr, *volatile coutr_ptr oder besser, weil lesbarer: typedef char *char_ptr; volatile char_ptr cinw_ptr, cinr_ptr, coutw_ptr, coutr_ptr;
Ja, das ist wie bei const. "const int * p" deklariert einen Zeiger, der auf einen konstanten Wert zeigt. Der Zeiger selbst darf verändert werden, aber nicht der Wert auf den er zeigt. "int * const p" dagegen deklariert einen konstanten Zeiger, der auf einen nicht-konstanten Wert zeigt. volatile verhält sich syntaktisch in den meisten Fällen wie const (ist beides ein "modifier"), daher brauchst du wohl sowas: typedef uchar * volatile v_ptr; v_ptr cinw_ptr, cinr_ptr, coutw_ptr, coutr_ptr; Sollte ich mich irren, bitte ich um Korrektur. :-)
Meine Herren, Hut ab ! der Erfolg gibt euch Recht. Jetzt wo es einem erklärt wird, klingt es irgendwie logisch ... Danke noch mal für die schnelle Hilfe Bernd
> volatile verhält sich syntaktisch in den meisten Fällen wie const > (ist beides ein "modifier"), ... Sachlich richtig (und das Ergebnis zeigt es ja auch), kleine formale Korrektur: beides sind type *qualifier*s. (ISO C99 kennt noch einen dritten, der nur in Funktionsdeklarationen und nur für Zeiger auftauchen kann, "restricted".)
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.