While-Schleife weg optimiert

8

Ich habe den folgenden Code in meinem Mikrocontroller-Programm:

// Wait for ADC conversion to complete
while ( ( ADCSRA && _BS( ADSC ) ) == _BS( ADSC ) ) {}

Wobei ADCSRA ein Register ist, das seinen Wert ändert, sobald eine analoge Konvertierung abgeschlossen ist, und wo ich warten möchte, bis ein bisschen klar ist. Dieses Bit zeigt an, dass die Konvertierung abgeschlossen ist.

Wenn Sie sich den resultierenden Assemblycode ansehen, wird die gesamte Schleife durch eine einzelne Anweisung ersetzt:

in      r24, 0x06       ; ADCSRA

Das Register wird gelesen, aber sein Wert wird nicht einmal getestet!?

Wie muss ich meinen C ++ - Code ändern, um den Compiler anzuweisen, das Register weiter zu überprüfen, ohne das Programm unnötig zu verzögern?

Ich benutze die avr-gcc Toolchain.

EDIT: Ich habe den Code wie folgt geändert (Thnx: lhballoti):

while ( ( ADCSRA & _BS( ADSC ) ) == _BS( ADSC ) ) {}

Was den Assembler-Code geändert hat in:

38:   36 99           sbic    0x06, 6         ; 6
3a:   fe cf           rjmp    .-4             ; 0x38 <__CCP__+0x4>

Was das Problem anscheinend löst.

Auf dieser Seite finden Sie das vollständige Programm und den daraus resultierenden zerlegten Code.

Jippie
quelle
3
Wollen Sie nicht ein bitweises UND verwenden?
lhballoti
Normalerweise deklarieren Sie die Register als flüchtig, und dann werden Schleifen, in denen Sie keine Änderungen vornehmen, nicht optimiert. Dies sollte jedoch in den Include-Dateien für Sie erledigt werden.
W5VO
Obwohl ich den Fehler sofort entdeckt habe, habe ich Probleme zu verstehen, warum der Compiler die Schleife im ersten Fall optimiert hat. Wenn ADCSRAes nicht volatil ist, unterliegt nicht auch der zweite Fall der gleichen Optimierung?
lhballoti
Sie sollten Ihre Frage nicht mit der Antwort bearbeiten, sondern eine Antwort von jemandem akzeptieren oder Ihre eigene Antwort schreiben und akzeptieren.
Kellenjb
@Kellenjb - Jippie hat es hinzugefügt, bevor es eine Antwort war. lhballoti gab es zuerst nur als Kommentar.
Stevenvh

Antworten:

11

Sie sollten ein bitweises UND verwenden. Der Ausdruck in der ersten whileSchleife wird mit Null ausgewertet, wodurch der Compiler die Schleife vollständig entfernt.

lhballoti
quelle