efuse 驱动
概述
efuse(Electrically Fusable)电熔丝是一种一次可编程存储器,用于存储芯片的唯一标识、配置参数、密钥等关键信息。BK7239N 内置 efuse 存储器,提供安全可靠的数据存储解决方案。
功能描述
一次可编程:efuse 只能从 0 编程为 1,不能从 1 变为 0
永久存储:数据一旦写入,永久保存,断电不丢失
安全存储:适合存储密钥、证书等敏感信息
唯一标识:支持芯片唯一标识存储
配置参数:支持系统配置参数存储
地址管理:支持灵活的地址空间管理
数据验证:支持写入数据验证
低功耗:支持低功耗模式下的数据保持
开发指引
初始化流程 - 调用 bk_efuse_driver_init() 初始化 efuse 驱动 - 确认要写入的地址区域可用 - 准备要写入的数据
基本使用 - 使用 bk_efuse_write_byte() 写入单字节数据 - 使用 bk_efuse_read_byte() 读取单字节数据 - 注意 efuse 只能从 0 编程为 1
地址管理 - 确认地址范围在有效范围内 - 避免重复写入同一地址 - 注意地址区域的用途限制
数据验证 - 写入后立即读取验证 - 检查数据是否正确写入 - 处理写入失败的情况
注意事项
确保在调用其他 efuse API 前先调用 bk_efuse_driver_init()
efuse 只能从 0 编程为 1,不能从 1 变为 0
写入操作不可逆,请谨慎操作
地址范围需要确认在有效范围内
写入前需要向 PM 申请地址区域
注意 efuse 的寿命限制
API 说明
主要 API 函数:
bk_efuse_driver_init() - 初始化 efuse 驱动
bk_efuse_driver_deinit() - 反初始化 efuse 驱动
bk_efuse_write_byte() - 写入单字节数据
bk_efuse_read_byte() - 读取单字节数据
示例代码
基本使用示例:
#include <driver/efuse.h>
void efuse_example(void)
{
// 初始化 efuse 驱动
bk_efuse_driver_init();
// 写入数据到 efuse
uint8_t write_data = 0xAA;
bk_err_t ret = bk_efuse_write_byte(0x10, write_data);
if (ret != BK_OK) {
printf("efuse write failed: %d\n", ret);
return;
}
// 读取数据验证
uint8_t read_data;
ret = bk_efuse_read_byte(0x10, &read_data);
if (ret == BK_OK) {
printf("efuse read: 0x%02X\n", read_data);
}
}
批量读写示例:
void efuse_batch_example(void)
{
uint8_t write_data[] = {0x01, 0x02, 0x03, 0x04};
uint8_t read_data[4];
// 批量写入
for (int i = 0; i < 4; i++) {
bk_err_t ret = bk_efuse_write_byte(0x20 + i, write_data[i]);
if (ret != BK_OK) {
printf("Write failed at address 0x%02X\n", 0x20 + i);
return;
}
}
// 批量读取验证
for (int i = 0; i < 4; i++) {
bk_err_t ret = bk_efuse_read_byte(0x20 + i, &read_data[i]);
if (ret == BK_OK) {
printf("Address 0x%02X: 0x%02X\n", 0x20 + i, read_data[i]);
}
}
}
安全存储示例:
void efuse_secure_storage_example(void)
{
// 存储密钥
uint8_t key[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
uint8_t key_addr = 0x30;
// 写入密钥
for (int i = 0; i < 8; i++) {
bk_err_t ret = bk_efuse_write_byte(key_addr + i, key[i]);
if (ret != BK_OK) {
printf("Key write failed at index %d\n", i);
return;
}
}
// 验证密钥
uint8_t verify_key[8];
for (int i = 0; i < 8; i++) {
bk_efuse_read_byte(key_addr + i, &verify_key[i]);
}
// 比较密钥
bool key_match = true;
for (int i = 0; i < 8; i++) {
if (key[i] != verify_key[i]) {
key_match = false;
break;
}
}
printf("Key verification: %s\n", key_match ? "PASS" : "FAIL");
}
配置参数存储示例:
void efuse_config_example(void)
{
// 存储配置参数
struct {
uint8_t device_id;
uint8_t version;
uint8_t features;
uint8_t reserved;
} config = {
.device_id = 0x01,
.version = 0x02,
.features = 0x03,
.reserved = 0x00
};
uint8_t config_addr = 0x40;
// 写入配置
bk_efuse_write_byte(config_addr, config.device_id);
bk_efuse_write_byte(config_addr + 1, config.version);
bk_efuse_write_byte(config_addr + 2, config.features);
bk_efuse_write_byte(config_addr + 3, config.reserved);
// 读取配置
uint8_t read_config[4];
for (int i = 0; i < 4; i++) {
bk_efuse_read_byte(config_addr + i, &read_config[i]);
}
printf("Device ID: 0x%02X\n", read_config[0]);
printf("Version: 0x%02X\n", read_config[1]);
printf("Features: 0x%02X\n", read_config[2]);
}
常见问题
写入失败:检查地址范围、数据格式、efuse 状态
读取错误:确认地址有效性、驱动初始化状态
数据不匹配:检查写入操作是否成功、地址是否正确
地址冲突:确认地址区域使用情况、避免重复写入
实战示例
存储芯片唯一标识
void efuse_chip_id_example(void)
{
uint8_t chip_id[4] = {0x12, 0x34, 0x56, 0x78};
uint8_t id_addr = 0x00;
// 写入芯片ID
for (int i = 0; i < 4; i++) {
bk_efuse_write_byte(id_addr + i, chip_id[i]);
}
// 读取验证
uint8_t read_id[4];
for (int i = 0; i < 4; i++) {
bk_efuse_read_byte(id_addr + i, &read_id[i]);
}
}
常见错误码说明
BK_ERR_EFUSE_DRIVER_NOT_INIT:未调用 bk_efuse_driver_init()
BK_ERR_EFUSE_ADDR_OUT_OF_RANGE:efuse 地址超出范围
BK_ERR_EFUSE_CANNOT_WRTIE:efuse 无法写入,不能将位从 1 变为 0
BK_ERR_EFUSE_WRTIE_NOT_EQUAL:efuse 读取数据与写入数据不相等