NVS write succeeds, but read fails intermittently after flash erase on first boot (nRF52840, NCS v2.6.0)

Hi Nordic team,

I'm using nRF52840 with nRF Connect SDK v2.6.0 and using NVS to store RSA key material on flash. The goal is to persistently store a generated RSA key pair and retrieve it across reboots.

Expected Behavior:

  • On first boot after flash erase, the device should:

    • Check for keys in NVS.

    • If not present, generate a new RSA key pair.

    • Store private/public keys and a hash using nvs_write().

    • Immediately read back for verification.

    • On subsequent boots, it should skip key generation.

Actual Behavior:

  • RSA keys are written successfully (confirmed via return values and log).

  • But after reboot, nvs_read() fails with return code -2 (ENODATA).

  • This happens intermittently during the first 1–2 boots after flashing, then stabilizes.

  • Once stable, NVS consistently returns the stored values across resets.

Setup:

  • MCU: nRF52840

  • SDK: nRF Connect SDK v2.6.0

  • Storage: NVS (2 sectors, 4 KB each)

Key Definitions:

#define OTP_NVS_ID_PRIVATE_KEY_LEN 0x0300
#define OTP_NVS_ID_PRIVATE_KEY 0x0301
#define OTP_NVS_ID_PUBLIC_KEY 0x0302
#define OTP_NVS_ID_PUBLIC_KEY_HASH 0x0303
#define OTP_NVS_ID_DEVICE_HUID 0x0304

Changing the ID range from 0x0100 to 0x0300 reduced the frequency of this issue but did not eliminate it.

Relevant Flow (simplified):

bt_enable(NULL); // BLE enabled
zb_remote_nvs_init(); // Mounts NVS
if (!is_private_key_present_in_otp())
{ RSA2048_Generator(); // Generates & writes to NVS }
else
{ printk("RSA key already exists\n"); }

Questions:

  1. Why does nvs_read() intermittently fail with -2 after a successful write + reboot?

  2. Is there a timing/sync issue after nvs_write() in NCS v2.6.0?

  3. Is fs_sync() necessary in this version, and how should it be used if fs.storage isn't available?

  4. Could BLE or other subsystems interfere with flash if initialized before/after NVS?

  5. Are NVS ID ranges like 0x0100 or 0x0300 sensitive or reserved internally?

What I’ve Tried:

  • Changing NVS ID range from 0x0100 to 0x0300: reduces issue but doesn't solve it.

  • Adding k_sleep(K_MSEC(200)) after write.

Any guidance on ensuring reliable write-read behavior on first boot would be very appreciated.

Let me know if I should share minimal reproducible code or boot logs.

Thanks!

Parents
  • Hi Sai Varma,

    If I understand correctly what you mean by nvs_read intermittently fails after write and reboot is that after couple of reboots the nvs_read succeeds sometimes? If that is the case, then the nvs_write was successful and there is some issue with the read sometimes.

    Is it possible for you to provide me a minimalistic project on nRF52840DK so that I can try to understand the issue better?

  • Hi Susheel Nuguru,

    Thank you for your response.

    We have observed that there's only one storage partition being used in our project, and it's currently being shared by BLE (settings) and Zigbee. We suspect this overlap might be contributing to the intermittent nvs_read() failures, especially during the early boots after flash erase.

    Additionally, in our code, we are calling bt_enable(NULL) before initializing our storage (i.e., before mounting the nvs_fs). While debugging, we also noticed in the NCS source code that the Bluetooth stack might also be using the same storage partition internally (possibly via the settings subsystem). This could lead to conflicts or data races when multiple components access the same flash region.

    Follow-up Questions:

    1. Is there a recommended way to create a dedicated/custom storage partition specifically for application data, separate from the one used by BLE/Zigbee settings?

    2. Are there known conflicts or best practices when multiple subsystems (like BLE and Zigbee) share the same storage partition?

    3. If partitioning is not an option, are there any other known resolutions or sync strategies to ensure data stability across boots?

    4. If we need to create a static (custom) storage partition, could you please provide the correct steps to define and use it properly (e.g., using partitions.yml, nvs_fs, dts, etc.)?

    We’re using the nRF52840 with NCS v2.6.0, and appreciate any guidance on how to resolve this storage overlap cleanly.

    Thanks again for your support.

    Best regards,
    Sai Varma

Reply
  • Hi Susheel Nuguru,

    Thank you for your response.

    We have observed that there's only one storage partition being used in our project, and it's currently being shared by BLE (settings) and Zigbee. We suspect this overlap might be contributing to the intermittent nvs_read() failures, especially during the early boots after flash erase.

    Additionally, in our code, we are calling bt_enable(NULL) before initializing our storage (i.e., before mounting the nvs_fs). While debugging, we also noticed in the NCS source code that the Bluetooth stack might also be using the same storage partition internally (possibly via the settings subsystem). This could lead to conflicts or data races when multiple components access the same flash region.

    Follow-up Questions:

    1. Is there a recommended way to create a dedicated/custom storage partition specifically for application data, separate from the one used by BLE/Zigbee settings?

    2. Are there known conflicts or best practices when multiple subsystems (like BLE and Zigbee) share the same storage partition?

    3. If partitioning is not an option, are there any other known resolutions or sync strategies to ensure data stability across boots?

    4. If we need to create a static (custom) storage partition, could you please provide the correct steps to define and use it properly (e.g., using partitions.yml, nvs_fs, dts, etc.)?

    We’re using the nRF52840 with NCS v2.6.0, and appreciate any guidance on how to resolve this storage overlap cleanly.

    Thanks again for your support.

    Best regards,
    Sai Varma

Children
Related