This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

MCU boot with external Flash littles partition and Secondary image partition

Hello ALL,

I am trying to use MCU boot with my application. I am using NRF916DK and it has external Flash similar to NR52840DK board. Now when I am creating a partition on external Flash and point LittleFs to that storage partition, after compiling when I see the partition.yml in the build folder, the LittleFs always in the primary Flash. I have tried few options as seen in the code but nothing is working. Can somebody please guide me on how I can enable these partitions and point secondary Image and littlefs to those partitions.

Here is my overlay file


/ {
	chosen {
		zephyr,bt-uart=&uart0;
	};
};

/delete-node/ &storage_partition;

&i2c2 {
    compatible = "nordic,nrf-twim";
    status = "okay";
    sda-pin = <26>;
    scl-pin = <27>;

    pcf85263a@51 {
        compatible = "nxp,pcf85263a";
        label = "PCF85063A";
        reg = <0x51>;
    };

};

&uart1 {
	status = "okay";
	current-speed = <9600>;
	tx-pin = <06>;
	rx-pin = <07>;
};


&spi3 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	sck-pin = <13>;
	mosi-pin = <11>;
	miso-pin = <12>;
	cs-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
	mx25r6435f: mx25r6435f@0 {
		compatible = "jedec,spi-nor";
		label = "MX25R6435F";
		reg = <0>;
		spi-max-frequency = <40000000>;
		wp-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
		hold-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
		jedec-id = [c2 28 14];
  		size = <0x0800000>; /* flash capacity in bits */
  		has-be32k;
  		has-dpd;
  		t-enter-dpd = <10000>;
  		t-exit-dpd = <35000>;
	};
};


&mx25r6435f {
 	partitions {
  		compatible = "fixed-partitions";
  		#address-cells = <1>;
  		#size-cells = <1>;
		storage_partition: partition@40000 {
   			label = "storage";
   			reg = <0x00040000 0x00020000>;
  		};
 	};
};

Here is prj.conf

# Heap and stacks
CONFIG_HEAP_MEM_POOL_SIZE=16384
CONFIG_MAIN_STACK_SIZE=8192
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

# General config
CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
CONFIG_ASSERT=y
CONFIG_REBOOT=y

# Logging config
CONFIG_LOG=y
CONFIG_LOG_PRINTK=y
CONFIG_LOG_IMMEDIATE=y
CONFIG_LOG_FUNC_NAME_PREFIX_ERR=y
CONFIG_LOG_FUNC_NAME_PREFIX_WRN=y
CONFIG_LOG_FUNC_NAME_PREFIX_INF=y
CONFIG_LOG_FUNC_NAME_PREFIX_DBG=y

# Console
CONFIG_STDOUT_CONSOLE=y
CONFIG_PRINTK=y
CONFIG_CONSOLE_SUBSYS=y
CONFIG_CONSOLE_HANDLER=y
CONFIG_CONSOLE_GETCHAR=y

# PWM
CONFIG_PWM=y
CONFIG_PWM_LOG_LEVEL_DBG=y

# I2C
CONFIG_I2C=y

# RTC
CONFIG_PCF85263A=y

# UART
CONFIG_UART_ASYNC_API=y
CONFIG_UART_1_ASYNC=y
CONFIG_UART_1_INTERRUPT_DRIVEN=n
CONFIG_UART_1_NRF_HW_ASYNC=n
CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2
CONFIG_NRFX_TIMER2=y
CONFIG_NRFX_UARTE1=y

CONFIG_NRFX_SPIM=y
CONFIG_NRFX_SPIM3=y

# CONFIG_NRFX_SPI=y
# CONFIG_NRFX_SPI0=y
CONFIG_BSD_LIBRARY_TRACE_ENABLED=n

# SPI Flash
CONFIG_SPI=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

# Enable flash operations.
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y



# Nordic specific external flash stuff
CONFIG_PM_EXTERNAL_FLASH=y
CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="MX25R6435F"
CONFIG_PM_EXTERNAL_FLASH_BASE=0x0
CONFIG_PM_EXTERNAL_FLASH_SIZE=0x0800000

# Enable the LittleFS file system.
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y
# CONFIG_APP_WIPE_STORAGE=n

# MCUBOOT
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_IMG_MANAGER=y
CONFIG_MCUBOOT_IMG_MANAGER=y

Here is my main.c

 

#include <zephyr.h>
#include <logging/log.h>
#include <drivers/uart.h>

#include <fs/fs.h>
#include <fs/littlefs.h>
#include <storage/flash_map.h>

#if (CONFIG_SPI_NOR - 0) || DT_NODE_HAS_STATUS(DT_INST(0, jedec_spi_nor), okay)
#define FLASH_DEVICE DT_LABEL(DT_INST(0, jedec_spi_nor))
#define FLASH_NAME "JEDEC SPI-NOR"
#elif (CONFIG_NORDIC_QSPI_NOR - 0) || DT_NODE_HAS_STATUS(DT_INST(0, nordic_qspi_nor), okay)
#define FLASH_DEVICE DT_LABEL(DT_INST(0, nordic_qspi_nor))
#define FLASH_NAME "JEDEC QSPI-NOR"
#else
#error Unsupported flash driver
#endif

LOG_MODULE_REGISTER(app);

/* Matches LFS_NAME_MAX */
#define MAX_PATH_LEN 255

FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(lfsstorage);
static struct fs_mount_t lfs_storage_mnt = {
		.type = FS_LITTLEFS,
		.fs_data = &lfsstorage,
		//.storage_dev = (void *)DT_FLASH_AREA_STORAGE_ID,
		.storage_dev = (void *)FLASH_AREA_ID(storage),
		//.storage_dev = (void *)FLASH_AREA_ID(external_flash),
		.mnt_point = "/lfs",
};

here is the partition.yml that is generated in the build folder after compilation

EMPTY_0:
  address: 0xc000
  placement:
    before:
    - mcuboot_pad
  region: flash_primary
  size: 0x4000
app:
  address: 0x1c200
  region: flash_primary
  size: 0x68e00
external_flash:
  address: 0x0
  region: external_flash
  size: 0x800000
littlefs_storage:
  address: 0xfa000
  placement:
    before:
    - end
  region: flash_primary
  size: 0x6000
mcuboot:
  address: 0x0
  placement:
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0xc000
mcuboot_pad:
  address: 0x10000
  placement:
    align:
      start: 0x8000
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0x10000
  orig_span: &id001
  - spm
  - mcuboot_pad
  - app
  region: flash_primary
  sharers: 0x1
  size: 0x75000
  span: *id001
mcuboot_primary_app:
  address: 0x10200
  orig_span: &id002
  - app
  - spm
  region: flash_primary
  size: 0x74e00
  span: *id002
mcuboot_secondary:
  address: 0x85000
  placement:
    after:
    - mcuboot_primary
    align:
      start: 0x1000
  region: flash_primary
  share_size:
  - mcuboot_primary
  size: 0x75000
otp:
  address: 0xff8108
  region: otp
  size: 0x2f4
spm:
  address: 0x10200
  inside:
  - mcuboot_primary_app
  placement:
    before:
    - app
  region: flash_primary
  size: 0xc000
spm_sram:
  address: 0x20000000
  inside:
  - sram_secure
  placement:
    after:
    - start
  region: sram_primary
  size: 0x10000
sram_primary:
  address: 0x20010000
  region: sram_primary
  size: 0x30000
sram_secure:
  address: 0x20000000
  orig_span: &id003
  - spm_sram
  region: sram_primary
  size: 0x10000
  span: *id003

  • Hi,

     

    Do you want the mcuboot_secondary partition to be on your external flash?

    I don't know how you have configured mcuboot, but this will also need to have a specific configuration that tells it that there's a external storage available.

    First you need to alter your CMakeLists.txt file, to allow adding mcuboot specific configurations and overlay.

    You can overload the configuration by adding this to the top of your CMakeLists.txt (just below the cmake_minimum_required()):

    if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/spm.conf")
      set(spm_CONF_FILE
        prj.conf
        ${CMAKE_CURRENT_LIST_DIR}/spm.conf
      )
    endif()
    
    if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.conf")
        list(APPEND mcuboot_OVERLAY_CONFIG
          "${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.conf"
          )
    endif()
    
    if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
      set(mcuboot_DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
      set(spm_DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
    endif()

     

    Now, you can create my_application/mcuboot.conf, which holds flash specific configurations (taken from your current configuration):

    CONFIG_PM_EXTERNAL_FLASH=y
    CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="MX25R6435F"
    CONFIG_PM_EXTERNAL_FLASH_BASE=0x0
    CONFIG_PM_EXTERNAL_FLASH_SIZE=0x0800000

     

    The above is similar to how it is setup in the documentation:

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#pm-external-flash

     

    If you want to specify the mcuboot secondary slot to external flash, you need to adjust your my_application/build/partitions.yml and place this in the application folder as "pm_static.yml" (my_application/pm_static.yml).

    This is covered more in detail in the documentation: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#static-configuration

     

    Here's an example on the secondary slot, pointed to your flash device:

    mcuboot_secondary:
      address: 0x0
      device: mx25r6435f
      region: external_flash
      size: 0x800000

      

    Kind regards,

    Håkon

  • Hi Håkon,

    Thanks for reaching out.

    I was already including spm.conf file and was adding overlay and spm.conf in my cMakelists.txt but now I changed that and make the If conditions as you have mentioned above. I have tried the above solution of creating a mcuboot.conf file and copying the configurations (CONFIG_PM_EXTERNAL...) to that file, after doing that and compiling, to my surprise the external flash was totally not included in the build/partition.yml. When I copied those configurations (CONFIG_PM_EXTERNAL...) back from mcuboot.conf to prj.conf, the external flash section start appearing again in the build/partition.yml as you can see in my initial attachment. There are two problems.

    1. The liilefs storage is pointing to the internal memory and to the same partition that I have deleted the node in overlay file and it is not pointing to external flash. so the external flash partition is not recognizing. Here is my overlay file.

    
    / {
    	chosen {
    		zephyr,bt-uart=&uart0;
    	};
    };
    
    /delete-node/ &storage_partition;
    
    &i2c2 {
        compatible = "nordic,nrf-twim";
        status = "okay";
        sda-pin = <26>;
        scl-pin = <27>;
    
        pcf85263a@51 {
            compatible = "nxp,pcf85263a";
            label = "PCF85063A";
            reg = <0x51>;
        };
    
    };
    
    &uart1 {
    	status = "okay";
    	current-speed = <9600>;
    	tx-pin = <06>;
    	rx-pin = <07>;
    };
    
    
    &spi3 {
    	compatible = "nordic,nrf-spim";
    	status = "okay";
    	sck-pin = <13>;
    	mosi-pin = <11>;
    	miso-pin = <12>;
    	cs-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
    	mx25r6435f: mx25r6435f@0 {
    		compatible = "jedec,spi-nor";
    		label = "MX25R6435F";
    		reg = <0>;
    		spi-max-frequency = <40000000>;
    		wp-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
    		hold-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
    		jedec-id = [c2 28 14];
      		size = <0x0800000>; /* flash capacity in bits */
      		has-be32k;
      		has-dpd;
      		t-enter-dpd = <10000>;
      		t-exit-dpd = <35000>;
    	};
    };
    
    
    &mx25r6435f {
     	partitions {
      		compatible = "fixed-partitions";
      		#address-cells = <1>;
      		#size-cells = <1>;
    		storage_partition: partition@40000 {
       			label = "storage";
       			reg = <0x00040000 0x00020000>;
      		};
     	};
    };
    

    Here is the build/partition.yml section

    littlefs_storage:
    address: 0xfa000
    placement:
    before:
    - end
    region: flash_primary
    size: 0x6000

    so clearly old storage_partition is not being deleted and littlefs is not poiting to the new storage_parttion that I have created in the external_flash in the overlay file above.

    2. HOw to create the partition in the same way as I have made for sotrage_parttion for secondary Image. I mean whats is the name of old partitions that I have to delete and what name should I made for new partitions such that it starts working with the new partition and both secondary image and LittleFs storage would point to new external flash partitions.

    3. As far as the pm_static.yml is concerned, I don't want to statically allocate at this time. I wanted to use an overlay file to create partitions region initially. the default partitions in the internal flash have also created this way as I saw the files of SDK and I have also seen examples online which use this method. but unfortunately, I am not successful in implementing that.

  • Hi,

     

    Waqas Qammar said:

    littlefs_storage:
    address: 0xfa000
    placement:
    before:
    - end
    region: flash_primary
    size: 0x6000

    so clearly old storage_partition is not being deleted and littlefs is not poiting to the new storage_parttion that I have created in the external_flash in the overlay file above.

    There's no logic that tells the "storage" to point to your external flash. 

     

    If you do not specify the storage of different partitions, you will end up with the default setup, which is that there's a external_flash partition, which is not populated and freely available to the application, not mcuboot or other partitions. If this is what you want, that is fine; but it seems you want to point mcuboot and lfs to your flash device? If that is so, you have to specify this using pm_static.yml.

     

     

    Waqas Qammar said:
    2. HOw to create the partition in the same way as I have made for sotrage_parttion for secondary Image. I mean whats is the name of old partitions that I have to delete and what name should I made for new partitions such that it starts working with the new partition and both secondary image and LittleFs storage would point to new external flash partitions.

     You specify both lfs and mcuboot_secondary to point to your "external_flash" region in pm_static.yml, as described in my first post. They shall not overlap in terms of addresses.

     

    Waqas Qammar said:
    As far as the pm_static.yml is concerned, I don't want to statically allocate at this time. I wanted to use an overlay file to create partitions region initially. the default partitions in the internal flash have also created this way as I saw the files of SDK and I have also seen examples online which use this method. but unfortunately, I am not successful in implementing that.

     As mentioned, you need to specify this. the partition manager will not assign a flash to given partitions unless you explicitly tell it to.

     

    Kind regards,

    Håkon

  • Hi Håkon,

    I have applied the above-suggested techniques but I was getting this error.

    Firmware/ncs/bootloader/mcuboot/boot/zephyr/flash_map_extended.c: In function 'flash_area_id_from_multi_image_slot':
    Firmware/ncs/bootloader/mcuboot/boot/zephyr/include/sysflash/sysflash.h:15:40: error: 'PM_MCUBOOT_SECONDARY_ID' undeclared (first use in this function); did you mean 'PM_MCUBOOT_PRIMARY_ID'?
    #define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID

    Firmware/ncs/bootloader/mcuboot/boot/zephyr/flash_map_extended.c: In function 'flash_area_id_to_multi_image_slot':
    Firmware/ncs/bootloader/mcuboot/boot/zephyr/include/sysflash/sysflash.h:15:40: error: 'PM_MCUBOOT_SECONDARY_ID' undeclared (first use in this function); did you mean 'PM_MCUBOOT_PRIMARY_ID'?
    #define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID

    Firmware/ncs/nrf/include/flash_map_pm.h:32:22: error: 'PM_external_flash_ID' undeclared here (not in a function)
    #define PM_ID(label) PM_##label##_ID

    I have used this method of defining littlefs storage and all are giving errors.

    #include <fs/fs.h>
    #include <fs/littlefs.h>
    #include <storage/flash_map.h>
    
    #if (CONFIG_SPI_NOR - 0) || DT_NODE_HAS_STATUS(DT_INST(0, jedec_spi_nor), okay)
    #define FLASH_DEVICE DT_LABEL(DT_INST(0, jedec_spi_nor))
    #define FLASH_NAME "JEDEC SPI-NOR"
    #elif (CONFIG_NORDIC_QSPI_NOR - 0) || DT_NODE_HAS_STATUS(DT_INST(0, nordic_qspi_nor), okay)
    #define FLASH_DEVICE DT_LABEL(DT_INST(0, nordic_qspi_nor))
    #define FLASH_NAME "JEDEC QSPI-NOR"
    #else
    #error Unsupported flash driver
    #endif
    
    LOG_MODULE_REGISTER(app);
    
    /* Matches LFS_NAME_MAX */
    #define MAX_PATH_LEN 255
    
    FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(lfsstorage);
    static struct fs_mount_t lfs_storage_mnt = {
    		.type = FS_LITTLEFS,
    		.fs_data = &lfsstorage,
    		//.storage_dev = (void *)DT_FLASH_AREA_STORAGE_ID,
    		//.storage_dev = (void *)FLASH_AREA_ID(storage),
    		.storage_dev = (void *)FLASH_AREA_ID(external_flash),
    		.mnt_point = "/lfs",
    };
    
     
    when I don't use pm_static.yml. and simple pm.yml and spm.conf These errors don't appear but I am stuck at a different location. While the program executes, I am unable to call the 
    err = uart_callback_set(uart, uart_callback, (void *)uart);
    	__ASSERT(err == 0, "Failed to set callback");
    and the program restarts. I think this is due to SPM attachment and some secure and non-secure regions. The program restarts every time. If you can help it would be highly appreciated.
    I have attached the complete program for you
  • Hi,

     

    You need to define the "external_flash" region. Try adding this to the top of your pm_static.yml:

    external_flash:
      address: 0x800000
      region: external_flash
      size: 0x0

    In addition, you should add the similar configuration to your prj.conf:

    CONFIG_PM_EXTERNAL_FLASH=y
    CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="MX25R6435F"
    CONFIG_PM_EXTERNAL_FLASH_BASE=0x0
    CONFIG_PM_EXTERNAL_FLASH_SIZE=0x0800000

     

    The project still didn't compile at my end, I needed to add the "include" folder to the project. This is done by adding this line to your CMakeLists.txt:

    zephyr_include_directories(include)
    

     

    Kind regards,

    Håkon

Related