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

[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;                               \
})



reply via email to

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