MCUboot Direct-XIP, always boots the primary partition

Hi

I am trying to modify the MCUboot image to meet the requirements of the project one of the rquirements is to boot the application directly from the secondary partition, I found the Direct-XIP configuration that does that exactly so I enable it at first it worked, the MCUboot image's "prj.conf" looked like this:

CONFIG_MCUBOOT_LOG_LEVEL_DBG=y
CONFIG_BOOT_SWAP_USING_MOVE=n
CONFIG_BOOT_DIRECT_XIP=y

later I made some modifications directly to the SDK since I needed to update the secondary partition's image so that the DFU service of the Bluetooth connection could overwrite the image, because the service detected that the image was never swapped and it will just restart the device without upgrading the image. To solve this I erased the Trailer of the secondary partition's image.

At some point (not sure when) the MCUboot stopped booting the secondary's partition image (the devices doesn't get stuck, it just boots the primary partition's image) even when the Log says that the image in the secondary partition is newer and that it will be booting it (the address send to the function "do_boot" is the address of the secondary partition).

I tried going back in all my changes but the error is still present.

Right now I have been debugging the booting process after the partition has been selected and it seems that both partitions have the same MSP (Main Stack Pointer) so that might be why the primary partition is booted even when the secondary partition is selected.

I also found that I might need to use a file that has the word "secondary" in its name when writing an image in the secondary partition, I suppose that this one has the correct MSP to boot the image in the secondary partition, but I cannot see it in the "build" folder, while searching for this file found the configuration "CONFIG_BOOT_BUILD_DIRECT_XIP_VARIANT" on the application's "prj.conf" but this configuration is of the SDK version 2.0.X and I am using the SDK version 1.8.0.

What should I do so that I can get the correct image for the secondary partition (I would like to avoid the migration of the SDK if posible) or what should I configure in the MCUboot so that it can be booted?

Thanks,
Erasmo

  • I did some quick tests with the hello world sample to try to achieve this:

    I'm using an nRF52840 DK, since I don't have any nRF5340 DK at the home office at the moment, but it shouldn't matter

    To generate the update bin file, you need to add CONFIG_BOOTLOADER_MCUBOOT=y. When mcuboot is enabled, the image will then be put after the mcuboot, and in this case the offset was 0xc000.

    Also, if MCUboot is enabled, the Partition Manager will be used to locate all the partitions, and the way the partition manager works (if I remember correctly) is by defining the position off all the child images first and wherever there is room at the end, the primary application will be put. So you can not modify the address and size of the app directly. Instead you need to increase the size of mcuboot, so the application offset increases as well.

    • Next, I enabled CONFIG_BOOTLOADER_MCUBOOT=y in prj.conf (to generate app_update.bin)

    Then, let's say you want to create an image for address 0xd000. To achieve this, you can increase the size of the mcuboot partition by 0x1000.

    • In order to increase the mcuboot size by 0x1000, I set CONFIG_PM_PARTITION_SIZE_MCUBOOT=0xd000 (was previously 0xc000) in C:\v2.0.0\bootloader\mcuboot\boot\zephyr\prj.conf (can also be done directly from the application by using any of the methods in this ticket)
    • Then I built the sample and programmed merged.hex to the 52840 DK and confirmed using the nRF Connect Programme app that it was correctly placed.

    The bottom green area you see is just some mcuboot header info and is only 32 bytes. The orange are is mcuboot.

    Now you should find the app_update.bin file located in C:\Nordic\ncs_samples_local\nonzero_offset\build\zephyr\app_update.bin which is built for address 0xD200, and it should have the correct reset address (somewhere between 0xD200 and 0x12B5E). Read more about the reset vector address in Updating start address to nrf52840 dk via code.

    I'm sorry for the long answer, and that I couldn't find any more straight forward way to achieve this. Maybe someone in the community knows?

    Best regards,

    Simon

  • Hi Simon,

    I first attempted the configurations CONFIG_FLASH_LOAD_OFFSET=0x500  and CONFIG_USE_DT_CODE_PARTITION=n, but my project wouldn't apply it.

    Then I attempted increasing the size of the MCUboot partition so that the primary partition will start where the secondary partition starts but the image's partitions became so small that the application couldn't fit so I got and Overflow error durring compilation.

    After that I tried using the configuration CONFIG_SINGLE_APPLICATION_SLOT in the MCUboot image configuration to remove one of the two image's partitions, that way the only partition will have the size it will normally have after I increase the size of the MCUboot partition. But for this to work I had to disable the Bluetooth module and I need it.

    Solution:

    Luckily, while I was checking one of the ticket you reference me to I saw a comment about reducing the size of the secondary partition and increasing the primary partition using a pm_static.yml file (place it in the root folder of the project, where the prj.conf file is). But instead of continue changing the size of the partitions I tried swapping the position of the image's partitions mcuboot_primary and mcuboot_secondary, this way when the application compiled it has the address of the primary partition which now is in the flash area where the secondary partition is originally.

    pm_static.yml:

    app:
      address: 0xc200
      end_address: 0x84000
      region: flash_primary
      size: 0x77e00
    mcuboot:
      address: 0x0
      end_address: 0xc000
      placement:
        before:
        - mcuboot_secondary
      region: flash_primary
      size: 0xc000
    mcuboot_secondary:
      address: 0xc000
      end_address: 0x84000
      placement:
        before:
        - mcuboot_primary
        align:
          start: 0x4000
      region: flash_primary
      share_size:
      - mcuboot_primary
      size: 0x78000
    mcuboot_pad:
      address: 0x84000
      end_address: 0x84200
      placement:
        align:
          start: 0x4000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0x84000
      end_address: 0xfc000
      orig_span: &id001
      - mcuboot_pad
      - app
      region: flash_primary
      sharers: 0x1
      size: 0x78000
      span: *id001
    mcuboot_primary_app:
      address: 0x84200
      end_address: 0xfc000
      orig_span: &id002
      - app
      region: flash_primary
      size: 0x77e00
      span: *id002
    otp:
      address: 0xff8100
      end_address: 0xff83fc
      region: otp
      size: 0x2fc
    pcd_sram:
      address: 0x2006e000
      end_address: 0x20070000
      placement:
        before:
        - rpmsg_nrf53_sram
        - end
      region: sram_primary
      size: 0x2000
    rpmsg_nrf53_sram:
      address: 0x20070000
      end_address: 0x20080000
      placement:
        before:
        - end
      region: sram_primary
      size: 0x10000
    settings_storage:
      address: 0xfc000
      end_address: 0x100000
      placement:
        align:
          start: 0x4000
        before:
        - end
      region: flash_primary
      size: 0x4000
    sram_primary:
      address: 0x20000000
      end_address: 0x2006e000
      region: sram_primary
      size: 0x6e000
    

    How this works is that when I am going to flash the MCUboot image and the application in the primary partition I remove the pm_static file and when I need to generate an app_update.bin file for the secondary partition I add the pm_static file.

    Regards,

    Erasmo

  • There you go! That seems like a better solution than what I suggested

Related