Forum: Mikrocontroller und Digitale Elektronik AVR-GCC Bug? if (uint16_t-Typ == 0).


von Michael S. (michael-dj2tk)


Lesenswert?

Hallo,

ich habe ein Problem mit dem AVR-gcc und seiner Optimierung. Angenommen 
sei folgender Ausschnitt aus einem C-Code:
1
    volatile static uint16_t readBytes;
2
3
    if ( (readBytes) == 0 )
4
    {
5
        PORTD = 0x01; // Beispiel
6
    }

Ohne irgendeine Optmierung (-Ox weggelassen) erzeugt gcc diesen Code:
1
lds  r24, 0x0060
2
lds  r25, 0x0061
3
sbiw  r24, 0x00  
4
breq  .+2        
5
rjmp  .+244
der für mich auch ok aussieht. Mit Optimierung (-O, -O2, -Os) erzeugt er 
das hier:
1
lds  r24, 0x0060
2
lds  r25, 0x0061
3
or  r24, r25
4
brne  .+4
Ich denke dass dieser Code falsch ist - in den Registern r24 und r25 
befinden sich das High- und Low-Byte der uint16 Variable. Eine 
Oder-Operation ergibt für mich als Test auf Null keinen Sinn (im 
Gegensatz zum unoptimierten Fall s.o.).

Diese Änderung ergibt sich erst, wenn ein O-Parameter angegeben wird. 
Wenn ich versuche, die Optimierungen mit -fxxx Parametern nachzubauen, 
bekomme ich das Problem nicht, allerdings ändert sich die Code-Größe 
auch nicht.

Das ganze ist natürlich in ein größeres Projekt eingebettet, so dass ich 
Optimierung haben will, schon aus Geschwindigkeitsgründen. Allerdings 
habe ich noch einen (diffusen) Fehler in der Software, die von der 
Optimierungsstufe abhängig ist, und diesen suche ich nun.

Die Frage ist nun, habe ich bei obigem Beispiel irgendwo einen 
Denkfehler? Warum "funktioniert" die Optimierung nur, wenn ich einen 
O-Parameter angebe, und nicht mit den f-Parametern? Auch über Literatur 
zu dem Thema und Tipps aus der Praxis wäre ich dankbar.

Vielen Dank schon mal für die Hilfe,
Michael

PS: Eingesetzte Version: avr-gcc 4.2.2 aus der Ubuntu 8.04 Standard 
Installation, avr-libc 1.4.7-1 (auch aus Ubuntu). Binutils 2.18-3. Eine 
eigene Toolchain zu erstellen wollte ich eigentlich vermeiden, aber wäre 
wohl einer der nächsten Schritte falls ich keine bessere Idee habe...

von Andreas K. (a-k)


Lesenswert?

Michael S. wrote:

> Eine Oder-Operation ergibt für mich als Test auf Null keinen Sinn

Für mich schon. Der Code ist völlig korrekt. Das Ergebnis dieser 
Operation ist genau und nur dann 0 wenn beide Register 0 sind, und das Z 
Flag gibt diesen Sachverhalt wieder.

von Benedikt K. (benedikt)


Lesenswert?

Für mich gibt das schon einen Sinn:
Wenn die 16bit Variable 0 ist, sind weder in r24 noch in r25 Bits 
gesetzt. Demzufolge ist das Ergebnis der Oder Operation auch 0 und das 
brne wird ausgeführt.

von Michael S. (michael-dj2tk)


Lesenswert?

Oh Mist, ich wusste ich stand auf dem Schlauch - gedanklich eine 
Und-Operation durchgeführt. Peinlich...

Danke für die schnelle Antwort! Dann werd ich mal weitersuchen...

von Andreas K. (a-k)


Lesenswert?

Worauf in diesem Zusammenhang allerdings zu achten ist: Wenn readBytes 
den Wert 0x0100 hat und im Interrupt auf 0x00FF runtergezählt wird, dann 
kann es vorkommen, dass der Test das untere Byte vor und das obere Byte 
nach dem Interrupt läd und damit fälschlicherweise auf 0 erkennt.

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.