各区域使用方法

逻辑区域

逻辑区域被划分为系统数据区域、Wi-Fi 校准数据区域、用户自定义 MTP 区域等。

系统数据区域

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

备注

系统数据区域和系统寄存器的对应关系,参考相应的 用户手册 文档。

由于历史原因,若系统数据区域的某个字节是第一次编程,对应的系统寄存器会保持初始值 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_LogicalRead(&data_read, 2, 1);
    
  2. 根据读到的值决定写入的值。

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

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

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

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

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

    AT+OTP=RMAP
    

    u8 data_read;
    OTP_LogicalRead(&data_read, 2, 1);
    

系统数据编程场景

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

RTL8721Dx:

偏移地址

比特位

符号

描述

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: 使能

0x02

[6]

LOGIC_PQC_EN

是否使能 PQC (ml-dsa-65) 安全启动功能

0: 禁用

1: 使能

0x02

[7]

WAKEUP_ENTRY_CHECK_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: 使能

0x1F

[7]

BOOT_VOL_SEL

启动电压选择

0: 0.9v

1: 1.0v

用户定义的 MTP 区域

用户定义的 MTP 区域 (0x170 ~ 0x19F,48 字节) 可以被用户自由使用。

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

API

描述

efuse_get_remaining_length

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

efuse_mtp_read

读取 用户自定义 MTP 区域的所有数据

efuse_mtp_write

将数据写入 用户自定义 MTP 区域

efuse_get_remaining_length

项目

描述

功能

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

参数

返回值

剩余可用长度

efuse_mtp_read

项目

描述

功能

读取 用户自定义 MTP 区域的所有数据

参数

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

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

efuse_mtp_write

项目

描述

功能

将数据写入 用户自定义 MTP 区域

参数

  • offset:待读取区域的偏移地址 (基地址为用户自定义 MTP 区域起始地址 0x170)

  • len:待写入的数据长度

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

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

API 使用方法

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

  1. 读取 用户自定义 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);
    

物理区域

物理区域被划分为映射区域、安全区域、用户自定义物理区域、ROM 代码补丁区域和隐藏物理区域。

安全区域

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

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

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

../../../_images/security_area_layout.svg

密钥区域

密钥区域包括以下内容:

RTL8721Dx:

功能

名称

偏移地址

使用方法

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

配置区域

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

RTL8721Dx:

偏移地址

比特位

符号

描述

使用方法

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

用户自定义 1 区域 (0x380~0x3BF) 安全保护

0: 使能

1: 禁用

-

[7]

UDF2_TRUSTZONE_EN

用户自定义 2 区域 (0x3C0~0x3FF) 安全保护

0: 使能

1: 禁用

-

0x368

[0]

UART_DOWNLOAD_DISABLE

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

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

用户自定义 physical 1 区域安全保护

0: 使能

1: 禁用

-

[4]

USER_PHYSICAL_TZ2_EN

用户自定义 physical 2 区域安全保护

0: 使能

1: 禁用

-

[5]

PQC_EN

使能/禁用 PQC (ml-dsa-65) 安全启动功能

-

[6]

SWTRIG_UART_DOWNLOAD_DISABLE

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

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 值对比,来实现安全区域不受攻击。

RTL8721Dx:

CRC 条目使用规则

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

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

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

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

示例

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

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

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

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

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

小心

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

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

用户自定义物理区域

用户自定义物理区域一共有 4 块,可以被用户自由使用。

RTL8721Dx:

名称

区域

使用方法

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

读取 用户自定义 physical 区域数据

efuse_otp_write

将数据写入 用户自定义 physical 区域

efuse_otp_read

项目

描述

功能

读取 用户自定义 physical 区域数据

参数

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

  • len:待读取的数据长度

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

返回值

读操作结果

  • RTK_SUCCESS:成功

  • RTK_FAIL:失败

efuse_otp_write

项目

描述

功能

将数据写入 用户自定义 physical 区域

参数

  • offset:待读取区域的偏移地址 (基地址为用户自定义 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 代码补丁区域

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

备注

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

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

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

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

RTL8721Dx:

偏移地址

符号

描述

0x701

[1:0]

ROM_PATCH_EN

使能 ROM 代码补丁 功能

1/2:使能

0/3:禁用

[2]

ROM_PATCH_LWE1

使能 ROM 代码补丁 区域(0x500 ~ 0x51F,32 字节)写保护

0:使能

1:禁用

[3]

ROM_PATCH_LWE2

使能 ROM 代码补丁 区域(0x520 ~ 0x53F,32 字节)写保护

0:使能

1:禁用

[4]

ROM_PATCH_LWE3

使能 ROM 代码补丁 区域(0x540 ~ 0x55F,32 字节)写保护

0:使能

1:禁用

[5]

ROM_PATCH_LWE4

使能 ROM 代码补丁 区域(0x560 ~ 0x57F,32 字节)写保护

0:使能

1:禁用

[6]

ROM_PATCH_LWE5

使能 ROM 代码补丁 区域(0x580 ~ 0x5FF,128 字节)写保护

0:使能

1:禁用

[7]

ROM_PATCH_HWE

使能 ROM 代码补丁 区域(0x600 ~ 0x6FF,256 字节)写保护

0:使能

1:禁用

隐藏物理区域

区域用途

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

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

RTL8721Dx:

偏移地址

符号

描述

使用说明

0x700

[7:0]

RMA (Life State)

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

RMA 模式

0x701

[1:0]

ROM_PATCH_EN

-

ROM 代码补丁 区域

[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

存放 ADC 校准数据

-

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 模式下,安全区域和部分用户自定义物理区域将不可访问。RMA 模式使用方法参考 生命周期

../../../_images/otp_rma_access.svg