DFU using USB file system (not serial emulation)?

My project has a nrf5340+external flash, and an external USB-C connector. The device exposes a USB file system (FAT) which is hosted on the external flash partition, and appears as an external disk when connected to a host. This all works well and is used to update config, image files etc for the device to use.

I would like to be able to do application / network firmware updates by simply copying the new image (hex or bin) to this file system and rebooting. Has anyone done this? I'm guessing it involves using MCUBoot bootloader and copying the image into the secondary image slot somehow? I also want to put the secondard image slot on my external flash as won't have space on the internal flash - even better would be if MCUBoot could take the image directly from the file in the FS....

by the way, to be clear, I do NOT want to use the 'DFU over USB serial emulation' method, as this requires the user to install the specific tool to the host machine, which may not be available for their host or may not be allowed by IT policy (or by their level of expertise...). 

thanks for any pointers!

Parents
  • Hi Brian, 
    You should set 

    CONFIG_MCUBOOT_SERIAL=n in the mcuboot.conf overlay to apply the config to the MCUBoot child image, not the application. Usually you put that file into child_image folder.  
    Anyway , by default MCUBOOT_SERIAL is not enable so you don't really have to worry about it. (double check with .config file in the MCUBoot build folder)
  • Ok... I removed all the wifi stuff from my app, added a mcuboot.cong in the child_image folder with:

    CONFIG_MCUBOOT_SERIAL=n
    CONFIG_BOOT_USE_MIN_PARTITION_SIZE=y

    This didn't fix it, although it has changed things.

    Latest build error is:

    [373/415] Performing build step for 'mcuboot_subimage'

    ...

    `text' will not fit in region `FLASH'
    c:/ncs/toolchains/cf2149caf2/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd.exe: region `FLASH' overflowed by 37320 bytes
    collect2.exe: error: ld returned 1 exit status
    ninja: build stopped: subcommand failed.

    ...
    [396/415] Linking C executable zephyr\zephyr_pre0.elf
    c:/ncs/toolchains/cf2149caf2/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd.exe: warning: orphan section `.fonts' from `app/libapp.a(u8g2_fonts.c.obj)' being placed in section `.fonts'
    [397/415] Generating ../../zephyr/net_core_app_test_update.hex
    image.py: sign the payload
    [402/415] Linking C executable zephyr\zephyr.elf
    FAILED: modules/mcuboot/mcuboot_subimage-prefix/src/mcuboot_subimage-stamp/mcuboot_subimage-build mcuboot/zephyr/zephyr.hex mcuboot/zephyr/zephyr.elf C:/work/dev/if-device-nrf53/cc1-med/build/modules/mcuboot/mcuboot_subimage-prefix/src/mcuboot_subimage-stamp/mcuboot_subimage-build C:/work/dev/if-device-nrf53/cc1-med/build/mcuboot/zephyr/zephyr.hex C:/work/dev/if-device-nrf53/cc1-med/build/mcuboot/zephyr/zephyr.elf
    ...
    Memory region Used Size Region Size %age Used
    FLASH: 446762 B 1031680 B 43.30%
    RAM: 152572 B 440 KB 33.86%
    IDT_LIST: 0 GB 32 KB 0.00%
    ninja: build stopped: subcommand failed.

    I note that the application built correctly, and is around 446Kb (with the wifi enabled I'm thinking this was showing 901kB...). But this didnt stop the mcuboot subimage failing, this time with its 'text' segment overflowing the FLASH...

    Maybe I should try to reconfigure to stop using the partition manager if its creating a partition for mcuboot which is too small?

    or just build the mcuboot child image to check if that is the issue?

  • Post update : once mcuboot has sucessfully swapped the slots, it runs the new image - great.

    But at the next boot, it swaps back, as it had done the swap in 'test' mode... and then next boot it swaps again... 

    Normally, to stop this 'revert', I understand from the mcuboot doc that the new image must make itself as 'good'. No thanks to the mcuboot doc page (which says nothing about how to do this), it seems this should be as simple as a call to 

    boot_write_img_confirmed();
    (definition in zephyr/dfu/mcuboot.h)
    So, I set a timer, and  60s after boot it pops and I call this method. return is 0, so success. 
    And on the next reset, mcuboot does indeed see the image_ok flag as 0x1 which (according to the doc) is OK.
    But... it swaps anyway
    *** Booting nRF Connect SDK 3758bcbfa5cd ***
    I: Starting bootloader
    I: Primary image: magic=good, swap_type=0x2, copy_done=0x1, image_ok=0x1
    I: Secondary image: magic=good, swap_type=0x2, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Image index: 0, Swap type: test
    I: Starting swap using move algorithm.
    I: Bootloader chainload address offset: 0xe000
    I guess this is because although primary image slot is OK, the secondard slot is also still OK, and it didn't set its flag to know ifs the old version or that the 'test' swap was really OK? ALso, image_ok=0x3 - can't find the doc that says what this value is : 0x1 or 0xFF are the only values noted....
    The mcuboot doc (https://docs.nordicsemi.com/bundle/ncs-2.6.2/page/mcuboot/design.html#image_swapping) implies that mcuboot itself should set the magic of the secondary slot to None, to disable it... I would have thought this would be when I call the confirmed() function.... but clearly this has not happend.
     
    Do I need to overwrite the secondary slot image header myself to remove the revert? 
  • After a look at the mcuboot bootutil code, I understand that the value 0x1 means "SET" and 0x3 means "UNSET". So at boot, copy_done=SET, image_ok=SET for primary slot.

    And as I understand the algorithm of mcuboot, ths should mean that even though the swap_type=0x2 (TEST), it should NOT swap to the secondary slot (unless my code expliclty asked for this as part of DFU - which it didn't).

    So, why did mcuboot swap in this case?

  • Hi Brian, 

    As far as I know you only need to call boot_write_img_confirmed() in the application at its first boot after the swap then it should be permanent. 

    You can find the call in the \nrf\samples\bluetooth\mesh\dfu\target sample. Where we call dfu_target_image_confirm() after bluetooth initialized. 

    From what I can see in the code swap type should be set to 

    swap_type = BOOT_SWAP_TYPE_PERM
    in boot_write_img_confirmed-> boot_set_next()

    Could you confirm you call dfu_target_image_confirm() in the application after the first boot after swapping ? 
    Please make sure you give the application enough time to write to flash before reset. 
  • As far as I know you only need to call boot_write_img_confirmed() in the application at its first boot after the swap then it should be permanent. 

    Yes, that was my understanding. My code calls 

    ret = boot_write_img_confirmed();
    exactly as per the sample. However the swap_type remains as BOOT_SWAP_TYPE_TEST - as far as I can see the bootutil code for boot_set_next() just updates the image_ok flag to SET...
    (inspecting the bootutil code on the mcu github)
    Where do you see the swap_type being updated?
  • Please make sure you give the application enough time to write to flash before reset. 

    yes, I give it at least 10s and this appears ot be ok as mcuboot sees image_ok as 0x1 after the reboot.

Reply Children
No Data
Related