avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] bug with bitfields in (volatile) registers?


From: Dmitry K.
Subject: Re: [avr-gcc-list] bug with bitfields in (volatile) registers?
Date: Fri, 7 Jan 2005 17:15:28 +1000
User-agent: KMail/1.5

On Friday 07 January 2005 16:43, Ned Konz wrote:
> I was just bit by this surprise with registers suddenly being treated as if
> they were not volatile (in avr-gcc 3.4.3). I'm using a chip with no RAM, so
> I would like the registers to work properly.
>
> // avr-gcc -Os -mmcu=avr2 -mcall-prologues -mint8 -mtiny-stack -save-temps
> -Wall -g -Wa,-almshd=registerbug.lst -Wl,--oformat=ihex -o registerbug.hex
> registerbug.c
> // avr-objdump -h -S registerbug.o  > registerbug.lss
>
> typedef struct
> {
>     unsigned char uartState:4;
>     unsigned char unused:4;
> } state_t;
>
> register unsigned char c __asm__("r16");
> register state_t state __asm__("r3");  // actually volatile...
> register unsigned char state2 __asm__("r17");
> register unsigned char state3 __asm__("r9");
>
> int main(void)
> {
>    0: c0 e0        ldi r28, 0x00 ; 0
>    2: d0 e0        ldi r29, 0x00 ; 0
>    4: de bf        out 0x3e, r29 ; 62
>    6: cd bf        out 0x3d, r28 ; 61
>
> // look what's happening here: r3 is getting copied to r24...
>    8: 83 2d        mov r24, r3
>    a: 8f 70        andi r24, 0x0F ; 15
>  for (;;)
>  {
> // and then the comparison is being done on r24.
> // however, meanwhile an interrupt handler is changing r3, and we
> // get stuck in this loop forever:
>   while (state.uartState == 10)
>    c: 8a 30        cpi r24, 0x0A ; 10
>    e: f1 f3        breq .-4       ; 0xc
> // that should be a branch back to 0x8 instead of 0xc!
>    ;
  [...]

Yes, it is impossible to treat register variables as volatiles.
(I have not try 3.4 branch).

But it is method to avoid this restriction by empty statement:
   asm volatile ("" ::: "r3");
which said to compiler about possible change of r3.
No run-time losses.
And it is needed simetimes to force writing to reg. variable,
method is analogous.

Example:

   register unsigned char reg asm ("r2");

   void foo1 (void);

   void foo_bad (void)
   {
       do {                /* --> error, incontinues loop */
           if (reg & 1) {
               foo1();
               reg &= ~1;
           }
       } while (1);
   }

   void foo_true (void)
   {
       do {                /* OK */
           if ( ({
                   unsigned char __c;
                   asm volatile ("" ::: "r2");
                   __c= reg;
               }) & 1 )
           {
               foo1();
               reg &= ~1;
           }
       } while (1);
   }

Regards.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]