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

How to use external app firmware update

Hi,

I would like to use external app firmware to update over BLE a secondary microncontroler behind a NRF52832. I read that it's an experimental feature but it's very intersting because this avoids to implement an other mecanism in mobile application to update the other MCU.

I already developped the DFU over BLE for application, bootloader and soft device. I now try to make work the external app update.

SDK 17.0.2, SoftDevice s112

The process I imagine :

  • Run the NRF52 in DFU mode
  • Upload the external firmware (in Bank 1 to preserve app in Bank 0)
  • Once done, run boot the secondary MCU by driving GPIO (nReset/Boot)
  • Send the firmware over UART
  • Restart in normal mode

I already created a zip package using nrfutil : nrfutil pkg generate --hw-version 52 --application-version-string 1.0.0 --application XYZ_Project.hex --external-app --key-file private.key XYZ_Project.zip

where XYZ_Project.hex is a STM32 hex file.

I succeed in downloading the zip file in the NRF52 and I check the internal memory of the MCU. Everythong looks good in Bank 1 ;)

Now, I want to push the Bank 1 data to the other MCU. Searhing the code, I saw I have to implement this method :

nrf_dfu_result_t nrf_dfu_validation_post_external_app_execute(dfu_init_command_t const * p_init, bool is_trusted)

However, it's never called; I ran the code in debbuger mode and saw this code section in postvalidate function nrf_dfu_validation.c but don't really understand how it works :

#if NRF_DFU_SUPPORTS_EXTERNAL_APP
        else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)
        {
            if (!is_trusted)
            {
                // This function must be implemented externally
                ret_val = nrf_dfu_validation_post_external_app_execute(p_init, is_trusted);
            }
            else
            {
                s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_EXT_APP;
            }
        }
#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP

The method nrf_dfu_validation_post_external_app_execute is never executed (in debugger mode, I put a breakpoint on the function).

Help is welcome Smiley

  • Hi,

    Aha, I was too quick. You are right, this implementation does not make sense, so this looks like a bug in the SDK bootloader.

    You could add another field in nrf_dfu_settings_t for the external app version which you update on every successful update of the external MCU, and check against that , but it may make more sense to handle this outside of the nRF 5 bootloader (that would not give the benefit of getting an error during the DFU process though).

  • Hi,

    Me again Smiley

    I'm studiyng how to solve this problem. My first idea was to modify the nrf_dfu_settings_t to add ext_app_version field as you had suggested me.

    By the way, this involve to :

    • Modify nrf_dfu_validation.c / method postvalidate : have to add s_dfu_settings.ext_app_version valorisation during when bootloader is running.
    • Generate new bootloader settings but I have to modify nrfutil to include this new field (maybe this can work without this but not really clean)

    I'm a little bit hesitant because I don't really want to have my own SDK (the next migration could be painfull). Moreover, it's not very easy to synchronise data during massive flash process (external MCU flash and NRF52 flash - all have to be well configured).

    The last option is propagate the external app version from the other MCU to the NRF52 after the DFU process through our home made protocol based on UART. However, this not allow to manage prevalidation version during DFU process.

    Ready to share the evolves concerning the ext app in the next NRF SDK version if needed.

    Thanks a lot for the advices ;)

  • Hi,

    Thank you for the update. I do not have any further recommendations, but it is interesting to follow this and potentially useful for others that may implement something similar in the future.

  • Hi,

    Thanks Einar. Step by step the implementation progress.

    However, I face a new problem I can't see with the debugger running : once the external firmware is updated, the application have to update the Bootloader settings to invalidate the bank 1.

    To accomplish this task, I use:

    nrf_dfu_bank_invalidate(&s_dfu_settings.bank_1);
    
    uint32_t ret_val = nrf_dfu_settings_write_and_backup(NULL);
    

    However, when the debbuger is not connected, the second instruction cause a Hard Fault. Actually, I don't really know why this doesn't happen with debbuger attached (maybe some registers configured externaly).

    In the bootloader, I saw some protections like this one :

        // Size of the flash area to protect.
        uint32_t area_size;
    
        area_size = BOOTLOADER_SIZE + NRF_MBR_PARAMS_PAGE_SIZE;
        if (!NRF_BL_DFU_ALLOW_UPDATE_FROM_APP && !NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && !NRF_DFU_TRANSPORT_BLE)
        {
            area_size += BOOTLOADER_SETTINGS_PAGE_SIZE;
        }
    
        ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, area_size);
    
        if (ret_val != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Could not protect bootloader and settings pages, 0x%x.", ret_val);
        }
        APP_ERROR_CHECK(ret_val);

    As I have NRF_DFU_TRANSPORT_BLE set at 1, the Boolloader settings page don't have to be protected...

    I saw this thread : https://devzone.nordicsemi.com/f/nordic-q-a/56993/not-able-to-update-firmware-using-bootloader-sdk15-3-0 and I'm tempted to play with NRF_BL_DFU_ALLOW_UPDATE_FROM_APP (in BL sdk_config.h) and with NRF_DFU_IN_APP (in App sdk_config.h).

    I also read this : https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.2/lib_secure_boot.html The main functionalities are explained but not the consequencies of parameters settings.

    I don't want to miss something because the firmware security is very important in our product.

    Thanks a lot for the precious help ;)

    Regards

  • Hi,

    Good to hear you are making progress.

    The reason you only see this issue when not debugging is that the BPROT is disabled while debugging. (See BPROT chapter in PS for details.)

    You have to allow writing to the bootloader settings page to achieve what you want in an elegant way, and that could be done for instance by enabling NRF_BL_DFU_ALLOW_UPDATE_FROM_APP as you write.

    Regarding security in general this is probably not a significant issue, depending on your requirements. The consequence of this is that the application can rewrite the bootloader settings page, so if it has been compromised somehow, an attacker would be able to do that. However, the bootloader also has a concept of bootloader settings backup, so critical parts is backed up and any changes to that overwritten next time the bootloader runs. You can look at the implementation of settings_forbidden_parts_copy_from_backup() to see the critical parts.

Related