nRF53 Custom b0n Build

I am trying to compile a custom bootloader for nRF5340 net core (b0n) that is part of a multi-image build.

I have created two separate applications, one based on b0n (nrf/samples/nrf5340/netboot) and one based on nrf/samples/bluetooth/peripheral_lbs. These both build without issue when used as single image applications and I can debug them (using hello_world on the app core) and they appear to work.

I have tried adding the b0n as a child image of the application by adding the following code to CMakeLists.txt

if (CONFIG_SECURE_BOOT)
  add_child_image(
    NAME b0n
    SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../boot_stage1
  )
endif()

If I then build the net app, the application builds, but b0n is neither built nor linked.

I have tried adding CONFIG_SECURE_BOOT=y to the prj.conf file. If I have the above CMakeLists.txt change, I get the following compilation error:

=== child image b0n -  begin ===
loading initial cache file C:/Users/anton/src/bootloader-test/netapp/build/b0n/child_image_preload.cmake
CMake Error: The source "C:/Users/anton/src/bootloader-test/boot_stage1/CMakeLists.txt" does not match the source "C:/Users/anton/ncs/v1.9.1/nrf/samples/nrf5340/netboot/CMakeLists.txt" used to generate cache.  Re-run cmake with a different source directory.
CMake Error at C:\Users\anton\ncs\v1.9.1\nrf\cmake\multi_image.cmake:409 (message):
  CMake generation for b0n failed, aborting.  Command: 1
Call Stack (most recent call first):
  C:\Users\anton\ncs\v1.9.1\nrf\cmake\multi_image.cmake:150 (add_child_image_from_source)
  c:\Users\anton\src\bootloader-test\netapp\build\CMakeLists.txt:21 (add_child_image)
This confuses me in the following ways
  • I don't know why the netboot sample should be used to generate the cache.
  • The CMakeLists.txt are identical in both the sample and in my local build.
  • I don't know why they need to match anyway.

What is going wrong here?

p.s. Most of the documnetation about multi-image bootloader builds suggest using CONFIG_B0_BUILD_STRATEGY_FROM_SOURCE=y. There doesn't appear to be an equivalent CONFIG_B0N_BUILD_STRATEGY_FROM_SOURCE.

  • Hi Anton

    I have tried adding the b0n as a child image of the application by adding the following code to CMakeLists.txt

    Can you specify which CmakeLists.txt you are referring to here?

    If I then build the net app

    The b0n is usually used alongside the bootloader in the application core. What happens if you build for nrf5340dk_nrf5340_cpuapp instead?

    Regards,
    Sigurd Hellesvik

  • The CMakeLists.txt that I am referring to is the root level CMakeLists.txt for the application on the net core (based on nrf/samples/bluetooth/peripheral_lbs on the net core).

    I think you are mistaken: b0 is the app core bootloader, b0n is the net core bootloader (https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/nrf5340/netboot/README.html). Also, as I have said, I can compile and run b0n on the net core without issue. Also, b0n isn't used alongside the bootloader, it is a bootloader. Did you mean it is often run alongside mcuboot as a set of first and second stage bootloaders?

    Edited: I attempted to build the b0n/app using app core but that failed as it was unable to find "pm_config.h" ... but I don't think that is the correct path to follow anyway.

  • Hi

    I explain a bunch of context. However, it might not be super-relevant for you until the red text further down.

    I agree with you here, I were unspecific in my previous answer.
    b0n is the bootloader for the network core.
    For the application core, you can use b0 and/or MCUBoot as a bootloader.

    For a typical example for use of b0n, with context:
    Our Machine Learning sample has configurations for bootloader support on the nRF5340.
    In this sample, MCUBoot is running on the Application Core, while b0n is running at the Network Core.
    To update the firmware, the nRF5340 has to enter Serial Recovery mode or using the Simple Management Protocol over Bluetooth.
    This will use the mcumgr tool to upload an image to the application core, which is then swapped to the network core using Peripheral CPU DFU (PCD).
    When you now reboot, b0n will boot into the new image.

    So when i sat "alongside", I really mean that it is generally not the only bootloader running on the nRF5340.

    I should point out that use of the b0n is a bit weird in the sense of multi-images.
    Normally, you can use overlays in your project to change the configurations of your child images.
    Or you could add a custom child image to your project, to avoid making changes to the nRF Connect SDK directly.
    When using the nRF5340, the code running on the network core will be built as a child image of the application.
    For example, if CONFIG_BT=y when you build for your nrf5340dk_nrf5340, the child image hci_rpmsg is added to your project.

    However, if you want to use the b0n, it is added as a child image of the child image running on the network core. (for example a child_image of hci_rpmsg).
    There is one  way to add a configuration overlay to a "recursive" child image, by nesting their names in CMake variables for child image configurations:

    west build -b nrf5340dk_nrf5340_cpuapp -- -Dhci_rpmsg_b0n_CONFIG_DEBUG=y

    So I think your approach is the best way to add a custom b0n: By first making an custom application for the network core. Then you can add this as a child image when you later make firmware for the network core.
    To try to answer your question:

    If I then build the net app, the application builds, but b0n is neither built nor linked.

    I have not been able to find where in the nRF Connect SDK this is set,
    but I am able to build with a custom b0n if I build hello_world for nrf52840dk_nrf52840_cpuapp with the following configurations:

    CONFIG_BT=y
    CONFIG_SECURE_BOOT=y
    CONFIG_BOOTLOADER_MCUBOOT=y
    

    (Hello World since it is a minimal sample)

    I will continue looking into child images next week, to try to find more for you. If you are able to figure out something in the meantime, let me know.

    Regards,
    Sigurd Hellesvik

  • I assume when you say that you are building a custom b0n for the cpuapp you mean that you are building a custom b0 for the cpuapp.

    So, I can get it to build the b0n image now. I just had to remove the "if (CONFIG_SECURE_BOOT)" and set that config to "n" in the prj.conf for the net application. It then tells me that it cannot add the child image unless "CONFIG_PARTITION_MANAGER_ENABLED" is set to "y". Fine. I do that. Then I get a build error where it cannot find "pm_config.h".

    Now I have chased that down to the following link: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html

    Now that link says that:

    So for some reason the partition manager script must not be running and must not be generating the "pm_config.h" header, or it is not in the correct include path. How do I rectify that?

  • I have tracked it down to the file "partition_manager.cmake", which should make the "pm_config.h" file. This section of code is where it exits before actually creating the header file.

    # This file is executed once per domain.
    #
    # It will be executed if one of the following criteria is true for the
    # current image:
    # - It's a child image, and is the dynamic partition in the domain
    # - It's the root image, and a static configuration has been provided
    # - It's the root image, and PM_IMAGES is populated.
    # - It's the root image, and other domains exist.
    # - A subsys has defined a partition and CONFIG_PM_SINGLE_IMAGE is set.
    # Otherwise, return here
    if (NOT (
      (IMAGE_NAME AND is_dynamic_partition_in_domain) OR
      (NOT IMAGE_NAME AND static_configuration) OR
      (NOT IMAGE_NAME AND PM_IMAGES) OR
      (NOT IMAGE_NAME AND PM_DOMAINS) OR
      (PM_SUBSYS_PREPROCESSED AND CONFIG_PM_SINGLE_IMAGE)
      ))
      return()
    endif()
     
    None of the above are true and so it doesn't create the header file. By adding CMake messages, I can see that:
    • For b0n the IMAGE_NAME is set to b0n and the other parameters are empty. I assume this means that b0n shouldn't build the pm_config.h (which is what I would expect.
    • None of the other parameters are set for the application, which seems wrong.
    • This seems like PM_IMAGES or PM_DOMAINS should not be blank ...

    What should these parameters be? Where should they be set?

Related