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

sd_flash_page_erase error code SUCCESS, but flash erase fail

Hi,

I try to erase 0x7F000 bootloader setting and reset MCU, then jump into bootloader,

let bootloader checked the bootloader setting CRC error, and force to execute OTA DFU.

Question:

I confirm that I have execute below function(sd_flash_page_erase).

Although erase flash function return success, some time the page of 0x7F000 did not erase success.

I insert debug message in bootloader, and J-Link Commander to read 0x7F000, it did not erase success some time.

    do {
        err_code = 0xFFFFFFFF;
        SEGGER_RTT_WriteString(0, "\npE");
        err_code = sd_flash_page_erase(0x7F);
        DebugShow4B(err_code);
        SEGGER_RTT_WriteString(0, "Eq\n");
	}
    while(err_code != NRF_SUCCESS);

Thanks a lot

Parents
  • When sd_flash_page_erase() returns NRF_SUCCESS, that only means that the erase request was successfully submitted to the SoftDevice. It does _not_ mean that the erase operation has actually been completed yet.

    When the erase operation completes, the SoftDevice will generate an event interrupt, and you must call sd_evt_get() to consume it. The event code will be NRF_EVT_FLASH_OPERATION_SUCCESS if the flash erase completes successfully, or NRF_EVT_FLASH_OPERATION_ERROR if it doesn't. You must wait until this event is generated and consume it with sd_evt_get() in order to know that the flash sector has actually been erased.

    -Bill

  • How about I read the data from page address to confirm the erasing process was success?

        #define BTL_SETTING_ADDR  0x7F000
        
        do {
                err_code = 0xFFFFFFFF;
                SEGGER_RTT_WriteString(0, "\npE");
                err_code = sd_flash_page_erase(BTL_SETTING_ADDR);
                DebugShow4B(err_code);
                SEGGER_RTT_WriteString(0, "Eq\n");
        	}
            while((*((uint32_t *)BTL_SETTING_ADDR) != 0xffffffff));

  • I'm not sure that will work. If you look at the NVMC documentation (in the nRF52832 or nRF52840 manual), you'll see that there is an NVMC->CONFIG register where you can set the flash to read enable, write enable or erase enable. The SoftDevice takes over control of the NVMC when it's running which is why you have to use the sd_flash_page_erase() API when the SoftDevice is active instead of programming the NVMC directly.

    Once you call sd_flash_page_erase(), the SoftDevice will set NVMC->CONFIG to enable the erase operation, and I'm not sure if it's ok to read from the flash until the operation completes and it sets NVMC->CONFIG back to the "read enable" state again.

    Also, the SoftDevice expects you to consume everything that it puts into its event queue: if the event queue goes unserviced for long enough, I think the SoftDevice may eventually trigger an assert.

    If you want to skip setting up the interrupt handler, it may be enough to call sd_evt_get() in loop, e.g.:

    uint32_t evt = 0;
    
    while (1) {
    
        sd_evt_get (&evt);
    
        if (evt == NRF_EVT_FLASH_OPERATION_SUCCESS || evt == NRF_EVT_FLASH_OPERATION_ERROR)
            break;
    }

    Also, sd_flash_page_erase() takes a flash sector number (0x7F), not an address like BTL_SETTING_ADDR, as you've written above.

    -Bill

Reply
  • I'm not sure that will work. If you look at the NVMC documentation (in the nRF52832 or nRF52840 manual), you'll see that there is an NVMC->CONFIG register where you can set the flash to read enable, write enable or erase enable. The SoftDevice takes over control of the NVMC when it's running which is why you have to use the sd_flash_page_erase() API when the SoftDevice is active instead of programming the NVMC directly.

    Once you call sd_flash_page_erase(), the SoftDevice will set NVMC->CONFIG to enable the erase operation, and I'm not sure if it's ok to read from the flash until the operation completes and it sets NVMC->CONFIG back to the "read enable" state again.

    Also, the SoftDevice expects you to consume everything that it puts into its event queue: if the event queue goes unserviced for long enough, I think the SoftDevice may eventually trigger an assert.

    If you want to skip setting up the interrupt handler, it may be enough to call sd_evt_get() in loop, e.g.:

    uint32_t evt = 0;
    
    while (1) {
    
        sd_evt_get (&evt);
    
        if (evt == NRF_EVT_FLASH_OPERATION_SUCCESS || evt == NRF_EVT_FLASH_OPERATION_ERROR)
            break;
    }

    Also, sd_flash_page_erase() takes a flash sector number (0x7F), not an address like BTL_SETTING_ADDR, as you've written above.

    -Bill

Children
  • Agree, the flash API should not be called in a loop like this.

    wpaul said:
    Once you call sd_flash_page_erase(), the SoftDevice will set NVMC->CONFIG to enable the erase operation, and I'm not sure if it's ok to read from the flash until the operation completes and it sets NVMC->CONFIG back to the "read enable" state again.

    The CPU will be halted during the erase.

    wpaul said:
    If you want to skip setting up the interrupt handler, it may be enough to call sd_evt_get() in loop, e.g.:

     It's ok to do this for testing, but note that it may cause other modules to lose SoC events from the Softdevice (e.g., fds/fstorage).  It's better to use the softdevice handler to forward the Softdevice events.

Related