LittleFs file support for QSPI flash in Zephyr

Mark Zachmann
Home Wireless
Published in
3 min readApr 16, 2020

The board I’m working on has 1MB of QSPI flash. That is serial flash that’s directly controlled by the Nordic nrf52840. See here ->

QspiFlash connections to chip

The chip can use any 6 high-speed pins it likes for the flash interface so I’ve chosen pins that make the layout simple. Nordic suggests certain pins for noise/speed reasons and these are mainly from that set.

I had a terrible time getting this working correctly. It’s not hard to get it working well, it’s hard to figure out exactly what to set. So,…

It’s simple in zephyr to read/write raw data to the chip, tougher to get integrated use of qspi functionality where the F_DataX pins produce a 4 pin data bus for speed and easy dma.

Author’s Note: the latest (Jun 2021) version of Zephyr has redone the Qspi interface, changing some of the dtsi specifications. This writeup doesn’t yet cover the changes because they seem to be not-quite-solid. I will update this article in a few months when the changes are firmed up.

The Nordic-specific Qspi driver was added at the end of 2019. I haven’t checked, but compared with raw SPI this driver should be much quicker and more power efficient.

1. Add Qspi Definition to the .dts file

This chunk specifies the pin mappings and other flash chip internals like max clock frequency.

It is added to my board .dtsi file. For information about the entries see: zephyr\dts\bindings\mtd\nordic,qspi-nor.yaml or use the gui to see qspi-nor settings.

This entry says we have a device based off the predefined qspi-nor device. See the schematic above for pin-mapping. It must be specified as &qspi to inherit from the nrf52840 qspi definition.

&qspi { /* dedicated MX25L */
status = "okay";
sck-pin = <21>;
io-pins = <17>, <23>, <22>, <19>;
csn-pins = <20>;
mx25r08: mx25r0835f@0 {
compatible = "nordic,qspi-nor";
reg = <0>;
writeoc = "pp4io";
readoc = "read4io";
sck-frequency = <8000000>;
label = "MX25R0835F";
jedec-id = [c2 28 14];
size = <0x0800000>; /* flash capacity in bits */
has-be32k;
has-dpd;
t-enter-dpd = <10000>;
t-exit-dpd = <35000>;
};
};

Note that if you get the jedec-id wrong then no driver will be created and you’ll be left with null pointers to undefined drivers.

The writeoc and readoc values indicate that all 4 pins are used for data and the size here is deliberately small to guarantee some of the flash is left alone. The sck-frequency is also very conservative.

2. Specify a “storage” partition

Also added to the board .dtsi file is the following partition:

// using an mx25R0835
/delete-node/ &storage_partition;
&mx25r08 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@40000 {
label = "storage";
reg = <0x00040000 0x00020000>;
};
};
};

Here I don’t need much space so I’ve started the partition at 0x40000 to leave space at the beginning for a fat system or other stuff. The reg setting is <’offset’ ‘size in bytes’>.

The &mx25r08 links it to the qspi definition subobject and we thus have a single partition of size 0x20000 named ‘storage’. We delete-node the original board default soc flash storage_partition.

3. Add defines to prj.conf

Now we have to add enough to the prj.conf to support qspi.

# Need this when storage is on MX25R08
CONFIG_NORDIC_QSPI_NOR=y
# the default page size is 64K but 4K is allowed so...
CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
#--- any file system
CONFIG_FLASH=y
CONFIG_FILE_SYSTEM=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y
#----little file system
CONFIG_FILE_SYSTEM_LITTLEFS=y

3a. Debugging ->

It’s hard to see what’s going wrong during qspi definition because most of the driver initialization is done static — before main() gets called. It is possible, however, to put breakpoints on that initialization code in Segger and that’s how I tracked down the jedec-id requirement. Find the source module then place a breakpoint.

Debugging the flash init sequence

4. Use it in code

Here’s a code chunk with one test method and one raw read/write method.

--

--

Mark Zachmann
Home Wireless

Entrepreneur, software architect, electrical engineer. Ex-academic.