This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Using FDS Flash storage for user settings as well as for DFU

I am building on a BLE DFU project which already has a NRF_FSTORAGE_DEF for allocation of non-volatile data used by DFU.
I want to add another instance of NRF_FSTORAGE_DEF for use with application setting data.

Can I define two different regions in Flash for this purpose, or do all uses of NRF_FSTORAGE_DEF need to be in a contiguous block of Flash memory?

One problem is that m_fs is used for both instance - which is easily fixed by renaming the DFU one to m_dfu_fs to avoid a name conflict.

The DFU section is set to between 0x7F000 - 0x80000.

Can I set my other section to 0x20000 - 0x22000?

I tried this and it compiles and runs OK, but when the pages_init() function is called on initialization of the FDS module, all three pages are marked as FDS_PAGE_UNDEFINED and are not erased, so all three are discounted and the function returns NO_PAGES.

I have the following settings in sdk_config.h:

#define FDS_VIRTUAL_PAGES 3

#define FDS_VIRTUAL_PAGE_SIZE 1024

#define FDS_VIRTUAL_PAGES_RESERVED 0

Are these settings correct for what I need?

If the Flash fs_data section needs to be contiguous, how should the region be defined? In the project settings or in code (as is done for the DFU region)?

Thanks...

Declan Traill

Parents
  • Hi Declan, 

    I don't think it's an problem to have multiple fstorage instances and if they are occupying different places in the flash. 

    However, why did you choose 0x20000 - 0x22000 ? Which SDK and softdevice you are using ?It's more likely inside the softdevice/application code space . I would suggest you to choose a place at the bottom of the flash, right before the bootloader. 

    In addition, to avoid the flash area being used by the bootloader as the swap bank , you would need to configure how large your data is by using NRF_DFU_APP_DATA_AREA_SIZE (the area right under the bootloader). The layout is here.

  • The latest is that the sd_flash_write() function is returning NRF_ERROR_FORBIDDEN      Tried to write to an address outside the application flash area.

    This is probably due to the way the FDS area is being defined, and that I have to override the flash_bounds_set() where it is supposed to set the start/end addresses (but was setting it to a non-erased region - so the init function failed).

    I can't see what setting to change at the moment - have tried a couple of things, but same result.

    BTW I have NRF_DFU_APP_DATA_AREA_SIZE set to 0x3000  for the app storage area just below the bootloader.

    Any suggestions?

  • Hi Declan, 

    S132 v5.0 is quite old softdevice, are you sure you use the latest ? Which exactly SDK version you are using ? 

    If you have a look here  you can have a rough idea of the memory layout. 

    I'm not sure why your FDS area is at 0x1000 - 0x3000 it should not be there, it's the area for MBR and softdevice. 

    What was the result of flash_end_addr() in your case  ?

    Where is your bootloader and your application located ? 

  • I am using the latest SDK (nRF5_SDK_15.3.0_59ac345)

    I tried changing to s132_nrf52_6.1.1_softdevice.hex and also changing the Flash region for the application from staring at 0x23000 to 0x26000 (due to the softdevice change).

    The flash_bounds_set() function still tries to set the pages address to 0x21000 - 0x24000 and finds all pages to be FDS_PAGE_UNDEFINED and not erased.

    If I override the flash_bounds_set() function and set the start/end address for my FDS region to 0x7A000 - 0x7E000, then the pages are found OK, but when a write is attempted it returns NRF_ERROR_INTERNAL.

    The FDS area is not 0x1000 - 0x3000. I just tried that once following your suggestion about placing it at the bottom of the Flash, before I realized that the softdevice was occupying that region.

    Can you see why the FDS module keeps wanting to set the Flash region to 0x21000 - 0x24000?

    I there some project setting/config that determines this that I need to change?

  • I found that the flash_bounds_set() function was using the defined BOOTLOADER_START_ADDR to determine where to put the FDS region (just below the bootloader as you suggested), but the value of BOOTLOADER_START_ADDR was set to 0x26000 which is the start of the application Flash region. So by adding a global setting for BOOTLOADER_START_ADDR = 0x78000 into the project file, the bootloader location can be specified, and the FDS area is then put below it, and further down is the application code (from 0x26000 to 0x4326C). This then seems to work OK.

Reply
  • I found that the flash_bounds_set() function was using the defined BOOTLOADER_START_ADDR to determine where to put the FDS region (just below the bootloader as you suggested), but the value of BOOTLOADER_START_ADDR was set to 0x26000 which is the start of the application Flash region. So by adding a global setting for BOOTLOADER_START_ADDR = 0x78000 into the project file, the bootloader location can be specified, and the FDS area is then put below it, and further down is the application code (from 0x26000 to 0x4326C). This then seems to work OK.

Children
  • Hi Declan, 
    Are you sure it was BOOTLOADER_START_ADDR  ? but not BOOTLOADER_ADDRESS. As far as I know the BOOTLOADER_START_ADDR  only used in the bootloader. This is how my flash_end_addr() looks like: 

    static uint32_t flash_end_addr(void)
    {
    uint32_t const bootloader_addr = BOOTLOADER_ADDRESS;
    uint32_t const page_sz = NRF_FICR->CODEPAGESIZE;

    #if defined(NRF52810_XXAA) || defined(NRF52811_XXAA)
    // Hardcode the number of flash pages, necessary for SoC emulation.
    // nRF52810 on nRF52832 and
    // nRF52811 on nRF52840
    uint32_t const code_sz = 48;
    #else
    uint32_t const code_sz = NRF_FICR->CODESIZE;
    #endif

    uint32_t end_addr = (bootloader_addr != 0xFFFFFFFF) ? bootloader_addr : (code_sz * page_sz);

    return end_addr - (FDS_PHY_PAGES_RESERVED * FDS_PHY_PAGE_SIZE * sizeof(uint32_t));
    }

    And here is flash_bound_set: 

    static void flash_bounds_set(void)
    {
    uint32_t flash_size = (FDS_PHY_PAGES * FDS_PHY_PAGE_SIZE * sizeof(uint32_t));
    m_fs.end_addr = flash_end_addr();
    m_fs.start_addr = m_fs.end_addr - flash_size;
    }

  • Yes, they are the same, but if you follow the definitions, you see BOOTLOADER_START_ADDR at the end of the line:

    #define BOOTLOADER_ADDRESS      ((*(uint32_t *)MBR_BOOTLOADER_ADDR) == 0xFFFFFFFF ? *MBR_UICR_BOOTLOADER_ADDR : *(uint32_t *)MBR_BOOTLOADER_ADDR) /**< The currently configured start address of the bootloader. If 0xFFFFFFFF, no bootloader start address is configured. */

    /** @brief Location (in the flash memory) of the bootloader address. */
    #define MBR_BOOTLOADER_ADDR      (0xFF8)

    /**
     * @brief Location of the pointer to the start of the bootloader.
     *
     * See also @c BOOTLOADER_ADDRESS in @c app_util.h.
     */
    #define NRF_UICR_BOOTLOADER_START_ADDRESS       (MBR_BOOTLOADER_ADDR)



        uint32_t  m_uicr_bootloader_start_address __attribute__((at(NRF_UICR_BOOTLOADER_START_ADDRESS)))
                                                        = BOOTLOADER_START_ADDR;


  • Hi Declan, 

    I'm sorry my mistake. I was confused with a similar case with fds in the application. In your case you are using it within the bootloader. 

    In the bootloader BOOTLOADER_START_ADDR is defined as (CODE_START)

    And CODE_START is defined as 

    #define CODE_START ((uint32_t)&Load$$LR$$LR_IROM1$$Base) 

    Which matches with the start address of the bootloader (address 0x78000) 

    We need to check why it points to 0x26000 in your case ? 

Related