partial erase vs BLE stack

Hello,

I have been developed a log system in the internal flash. To do that I have been using the nrf storage library.

My first problem came up when I tried to use nrf_fstorage_erase for one single page; this operation is blocking the interrupts of some sensors, so I am losing some data. I calculated how much was the elapsed time during which I am blocked and I obtained around 150 ms (which is higher than the 85 ms that I found for a single page erase in the datasheet) which is strange to me.

As I cannot afford to lose the data during 150 ms, I have checked the partial erase feature. Following this idea, I developed the following function:

static void partial_erase(nrf_fstorage_t const* p_fstorage, uint32_t p_flash_start, uint32_t num_pages)
{
    ret_code_t err_code;
    
    /* Check that the address and size are aligned to the flash page size */
    if (p_flash_start % FLASH_PAGE_SIZE) {
        /* Handle unaligned address or size */
    }
  
    /* Enable the write access to the flash */
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);
        
    /* Configure the partial erase duration */
    NRF_NVMC->ERASEPAGEPARTIALCFG = PARTIAL_ERASE_TIME_MS;

    /* Erase the specified number of pages */
    for (uint32_t i = 0; i < num_pages; i++) {
        /* Calculate the address of the page to erase */
        uint32_t page_address = p_flash_start + (i * FLASH_PAGE_SIZE);
    
        /* Specify the address of the page to partially erase */
        NRF_NVMC->ERASEPAGEPARTIAL = page_address;

        /* Wait for the erase operation to complete */
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
//        wait_for_flash_ready(&fstorage);
    }
    
    /* Disable the write access to the flash */
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
}

The problem here is that it looks incompatible with the parallel execution of BLE stack.

I got into the function "app_error_fault_handler" right after the execution of the line:

NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);

My understanding is that there is some conflict with the parallel BLE execution and partial erase, so I updated my function disabling/enabling temporarily the ble stack in this way:

static void pause_ble()
{
    nrf_sdh_disable_request();  
}

static void resume_ble()
{
    nrf_sdh_enable_request();

    // Wait for SoftDevice to be enabled
    while (!nrf_sdh_is_enabled()) {
         __WFE();
    }
    
    // Wait for HFCLK to be started
    while (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY) != true) {}
}

static void partial_erase(nrf_fstorage_t const* p_fstorage, uint32_t p_flash_start, uint32_t num_pages)
{
    ret_code_t err_code;
    
    /* Check that the address and size are aligned to the flash page size */
    if (p_flash_start % FLASH_PAGE_SIZE) {
        /* Handle unaligned address or size */
    }

    pause_ble();
  
    /* Enable the write access to the flash */
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);
        
    /* Configure the partial erase duration */
    NRF_NVMC->ERASEPAGEPARTIALCFG = PARTIAL_ERASE_TIME_MS;

    /* Erase the specified number of pages */
    for (uint32_t i = 0; i < num_pages; i++) {
        /* Calculate the address of the page to erase */
        uint32_t page_address = p_flash_start + (i * FLASH_PAGE_SIZE);
    
        /* Specify the address of the page to partially erase */
        NRF_NVMC->ERASEPAGEPARTIAL = page_address;

        /* Wait for the erase operation to complete */
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
//        wait_for_flash_ready(&fstorage);
    }
    
    /* Disable the write access to the flash */
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);      
    
    resume_ble();
}

After this modification, I got another issue: BLE_ERROR_NOT_ENABLED after the interrupt SWI2_EGU2_IRQn is triggered. It looks like there is some BLE operation before the BLE stack is enabled, but I don't know how to prevent the SWI2_EGU2_IRQn to raise in order to avoid the error.

Could you please provide me some suggestions or corrections of my code to make partial erase and BLE stack working?

Thanks!

Parents
  • Hi, thanks for your answer.

    I have added error control to the enable/disable requests and no error is returned (so it looks like no observer is blocking my request). I have also added the wait for disabled events in my pause_ble() function. The problem is always the same, after partial_erase execution, at some point the interrupt SWI2_EGU2_IRQn is raised, then the BLE_ERROR_NOT_ENABLED is produced blocking my execution. I have checked the sdk function "nrf_sdh_disable_request" and there is a sd_softdevice_disable(); called followed by softdevice_evt_irq_disable();, so I don't understand where is this interrupt coming from and how it comes it is not disabled during this process.

    Any idea?

    Additionally, in my first tests I mentioned that I used fstorage library, but I changed to partial erase due to the high overrun in page erase (150 ms), 2 questions here:

    * Is it normal this 150 ms elapsed time for a nrf_fstorage_erase when the datasheet is marking 85 ms?

    * When I use nrf_fstorage_erase I have not such an issue in my execution, even though the execution is too long, there is no interrupt generating errors during the process. What is nrf_fstorage_erase doing that I don't do with my approach?

    Thanks.

    Juan

Reply
  • Hi, thanks for your answer.

    I have added error control to the enable/disable requests and no error is returned (so it looks like no observer is blocking my request). I have also added the wait for disabled events in my pause_ble() function. The problem is always the same, after partial_erase execution, at some point the interrupt SWI2_EGU2_IRQn is raised, then the BLE_ERROR_NOT_ENABLED is produced blocking my execution. I have checked the sdk function "nrf_sdh_disable_request" and there is a sd_softdevice_disable(); called followed by softdevice_evt_irq_disable();, so I don't understand where is this interrupt coming from and how it comes it is not disabled during this process.

    Any idea?

    Additionally, in my first tests I mentioned that I used fstorage library, but I changed to partial erase due to the high overrun in page erase (150 ms), 2 questions here:

    * Is it normal this 150 ms elapsed time for a nrf_fstorage_erase when the datasheet is marking 85 ms?

    * When I use nrf_fstorage_erase I have not such an issue in my execution, even though the execution is too long, there is no interrupt generating errors during the process. What is nrf_fstorage_erase doing that I don't do with my approach?

    Thanks.

    Juan

Children
  • Are you triggering the flash erase from main or interrupt context? If interrupt, what is the interrupt priority of this handler? You are not using app_scheduler in your application/for the SoftDevice handler library? Could you check which events are generated? Is it related to flash operations?

    Juan Lahera said:
    * Is it normal this 150 ms elapsed time for a nrf_fstorage_erase when the datasheet is marking 85 ms?

    If you are using the SoftDevice backend for fstorage, the time it will take to complete the flash operation depends on the SoftDevice activity and scheduling. If there is no activity, the operations can complete faster, but it can also never succeed if there is too much activity, see Flash memory API.

    Juan Lahera said:
    * When I use nrf_fstorage_erase I have not such an issue in my execution, even though the execution is too long, there is no interrupt generating errors during the process. What is nrf_fstorage_erase doing that I don't do with my approach?

    If you use the Softdevice backend for Fstorage, it will use the SoftDevice API to perform the erase operation. The SoftDevice flash API is still available if the SoftDevice is disabled: "If the SoftDevice is not enabled no event will be generated, and this call will return NRF_SUCCESS when the erase has been completed".

Related