[Zigbee] FOTA mcuboot update

Setup
nRF Connect SDK 2.3.0
nRF52840

Hi all,

I would like to add mcuboot update over Zigbee FOTA to my application. 
I am aware of that the bootloader update over Zigbee is not currently supported by the nRF Connect SDK and it will require multiple steps to make it possible.

From my point of view the necessary steps are: 

  1. Generating the mcuboot FOTA image to be distributed by Zigbee FOTA server in a following way:
    1. build/mcuboot/zephyr.bin -> imgtool.py (with specific options like slot size, keys, etc.) -> dfu_multi_image.py -> zb_add_ota_header.py
  2. Determine the image type by image type field or image comment directly in the zigbee_fota subsys -> zigbee_fota_zcl_cb()
  3. Check the mcuboot fw versions in the s0 and s1 partition and choose lower one as current/active partition.
  4. Handle the incoming data: 
    1. Option A: Save the data directly to flash (current partition)
    2. Option B: Use DFU target library (?)
  5. Increase the version number of the mcuboot stored in current partition to be higher than mcuboot stored in alternative partition.
  6. Reboot 

The questions are: 

  1. Are there any other limitations of which I am not aware of ? 
  2. Is it possible to use DFU target library for handling the image flash saving ? By setting/changing some configs ? 

I am looking forward to hearing from you

  • Hello,

    I will look into this. Thank you for your patience.

    Best regards,

    Maria

  • Hello again,

    Thanks again for your patience.

    You seem to have covered the steps needed to adding an upgradable bootloader to your Zigbee application.

    I have a few comments on step 4:

    You can choose the option which suits you best (A or B).

    Choosing option A will give you the most control over what is happening and more of the development is on you. The generated pm_config.h defines the start addresses for the different sections of flash and the header file can be included in your project. From your build folder it can be found in zephyr/include/generated.

    If you opt for option B and choose the DFU target library, the functionality for firmware upgrade is already implemented. This option will include that you get familiar with the library and its complexity.

    Other than the above, I recommend that you take the instructions and documentation for Zigbee FOTA into account:
    Enabling Zigbee FOTA in an application
    Zigbee FOTA library

    Best regards,

    Maria

  • Hi Maria,

    Thank you so much for taking a look on that topic. 

    I did some further research regarding choosing option A or B, but I have not decided yet. From my understanding option A
    will require using Flash API, which seems like code duplication knowing that dfu target(stream) is already using that.
    At this moment I tend to use the dfu library. 
    I assume that if I will choose the DFU lib I will have to write the code which will be similar to dfu_target_mcuboot.c 
    is that right ? 

    I am looking forward to hearing from you.

  • Hi, in the past few days, I have implemented the source code for handling the mcuboot image update over Zigbee. 
    Since today I am able to send the image through Zigbee FOTA server, parse the image on the client side, save it to flash and correctly boot with the new version. 
    Implementation has got some limitations which I am going to overcome in the next steps. 
    I am using CONFIG_FW_INFO  (fw_info_find) to read the content of both s0,s1 partitions metadata like firmware version. On the application side when the Zigbee Image Response arrives I check the greatest firmware version stored in any of the partitions to avoid downgrading.
    If that requirement is met I decide which partition should be updated. In other words I look for slot which has got the lowest firmware version.
    Then the update starts and data is being saved to flash starting from  PM_S0_ADDRESS or PM_S1_ADDRESS. 

    Everything works well if  signed_by_mcuboot_and_b0_s0_image_update.bin is used for updating s0 partition, and signed_by_mcuboot_and_b0_s1_image_update.bin for s1 partition. 

    I compared both binaries and they have got a lot of differences. I noticed that every bin file contains the firmware info which also contains the start address of image, so when the signed_by_mcuboot_and_b0_s1_image_update.bin is used for updating the s0 partition, b0 (NSIB) tries to boot the s0 from  PM_S1_ADDRESS which ends with error: 
    "Firmware info doesn't point to itself".

    That problem might be resolved by giving the s1 and s0 updatable images their own Zigbee image types. The FOTA client will periodically send the request for image type 0xXXX which will inform FOTA server to send the bootloader update image for s0. For s1 the client will send request for image type 0xYYYY. 
    It should work as intended but it seems like a waste of memory on the FOTA server side because it will need to have enough space for containing s0, s1 and app images. 

    The other option is to use s0 as a main bootloader (well-tested, lifeguard) and update only bootloader in s1 partition. 

    What I am trying to achieve is to have only one binary file which will be suitable for both partitions. Is it even possible ? If not, why ?

  • Due to the summer holiday period in Norway we currently have low staffing on DevZone. We apologize for possible delays caused by this and thank you for your patience.


    Hello,

    Pawel(embeddedsolutions.pl) said:
    I assume that if I will choose the DFU lib I will have to write the code which will be similar to dfu_target_mcuboot.c 
    is that right ? 

    Yes, your DFU target is MCUboot, so the functions to use are in that file as well as in dfu_target.c. Please see the MCUBoot-style upgrades part of the DFU target library documentation for information on how to use the API functions.

    Pawel(embeddedsolutions.pl) said:
    I compared both binaries and they have got a lot of differences. I noticed that every bin file contains the firmware info which also contains the start address of image, so when the signed_by_mcuboot_and_b0_s1_image_update.bin is used for updating the s0 partition, b0 (NSIB) tries to boot the s0 from  PM_S1_ADDRESS which ends with error: 
    "Firmware info doesn't point to itself".
    Pawel(embeddedsolutions.pl) said:
    What I am trying to achieve is to have only one binary file which will be suitable for both partitions. Is it even possible ? If not, why ?

    From Pre-signed variants in the Secure bootloader chain documentation:

    You must build with pre-signed variants when building upgrade images for the image that follows the nRF Secure Immutable Bootloader in the boot chain, such as the upgradable bootloader or the application. Firmware update packages of the upgradable bootloader must contain images for both slots, since it may not be known which slot is in use by its current version while deployed in the field.

    From the documentation excerpt above it looks like it will not be possible to have one binary to fit both slots.

    Edit: I want to add that the reason for the different images is that the code is memory-dependent. The difference in images is necessary for the firmware to run properly.

    Best regards,

    Maria

Related