nRF5340 Upgrade of App and Net core firmware

Hi, 

I am using SDK 1.9.1 and nRF5340.

Scenario

I am investigating the following scenario:

  • files containing the firmware upgrade for the app and/or net cores will be initially stored in the filesystem partition (extenal flash) as they are produced during the compilation phase (app_update.bin and net_core_app_update.bin);
  • on request, the upgrade of the app or net core will start;
  • the request will be handled by the firmware running in the app core: the request will specify the file to use for the upgrade;
  • the file containing the upgrade will be first validated; if validation is passed, the file will be copy into the mcuboot_secondary partition (external flash, but at the moment internal) and MCUBoot will take over the control of this phase and perform the upgrade of the core;
  • due a bug, i cannot used the external flash to store the new image of the app and net core, so at the moment internal flash will be used; but the final goal is to use the external spi flash.

Looking in the documentation and in some tickets, I understood that one possible way to do it would be to use the DFU taget library. Here below  the pseudo-code:

uint8_t buffer[1024] = {0};

(void)fileOpen("app_update.bin", READ_MODE, handle);

(void)fileRead(handle, &buffer[0], 4);    /* read the first 4 bytes at the beginning of the upgrade bin file */

int imageType = dfu_target_img_type(const void *const &buffer[0], sizeof(buffer));

/* imageType should be 0x01,  DFU_TARGET_IMAGE_TYPE_MCUBOOT */

uint32_t fileSize = fileSize("app_update.bin"); 

int ret = dfu_target_init(imageType, fileSize, NULL);

if (ret < 0) return;
uint32_t offset = 0;
do
{
    uint32_t bytesRead = fileRead(handle, offset, &buffer[0], sizeof(buffer)); 
    ret = dfu_target_write(&buffer[0], bytesRead);
    fileSize -= bytesRead;
	offset += bytesRead;
}while ((filesize > 0) && (ret > 0)); 

if ((filesize == 0) && (ret == 0))
{
	dfu_target_done(true);
}
else
{
	dfu_target_done(false);
	dfu_target_reset();
	/*Reset the nRF5340 */
}

When the upgraded app firmware restarts, the function  boot_write_img_confirmed()  will be invoked.

Using the app nRF Connect Device Manager i am able to update both app and net core.

In my actual project i have defined only mcuboot_secondary partition.

I can see that with the app is possible to swap the firmware, instead with the netcore is not.

Questions:

  1. is the reported approach correct ? If not, could you kindly indicate an example that suites my scenario ?
  2. Can it work also for the network core ? How do i specify the core to be updated ? Basically, doing the same thing that nRF Connect Device Manager does.
  3. Is there a function that perform the validation of the bin files before being copy in the DFU target ?
  4. I saw that there is DFU multi-image library. is there any example using that ? is the zip file produced during the compilation that need to be sent to the DFU target? 

Thanks in advance for your kind help.

  • is the reported approach correct ? If not, could you kindly indicate an example that suites my scenario ?

    It seems good. As long as you put the app_update.bin or the net_core_app_update.bin into the secondary flash partition, mcuboot will handle the rest. Based on the reset addr it will decide whether it is a netcore update or an appcore update and take the appropriate action.

    Can it work also for the network core ? How do i specify the core to be updated ? Basically, doing the same thing that nRF Connect Device Manager does.

    Actually, all you need to do is to put net_core_app_update.bin into secondary flash, and mcuboot will handle the rest.

    Is there a function that perform the validation of the bin files before being copy in the DFU target ?

    I did provide a similar answer in another private ticket. In that case mcumgr was used, and I explained how to do some verification of the .bin file from the computer as well as from the chip. I'll copy it in here. Let me know if this is not what you asked about:

    "The mcumgr tool does not have this functionality. If you would like to do some verification from the computer, you could use Image tool (located in <ncs>/bootloader/mcuboot/scripts) to verify the binary file. Use imgtool verify:"

    @$ imgtool verify -h
    Usage: imgtool verify [OPTIONS] IMGFILE
    
      Check that signed image can be verified by given key
    
    Options:
      -k, --key filename
      -h, --help          Show this message and exit.

    "As said the mcumgr is quite dumb and pretty much only writes the image to the secondary slot (with one exception), with no checks on it. The verification is done by mcuboot, when mcuboot tries to swap images. The exception is when checking for image address is enabled, so that an image with an incorrect boot adress would not get uploaded, because the image may be still be verified by mcuboot and brick the device - but this needs to be enabled and special TLV needs to be added with the start image address using the imgtool.

    Also topic of image verification is quite broad and may mean anything from signature, version, CPU, board revision, device purpose, nearly anything - and mcuboot currently only supports signatures, versions and some other basic checks that are rather related to correctness of an image than it's purpose.

    If you have some additional conditions the img needs to fulfill, you can try providing an own callback img_mgmt_upload_cb that allows to do some additional checks on received image chunk, after mcumgr has already accepted it as valid but not yet written."

    I saw that there is DFU multi-image library. is there any example using that ? is the zip file produced during the compilation that need to be sent to the DFU target?

    I'm not too familiar with simultaneous multi image DFU, however it makes sense to update both the netcore and appcore simultaneously if Bluetooth is affected, for changes that is related to the Bluetooth communication between the chips. You could take a look at the Machine Learning application and the Thingy:53 configuration, it demonstrates how to do multi image DFU. Use the file dfu_application.zip to do multi image DFU.

    Let me know if anything is unclear, and I will try to clarify or investigate further.

    Best regards,

    Simon

  • Hi Simon,

    thanks for the detailed information and sorry for my late feedback.

    Regarding the code, what it was missing was the allocation for the mcuboot buffer: unfortunately dfu_target_mcuboot_set_buf is not part of the single image DFU library so i noticed that i had to add it only when the fw crashed and the assert told me to invoke this function.

    My configuration place the mcuboot_secondary in the EXTERNAL FLASH, for both the app and net core.

    In order to have it properly executed, i had to introduce the patch in the loader.c for the MCUboot reported in these links: link1 and link2.

    Neverteless, the patched MCUBoot works ONLY FOR THE APP CORE: having the netcore new image in the external flash causes a bus fault:

    #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS)
            /* If the update is valid, and it targets the network core: perform the
             * update and indicate to the caller of this function that no update is
             * available
             */
            if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) {
                struct image_header *hdr = (struct image_header *)secondary_fa->fa_off;
                uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size;
                uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); /*!!! BUS FAULT !!! */
                uint32_t fw_size = hdr->ih_img_size;
                BOOT_LOG_INF("Starting network core update");
                rc = pcd_network_core_update(net_core_fw_addr, fw_size);
    

    I saw that the same thing was reported in this ticket

    Is a solution planned for the netcore with this configuration (that is one only mcuboot seconday in the external flash) ? Or are there any configuration parameters that i am missing to enable such of management ?

    Thanks in advance !

    Kind regards

    Riccardo 

  • As a temporary fix, could you try to modify loader.c as the customer did in this reply:  RE: nRF5340 non-simultaneous netcore updates with external QSPI ,it seems like he was able to perform a netcore update with the secondary slot in external flash with that modifications:

    " I can now perform net and app core updates one at a time from a single secondary slot on the external qspi in a way that still allows for reversion of the application core."

    Based on that, I will see if I can create a hooks file that achieves the same, which is a better approach than modifying mcuboot and the loader.c file.

    Best regards,

    Simon

  • Good morning Simon,

    thanks for the feedback.

    Yes, I saw his proposal but - if i am not mistaken - the hook approach works only in multi image approach where the rolling back of the app image is not possible. Is that correct ?

    Anyway, thanks for investing time to dig in this issue.

    Looking forward to hearing from you.

    Kind regards

    Riccardo 

  • In that reply he modified loader.c directly, he didn't use any hooks. So that could be a temporary workaround. But you are correct, currently the nrf53_hooks.c file is only working with multi-image simultaneous DFU. I will look into creating a hook file for your case.

Related