Bank 1 DFU settings empty in bootloader after custom DFU in app

Hi

I am currently developing a custom dfu in my app in background through LTE communication. I am working with nRF5 SDK 17.0.2, softdevice s132 7.2.0 and nRF52832.

I am using the secure bootloader given in the SDK in which I set NRF_BL_DFU_ALLOW_UPDATE_FROM_APP to 1.

So far I've used nrf_dfu_req_handler module to write first init packet and then new firmware to flash memory in bank 1.

In the app everything seems to be working well: the signature from the init packet is successfully verified, init packet is written to flash, then firmware is written to flash through several objects and it ends with postvalidation. Here are the last logs I get before resetting to bootloader. There are my own logs starting with [] in the middle.

If I understand well, at the end of firmware update in bank1, the app "postvalidation" just writes new dfu settings to flash memory in order for the bootloader to make the actual postvalidation and activate this new image to copy it to bank0.

I have checked that at the end the debugger goes through the line s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_1; in function postvalidate() in nrf_dfu_validation.c

When DFU is finished I request a software reset by calling nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_RESET); like in the example of background DFU you have made (nRF_SDK_15.3.0_background_dfu_3 found on devzone).

After the reset, the bootloader starts and launches the app in bank0 instead of bank1.

In the bootloader when I reach the section below I have noticed that s_dfu_settings.bank_current is 0 so that postvalidate() function is not executed.

ret_val = nrf_dfu_settings_init(false);
    if (ret_val != NRF_SUCCESS)
    {
        return NRF_ERROR_INTERNAL;
    }

    #if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
    // Postvalidate if DFU has signaled that update is ready.
    if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1)
    {
				postvalidate();
    }
    #endif

    // Check if an update needs to be activated and activate it.
    activation_result = nrf_bootloader_fw_activate();

I have tried to put a breakpoint right after nrf_dfu_settings_init(false); function and noticed that s_dfu_settings is all empty for bank1 : 

Maybe I am mistaken but I thought that s_dfu_settings in the bootloader would be the same value as set in the app at the end of custom DFU process. So I would expect bank_current to be NRF_DFU_CURRENT_BANK_1.

1. Is my understanding of postvalidation ok ? The app dfu modules write the necessary settings to flash for the bootloader to postvalidate, activate and swap bank1 and 0. The postvalidation is made in the bootloader since I set NRF_DFU_IN_APP to 1 in my app sdk_config.h.

2. Why is s_dfu_settings empty for bank1 in the bootloader ?

3. More generally, do you have an idea why my bootloader does not copy the new firmware from bank1 to bank0 ?

Best regards

Parents
  • Hi,

    1. Is my understanding of postvalidation ok ? The app dfu modules write the necessary settings to flash for the bootloader to postvalidate, activate and swap bank1 and 0. The postvalidation is made in the bootloader since I set NRF_DFU_IN_APP to 1 in my app sdk_config.h.

    Yes, this is correct. I do not see all you have done, but I wonder if the issue here is related to the backup and restoration of the bootloader settings page. The current bank is overwritten as you can see from the implementation of settings_forbidden_parts_copy_from_backup() in components/libraries/bootloader/dfu/nrf_dfu_settings.c. Based on what you write, it could be that it would be enough to remove the line that copies the bank_current from the backup. Byt normally the bootloader would handle this for you, as long as you have copied the init packet to the bootloader settings (this is not overwritten by the backup when you have NRF_BL_DFU_ALLOW_UPDATE_FROM_APP enabled).  See this post for more on that.

    2. Why is s_dfu_settings empty for bank1 in the bootloader ?

    If s_dfu_settings.bank_1 was not empty before, then the only reason I can think of that would make it empty is if nrf_dfu_bank_invalidate() was called with it's address. And this happens close to the end of postvalidate().

    3. More generally, do you have an idea why my bootloader does not copy the new firmware from bank1 to bank0 ?

    I believe it is because of the backup restoration explained above, which means that the active bank will be reverted to bank0.

    PS: I recommend that you use nRF5 SDK 17.1.0 instead of 17.0.2, as that has support for the latest revision of the nRF52832 (alternatively you must update the MDK as explained in IN142).

  • Hi,

    Thanks for the reply.

    After looking closer, the bank_1 part of struct s_dfu_settings is also empty in my app when dfu is completed so I guess it is normal to get it empty from the bootloader after the reset. My problem is just for bank_current.

    As you mention it I confirm that my app successfully copies the init packet to the bootloader settings at the beginning of DFU.

    I've investigated a little more and the issue does not seem to come from settings_forbidden_parts_copy_from_backup() function in the bootloader.

    I have looked to flash memory closer and at the bootloader settings address 0x0007F000 data are not the same when the app ask for reset and when the bootloader starts. It seems that data is lost in between.
    When I call nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_RESET); in the app to reset right after custom DFU, the bank_current value at address 0x0007F014 is 0x01. But at the beginning of the bootloader (first instruction of main()) the bank_current value at address 0x0007F014 is 0x00.

    So I was wondering if bootloader settings were considered to be at the same flash memory address in the app and in the bootloader but apparently in both projects m_dfu_settings_buffer[] is set at address 0x0007F000. Thus both projects are reading/writing the same flash area.

    What can happen during the reset that can change flash in bootloader settings section ?

    I also tried to migrate the SDK to 17.1.0 but it does not solve the issue.

    BR

  • Hi,

    TOCGRE said:
    What can happen during the reset that can change flash in bootloader settings section ?

    The reset itself does not cause any writing to flash, so it would have to be either the application before the reset, or the bootloader after. And the bootloader will normally only write to bootloader settings during a DFU update, and if some of the "forbidden" parts have been changed. If this change does not happen during settings_forbidden_parts_copy_from_backup(), perhaps you can experiment with setting a breakpoint (or an eternal loop to prevent further execution or something else) in the bootloader and moving it around to try to narrow down where the data is changed (there are not that many part of the bootloader that writes to the bootloder settings page)?

  • Hi,

    I've found the issue : the nrf52832 does not behave the same way with or without debugger attached when logs are enabled in release config.

    As my app size is  too big in debug config to do a dual bank DFU, I just added some logs to the release config to make the app smaller and enable dual bank DFU.

    When debugger is attached, the whole dfu process goes on without any error and new bootloader settings are written correctly. However if I attach debugger in the app project the program gets stuck when resetting to the bootloader (I still don't know why). So the only way I found to debug the bootloader was to wait for the app to make DFU without attaching the debugger and attach the debugger as soons as the bootloader starts (supposedly at the end of the DFU process in app) thanks to a LED blink. But when running app without attaching debugger, I discovered that an error occurs and leads to a reset (which I thought was the one at the end of successful DFU process). Thus the bootloader I'm debugging does not find new firmware info in bootloader settings. Hence the bootloader starts and launches the current app in bank0.

    I found that this error occuring during the in app DFU was due to logs. So I just disabled the logs in release config and copying the bank1 to bank0 and jumping to it works !

    So I don't know exactly what the problem is but I guess that mayby logs in release are in conflict with dfu modules or share a common area in flash...

    Anyway thanks for helping me

    BR

Reply
  • Hi,

    I've found the issue : the nrf52832 does not behave the same way with or without debugger attached when logs are enabled in release config.

    As my app size is  too big in debug config to do a dual bank DFU, I just added some logs to the release config to make the app smaller and enable dual bank DFU.

    When debugger is attached, the whole dfu process goes on without any error and new bootloader settings are written correctly. However if I attach debugger in the app project the program gets stuck when resetting to the bootloader (I still don't know why). So the only way I found to debug the bootloader was to wait for the app to make DFU without attaching the debugger and attach the debugger as soons as the bootloader starts (supposedly at the end of the DFU process in app) thanks to a LED blink. But when running app without attaching debugger, I discovered that an error occurs and leads to a reset (which I thought was the one at the end of successful DFU process). Thus the bootloader I'm debugging does not find new firmware info in bootloader settings. Hence the bootloader starts and launches the current app in bank0.

    I found that this error occuring during the in app DFU was due to logs. So I just disabled the logs in release config and copying the bank1 to bank0 and jumping to it works !

    So I don't know exactly what the problem is but I guess that mayby logs in release are in conflict with dfu modules or share a common area in flash...

    Anyway thanks for helping me

    BR

Children
No Data
Related