MCUBoot Not finding a image

Hi,

I have searched the forum but haven't been able to find a solution that works for me. But I am using a nRF9160 on a custom board and am trying to use SDK 2.5.0 with MCUBoot and TFM for secure boot. The application is a simple one to start with, I just want to print some statements using printk to get some information about the modem and then turn the modem on to connect to the network. I have the application building and can flash the nRF9160 using a jlink, but whenever I try to run the program, MCUBoot gives me an error saying that the primary slot is not valid. I have attached my configurations below as well as the static partitions I'm attempting to use. Can you please help? 

Terminal Output from device: 

*** Booting nRF Connect SDK v2.5.0 ***
I: Starting bootloader
I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
I: Boot source: none
I: Image index: 0, Swap type: none
E: Image in the primary slot is not valid!
E: Unable to find bootable image

Configuration File for the board: 

# SPDX-License-Identifier: Apache-2.0

CONFIG_SOC_SERIES_NRF91X=y
CONFIG_SOC_NRF9160_SICA=y
CONFIG_BOARD_SANSA_NS=y

# Enable MPU
CONFIG_ARM_MPU=y

# Enable hardware stack protection
CONFIG_HW_STACK_PROTECTION=y

# Enable TrustZone-M
CONFIG_ARM_TRUSTZONE_M=y
CONFIG_BUILD_WITH_TFM=y

# This Board implies building Non-Secure firmware
CONFIG_TRUSTED_EXECUTION_NONSECURE=y

# enable GPIO
CONFIG_GPIO=y

# Enable uart driver
CONFIG_SERIAL=y

# enable console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

CONFIG_PINCTRL=y

Configuration file of the project: 

# Network
CONFIG_NETWORKING=y
CONFIG_NET_NATIVE=n
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_OFFLOAD=y

# Modem library
CONFIG_NRF_MODEM_LIB=y
CONFIG_MODEM_INFO=y

# LTE link control
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n

# NEWLIB C
CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

#Ensure an MCUboot - compatible binary is generated.
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_MCUBOOT_BOOTUTIL_LIB=y

# Enable the serial mcumgr transport.
#CONFIG_MCUMGR_SMP_UART=y

# Some command handlers require a large stack.
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_HEAP_MEM_POOL_SIZE=2048

CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE1=y
CONFIG_UART_INTERRUPT_DRIVEN=y

CONFIG_PWM=y

CONFIG_PM_SINGLE_IMAGE=y

pm_static.yml:

EMPTY_0:
  address: 0xf0000
  end_address: 0x100000
  region: flash_primary
  size: 0x10000
app:
  address: 0x50000
  end_address: 0x80000
  region: flash_primary
  size: 0x30000
mcuboot:
  address: 0x0
  end_address: 0x10000
  placement:
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0x10000
mcuboot_pad:
  address: 0x10000
  end_address: 0x10200
  placement:
    align:
      start: 0x8000
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0x10000
  end_address: 0x80000
  orig_span: &id001
  - app
  - mcuboot_pad
  - tfm
  region: flash_primary
  sharers: 0x1
  size: 0x70000
  span: *id001
mcuboot_primary_app:
  address: 0x10200
  end_address: 0x80000
  orig_span: &id002
  - app
  - tfm
  region: flash_primary
  size: 0x6fe00
  span: *id002
mcuboot_secondary:
  address: 0x80000
  end_address: 0xf0000
  placement:
    after:
    - mcuboot_primary
    align:
      start: 0x8000
  region: flash_primary
  share_size:
  - mcuboot_primary
  size: 0x70000
tfm:
  address: 0x10200
  end_address: 0x50000
  inside:
  - mcuboot_primary_app
  placement:
    before:
    - app
  region: flash_primary
  size: 0x3fe00
tfm_nonsecure:
  address: 0x50000
  end_address: 0x80000
  orig_span: &id007
  - app
  region: flash_primary
  size: 0x30000
  span: *id007
tfm_secure:
  address: 0x10000
  end_address: 0x50000
  orig_span: &id008
  - mcuboot_pad
  - tfm
  region: flash_primary
  size: 0x40000
  span: *id008

main.c (Based off of the modem callback example)

#include <stdio.h>
#include <stdint.h>
#include <zephyr/kernel.h>
#include <modem/nrf_modem_lib.h>
#include <modem/modem_info.h>
#include <modem/lte_lc.h>
#include <zephyr/dfu/mcuboot.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
#include <hal/nrf_regulators.h>

NRF_MODEM_LIB_ON_INIT(init_hook, on_modem_init, NULL);
NRF_MODEM_LIB_ON_SHUTDOWN(shutdown_hook, on_modem_shutdown, NULL);

static const struct gpio_dt_spec BOOT_PIN = GPIO_DT_SPEC_GET(DT_ALIAS(boot), gpios);

void shutdown();

static void on_modem_init(int ret, void *ctx)
{
    printk("> Initialized with value %d\r\n", ret);
}

static void on_modem_shutdown(void *ctx)
{
    printk("> Shutting down\r\n");
}

LTE_LC_ON_CFUN(cfun_monitor, on_cfun, NULL);

static void on_cfun(enum lte_lc_func_mode mode, void *ctx)
{
    printk("> Functional mode has changed to %d\r\n", mode);
}

int main(void)
{
    printk("Huxley Sansa Firmware (nRF9160)\r\n");

    // Configure the boot pin so we can determine whether we need to be in boot mode (HIGH) or not (LOW)
    if (gpio_pin_configure_dt(&BOOT_PIN, GPIO_INPUT) != 0) {
        printk("ERROR: Unable to configure the LTE WakeUp pin\r\n");
        return 1;
    }
    
    //todo do more with this gpio pin later

    printk("Getting Modem Info First\r\n");

    int err = modem_info_init();
    if (err)
    {
        printk("Error: Modem Info Module Failed to initialize, err %d \r\n", err);
    }

    struct modem_param_info my_modem_info;
    err = modem_info_params_get(&my_modem_info);
    if (err)
    {
        printk("Error: Can't get modem parameters, err %d \r\n", err);
    }
    else
    {
        printk("Modem's ICCID: %s \r\n", my_modem_info.sim.iccid.value_string);
    }

    printk("Modem callbacks sample started\r\n");

    printk("Initializing modem library\r\n");
    err = nrf_modem_lib_init();
    if (err) {
        printk("Modem initialization failed, err %d\r\n", err);
        return 0;
    }

    printk("Changing functional moder\n");
    err = lte_lc_init_and_connect();
    if (err) {
        printk("lte_lc_init_and_connect() failed, err %d\r\n", err);
    }

    while(true)
    {
        // just wait forever since we don't want to shutdown
        k_cpu_idle();
        //k_msleep(1000);
    }

    printk("Bye\r\n");

    return 0;
}

void shutdown(void)
{
    printk("Shutting down modem library\r\n");
    int status = nrf_modem_lib_shutdown();
    if (status == 0)
    {
      printk("Modem shutdown successfully\r\n");
    }
    else
    {
      printk("Modem failed to shutdown: %d\r\n", status);
    }

    printk("Taking a nap...\r\n");

    nrf_regulators_system_off(NRF_REGULATORS);
}
 

  • Well, I got it to find an image when I modified the `pm_static.yml` to look like what is below. And then updated the boards devicetree file to look like below. But now I am in a bootloop. So I'm not sure I am actually better off and some insight on what I might be doing wrong would be appreciated. 

    updated pm_static.yml: 

    storage_partition:
      address: 0xf0000
      end_address: 0x100000
      region: flash_primary
      size: 0x10000
    app:
      address: 0x50000
      end_address: 0x80000
      region: flash_primary
      size: 0x30000
    mcuboot:
      address: 0x0
      end_address: 0x10000
      placement:
        before:
        - mcuboot_primary
      region: flash_primary
      size: 0x10000
    mcuboot_pad:
      address: 0x10000
      end_address: 0x10200
      placement:
        align:
          start: 0x8000
        before:
        - mcuboot_primary_app
      region: flash_primary
      size: 0x200
    mcuboot_primary:
      address: 0x10000
      end_address: 0x80000
      orig_span: &id001
      - app
      - mcuboot_pad
      - tfm
      region: flash_primary
      sharers: 0x1
      size: 0x70000
      span: *id001
    mcuboot_primary_app:
      address: 0x10200
      end_address: 0x80000
      orig_span: &id002
      - app
      - tfm
      region: flash_primary
      size: 0x6fe00
      span: *id002
    mcuboot_secondary:
      address: 0x80000
      end_address: 0xf0000
      placement:
        after:
        - mcuboot_primary
        align:
          start: 0x8000
      region: flash_primary
      share_size:
      - mcuboot_primary
      size: 0x70000
    tfm:
      address: 0x10200
      end_address: 0x50000
      inside:
      - mcuboot_primary_app
      placement:
        before:
        - app
      region: flash_primary
      size: 0x3fe00
    tfm_nonsecure:
      address: 0x50000
      end_address: 0x80000
      orig_span: &id007
      - app
      region: flash_primary
      size: 0x30000
      span: *id007
    tfm_secure:
      address: 0x10000
      end_address: 0x50000
      orig_span: &id008
      - mcuboot_pad
      - tfm
      region: flash_primary
      size: 0x40000
      span: *id008
    sram_nonsecure:
      address: 0x20008000
      end_address: 0x20080000
      orig_span: &id004
      - sram_primary
      region: sram_primary
      size: 0x78000
      span: *id004
    sram_primary:
      address: 0x20008000
      end_address: 0x20080000
      region: sram_primary
      size: 0x68000
    sram_secure:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id005
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id005

    boards .dti file: 

    #include "my_board-pinctrl.dtsi"
    
    / {
        model = "My Custom Board";
        compatible = "foo,barred";
    
        chosen {
            zephyr,console = &uart0;
            zephyr,shell-uart = &uart0;
            zephyr,uart-mcumgr = &uart2;
        };
    
    	pwmleds {
    		compatible = "pwm-leds";
    		pwm_debug_led: pwm_led0 {
    			pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
    		};
    	};
    
        aliases {
            boot = &lte_wun;
        };
    
        stm32u5_interface {
            compatible = "gpio-keys";
            mcu_nrst: mcu_nrst {
                gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
                label = "MCU_NRST";
            };
            mcu_boot0: mcu_boot0 {
                gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
                label = "MCU_BOOT0";
            };
            lte_wun: lte_wun {
                gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
                label = "LTE_WUn";
            };
            mcu_wun: mcu_wun {
                gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
                label = "MCU_WUn";
            };
        };
    
        unused_gpios {
            compatible = "gpio-leds";
            p03: p03 {
                gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
                label = "P0.03";
            };
            p04: p04 {
                gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
                label = "P0.04";
            };
            p07: p07 {
                gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
                label = "P0.07";
            };
            p08: p08 {
                gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
                label = "P0.08";
            };
            p09: p09 {
                gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
                label = "P0.09";
            };
            p10: p10 {
                gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
                label = "P0.10";
            };
            p11: p11 {
                gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
                label = "P0.11";
            };
            p12: p12 {
                gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
                label = "P0.12";
            };
            p13: p13 {
                gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
                label = "P0.13";
            };
            p14: p14 {
                gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
                label = "P0.14";
            };
            p15: p15 {
                gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
                label = "P0.15";
            };
            p16: p16 {
                gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
                label = "P0.16";
            };
            p17: p17 {
                gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
                label = "P0.17";
            };
            p18: p18 {
                gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
                label = "P0.18";
            };
            p19: p19 {
                gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
                label = "P0.19";
            };
        };
    };
    
    &adc {
        status = "okay";
    };
    
    &gpiote {
        status = "okay";
    };
    
    &gpio0 {
        status = "okay";
    };
    
    &pwm0 {
        compatible = "nordic,nrf-pwm";
        status = "okay";
        pinctrl-0 = <&pwm0_default>;
        pinctrl-1 = <&pwm0_sleep>;
        pinctrl-names = "default", "sleep";
    };
    
    &uart0 {
        compatible = "nordic,nrf-uarte";
        status = "okay";
        current-speed = <115200>;
        pinctrl-0 = <&uart0_default>;
        pinctrl-1 = <&uart0_sleep>;
        pinctrl-names = "default", "sleep";
    };
    
    // Disable because UART1 is used by the TF-M
    &uart1 {
        status = "disabled";
    };
    
    &uart2 {
        compatible = "nordic,nrf-uarte";
        status = "okay";
        current-speed = <115200>;
        pinctrl-0 = <&uart2_default>;
        pinctrl-1 = <&uart2_sleep>;
        pinctrl-names = "default", "sleep";
    };
    
    &flash0 {
    
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		boot_partition: partition@0 {
    			label = "mcuboot";
    			reg = <0x00000000 0x10000>;
    		};
    		slot0_partition: partition@10000 {
    			label = "image-0";
    		};
    		slot0_ns_partition: partition@50000 {
    			label = "image-0-nonsecure";
    		};
    		slot1_partition: partition@80000 {
    			label = "image-1";
    		};
    		slot1_ns_partition: partition@c0000 {
    			label = "image-1-nonsecure";
    		};
    		storage_partition: partition@f0000 {
    			label = "storage";
    			reg = <0xf0000 0x10000>;
    		};
    	};
    };
    
    / {
    
    	reserved-memory {
    		#address-cells = <1>;
    		#size-cells = <1>;
    		ranges;
    
    		sram0_s: image_s@20000000 {
    			/* Secure image memory */
    		};
    
    		sram0_modem: image_modem@20008000 {
    			/* Modem (shared) memory */
    		};
    
    		sram0_ns: image_ns@20008000 {
    			/* Non-Secure image memory */
    		};
    	};
    };
    
     &slot0_partition {
    	reg = <0x00010000 0x40000>;
    };
    
    &slot0_ns_partition {
    	reg = <0x00050000 0x30000>;
    };
    
    &slot1_partition {
    	reg = <0x00080000 0x40000>;
    };
    
    &slot1_ns_partition {
    	reg = <0x000c0000 0x30000>;
    };
    
    &sram0_s {
    	reg = <0x20000000 0x8000>;
    };
    
    &sram0_modem {
    	reg = <0x20008000 0x4568>;
    };
    
    &sram0_ns {
    	reg = <0x20008000 0x78000>;
    };
    

  • Hello

    From your description and the update, it looks like there are issues or inconsistencies in the PM Static Yml file.

    As such, I would recommend if you remove static partition file, and then build the project such that it automatically generates the 'partitions.yml' in the build folder, and then see and modify as per your requirements.

    This will also allow you to track changes that are erroneous, and would provide a starting point.

    In the below image, I have just compiled the 'TFM_SECURE_PARTITION' project for 9160DK, and can see the 'partitions.yml' file in the build folder.

  • Hi,

    You just described how I arrived at this particular pm_static.yml file that I have posted. Between looking at generated partition.yml files for examples and reading various posts on this site, I have tried to remake this a few times now. If there are issues or inconsistencies in the static partitions then I'm asking if someone can take a look at it to see what those might be because I clearly am not seeing them. 

    To be clear, I can also compile examples for dev boards and run them on a dev board, but it's not translating to my custom board running the nRF9160 and I am not seeing why. So if you see something in my pm_static.yml file that seems odd or out of place, please let me know as it would be greatly appreciated. 

  • Hello,

    I don't see any other issue except that one of the size (number) is wrong (snapshot attached below) and that the storage_partition is getting defined two times (in the board file and in the .yml file). 

    What I have seen is that if you need to change the storage_partition already defined in the board file, then first they delete it (using delete property in the overlay) and then redefine it.

  • So with working with the support engineer from Nordic, I have found my problem. Along with needing the pm_static.yml file massaged, I also basically needed to add the following config lines as well as had fat fingered a pin definition for my devicetree. The pins caused the app to crash once it was booted into as well. 

    Lines I needed to add to my config to get TFM to play nice with MCUBOOT: 

    CONFIG_TFM_PROFILE_TYPE_MINIMAL=y
    CONFIG_TFM_BL2=n
    CONFIG_PSA_WANT_GENERATE_RANDOM=y
    CONFIG_PM_SINGLE_IMAGE=y

    Also moved `CONFIG_BUILD_WITH_TFM` to the prj.conf file instead of in the board config. 

Related