2024-02-12 10:33 AM
Hi everyone,
I have a peculiar case. We are updating our product from a legacy micro, on which we were using an external EEPROM to store a LOT of settings (in the hundreds of KB). These were stored in pages of 1K each, and each page was different.
Now, we want to update these boards with an STM32 but use the same format to store these settings.
For example, page0 at offset 0 stores an uint8_t called product type. Offset 1 stores a uint16_t called product_subtype, offset 3 another uint16_t, etc
We need to have a very well defined location for each of these, as we load them from EEPROM on boot and store them back to the EEPROM on shutdown. There is also a software that manipulates these settings, and to change these settings, the software tells the micro that it wants to read the uint16_t variable at page0, offset 1 (ie product_subtype), then maybe store the value "2" to this address.
So, for all this to work, the address of all these variables must be defined and respected.
In our legacy processor, we could just say:
uint8_t product @0;
uint16_t product_subtype @1;
uint16_t product_subtype_2 @3;
etc.
Then we can store and load the entire settings from RAM to EEPROM and vice versa with a simple for loop and do the same with the configuration software. We are very new to STM32Cube and the GCC way of doing things, our previous compiler/linker pretty much did it all without us needing to mess with .ld files or anything.g
Thank you!
2024-02-12 10:56 AM
Use a packed structure, this will allow for byte level alignment, rather that 32 or 64-bit alignment the ARM tools will prefer. Depending on the specific architecture it can fault on alignment, you can memcpy() things to avoid alignment issues.
You could use pointers to these structures or unions.
You can hide memory from the linker.
You could create sections that subdivide the memory space in the linker's view, and use attribute to direct content, structures or variables into it.
2024-02-12 10:58 AM
Or use this as an opportunity to refactor into more portable methods?
Which STM32? Plan on adding QSPI Flash for long-term storage? eMMC / SDIO / SDMMC for content into files? An I2C EEPROM?
2024-02-12 11:27 AM
Maybe try using unions and packed structs (example for gcc, for other compilers you have to check yourself):
union __attribute__((packed)) {
struct __attribute__((packed)) {
union __attribute__((packed)){
struct __attribute__((packed)) {
uint8_t product; // @0
uint16_t product_subtype; // @1
uint16_t product_subtype_2; // @3
};
uint8_t page0[1024]; // placeholder to fill all page
};
union __attribute__((packed)){
struct __attribute__((packed)) {
uint32_t var1; // @0
uint8_t var2; // @4
uint16_t var3; // @5
};
uint8_t page1[1024]; // placeholder to fill all page
};
// etc.
};
all[8][1024];
} ee;
EeSetVal(uint32_t value, uint32_t page, uint32_t addr, uint32_t size) {
uint32_t i;
for (i = 0; i < size; i++) {
ee.all[page][addr + i] = value & 0xFF;
value = value >> 8;
}
}
JW
2024-02-12 12:24 PM
Hi,
EEPROMs usually have i2c or SPI interfaces, STM32 can perfectly work with either.
As for storing back on shutdown - do you mean an unexpected shutdown, like power off? In this case you can add a super-cap or a similar short-time battery to allow the write back, and use a special type of eeprom that is designed for this scenario.
>In our legacy processor, we could just say:
> uint8_t product @0;
Unlike STM8, the ARM compilers do not support this syntax. You'll have to define your data structures in RAM, read them from the EEPROM and write modified pages back as needed. No need to mess with .ld files at all.
If you need help with writing the software or with hardware design, it can be found here.