MCUBoot/sysbuild with external partition, on XIAO_BLE device/nrf52840

Hello,

I'm trying to move my project based on the xiao_ble board from using SDK 2.6.2 with Adafruit_bootloader to SDK 2.9.0 with MCUBoot/sysbuild.

To keep things simple, I'm trying to run the "zephyr/samples/sysbuild/with_mcuboot" code, the only difference being that I added my custom board/overlay. After a few tweaks, I managed to run the application fine when using only the internal flash for both mcuboot_primary and mcuboot_secondary partitions.

Due to constraints on the project however, I have to declare mcuboot_secondary on the external flash, hence my troubles. The code compile fine, but when I run it, I get the following dynamic error:

*** Booting MCUboot v2.1.0-dev-12e5ee106034 ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
E: Failed to open flash area ID 2 (image 0 slot 1): -19, cannot continue

Here is what my sysbuild.conf file looks like:

SB_CONFIG_BOOTLOADER_MCUBOOT=y
SB_CONFIG_PARTITION_MANAGER=y
SB_CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y
SB_CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y

(The last line "SB_CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y" is dubious but it doesn't appear to do any good nor harm).

prj.conf:

CONFIG_GPIO=y
CONFIG_MULTITHREADING=y
CONFIG_NORDIC_QSPI_NOR=y

sysbuild/mcuboot.conf:

CONFIG_MCUBOOT_LOG_LEVEL_WRN=y
CONFIG_BOOT_UPGRADE_ONLY=y
CONFIG_MCUBOOT_DOWNGRADE_PREVENTION=y
CONFIG_MULTITHREADING=y
CONFIG_NORDIC_QSPI_NOR=y

pm_static.yml:

app:
  address: 0xf200
  end_address: 0x87000
  region: flash_primary
  size: 0x77e00
external_flash:
  address: 0x0
  end_address: 0x200000
  region: external_flash
  default_driver_kconfig: CONFIG_NORDIC_QSPI_NOR
  device: DT_CHOSEN(nordic_pm_ext_flash)
  size: 0x200000
mcuboot:
  address: 0x0
  end_address: 0xf000
  placement:
    align:
      end: 0x1000
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0xf000
mcuboot_pad:
  address: 0xf000
  end_address: 0xf200
  placement:
    align:
      start: 0x1000
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0xf000
  end_address: 0x100000
  orig_span: &id001
  - app
  - mcuboot_pad
  region: flash_primary
  sharers: 0x1
  size: 0x0f1000
  span: *id001
mcuboot_primary_app:
  address: 0xf200
  end_address: 0x100000
  orig_span: &id002
  - app
  region: flash_primary
  size: 0x0f0e00
  span: *id002

mcuboot_secondary:
  address: 0x0
  end_address: 0x0f1000
  device: DT_CHOSEN(nordic_pm_ext_flash)
  placement:
    align:
      start: 0x1000
    align_next: 0x1000
  region: external_flash
  share_size:
  - mcuboot_primary
  size: 0x0f1000

sram_primary:
  address: 0x20000000
  end_address: 0x20040000
  region: sram_primary
  size: 0x40000

Relevant board.overlay code snippet:

chosen {
        nordic,pm-ext-flash = &p25q16h;
    };
    

I have successfully tested that I can access the external flash by testing my custom board with the spi_flash sample, as provided (aka without bootloader nor partition manager):

*** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***

ext_flash SPI flash testing
==========================

Perform test on single sector
Test 1: Flash erase
Flash erase succeeded!

Test 2: Flash write
Attempting to write 4 bytes

How should I take it from there ? My main lead for solving the problem is about the regions.yml file that is generated in the build directory:

external_flash:
  base_address: 0x0
  default_driver_kconfig: CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK
  device: DT_CHOSEN(nordic_pm_ext_flash)
  dynamic_partition: null
  name: external_flash
  placement_strategy: start_to_end
  size: 0x40000
flash_primary:
  base_address: 0x0
  default_driver_kconfig: CONFIG_SOC_FLASH_NRF
  device: flash_controller
  dynamic_partition: null
  name: flash_primary
  placement_strategy: complex
  size: 0x100000
sram_primary:
  base_address: 0x20000000
  default_driver_kconfig: ''
  device: ''
  dynamic_partition: sram_primary
  name: sram_primary
  placement_strategy: complex
  size: 0x40000

which is almost good, but for the size of the external flash region. How am I supposed to edit this file ? The only documentation I found about regions is this. I have written a partition_manager.cmake which looks like this:

add_region(
  external_flash
  200000
  0x0
  start_to_end
  )

but I am unsure if a) this is proper code, b) how to call the actual thing (while sitting in the root directory the file doesn't have any effect on the generated regions.yml file). Of course all of this regions.yml consideration could be unrelated to the actual problem.

Thank you for your time !

Parents
  • OK I figured this out ...

    I needed to add a sysbuild/mcuboot.overlay file:

    / {
        chosen {
            nordic,pm-ext-flash = &p25q16h;
        };
    };

    in addition to the overlay file that is already providend in the board directory.

    I also had to add the two following lines to sysbuild/mcuboot.conf:

    CONFIG_BOOT_MAX_IMG_SECTORS=256
    CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

    In order to match the actual size of my partition.

    Unrelated to the issue, but to answer my previous concerns with regions.yml: the file doesn't seem relevant at all. All it seems to do is create a generic partition "external_partition" but this partition can be overriden in the pm_static.yml file.

    After some tweaks I ended up with a pm_static.yml file like this:

    app:
      address: 0xf200
      end_address: 0x87000
      region: flash_primary
      size: 0x77e00
    mcuboot:
      address: 0x0
      end_address: 0xf000
      placement:
        align:
          end: 0x1000
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0xf000
    mcuboot_pad:
      address: 0xf000
      end_address: 0xf200
      placement:
        align:
          start: 0x1000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0xf000
      end_address: 0x100000
      orig_span: &id001
      - app
      - mcuboot_pad
      region: flash_primary
      sharers: 0x1
      size: 0x0f1000
      span: *id001
    mcuboot_primary_app:
      address: 0xf200
      end_address: 0x100000
      orig_span: &id002
      - app
      region: flash_primary
      size: 0x0f0e00
      span: *id002
    
    external_flash:
      address: 0x000000
      end_address: 0x200000
      region: external_flash
      default_driver_kconfig: CONFIG_NORDIC_QSPI_NOR
      device: DT_CHOSEN(nordic_pm_ext_flash)
      orig_span: &id003
      - mcuboot_secondary
      size: 0x200000
      span: *id003
    mcuboot_secondary:
      address: 0x0
      end_address: 0x0f1000
      placement:
        align:
          start: 0x1000
      share_size:
      - mcuboot_primary
      region: external_flash
      size: 0x0f1000
    
    sram_primary:
      address: 0x20000000
      end_address: 0x20040000
      region: sram_primary
      size: 0x40000

    and "west build -t partition_manager_report" does report  a nice external partition with the correct size:

      external_flash (0x200000 - 2048kB): 
    +-------------------------------------------+
    +---0x0: external_flash (0x200000 - 2048kB)-+
    | 0x0: mcuboot_secondary (0xf1000 - 964kB)  |
    +-------------------------------------------+
    
      flash_primary (0x100000 - 1024kB): 
    +-------------------------------------------------+
    | 0x0: mcuboot (0xf000 - 60kB)                    |
    +---0xf000: mcuboot_primary (0xf1000 - 964kB)-----+
    | 0xf000: mcuboot_pad (0x200 - 512B)              |
    +---0xf200: mcuboot_primary_app (0xf0e00 - 963kB)-+
    | 0xf200: app (0xf0e00 - 963kB)                   |
    +-------------------------------------------------+
    
      sram_primary (0x40000 - 256kB): 
    +--------------------------------------------+
    | 0x20000000: sram_primary (0x40000 - 256kB) |
    +--------------------------------------------+

    Have a good day.

  • Hi there,

    Wow, this is a great Thread, and GREAT work getting it done. Exactly what I want to work with too. 

    what tool or method will you use to Update ?

    TIA

    GL  :-) PJ :v:

Reply Children
  • Hello, thank you for your kind words.

    Do you mean to update the software version ? I'm currently using SMP server on the chip, and deploy with nRFConnect on my phone. It is really straightforward to set this up once you have MCUBoot running.

    At some point I will have to replace nRFConnect with my own application for the purpose of pushing updates to the device. I'm not there yet though.

    Have a nice day.

  • Hi there,

    So for me the best solution is to use my MIT app Front-end and just use the NRF DFU behind the scense as I understand it I can do it two ways , one just hand off the task to NRF when the user selects UPDATE on my app that controls the device through BLE. the second is to have The NRF DFU as a gateway always running in the background. I'm investigating the former. 

    GL :-) PJ :v:

    LIke this:

    MIT App Inventor as a Front End:
    Instead of trying to implement all the DFU logic in your MIT App Inventor project (which can be very challenging given its limited native BLE blocks), you can use it to:

    • Configure the Device: Allow the user to select firmware, configure update settings, or display update status.
    • Launch the DFU Process: When an update is needed, your MIT App Inventor app can simply call an intent (on Android) or use a similar mechanism to open the dedicated DFU app.
    • Monitor and Report: Optionally, your app could get a status update (if the DFU client can pass back information) or simply notify the user that the update is in progress and then completed.
  • Okay, interesting. Unfortunately I can't help you getting through this, but I wish you good luck with your endeavors :)

Related