[Top][All Lists]
[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.