I’m working on an nRF52832-based project using the Nordic SDK (v3.5.99-ncs1-1) and MCUboot for OTA updates. I have a 512KB internal flash and 4MB external SPI flash (P25Q32H) configured. Partition Manager is enabled, and I’m using both internal and external flash for primary and secondary image storage. However, upon booting, I consistently get the following error message:
*** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
Attempting to boot slot 0.
No fw_info struct found.
Attempting to boot slot 1.
No fw_info struct found.
No bootable image found. Aborting boot.
It seems that MCUboot is unable to find a valid firmware image in either slot. Below are the details of my partition setup and configuration:
DTS File
// Copyright (c) 2024 Nordic Semiconductor ASA
// SPDX-License-Identifier: Apache-2.0
/dts-v1/;
#include <nordic/nrf52832_qfaa.dtsi>
#include "fde_x2-pinctrl.dtsi"
/ {
model = "FDE_x2";
compatible = "sollatek,fde-x2";
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,code-partition = &boot_partition;
zephyr,shell-uart = &uart0;
zephyr,gpio = &gpio0;
zephyr,console = &uart0;
zephyr,uart-mcumgr = &uart0;
nordic,pm-ext-flash = &dev_spi_flash;
};
zephyr,user {
modem_pwrkey-gpios = <&gpio0 12 0>;
modem_pwr_en-gpios = <&gpio0 25 0>;
modem_reset-gpios = <&gpio0 11 0>;
acc_int1-gpios = <&gpio0 30 0>;
acc_cs-gpios = <&gpio0 31 0>;
uart0_wifi = <&uart0_wifi>;
uart0_stm = <&uart0_stm>;
uart0_gsm = <&uart0_gsm>;
uart0_default = <&uart0_default>;
io-channels = <&adc 5>;
power_detect-gpios = <&gpio0 28 0>;
wifi_pwr_en-gpios = <&gpio0 2 0>;
};
aliases {
spi0dev = &spi0;
watchdog0 = &wdt;
rtc2dev = &rtc2;
spi-flash0 = &dev_spi_flash;
};
};
&uart0 {
compatible = "nordic,nrf-uarte";
status = "okay";
current-speed = <115200>;
label = "UART_0";
pinctrl-0 = <&uart0_default>;
pinctrl-names = "default";
};
&gpio0 {
status = "okay";
gpiote-instance = <&gpiote>;
};
&gpiote {
status = "okay";
};
&spi0 {
compatible = "nordic,nrf-spi";
status = "okay";
pinctrl-0 = <&spi0_default_alt>;
pinctrl-1 = <&spi0_sleep_alt>;
pinctrl-names = "default", "sleep";
cs-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>,
<&gpio0 31 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
label = "DEV_SPI0";
dev_spi_flash: dev_spi_flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
label = "DEV_SPI_FLASH";
status = "okay";
jedec-id = [ 85 60 16 ]; //P25Q32H
size = <(1048576 * 8 * 4)>;//4MB
spi-max-frequency = <8000000>;
};
};
&rtc2 {
status = "okay";
};
&systick {
status = "disabled";
};
&adc {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
channel@5 {
reg = <5>;
zephyr,gain = "ADC_GAIN_1_6";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN5>;
zephyr,resolution = <8>;
zephyr,oversampling = <8>;
};
};
&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
boot_partition: partition@8200 {
label = "mcuboot";
reg = <0x8200 0x10000>;
};
slot0_partition: partition@2a000 {
label = "image-0";
reg = <0x2a000 0x56000>;
};
};
};
&dev_spi_flash {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
slot1_partition: partition@0 {
label = "image-1";
reg = <0x00 0x56000>;
};
};
};
pm_static.yml
EMPTY_0:
address: 0x18200
end_address: 0x19000
placement:
before:
- s1_pad
region: flash_primary
size: 0xe00
EMPTY_1:
address: 0x29200
end_address: 0x2a000
placement:
before:
- mcuboot_pad
region: flash_primary
size: 0xe00
app:
address: 0x2a200
end_address: 0x80000
region: flash_primary
size: 0x55e00
app_image:
address: 0x2a200
end_address: 0x80000
orig_span: &id001
- app
region: flash_primary
size: 0x55e00
span: *id001
b0:
address: 0x0
end_address: 0x7000
placement:
after:
- start
region: flash_primary
size: 0x7000
b0_container:
address: 0x0
end_address: 0x8000
orig_span: &id002
- b0
- provision
region: flash_primary
size: 0x8000
span: *id002
external_flash_storage:
address: 0x5E000
end_address: 0x400000
region: external_flash
size: 0x3A2000
external_flash_params:
address: 0x56000
end_address: 0x5E000
region: external_flash
size: 0x8000
external_flash_ota:
address: 0x00
end_address: 0x56000
region: external_flash
size: 0x56000
mcuboot:
address: 0x8200
end_address: 0x18200
placement:
before:
- mcuboot_primary
region: flash_primary
sharers: 0x1
size: 0x10000
mcuboot_pad:
address: 0x2a000
end_address: 0x2a200
placement:
align:
start: 0x1000
before:
- mcuboot_primary_app
region: flash_primary
sharers: 0x2
size: 0x200
mcuboot_primary:
address: 0x2a000
end_address: 0x80000
orig_span: &id003
- mcuboot_pad
- app
region: flash_primary
size: 0x56000
span: *id003
mcuboot_primary_app:
address: 0x2a200
end_address: 0x80000
orig_span: &id004
- app
region: flash_primary
size: 0x55e00
span: *id004
mcuboot_secondary:
address: 0x0
device: DT_CHOSEN(DEV_SPI_FLASH)
end_address: 0x56000
placement:
align:
start: 0x4
region: external_flash
share_size:
- mcuboot_primary
size: 0x56000
provision:
address: 0x7000
end_address: 0x8000
placement:
after:
- b0
align:
start: 0x1000
region: flash_primary
size: 0x1000
s0:
address: 0x8000
end_address: 0x18200
orig_span: &id005
- s0_pad
- mcuboot
region: flash_primary
size: 0x10200
span: *id005
s0_image:
address: 0x8200
end_address: 0x18200
orig_span: &id006
- mcuboot
region: flash_primary
size: 0x10000
span: *id006
s0_pad:
address: 0x8000
end_address: 0x8200
placement:
after:
- b0_container
align:
start: 0x1000
region: flash_primary
share_size:
- mcuboot_pad
size: 0x200
s1:
address: 0x19000
end_address: 0x29200
orig_span: &id007
- s1_pad
- s1_image
region: flash_primary
size: 0x10200
span: *id007
s1_image:
address: 0x19200
end_address: 0x29200
placement:
after:
- s1_pad
- s0
region: flash_primary
share_size:
- mcuboot
size: 0x10000
s1_pad:
address: 0x19000
end_address: 0x19200
placement:
after:
- s0
align:
start: 0x1000
region: flash_primary
share_size:
- mcuboot_pad
size: 0x200
sram_primary:
address: 0x20000000
end_address: 0x20010000
region: sram_primary
size: 0x10000
prj.conf
# Configure Cosnsole (Debug) CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=n CONFIG_RTT_CONSOLE=y CONFIG_USE_SEGGER_RTT=y CONFIG_SEGGER_RTT_BUFFER_SIZE_DOWN=128 # Configure Internal Clock CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y # NFC pins as GPIOs CONFIG_NFCT_PINS_AS_GPIOS=y # MCUBOOT and DFU CONFIG_BOOTLOADER_MCUBOOT=y CONFIG_DFU_TARGET_MCUBOOT=y CONFIG_STREAM_FLASH=y CONFIG_STREAM_FLASH_ERASE=y CONFIG_DFU_TARGET=y CONFIG_DFU_TARGET_STREAM=y CONFIG_SECURE_BOOT=y CONFIG_IMG_MANAGER=y CONFIG_IMG_ERASE_PROGRESSIVELY=y CONFIG_MCUBOOT_IMG_MANAGER=y # Configure Watchdog CONFIG_WATCHDOG=y CONFIG_WDT_DISABLE_AT_BOOT=n # Configure UART CONFIG_SERIAL=y CONFIG_UART_USE_RUNTIME_CONFIGURE=y # Configure GPIO CONFIG_GPIO=y # Configure SPI CONFIG_SPI=y # Configure GPIO CONFIG_GPIO_AS_PINRESET=n CONFIG_PINCTRL=y CONFIG_PINCTRL_DYNAMIC=y # Configure RTC CONFIG_COUNTER=y # Configure ADC CONFIG_ADC=y # Main Thread Stack Size CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_MAIN_STACK_SIZE=8192 # Debug CONFIG_PARAM_SYSTEM_LOG=y CONFIG_PARAM_MODEM_LOG=n CONFIG_PARAM_GWC_LOG=n CONFIG_PARAM_STM_LOG=n # Enable HW INFO CONFIG_HWINFO=y # BLE CONFIG_BT=y # BLE Central CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y CONFIG_BT_GATT_CLIENT=y # Enable the BLE Central modules from NCS CONFIG_BT_SCAN=y CONFIG_BT_SCAN_FILTER_ENABLE=y CONFIG_BT_SCAN_ADDRESS_CNT=1 CONFIG_BT_GATT_DM=y # BLE Peripheral CONFIG_BT_PERIPHERAL=y CONFIG_BT_DEVICE_NAME="FDE" CONFIG_BT_MAX_CONN=2 CONFIG_BT_MAX_PAIRED=2 CONFIG_BT_DEVICE_NAME_DYNAMIC=y CONFIG_BT_DEVICE_NAME_MAX=65 # SPI Flash CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_FLASH_MAP=y CONFIG_MPU_ALLOW_FLASH_WRITE=y CONFIG_SPI_ASYNC=y CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 # Firmware Version CONFIG_APP_HW_VERSION_MAJOR=1 CONFIG_APP_FW_VERSION_MAJOR=6 CONFIG_FW_INFO=y
mcuboot.conf
# SPI and Flash CONFIG_SPI=y CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 # Multithreading CONFIG_MULTITHREADING=y #MCU BOOT CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y CONFIG_BOOT_SIGNATURE_KEY_FILE="./certs/mcuboot_pkey.pem" CONFIG_BOOT_MAX_IMG_SECTORS=128 CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x10000 # Configure Internal Clock CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y # NFC pins as GPIOs CONFIG_NFCT_PINS_AS_GPIOS=y
What I’ve Tried So Far:
- I’ve ensured that the partition sizes between the internal and external flash for slot 0 and slot 1 are the same (448KB).
- The external SPI flash is properly configured and recognized in the device tree (
jedec,spi-norcompatible). - Partition Manager seems to generate the correct memory map, and I have verified this by inspecting
build/zephyr/pm.yml. - I am able to flash the primary image (
image_0_partition) using thewest flashcommand, but the bootloader still cannot detect any valid firmware in either slot.
My Questions:
- What could be causing the bootloader to not find the
fw_infostruct in either slot 0 or slot 1? - Is there any additional configuration required to ensure that the
fw_infois properly embedded in the image so that MCUboot can detect it? - Do I need any specific settings in the
prj.conffile to make sure the bootloader can correctly identify and boot from the internal or external flash? - Is there a recommended way to debug and confirm whether the firmware image is being properly written and contains the expected metadata?
Any help or guidance would be greatly appreciated!
Additional Info:
- Chip: nRF52832 (512KB internal flash, 64KB SRAM)
- SDK Version: 2.6.1
- External Flash: P25Q32H (4MB SPI NOR flash)
- MCUboot: Enabled via Partition Manager
- Toolchain: Zephyr with
westbuild system
Thank you for your assistance!