I am trying to define a look up table that is not a constant on an STM32F103. Basically I want to have a page of flash that acts like a constant lookup table in normal operation, but every once in a while (think days apart) I want to be able to erase that table and write a new one to the page of flash. I believe I understand how to use the HAL to functions to do what I need in my program, but it seems like I would need to declare this block of memory in the linker file and I'm having a lot of trouble finding an example that covers that. The default mem.ld from CubeMX looks like this:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}
It seems like I need an output sections block after that where I commit a keyword to >FLASH but I don't know what keyword that would be or how I would declare the table in the code to give it the right address.
I have seen the emulated EEPROM application note, but it seems like a lot of extra overhead for memory that will not see enough erase/write cycles to be concerned about the memory's lifetime. Help!
Answer
Note: linking is not a part of the C language standards, so each compiler implements linker files differently. You seem to be using GCC, so I will share some code that works with it.
linker.ld:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 31K
/*(1)*/ FIXED_DATA(rw) : ORIGIN = 0x8007C00, LENGTH = 1K /* your LUT here*/
}
............
.FIXED_DATA (NOLOAD):/*(2)*/
{
*(STATIC_DATA);/*(3)*/
} >FIXED_DATA /*(4)*/
In C:
__attribute__((section("STATIC_DATA")))
const static volatile statistic_static_data_t staticData;
What this does:
(1) create an area named FIXED_DATA of given location and size. Note that my code is from a different device. Check your datasheet do see what size your blocks are (they may not even be equally sized inside a device!). Make sure to reduce the size of FLASH accordingly, otherwise you will get an error about them not fitting into memory.
(2) create a section named FIXED_DATA. It doesn't have to be called FIXED_DATA actually, but it helps keep track. Attribute NOLOAD tells the linker to not fill the area (see below).
(3) put all variables marked STATIC DATA into this memory section
(4) put everything in this section into the area named FIXED_DATA that we created way above
In the C file, you just have to tag the variables you want put into the area. I recommend calling them const because you don't generally want to write to flash directly. Volatile helps with compiler optimizations that assume const data never changes.
Why go through all this trouble, instead of using the much simpler solutions in other answers? Because it's upgradeable. If, in the future, you want to do a FW update, you may want to keep the stored data in memory. The NOLOAD instruction in the linker file does just that: the linker does not fill the data with 0, as it would normally do if you have a global variable living there.
You can find out more about the arcane ways of the linker if you search for "ld syntax"
No comments:
Post a Comment