Is it supported to configure one LittleFS partition on external SPI flash and another in internal FLASH?

Hello

I’m aware that this topic has been discussed in several posts from a couple of years ago, but I haven’t found a concrete solution yet.

I'm currently using an external flash to store large files, but I would also like to use the internal flash for smaller ones. Here's what I’ve tried so far:

prj.conf : 

CONFIG_NCS_SAMPLES_DEFAULTS=y
CONFIG_DK_LIBRARY=y
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_UART_CONSOLE=n

CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="FREEDOM"
CONFIG_BT_MAX_CONN=2
CONFIG_BT_SMP=y
CONFIG_BT_MAX_PAIRED=8

CONFIG_BT_GATT_AUTO_SEC_REQ=y
CONFIG_BT_FIXED_PASSKEY=y

CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y

# Enable bonding
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_SETTINGS_RUNTIME=y
CONFIG_SETTINGS_NVS=y

CONFIG_BT_DIS=y
CONFIG_BT_DIS_SETTINGS=y
CONFIG_BT_DIS_STR_MAX=32
CONFIG_BT_DIS_PNP=n
CONFIG_BT_DIS_MODEL="FREEDOM"
CONFIG_BT_DIS_MANUF="TELEDYNE"
CONFIG_BT_DIS_SERIAL_NUMBER=y
CONFIG_BT_DIS_FW_REV=y
CONFIG_BT_DIS_HW_REV=y
CONFIG_BT_DIS_SW_REV=y
CONFIG_BT_DIS_SERIAL_NUMBER_STR="123456789abcdef"
CONFIG_BT_DIS_FW_REV_STR="0.0.0"
CONFIG_BT_DIS_HW_REV_STR="0.0.0"
CONFIG_BT_DIS_SW_REV_STR="0.0.0"

#Enable MCUBOOT bootloader build in the application
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="priv.pem"
#Include MCUMGR and the dependencies in the build
CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y
#CONFIG_MCUMGR_TRANSPORT_BT_AUTHEN=y

CONFIG_BT_EXT_ADV=y
CONFIG_BT_EXT_ADV_MAX_ADV_SET=2
CONFIG_BT_DEVICE_NAME_DYNAMIC=n
CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=100

CONFIG_MODBUS=y
CONFIG_MODBUS_RAW_ADU=y
CONFIG_MODBUS_ROLE_CLIENT=y

CONFIG_PARTITION_MANAGER_ENABLED=y

CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y

CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n
CONFIG_MULTITHREADING=y

CONFIG_HEAP_MEM_POOL_SIZE=60000

# Enable binary descriptors
#CONFIG_BINDESC=y

# Enable definition of binary descriptors
#CONFIG_BINDESC_DEFINE=y

# Enable default build time binary descriptors
#CONFIG_BINDESC_DEFINE_BUILD_TIME=y
#CONFIG_BINDESC_BUILD_DATE_TIME_STRING=y

##################################################
################ CONF TO CHECK ###################
################ TO BE REMOVED ###################
##################################################

# Enable file system commands
CONFIG_MCUMGR_GRP_FS=y
CONFIG_MCUMGR_GRP_FS_DL_CHUNK_SIZE=200

# Enable the storage erase command.
CONFIG_MCUMGR_GRP_ZBASIC=y
CONFIG_MCUMGR_GRP_ZBASIC_STORAGE_ERASE=y
# Optionally force the file system to be recreated
#CONFIG_APP_WIPE_STORAGE=y
# fs_dirent structures are big.
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_BT_RX_STACK_SIZE=4096
CONFIG_BT_HCI_TX_STACK_SIZE=4096
CONFIG_MCUMGR_TRANSPORT_WORKQUEUE_STACK_SIZE=6000

# Let __ASSERT do its job
CONFIG_DEBUG=y

CONFIG_INIT_STACKS=y
CONFIG_THREAD_STACK_INFO=y
CONFIG_STACK_SENTINEL=y
CONFIG_THREAD_MONITOR=y
CONFIG_THREAD_NAME=y

CONFIG_PM_SINGLE_IMAGE=y  # ou CONFIG_PM_MULTI_IMAGE si tu utilises MCUboot
CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y

CONFIG_PM_PARTITION_REGION_LITTLEFS_EXTERNAL=y
#CONFIG_PM_PARTITION_REGION_SETTINGS_STORAGE_EXTERNAL=y
#CONFIG_PM_PARTITION_REGION_NVS_STORAGE_EXTERNAL=y

CONFIG_SPI=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
#CONFIG_NORDIC_QSPI_NOR=y
#CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

CONFIG_NFCT_PINS_AS_GPIOS=y
#CONFIG_LOG_DEFAULT_LEVEL=4
#CONFIG_WATCHDOG=n

CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_INTERRUPT_DRIVEN=n

app.overlay

 / {
     chosen {
         nordic,pm-ext-flash = &mx25r16;
     };

     fstab {
         compatible = "zephyr,fstab";
         lfs1: lfs1 {
             compatible = "zephyr,fstab,littlefs";
             mount-point = "/lfs1";
             partition = <&lfs1_partition>;
             /*automount;*/
             read-size = <16>;
             prog-size = <16>;
             cache-size = <64>;
             lookahead-size = <32>;
             block-cycles = <512>;
         };
         lfs2: lfs2 {
             compatible = "zephyr,fstab,littlefs";
             mount-point = "/lfs2";
             partition = <&lfs2_partition>;
             /*automount;*/
             read-size = <16>;
             prog-size = <16>;
             cache-size = <64>;
             lookahead-size = <32>;
             block-cycles = <512>;
         };
     };
 };


&flash0 {

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

		boot_partition: partition@0 {
			label = "mcuboot";
			reg = <0x00000000 DT_SIZE_K(48)>;
		};

		slot0_partition: partition@c000 {
			label = "image-0";
			reg = <0x0000c000 DT_SIZE_K(472)>;
		};

		slot1_partition: partition@82000 {
			label = "image-1";
			reg = <0x00082000 DT_SIZE_K(464)>;
		};

		lfs2_partition: partition@f6000 {
            label = "lfs2";
            reg = <0x000f6000 DT_SIZE_K(8)>;
        };

		storage_partition: partition@f8000 {
			label = "storage";
			reg = <0x000f8000 DT_SIZE_K(32)>;
		};

	};
};

&spi2 {
	compatible = "nordic,nrf-spi";
	status = "okay";
	cs-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
	pinctrl-0 = <&spi2_default>;
	pinctrl-1 = <&spi2_sleep>;
	pinctrl-names = "default", "sleep";
	mx25r16: mx25r1635f@0 {
		compatible = "jedec,spi-nor";
		reg = <0>;
		spi-max-frequency = <8000000>;
        jedec-id = [c2 28 15];
        /* 
		sfdp-bfp = [
			e5 20 f1 ff  ff ff ff 03  44 eb 08 6b  08 3b 04 bb
			ee ff ff ff  ff ff 00 ff  ff ff 00 ff  0c 20 0f 52
			10 d8 00 ff  23 72 f5 00  82 ed 04 cc  44 83 68 44
			30 b0 30 b0  f7 c4 d5 5c  00 be 29 ff  f0 d0 ff ff
		];*/
        size = <DT_SIZE_M(16)>;
		has-dpd;
		t-enter-dpd = <10000>;
		t-exit-dpd = <35000>;
	};
};

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

        lfs1_partition: partition@0 {
            label = "lfs1";
            reg = <0x00000000 0x200000>;
        };
    };
};

pm_static.yml

app:
  address: 0xc200
  end_address: 0x85000
  region: flash_primary
  size: 0x78e00
mcuboot:
  address: 0x0
  end_address: 0xc000
  placement:
    align:
      end: 0x1000
    before:
    - mcuboot_primary
  region: flash_primary
  size: 0xc000
mcuboot_pad:
  address: 0xc000
  end_address: 0xc200
  placement:
    align:
      start: 0x1000
    before:
    - mcuboot_primary_app
  region: flash_primary
  size: 0x200
mcuboot_primary:
  address: 0xc000
  end_address: 0x85000
  orig_span: &id001
  - mcuboot_pad
  - app
  region: flash_primary
  sharers: 0x1
  size: 0x79000
  span: *id001
mcuboot_primary_app:
  address: 0xc200
  end_address: 0x85000
  orig_span: &id002
  - app
  region: flash_primary
  size: 0x78e00
  span: *id002
mcuboot_secondary:
  address: 0x85000
  end_address: 0xfe000
  placement:
    after:
    - mcuboot_primary
    align:
      start: 0x1000
  region: flash_primary
  share_size:
  - mcuboot_primary
  size: 0x79000
settings_storage:
  address: 0xfe000
  end_address: 0x100000
  placement:
    align:
      start: 0x1000
    before:
    - end
  region: flash_primary
  size: 0x2000
sram_primary:
  address: 0x20000000
  end_address: 0x20040000
  region: sram_primary
  size: 0x40000
littlefs_storage:
  address: 0xF6000
  end_address: 0xF8000
  region: flash_primary
  size: 0x2000
littlefs_storage:
  address: 0x0
  device: mx25r16
  end_address: 0x200000
  region: external_flash
  size: 0x200000
external_flash:
   address: 0x0
   size: 0x200000
   device: mx25r16f
   region: external_flash

The problem is: even though I’m trying to mount an internal flash partition as lfs2, it still seems to point to the external flash, just like lfs1.

Any ideas on how to properly configure LittleFS to use both internal and external flash independently?

Thank you in advance

Best regards,

Aurélien

Related