While loop optimized away

I have the following code in my microcontroler program:

// Wait for ADC conversion to complete


Where ADCSRA is a register that will change its value once an analog conversion is completed and where I want to wait for a bit to be clear. This bit indicates conversion completed.

Looking at the resulting assembly code, the whole loop is replace by a single instruction:

in      r24, 0x06       ; ADCSRA


The register is read, but its value isn't even tested!?

How do I have to change my C++ code to instruct the compiler to keep rechecking the register, without unnecessary delaying the program?

I use the avr-gcc toolchain.

EDIT: I changed the code as follows (Thnx: lhballoti):

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


Which changed the assembly code to:

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


Which apperently solves the problem.

Check this page for the complete program and its disassembled resulting code.

• Don't you mean to use a bitwise AND? – lhballoti Jul 7 '12 at 17:15
• usually you would declare the registers to be volatile, and then loops where you don't modify things won't be optimized... but that should be done for you in the include files. – W5VO Jul 7 '12 at 17:21
• Although I spotted the mistake right away, I'm having trouble understanding why the compiler optimized the loop away in the first case. If ADCSRA isn't volatile, isn't the second case also subject to the same optimization? – lhballoti Jul 7 '12 at 17:57
• You shouldn't edit your question with the answer, rather accept someones answer or write your own answer and accept it. – Kellenjb Jul 7 '12 at 18:27
• @Kellenjb - jippie added it before it was an answer. lhballoti first just gave it as a comment. – stevenvh Jul 7 '12 at 18:40

You should be using a bitwise AND. The expression in the first while loop evaluates to zero, which causes the compiler to remove the loop altogether.