OTP 存储控制器(OTPC)

概述

OTP 存储控制器(One-Time Programmable Controller)是一种基于反熔丝结构的嵌入式非易失性存储器,具备极高的安全性和数据不可更改性。其存储单元默认值为 1,仅支持一次性、不可逆地改写为 0。

OTP 布局

OTP 的布局如下图所示:

备注

关于 OTP 各分区的详细布局,参考相应的 User Manual 文档。

物理区域

物理区域的大小 0x800 字节。其布局已经被 Realtek 预先定义,包括映射区域、安全区域、User-defined 物理区域、ROM code patch 区域、隐藏物理区域。

小心

物理区域仅支持一次性、不可逆地从 1 改写为 0,请谨慎操作。

物理区域分区

地址

描述

使用方法

映射区域

(0x000-0x1FF, 512 字节)

映射到逻辑区域

-

安全区域

(0x200-0x37F, 384 字节)

保存各类密钥和相关配置

安全区域使用方法

User-defined 物理区域

(0x380-0x4FF, 384 字节)

用户自由使用

User-defined 物理区域使用方法

ROM code patch 区域

(0x500-0x6FF, 512 字节)

用于在 ROM 中加入补丁

ROM code patch 区域使用方法

隐藏物理区域

(0x700-0x7FF, 256字节)

用于 RMA 等功能

隐藏物理区域使用方法

逻辑区域

逻辑区域的大小为 0x400 字节。逻辑区域的值允许被多次修改。 逻辑区域由物理区域的映射区域(0x000 ~ 0x1FF, 512 字节)经 Realtek 定义的关系映射而来,映射关系如下图所示:

../../../_images/otp_mapping_logic.svg

逻辑区域的每块数据都要占用映射区域的一个帧,硬件会顺序扫描映射区域各个帧的内容,将数据映射到逻辑区域。当多个帧映射到逻辑区域的同一个地址的时候,硬件会采用最后一个帧的数据,这使得逻辑区域可以被多次修改。

备注

  • 逻辑区域和映射区域的详细映射关系,参考相应的 User Manual 文档。

  • 每次修改逻辑区域的值,都要占用映射区域的一个帧,因此当映射区域被写满,逻辑区域将无法再被修改。

逻辑区域布局已经被 Realtek 预先定义,包括系统数据区域、User-defined MTP 区域、校准区域等。

逻辑区域分区

地址

描述

使用方法

系统数据区域

(0x000-0x01F, 32 字节)

存放系统数据

系统数据使用方法

Wi-Fi Calibration 区域

(0x020-0x13F, 288 字节)

保存 Wi-Fi 校准数据。

Realtek使用

HCI-USB

(0x150-0x15F, 16 字节)

存放 USB 设备相关的配置数据。

Realtek使用

Cap-Touch Calibration 区域

(0x160-0x16F, 16 字节)

存放 Cap-Touch 校准数据。

Realtek使用

User-defined MTP 区域

(0x170-0x19F, 48 字节)

用户自由使用。

User-defined MTP 区域使用方法

BT parameters 区域

(0x1B0-0x1FF, 80 字节)

存放 BT 的参数。

Realtek使用

OTP API 参考

OTP API

API

描述

操作区域

OTP_Read8

读取 OTP 物理区域单个字节

物理区域

OTP_Read32

读取 OTP 物理区域 4 个字节

物理区域

OTP_Write8

写入 OTP 物理区域单个字节

物理区域

OTP_LogicalMap_Read

按长度读取 OTP 逻辑映射区域

逻辑区域

OTP_LogicalMap_Write

按长度写入 OTP 逻辑映射区域地址

逻辑区域

otp_logical_remain

获取逻辑映射区域中 OTP 剩余可用长度

逻辑区域

OTPSetCRC

设置安全区域的 CRC 校验值

物理区域

OTP_Read8

项目

描述

功能

读取 OTP 物理区域单个字节

参数

  • Addr:待读取的 OTP 物理区域地址

  • Data:OTP 数据读取缓冲区(1 字节)

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

OTP_Read32

项目

描述

功能

读取 OTP 物理区域 4 字节

参数

  • Addr:待读取的 OTP 物理区域地址

  • Data:OTP 数据读取缓冲区(4 字节)

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

OTP_Write8

项目

描述

功能

写入 OTP 物理区域单个字节

参数

  • Addr:待写入的 OTP 物理区域地址

  • Data:待写入的 1 字节数据

返回值

写操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

OTP_LogicalMap_Read

项目

描述

功能

按长度读取 OTP 逻辑映射区域

参数

  • pbuf:OTP 逻辑映射区域使用的缓冲区

  • addr:待读取的 OTP 逻辑映射区域起始地址

  • len:待读取的 OTP 逻辑映射区域字节长度

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

OTP_LogicalMap_Write

项目

描述

功能

按长度写入 OTP 逻辑映射区域地址

参数

  • addr:待写入的 OTP 逻辑映射区域起始地址

  • cnts:待写入的 OTP 逻辑映射区域字节长度

  • data:待写入的数据

返回值

写操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

otp_logical_remain

项目

描述

功能

获取逻辑映射区域中 OTP 剩余可用长度

参数

返回值

剩余可用长度

OTPSetCRC

项目

描述

功能

设置安全区域的 CRC 校验值

参数

返回值

操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

OTP API 使用方法

逻辑区域

将逻辑地址 0x02[1] 的值编程为 1,按以下步骤操作:

  1. 读取逻辑地址 0x02 的原始值,并检查函数返回值。

    u8 data_read;
    int ret;
    ret = OTP_LogicalMap_Read(&data_read, 2, 1);
    
  2. 假设步骤 1 中读取的逻辑地址 0x02 数据为 0xA0。将 0xA0 与目标位 0x02[1] 的值进行或操作,其余数据保持默认值。所以新写入的值为 0xA2

  3. 写入新值 0xA2 到逻辑地址 0x02,并检查函数返回值。

    u8 data_written = 0xA2;
    int ret;
    ret = OTP_LogicalMap_Write(2, 1, &data_written);
    

备注

编程系统数据区域时,如果是第一次编程某个字节,该字节要做特殊处理。参考 系统数据区域

物理区域

将物理地址 0x02[1] 的值编程为 0,按以下步骤操作:

  1. 读取物理地址 0x02 的原始值, 并检查返回值。

    u8 data_read;
    int ret;
    ret = OTP_Read8(0x2, &data_read);
    
  2. 假设步骤 1 中读取的物理地址 0x02 数据为 0xAF。将 0xAF 与目标位 0x02[1] 的值进行与操作,其余数据保持默认值。所以新写入的值为 0xAD

  3. 写入新值 0xAD 到物理地址 0x02,并检查返回值。

    u8 data_written = 0xAD;
    int ret;
    ret = OTP_Write8(0x2, data_written);
    

OTP 串口编程

可通过串口对 OTP 的物理区域和逻辑区域编程。

逻辑区域

通过以下命令可以对逻辑区域进行读写操作。

操作

命令

描述

AT+OTP=RMAP

读取整个逻辑区域

AT+OTP=WMAP,<address>,<length>,<data>

写入到逻辑区域的指定地址

  • address:待写入的起始逻辑地址(十六进制)

  • length: 待写入数据的字节数(十六进制)

  • data:待写入的数据(十六进制)

备注

待写入数据的字符串长度必须为偶数,且不能带前缀 0x

将逻辑地址 0x02[1] 的值编程为 1,按以下步骤操作:

  1. 读取逻辑映射,检查逻辑地址 0x02 的原始值。

AT+OTP=RMAP

EFUSE[000]: ff ff a0 ff ff ff ff ff ff ff ff ff ff ff ff ff
EFUSE[010]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
EFUSE[020]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
EFUSE[030]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
...
  1. 假设步骤 1 中读取的逻辑地址 0x02 数据为 0xA0。将 0xA0 与目标位 0x02[1] 的值进行或操作,其余数据保持默认值。所以新写入的值为 0xA2

  2. 写入新值 0xA2 到逻辑地址 0x02。

AT+OTP=WMAP,0x2,0x1,A2
[ATCMD_OTP-I] efuse wmap write len:1, string len:2
  1. 再次读取数据以验证写入是否成功。

AT+OTP=RMAP

EFUSE[000]: ff ff a2 ff ff ff ff ff ff ff ff ff ff ff ff ff
EFUSE[010]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
EFUSE[020]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
EFUSE[030]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
...

备注

编程系统数据区域时,如果是第一次编程某个字节,该字节要做特殊处理。参考 系统数据区域

物理区域

通过以下命令可以对物理区域进行读写操作。

操作

命令

描述

AT+OTP=RRAW

读取整个物理区域

AT+OTP=WRAW,<address>,<length>,<data>

写入到物理区域的指定地址

  • address:待写入的起始物理地址(十六进制)

  • length: 待写入数据的字节数(十六进制)

  • data:待写入的数据(十六进制)

备注

待写入数据的字符串长度必须为偶数,且不能带前缀 0x

将物理地址 0x02[1] 的值编程为 0,按以下步骤操作:

  1. 读取物理映射,检查物理地址 0x02 的原始值。

AT+OTP=RRAW

RawMap[000]: ff ff af ff ff ff ff ff ff ff ff ff ff ff ff ff
RawMap[010]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
RawMap[020]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
RawMap[030]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
...
  1. 假设步骤 1 中读取的物理地址 0x02 数据为 0xAF。将 0xAF 与目标位 0x02[1] 的值进行与操作,其余数据保持默认值。所以新写入的值为 0xAD

  2. 写入新值 0xAD 到物理地址 0x02。

AT+OTP=WRAW,0x2,0x1,AD
[ATCMD_OTP-I] efuse wraw write len:1, string len:2
wraw: 2 ad
  1. 再次读取数据以验证写入是否成功。

AT+OTP=RRAW

RawMap[000]: ff ff ad ff ff ff ff ff ff ff ff ff ff ff ff ff
RawMap[010]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
RawMap[020]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
RawMap[030]: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
...

备注

RF 校准工具会使用 iwpriv 命令来编程 OTP,但不建议其他工具使用该命令对 OTP 编程。

各区域使用方法

逻辑区域

逻辑区域被划分为系统数据,Wi-Fi 校准数据,User-defined MTP 等区域。

系统数据区域

系统数据区域(0x000 ~ 0x01F,32 字节)用于保存系统启动时可能要使用的系统数据。系统数据会在系统启动时由硬件自动加载至系统寄存器,并在系统启动时生效。

备注

系统数据区域和系统寄存器的对应关系,参考相应的 User Manual 文档。

由于历史原因,若系统数据区域的某个字节是第一次编程,对应的系统寄存器会保持初始值 0x00,而非读取逻辑区域返回的 0xFF,因此要对系统数据第一次编程的情况做特殊处理。

备注

当系统数据的某个字节已经被编程非 0xFF 值,然后又被编程为 0xFF,对应的系统寄存器的值会是 0xFF 而不再是初始值 0x00,因此不建议将系统数据区域从非 0xFF 值编程为 0xFF。

系统数据的编程流程如下:

../../../_images/programming_the_system_data.svg

示例

将逻辑地址 0x02[1] 的值编程为 1,按以下步骤操作:

  1. 读取逻辑映射,检查逻辑地址 0x02 的原始值。

    AT+OTP=RMAP
    

    u8 data_read;
    OTP_LogicalMap_Read(&data_read, 2, 1);
    
  2. 根据读到的值决定写入的值。

    • 如果步骤 1 中读取的逻辑地址 0x02 数据为 0xA0,表明 不是第一次编程 此字节。将 0xA0 与目标位 0x02[1] 的值进行或操作,所以新写入的值为 0xA2

      AT+OTP=WMAP,0x2,0x1,A2
      

      u8 data_written = 0xA2;
      OTP_LogicalMap_Write(2, 1, &data_written);
      
    • 如果步骤 1 中读取的逻辑地址 0x02 数据为 0xFF,表明是 第一次编程 此字节。将 0x00 与目标位 0x02[1] 的值进行或操作,所以新写入的值为 0x02

      AT+OTP=WMAP,0x2,0x1,02
      

      u8 data_written = 0x02;
      OTP_LogicalMap_Write(2, 1, &data_written);
      
  3. 再次读取数据以验证写入是否成功。

    AT+OTP=RMAP
    

    u8 data_read;
    OTP_LogicalMap_Read(&data_read, 2, 1);
    
系统数据编程场景

一般来说,系统数据有其初始值,用户可按需修改。

偏移地址

比特位

符号

描述

0x02

[0]

FLASH_DEEPSLEEP_EN

系统进入睡眠模式是否使能 Flash 进入深度睡眠模式

0: 除能

1: 使能

0x02

[1]

SPIC_ADDR_4BYTE_EN

是否使能 SPI Flash 控制器 4-byte 地址模式

0: 除能

1: 使能

0x02

[2]

SPIC_BOOT_SPEEDUP_DIS

是否启动时加速 SPIC 初始化

0: 加速

1: 不加速

0x02

[3]

BOOT_FLASH_CLOCK_SEL

启动时 Flash 时钟选择

0: 20MHz

1: 10MHz

0x02

[4]

BOOT_INT_FLASH

选择从外部还是内部 Flash 启动

0: 内部 Flash

1: 外部 Flash

0x02

[5]

BOOT_CNT_LMT_EN

是否使能软启动次数限制

0: 除能

1: 使能

0x03

[0]

DIS_BOOT_LOG_EN

是否关闭启动日志

0: 使能

1: 除能

0x03

[1]

LOW_BAUD_LOG_EN

选择 Loguart 波特率

0: 1.5Mbps

1: 115200bps

0x03

[2]

LOGIC_SECURE_BOOT_EN

是否使能 安全启动

0: 除能

1: 使能

0x03

[3]

LOGIC_RSIP_EN

是否使能 安全固件保护 (RSIP)

0: 除能

1: 使能

0x03

[4]

LOGIC_RDP_EN

是否使能 读保护 (RDP)

0: 除能

1: 使能

0x03

[5]

BOOT_RAND_DELAY_EN

是否使能启动时随机延时

0: 除能

1: 使能

0x03

[6]

USB_CLK_CAL_EN

是否为 USB 使能 Soc 时钟校准

0: 除能

1: 使能

0x03

[7]

USB_DOWNLOAD_EN

是否使能 USB 下载功能

0: 除能

1: 使能

User-defined MTP 区域

User-defined MTP 区域 (0x170 ~ 0x19F,48 字节) 可以被用户自由使用。

Realtek 提供了专门用于该区域的 API 供用户使用。

API

描述

efuse_get_remaining_length

获取映射区域剩余可用长度

efuse_mtp_read

读取 User-defined MTP 区域的所有数据

efuse_mtp_write

将数据写入 User-defined MTP 区域

efuse_get_remaining_length

项目

描述

功能

获取映射区域剩余可用长度

参数

返回值

剩余可用长度

efuse_mtp_read

项目

描述

功能

读取 User-defined MTP 区域的所有数据

参数

  • data:待读取的数据缓冲区指针

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

efuse_mtp_write

项目

描述

功能

将数据写入 User-defined MTP 区域

参数

  • offset:待读取区域的偏移地址 (基地址为User-defined MTP 区域起始地址 0x170)

  • len:待写入的数据长度

  • data:待写入的数据缓冲区指针

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

API 使用方法

将逻辑地址 0x172[1] (偏移地址为 0x2)的值编程为 1,按以下步骤操作:

  1. 读取 User-defined MTP 区域的值,并检查返回值。

    u8 data_read[48];
    int ret;
    ret = efuse_mtp_read(data_read);
    
  2. 假设步骤 1 中读取的逻辑地址 0x172 (偏移地址为 0x2)数据为 0xA0。将 0xA0 与目标位 0x172[1] 的值进行或操作,其余数据保持默认值。所以新写入的值为 0xA2

  3. 写入新值 0xA2 到偏移地址 0x2,并检查函数返回值。

    u8 data_written = 0xA2;
    int ret;
    ret = efuse_mtp_write(0x2, 0x1, &data_written);
    

物理区域

物理区域被划分为映射区域,安全区域,User-defined physical 区域, ROM code patch 区域和隐藏物理区域。

安全区域

安全区域分为以下两部分:

  • 密钥区域:0x200~0x35F,352 字节。此区域存储各类密钥,在系统启动时被自动加载到内部存储空间。

  • 配置区域:0x360~0x37F,32 字节。此区域控制各个密钥等区域的访问权限。

../../../_images/security_area_layout.svg
密钥区域

密钥区域包括以下内容:

功能

名称

偏移地址

使用方法

IPSEC

S_IPSEC_Key1 (RDP)

0x200~0x21F

对称硬件加密引擎

S_IPSEC_Key2

(Secure boot HMAC)

0x220~0x23F

NS_IPSEC_Key1

0x240~0x25F

NS_IPSEC_Key2

0x260~0x27F

USER PRI

USER_PRI_KEY1

0x280~0x29F

用户密钥区,可自由使用

USER_PRI_KEY2

0x2A0~0x2BF

RSIP

RSIP_KEY1

0x2C0~0x2DF

RSIP

RSIP_KEY2

0x2E0~0x2FF

SWD

SWD_PASSWORD

0x300~0x30F

SWD 保护

PSA

HUK

0x310~0x31F

HUK 生成

Secure Boot

PK1 (ROTPK hash)

0x320~0x33F

安全启动

PK2 (ROTPK hash)

0x340~0x35F

配置区域

配置区域的内容如下表所示。关于本区域各字段的具体用法,参考对应章节的详细说明。

偏移地址

比特位

符号

描述

使用方法

0x360

[31:0]

SWD_ID

设备的 SWD ID

SWD 保护

0x364

[0]

SWD_PWD_EN

使能 SWD 密码

[1]

SWD_DBGEN

SWD 外部调试身份验证

[2]

SWD_NIDEN

[3]

SWD_SPIDEN

[4]

SWD_SPNIDEN

[5]

SWD_PWD_R_Protection_EN

密钥读保护和写保护使能

[6]

SWD_PWD_W_Forbidden_EN

[7]

HUK_W_Forbidden_EN

HUK 生成

0x365

[0]

RSVD

[1]

PK1_W_Forbidden_EN

安全启动

[2]

PK2_W_Forbidden_EN

[3]

S_IPSEC_Key1_R_Protection_EN

对称硬件加密引擎

[4]

S_IPSEC_Key1_W_Forbidden_EN

[5]

S_IPSEC_Key2_R_Protection_EN

[6]

S_IPSEC_Key2_W_Forbidden_EN

[7]

NS_IPSEC_Key1_R_Protection_EN

0x366

[0]

NS_IPSEC_Key1_W_Forbidden_EN

[1]

NS_IPSEC_Key2_R_Protection_EN

[2]

NS_IPSEC_Key2_W_Forbidden_EN

[3]

USER_PRI_KEY1_R_Protection_EN

用户密钥区的读写保护

[4]

USER_PRI_KEY1_W_Forbidden_EN

[5]

USER_PRI_KEY2_R_Protection_EN

[6]

USER_PRI_KEY2_W_Forbidden_EN

[7]

RSIP_KEY1_R_Protection_EN

RSIP

0x367

[0]

RSIP_KEY1_W_Forbidden_EN

[1]

RSIP_KEY2_R_Protection_EN

[2]

RSIP_KEY2_W_Forbidden_EN

[3]

RSIP_MODE_W_Forbidden_EN

[4]

SIC_SECURE_EN

是否使能 SIC 功能

1: 使能

0: 除能

-

[5]

CPU_PC_DBG_EN

是否使能允许调试端口获取 CPU PC 值

1: 使能

0: 除能

-

[6]

UDF1_TRUSTZONE_EN

User-defined 1 区域 (0x380~0x3BF) 安全保护

0: 使能

1: 除能

-

[7]

UDF2_TRUSTZONE_EN

User-defined 2 区域 (0x3C0~0x3FF) 安全保护

0: 使能

1: 除能

-

0x368

[0]

UART_DOWNLOAD_DISABLE

是否使能通过 Trap pin 进入 UART download 模式

0: 除能

1: 使能

-

[1]

RSVD

-

-

[2]

RSIP_EN

使能/除能 RSIP 功能

RSIP

[3]

SECURE_BOOT_EN

使能/除能安全启动功能

安全启动

[4]

SECURE_BOOT_HW_DIS

[5]

RDP_EN

使能/除能 RDP 功能

读保护 (RDP)

[6]

ANTI_ROLLBACK_EN

OTA 固件升级

[7]

FAULT_LOG_PRINT_DIS

是否开启 ROM 中 hard fault 日志

0: 除能

1: 使能

-

0x369

[1:0]

RSIP_MODE

RSIP 模式

RSIP

[2]

HUK_DERIV_EN

使能/除能 HUK 生成

HUK 生成

[3]

USER_PHYSICAL_TZ1_EN

User-defined physical 1 区域安全保护

0: 使能

1: 除能

-

[4]

USER_PHYSICAL_TZ2_EN

User-defined physical 2 区域安全保护

0: 使能

1: 除能

-

[5]

SW_RSVD0

-

-

[6]

SWTRIG_UART_DOWNLOAD_DISABLE

是否开启通过软件触发进入 UART download 模式

0: 除能

1: 使能

-

[7]

SPIC_PINMUX_IN_TESTMODE_DISABLE

Realtek使用

-

0x36A

[7:0]

RSVD

-

-

0x36B

[3:0]

SECURE_BOOT_AUTH_LOG

安全启动认证算法

安全启动

[7:4]

SECURE_BOOT_HASH_LOG

安全启动哈希算法

0x36C

[15:0]

OTA_ADDR

OTA 地址, 4K 对齐

OTA 固件升级

0x36E

[15:0]

BOOTLOADER_VERSION

Bootloader 版本

0x370

[31:0]

CRC0

CRC 检查

CRC

0x374

[31:0]

CRC1

0x378

[31:0]

CRC2

0x37C

[31:0]

CRC3

备注

如果 RSIP_MODE_W_Forbidden_EN 被编程,则 0x369[7:0] 无法被编程。

安全区域 CRC 校验

CRC 用于防御注入攻击。通过比较编程到 OTP 中的有效 CRC 条目与硬件安全区域计算的 CRC 值对比,来实现安全区域不受攻击。

CRC 条目使用规则

  • OTP 中总共有 4 个 CRC 条目,每个包括 2 字节的魔数和 2 字节的有效 CRC 值。一次只能使用一个条目,且必须按顺序使用。可通过硬件获取当前安全区域 CRC 的值而无需软件计算。在启用新的条目时,要将之前使用的条目全部编程为 0x00 使之前的条目无效。这些操作都集成在函数 OTPSetCRC() 中,用户只需要调用此函数即可。

  • CRC 的计算区间为安全区域的(0x200~0x36B)部分。

  • 确保安全区域已经编程完成后,再对 CRC 条目进行编程。因为对安全区域的计算区间的任何修改都会导致 CRC 值的变化,这样必须重新编程一个新的 CRC 条目。

  • 一旦启用 CRC 检查,就无法禁用。如果魔数或有效 CRC 检查失败,ROM 将进入无限循环。

示例

  1. 确保安全区域已经被修改。

  2. 写入 CRC 的值,并根据返回值,和打印信息判断是否写入成功。

    int ret;
    ret = OTPSetCRC();
    
  3. 重启芯片。

    • 如果 CRC 条目检查通过,启动过程将成功进行。

    • 如果 CRC 条目检查失败,芯片将在 ROM 中陷入无限循环,无法正常启动。

小心

  • 建议用户有防御注入攻击的需求才使能此功能,否则一旦使能此功能,如果安全区域 CRC 值和写入 CRC 条目的值不匹配,芯片将永久性的无法启动。

  • 如果 CRC 条目已经被编程,如果用户需要再次修改安全区域,要在 重新启动之前 写入新的 CRC 的值。否则,芯片将永久性的无法启动。

user-defined physical 区域

user-defined 区域一共有 4 块,可以被用户自由使用。

名称

区域

使用方法

User_defined1

0x380-0x3BF

  • 用户自由使用。也可用于安全需求,0x367[6]编程为0后该区域变为安全区域。

  • RMA 模式下,此区域将无法访问。

User_defined2

0x3C0-0x3FF

  • 用户自由使用。也可用于安全需求,0x367[7]编程为0后该区域变为安全区域。

  • RMA 模式下,此区域将无法访问

User_physical1

0x400-0x480

  • 用户自由使用。也可用于安全需求,0x369[3]编程为0后该区域变为安全区域。

  • RMA 模式下,此区域将无法访问。

User_physical2

0x480-0x4FF

  • 用户自由使用。也可用于安全需求,0x369[4]编程为0后该区域变为安全区域。

  • RMA 模式下,此区域将无法访问。

Realtek 提供了专门用于该区域的 API 供用户使用。

API

描述

efuse_otp_read

读取 User-defined physical 区域数据

efuse_otp_write

将数据写入 User-defined physical 区域

efuse_otp_read

项目

描述

功能

读取 User-defined physical 区域数据

参数

  • offset:待读取区域的偏移地址 (基地址为 0x380)

  • len:待读取的数据长度

  • buf:待读取的数据缓冲区指针

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

efuse_otp_write

项目

描述

功能

将数据写入 User-defined physical 区域

参数

  • offset:待读取区域的偏移地址 (基地址为User-defined physical 区域的其实地址 0x380)

  • len:待写入的数据长度

  • buf:待写入的数据缓冲区指针

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

API 使用方法

将物理地址 0x382[1] (偏移地址为 0x2)的值编程为 0,按以下步骤操作:

  1. 读取值,并检查返回值。

    u8 data_read;
    int ret;
    ret = efuse_otp_read(0x2, 0x1, &data_read);
    
  2. 假设步骤 1 中读取到的数据为 0xAF。将 0xAF 与目标位 0x382[1] 的值进行与操作,其余数据保持默认值。所以新写入的值为 0xAD

  3. 写入新值 0xAD 到物理地址 0x02,并检查返回值。

    u8 data_written = 0xAD;
    int ret;
    ret = efuse_otp_write(0x2, 0x1, &data_written);
    

ROM code patch 区域

ROM code patch 区域(0x500 ~ 0x6FF,512 字节)用于在 ROM 中一定限度的加入补丁。

备注

  • 如果使能了 ROM code patch 功能,对应区域使能写保护后,其具有和掩膜 ROM 同等的安全性。

  • 芯片出厂时,如果未使能 ROM code patch 功能,ROM_PATCH_EN 会被编程为 0,永久关闭此功能。

  • Realtek 目前未使用此区域,此区域可以用作 user-defined 区域,请咨询 Realtek 获取使用该区域的方法与注意事项。

此区域分为多个部分,每个部分有独立的控制位。

偏移地址

符号

描述

0x701

[1:0]

ROM_PATCH_EN

使能 ROM code patch 功能

1/2:使能

0/3:除能

[2]

ROM_PATCH_LWE1

使能 ROM code patch 区域(0x500 ~ 0x51F,32 字节)写保护

0:使能

1:除能

[3]

ROM_PATCH_LWE2

使能 ROM code patch 区域(0x520 ~ 0x53F,32 字节)写保护

0:使能

1:除能

[4]

ROM_PATCH_LWE3

使能 ROM code patch 区域(0x540 ~ 0x55F,32 字节)写保护

0:使能

1:除能

[5]

ROM_PATCH_LWE4

使能 ROM code patch 区域(0x560 ~ 0x57F,32 字节)写保护

0:使能

1:除能

[6]

ROM_PATCH_LWE5

使能 ROM code patch 区域(0x580 ~ 0x5FF,128 字节)写保护

0:使能

1:除能

[7]

ROM_PATCH_HWE

使能 ROM code patch 区域(0x600 ~ 0x6FF,256 字节)写保护

0:使能

1:除能

隐藏物理区域

隐藏物理区域(0x700 ~ 0x7FF,128 字节)存储部分 RMA 密钥和 Realtek 校准数据,用户仅允许编程与 RMA 相关的区域。

隐藏物理区域的具体内容及用途如下表所示:

偏移地址

符号

描述

使用说明

0x700

[7:0]

RMA (Life State)

定义设备是否工作在 RMA 模式

RMA 模式

0x701

[1:0]

ROM_PATCH_EN

-

ROM code patch 区域

[2]

ROM_PATCH_LWE1

[3]

ROM_PATCH_LWE2

[4]

ROM_PATCH_LWE3

[5]

ROM_PATCH_LWE4

[6]

ROM_PATCH_LWE5

[7]

ROM_PATCH_HWE

0x702

[0]

RMA_SWD_PWD_R_Protection_EN

密钥读保护和写保护

如果要对RMA模式下密钥加入读写保护,把相应位写为0。

[1]

RMA_SWD_PWD_W_Forbidden_EN

[2]

RMA_PK_W_Forbidden_EN

[7:3]

RSVD

-

-

0x704

[63:0]

ADC calibration

Realtek 定义

Realtek 使用

0x710

[127:0]

RMA SWD Key

RMA 模式下的 SWD 密钥

如果要对RMA模式下SWD进行加密,编程此区域。

0x720

[255:0]

RMA SBOOT KEY HASH

RMA 模式下的 SBOOT 密钥哈希

如果要对RMA模式下使能安全启动,编程此区域。

RMA 状态

RMA 模式 用于用户芯片返修。用户需要将芯片编程为 RMA 模式,且提供密钥(如果密钥被启用)以允许 Realtek 进行调试。 RMA 模式下,安全区域和部分 user-defined physical 区域将不可访问。