非易失性存储器(NVMEM)

NVMEM 子系统为访问非易失性存储设备提供通用接口。它抽象底层硬件,并提供用于读写数据的统一 API。

关键概念

NVMEM 提供者

NVMEM 提供者是公开 NVMEM 单元的驱动。例如,EEPROM 驱动可以是 NVMEM 提供者。NVMEM 提供者负责向底层硬件读写数据。

NVMEM 单元

NVMEM 单元是非易失性存储器的区域。它在 devicetree 中定义,并具有偏移量、大小和只读状态等属性。

NVMEM 使用者

NVMEM 使用者是使用 NVMEM 单元存储或检索数据的驱动或应用。

配置

Devicetree 绑定

NVMEM 子系统依赖 devicetree 绑定来定义 NVMEM 单元。以下是在 devicetree 中定义 NVMEM 提供者和单元的示例:

&eeprom0 {
	nvmem-layout {
		compatible = "fixed-layout";
		#address-cells = <1>;
		#size-cells = <1>;

		mac_address: mac_address@0 {
			reg = <0x0 6>;
			#nvmem-cell-cells = <0>;
			read-only;
		};

		calibration_data: calibration_data@6 {
			reg = <0x6 100>;
			#nvmem-cell-cells = <0>;
		};
	};
};

reg 属性是一个数组,包含:

  • 在其中创建单元的内存偏移量,

  • 单元的大小(以字节为单位)。

#nvmem-cell-cells 描述 phandle 中属性项的数量,参见 Specifier cell names (*-cells),通常设置为零。

然后,使用者可以像这样引用 NVMEM 单元:

my_consumer: my-consumer {
	compatible = "my,consumer";
	nvmem-cells = <&mac_address>, <&calibration_data>;
	nvmem-cell-names = "mac-address", "calibration-data";
};

用法示例

以下示例展示如何使用 NVMEM API 从 NVMEM 单元读取数据:

#include <zephyr/nvmem.h>

static const struct nvmem_cell mac_address =
	NVMEM_CELL_GET_BY_NAME(DT_NODELABEL(my_consumer), mac_address);

int main(void)
{
	uint8_t mac[6];
	int ret;

	if (!nvmem_cell_is_ready(&mac_address)) {
		printk("NVMEM cell is not ready\n");
		return -ENODEV;
	}

	ret = nvmem_cell_read(&mac_address, mac, 0, sizeof(mac));
	if (ret < 0) {
		printk("Failed to read MAC address: %d\n", ret);
		return ret;
	}

	/* ... */
}

API 参考

NVMEM