How to get started with NOR flash on Zephyr ?

Hi,

I'm pretty new to Zephyr and I have to figure out how to connect to a NOR flash over SPI. Final application is the implementation of a file system, e.g. littlefs.

There is very little documentation on the web on that subject and one of the only I could find was this thread here: https://devzone.nordicsemi.com/f/nordic-q-a/75393/how-to-get-started-with-zephyr-fs-on-external-nor-flash?focus=true and those linked with it.

I'm working on a custom platform with a standard 4-wire SPI and the NOR Flash is Microchip SST25VF016. Maybe someone could help me with a general hint because due to little documentation and experience, I'm stucked. Thanks in advance!

First goal is to make the Zephyr NOR-flash example to run.

First problem is that my device handle from the devicetree is always empty. I guess that something is missing/ wrong with the NOR Flash driver but I don't get it. Do I need a binding (.yaml) file for the particular flash type? If so, where can I find a template (like the everywhere used MX25r64)?

In my config I added this:

# support nor flash on spi
CONFIG_FLASH=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

In the devicetree I added "jedec, spi-nor" and "fixed-partitions" object: (the SPI-interface for itself has been tested before and is working).

&spi1 {    
    status = "okay";
    pinctrl-0 = <&spi1_sck_pg2 &spi1_miso_pg3 &spi1_mosi_pg4>;
    pinctrl-names = "default";
      sst25: sst25vf016@0  {
        compatible = "jedec,spi-nor";
        label = "SST25";
        reg = <0>;
        spi-max-frequency = <1000000>;
        jedec-id = [c2 28 17];
        size = <16777216>;
    };
};

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

        partition@0 {
          label = "storage";
          reg = <0x01000000 0x00800000>;
        };
    };
};

My initialization looks like this:

#include "stdIncl.h"
#include <drivers/spi.h>
#include <drivers/flash.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"
#else
#error "Missing SPI-NOR flash in device tree"
#endif

Everything builds and runs fine. FLASH_DEVICE resolves to "SST25" but after the initialization, the device handle is always null:

static const struct device* s_device_p;

s_device_p = device_get_binding( FLASH_DEVICE ); //becomes 0x0

Any help is appreciated!

  • Hi, 

    s_device_p = device_get_binding( FLASH_DEVICE ); //becomes 0x0

    Which version of NCS are you using? Is it v2.1.0? If so, func:`device_get_binding()` usage is removed in favor of func:`DEVICE_DT_GET()`. See the release-notes-2.1.0

    See the example here https://github.com/nrfconnect/sdk-zephyr/blob/main/samples/drivers/spi_flash/src/main.c#L37 

    Regards,
    Amanda H.

  • Hi,

    Thank you for the quick reply!

    With s_flashdevice_p = DEVICE_DT_GET(DT_NODELABEL(sst25));

    I now get a non-null instance that looks like that:

    s_flashdevice_p: 0x804ede8 <__device_dts_ord_626>
        name: 0x8059f6e "SST25VF016"
            *name: 83 'S'
        config: 0x8050c24 <spi_nor_config_0>
        api: 0x8050c10 <spi_nor_api>
        state: 0x20000d70 <__devstate_dts_ord_626>
            init_res: 22
            initialized: true
        data: 0x200053b4 <spi_nor_data_0>
        handles: 0x804f3d8 <__devicehdl_DT_N_S_soc_S_spi_40013000_S_sst25vf016_0>
            *handles: 36

    But then, doing

    device_is_ready( s_flashdevice_p );

    returns false, due to init_res != 0 I guess.

    Any hint what might be wrong with my setup?

    In the sample, you use DEVICE_DT_GET(DT_ALIAS(spi_flash0)); Where is spi_flash0 definied? I can't find any dts in the sample project. It might be helpful as a starting point!

    Thanx,

    Marco

  • Hi again,

    I figured out the reason for the device_is_ready() = false: The initialization fails because the JEDEC-ID does not match. This is probably because of the way we initialize the SPI-interface.

    I'll come back when I have new findings!

  • Hi again,

    I was able to make the NOR-flash run over SPI! Mainly the configuration for the SST25 had to be adapted and some particularity with our board.

    I was also able to make the NVS Filesystem sample run.

    Now I try with the littleFS sample and here I got stuck again: When building, I get an error saying

    /zephyr/include/zephyr/fs/littlefs.h:14:10: fatal error: lfs.h: No such file or directory
       14 | #include <lfs.h>

    As this file does not exist nowhere in the filesystem I suppose it should be generated by zephyr but it isn't

    Within littlefs.h I find

    #include <lfs.h>

    When I comment it out, some symbols like

    struct lfs_config cfg;

    are marked as unknown.

    My dts looks like this:

    &sst25 {
        partitions {
            compatible = "fixed-partitions";
            #address-cells = <1>;
            #size-cells = <1>;
            /* 16 KBy partition to use for LFS filesystem */
            partition@0001000 {
                label = "storage";
                reg = <0x0001000 0x0004000>;
            };
        };
    };

    and the node initialization like this:

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

    and the conf like this:

    CONFIG_FLASH=y
    CONFIG_FLASH_MAP=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_SPI_NOR=y
    CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
    CONFIG_FILE_SYSTEM=y
    CONFIG_FILE_SYSTEM_LITTLEFS=y

    Any idea what could cause this problem?

    Thanx

    Marco

  • Hi, 

    Which version of NCS are you using?

    If you are using v2.1.1, lfs.h is under modules\fs\littlefs.

    -Amanda H.

Related