External flash on nRF9151-DK using NVS - nvs.h and too little storage

Hi,
I want to use the external flash on nRF9151-DK (gd25wb256).
Having set all the necessary files (prj.conf, nrf9151dk_nrf9151_ns.overlay) and some parameters in the main.c (code below) I eventually gained access and ability to store data in flash memory using NVS. However ,I have encountered two problems:

  1. The first one was having an error (overflow of nvs_fs.sector_size) during the initialization of the NVS, which I have resolved by changing the type (uint16_t to uint32_t inside the nvs.h file - as suggested in this issue: https://github.com/zephyrproject-rtos/zephyr/issues/36590). Is there any cleaner way to get the NVS to work with this memory?

  2. I set the config to 256 sectors of 65536 bytes to get it working, but it results in only about 16MiB (16707592 bytes reported by library) of memory. However, setting the config to 512 (accordingly to the datasheet I found) results in having corrupted data (error during reading). Why is that?

    nrf9151dk_nrf9151_ns.overlay:
    / {
    	chosen {
    		nordic,pm-ext-flash = &gd25wb256;
    	};
    };
    
    &gd25wb256 {
    	status = "okay";
    };


    prj.conf:
    CONFIG_LOG=y
    CONFIG_LOG_MODE_IMMEDIATE=y
    CONFIG_NVS_LOG_LEVEL_DBG=y
    
    CONFIG_GPIO=y
    CONFIG_NVS=y
    
    CONFIG_FLASH=y
    CONFIG_FLASH_MAP=y
    CONFIG_SPI=y
    CONFIG_SPI_NOR=y
    CONFIG_SPI_NOR_SFDP_DEVICETREE=y
    CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y
    CONFIG_PM_PARTITION_REGION_NVS_STORAGE_EXTERNAL=y


    main.c:
    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/flash.h>
    #include <zephyr/storage/flash_map.h>
    #include <zephyr/fs/nvs.h>
    #include <string.h>
    #include <zephyr/drivers/uart.h>
    #include <zephyr/drivers/gpio.h>
    
    #define NVS_PARTITION external_flash
    #define NVS_PARTITION_DEVICE FIXED_PARTITION_DEVICE(NVS_PARTITION)
    #define NVS_PARTITION_OFFSET FIXED_PARTITION_OFFSET(NVS_PARTITION)
    
    static struct nvs_fs fs;
    
    int main(void)
    {
        int rc = 0;
        struct flash_pages_info info;
    
        fs.flash_device = NVS_PARTITION_DEVICE;
    
    	printk("Flash device name: %s\n", fs.flash_device->name);
        if (!device_is_ready(fs.flash_device))
        {
            printk("Flash device %s is not ready\n", fs.flash_device->name);
            return 0;
        }
        fs.offset = NVS_PARTITION_OFFSET;
        rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info);
        if (rc)
        {
            printk("Unable to get page info\n");
            return 0;
        }
    
        fs.sector_size = info.size;
        printk("Sector size: %u", fs.sector_size);
    
        fs.sector_count = 256;
    
        rc = nvs_mount(&fs);
        if (rc)
        {
            printk("Flash Init failed\n");
    		printk("Flash device name: %s\n", fs.flash_device->name);
            return 0;
        }
        ssize_t free_space = nvs_calc_free_space(&fs);
    
        printk("Free space on NVS partition NVS: %zd bytes\n", free_space);
        return 0;
    }
    


    output:
    [00:00:00.428,619] <inf> spi_nor: gd25wb256e3ir@1: 32 MiBy flash
    *** Booting nRF Connect SDK v3.1.1-e2a97fe2578a ***
    *** Using Zephyr OS v4.1.99-ff8f0c579eeb ***
    Flash device name: gd25wb256e3ir@1
    Sector size: 65536[00:00:00.489,471] <dbg> fs_nvs: nvs_recover_last_ate: Recovering last ate from sector 0
    [00:00:02.482,360] <inf> fs_nvs: 256 Sectors of 65536 bytes
    [00:00:02.488,311] <inf> fs_nvs: alloc wra: 0, ffe8
    [00:00:02.493,621] <inf> fs_nvs: data wra: 0, 0
    Free space on NVS partition NVS: 16707592 bytes


    Is there any way to gain acces to whole memory using NVS? Is there any more elegant way to fix the header file (nvs.h).
    I will be grateful for any feedback, thanks!

    Best regards,
    Michal

  • Have You modified the nvs.h as I have (described in the first bullet point)? 

    It seems like that's an error I was dealing with before modyfing type in the header file. 

    My NCS version is 3.1.1

    Partitions.yml:

    app:
      address: 0x8000
      end_address: 0x100000
      region: flash_primary
      size: 0xf8000
    external_flash:
      address: 0x6000
      end_address: 0x2000000
      region: external_flash
      size: 0x1ffa000
    nrf_modem_lib_ctrl:
      address: 0x20008000
      end_address: 0x200084e8
      inside:
      - sram_nonsecure
      placement:
        after:
        - tfm_sram
        - start
      region: sram_primary
      size: 0x4e8
    nrf_modem_lib_rx:
      address: 0x2000a568
      end_address: 0x2000c568
      inside:
      - sram_nonsecure
      placement:
        after:
        - nrf_modem_lib_tx
      region: sram_primary
      size: 0x2000
    nrf_modem_lib_sram:
      address: 0x20008000
      end_address: 0x2000c568
      orig_span: &id001
      - nrf_modem_lib_ctrl
      - nrf_modem_lib_tx
      - nrf_modem_lib_rx
      region: sram_primary
      size: 0x4568
      span: *id001
    nrf_modem_lib_tx:
      address: 0x200084e8
      end_address: 0x2000a568
      inside:
      - sram_nonsecure
      placement:
        after:
        - nrf_modem_lib_ctrl
      region: sram_primary
      size: 0x2080
    nvs_storage:
      address: 0x0
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0x6000
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x6000
    otp:
      address: 0xff8108
      end_address: 0xff83fc
      region: otp
      size: 0x2f4
    sram_nonsecure:
      address: 0x20008000
      end_address: 0x20040000
      orig_span: &id002
      - sram_primary
      - nrf_modem_lib_ctrl
      - nrf_modem_lib_tx
      - nrf_modem_lib_rx
      region: sram_primary
      size: 0x38000
      span: *id002
    sram_primary:
      address: 0x2000c568
      end_address: 0x20040000
      region: sram_primary
      size: 0x33a98
    sram_secure:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id003
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id003
    tfm:
      address: 0x0
      end_address: 0x8000
      placement:
        before:
        - app
      region: flash_primary
      size: 0x8000
    tfm_nonsecure:
      address: 0x8000
      end_address: 0x100000
      orig_span: &id004
      - app
      region: flash_primary
      size: 0xf8000
      span: *id004
    tfm_secure:
      address: 0x0
      end_address: 0x8000
      orig_span: &id005
      - tfm
      region: flash_primary
      size: 0x8000
      span: *id005
    tfm_sram:
      address: 0x20000000
      end_address: 0x20008000
      inside:
      - sram_secure
      placement:
        after:
        - start
      region: sram_primary
      size: 0x8000
    

  • You can try to change the nvs_storage partition by adding it in a pm_static.yml file, and changing the size property;

    nvs_storage:
      address: 0x0
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0x6000
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x6000

  • After adding pm_static.yml file and changing the size, nvs_storage partition got larger.

    However, I think it is external_flash that is being used. Free space on NVS (printed from main.c) was still the same (there were still 256 sectors times 65536 bytes in the init of nvs):

    *** Booting nRF Connect SDK v3.1.1-e2a97fe2578a ***
    *** Using Zephyr OS v4.1.99-ff8f0c579eeb ***
    Flash device name: gd25wb256e3ir@1
    Sector size: 65536[00:00:00.334,442] <dbg> fs_nvs: nvs_recover_last_ate: Recovering last ate from sector 0
    [00:00:02.014,251] <inf> fs_nvs: 256 Sectors of 65536 bytes
    [00:00:02.020,202] <inf> fs_nvs: alloc wra: 0, 9a68
    [00:00:02.025,482] <inf> fs_nvs: data wra: 0, 1ae0
    Free space on NVS partition NVS: 16699324 bytes
    


    Changing the sector count to 512 resulted in error (as originally):
    *** Booting nRF Connect SDK v3.1.1-e2a97fe2578a ***
    *** Using Zephyr OS v4.1.99-ff8f0c579eeb ***
    Flash device name: gd25wb256e3ir@1
    Sector size: 65536[00:00:00.532,379] <dbg> fs_nvs: nvs_recover_last_ate: Recovering last ate from sector 0
    [00:00:02.211,547] <inf> fs_nvs: 512 Sectors of 65536 bytes
    [00:00:02.217,498] <inf> fs_nvs: alloc wra: 0, 9a68
    [00:00:02.222,808] <inf> fs_nvs: data wra: 0, 1ae0
    Free space on NVS partition NVS: -22 bytes
    


    Could you confirm whether the modifications to nvs.h were applied during the issue reproduction?

  • Mich@l said:
    Changing the sector count to 512 resulted in error (as originally):

    I get this error when I run the code with the original partition layout. But after changing it with pm_static.yml, it seems to work;

    app:
      address: 0x8000
      end_address: 0x100000
      region: flash_primary
      size: 0xf8000
    external_flash:
      address: 0x0
      end_address: 0x2000000
      region: external_flash
      size: 0x2000000
    nrf_modem_lib_ctrl:
      address: 0x20008000
      end_address: 0x200084e8
      inside:
      - sram_nonsecure
      placement:
        after:
        - tfm_sram
        - start
      region: sram_primary
      size: 0x4e8
    nrf_modem_lib_rx:
      address: 0x2000a568
      end_address: 0x2000c568
      inside:
      - sram_nonsecure
      placement:
        after:
        - nrf_modem_lib_tx
      region: sram_primary
      size: 0x2000
    nrf_modem_lib_sram:
      address: 0x20008000
      end_address: 0x2000c568
      orig_span: &id001
      - nrf_modem_lib_ctrl
      - nrf_modem_lib_tx
      - nrf_modem_lib_rx
      region: sram_primary
      size: 0x4568
      span: *id001
    nrf_modem_lib_tx:
      address: 0x200084e8
      end_address: 0x2000a568
      inside:
      - sram_nonsecure
      placement:
        after:
        - nrf_modem_lib_ctrl
      region: sram_primary
      size: 0x2080
    nvs_storage:
      address: 0x0
      device: DT_CHOSEN(nordic_pm_ext_flash)
      end_address: 0x2000000
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x2000000
    otp:
      address: 0xff8108
      end_address: 0xff83fc
      region: otp
      size: 0x2f4
    sram_nonsecure:
      address: 0x20008000
      end_address: 0x20040000
      orig_span: &id002
      - sram_primary
      - nrf_modem_lib_ctrl
      - nrf_modem_lib_tx
      - nrf_modem_lib_rx
      region: sram_primary
      size: 0x38000
      span: *id002
    sram_primary:
      address: 0x2000c568
      end_address: 0x20040000
      region: sram_primary
      size: 0x33a98
    sram_secure:
      address: 0x20000000
      end_address: 0x20008000
      orig_span: &id003
      - tfm_sram
      region: sram_primary
      size: 0x8000
      span: *id003
    tfm:
      address: 0x0
      end_address: 0x8000
      placement:
        before:
        - app
      region: flash_primary
      size: 0x8000
    tfm_nonsecure:
      address: 0x8000
      end_address: 0x100000
      orig_span: &id004
      - app
      region: flash_primary
      size: 0xf8000
      span: *id004
    tfm_secure:
      address: 0x0
      end_address: 0x8000
      orig_span: &id005
      - tfm
      region: flash_primary
      size: 0x8000
      span: *id005
    tfm_sram:
      address: 0x20000000
      end_address: 0x20008000
      inside:
      - sram_secure
      placement:
        after:
        - start
      region: sram_primary
      size: 0x8000
    

    This is the output;

  • Thanks a lot! The configuration you provided works. However, just to clarify, do we need to change the type in nvs.h?
    Even with your partition configuration, there was an error (<err> fs_nvs: Invalid sector size) when using the original header file.

Related