Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dsyx/docs.silabs.com_zh/llms.txt

Use this file to discover all available pages before exploring further.

NVM3(Third Generation Non-Volatile Memory)驱动程序提供了一种读写存储在闪存中的数据对象(Key/Value Pair)的方法。磨损均衡用于减少擦写周期并最大化闪存寿命。该驱动程序对断电和重启事件具有弹性,确保从驱动程序检索的对象始终处于有效状态。单个 NVM3 实例可以在多个无线协议栈和应用程序代码之间共享,非常适合多协议应用程序。

NVM3 核心特性

Key/Value Pair 存储

使用 20-bit Key 标识每个数据对象,支持数据对象(最大 4096 字节)和计数器对象两种类型。

磨损均衡

通过循环缓冲区(Circular Buffer)实现磨损均衡,均匀分散闪存写入,最大化闪存寿命。

断电弹性

对断电和复位事件具有弹性,保证从驱动程序检索的对象始终处于有效状态。

多协议共享

支持在 Bluetooth、Zigbee、OpenThread、Connect、Z-Wave 等协议栈间共享单一 NVM3 实例。

完整特性列表

  • 在闪存中使用 Key/Value Pair 数据存储
  • 运行时创建和删除对象
  • 在断电和复位事件间持久化
  • 磨损均衡以最大化闪存寿命
  • 对象大小最多可配置为 4096 字节
  • 可配置闪存存储大小(最少 3 个闪存页
  • 具有可配置大小的 Cache,用于加速对象访问
  • 数据和计数器两种对象类型
  • 包括多个 Silicon Labs 持久化存储 API 的兼容性层(Token API、Bluetooth NVM API)
  • 在多协议应用程序中实现单个共享存储实例
  • 重新封装(Repack)API,允许应用程序在 CPU 负载较低的时段运行待清除页的擦除

NVM3 默认实例

在一个设备上可以创建多个 NVM3 实例,但为节省存储开销,基于 Silicon Labs 无线栈的应用程序通常使用一个通用默认实例。这允许 DMP(Dynamic Multiprotocol)应用程序将多个无线栈组合在一起共享同一 NVM3 实例。
当为已包含 NVM3 实例的设备创建新应用程序时,为 NVM3 实例配置的闪存页数量必须与设备上已有的 NVM3 实例的页数量匹配。一旦将 NVM3 实例安装到设备上,如不先擦除持有 NVM3 实例的闪存页,就无法更改其大小。

NVM3 Cache 配置

NVM3 具有 Cache 以加快对象访问。Cache 大小必须设置为大于或等于在 NVM3 中存储的对象数量(包括存活对象和已删除对象)。可使用 nvm3_countObjects() 函数查找 NVM3 中的存活对象和已删除对象数量,在所有 NVM3 对象初始化完成后检查此函数,以确定合适的缓存大小。

NVM3 默认实例 Key Space

NVM3 使用 20-bit Key 标识每个对象。为避免 Key 冲突,默认 NVM3 实例的 Key Space 按域划分:
DomainNVM3 Key 范围
User0x00000 - 0x0FFFF
Zigbee EmberZNet stack0x10000 - 0x1FFFF
OpenThread stack0x20000 - 0x2FFFF
Connect stack0x30000 - 0x3FFFF
Bluetooth stack0x40000 - 0x4FFFF
Z-Wave stack0x50000 - 0x5FFFF
Bluetooth mesh stack0x60000 - 0x6FFFF
Reserved0x70000 - 0x7FFFF
Apple HomeKit0x80000 - 0x80FFF
Zigbee Cluster Library (ZCL)0x81000 - 0x81FFF
dotdot0x82000 - 0x82FFF
Platform CLI SM0x83000 - 0x830FF
Platform Crypto0x83100 - 0x870FF
Bootloader0x87100 - 0x871FF
Matter0x87200 - 0x87FFF
Reserved0x88000 - 0x8FFFF
Wi-SUN0x90000 - 0x9FFFF
Reserved0xA0000 - 0xFFFFF
用户自定义的 NVM3 对象应放置在 0x10000 以下(User 域:0x00000 - 0x0FFFF)。

在 Simplicity Studio 5 中配置 NVM3

在 Project Configurator 的 Software Components 视图中,安装 NVM3 CoreNVM3 Default Instance 组件。 NVM3 Default Instance 组件提供以下配置项:
配置项说明
Cache Size要缓存的对象数量,应 ≥ 任意时刻 NVM3 中存活和已删除对象总数
Max Object Size允许的最大 NVM3 对象大小(字节),必须介于 208 ~ 4096 字节
User Repack Headroom用户重打包限制低于强制重打包限制的字节余量,默认为 0
Default Instance Size闪存中 NVM3 存储区域大小,必须为整数个闪存页,最少 3 页
若项目中包含 System Init 组件,默认实例将在 sl_system_init() 期间自动初始化。

各协议栈中使用 NVM3

默认情况下,GSDK 中所有 Zigbee 示例应用程序均配置为使用 NVM3。这些应用程序:
  • 利用通用的默认 NVM3 实例
  • 在项目中包含 NVM3 CoreNVM3 Default Instance 组件
  • 使用 Native NVM3 API 访问 NVM3 对象
  • Zigbee 栈使用的 NVM3 Key Space:0x10000 - 0x1FFFF
若有以旧版 SimEE 格式存储的数据需要保留,可使用 Token Manager 组件辅助管理数据存储和迁移。

NVM3 API 使用

NVM3 提供三种 API 层,可根据需求选择:
用于通过 EmberZNet 和 Connect 栈访问 NVM3 数据,与 SimEE 的 Token API 兼容。定义与 NVM3 和 SimEE 都兼容的 Token(同时包含 NVM3 Key 和 Creator Code):
// Token 定义示例(同时兼容 NVM3 和 SimEE)
#define CREATOR_MY_TOKEN    0x1234          // 16-bit Creator Code(SimEE 用)
#define NVM3KEY_MY_TOKEN    0x00001         // 20-bit NVM3 Key(NVM3 用)

#ifdef DEFINETYPES
  typedef uint32_t my_token_type;
#endif

#ifdef DEFINETOKENS
  DEFINE_BASIC_TOKEN(MY_TOKEN, my_token_type, 0xFFFFFFFF)
#endif
Indexed Token 的特殊要求:NVM3 不支持 Indexed Token 的 Native 支持,每个索引存储在单独的对象中,需为每个 Indexed Token 保留 128 个连续 NVM3 Key
// Indexed Token 的 Key 分配示例(在 User Key Domain 中)
// 此 Key 用于 Indexed Token,随后的 0x7F 个 Key 也被保留
#define NVM3KEY_MY_INDEXED_TOKEN_A 0x00000
// 此 Key 用于 Indexed Token,随后的 0x7F 个 Key 也被保留
#define NVM3KEY_MY_INDEXED_TOKEN_B 0x00080
最初为 PS Store 设计,在 NVM3 和 PS Store 下以相同方式使用。Bluetooth 栈自动将 API 调用转换为对应的存储实现。Bluetooth NVM API 使用 16-bit Key,映射到 20-bit NVM3 Key 时,高 4 位设置为 0x4,放入 Bluetooth Domain(0x40000 - 0x4FFFF)。以下 API 调用效果相同(写入相同存储区域):
// 方法一:Native NVM3 API
nvm3_writeData(nvm3_defaultHandle, 0x44000, (void*)data, len);

// 方法二:Bluetooth SDK v2.x API(Flash 分类)
gecko_cmd_flash_ps_save(0x4000, len, data);

// 方法三:Bluetooth SDK v3.x API(NVM 分类)
sl_bt_nvm_save(0x4000, len, data);
同样地,读取相同数据的 API 调用:
// 方法一:Native NVM3 API
nvm3_readData(nvm3_defaultHandle, 0x44000, (void*)read_buffer, maxlen);

// 方法二:Bluetooth SDK v2.x
gecko_cmd_flash_ps_load(0x4000);

// 方法三:Bluetooth SDK v3.x
sl_bt_nvm_load(0x4000, maxlen, &read_len, (uint8_t*)read_buffer);
如果在同一应用中同时使用 Bluetooth NVM API 和 Native NVM3 API,需先初始化 Bluetooth 栈,再打开 NVM3 默认实例:
// 初始化 Bluetooth 栈(打开其 NVM3 实例)
gecko_init(pconfig);

// 打开 NVM3 默认实例
nvm3_open(nvm3_defaultHandle, nvm3_defaultInit);
对于不需要与 Token 或 PS Store API 兼容的代码,推荐使用 Native NVM3 API,可减少代码大小并利用 NVM3 的全部特性。写入数据对象
#include "nvm3_default.h"

#define MY_KEY  0x00001  // 在 User Domain 中定义 Key

// 写入数据
uint32_t myData = 42;
Ecode_t status = nvm3_writeData(nvm3_defaultHandle,
                                MY_KEY,
                                &myData,
                                sizeof(myData));
if (status != ECODE_NVM3_OK) {
    // 处理写入错误
}
读取数据对象
uint32_t myData = 0;
uint32_t dataLen;
Ecode_t status;

// 获取对象类型和长度
uint32_t objectType;
status = nvm3_getObjectInfo(nvm3_defaultHandle, MY_KEY,
                            &objectType, &dataLen);

if (status == ECODE_NVM3_OK && objectType == NVM3_OBJECTTYPE_DATA) {
    // 读取数据
    status = nvm3_readData(nvm3_defaultHandle,
                           MY_KEY,
                           &myData,
                           sizeof(myData));
}
删除对象
Ecode_t status = nvm3_deleteObject(nvm3_defaultHandle, MY_KEY);
计数器对象操作
#define COUNTER_KEY  0x00002

// 初始化计数器
nvm3_writeCounter(nvm3_defaultHandle, COUNTER_KEY, 0);

// 递增计数器(高效,无需读取-修改-写入)
nvm3_incrementCounter(nvm3_defaultHandle, COUNTER_KEY, NULL);

// 读取计数器值
uint32_t counterValue;
nvm3_readCounter(nvm3_defaultHandle, COUNTER_KEY, &counterValue);
手动触发重打包(Repack)
// 检查是否需要重打包
if (nvm3_repackNeeded(nvm3_defaultHandle)) {
    // 在 CPU 负载较低时执行重打包
    nvm3_repack(nvm3_defaultHandle);
}

在 AppBuilder 应用中使用 NVM3

对于基于 AppBuilder 的应用程序(EmberZNet 6.10.x 及更低版本等),需在 AppBuilder 中添加相关插件:
1

添加 NVM3 Library 插件

在 AppBuilder 中选中 NVM3 Library 插件,并取消所有 PS Store 和 SimEE 插件的选中状态。配置插件选项:
  • Flash Pages:NVM3 存储的闪存页数(≥3),Series 1 默认 18 页,Series 2 默认 4 页
  • Cache Size:缓存对象数量
  • Max Object Size:最大对象大小(208 ~ 4096 字节)
  • User Repack Headroom:用户重打包余量,默认 0
2

添加升级插件

同时必须包含以下插件之一:
  • Simulated EEPROM version 2 to NVM3 Upgrade Library:若需要将现有 SimEEv2 Token 升级到 NVM3
  • Simulated EEPROM version 2 to NVM3 Upgrade Stub Library:若无需迁移 SimEEv2 数据

使用 Simplicity Commander 操作 NVM3

Simplicity Commander 支持从设备读取 NVM3 数据区域并解析 NVM3 数据,在调试场景中非常有用:
# 从设备读取 NVM3 数据并解析
commander nvm3 read --device EFR32MG21A010F1024 --serialno 440048205

# 打印 NVM3 存储内容
commander nvm3 print --help
详细命令参考 UG162: Simplicity Commander Reference Guide
在所有 NVM3 对象初始化完成后,使用 nvm3_countObjects() 函数检查存活对象和已删除对象数量,以确定 NVM3 默认 Cache 的合适大小,避免因 Cache 过小导致性能下降。

Build docs developers (and LLMs) love