LittleFS failing to mount on QSPI NOR Flash (err -28)

I am trying to implement LittleFS on 1Gb QSPI NOR flash (W25Q01JV) on the nRF5340.

I am running nRF Connect SDK version 2.4.2 and am using a slightly modified version of the LittleFS example to work with my custom board.

Whenever I try to mount the file system I get this error:

Here is the relevant Device tree bindings:

/ {
    chosen {
        nordic,pm-ext-flash = &w25q01;
    };
    fstab {
		compatible = "zephyr,fstab";
		lfs: lfs {
			compatible = "zephyr,fstab,littlefs";
			mount-point = "/lfs";
			partition = <&lfs_part>;
			read-size = <16>;
			prog-size = <16>;
			cache-size = <64>;
			lookahead-size = <32>;
			block-cycles = <512>;
		};
	};
};

//delete-node/ &storage_partition;

&qspi {
	status = "okay";
	pinctrl-0 = <&qspi_default>;
	pinctrl-1 = <&qspi_sleep>;
	pinctrl-names = "default", "sleep";
    w25q01: w25q01@0 {
        compatible = "nordic,qspi-nor";
		reg = <0>;
		writeoc = "pp4o";
		readoc = "read4io";
		sck-frequency = <8000000>;
		jedec-id = [EF 40 21];
        sfdp-bfp = [
        e5 20 fb ff  ff ff ff 3f  44 eb 08 6b  08 3b 42 bb
        fe ff ff ff  ff ff 00 00  ff ff 40 eb  0c 20 0f 52
        10 d8 00 00  36 02 a6 00  82 ea 14 e2  e9 63 76 33
        7a 75 7a 75  f7 a2 d5 5c  19 f7 4d ff  e9 70 f9 a5
        ];
        //has-lock = <0x7C>;
		size = <1073741824>;
		has-dpd;
		t-enter-dpd = <3000>;
		t-exit-dpd = <3000>;
        quad-enable-requirements= "S2B1v1";
        //requires-ulbpr;
        address-size-32;
        enter-4byte-addr= <0xB7>; // 0xA5 is what is reported, but DS says 0xB7?
        partitions {
            compatible = "fixed-partitions";
            #address-cells = <1>;
            #size-cells = <1>;
    
            lfs_part: partition@0 {
                label = "lfs_storage";
                reg = <0x00000000 0x08000000>;
            };
        };
	};
};

And here is my relevant prj.conf settings:

# file system
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y
CONFIG_FS_LITTLEFS_BLK_DEV=y
CONFIG_DISK_ACCESS=y
CONFIG_FILE_SYSTEM_MKFS=y

# nvs and partitioning
CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_SETTINGS_NVS=y
CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE=y
CONFIG_NORDIC_QSPI_NOR=y
CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=65536
CONFIG_PM_PARTITION_REGION_LITTLEFS_EXTERNAL=y
CONFIG_PM_PARTITION_SIZE_LITTLEFS=0x8000000
CONFIG_MPU_ALLOW_FLASH_WRITE=y
CONFIG_FLASH_JESD216_API=y

CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y
CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=n

I've been messing with Device tree and overlay settings for a while without getting anywhere past this error -28 so far.

I did find that if I removed the CONFIG_PM_PARTITION_REGION_LITTLEFS_EXTERNAL setting, it would mount and run, but to the internal flash controller instead of external flash, despite any of the partition settings in the device tree.

I've ran the jesd216 example code to generate the following config information:

w25q01jv@0: SFDP v 1.6 AP ff with 2 PH
PH0: ff00 rev 1.6: 16 DW @ 80
Summary of BFP content:
DTR Clocking supported
Addressing: 3- or 4-Byte
4-KiBy erase: uniform
Support QSPI XIP
Support 1-1-1
Support 1-1-2: instr 3Bh, 0 mode clocks, 8 waits
Support 1-1-4: instr 6Bh, 0 mode clocks, 8 waits
Support 1-2-2: instr BBh, 2 mode clocks, 2 waits
Support 1-4-4: instr EBh, 2 mode clocks, 4 waits
Support 4-4-4: instr EBh, 2 mode clocks, 0 waits
Flash density: 134217728 bytes
ET1: instr 20h for 4096 By; typ 64 ms, max 896 ms
ET2: instr 52h for 32768 By; typ 128 ms, max 1792 ms
ET3: instr D8h for 65536 By; typ 160 ms, max 2240 ms
Chip erase: typ 60928 ms, max 365568 ms
Byte program: type 32 + 3 * B us, max 192 + 18 * B us
Page program: typ 704 us, max 4224 us
Page size: 256 By
Suspend: 75h ; Resume: 7Ah
DPD: Enter B9h, exit ABh ; delay 3000 ns ; poll 0x3d
HOLD or RESET Disable: unsupported
QER: 4
0-4-4 Mode methods: entry 0xd ; exit 0x3d
4-4-4 Mode sequences: enable 0x11 ; disable 0x9
4-byte addressing support: enter 0xa5, exit 0x3e5
Soft Reset and Rescue Sequence support: 0x30
Status Register 1 support: 0x69
size = <1073741824>;
sfdp-bfp = [
        e5 20 fb ff  ff ff ff 3f  44 eb 08 6b  08 3b 42 bb
        fe ff ff ff  ff ff 00 00  ff ff 40 eb  0c 20 0f 52
        10 d8 00 00  36 02 a6 00  82 ea 14 e2  e9 63 76 33
        7a 75 7a 75  f7 a2 d5 5c  19 f7 4d ff  e9 70 f9 a5
        ];
PH1: ff84 rev 1.0: 2 DW @ d0
sfdp-ff84 = [
        ff 0a f0 ff  21 ff dc ff
        ];
jedec-id = [ef 40 21];

I've tried manually declaring the partition in pm_static.yml, as well as modifying a lot of the devicetree and prj.conf settings without any success. I've seen others with similar issues when trying to use a NOR Flash chip greater than 128mb, is it a known issue? Or is there something obviously wrong in my configuration code that I am not catching?

Thanks,

- Brett

  • I believe I found the issue, I was able to get the littlefs sample working after adding a pullup resistor to both IO3/HOLD and IO2/WP. I wrongfully was assuming that the driver would be driving those high/low when needed, and that running it in Quad enable that it wouldn't be needed at all.

    Odd that the flash and JESD216 samples worked with this hardware configuration, while the littlefs sample could not.

    I will continue with these new hardware and firmware configurations in adding it into my main application, and update if I run into any other issues, otherwise I'll mark it closed.

  • Great find!

    This seems similar to the issue in  spi_flash is not running on nRF5340DK out of box  We first found this for v2.6.0, so I thought this would not be an issue for you since you use v2.4.2.

    But one of the PRs I mention there also mention IO3, so it is a good chance that this will have been fixed for you in v2.6.1.

  • Integration into my main application is going well. I want to round off this thread with some of the config settings I've found to have made a difference, and others I've settled on. Just in case someone finds it helpful.

    My relevant device tree came out to be this:

    &qspi {
    	status = "okay";
    	pinctrl-0 = <&qspi_default>;
    	pinctrl-1 = <&qspi_sleep>;
    	pinctrl-names = "default", "sleep";
        w25q01: w25q01@0 {
            compatible = "nordic,qspi-nor";
    		reg = <0>;
    		writeoc = "pp4o";
    		readoc = "read4io";
    		sck-frequency = <16000000>;
    		jedec-id = [EF 40 21];
            //sfdp-bfp = [
            //e5 20 fb ff  ff ff ff 3f  44 eb 08 6b  08 3b 42 bb
            //fe ff ff ff  ff ff 00 00  ff ff 40 eb  0c 20 0f 52
            //10 d8 00 00  36 02 a6 00  82 ea 14 e2  e9 63 76 33
            //7a 75 7a 75  f7 a2 d5 5c  19 f7 4d ff  e9 70 f9 a5
            //];
    
    		size = <1073741824>;
    		has-dpd;
    		t-enter-dpd = <3000>;
    		t-exit-dpd = <3000>;
            //requires-ulbpr;
            sck-delay = <5>;
            quad-enable-requirements= "S2B1v1";
            address-size-32;
            enter-4byte-addr= <0xB7>; // 0xA5 is what is reported, but DS says 0xB7?
    	};
    };


    I found that the sdfp-bfp field, and a few others from the JESD216 example weren't exactly accurate for some reason. But the manual config above seemed to work well. Also having nordic,drive-mode = <NRF_DRIVE_H0H1>; in my qspi pinctrl  proved necessary.

    Since I'm using the partition manager, and FSTAB or partition setting in the DTS would not have any effect, instead I could either manually declare it in pm_static, or use the prj.conf settings to put it in external and set the size. I chose the latter, with this code configuration to set the mount point:
    FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(lfs_storage);
    static struct fs_mount_t lfs_storage_mnt = {
    	.type = FS_LITTLEFS,
    	.fs_data = &lfs_storage,
    	.storage_dev = (void *)FIXED_PARTITION_ID(littlefs_storage),
    	.mnt_point = "/lfs",
    };


    My current prf.conf settings regarding qspi and FS are:

    # file system
    CONFIG_FLASH=y
    CONFIG_FLASH_MAP=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FILE_SYSTEM=y
    CONFIG_DISK_ACCESS=y
    CONFIG_FILE_SYSTEM_MKFS=y
    CONFIG_FILE_SYSTEM_LITTLEFS=y
    
    # nvs and partitioning
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    CONFIG_SETTINGS_NVS=y
    CONFIG_NORDIC_QSPI_NOR=y
    CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=65536
    CONFIG_PM_PARTITION_REGION_LITTLEFS_EXTERNAL=y
    CONFIG_PM_PARTITION_SIZE_LITTLEFS=0x8000000
    CONFIG_MPU_ALLOW_FLASH_WRITE=y
    CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=n


    Obviously having pullups on CS, IO3/HOLD and IO2/WP was the main difference maker in getting it working, but wanted to cover the other lessens learned.

    I had already begun the process to update to 2.6.X, just to stay up to date, but it is good to hear that a possible fix has already been rolled out.

    - Brett

Related