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

Sharing free flash memory region between Flash Data Storage and DFU

Hello,

We're intending to use the free flash region for two purposes: Flash Data Storage and DFU. The Flash Data Storage will be allocated a large number of pages (100 pages, around 400kB). We wish to use dual bank DFU so the application image will overlap with the region of free flash allocated to FDS. Any attempts to perform a DFU would corrupt the FDS region of memory, and so the FDS would not initialize properly (returning FDS_ERR_NO_PAGES).

It was suggested that we fully erase the FDS pages after a DFU, but there does not appear to be a clear all function provided by the FDS library. I assume we would have to manually call nrf_fstorage_erase and specify the starting address of the FDS flash region? Are there any methods provided by the library that can perform this safely?

Thank you for your assistance.

Parents
  • Hi,

    I guess this can be done in various ways, but maybe something like this (this should work both if softdevice is enabled or not):

    static inline void wait_for_flash_ready(void)
    {
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;}
    }
    
    void nrf_nvmc_page_erase(uint32_t address)
    {
        // Enable erase.
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
        __ISB();
        __DSB();
    
        // Erase the page
        NRF_NVMC->ERASEPAGE = address;
        wait_for_flash_ready();
    
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        __ISB();
        __DSB();
    }
    
    void fds_format(void)
    {
    
      uint32_t bootloader_addr;
      if(NRF_UICR->NRFFW[0] != 0xFFFFFFFF)
        bootloader_addr = NRF_UICR->NRFFW[0];
      else
        bootloader_addr = (NRF_FICR->CODESIZE * NRF_FICR->CODEPAGESIZE);
    
      uint32_t page_size = NRF_FICR->CODEPAGESIZE;
      uint32_t fds_start_addr = bootloader_addr - (page_size * FDS_VIRTUAL_PAGES);
    
      __disable_irq();
    
      // Disable sandboxing of NVMC if softdevice is enabled
      NRF_MWU->PREGION[0].SUBS &= ~(MWU_PREGION_SUBS_SR30_Include << MWU_PREGION_SUBS_SR30_Pos);
      __DSB(); // barrier to ensure register is set before accessing NVMC. 
    
      for (uint16_t i = 0; i < FDS_VIRTUAL_PAGES; i++)
        nrf_nvmc_page_erase(fds_start_addr + i * page_size);
    
      NVIC_SystemReset();
    }
    

    Best regards,
    Kenneth

Reply
  • Hi,

    I guess this can be done in various ways, but maybe something like this (this should work both if softdevice is enabled or not):

    static inline void wait_for_flash_ready(void)
    {
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {;}
    }
    
    void nrf_nvmc_page_erase(uint32_t address)
    {
        // Enable erase.
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
        __ISB();
        __DSB();
    
        // Erase the page
        NRF_NVMC->ERASEPAGE = address;
        wait_for_flash_ready();
    
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
        __ISB();
        __DSB();
    }
    
    void fds_format(void)
    {
    
      uint32_t bootloader_addr;
      if(NRF_UICR->NRFFW[0] != 0xFFFFFFFF)
        bootloader_addr = NRF_UICR->NRFFW[0];
      else
        bootloader_addr = (NRF_FICR->CODESIZE * NRF_FICR->CODEPAGESIZE);
    
      uint32_t page_size = NRF_FICR->CODEPAGESIZE;
      uint32_t fds_start_addr = bootloader_addr - (page_size * FDS_VIRTUAL_PAGES);
    
      __disable_irq();
    
      // Disable sandboxing of NVMC if softdevice is enabled
      NRF_MWU->PREGION[0].SUBS &= ~(MWU_PREGION_SUBS_SR30_Include << MWU_PREGION_SUBS_SR30_Pos);
      __DSB(); // barrier to ensure register is set before accessing NVMC. 
    
      for (uint16_t i = 0; i < FDS_VIRTUAL_PAGES; i++)
        nrf_nvmc_page_erase(fds_start_addr + i * page_size);
    
      NVIC_SystemReset();
    }
    

    Best regards,
    Kenneth

Children
Related