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

Parents Reply Children
  • Hi Sigurd,

    Answering your questions in the same order:
    1. Yes, I have run the eraseall before and even during the flash command with the flag "--erase"

    2. I have actually undone all the changes I made to the nRF Connect SDK

    .../v1.8.0/bootloader/mcuboot ((v1.7.99-ncs4))
    $ git status
    HEAD detached at refs/heads/manifest-rev
    nothing to commit, working tree clean
    

    and the error is still present, in the application's project I configured the values:

    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_MCUBOOT_IMAGE_VERSION="0.1"

    and on the MCUboot image's configuration overlay file I set the values:

    CONFIG_MCUBOOT_LOG_LEVEL_DBG=y
    CONFIG_BOOT_SWAP_USING_MOVE=n
    CONFIG_BOOT_DIRECT_XIP=y

    Here the application's log that shows what the problem:

    // ========== Flashed the MCUboot and the application imagge with the --erase flag ========
    *** Booting Zephyr OS build v2.7.0-ncs1  ***
    I: Starting Direct-XIP bootloader
    I: Primary   slot: version=0.1.0+0
    I: Image 0 Secondary slot: Image not found
    I: Image 0 loaded from the primary slot
    I: Bootloader chainload address offset: 0xc000
    *** Booting Zephyr OS build v2.7.0-ncs1  *** 
    [00:00:00.004,791] <inf> : Executing application version {0.1} 
    [00:00:00.039,550] <inf> : BLE library successfully initialized
    [00:00:00.044,311] <inf> : BLE MAC address loaded, addr=C54DC37971B4
    [00:00:00.050,476] <inf> : BLE Advertising process successfully started
    [00:00:05.519,927] <inf> : BLE device connected
    // Started sending the new image through the Bluetooth's DFU service
    [00:00:21.366,058] <inf> mcuboot_util: Swap type: none
    [00:00:21.637,207] <inf> mcuboot_util: Swap type: none
    [00:00:21.637,329] <inf> mcuboot_util: Swap type: none
    // finished the DFU process and the device restarted automatically
    *** Booting Zephyr OS build v2.7.0-ncs1  ***
    I: Starting Direct-XIP bootloader
    I: Primary   slot: version=0.1.0+0
    I: Secondary slot: version=0.4.0+0
    I: Image 0 loaded from the secondary slot
    I: Bootloader chainload address offset: 0x74000 // This is the offset of the secondary partition
    *** Booting Zephyr OS build v2.7.0-ncs1  ***
    [00:00:00.004,821] <inf> : Executing application version {0.1} // As you can see the message is printing the version of theprimary partition's image
    [00:00:00.039,550] <inf> : BLE library successfully initialized
    [00:00:00.044,311] <inf> : BLE MAC address loaded, addr=C54DC37971B4
    [00:00:00.050,476] <inf> : BLE Advertising message successfully started

    This is how I print the application's first log message

    LOG_INF("Executing application version {%s}", CONFIG_MCUBOOT_IMAGE_VERSION);

    3. Just to be clear I didn't erase the trailer to fix the secondary partition's booting error. The thing is that I send the "app_update.bin" to my smartphone, then use the "nRF Connect" application to connect to the device through Bluetooth and do the DFU process. The problem here was that I couldn't overwrite the image in the secondary partition, for example:

    Lets say that in the primary partition I have the image version 2 and the secondary partition is empty, the primary partition is booted, then I do the DFU process and write the image version 1 in the secondary partition, the device restarts and since the secondary partition has a lower version than the primary partition the later is booted. After that I try to send the image version 3 through the DFU process so that it will overwrite the image version 1 that it's in the secondary partition but the during the process it reads that the image in the secondary partition is pending to be swapped, so it restarts the device so that the MCUboot do the swapping process but since I have enable the Direct-XIP configuration in the MCUboot image it will never swap the partitions' images and the swap state won't be updated so every time I try the DFU process it will read the same status and it will just restart the device, meaning I can only write an image in the secondary partition once and I cannot overwrite it.

    I debugged the MCUboot swapping process to see what values of the image's header and trailer modified during the process. On of them was the erasing the image's trailer. So what I did was to open the flash area of the secondary partition and then erase the trailer sector with the same function that the swap process used, this are the two functions I used to do this:

    struct boot_loader_state *state; // parameter of the function
    flash_area_open(FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state)), &fap);
    swap_erase_trailer_sectors(state, fap);

    this change did make it possible to overwrite the image in the secondary partition through the Bluetooth's DFU process.

    Regards

    Erasmo

  • This reply was deleted.
  • You should be aware that the image you put in the secondary slot should be built for that exact address. For example an app_update.bin file might be built for addr. 0x1000 and have the reset addr 0x1100. If you then put this binary file in addr 0x2000 (and reset addr should be 0x2100), it will still see 0x1100 and try to jump there to start code execution.

    Does this make sense? Do you think this is the core of your issue?

    Best regards,

    Simon

  • Yes, that makes sense to me and I also though that might be the issue.

    Is there a configuration that I can use to change the reset address and set it to point at the secondary partition ? or how could I make it boot from the secondary partition directly?

    Regards,

    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

Related