Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Initial Start-up "load once" data / absolute flash allocation

I have a structure that holds my configuration data for my device.  When manufactured, the programming station will flash a hex file to device that has the application and device specific data to a certain location in flash--the device specific data will match the structure of configuration data.

The idea is, that when the device is flashed, then power cycled, the application will load the configuration data from a flash location on first boot up, then it will use the FDS module to save that configuration data to flash, and from there on out the application will use FDS module to save/load the data as needed.

What would be the best way to accomplish this?  Using linker script and __attribute__ to allocate a section of data in flash?  Is there maybe a way to write to the area of flash (with HEX file) that FDS will be using so the first time fds_record_find is called, it will find the file?

What are my best options? (Using nRF5 SDK v16.0.0)

Parents
  • Hi,

    There bootloader examples in the nRF5 SDK demonstrate how you can place data at a specific location in flash. Specifically this is used to place the 4 byte addresses of the bootloader and the MBR params page in the UICR. However, the exact same approach can be used to place any type of data of any size at any location. I suggest you refer to how it is done for the bootloader start address in UICR and do the same in your case. You do not write which toolchain you use so I will explain for Segger Embedded Studio (SES), but if you refer to a bootloader example you can see how this is done in a similar way for other toolchains.

    In flash_placement.xml you have this part where the start address and size of the segment is specified. Do the same, just with a different name, address (not in UCIR but in normal flash in yoru case), and size:

      <MemorySegment name="uicr_bootloader_start_address" start="0x10001014" size="0x4">
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".uicr_bootloader_start_address" address_symbol="__start_uicr_bootloader_start_address" end_symbol="__stop_uicr_bootloader_start_address" start = "0x10001014" size="0x4" />
      </MemorySegment>

    then you can see in components\libraries\bootloader\nrf_bootloader_info.c how a variable is declared and placed at this location. You can do the same, but using your struct instead of a uint32_t:

    #define UICR_BOOTLOADER_ADDR 0x10001014
    ...
        volatile uint32_t m_uicr_bootloader_start_address  __attribute__ ((section(".uicr_bootloader_start_address")))
                                                = BOOTLOADER_START_ADDR;

    In the SES project you also need to add this to the linker_section_placements_segments list, most easily by editing the .emProject in a text editor and make sur it is part of the list like this:

          linker_section_placements_segments="FLASH1 RX 0x0 0x80000;RAM1 RWX 0x20000000 0x10000;mbr_params_page RX 0x0007E000 0x1000;bootloader_settings_page RX 0x0007F000 0x1000;uicr_bootloader_start_address RX 0x10001014 0x4;uicr_mbr_params_page RX 0x10001018 0x4"
    

    With this you can access the array at that specific location in your code and copy it to FDS as you write, in the same way as you would write any other FDS record.

Reply
  • Hi,

    There bootloader examples in the nRF5 SDK demonstrate how you can place data at a specific location in flash. Specifically this is used to place the 4 byte addresses of the bootloader and the MBR params page in the UICR. However, the exact same approach can be used to place any type of data of any size at any location. I suggest you refer to how it is done for the bootloader start address in UICR and do the same in your case. You do not write which toolchain you use so I will explain for Segger Embedded Studio (SES), but if you refer to a bootloader example you can see how this is done in a similar way for other toolchains.

    In flash_placement.xml you have this part where the start address and size of the segment is specified. Do the same, just with a different name, address (not in UCIR but in normal flash in yoru case), and size:

      <MemorySegment name="uicr_bootloader_start_address" start="0x10001014" size="0x4">
        <ProgramSection alignment="4" keep="Yes" load="Yes" name=".uicr_bootloader_start_address" address_symbol="__start_uicr_bootloader_start_address" end_symbol="__stop_uicr_bootloader_start_address" start = "0x10001014" size="0x4" />
      </MemorySegment>

    then you can see in components\libraries\bootloader\nrf_bootloader_info.c how a variable is declared and placed at this location. You can do the same, but using your struct instead of a uint32_t:

    #define UICR_BOOTLOADER_ADDR 0x10001014
    ...
        volatile uint32_t m_uicr_bootloader_start_address  __attribute__ ((section(".uicr_bootloader_start_address")))
                                                = BOOTLOADER_START_ADDR;

    In the SES project you also need to add this to the linker_section_placements_segments list, most easily by editing the .emProject in a text editor and make sur it is part of the list like this:

          linker_section_placements_segments="FLASH1 RX 0x0 0x80000;RAM1 RWX 0x20000000 0x10000;mbr_params_page RX 0x0007E000 0x1000;bootloader_settings_page RX 0x0007F000 0x1000;uicr_bootloader_start_address RX 0x10001014 0x4;uicr_mbr_params_page RX 0x10001018 0x4"
    

    With this you can access the array at that specific location in your code and copy it to FDS as you write, in the same way as you would write any other FDS record.

Children
No Data
Related