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.

Parents
  • 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.
Reply
  • 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.
Children
  • First I will start with some clarifications

    You don't need to use the pm_static.yml file at all. All the partitions will get it's size from pm.yml files by default. For example the nvs_storage partition will get it from ncs/nrf/subsys/partition_manager/pm.yml.nvs and mcuboot will get it from ncs/bootloader/mcuboot/boot/zephyr/pm.yml.

    The position of the partitions are set relatively/dynamically in the pm.yml-files, and the Partition Manager script will go through all the pm.yml files and generate a static fixed output.

    napei_ said:
    I was able to remove the pm_static.yml file completely and all works fine.

    Yes, in my original reply, that was my workaround as well. As mentioned above, this file is not needed. If you want to set the size and/or position of the nvs_storage to a fixed value, you can use the pm_static.yml file or Kconfigs (CONFIG_PM_PARTITION_SIZE_NVS_STORAGE for example).

    The important thing is that you should use the partition manager definitions in the source code to get the size and offset of the nvs_storage, for example by using FLASH_AREA_OFFSET(nvs_storage). This is to guarantee that the flash area you're accessing is not used by something else, like mcuboot, tfm/spm or the secondary slot.

    napei_ said:
    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.

    If your application have more than one image (not only the app partition), the DTS flash partitions will be ignored and the Partition Manager script and pm.yml/pm_static.yml files will be used to partition the flash. So setting the external flash to 16MB in the devicetree will have no effect.

    See the following note in the Partition Manager documentation:

    napei_ said:

    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)

    Have you been able to figure this out? Let me know if I should take a closer look at this.

    Best regards,

    Simon

  • Thanks Simon.

    In case it was unclear, placing the NVS partition on external flash was not working for me until I built using this commit of the SDK. I don't know why, it just wasn't booting and the output yaml was wrong, but this is solved now.

    Nonetheless, while I can read and write to the whole 16MB of flash manually, I can't find (or it's not supported) a way to make the NVS partition 16MB wide, which it does incorrectly as reflected by the negative size in the yml file. Probably worth looking into. Setting it to 16MB with KConfig yields some EINVAL errors that I can't concretely track down their source through debugging, but that may have been something else. Technically it "works" though.

    If there is a specific way I should set the nvs_storage size other than CONFIG_PM_PARTITION_SIZE_NVS_STORAGE that would be good to know, but I feel it may be a bug.

Related