Dear Nordic team,
I am trying to set up OTA updates by using the DFU target API on an nRF9151 DK with MCUboot and TF-M partitions. (NCS v3.4.1) My goal is to use the immutable MCUboot bootloader and update both the application and the TF-M partition. I've declared
SB_CONFIG_BOOTLOADER_MCUBOOT=y
in the project's "sysbuild.conf" file and have set up a board overlay (PROJECT_DIR/boards/nrf9151dk_nrf9151_ns.overlay) with the following partitions.
/ {
chosen {
nordic,pm-ext-flash = &gd25wb256;
};
};
/delete-node/ &boot_partition;
/delete-node/ &slot0_partition;
/delete-node/ &slot1_partition;
/delete-node/ &tfm_ps_partition;
/delete-node/ &tfm_its_partition;
/delete-node/ &tfm_otp_partition;
/delete-node/ &storage_partition;
&flash0 {
/*
* Flash partition layout for non-minimal TF-M in combination with MCUboot
*
* 0x0000_0000 BL2 - MCUBoot (64 KB)
* 0x0001_0000 Primary image area (448 KB):
* 0x0001_0000 Secure image primary (192 KB)
* 0x0004_0000 Non-secure image primary (256 KB)
* 0x0008_0000 Secondary image area (448 KB):
* 0x0008_0000 Secure image secondary (192 KB)
* 0x000b_0000 Non-secure image secondary (256 KB)
* 0x000f_0000 Protected Storage Area (16 KB)
* 0x000f_4000 Internal Trusted Storage Area (8 KB)
* 0x000f_6000 OTP / NV counters area (8 KB)
* 0x000f_8000 Non-secure storage, used when built with NRF_NS_STORAGE=ON,
* otherwise unused (32 KB)
*/
partitions {
ranges;
#address-cells = <1>;
#size-cells = <1>;
boot_partition: partition@0 {
compatible = "zephyr,mapped-partition";
label = "mcuboot";
reg = <0x00000000 0x10000>;
};
slot0_partition: partition@10000 {
compatible = "zephyr,mapped-partition";
label = "image-0";
reg = <0x00010000 0x70000>;
ranges = <0x0 0x10000 0x70000>;
#address-cells = <1>;
#size-cells = <1>;
slot0_s_partition: partition@0 {
compatible = "zephyr,mapped-partition";
label = "image-0-secure";
reg = <0x00000000 0x30000>;
};
slot0_ns_partition: partition@30000 {
compatible = "zephyr,mapped-partition";
label = "image-0-nonsecure";
reg = <0x00030000 0x40000>;
};
};
slot1_partition: partition@80000 {
compatible = "zephyr,mapped-partition";
label = "image-1";
reg = <0x00080000 0x70000>;
ranges = <0x0 0x80000 0x70000>;
#address-cells = <1>;
#size-cells = <1>;
slot1_s_partition: partition@0 {
compatible = "zephyr,mapped-partition";
label = "image-1-secure";
reg = <0x00000000 0x30000>;
};
slot1_ns_partition: partition@30000 {
compatible = "zephyr,mapped-partition";
label = "image-1-nonsecure";
reg = <0x00030000 0x40000>;
};
};
tfm_ps_partition: partition@f0000 {
compatible = "zephyr,mapped-partition";
label = "tfm-ps";
reg = <0x000f0000 0x00004000>;
};
tfm_its_partition: partition@f4000 {
compatible = "zephyr,mapped-partition";
label = "tfm-its";
reg = <0x000f4000 0x00002000>;
};
tfm_otp_partition: partition@f6000 {
compatible = "zephyr,mapped-partition";
label = "tfm-otp";
reg = <0x000f6000 0x00002000>;
};
storage_partition: partition@f8000 {
compatible = "zephyr,mapped-partition";
label = "storage";
reg = <0x000f8000 0x00008000>;
};
};
};
/delete-node/ &sram0_s;
/delete-node/ &sram0_ns;
&sram0 {
/*
* SRAM partition layout for non-minimal TF-M
*
* 0x2000_0000 Secure RAM ( 88 kB)
* 0x2001_6000 Non-secure RAM area ( 168 kB)
* 0x2001_6000 Modem shared area ( 17768 B)
* 0x2001_6000 control ( 1256 B)
* 0x2001_64e8 app -> cell ( 8320 B)
* 0x2001_8568 cell -> app ( 8 kB)
* 0x2001_a568 Application RAM (154264 B)
*/
sram0_s: sram@0 {
reg = <0x0 0x16000>;
};
sram0_ns: sram@16000 {
reg = <0x16000 0x2a000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x16000 0x2a000>;
/* Must be in first 128 kB of RAM. */
sram0_ns_modem: sram0_ns@0 {
/* Modem (shared) memory */
reg = <0x0 0x4568>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x4568>;
cpuapp_cpucell_ipc_shm_ctrl: sram0_ns_modem@0 {
/* Modem IPC control */
reg = <0x0 0x4e8>;
};
cpuapp_cpucell_ipc_shm_heap: sram0_ns_modem@4e8 {
/* Modem IPC transmit */
reg = <0x4e8 0x2080>;
};
cpucell_cpuapp_ipc_shm_heap: sram0_ns_modem@2568 {
/* Modem IPC receive */
reg = <0x2568 0x2000>;
};
};
sram0_ns_app: sram0_ns@4568 {
/* Non-Secure application memory */
reg = <0x4568 0x25a98>;
};
};
};
&gd25wb256 {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
lfs_partition: partition@0 {
label = "lfs_storage";
// reg = <0x00000000 0x00040000>; /* 256kB */
reg = <0x00000000 0x02000000>; /* 32MB */
};
};
};
The code initializes the DFU target, downloads update chunks via CoAP and writes the chunks with `dfu_target_write`. The code compiles and runs, but causes a "SECURE FAULT" when running `dfu_target_write`:
[00:00:23.089,080] <err> os: ***** SECURE FAULT ***** [00:00:23.089,080] <err> os: Address: 0x80000 [00:00:23.089,111] <err> os: Attribution unit violation [00:00:23.089,141] <err> os: r0/a1: 0x00080000 r1/a2: 0x00000000 r2/a3: 0xffffffff [00:00:23.089,172] <err> os: r3/a4: 0x40039000 r12/ip: 0x00000100 r14/lr: 0x0004d47b [00:00:23.089,202] <err> os: xpsr: 0x21000000 [00:00:23.089,233] <err> os: Faulting instruction address (r15/pc): 0x000532fe [00:00:23.089,324] <err> os: >>> ZEPHYR FATAL ERROR 41: Unknown error on CPU 0 [00:00:23.089,416] <err> os: Current thread: 0x200203c8 (main) [00:00:23.282,043] <err> os: Halting system
My thoughts are that the "SECURE FAULT" might be caused, because the `slot1_partition` might be treated as a secure partition and therefore cannot be written to. (the fault points to the start of slot1_partitions's flash range) Also, I suspect that the image number passed into `dfu_target_init` might be incorrect. At first I though it would have to be set to `0` or `CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER`, but I am not sure about that. My current DFU target initialization looks like this:
#define IMAGE_NUMBER 0
...
int32_t img_type = dfu_target_img_type(chunk, chunk_len);
err = dfu_target_init(img_type, IMAGE_NUMBER, file_size, NULL);
if (err < 0) {
LOG_DBG("Failed to initialize DFU target, errno: %d", err);
goto out;
}
...
I've also tried to reference the board overlay in the "PROJECT_DIR/sysbuild_mcubot/boards" directory. There I've added a "nrf9151dk_nrf9151_ns.overlay" file with the following content:
#include "../../../boards/nrf9151dk_nrf9151_ns.overlay" #include "../app.overlay"
The included "app.overlay" file has:
/ {
chosen {
zephyr,code-partition = &boot_partition;
};
};
Am I missing some definitions in the overlay file, or does Sysbuild have to be made aware of the partitions some other way?
Is the image number `0` correct for this case?
To allow for modem delta updates in the next step, is this setup viable and can the same DFU target procedure and initialization be used?
Guidance is greatly appreciated.
Best,
Tom