Sysbuild builds MCUBoot before static partitions are pulled in

Hi, I'm currently working on porting an nrf5340 - NCS 2.6.0 project repo to NCS 2.7.0 starting with my own minimal sample. Having some trouble getting the sample to build with MCUBoot and a static partition map.


https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/releases_and_maturity/migration/migration_sysbuild.html#partition_manager

Documentation seems to suggest that when building Sysbuild + MCUBoot with a static partition map defined, MCUBoot will build using the partition manager definitions in pm_static.yml. However, my build always seems to fail if boot_partition, slot0_partition, and slot1_partition AREN'T defined in my device tree. Only after MCUBoot finishes and my main application begins compilation do I see the pm_static.yml being used. This seems to run contrary to what the documentation suggests. Ideally we'd like to have a single source of truth in the pm_static.yml rather than having to define the same partitions in the devicetree for MCUBoot. Please advise.

Sysbuild Conf:

SB_CONFIG_PARTITION_MANAGER=y

# Net Core Multiprotocol Radio Image
SB_CONFIG_NETCORE_IPC_RADIO=y
SB_CONFIG_NETCORE_IPC_RADIO_BT_HCI_IPC=y
SB_CONFIG_NETCORE_IPC_RADIO_IEEE802154=y

# MCUBoot Bootloader
SB_CONFIG_BOOTLOADER_MCUBOOT=y
SB_CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y

Build Output with boot partitions and slots0/1 not defined:

-- west build: making build dir /Users/timothy.lee/echo_low_power/apps/low_power_app/build_app pristine
-- west build: generating a build system
Loading Zephyr module(s) (Zephyr base): sysbuild_default
-- Found Python3: /opt/homebrew/opt/[email protected]/bin/python3.11 (found suitable version "3.11.7", minimum required is "3.8") found components: Interpreter 
-- Cache files will be written to: /Users/timothy.lee/Library/Caches/zephyr
-- Found west (found suitable version "1.2.0", minimum required is "0.14.0")
-- Board: maven, qualifiers: nrf5340/cpuapp
Parsing /Users/timothy.lee/echo3_ncs/zephyr/share/sysbuild/Kconfig
Loaded configuration '/Users/timothy.lee/echo_low_power/apps/low_power_app/build_app/_sysbuild/empty.conf'
Merged configuration '/Users/timothy.lee/echo_low_power/apps/low_power_app/sysbuild.conf'
Configuration saved to '/Users/timothy.lee/echo_low_power/apps/low_power_app/build_app/zephyr/.config'
Kconfig header saved to '/Users/timothy.lee/echo_low_power/apps/low_power_app/build_app/_sysbuild/autoconf.h'
-- 
   *****************************
   * Running CMake for mcuboot *
   *****************************

Loading Zephyr default modules (Zephyr base).
-- Application: /Users/timothy.lee/echo3_ncs/bootloader/mcuboot/boot/zephyr
-- CMake version: 3.26.4
-- Found Python3: /opt/homebrew/bin/python (found suitable version "3.11.7", minimum required is "3.8") found components: Interpreter 
-- Cache files will be written to: /Users/timothy.lee/Library/Caches/zephyr
-- Zephyr version: 3.6.99 (/Users/timothy.lee/echo3_ncs/zephyr)
-- Found west (found suitable version "1.2.0", minimum required is "0.14.0")
-- Board: maven, qualifiers: nrf5340/cpuapp
-- ZEPHYR_TOOLCHAIN_VARIANT not set, trying to locate Zephyr SDK
-- Found host-tools: zephyr 0.16.1 (/Users/timothy.lee/zephyr-sdk-0.16.1)
-- Found toolchain: zephyr 0.16.1 (/Users/timothy.lee/zephyr-sdk-0.16.1)
-- Found Dtc: /opt/homebrew/bin/dtc (found suitable version "1.7.0", minimum required is "1.4.6") 
-- Found BOARD.dts: /Users/timothy.lee/echo_low_power/boards/level/maven/maven_nrf5340_cpuapp.dts
-- Found devicetree overlay: /Users/timothy.lee/echo3_ncs/bootloader/mcuboot/boot/zephyr/app.overlay
devicetree error: /chosen: undefined node label 'boot_partition'

Parents
  • Hi Timothy, 

    You can find some discussion earlier about this here.

    My understanding is that the partitions defined in device tree and the partitions in pm_static.yml with partition manager are 2 differents system. As mentioned in the above ticket when you use partition manager the device tree's partition become irrelevant. However, you can't build without that.

    I would suggest to double check if modifying dts partition wouldn't affect the location of MCUBoot or slot0 or slot1. I would assume they don't

    As mentioned in the ticket, we hope in the future it would be more clean and better align between Zephyr upstream and nRF Connect SDK.

  • Thanks for the response,

    Like you suggested, i modified the dts partition map and mcuboot still jumped to the application address in my static partition map.

    I'd still like some assurance that slot0 and slot1 arent being used as well. The errors when slot0 and slot1 partition aren't defined seem to be coming from bootloader/mcuboot/boot/zephyr/CmakeLists.txt on line 372 where there are some checks being on the slot partition sizes and flash r/w/e sizes. There are some cmake variables getting set in this code block. Can you confirm whether or not these checks are arbitrary and if the set variables are used elsewhere?

    if(SYSBUILD)
      function(align_up num align result)
        math(EXPR out "(((${num}) + ((${align}) - 1)) & ~((${align}) - 1))")
        set(${result} "${out}" PARENT_SCOPE)
      endfunction()
    
      function(dt_get_parent node)
        string(FIND "${${node}}" "/" pos REVERSE)
    
        if(pos EQUAL -1)
          message(ERROR "Unable to get parent of node: ${${node}}")
        endif()
    
        string(SUBSTRING "${${node}}" 0 ${pos} ${node})
        set(${node} "${${node}}" PARENT_SCOPE)
      endfunction()
    
      if(CONFIG_SINGLE_APPLICATION_SLOT OR CONFIG_BOOT_FIRMWARE_LOADER OR CONFIG_BOOT_SWAP_USING_SCRATCH OR CONFIG_BOOT_SWAP_USING_MOVE OR CONFIG_BOOT_UPGRADE_ONLY OR CONFIG_BOOT_DIRECT_XIP OR CONFIG_BOOT_RAM_LOAD)
        # TODO: RAM LOAD support
        dt_nodelabel(slot0_flash NODELABEL "slot0_partition")
        dt_get_parent(slot0_flash)
        dt_get_parent(slot0_flash)
    
        if(NOT CONFIG_SINGLE_APPLICATION_SLOT)
          dt_nodelabel(slot1_flash NODELABEL "slot1_partition")
          dt_get_parent(slot1_flash)
          dt_get_parent(slot1_flash)
    
          if(NOT "${slot0_flash}" STREQUAL "${slot1_flash}")
            # Check both slots for the one with the largest write/erase block size
            dt_prop(erase_size_slot0 PATH "${slot0_flash}" PROPERTY "erase-block-size")
            dt_prop(write_size_slot0 PATH "${slot0_flash}" PROPERTY "write-block-size")
            dt_prop(erase_size_slot1 PATH "${slot1_flash}" PROPERTY "erase-block-size")
            dt_prop(write_size_slot1 PATH "${slot1_flash}" PROPERTY "write-block-size")

    It seems like there should be documentation on the interaction between partition manager and sysbuild in 2.7.0 (perhaps in the migration guide). I asked a similar question while working on 2.6.0 and I was told that devicetree partitions weren't required to build MCUBoot.

     Understanding MCUBoot partition management 

Reply
  • Thanks for the response,

    Like you suggested, i modified the dts partition map and mcuboot still jumped to the application address in my static partition map.

    I'd still like some assurance that slot0 and slot1 arent being used as well. The errors when slot0 and slot1 partition aren't defined seem to be coming from bootloader/mcuboot/boot/zephyr/CmakeLists.txt on line 372 where there are some checks being on the slot partition sizes and flash r/w/e sizes. There are some cmake variables getting set in this code block. Can you confirm whether or not these checks are arbitrary and if the set variables are used elsewhere?

    if(SYSBUILD)
      function(align_up num align result)
        math(EXPR out "(((${num}) + ((${align}) - 1)) & ~((${align}) - 1))")
        set(${result} "${out}" PARENT_SCOPE)
      endfunction()
    
      function(dt_get_parent node)
        string(FIND "${${node}}" "/" pos REVERSE)
    
        if(pos EQUAL -1)
          message(ERROR "Unable to get parent of node: ${${node}}")
        endif()
    
        string(SUBSTRING "${${node}}" 0 ${pos} ${node})
        set(${node} "${${node}}" PARENT_SCOPE)
      endfunction()
    
      if(CONFIG_SINGLE_APPLICATION_SLOT OR CONFIG_BOOT_FIRMWARE_LOADER OR CONFIG_BOOT_SWAP_USING_SCRATCH OR CONFIG_BOOT_SWAP_USING_MOVE OR CONFIG_BOOT_UPGRADE_ONLY OR CONFIG_BOOT_DIRECT_XIP OR CONFIG_BOOT_RAM_LOAD)
        # TODO: RAM LOAD support
        dt_nodelabel(slot0_flash NODELABEL "slot0_partition")
        dt_get_parent(slot0_flash)
        dt_get_parent(slot0_flash)
    
        if(NOT CONFIG_SINGLE_APPLICATION_SLOT)
          dt_nodelabel(slot1_flash NODELABEL "slot1_partition")
          dt_get_parent(slot1_flash)
          dt_get_parent(slot1_flash)
    
          if(NOT "${slot0_flash}" STREQUAL "${slot1_flash}")
            # Check both slots for the one with the largest write/erase block size
            dt_prop(erase_size_slot0 PATH "${slot0_flash}" PROPERTY "erase-block-size")
            dt_prop(write_size_slot0 PATH "${slot0_flash}" PROPERTY "write-block-size")
            dt_prop(erase_size_slot1 PATH "${slot1_flash}" PROPERTY "erase-block-size")
            dt_prop(write_size_slot1 PATH "${slot1_flash}" PROPERTY "write-block-size")

    It seems like there should be documentation on the interaction between partition manager and sysbuild in 2.7.0 (perhaps in the migration guide). I asked a similar question while working on 2.6.0 and I was told that devicetree partitions weren't required to build MCUBoot.

     Understanding MCUBoot partition management 

Children
  • Hi Timothy, 
    You can try to do a quick test to set the slot0_partition and slot1_partition address to very near address , or at the very end of flash to see if you can still do DFU update. 
    From what I know we overwrite them with mcuboot_primary and mcuboot_secondary in our \nrf\include\flash_map_pm.h 

    I don't see slot0_flash and slot1_flash being used anywhere in the SDK else except from the define of them in the CMakelist.txt you pointed to. 

Related