sd_flash_* operations no longer working after SDK(14.2) -> (15.2) and SD(5.1) -> (6.1.1) migration

Hi there,

I'm in the midst of migrating between SDK14.2->15.2, and SD 5.1->6.1

I'm calling sd_flash_write() and sd_flash_page_erase() before enabling the SoftDevice with no issue, however, once I enable the softdevice these functions return NRF_ERROR_BUSY indefinitely. This happens even though I have not started advertising. I have tried calling it 10,000 times with a delay of 1ms between tries, and still always get NRF_ERROR_BUSY.

I would prefer to use the SoftDevice directly (as opposed to Fstorage) to leverage it's async properties.

Do you know why this method used to work where now it does not? 

Attached is my sdk_config.h if that helps

Thanks,

Matthew

Parents
  • Hi,

    Do the first call to sd_flash_write()/sd_flash_page_erase() after enabling the softdevice return successfully?

    Are you processing the events from the softdevice? E.g through the Softdevice handler library, etc?

    Are you calling the functions from main context or interrupt context? Can you post a minimal code showing how we can reproduce this problem?

    I would prefer to use the SoftDevice directly (as opposed to Fstorage) to leverage it's async properties.

    Fstorage is also using the sd_flash* API in its Softdevice backend. It is not possible to write/erase the flash through NVMC peripheral when the softdevice is enabled, without using the Softdevice APIs.

    Best regards,
    Jørgen

  • Hi,

    I tried adding your code examples to the ble_app_beacon example in nRF5 SDK v15.2.0, by replacing the ble_stack_init function and removing the advertising parts. With this configuration, I'm not getting the NRF_ERROR_BUSY return code from the second call to sd_flash_page_erase(). This leads me to believe there is something else in your application causing this behavior. Attaching the example project for reference: ble_app_sd_flash_sdk15.2.0_s132_v6.1.1.zip

    Matthew Leroy Stephens said:
    In regards to fstorage, it's my understanding that nrf_fstorage_write() enqueues a flash write operation onto the application event queue (which is eventually serviced through a call to app_sched_execute())

    Fstorage does not use the application scheduler library. It has its own queue implementation, which enables you to schedule multiple flash operations from the application, without having to wait for the Softdevice to complete the previous operation, but it does not depend on the application to execute the scheduled operations. When you call the fstorage write or erase functions, the operation is added to the queue, but the function will immediately call the queue_start() function to start processing the queued operations. When a flash operation is completed, fstorage library will be notified by the Softdevice flash event, and fstorage will start the next queued flash operation.

    Matthew Leroy Stephens said:
    whereas sd_flash* directly kicks of a flash operation (blocking if SD enabled, async if not).

    The softdevice will accept a requested flash operation, but it will schedule the execution between other BLE activity. See Flash memory API and Scheduling. This implies that it is not safe to use a delay set to the maximum time for the flash operation according to the product specification, you need to wait for the NRF_EVT_FLASH_OPERATION_SUCCESS/NRF_EVT_FLASH_OPERATION_ERROR events before starting a new operation.

    Best regards,
    Jørgen

  • Thanks for you detailed response,

    Other than a configuration issue in sdk_config.h, I don't know how my application could be causing this behavior. I made a test main() which only runs the code snippets I shared, so nothing else is happening. Are there any relevant configuration macros in sdk_config.h that could be causing this?

    I also went ahead and tried registering a SDH_SOC observer to print some output when the FLASH_OPERATION_* event is generated, but it never runs.

    void soc_handler(uint32_t evt_id, void * p_context)
    {
    //This never prints, soc_handler never called?
      UART_CRITICAL_PRINTF("soc_handler evt_id:%d", evt_id); 
    }
    
    NRF_SDH_SOC_OBSERVER(obs, 1, soc_handler, NULL);

    It seems like the FLASH_OPERATION event is never being generated so the SD always believes it's busy, returning the error that I'm seeing.

    Thanks

  • Looks like I found a workaround?

    If I create a 1000 attempt retry loop, and call sd_evt_get after attempting to call sd_flash*, the next time I attempt sd_flash*, it works.

        for (uint16_t i = 0; i < 1000; i++)
        {
          err_code = sd_flash_page_erase(page_to_erase + i);
          if (err_code == NRF_SUCCESS)
            break;
    
          uint32_t evt = 0;
          sd_evt_get(&evt);
          nrf_delay_ms(1);
        }

    The flash operations in my application as critical, so I'm interested in reason why these functions are behaving this way.

    Thanks

  • Do sd_evt_get() return NRF_SUCCESS or NRF_ERROR_NOT_FOUND? Does your "workaround" also work if you do not call sd_evt_get() inside the loop? Or if you only call sd_evt_get() inside the loop?

Reply Children
No Data
Related