(Zephyr / NCS) NVS Error: flash_nrf: invalid address: with CONFIG_SETTINGS=y

I am trying to implement bonded pairing with a project in which I already have NVS configured for user data. When implementing bonding, I understand that I need to remove the CONFIG_SETTINGS_NONE=y flag and add a CONFIG_SETTINGS=y flag. I assume this is to store the bond information on the device in persistent storage.

However, when I remove CONFIG_SETTINGS_NONE from my project, my NVS reads start to fail. The error I am receiving is below:

[00:01:02.705,261] <err> flash_nrf: invalid address: 0x00080ff8:8

Here is how I start my NVS driver:

#define STORAGE_NODE DT_NODE_BY_FIXED_PARTITION_LABEL(storage)
#define FLASH_NODE DT_MTD_FROM_FIXED_PARTITION(STORAGE_NODE)

user_config_data_t user_config_data;

static struct nvs_fs fs;

void load_user_data(void)
{
	int rc_flash;
	struct flash_pages_info info;
	const struct device *flash_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));
	/* define the nvs file system by settings with:
	 *	sector_size equal to the pagesize,
	 *	3 sectors
	 *	starting at FLASH_AREA_OFFSET(storage)
	 */
	if (!device_is_ready(flash_dev))
	{
		printk("Flash device %s is not ready\n", flash_dev->name);
		return;
	}
	fs.offset = FLASH_AREA_OFFSET(storage);
	rc_flash = flash_get_page_info_by_offs(flash_dev, fs.offset, &info);
	if (rc_flash)
	{
		printk("Unable to get page info\n");
		return;
	}
	fs.sector_size = info.size;
	fs.sector_count = 3U;

	rc_flash = nvs_init(&fs, flash_dev->name);
	if (rc_flash)
	{
		printk("Flash Init failed\n");
		return;
	}

	/* LONG_ID is used to store a larger dataset ,lets see if we can read
	 * it from flash
	 */
	rc_flash = nvs_read(&fs, USER_DATA_ADDRESS, &user_config_data, sizeof(user_config_data));
	if (rc_flash > 0)
	{
		printk("User data found!\n");
		... do stuff
	}
	else
	{
		/* entry was not found, add it if reboot_counter = 0*/
		printk("User data not found, adding it as id %d\n", USER_DATA_ADDRESS);
	    ... do stuff
	}
}

Below is my flash0 node in my custom board dts file.

&flash0 {

	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		boot_partition: partition@0 {
			label = "mcuboot";
			reg = <0x00000000 0xc000>;
		};
		slot0_partition: partition@c000 {
			label = "image-0";
			reg = <0x0000C000 0x32000>;
		};
		slot1_partition: partition@3e000 {
			label = "image-1";
			reg = <0x0003E000 0x32000>;
		};
		scratch_partition: partition@70000 {
			label = "image-scratch";
			reg = <0x00070000 0xa000>;
		};
		storage_partition: partition@7a000 {
			label = "storage";
			reg = <0x0007a000 0x00006000>;
		};
	};
};

I have a feeling it has something to do with the settings_partition and it eating up my storage NVS offset. I do not know how to fix this though as calculating flash partitions is new to me.

Parents Reply Children
  • So it seems that my issue is due to using MCUBoot in combination with NVS. I understand that the device tree is ignored when using a multi-image build configuration.

    This can be re-created by trying to compile the NVS sample with CONFIG_BOOTLOADER_MCUBOOT=y set. The problem line is below and is because the macro cannot find the storage label which was defined in the device tree (being ignored).

    #define STORAGE_NODE DT_NODE_BY_FIXED_PARTITION_LABEL(storage)
    #define FLASH_NODE DT_MTD_FROM_FIXED_PARTITION(STORAGE_NODE)
    flash_dev = DEVICE_DT_GET(FLASH_NODE);

    Here is the error:

    error: '__device_dts_ord_DT_COMPAT_fixed_partitions_LABEL_nvs_storage_PARENT_PARENT_ORD' undeclared (first use in this function)
       80 | #define DEVICE_NAME_GET(name) _CONCAT(__device_, name)

    I am able to fix the compilation error by adding a pm_static.yml file to the root directory of the NVS sample as described far down in this thread.

    storage:
      address: 0x7a000
      size: 0x6000
      end_address: 0x80000
      placement:
        before: 
        - user_storage
      region: flash_primary
    user_storage:
      address: 0x80000
      size: 0x2000
      end_address: 0x82000
      placement:
        before:
        - end
      region: flash_primary

    However, in a different thread (that I cannot find right now), it is recommended to avoid static configuration. This seems to make sense.

    So in order to prefer the partition manager's output, I have removed the two problems lines (above) and ran a `ninja report` in the build folder. The output is below:

      flash_primary (0x80000 - 512kB): 
    +-------------------------------------------------+
    | 0x0: mcuboot (0xc000 - 48kB)                    |
    +---0xc000: mcuboot_primary (0x37000 - 220kB)-----+
    | 0xc000: mcuboot_pad (0x200 - 512B)              |
    +---0xc200: mcuboot_primary_app (0x36e00 - 219kB)-+
    | 0xc200: app (0x36e00 - 219kB)                   |
    +-------------------------------------------------+
    | 0x43000: mcuboot_secondary (0x37000 - 220kB)    |
    | 0x7a000: nvs_storage (0x6000 - 24kB)            |
    +-------------------------------------------------+
    
      sram_primary (0x10000 - 64kB): 
    +-------------------------------------------+
    | 0x20000000: sram_primary (0x10000 - 64kB) |
    +-------------------------------------------+

    This seems to imply that there is a partition labeled `nvs_storage` that I can use as a FLASH_NODE.

    However, when changing my problem lines to target the partition labeled nvs_storage (as described in the report output) I am still faced with the same compilation error.

    I do not see any documentation on the partition manager page that describes how to actually use it in the multi-image builds. Am I missing something? What is the alternative to defining a static partition?

Related