IC:

概述

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

OTP 布局

OTP 的布局如下图所示。

../../rst_rtos/1_otpc/figures/otp_layout_dplus_21Dx.svg

备注

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

物理区域

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

小心

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

物理区域分区

地址

描述

使用方法

映射区域

(0x000-0x1FF, 512 字节)

映射到逻辑区域

-

安全区域

(0x200-0x37F, 384 字节)

保存各类密钥和相关配置

安全区域使用方法

User-defined physical 区域

(0x380-0x4FF, 384 字节)

用户自由使用

User-defined physical 区域使用方法

ROM code patch 区域

(0x500-0x6FF, 512 字节)

用于在 ROM 中加入补丁

ROM code patch 区域使用方法

隐藏物理区域

(0x700-0x7FF, 256字节)

用于 RMA 等功能

隐藏物理区域使用方法

逻辑区域

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

../../rst_rtos/1_otpc/figures/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。

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

../../rst_rtos/1_otpc/figures/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

0

是否使用 Flash 的深度睡眠模式

0: 除能

1: 使能

如果要启用睡眠模式下 Flash 进入深度睡眠,将它编程为 1, 否则忽略它。

0x02

[1]

SPIC_ADDR_4BYTE_EN

0

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

0: 除能

1: 使能

如果选用外部 Flash,且容量大于 16M 字节,将它编程为 1, 否则忽略它。

0x02

[2]

SPIC_BOOT_SPEEDUP_DIS

0

是否启动时加速 SPIC 初始化

0: 加速

1: 不加速

如果不想在系统启动时加速 SPIC 初始化,将它编程为 1,否则忽略它。

0x02

[3]

BOOT_FLASH_CLOCK_SEL

0

启动时 Flash 时钟选择

0: 20MHz

1: 10MHz

如果要把系统启动时 Flash 的时钟切为 10M,将它编程为 1 ,否则忽略它。

0x02

[4]

BOOT_INT_FLASH

0

从外部还是内部 Flash 启动

0: 内部 Flash

1: 外部 Flash

如果是从外部 Flash 启动,将它编程为 1,否则忽略它。

0x02

[5]

BOOT_CNT_LMT_EN

0

是否使能软启动次数限制

0: 除能

1: 使能

如果要使能系统软启动次数限制,将它编程为 1,否则忽略它。

0x03

[0]

DIS_BOOT_LOG_EN

0

是否关闭启动日志

0: 使能

1: 除能

如果想关闭启动的日志,将它编程为 1,否则忽略它。

0x03

[1]

LOW_BAUD_LOG_EN

0

选择 Loguart 波特率

0: 1.5Mbps

1: 115200bps

如果LOGUART的波特率选择为 115200,将它编程为 1,否则忽略它。

0x03

[2]

LOGIC_SECURE_BOOT_EN

0

是否使能安全启动功能

0: 除能

1: 使能

安全启动

0x03

[3]

LOGIC_RSIP_EN

0

是否使能 RSIP 功能

0: 除能

1: 使能

RSIP

0x03

[4]

LOGIC_RDP_EN

0

是否使能 RDP 功能

0: 除能

1: 使能

AP 安全服务(SPE)

0x03

[5]

BOOT_RAND_DELAY_EN

0

是否使能启动时随机延时

0: 除能

1: 使能

如果要在系统启动时加入随机延时,将它编程为 1,否则忽略它。

0x03

[6]

USB_CLK_CAL_EN

0

是否为 USB 使能 Soc 时钟校准

0: 除能

1: 使能

如果要为USB使能 Soc 时钟校准,将它编程为 1,否则忽略它。

0x03

[7]

USB_DOWNLOAD_EN

0

是否使能 USB 下载功能

0: 除能

1: 使能

如果要使能 USB 下载功能,将它编程为 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 字节。此区域控制各个密钥等区域的访问权限。

../../rst_rtos/1_otpc/figures/security_area_layout.svg

密钥区域

密钥区域包括以下内容:

功能

名称

大小 (bits)

开始偏移地址

结束偏移地址

使用方法

IPSEC

S_IPSEC_Key1 (RDP)

256

0x200

0x021F

对称硬件加密引擎

S_IPSEC_Key2 (Secure boot HMAC)

256

0x220

0x023F

NS_IPSEC_Key1

256

0x240

0x025F

NS_IPSEC_Key2

256

0x260

0x027F

USER PRI

USER_PRI_KEY1

256

0x280

0x029F

用户密钥区,可自由使用

USER_PRI_KEY2

256

0x2A0

0x02BF

RSIP

RSIP_KEY1

256

0x2C0

0x02DF

RSIP

RSIP_KEY2

256

0x2E0

0x02FF

SWD

SWD_PASSWORD

128

0x300

0x030F

SWD 保护

PSA

HUK

128

0x310

0x031F

HUK 生成

Secure Boot

PK1 (ROTPK hash)

256

0x320

0x033F

安全启动

PK2 (ROTPK hash)

256

0x340

0x035F

配置区域

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

偏移地址

比特位

符号

描述

使用方法

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 功能

如果有关闭 SIC 功能的需求,将它编程为 0。

[5]

CPU_PC_DBG_EN

调试端口能否获取 CPU PC 值

1: 使能

0: 除能

如果有禁止调试端口获取CPU PC 值的需求,将它编程为 0。

[6]

UDF1_TRUSTZONE_EN

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

0: 使能

1: 除能

如果要让 User-defined 1 区域仅可被安全区域访问,将它编程为 0。

[7]

UDF2_TRUSTZONE_EN

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

0: 使能

1: 除能

如果要让 User-defined 2 区域仅可被安全区域访问,将它编程为 0。

0x368

[0]

UART_DOWNLOAD_DISABLE

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

0: 除能

1: 使能 (默认)

如果有关闭通过 UART Trap pin 进入 UART download 模式的需求,将它编程为 0。

[1]

RSVD

-

-

[2]

RSIP_EN

使能/除能 RSIP 功能

RSIP

[3]

SECURE_BOOT_EN

使能/除能安全启动功能

安全启动

[4]

SECURE_BOOT_HW_DIS

[5]

RDP_EN

使能/除能 RDP 功能

AP 安全服务(SPE)

[6]

ANTI_ROLLBACK_EN

OTA 固件升级

[7]

FAULT_LOG_PRINT_DIS

是否关闭 ROM 中 hard fault 日志

0: 除能

1: 使能 (默认)

如果有关闭 ROM hard fault 日志的需求,将它编程为 0。

0x369

[1:0]

RSIP_MODE

RSIP 模式

RSIP

[2]

HUK_DERIV_EN

使能/除能 HUK 生成

HUK 生成

[3]

USER_PHYSICAL_TZ1_EN

User-defined physical 1 区域安全保护

0: 使能

1: 除能

如果要让 User-defined physical 1 区域仅可被安全区域访问,将它编程为 0。

[4]

USER_PHYSICAL_TZ2_EN

User-defined physical 2 区域安全保护

0: 使能

1: 除能

如果要让 User-defined physical 2 区域仅可被安全区域访问,将它编程为 0。

[5]

SW_RSVD0

-

-

[6]

SWTRIG_UART_DOWNLOAD_DISABLE

是否关闭通过软件触发进入 UART download 模式

0: 除能

1: 使能 (默认)

如果有关闭通过软件触发进入 UART download 模式的需求,将它编程为 0。

[7]

SPIC_PINMUX_IN_TESTMODE_DISABLE

Realtek使用

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 功能

如果要使能 Rom code patch 功能,将它编程为 1 或者 2

[2]

ROM_PATCH_LWE1

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

如果要使能此区域写保护功能,将它编程为 0

[3]

ROM_PATCH_LWE2

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

如果要使能此区域写保护功能,将它编程为 0

[4]

ROM_PATCH_LWE3

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

如果要使能此区域写保护功能,将它编程为 0

[5]

ROM_PATCH_LWE4

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

如果要使能此区域写保护功能,将它编程为 0

[6]

ROM_PATCH_LWE5

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

如果要使能此区域写保护功能,将它编程为 0

[7]

ROM_PATCH_HWE

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

如果要使能此区域写保护功能,将它编程为 0

隐藏物理区域

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

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

偏移地址

符号

描述

使用说明

0x700

[7:0]

RMA (Life State)

定义设备工作在哪种模式

  • 若 1 的个数为奇数,设备将进入 RMA 模式

  • 若 1 的个数为偶数,设备将进入​正常模式

设备上电时,硬件将首先自动加载工作模式。

在 RMA 模式下,特定安全区域(4Kb)会得到保护,任何读操作始终返回全 1。

  • 为了使设备进入 RMA 模式,请将该字段中 1 的个数配置为奇数。

  • 为了使设备进入正常模式,请将该字段中 1 的个数配置为偶数。

  • 默认值为 0xFF(全 1),对应正常模式。

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 区域将不可访问。