Search code examples
avriaravr-gcc

__eeprom and EEMEM


I am trying to port a code base from iar to avr-gcc. Amongst other things that have to replaced, the iar eeprom memory attribute __eeprom has to replaced with a avr-gcc friendly attribute. AFAIK the replacement for that is EEMEM, but the usage differs and I am not able to figure out how to replace __eeprom in the cleanest manner.

../src/myfunc.h:35:46: error: section attribute not allowed for 'src'
     UBYTE *strcpye(UBYTE *dest, UBYTE EEMEM *src);

This error is not limited to pointers, but to all variables in general. IMO the usage of EEMEM is correct, where am I going wrong?


Solution

  • In the avr-gcc toolchain, avr-libc defines macro EEMEM in avr/eeprom.h:

    #define EEMEM __attribute__((section(".eeprom")))

    This means it's just an attribute that determines the section in which an object with this attribute will be located. In particular, EEMEM only makes sense for variables in static storage. Moreover, accesses to objects located in EEMEM have to be done by hand using functions / macros supplied by avr/eeprom.h like

    void eeprom_read_block (void *dst, const void *src, size_t n);
    void eeprom_write_byte (uint8_t *p, uint8_t value);
    void eeprom_update_word (uint16_t *p, uint16_t value);
    

    etc. Also notice that EEMEM is just an attribute and not a qualifier (like __flash for example). This means that even though you can tag a pointer (target) using attributes, that won't change the access in any way. To be more specific, any access through a pointer that's attributed EEMEM will be to RAM and not to eeprom.

    In your case, the prototype of strcpye would read

    char* strcpye (char *dest, const char *src);

    and the implementation of that function would apply eeprom_read_byte on src++ and write to dest++ until it reads a terminal \0. Notice that you might need an explicit pointer cast as eeprom_read_byte expects [const] uint8_t*, and that char, signed char and unsigned char are 3 distinct types in C.