Using NVS on external flash with Partition_Manager through QSPI_NOR.

Hello,

I am moving my project from SDK 2.6.2 with Adafruit_bootloader to SDK 2.9.0 with MCUboot/sysbuild. The problem I face is that I can't access the external flash using NVS anymore.

Here is my relevant zephyr_code.c, where "user_partition" is declared in the external flash:

#define NVS_PARTITION user_partition
#define NVS_PARTITION_DEVICE FIXED_PARTITION_DEVICE(NVS_PARTITION)
#define NVS_PARTITION_OFFSET FIXED_PARTITION_OFFSET(NVS_PARTITION)

int nvs_init(const uint16_t max_retries) {
  int rc = 0;
  struct flash_pages_info info;

  LOG_INF("NVS init");

  fs.flash_device = NVS_PARTITION_DEVICE;
  if (!device_is_ready(fs.flash_device)) {
    LOG_ERR("Flash device %s is not ready\n", fs.flash_device->name);
    return EXIT_FAILURE;
  }
  fs.offset = NVS_PARTITION_OFFSET;
  rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info);
  if (rc) {
    LOG_ERR("Unable to get page info\n");
    return EXIT_FAILURE;
  }
  fs.sector_size = info.size;
  fs.sector_count = NVS_SECTOR_COUNT;
  
  rc = nvs_mount(&fs);
  return EXIT_SUCCESS;
}

The code fails in the following line:

rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info)

When I inspect it in debugger mode, I can localize the problem to this line of flash_page_layout.c:

static int flash_get_page_info(const struct device *dev, off_t offs,
uint32_t index, struct flash_pages_info *info)
[...]
api->page_layout(dev, &layout, &layout_size);

The layout retrieved by the driver has 64 pages of 4096 bytes each, which is 0x40000 bytes total, instead of the expected 0x200000 bytes. As a result, the external device's size is assessed shorter than the base address of user_partition and an error is returned.

Here is the output of "west build -t partition_manager_report", for an overview of how I expect my partitions to behave:

  external_flash (0x200000 - 2048kB): 
+---------------------------------------------+
+---0x0: external_flash (0x200000 - 2048kB)---+
| 0x0: mcuboot_secondary (0xf1000 - 964kB)    |
| 0xf1000: storage_partition (0x10000 - 64kB) |
| 0x101000: user_partition (0x10000 - 64kB)   |
+---------------------------------------------+

  flash_primary (0x100000 - 1024kB): 
+-------------------------------------------------+
| 0x0: mcuboot (0xf000 - 60kB)                    |
+---0xf000: mcuboot_primary (0xee000 - 952kB)-----+
| 0xf000: mcuboot_pad (0x200 - 512B)              |
+---0xf200: mcuboot_primary_app (0xede00 - 951kB)-+
| 0xf200: app (0xece00 - 947kB)                   |
| 0xfc000: settings_storage (0x2000 - 8kB)        |
| 0xfe000: internal_storage (0x2000 - 8kB)        |
+-------------------------------------------------+

  sram_primary (0x40000 - 256kB): 
+--------------------------------------------+
| 0x20000000: sram_primary (0x40000 - 256kB) |

Now this 0x40000 value reminds me of the auto-generated regions.yml file which looks like this:

external_flash:
  base_address: 0x0
  default_driver_kconfig: CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK
  device: DT_CHOSEN(nordic_pm_ext_flash)
  dynamic_partition: null
  name: external_flash
  placement_strategy: start_to_end
  size: 0x40000
flash_primary:
  base_address: 0x0
  default_driver_kconfig: CONFIG_SOC_FLASH_NRF
  device: flash_controller
  dynamic_partition: null
  name: flash_primary
  placement_strategy: complex
  size: 0x100000
sram_primary:
  base_address: 0x20000000
  default_driver_kconfig: ''
  device: ''
  dynamic_partition: sram_primary
  name: sram_primary
  placement_strategy: complex
  size: 0x40000

Here the size of the external_flash region is 0x40000 which is really suspicious. Is this the root of my problem ? If yes, how do I change this value ? The only doc I found is very unclear, or at least I don't manage to change the region size this way.

As additional info, here is the device.overlay I'm using to access the external flash:

&qspi {
	status = "okay";
	pinctrl-0 = <&qspi_default>;
	pinctrl-1 = <&qspi_sleep>;
	pinctrl-names = "default", "sleep";
	p25q16h: p25q16h@0 {
		compatible = "nordic,qspi-nor";
		reg = <0>;
		sck-frequency = <104000000>;
		quad-enable-requirements = "S2B1v1";
		jedec-id = [85 60 15];
		sfdp-bfp = [
			e5 20 f1 ff  ff ff ff 00  44 eb 08 6b  08 3b 80 bb
			ee ff ff ff  ff ff 00 ff  ff ff 00 ff  0c 20 0f 52
			10 d8 08 81
		];
		size = <2000000>;
		has-dpd;
		t-enter-dpd = <3000>;
		t-exit-dpd = <8000>;
	};
};

Thank you for your time !

Parents
  • Okay, once again I got it. Second time I'm posting on this forum and answer myself the next day. Somehow posting on this forum is a very efficient process :D.

    I got tricked into thinking that the <size> parameter of p25q16h was expressed in bytes, not bit. So the size of my external device was 8 times lower than what I expected. I corrected it and resolved my bug. I also noticed that following this modification, the size parameter in regions.yml has been correctly adjusted to 0x200000, so apparently this value is based directly on the value read on the device tree.

Reply
  • Okay, once again I got it. Second time I'm posting on this forum and answer myself the next day. Somehow posting on this forum is a very efficient process :D.

    I got tricked into thinking that the <size> parameter of p25q16h was expressed in bytes, not bit. So the size of my external device was 8 times lower than what I expected. I corrected it and resolved my bug. I also noticed that following this modification, the size parameter in regions.yml has been correctly adjusted to 0x200000, so apparently this value is based directly on the value read on the device tree.

Children
No Data
Related