cancel
Showing results for 
Search instead for 
Did you mean: 

Update of Flash lookup table - where to put in linker script

Posted on August 18, 2014 at 22:55

I'm editing this as I see that my first post - from an iPad - wasn't accepted as it was from a mobile device.

I'm writing for a STM32F4 device that involves getting information from a number of lookup tables.  These tables are perhaps 1K in total size.  The user will update these occasionally.  The main code will, apart from bug fixes, be seldom updated.  All updates will be via the inbuilt bootloader.  In order not to unnecessarily expose our main code from being downloaded (by providing an update image for the boot loader), we wish to update the lookup tables separately from the main code.

My question is on strategies for where to store the lookup data in flash.

If the data is stored in flash, the section needs to be deleted before the update, and the smallest section is 16K.  It therefore seems very wasteful to put the lookup tables in a separate section as they're only going to be 1K max, and probably very much smaller.

Should I do this, however?  

Or should I just put the data in the .data section along with all other initialised variables and just update all of these when I update the tables?

How do I know the address of the start of the .data section when updating the tables so that I can access this when copying the data from ROM to RAM? 

If I need to align the data on a section page (16K), how do I do this and align the elements on a 4 byte boundary?  Do I do this in the linker script or when defining the variable using the ''aligned'' attribute?

Sorry for the numpty questions, but this is my first experience of working with linker scripts.

#discovery #stm32f4 #linker-script-stm32
3 REPLIES 3
Posted on August 19, 2014 at 03:16

This forum does not support posting from mobile devices.

Linker scripts would permit you to place specific objects into specific memory regions, and you might also be able to use #pragma's or attributes to get specific variables/functions into named segments, which you have enumerated in the linker script.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 19, 2014 at 09:17

So I think I've managed to answer part of my question, so am posting here for others.  The following seems to create a .data section aligned on a 16K boundary.

  /* used by the startup to initialize data */

  . = ALIGN(16384);

  _sidata = .;

  /* Initialized data sections goes into RAM, load LMA copy after code */

  .data : AT ( _sidata )

  {

    . = ALIGN(4);

    _sdata = .;        /* create a global symbol at data start */

    *(.data)           /* .data sections */

    *(.data*)          /* .data* sections */

    . = ALIGN(4);

    _edata = .;        /* define a global symbol at data end */

  } >RAM

  _eidata = _sidata + SIZEOF(.data);

So I have now global symbols, _sidata and _eidata, marking the start and end of the .data section (_eidata is the actual end, not the nearest 16K boundary). _sdata and _edata are the addresses of the start and end of the .data section in RAM (as I believe I've determined from looking at the output from nm on the executable).

How do you know what the LMA address of a variable is?  I am assuming that when updating the lookup table, the data needs to be written to the same LMA?  So how would I overwrite this in C?
Posted on August 19, 2014 at 17:09

I'd consider doing this externally, ie have the C code reference specific tables, with specific addresses, that you have floor planed out of one of the 16 KB flash regions that is outside your application/boot loader foot print.

Have the tables/structures tagged so you can see if they are erased/empty. Have the application fill them with default values if required, and manage the erasure and loading of the tables. Familiarize yourself with the Flash Erase and Write functionality/functions.

typedef struct _FOO {
uint32_t Valid; // Magic Value, not 0xFFFFFFFF
uint8_t Table[32];
} FOO;
typedef struct _BAR {
uint32_t Valid; // Magic Value, not 0xFFFFFFFF
uint8_t Table[64];
} BAR;
FOO *foo = (FOO *)0x08008000;
BAR *bar = (BAR *)0x08008200;
 if (foo->Valid == FOO_MAGIC)
 puts(''Table FOO valid'');
 ... 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..