nrf_storage_erase crashes but not when debugger is connected.

Hi,

We are developing a product with an nRF528322 that should be able to perform a DFU on an external microcontroller by receiving the firmware over BLE and then sending it to the external microcontroller over UART.

We do this by letting the nRF bootloader receive the firmware and place it in the DFU bank and the boot our firmware. In our firmware we send the firmware over UART and then invalidate the DFU bank.

Invalidating the firmware works when we have a debugger connected and logging (even if no log function is called) but when it is disconnected the firmware crashes. The crash occurs after the
call to return (p_fs->p_api)->erase(p_fs, page_addr, len, p_context);  from the function nrf_fstorage_erase

The crash location have been deduced by turning of and on some LEDS and see when a LED action does not occur. It also seems the erase function is called twice and it is during the second time it crashes.

How we invalidate the DFU bank:

https://pastebin.com/swb1VtRU

Best Regards,
Andreas

  • I have narrowed down the crash to the function nrf_nvmc_page_erase and specifically the line NRF_NVMC->ERASEPAGE = address;

    It is called twice. First time address = 0x7F000, second time 0x7E000. This is true for when having a debugger attached and detached. The address of NRF_NVMC->ERASEPAGE is also the same in both cases. Confirmed with if statemements and LEDS. But for some reason the code never goes past the second time that line of code is called.

  • Could it be that the bootloader dfu settings backup( addr 0x7E000) is HW locked and causes a permanent CPU halt since the erase fails?

    Note that: the software check if the address is a forbidden during a "settings_write" is removed as the dfu settings backup is "forbidden" and we need to re-write it to invalidate the firmware in the DFU bank.

  • I think you are closing in. Without having looked too close at where you are trying to erase the page. Why it doesn't happen when the debugger is connected I am not sure. But it should be fairly easy to test. Try opening your bootloader project (which I assume is the pca10040_s132_ble project), and search for "nrf_bootloader_flash_protect". There you will see all the flash regions that the bootloader will protect. I guess the quickest check is to just comment out all the content inside nrf_bootloader_flash_protect() (implemented in nrf_bootloader_app_start_final.c), and make it return NRF_SUCCESS. But it looks like the call that protects the bootloader settings (0x7E000) is line 169 in nrf_bootloader_app_start_final.c, inside nrf_bootloader_app_start_final();

    If it doesn't work to either remove that line (remember to also remove the error check directly after that line), then we can start looking elsewhere. Does your custom board have an LFXTAL (32KHz)? If not, have you taken this into account in both your bootloader's and application's sdk_config.h file?

    Best regards,

    Edvin

  • Yup, that was it. Removing the line 169 in nrf_bootloader_app_start_final.c did it. Cheers!

    Very strange behavior though. Why is flash protect ignored when the debugger is connected? And should it halt the CPU and fail silently?

    Best Regards

  • When you are trying to write to or erase a page that is protected, the device will hardfault. Unless you have a hardfault handler in your application, the device will reset (unless you are doing a debug session. I don't remember exactly how this works, but it may be that you need to power cycle the device after you did a debug session to reset this behavior properly). 

    Are you sure it halted the CPU silently? I don't know how you set up your test, but could it be that it ran up to that point, then hardfaulted, restarted the application, and ran up to that point again? It may not be so obvious without debugging access.

    The reason it doesn't happen when you are in a debug session is that there is a register in the BPROT (flash block protection module) that says DISABLEINDEBUG. By default, this has the reset value 1, so unless you actively changed this, then you can still access/modify the protected flash blocks when you are doing a debug session. 

    I discussed this behavior with a colleague, and he also told me I should make you aware of that the default bootloader behavior is that if the bootloader settings page is different from the backup page, then the bootloader will restore the settings page from the backup page on the next reboot. So either, you need to make the same changes to both the settings page and backup page, or you can try to enable NRF_BL_DFU_ALLOW_UPDATE_FROM_APP and NRF_DFU_IN_APP in your bootloader's sdk_config.h file. 

    Best regards,

    Edvin

Related