External SPI Flash to use with LittleFS on nRF9160 w/ MCUboot

Hey all,

I've been bringing up the nRF9160 Feather and noticed some curious issues with adding an external partition when MCUboot is enabled.

I first tested the external chip without MCUboot using the example provided at this path: ncs/zephyr/samples/subsys/fs/littlefs

The tests passed with an .overlay file like so:

/delete-node/ &storage_partition;

&w25q16jv {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		storage_partition: partition@0 {
			label = "storage";
			reg = <0x00000000 0x00010000>;
		};
	};
};

Now I'm trying to merge together the MCUboot + External LittleFS into one app.

My prj.conf looks like so:

# Note: fs_dirent structures are big.
CONFIG_MAIN_STACK_SIZE=2048

# Print a banner on the UART on startup.
CONFIG_BOOT_BANNER=y

# Enable console and printk()
CONFIG_PRINTK=y
CONFIG_STDOUT_CONSOLE=y

# Let __ASSERT do its job
CONFIG_DEBUG=y
CONFIG_LOG=y

# Enable Zephyr application to be booted by MCUboot
CONFIG_BOOTLOADER_MCUBOOT=y

# Adding Peripherals
CONFIG_GPIO=y
# CONFIG_I2C=y
# CONFIG_I2C_2=y

# SPI Related
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
# CONFIG_MPU_ALLOW_FLASH_WRITE=y # Note: only necessary for internal flash

# Nordic specific external flash stuff
CONFIG_PM_EXTERNAL_FLASH=y
CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="w25q16jv"
CONFIG_PM_EXTERNAL_FLASH_BASE=0x0
CONFIG_PM_EXTERNAL_FLASH_SIZE=0x1000000

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

After some serious searching, I found there was some documentation related to external flash plus Nordic's partition manager. I was able to get the external flash to show up in the devicetree_legacy_unfixed.h

It's not quite clear to me where the devicetree ends and the partition manager begins. Here's some output from my app versus the example code:

*** Booting Zephyr OS build v2.1.99-ncs1-2955-ge34f48a24ac4  ***
Hello World from Zephyr on circuitdojo_feather_nrf9160!
Area 6 at 0x10200 on NRF_FLASH_DRV_NAME for 478720 bytes
FAIL: mount id 6 at /lfs: -22
[00:00:00.017,028] .[0m<inf> littlefs: LittleFS version 2.2, disk version 2.0.[0m
[00:00:00.017,150] .[0m<inf> littlefs: FS at NRF_FLASH_DRV_NAME:0x10200 is 116 0x1000-byte blocks with 512 cycle.[0m
[00:00:00.017,150] .[0m<inf> littlefs: sizes: rd 16 ; pr 16 ; ca 64 ; la 32.[0m
[00:00:00.017,242] .[1;31m<err> littlefs: WEST_TOPDIR/modules/fs/littlefs/lfs.c:998: Corrupted dir pair at {0x0, 0x1}.[0m
[00:00:00.017,242] .[1;33m<wrn> littlefs: can't mount (LFS -84); formatting.[0m
[00:00:00.017,303] .[1;31m<err> littlefs: format failed (LFS -22).[0m
[00:00:00.017,303] .[1;31m<err> fs: fs mount error (-22).[0m

My code (which is some of the early bits of the LittleFS example)

*** Booting Zephyr OS build v2.1.99-ncs1-2955-ge34f48a24ac4  ***
Area 6 at 0x0 on W25Q16JV for 65536 bytes
/lfs mount: 0
/lfs: bsize = 16 ; frsize = 4096 ; blocks = 16 ; bfree = 14
/lfs/boot_count stat: 0
.fn 'boot_count' siz 4
/lfs/boot_count read count 10: 4
/lfs/boot_count seek start: 0
/lfs/boot_count write new boot count 11: 4
/lfs/boot_count close: 0
/lfs opendir: 0
  F 4 boot_count
End of files
/lfs unmount: 0
[00:00:00.011,108] .[0m<inf> littlefs: LittleFS version 2.2, disk version 2.0.[0m
[00:00:00.011,138] .[0m<inf> littlefs: FS at W25Q16JV:0x0 is 16 0x1000-byte blocks with 512 cycle.[0m
[00:00:00.011,169] .[0m<inf> littlefs: sizes: rd 16 ; pr 16 ; ca 64 ; la 32.[0m
[00:00:00.016,601] .[0m<inf> littlefs: /lfs mounted.[0m
[00:00:00.057,830] .[0m<inf> littlefs: /lfs unmounted.[0m

You can see it's referencing the correct ID but not the rest of the correct info. (Like the mount point, name, size, etc)

Any help is appreciated!

Parents
  • Hi,

    Unfortunately, I don’t have a w25q16jv flash device, but we have an on-board 64 Mb external flash memory (MX25R6435F) on the nRF52840 DK and nRF5340 PDK that perhaps can be used to recreate this.

    Is the goal to store a DFU image in the external flash ? If yes, did you try it without using littlefs?

    If you want to configure MCUboot to use external flash for the secondary slot , take a look at the chapter “Flash partitions used by MCUboot” at this page http://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_bootloader.html#adding-mcuboot-as-an-upgradable-bootloader

  • Hey 

    After researching it a bit more it seems related to the partition manager. Even without an external flash, I'm finding that the wrong partition address and size are being referenced.

    It seems as if this is not the first time someone has had issues with the Nordic Partition Manager. It looks like this was a discussion about this a while back here. 

    Seems like there's more information here related to all of this.

  • I ran into this exact problem last week; it seems that legacy partitions are no longer supported, and that the Nordic Partition Manager always sets this in pm_config.h:

    #define PM_LITTLEFS_STORAGE_DEV_NAME "NRF_FLASH_DRV_NAME"

    Regardless if what's in the .overlay.

    I was able to work around this, by defining CONFIG_PM_EXTERNAL_FLASH as you have above, then configuring LittleFS to use FLASH_AREA_ID(external_flash) for the .storage_dev, instead of FLASH_AREA_ID(storage).

    This works fine if you want to have a single partition on the external SPI flash.  I eventually want to partition the SPI flash, and it's not quite clear to me how to do that - I think I'll need to create a pm.yml and use the Nordic Partition Manager to define the partitions, but the documentation seems to be incorrect (e.g., there is no files named pm.config), and I'm not sure where to create the pm.yml, since it only seems applicable for child images.

Reply
  • I ran into this exact problem last week; it seems that legacy partitions are no longer supported, and that the Nordic Partition Manager always sets this in pm_config.h:

    #define PM_LITTLEFS_STORAGE_DEV_NAME "NRF_FLASH_DRV_NAME"

    Regardless if what's in the .overlay.

    I was able to work around this, by defining CONFIG_PM_EXTERNAL_FLASH as you have above, then configuring LittleFS to use FLASH_AREA_ID(external_flash) for the .storage_dev, instead of FLASH_AREA_ID(storage).

    This works fine if you want to have a single partition on the external SPI flash.  I eventually want to partition the SPI flash, and it's not quite clear to me how to do that - I think I'll need to create a pm.yml and use the Nordic Partition Manager to define the partitions, but the documentation seems to be incorrect (e.g., there is no files named pm.config), and I'm not sure where to create the pm.yml, since it only seems applicable for child images.

Children
  • Thanks Rakk!

    This was the trick. I did have to create an overlay file for the device I was testing though to delete the default chip I was using (I upgraded but my _common.dts still has the old part)

    /delete-node/ &w25q16jv;
    
    &spi3 {
    	compatible = "nordic,nrf-spim";
    	status = "okay";
    	sck-pin = <11>;
    	mosi-pin = <9>;
    	miso-pin = <28>;
    	cs-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
    	w25q32jv: w25q32jv@0 {
    		compatible = "jedec,spi-nor";
    		label = "W25Q32JV";
    		reg = <0>;
    		spi-max-frequency = <40000000>;
    		wp-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
    		hold-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
    		size = <0x2000000>;
    		has-dpd;
    		t-enter-dpd = <4000>;
    		t-exit-dpd = <25000>;
    		jedec-id = [ef 40 16];
    		has-be32k;
    	};
    };

    For anyone else who may be integrating other parts, the most important thing to have is the correct jedec-id. You can find that in the part data sheet.

    Other than that here's my final prj.conf

    # 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
    
    # Enable the LittleFS file system.
    CONFIG_FILE_SYSTEM=y
    CONFIG_FILE_SYSTEM_LITTLEFS=y
    
    # CONFIG_APP_WIPE_STORAGE=y
    
    # Nordic specific external flash stuff
    CONFIG_PM_EXTERNAL_FLASH=y
    CONFIG_PM_EXTERNAL_FLASH_DEV_NAME="W25Q32JV"
    CONFIG_PM_EXTERNAL_FLASH_BASE=0x0
    CONFIG_PM_EXTERNAL_FLASH_SIZE=0x2000000

    This is working perfectly on a pre-production nRF9160 Feather!

Related