How to determine if flash write has completed using zms_write() or nvs_write()

NCS 3.02 + nRF54L15

I'm troubleshooting a potential bug. Are these blocking routines, or if not how do I monitor for successful completion of flash write? I looked the the API docs and the ZMS sample project but neither give any clue.

My concern is if the system is rebooted too soon after saving might result in corruption.

Thanks

  • The APIs are blocking. Other threads and interrupt routines might run while the operation is ongoing though.

    I wouldn't use ZMS at this stage though since I wouldn't call the code stable/bug-free yet. I found many bugs when I inspected the code some time ago, see e.g. https://github.com/zephyrproject-rtos/zephyr/issues/88373 and https://github.com/zephyrproject-rtos/zephyr/pull/87809#issuecomment-2787666716. There are still bugs remaining that have not been fixed.

  • I wouldn't use ZMS at this stage though since I wouldn't call the code stable/bug-free yet.

    Is this official Nordic advice? According to another ticket that ZMS is the way to go for nRF54L.

    nRF54L requires the ZMS backend while all others use NVS.
  • No, this is my own advice after thoroughly reading the code of ZMS and inspecting its quality, and finding many bugs. I wouldn't use it in its current state since the storage can become corrupt. I found issues where corruptions could be possible with power cuts as well as even without power cuts.

    Since data integrity is pretty vital, I'm a bit surprised that no one has fixed the issues I reported as of now.

  • There's definitely something wacky going on when I use zms_write().

    This is my snip of code to do the save:

    	struct zms_fs fs;
    	struct flash_pages_info info;
    	fs.flash_device = ZMS_PARTITION_DEVICE;
    	if (!device_is_ready(fs.flash_device)) {
    		printk("Storage device %s is not ready\n", fs.flash_device->name);
    		return 0;
    	}
    	fs.offset = ZMS_PARTITION_OFFSET;
    	rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info);
    	if (rc) {
    		printk("Unable to get page info, rc=%d\n", rc);
    		return 0;
    	}
    	fs.sector_size = info.size;
    	fs.sector_count = 3U;
    	rc = zms_mount(&fs);
    	if (rc) {
    		printk("Flash Init failed, rc=%d\n", rc);
    		return rc;
    	}
    	rc = zms_write(&fs, NVS_SETTINGS_ADDR, &nv_settings, sizeof(nv_settings));
    	if (rc == sizeof(nv_settings))
    	{
    		printk("Settings saved" CRLF);
    	}
    	else
    	{
    		printk("Error saving settings" CRLF);
    	}
    	return rc;

    (nv_settings is a struct)

    And this is an example of the debug log when it goes wrong

    [00:01:40.674,492] <inf> fs_zms: 3 Sectors of 4096 bytes
    [00:01:40.674,514] <inf> fs_zms: alloc wra: 0, ed0
    [00:01:40.674,523] <inf> fs_zms: data wra: 0, 410
    Settings saved
    [00:01:47.214,505] <wrn> app: Not able to allocate UART receive buffer
    [00:01:47.264,545] <wrn> app: Not able to allocate UART receive buffer

    The uart handling is basically a copy of the sample project lp_uart. I have a command to print a menu of the settings (so lots of printing) which I can run repeatedly, but I can make this crash after multiple (14 last time I tried it) saves.

    I don't think this is a UART issue, because I can make the system do the same thing by command sent via BLE.

    Note there is no kernel panic, reboot etc happening. Just as you see it in the log.

  • Emil Lenngren said:
    I wouldn't use ZMS at this stage though since I wouldn't call the code stable/bug-free yet.

    As written in nrf/doc/nrf/app_dev/data_storage.rst, Nordic´s official stance is

    The :ref:`Zephyr Memory Storage (ZMS) <zephyr:zms_api>` is the recommended storage solution for the nRF54L and nRF54H Series.
    ZMS uses a flexible data management system that reduces write and erase cycles, extending the lifespan of non-volatile memory.
    ZMS stores data as values identified by a 32-bit integer ID.

    and as shown in nrf/doc/nrf/app_dev/device_guides/nrf54l/zms.rst

    For the nRF54L and nRF54H Series, use the :ref:`Zephyr Memory Storage (ZMS) <zephyr:zms_api>`.
    ZMS utilizes a flexible data management system that reduces write and erase cycles, extending the lifespan of non-volatile memory.

    For trusted storage as written in nrf/doc/nrf/libraries/security/trusted_storage.rst

        ZMS is the only allowed storage option for nRF54L Series devices, while other devices using the trusted storage library can choose between the two options.

    Now regarding the issue you are seeing with ZMS, There seems to be one unhandled bug that Emil has already linked to, which seems a bit related to the memory leak kind of issue you are seeing. Lots of other systems in our solutions are using ZMS, but since you have hit this one where there does not seem to a fix yet, maybe you can try using NVS. But you wont be able to use some trusted_storage libraries as ZMS is the only backend supported for nRF54L devices for those libraries.

Related