This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF9160dk storing to and reading from flash

What is the best/easiest way to store a struct or string to flash persistently?  I see other boards using FDS and other tools but those don't appear to be available on this board.  Are there any examples that write and read to and from flash?  I see DT_FLASH_AREA_6_DEV_LABEL=STORAGE so I assume I'm going to want to use that section of flash for my needs?

Any guidance would be much appreciated!

  • I was able to figure it out.  Zephyr has a library called NVS.

    In my prj.conf I added:

    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_NVS=y

    and then my code looks like this:

    #include <nvs/nvs.h>
    #include <device.h>
    #include <flash.h>
    
    
    {
    
    static struct nvs_fs fs;
    
    struct flash_pages_info info;
    fs.offset = DT_FLASH_AREA_STORAGE_OFFSET;
    err = flash_get_page_info_by_offs(device_get_binding(DT_FLASH_DEV_NAME),
        fs.offset, &info);
    if (err) {
        printk("Unable to get page info");
    }
    fs.sector_size = info.size;
    fs.sector_count = 3U;
    err = nvs_init(&fs, DT_FLASH_DEV_NAME);
    if (err) {
        printk("Flash Init failed\n");
    }
    
    char wbuf[16];
    char rbuf[16];
    strcpy(wbuf, "Hello");
    nvs_write(&fs, DT_FLASH_AREA_STORAGE_OFFSET, &wbuf, strlen(wbuf)+1);
    err = nvs_read(&fs, DT_FLASH_AREA_STORAGE_OFFSET, &rbuf, sizeof(rbuf));
    printk("%s", rbuf);
    
    }

  • Wanted to point out something I noticed after posting this:

    I name the return variable of the nvs read call "err" here, short for error. This could cause confusion because nvs_read returns the number of bytes read successfully and not an error code

  • Nice answer!

    Just please take into consideration that Zephyr is constantly under development, so API and libary locations might change, it is best to have a look at samples. 

    Currently good examples are under
    /zephyr/samples/subsys/nvs  
    and
    /nrf/lib/bin/lwm2m_carrier/os

    For example, now I had to use different include paths for flash and nvs:

    #include <drivers/flash.h>
    #include <fs/nvs.h>


    Also note that second parameter for nvs_write/nvs_read is currently not a memory offset, it is an ID.
    For details see https://docs.zephyrproject.org/latest/reference/storage/nvs/nvs.html?highlight=nvs_write#c.nvs_write

    Last, but not the least, depending where you are writing (e.g. I needed to write to inernal memory of NRF9160, I have custom layout),

    CONFIG_MPU_ALLOW_FLASH_WRITE=y

    Might be needed in your prj.conf
Related