No boot with CONFIG_NVS or LITTLEFS enabled

Hi,

I am trying to implement external flash storage onto my custom board, featuring an nrf9160-SICA-B1 and a Winbound w25q128jv 128Mbit flash chip on SPI3 (I cannot get QSPI to work in devicetree).

I am able to successfully read the entire flash chip through a small test script using the base flash_read APIs, however as soon as I enable either CONFIG_NVS or CONFIG_FILE_SYSTEM_LITTLEFS the board no longer boots, and debugging has only gotten me so far with an exception handler break somewhere inside TFM. I am unsure on how to debug this further, or what the root cause is. It's not clear what exactly breaks, as I don't even need to implement anything in my storage module (remove from cmake) and the board will still refuse to boot (or at least output to UART) so I assume something is wrong inside the TFM side of things.

Stepping through with the debugger it never gets past FIH_CALL(tfm_core_init, fih_rc);

It also appears that the partitions are not being placed into the external flash as I would expect, just looking at the partition yaml file. I tried static partition config but that also didn't help, and I am unsure on how to proceed for that as the documentation is unclear.

My end goal, is to have 16MB (128MBit) of flash memory available to either littlefs or NVS for storing persistent data offline while waiting for LTE to sync.

SPI3 Definition:

&spi3 {
  label = "SPI3";
  compatible = "nordic,nrf-spim";
  status = "okay";
  cs-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
  pinctrl-0 = <&spi3_default>;
  pinctrl-1 = <&spi3_sleep>;
  pinctrl-names = "default", "sleep";
  w25q128jv: w25q128jv@0 {
    compatible = "jedec,spi-nor";
    label = "W25Q128JV_SPI";
    reg = <0x0>;
    spi-max-frequency = <80000000>;
    wp-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
    hold-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
    size = <DT_SIZE_M(16)>;
    // has-dpd;
    // t-enter-dpd = <4000>;
    // t-exit-dpd = <25000>;
    jedec-id = [ ef 40 18  ];
  };
};

/{
  chosen {
    nordic,pm-ext-flash = &w25q128jv;
  };

};

Partition Definition:

/delete-node/ &storage_partition;

&w25q128jv {
  partitions {
    compatible = "fixed-partitions";
    #address-cells = <1>;
    #size-cells = <1>;
    partition@0 {
      label = "storage";
      reg = <0x0 DT_SIZE_M(16)>;
    };
  };
};

My prj.conf

#### Flash Storage ####
CONFIG_SPI=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
CONFIG_NORDIC_QSPI_NOR=n

CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FILE_SYSTEM=y
CONFIG_FS_LOG_LEVEL_DBG=y

# Uncommenting either of these causes the board to not run
# CONFIG_FILE_SYSTEM_LITTLEFS=y
# CONFIG_NVS=y

Happy to provide more debugging information as necessary, just not sure what to include. I may be missing something.

  • I was able to configure the NVS sample to use onboard external flash on the nRF9160 DK. I programmed using the 0.14.0 version of the board,

    which will apply this dts node:

    https://github.com/nrfconnect/sdk-zephyr/blob/98bc3a7a6b3917ce5a058e7a7271d3036edffb88/boards/arm/nrf9160dk_nrf9160/nrf9160dk_nrf9160_common_0_14_0.dtsi#L40-L60

    Can you test the following sample? Test it with the nRF9160 DK first (remember to program the nrf9160dk_nrf52840 with this sample first).

    0143.nvs_ext_flash_9160.zip

    If you succeed with that, modify it to your specific flash device.

    The proper way to do it, would be to add a pm_static.yml file with something like this:

    nvs_storage:
      address: 0x00000
      device: MX25R64
      region: external_flash
      size: 0x40000
    external_flash:
      address: 0x0
      end_address: 0x800000
      region: external_flash
      size: 0x800000
    

    Then fetch the device and offset from the storage partition in main.c, 

    #define STORAGE_NODE_LABEL storage //this should resolve to the nvs_storage partition defined in the pm_static.yml file
    
    
    //This should get the "MX25R64" device from the pm_static.yml file
    FLASH_AREA_DEVICE(STORAGE_NODE_LABEL);
    if (!device_is_ready(fs.flash_device)) {
    	printk("Flash device %s is not ready\n", fs.flash_device->name);
    	return;
    }
    
    //This should get the offset (address) from the pm_static.yml file
    fs.offset = 0x0;//FLASH_AREA_OFFSET(storage);

    However, I was not able to get it to work doing it this way, so I just set the device and offset directly.

    Let me know if are able to get the sample to run, and if you're able to modify it according to your external flash. Also let me know if you would like me to look more into the pm_static.yml-approach.

    Best regards,

    Simon

  • Hi Simon,

    I don't have a DK, we developed on a SparkFun Thing Plus nrf9160, however modifying the sample you gave for my board yielded the same results. No boot, and the debugger dying after a call to FIH_CALL(tfm_core_init, fih_rc);

    Applying partition manager to my project and adjusting for the 128MBit size doesn't seem to make partition manager happy. Honestly memory addresses and stuff like that confuse me a little, so I may have missed something.

    nvs_storage:
      address: 0x00000
      device: W25Q128JV
      region: external_flash
      size: 0x7F00000
    external_flash:
      address: 0x0
      end_address: 0x8000000
      region: external_flash
      size: 0x8000000
    

    I would posit that it appears there is nothing wrong with my devicetree spec or hardware layout, as I have been experimenting with nanopb and raw read/write to flash with no issues, although it's entirely possible it's something in there. I notice that the DK version has a definition for sfdp-bfp which I don't really know how to get out of the device and I'm not 100% on the JEDEC ID for my particular chip, only following what others have done online. The other thing that is different is I am using pinctrl and have dpd disabled; changing either does not resolve the issue.

    I think static partition definition will be easier, but does not solve the problem of  the OS not booting regardless of where the partition is placed with either CONFIG_NVS or CONFIG_FILE_SYSTEM_LITTLEFS enabled.

  • Small update. I was able to compile the application an flash it with successful boot with a hardcoded region size of 0x200000 (2MB), which is not ideal realy but will do for now. My flash chip is 16MB. I have yet to test if NVS actually stores data on the SPI flash or not but for now at least the board boots.


    It seems somewhere external_flash is hardcoded to be 0x200000 and I can't really find where to change that, as the pm_static.yml file does not override the region size only the partition size.

    The size parameter in regions.yaml doesn't seem to be able to be over 2MB.

     

    nvs_storage:
      address: 0x0
      device: W25Q128JV
      region: external_flash
      size: 0x200000
    external_flash:
      address: 0x0
      end_address: 0x200000
      region: external_flash
      size: 0x200000
    

  • Thanks for pointing this out. I can confirm checking out to this commit worked fine (specifically 15f20b80ea09a9485968b4d312a3fcf1a51d6ec3)

    I was able to remove the pm_static.yml file completely and all works fine. However, despite having the flash device size set as 16MB in devicetree (
    DT_SIZE_M(16)), the external_flash region is still only 2MB large and I can't find where to change this.


    Explicitly making the nvs_storage partition 16MB using 
    CONFIG_PM_PARTITION_SIZE_NVS_STORAGE=0x1000000 yields some interesting and probably incorrect results.

    partitions.yml sets the external_flash partition to have a negative size, spefically 2MB - 16MB (-0xe00000)
    external_flash:
      address: 0x1000000
      end_address: 0x200000
      region: external_flash
      size: -0xe00000
    
    ...
    
    nvs_storage:
      address: 0x0
      device: /soc/peripheral@40000000/spi@b000/w25q128jv@0
      end_address: 0x1000000
      placement:
        before:
        - tfm_storage
        - end
      region: external_flash
      size: 0x1000000
    And in regions.yml, the external_flash region is still set as 2MB wide.
    external_flash:
      base_address: 0x0
      default_driver_kconfig: CONFIG_NORDIC_QSPI_NOR
      device: /soc/peripheral@40000000/spi@b000/w25q128jv@0
      dynamic_partition: null
      name: external_flash
      placement_strategy: start_to_end
      size: 0x200000
    I cannot seem to change the region size manually only the partition of the same name, despite the flash chip's size being specified in devicetree.
    The device does still boot however, and does not complain about initialising 4096 sectors of 4096 bytes of NVS (16MB) but I don't know if this is actually writeable or not, or if the yml is just wrong and that doesn't impact much.
Related