Boucle optimisée

8

J'ai le code suivant dans mon programme de microcontrôleur:

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

Où ADCSRA est un registre qui changera sa valeur une fois la conversion analogique terminée et où je veux attendre un peu pour être clair. Ce bit indique que la conversion est terminée.

En regardant le code d'assemblage résultant, la boucle entière est remplacée par une seule instruction:

in      r24, 0x06       ; ADCSRA

Le registre est lu, mais sa valeur n'est même pas testée!?

Comment dois-je changer mon code C ++ pour demander au compilateur de continuer à revérifier le registre, sans retarder inutilement le programme?

J'utilise la chaîne d'outils avr-gcc.

EDIT: J'ai changé le code comme suit (Thnx: lhballoti):

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

Ce qui a changé le code assembleur en:

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

Ce qui résout de façon apparente le problème.

Consultez cette page pour le programme complet et son code résultant démonté.

jippie
la source
3
Vous ne voulez pas utiliser un ET au niveau du bit?
lhballoti
généralement, vous déclarez que les registres sont volatils, puis les boucles où vous ne modifiez pas les choses ne seront pas optimisées ... mais cela devrait être fait pour vous dans les fichiers d'inclusion.
W5VO
Bien que j'ai repéré l'erreur tout de suite, j'ai du mal à comprendre pourquoi le compilateur a optimisé la boucle dans le premier cas. S'il ADCSRAn'est pas volatil, le deuxième cas n'est-il pas également soumis à la même optimisation?
lhballoti
Vous ne devez pas modifier votre question avec la réponse, plutôt accepter la réponse de quelqu'un ou écrire votre propre réponse et l'accepter.
Kellenjb
@Kellenjb - jippie l'a ajouté avant que ce ne soit une réponse. lhballoti vient d'abord de le faire en commentaire.
stevenvh

Réponses:

11

Vous devez utiliser un ET au niveau du bit. L'expression dans la première whileboucle est évaluée à zéro, ce qui oblige le compilateur à supprimer complètement la boucle.

lhballoti
la source