[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] AvrX and pgm_read_byte_near()
From: |
E. Weddington |
Subject: |
Re: [avr-gcc-list] AvrX and pgm_read_byte_near() |
Date: |
Mon, 24 Nov 2003 17:23:16 -0700 |
On 24 Nov 2003 at 18:37, Brian Cuthie wrote:
>
> So I have an AvrX task that spins something like this:
>
> unsigned char b;
>
> while (1) {
>
> b = pgm_read_byte_near(0x54 /* or some other small
> address */);
>
> /* write something to I/O so I can see what's happening
> */
>
> /* delay */
> AvrXDelay(&timer2, 100);
> }
>
>
> Strangely, if I run this the I/O happens once and never again. If I
> remove 'pgm_read_byte_near()' it works great.
>
> Before I get some more gray hair trying to figure out what's hosing AvrX
> (I'm guessing using the Z register has it unhappy), I thought I'd post
> something here in hopes that I'm not the first person to see this behavior.
>
Interesting. I don't know if the use of the Z reg is what is making AvrX
unhappy (Larry Barello would have to comment on that).
However, in looking through pgmspace.h I noticed that all the __LPM* inline
assembly macros don't have the Z reg (r30, r31) in their clobber lists, but
all the __ELPM* inline assembly macros do have it in their clobber lists.
Below are updated versions of the __LPM macros (found in <avr/pgmspace.h>)
with the Z reg in the clobber lists. With this, GCC should know that the Z
reg should be restored. Let me know if this works and if it does I'll
update avr-libc.
Eric
-----------
#define __LPM_classic__(addr) \
({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint8_t __result; \
__asm__ \
( \
"lpm" "\n\t" \
"mov %0, r0" "\n\t" \
: "=r" (__result) \
: "z" (__addr16) \
: "r0", "r30", "r31" \
); \
__result; \
})
#define __LPM_enhanced__(addr) \
({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint8_t __result; \
__asm__ \
( \
"lpm %0, Z" "\n\t" \
: "=r" (__result) \
: "z" (__addr16) \
: "r30", "r31" \
); \
__result; \
})
#define __LPM_word_classic__(addr) \
({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint16_t __result; \
__asm__ \
( \
"lpm" "\n\t" \
"mov %A0, r0" "\n\t" \
"adiw r30, 1" "\n\t" \
"lpm" "\n\t" \
"mov %B0, r0" "\n\t" \
: "=r" (__result), "=z" (__addr16) \
: "1" (__addr16) \
: "r0", "r30", "r31" \
); \
__result; \
})
#define __LPM_word_enhanced__(addr) \
({ \
uint16_t __addr16 = (uint16_t)(addr); \
uint16_t __result; \
__asm__ \
( \
"lpm %A0, Z+" "\n\t" \
"lpm %B0, Z" "\n\t" \
: "=r" (__result), "=z" (__addr16) \
: "1" (__addr16) \
: "r30", "r31" \
); \
__result; \
})