MCUBoot manual compile + usage

We're using NCS embedded into our Makefile-based build system to compile nRF5340 applications out-of-tree, but still having unresolved problems. The target board is a custom nRF5340 design. I'm continuously looking for alternative ways to achieve my goal: have MCUBoot run on APP core alongside our program + being able to perform FW upgrade. The problems are described in the linked ticket, now I'd like to show what other things I've been trying to do.

I've figured out how to manually configure, menuconfig and compile NCS's MCUBoot, so now I can generate MCUBoot's zephyr.hex independently of my application. Burning it to the flash isn't a problem either. Important to note, the application has no MCUBoot enabled as a child image (because we're having problems with it, see the linked ticket), it's a simple, standalone program.

Once the application is compiled, the resulting zephyr.hex is signed like this:

imgtool.py sign --align=1 --version="9.8.7" --header-size=512 --slot-size=0x77000 --hex-addr=0x10000 zephyr.hex signed.hex

Burning signed.hex to flash, MCUBoot successfully boots it. Great!

To check how MCUBoot swapping is operating, generated a different zephyr.hex and signed it:

imgtool.py sign --align=1 --version="9.8.7" --header-size=512 --slot-size=0x77000 --hex-addr=0x87000 ph2.hex signed.hex

(In DTS, slot0_partition begins at 0x10000, while slot1_partition begins at 0x87000, their sizes are 0x77000)

After burning the new FW image to slot1, MCUBoot does nothing, still boots the original image. (Swapping is enabled in MCUBoot config). This is what MCUBoot displays on serial console:

*** Booting Zephyr OS build v3.2.99-ncs1 ***
I: Starting bootloader
I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Boot source: none
I: Swap type: none
I: Bootloader chainload address offset: 0x10000
�*** Booting Zephyr OS build v3.2.99-ncs1 ***
================================================================================
project config: default sample project
...
...

I'd like to ask for some help, pointers or advices on the following questions:

  1. how can I make MCUBoot swap my new FW image? I believe this must be something with the lack of FW image trailers. If so, how can I manually generate trailers, or how to init them?
  2. Planned FW upgrade will be working like this: the running application gets the image file fragments via some kind of networking (e.g. TCP/IP). How can the application pass the fragments to MCUBoot? This is pretty unclear to me, as MCUBoot executes first after reset, but when it loads the application from slot0, MCUBoot no longer remains in memory, it's no longer running (if I'm not totally wrong). So if my assumption is right, there must be some MCUBoot-support code in Zephyr, which makes it possible to write new image's fragment to slot1, generate trailer and so on.
    The first thing I want to experiment with is that a sample app is being burnt into slot0, and this app contains the image of a new app; this old sample app emits image fragments, which get written to slot1, and then resets and MCUBoot does its job (swaps images);

Many thanks, regards,

Parents
  • There is some progress regarding FW upgrade.

    We have given up the concept of manually compiling MCUboot, instead the build system does the job. It was a good decision ;)

    The new image to be burnt to APP and NET cores are available on the APP core (by TCP/IP or other magic of ours).

    Our custom board doesn't feature any external flash.

    I've enabled MCUboot on both APP and NET cores and created static partition layouts for both cores. This resulted in two large prog partitions (primary and secondary) on both cores (and other small partitions).

    We can successfully upgrade APP core's FW by using MCUboot's "move swap" feature. The FW upgrade is initiated somehow like this:

    struct flash_img_context fic;

    flash_img_init_id(&fic, PM_MCUBOOT_SECONDARY_ID);
    boot_erase_img_bank(PM_MCUBOOT_SECONDARY_ID);
    flash_img_buffered_write(&fic, fw_upg_img, sizeof(fw_upg_img), true);
    boot_request_upgrade(BOOT_UPGRADE_PERMANENT);

    On next reboot MCUboot copies the new image from secondary partition to primary, works well.

    Now we need to make it work for NET core too. Unfortunately, if we follow the same scheme for NET core flash partitioning as for APP core partitioning, the resulting primary and secondary partitions will be very small, less than 128kB, so the new image can easily outrun this size. If we had only one prog partition that could be almost 256kB in size.

    My idea is to programmatically shut down NET core and update NET core flash area from a program running on APP core. This way we don't need to create primary and secondary partitions on the NET core, and the only prog partition can be large enough.

    Does the MCU support this kind of operation?

    There are some other alternatives naturally. One that I can think of now: APP core resets NET core, the MCUboot on the NET core takes FW image parts from the APP-NET shared memory and upgrades the program partition. Does MCUboot support this or anything similar?

    Thanks, regards,

  • As I can see, a BusFault is generated when APP core tries to access NET core's flash area, but it's working in the opposite direction, at least NET core is capable of reading APP's flash area.

    The best would be if NET MCUboot could take FW image chunks from APP core through e.g. shared memory, so it could write directly onto flash, and there was no need for a secondary flash partition...

  • Please have a look at the source code structure in our project:

    src
    test
    app
    sources, CMakeList.txt etc for the
    program on APP core
            net
    sources, CMakeList.txt etc for the
    program on NET core

    To build the project, two west builds are commited, one for 'app' (cd src/test/app, west build...) , another one for 'net' (cd src/test/net, west build...) , resp. 'app' has a child image (MCUboot), 'net' also has a child image (B0n). 'app' compiles without a problem, while 'net' fails with this error:

    -- west build: building application
    ninja: error: 'modules/nrf/subsys/app_hex', needed by 'zephyr/nrf/subsys/bootloader/generated/app_firmware.signature', missing and no known rule to make it
    

    CONFIG_SECURE_BOOT is enabled. I was unable to find the reason by investigating the build system.

    (NOTE: if MCUboot is enabled instead of B0n on NET core, it compiles without a problem)

  • It looks like the build script is failing to sign the network core image. 

  • At this point there's no .elf, .bin in the build directory...

  • This is expected as the build failed. Can you please build the SMP SRV sample as I suggested and compare the generated .config files?

  • I've given up struggling with mystic B0n compilation issues. Instead, I've compiled MCUboot to NET core with a single (primary) partition, configured MCUboot to single slot mode. Then I've manually added PCD NET support to MCUboot, so now APP core MCUboot and NET core MCUboot communicate through PCD library and the new NET core FW image is successfully programmed ;) Several NET core FW upgrade procedures have succeeded, but the rest of the testing is still remaining.

Reply
  • I've given up struggling with mystic B0n compilation issues. Instead, I've compiled MCUboot to NET core with a single (primary) partition, configured MCUboot to single slot mode. Then I've manually added PCD NET support to MCUboot, so now APP core MCUboot and NET core MCUboot communicate through PCD library and the new NET core FW image is successfully programmed ;) Several NET core FW upgrade procedures have succeeded, but the rest of the testing is still remaining.

Children
No Data
Related