I'm trying to place a variable in EEPROM such that the address of the variable shows up at the EEPROM's address but the linker does not try to initialize the var. The idea is that when code reads the variable it's reading from EEPROM and any writes are done via EEPROM_xxx() functions.
I realize this would be easier done with a pointer to a structure that has all the EEPROM-backed values but it's kind of nice to just have the compiler and linker take care of everything.
Here's what I have in my C code:
__attribute ((section ("EEPROM"))) uint8_t Bias_Current; __attribute ((section ("EEPROM"))) bool Auto_test;
I set up sections in the "Target" dialog and I'm using the following scatter load file: LR_IROM1 0x08000000 0x00020000 { ; load region size_region ER_IROM1 0x08000000 0x00020000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00004000 { ; RW data icc_measure_Ram.o (+RO) .ANY (+RW +ZI) } ER_ROM1 0x00808000 UNINIT 0x00001000 { ; load address = execution address *(EEPROM) } }
However, when I run the code the scatter load algorithm crashes because it's trying to initialize the target address (0x808000), even though I marked it as "UNINIT".
What's the best way to use scatter loading to place variables at a target address but make sure the target address doesn't get written to by the scatter loader?
Thanks, Andrew
I agree, I can't say I really like the approach either, which is why I mentioned the pointer approach would probably be easier in my original post.
The code in questions is written by someone else and I'm porting it from IAR to Keil. I wanted to understand why it isn't working for me but it's small enough to rewrite with pointers. It'll be better in other ways, e.g. support for multiple unrelated modules sharing EEPROM is easier. With the linker approach I'd be relying on the sct file to make sure things are always placed in the same order. With the pointer approach that can be made explicit in the code. Also, I usually put sentries and some kind of checksum in my non-volatile structures to make sure things are ok.
Andrew
Answering my own question for future reference, although I already decided to abandon this approach:
In RVCT 2.1 and later global variables smaller than 8 bytes are silently moved into the a normal RW data segment instead of the zero-init section. You need to add zero_init to the attributes to force the variable back into .bss. In my case it's extra confusing because I want to actually suppress the zero-fill completely but to get everything working you need to force the variable into a .bss-type segment and use the UNINIT directive in the .sct file to suppress the zero-fill.
__attribute ((section ("EEPROM"),zero_init)) uint8_t Bias_Current;
and
ER_ROM1 0x00808000 UNINIT 0x00001000 { ; load address = execution address *(EEPROM) }
Details here:
infocenter.arm.com/.../ka3947.html