Unable to write to specific area of flash shared by custom bootloader and BLE application

Hello Nordic Team,

I am working on an application which has custom bootloader and BLE application firmware. The bootloader code resides in flash area 0xE0000 - 0xEDFFF, application firmware code resides in 0x27000 - 0xDFFFF. There is some data that is used by both application and bootloader and this is placed in flash area 0xEE000 - 0xEFFFF. Data which is used only by application is placed in flash area 0xF0000 - 0xF5FFF. 

For writing to flash in bootloader, I am using nrf_nvmc_write_words() which works as there is no Softdevice running in bootloader. For writing to flash in BLE application firmware, I am using nrf_fstorage_write() with fstorage api pointing to nrf_fstorage_sd and wait until flash is not busy using this function: 

static void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage)
{
    /* While fstorage is busy, sleep and wait for an event. */
    while (nrf_fstorage_is_busy(p_fstorage))
    {

    }
}

Writing to flash in application firmware works fine for flash area 0xF0000. However, when trying to write to area 0xEE000 from application, the program is stuck forever in wait_for_flash_ready(). Could you please let me know what could be the cause of this issue?

Regards,

Anusha

Parents
  • Hi Anusha,

    Without knowing much about your application there are a few potential issues that come to mind:

    • Could it be that the flash operation is blocked by same or higher priority interrupts so that the flash write operation(s) never happen or that prevents you from getting the events about it's completion?
    • Do you have a lot of Bluetooth activity and tight connection parameters? If so, it could happen that the SoftDevice never gets a chance to process flash write operations (see SoftDevice timing-activities and priorities).
    • It is also worth checking that the way you write to flash when using a SoftDevice via fstorage is sensible, for instance by looking at the fstorage sample.

    If you don't make progress, then perhaps you can share more information about your application, how you write to flash, and what else is happening at the same time? Also, what have you learned when debugging?

    Regards,

    Einar

  • Hi Einar,

    Thanks for your response.

    Could it be that the flash operation is blocked by same or higher priority interrupts so that the flash write operation(s) never happen or that prevents you from getting the events about it's completion?

    I don't think this is the case because I am able to write successfully to memory area that starts at 0xF0000.
    The issue happens when I write some bytes of data to another flash area that starts at 0xEE000. I can see that it is able to write the bytes in the area 0xEE000 but after writing, nrf_fstorage_is_busy() is busy forever.

    Do you have a lot of Bluetooth activity and tight connection parameters? If so, it could happen that the SoftDevice never gets a chance to process flash write operations (see SoftDevice timing-activities and priorities).

    I am performing the flash write operation after enabling BLE SoftDevice (i.e much later after nrf_sdh_ble_enable()). So, there is no BLE activity such as scanning or connections. 

    It is also worth checking that the way you write to flash when using a SoftDevice via fstorage is sensible, for instance by looking at the fstorage sample.

    My code for performing the flash write is based on the flash_fstorage example. One difference is that I have not defined the function nrf5_flash_end_addr_get(). This is okay, right?

    Here is some information , that could help in understanding my application:

    This is the memory layout of my application:

    Note that 0xF6000 onwards is reserved for Zigbee data as specified here: infocenter.nordicsemi.com/index.jsp and my application can use either BLE or Zigbee.

    For writing to flash, this is the code used:

    #include <string.h>
    #include "nrf.h"
    #include "nrf_fstorage_sd.h"
    
    nrf_fstorage_api_t * p_fs_api;
    
    static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
    static void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage);
    
    NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
    {
        /* Set a handler for fstorage events. */
        .evt_handler = fstorage_evt_handler,
    
        /* These below are the boundaries of the flash space assigned to this instance of fstorage.
         * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
         * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
         * last page of flash available to write data. */
        .start_addr = 0xEE000,
        .end_addr   = 0xF5FFF,
    };
    
    void flash_init(void)
    {
      p_fs_api = &nrf_fstorage_sd;
      nrf_fstorage_init(&fstorage, p_fs_api, NULL);
    }
    
    void writeToFlash(uint32_t *address, uint32_t *data, uint32_t length)
    {
      uint32_t add;
      add = (uint32_t) address;
      uint32_t len = length;
    
      if (length % sizeof(uint32_t))
      {
         len = (length + sizeof(uint32_t)) - (length % sizeof(uint32_t));
      }
      nrf_fstorage_write(&fstorage, add, data, len, NULL);
      wait_for_flash_ready(&fstorage);
    }
    
    void eraseFlash(uint32_t *address)
    {
      uint32_t pageSize = NRF_FICR->CODEPAGESIZE;
      uint32_t pageAddress = (uint32_t) address;
    
      pageAddress /= pageSize;
      pageAddress *= pageSize;
      nrf_fstorage_erase(&fstorage, pageAddress, 1, NULL);
    }
    
    static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
    {
        if (p_evt->result != NRF_SUCCESS)
        {
            PRINT( "ERROR while executing an fstorage operation.\r\n");
            return;
        }
    
        switch (p_evt->id)
        {
            case NRF_FSTORAGE_EVT_WRITE_RESULT:
            {
                PRINT("Wrote %d bytes at address 0x%x.\r\n", p_evt->len, p_evt->addr);
            } break;
    
            case NRF_FSTORAGE_EVT_ERASE_RESULT:
            {
                PRINT("Erased %d page from address 0x%x.\r\n", p_evt->len, p_evt->addr);
            } break;
    
            default:
                break;
        }
    }
    
    static void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage)
    {
        /* While fstorage is busy, sleep and wait for an event. */
        while (nrf_fstorage_is_busy(p_fstorage))
        {
         
        }
    }

    I tried to use only application with softdevice (without bootloader) to see if I'm able to write to flash 0xEE000 but in this case also, I was facing the issue that nrf_fstorage_is_busy() is busy forever after writing first set of bytes. So, having the bootloader sharing the flash area 0xEE000 does seem to be the issue.

    Regards,

    Anusha

Reply
  • Hi Einar,

    Thanks for your response.

    Could it be that the flash operation is blocked by same or higher priority interrupts so that the flash write operation(s) never happen or that prevents you from getting the events about it's completion?

    I don't think this is the case because I am able to write successfully to memory area that starts at 0xF0000.
    The issue happens when I write some bytes of data to another flash area that starts at 0xEE000. I can see that it is able to write the bytes in the area 0xEE000 but after writing, nrf_fstorage_is_busy() is busy forever.

    Do you have a lot of Bluetooth activity and tight connection parameters? If so, it could happen that the SoftDevice never gets a chance to process flash write operations (see SoftDevice timing-activities and priorities).

    I am performing the flash write operation after enabling BLE SoftDevice (i.e much later after nrf_sdh_ble_enable()). So, there is no BLE activity such as scanning or connections. 

    It is also worth checking that the way you write to flash when using a SoftDevice via fstorage is sensible, for instance by looking at the fstorage sample.

    My code for performing the flash write is based on the flash_fstorage example. One difference is that I have not defined the function nrf5_flash_end_addr_get(). This is okay, right?

    Here is some information , that could help in understanding my application:

    This is the memory layout of my application:

    Note that 0xF6000 onwards is reserved for Zigbee data as specified here: infocenter.nordicsemi.com/index.jsp and my application can use either BLE or Zigbee.

    For writing to flash, this is the code used:

    #include <string.h>
    #include "nrf.h"
    #include "nrf_fstorage_sd.h"
    
    nrf_fstorage_api_t * p_fs_api;
    
    static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
    static void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage);
    
    NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
    {
        /* Set a handler for fstorage events. */
        .evt_handler = fstorage_evt_handler,
    
        /* These below are the boundaries of the flash space assigned to this instance of fstorage.
         * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
         * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
         * last page of flash available to write data. */
        .start_addr = 0xEE000,
        .end_addr   = 0xF5FFF,
    };
    
    void flash_init(void)
    {
      p_fs_api = &nrf_fstorage_sd;
      nrf_fstorage_init(&fstorage, p_fs_api, NULL);
    }
    
    void writeToFlash(uint32_t *address, uint32_t *data, uint32_t length)
    {
      uint32_t add;
      add = (uint32_t) address;
      uint32_t len = length;
    
      if (length % sizeof(uint32_t))
      {
         len = (length + sizeof(uint32_t)) - (length % sizeof(uint32_t));
      }
      nrf_fstorage_write(&fstorage, add, data, len, NULL);
      wait_for_flash_ready(&fstorage);
    }
    
    void eraseFlash(uint32_t *address)
    {
      uint32_t pageSize = NRF_FICR->CODEPAGESIZE;
      uint32_t pageAddress = (uint32_t) address;
    
      pageAddress /= pageSize;
      pageAddress *= pageSize;
      nrf_fstorage_erase(&fstorage, pageAddress, 1, NULL);
    }
    
    static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
    {
        if (p_evt->result != NRF_SUCCESS)
        {
            PRINT( "ERROR while executing an fstorage operation.\r\n");
            return;
        }
    
        switch (p_evt->id)
        {
            case NRF_FSTORAGE_EVT_WRITE_RESULT:
            {
                PRINT("Wrote %d bytes at address 0x%x.\r\n", p_evt->len, p_evt->addr);
            } break;
    
            case NRF_FSTORAGE_EVT_ERASE_RESULT:
            {
                PRINT("Erased %d page from address 0x%x.\r\n", p_evt->len, p_evt->addr);
            } break;
    
            default:
                break;
        }
    }
    
    static void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage)
    {
        /* While fstorage is busy, sleep and wait for an event. */
        while (nrf_fstorage_is_busy(p_fstorage))
        {
         
        }
    }

    I tried to use only application with softdevice (without bootloader) to see if I'm able to write to flash 0xEE000 but in this case also, I was facing the issue that nrf_fstorage_is_busy() is busy forever after writing first set of bytes. So, having the bootloader sharing the flash area 0xEE000 does seem to be the issue.

    Regards,

    Anusha

Children
Related