Skip to content

Instantly share code, notes, and snippets.

@rikka0w0
Created March 16, 2021 14:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rikka0w0/47541729db3cbf5511d98b3b06be47cd to your computer and use it in GitHub Desktop.
Save rikka0w0/47541729db3cbf5511d98b3b06be47cd to your computer and use it in GitHub Desktop.
Change the linkerscript to allocate some space for storing non-volatile user data

Solution 1: User Data at the end of flash

Define constants before MEMORY section:

/* EEPROM emulator */
_Flash_Page_Size = 0x400;	/* Page size of the flash in bytes, see MCU datasheet */
_User_Config_Size = 0x400;	/* Size of the emulated EEPROM in bytes, must be multiples of _Flash_Page_Size */

Define the section for non-volatile user data:

  /* Flash reserved for the EEPROM emulation at the end of the Flash*/
  ._user_configuration :
  {
    . = ORIGIN(FLASH) + LENGTH(FLASH) - _User_Config_Size - _User_Config_Size;
    . = ALIGN(_Flash_Page_Size);
    _user_config_start = .;
    . = . + _User_Config_Size;
    _user_config_break = .;
    . = . + _User_Config_Size;
    _user_config_end = .;
  } >FLASH

In C code, access the addresses via &_user_config_start, &_user_config_break and &_user_config_end.

Advantage:

  1. The size of the user data section can grow as needed.
  2. Does not interfere with OTA

Disadvantage:

  1. Increasing the size of the Flash will need to change the base address of the user data section.

Solution 2: User Data before code but after vector table

Define constants and edit the MEMORY section:

/* EEPROM emulator */
_Flash_Page_Size = 0x400;	/* Page size of the flash in bytes, see MCU datasheet */
_User_Config_Size = 0x400;	/* Size of the emulated EEPROM in bytes, must be multiples of _Flash_Page_Size */
_Flash_Size = 32K;			/* Total size of the MCU flash */

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 4K
VECTORS (rx)   : ORIGIN = 0x8000000, LENGTH = _Flash_Page_Size
USER (r)       : ORIGIN = 0x8000400, LENGTH = _User_Config_Size + _User_Config_Size
FLASH (rx)     : ORIGIN = 0x8000c00, LENGTH = _Flash_Size - _Flash_Page_Size - _User_Config_Size - _User_Config_Size
}

Move the vector table to VECTORS section.

  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >VECTORS

Define user data section:

  /* Flash reserved for the EEPROM emulation at the end of the Flash*/
  ._user_configuration :
  {
    . = ALIGN(_Flash_Page_Size);
    _user_config_start = .;
    . = . + _User_Config_Size;
    _user_config_break = .;
    . = . + _User_Config_Size;
    _user_config_end = .;
  } >USER

Advantage:

  1. The address of the user data section remains constant between different MCU with different Flash size.

Disadvantage:

  1. Increasing the size of the user data section requires moving of the code section, which could become a problem if OTA feature is required.

Note: if OpenOCD reports an error after editing the linkerscript file, perform a complete flash erase and try again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment