[SOLVED] Assigning variables to fixed addresses in flash

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • [SOLVED] Assigning variables to fixed addresses in flash

    Our project uses SEGGER Embedded Studio for ARM Release 7.12a Build 2023031402.52776 and works with the STM32F411VET. There are end-user settings we want to store in flash so they can be modified and preserved between power cycles of the device. Looking around we found two major sources of information on how to pull this off, but neither worked completely correctly.

    The first comes from this Segger forum post (note that this is dated 2017, so may now be inaccurate) :

    [SOLVED] Placing data at a specific memory address with Segger Embedded Studio

    This tells you to edit the XML memory map file and then use the "attribute" property to flag where the variable should be stored. Following the example from the above thread and having the XML file modified like so:

    XML Source Code

    1. <!DOCTYPE Board_Memory_Definition_File>
    2. <root name="STM32F411VETx">
    3. <MemorySegment name="FLASH1" start="0x08000000" size="0x00080000" access="ReadOnly" />
    4. <MemorySegment name="RAM1" start="0x20000000" size="0x00020000" access="Read/Write" />
    5. <MemorySegment name="$(FLASH_NAME:FLASH)">
    6. <ProgramSection alignment="4" load="Yes" name=".MyVar" start="0x00080000" />
    7. </MemorySegment>
    8. </root>




    And then declaring the variable to be placed in flash like so (tPagedata being a structure type) :

    C Source Code

    1. __attribute__((section(".MyVar"))) const tPagedata flashData =
    2. {
    3. .data = {
    4. {"0123456789AB"},
    5. {"0123456789AB"},
    6. {"0123456789AB"},
    7. UNITS_IMPERIAL,
    8. OLED_MAX_BRIGHT}
    9. };
    This ends up not working since the location in memory for value flashData ends up being 0x080066D8, not 0x08000000 as expected. Side note, after trying :


    XML Source Code

    1. <!DOCTYPE Board_Memory_Definition_File>
    2. <root name="STM32F411VETx">
    3. <MemorySegment name="FLASH1" start="0x08000000" size="0x00080000" access="ReadOnly">
    4. <ProgramSection alignment="4" load="Yes" name=".MyVar" start="0x00080000" />
    5. </MemorySegment>
    6. <MemorySegment name="RAM1" start="0x20000000" size="0x00020000" access="Read/Write" />
    7. </root>
    As a variation, the value was still placed at 0x080066D8. The second description comes from a Segger wiki (which is at least dated from 2023) :

    wiki.segger.com/Add_new_Memory_Sections_and_Segments
    Following these directions the XML memory map gets altered as such :

    XML Source Code

    1. <!DOCTYPE Board_Memory_Definition_File>
    2. <root name="STM32F411VETx">
    3. <MemorySegment name="CONFIG" start="0x08000000" size="0x00004000" access="ReadOnly" />
    4. <MemorySegment name="FLASH1" start="0x08004000" size="0x0007C000" access="ReadOnly" />
    5. <MemorySegment name="RAM1" start="0x20000000" size="0x00020000" access="Read/Write" />
    6. </root>
    With the flash.icf file getting this added to the end :

    C Source Code

    1. place in CONFIG { symbol flashData };
    2. keep { symbol flashData };
    However, if I do this, then the code fails to execute and I get a UsageFault_StateError. We could use some guidance on how to get either of these techniques working correctly.
  • Hello,

    Thank you for your inquiry.
    The recommended way to place variables in Flash with SEGGER Linker is explained here:
    wiki.segger.com/How_to_place_variables_in_Flash

    Best regards,
    Nino
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.
  • Thank you for the feedback. The issue isn't declaring a value to exist in a particular region per se, but I also need to split off the flash to divide it into a R/W section for user data and save the rest for the code. Following the advice from the Segger wiki to make a new flash memory section leads to a UsageFault_StateError before I can even verify that the desired variables are correctly placed, as outlined in my original post.
  • As an addendum, I want to point out that this ST processor is unusual in that the flash memory pages are not divided equally as they are in literally every processor I've ever seen in a 20 year career:

    Source Code

    1. Sector 0 0x0800 0000 - 0x0800 3FFF 16 Kbytes
    2. Sector 1 0x0800 4000 - 0x0800 7FFF 16 Kbytes
    3. Sector 2 0x0800 8000 - 0x0800 BFFF 16 Kbytes
    4. Sector 3 0x0800 C000 - 0x0800 FFFF 16 Kbytes
    5. Sector 4 0x0801 0000 - 0x0801 FFFF 64 Kbytes
    6. Sector 5 0x0802 0000 - 0x0803 FFFF 128 Kbytes
    7. Sector 6 0x0804 0000 - 0x0805 FFFF 128 Kbytes
    8. Sector 7 0x0806 0000 - 0x0807 FFFF 128 Kbytes
    So it could be that the Segger tools are doing something incorrectly on this particular chip if the tools assumed all flash memory pages were of equal size when they aren't. As can be seen in my original post I tried splitting sector 0 off into its own section but this produces errors.
  • Hello,

    Of course we are aware of the different flash bank sizes and it is actually not that uncommon. But it is also nothing the toolchain has to worry about. This is handled by our J-Link flash loaders and in your case also seems to be working otherwise the download and debug session start would already fail. Which is not the case here.

    All you have to do is supply a valid memory map that describes the complete memory blocks as one unit. So the correct memory map for your device is this:

    XML Source Code

    1. <!DOCTYPE Board_Memory_Definition_File>
    2. <root name="STM32F411VETx">
    3. <MemorySegment name="FLASH1" start="0x08000000" size="0x00080000" access="ReadOnly" />
    4. <MemorySegment name="RAM1" start="0x20000000" size="0x00020000" access="Read/Write" />
    5. </root>
    And nothing else!

    Everything else regarding placement is done via the linker or your code, depending on how you are placing the variable.
    Attached you can find a simple example project for your device that places a const string at a specific location in Flash.
    This can be of course done with any symbol.

    Also you seem to be trying to place data at Flash offset 0. While from Linker side you can of course do so, your Cortex-M will never boot as Cortex-M requires a vector table at that location which at least points to the Reset_Handler address and contains the stack pointer. That is why explicit placement on offset 0 does not work with the default linker script generated by ES because you have this line in your linker script to accommodate this:
    place at start of FLASH { block vectors }; // Vector table section

    If you change that line to
    place in FLASH { block vectors }; // Vector table section

    And do an explicit placement of your symbol to 0, then it will be placed there. But again, if that data does not contain the vector table your device will not start.


    For more information about the SEGGER Linker see here:
    segger.com/doc/UM20005_Linker.html


    Best regards,
    Nino
    Files
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.