I'm just learning to use inline assembly with avr-gcc, and I've
encountered what seems to me to be a very strange bug (but may be user
silliness).
In the test case below, I repeatedly change the first entry of the
data array between 0xFF and 0x00. A short piece of assembly then
moves data[0] into r0 and pushes it out to PORTB. This causes an LED
to flash. This works.
However, when I change:
"ldd r0, %a1+0 \n\t"
"out %0, r0 \n\r"
to:
ldd r1, %a1+0 \n\t"
"out %0, r1 \n\r"
IE: replace r0 with r1, the LED just stays lit continuously.
Fine, so I look at the assembly listing generated by avr-objdump -h -S
ads-tx.elf > ads-tx.lst
This is the diff between the working and non-working versions:
99,102c99,102
< ae: 10 80 ld r1, Z
< b0: 15 b8 out 0x05, r1 ; 5
< "ldd r1, %a1+0 \n\t"
< "out %0, r1 \n\r"
---
> ae: 00 80 ld r0, Z
> b0: 05 b8 out 0x05, r0 ; 5
> "ldd r0, %a1+0 \n\t"
> "out %0, r0 \n\r"
170,171c170,171
< e4: 10 80 ld r1, Z
< e6: 15 b8 out 0x05, r1 ; 5
---
> e4: 00 80 ld r0, Z
> e6: 05 b8 out 0x05, r0 ; 5
188,189c188,189
< f0: 10 80 ld r1, Z
< f2: 15 b8 out 0x05, r1 ; 5
---
> f0: 00 80 ld r0, Z
> f2: 05 b8 out 0x05, r0 ; 5
It looks to me like the only thing that has changed is R0/R1.
Even more strange is that using R2, R3, R13 all work. Just R1 fails.
I am baffled.
Test code:
#include <stdint.h>
#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>
void send_packet(volatile uint8_t* data)
{
asm volatile(
//first load data in to RX
"ldd r0, %a1+0 \n\t"
"out %0, r0 \n\r"
:
:"I" (_SFR_IO_ADDR(PORTB)), "e" (data)
: "r0", "r1", "r2", "r3", "r13");
}
void main(void)
{
//this shouldn't need volatile, but gcc optimizes it out otherwise?
volatile uint8_t data[14];
DDRB = 0xFF;
while (1)
{
data[0] = 0x00;
send_packet(data);
_delay_ms(20);
data[0] = 0xFF;
send_packet(data);
_delay_ms(20);
}
}
Thanks for the help,
-DC
_______________________________________________
AVR-GCC-list mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list