AVR: avr-libc Internals

pgm_read_byte()

Abstract

The pgm_read_byte() is a macro that reads a byte of data stored in a specified address(PROGMEM area).

Source Code

The pgm_read_byte() is defined in hardware/tools/avr/avr/include/avr/pgmspace.h as below.

#define pgm_read_byte(address_short)    pgm_read_byte_near(address_short)

The input is address_short and calls the pgm_read_byte_near() macro.

pgm_read_byte_near()

Abstract

The pgm_read_byte_near() is a macro that reads a byte of data stored in a specified address(PROGMEM area).

Source Code

The pgm_read_byte_near() is defined in hardware/tools/avr/avr/include/avr/pgmspace.h as below.

#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))

The input is address_short and the macro converts the address_short to uint16_t, then calls __LPM() macro.

__LPM()

Abstract

The __LPM() is a macro that reads a byte of data stored in a specified address(PROGMEM area).

Source Code

The __LPM() is defined in hardware/tools/avr/avr/include/avr/pgmspace.h as below.

#define __LPM(addr)         __LPM_enhanced__(addr)

The input is addr and just calls __LPM_enhanced__().
See Intrinsic Functions

__LPM_enhanced__()

Abstract

The __LPM_enhanced() is an assembler code that reads a byte of data stored in a specified address(PROGMEM area).

Source Code

The __LPM_enhanced() is defined in hardware/tools/avr/avr/include/avr/pgmspace.h as below.

#define __LPM_enhanced__(addr)  \
(__extension__({                \
    uint16_t __addr16 = (uint16_t)(addr); \
    uint8_t __result;           \
    __asm__                     \
    (                           \
        "lpm %0, Z" "\n\t"      \
        : "=r" (__result)       \
        : "z" (__addr16)        \
    );                          \
    __result;                   \
}))

or newer avr-libc

#define __LPM_classic__(addr)   \
(__extension__({                \
    uint16_t __addr16 = (uint16_t)(addr); \
    uint8_t __result;           \
    __asm__                     \
    (                           \
        "lpm" "\n\t"            \
        "mov %0, r0" "\n\t"     \
        : "=r" (__result)       \
        : "z" (__addr16)        \
        : "r0"                  \
    );                          \
    __result;                   \
}))

The lpm, short for Load Program Memory, is a instruction that reads a byte of data from PROGMEM area. It substitue a data at addr for __result, then returns the __result.

Sources:
pgm_read_byte() marco
pgm_read_byte_near() marco
__LPM() marco
__LPM_enhanced__() marco

Leave a Reply

Your email address will not be published. Required fields are marked *