NCS 2.0 custom child image + mcuboot build

Hi,

In NCS 2.0, the ability to add a custom child image was added. This works fine but as soon as you include the mcuboot child image, the order of the child image builds changes.

For example,

If I build an application including mcuboot and the hci_rpmsg sample app, the child build order looks like this:

=== child image hci_rpmsg - CPUNET begin ===
=== child image b0n - CPUNET (inherited) begin ===
=== child image b0n - CPUNET (inherited) end ===
=== child image hci_rpmsg - CPUNET end ===
=== child image mcuboot - begin ===
=== child image mcuboot - end ===

If I build an application including mcuboot plus a custom child image, the child build order looks like this:

=== child image mcuboot - begin ===
=== child image mcuboot - end ===
=== child image hci_rpmsg - CPUNET begin ===
=== child image b0n - CPUNET (inherited) begin ===
=== child image b0n - CPUNET (inherited) end ===
=== child image hci_rpmsg - CPUNET end ===

The output of the mcuboot with the hci_rpmsg sample in the build/zephyr directory includes the following files:

app_to_sign.bin

app_update.bin

isrList.bin

net_core_app_to_sign.bin

net_core_app_update.bin  zephyr.bin

zephyr.bin

The output of the mcuboot with the custom child image in the build/zephyr directory include the following files:

app_to_sign.bin

app_update.bin

isrList.bin

zephyr.bin

The build with the custom child image is missing the net_core_app_to_sign.bin and net_core_app_update.bin files.

I did some investigation and it looks like the two missing files are generated in the following C:\ncs\v2.0.0\nrf\modules\mcuboot\CMakeLists.txt file.

    get_shared(cpunet_signed_app_hex IMAGE CPUNET PROPERTY PM_SIGNED_APP_HEX)

    if (CONFIG_NRF53_UPGRADE_NETWORK_CORE
        AND DEFINED cpunet_signed_app_hex)
      # Network core application updates are enabled.
      # We know this since MCUBoot is enabled on the application core, and
      # a network core child image is included in the build.
      # These updates are verified by the application core MCUBoot.
      # Create a signed variant of the network core application.

      get_shared(cpunet_images IMAGE CPUNET PROPERTY PM_DOMAIN_IMAGES)
      foreach(image ${cpunet_images})
        if(${image} MATCHES "CPUNET:(.*)")
          set(image_name ${CMAKE_MATCH_1})
          if(TARGET ${image_name}_subimage)
            get_shared(${image_name}_byproducts IMAGE ${image_name} PROPERTY BUILD_BYPRODUCTS)
            list(APPEND sign_depends ${image_name}_subimage ${${image_name}_byproducts})
          endif()
        endif()
      endforeach()

      set(net_core_binary_name net_core_app_update.bin)

      if (CONFIG_NRF53_ENFORCE_IMAGE_VERSION_EQUALITY)
        # Add dependency inside network core image to require the latest application core image.
        set(sign_dependencies IMAGE_DEPENDENCIES "(${APPLICATION_IMAGE_PAIR_IDX},${CONFIG_MCUBOOT_IMAGE_VERSION})")
      endif()

      sign(
        SIGNED_BIN_FILE_IN ${cpunet_signed_app_hex}
        SIGNED_HEX_FILE_NAME_PREFIX ${PROJECT_BINARY_DIR}/net_core_app
        SLOT_SIZE $<TARGET_PROPERTY:partition_manager,net_app_slot_size>
        START_ADDRESS_OFFSET $<TARGET_PROPERTY:partition_manager,net_app_TO_SECONDARY>
        SIGNED_HEX_FILE_OUT net_core_app_signed_hex
        SIGNED_BIN_FILE_OUT net_core_app_signed_bin
        SIGNED_HEX_TEST_FILE_OUT net_core_app_signed_test_hex
        ${sign_dependencies}
        DEPENDS ${sign_depends}
        )

      add_custom_target(
        net_core_app_sign_target
        DEPENDS ${net_core_app_signed_hex}
          ${net_core_app_signed_bin}
          ${net_core_app_signed_test_hex}
        )

      add_dependencies(
        mcuboot_sign_target
        net_core_app_sign_target
        )

      get_shared(net_core_soc IMAGE net_core PROPERTY SOC)
      get_shared(net_core_version IMAGE net_core PROPERTY VERSION)

      set(generate_bin_files
        ${PROJECT_BINARY_DIR}/${app_core_binary_name}
        ${PROJECT_BINARY_DIR}/${net_core_binary_name}
        )
      set(generate_script_params
        "${app_core_binary_name}load_address=$<TARGET_PROPERTY:partition_manager,PM_APP_ADDRESS>"
        "${app_core_binary_name}image_index=0"
        "${app_core_binary_name}slot_index_primary=1"
        "${app_core_binary_name}slot_index_secondary=2"
        "${app_core_binary_name}version_MCUBOOT=${CONFIG_MCUBOOT_IMAGE_VERSION}"
        "${net_core_binary_name}image_index=1"
        "${net_core_binary_name}slot_index_primary=3"
        "${net_core_binary_name}slot_index_secondary=4"
        "${net_core_binary_name}load_address=$<TARGET_PROPERTY:partition_manager,CPUNET_PM_APP_ADDRESS>"
        "${net_core_binary_name}board=${CONFIG_DOMAIN_CPUNET_BOARD}"
        "${net_core_binary_name}version=${net_core_version}"
        "${net_core_binary_name}soc=${net_core_soc}"
        )
    else()
      # No network core update
      set(generate_bin_files
        ${PROJECT_BINARY_DIR}/${app_core_binary_name}
        )
      set(generate_script_params
        "load_address=$<TARGET_PROPERTY:partition_manager,PM_APP_ADDRESS>"
        "version_MCUBOOT=${CONFIG_MCUBOOT_IMAGE_VERSION}"
        )
    endif()

Since mcuboot is built first, the PM_SIGNED_APP_HEX variable (in line #1 above) is not defined. The PM_SIGNED_APP_HEX variable is set when the custom child image is built.

Let me know if there's a fix that I can apply to the CMake files to fix the build order.  I haven't figured out a way to fix it yet.

Thanks

  • Hello,

    We will get back to you on this. Note that we are in the summer holiday period in Norway and staffing is low, so some delays should be expected.

    Regards,

    Elfving

  • Hi Ronald,

    We are looking into this. Would you be able to share a simple project demonstrating this?

    Regards,

    Håkon

  • Hi Håkon,

    You can duplicate the out of order child image builds by building the multicore sample application located in the /c/ncs/v2.0.0/nrf/samples/nrf5340/multicore directory using the following west build options.

    $ west build -p -b nrf5340dk_nrf5340_cpuapp -- -DCONFIG_BOOTLOADER_MCUBOOT=y > build.log 2>&1

    $ grep "child image" build.log
    === child image mcuboot - begin ===
    === child image mcuboot - end ===
    === child image cpunet - cpunet begin ===
    === child image cpunet - cpunet end ===

    I wasn't successful in modifying the project to also build the b0n bootloader. I tried creating a child_image/mcuboot.conf file with the CONFIG_PCD=y, but I get a build error about PM_CPUNET_B0N_CONTAINER_SIZE being undefined.

    Regards,

    Ronald

  • Hi Ronald

    Håkon is currently on leave, and I will help you with this in the mean time. 

    The build order is not explicitly stated anywhere, and will be a result of what order the modules are included. 

    This can be affected by using the depends key in your module.yml file. 

    It is possible that we are missing some dependencies to ensure that the build order is correct when custom child images are added, but I will need some more time to look into this. I will do my best to get you an update by the end of the week. 

    If you haven't found it already there is more information on the module system here

    Best regards
    Torbjørn

  • Hi Torbjørn,

    FYI. I tried updating the multicore zephyr/module.yml file to look like this

    $ cat zephyr/module.yml
    build:
    cmake: aci
    depends:
    - mcuboot

    but it didn't change the build order. MCUboot still got built first.

Related