第三十三章 OTP——一次性编程区域读写
目录
W55MH32的OTP(One-Time Programmable,一次性可编程存储器)是芯片内部一种特殊的非易失性存储区域,主要用于存储需要一次性写入且不可擦除的关键数据。以下从功能特性、典型应用、程序设计及注意事项等方面展开详解:
1 OTP功能特性
1.1 非易失性
OTP存储的数据在芯片掉电后仍可保留,无需额外电源维持,与Flash、EEPROM类似。
1.2 一次性写入限制
W55MH32的OTP区域仅允许每个存储单元(通常为位或字节)写入一次(部分型号支持按块/页写入,但整体仍为一次性)。写入后无法擦除或覆盖,因此写入前需确保数据准确性。
1.3 物理保护机制
OTP的写入通常通过熔断(Fuse)或特殊工艺实现(如反熔丝)。写入操作会永久改变存储单元的物理状态(如熔断金属连线),从而保证数据不可篡改。
W55MH32为反熔丝工艺型OTP,即具有“只能写1(将未编程的0变为1)、不能写0(已编程的1无法恢复为0)”的特性。
反熔丝OTP原理如下:
- 初始状态(未编程):存储单元为逻辑0(如反熔丝未击穿,等效高阻或电容,代表0)。
- 编程时:施加高电压击穿反熔丝,单元变为逻辑1(等效低阻,代表1),且一旦编程(写1),无法逆向恢复为0(物理结构不可逆)。
与熔丝型OTP对比:
- 熔丝型:初始为1(熔丝未熔断),编程时熔断熔丝,单元变为0(只能写0,不能写1)。
- 反熔丝型:初始为0,编程后为1(只能写1,不能写0),符合“写1不可逆”的描述。
1.4 访问权限控制
W55MH32的OTP区域支持写保护(通过寄存器锁存),需通过特定指令(写入解锁密钥)才能开启写入权限,防止误操作。
2 应用场景
OTP的“一次性写入+非易失”特性使其适用于以下场景:
2.1 唯一标识符(UID)存储
芯片出厂时,厂商可能通过OTP写入全局唯一的设备ID(如96位或更长),用于产品追溯、防伪或加密认证(如作为AES密钥的种子)。
2.2 校准参数存储
传感器或模拟模块(如ADC、DAC)的校准数据(如偏移量、增益系数)需在出厂前通过测试设备写入OTP,避免因Flash擦写次数限制导致数据丢失。
2.3 安全密钥存储
用于存储加密密钥(如AES-128/256密钥、HMAC密钥)或安全配置(如禁止JTAG调试的锁定位)。由于OTP不可擦除,即使芯片被物理攻击,密钥也难以被篡改或窃取。
2.4 客户定制化数据
设备制造商可在生产阶段写入客户定制信息(如硬件版本、区域配置),避免后续软件修改带来的成本。
3 注意事项
3.1 写入次数限制
OTP的每个存储单元仅允许写入一次(支持按位写入,但同一位多次写入会被视为“0→1”的单向操作)。若尝试重复写入同一地址,可能导致数据错误或硬件锁死。
3.2 电压与时序要求
OTP的写入需要稳定的电源(通常需满足芯片手册规定的最小电压,如2.7V~3.6V),且写入时序需严格遵循数据手册(如写入脉冲宽度、地址建立时间)。
3.3 安全风险
部分OTP区域可能与芯片的安全机制(如读保护、调试接口锁定)关联。错误写入可能导致芯片无法调试或功能失效,需谨慎操作。
4 程序设计
以下为OTP例程的程序设计流程:
4.1 OTP上电
在使用OTP模块前我们需要为其提供稳定的工作电源,通过配置系统时钟、解锁保护机制,并设置低压差稳压器(LDO)的启动时间,确保OTP在操作(如写入熔断)时电源满足要求。主要通过OTP_PowerOn()函数来实现,内容如下:
void OTP_PowerOn(uint32_t Time)
{
RCC->RCC_SYSCFG_CONFIG = 0x01;
SYSCFG->SYSCFG_LOCK = 0xAB12DFCD;
if(Time > OTP_POWERON_TIME)
{
OTP->OTP_LDO =Time;
}
else
{
OTP->OTP_LDO = OTP_POWERON_TIME;
}
}
OTP_PowerOn()函数是OTP模块的电源初始化函数,主要用于配置OTP的供电时序以确保其稳定工作:首先通过RCC->RCC_SYSCFG_CONFIG=0x01启用SYSCFG模块时钟,为后续配置提供基础;接着向SYSCFG->SYSCFG_LOCK写入解锁密钥0xAB12DFCD解除保护,允许修改OTP电源参数;最后根据输入的Time配置OTP的LDO(低压差稳压器)启动时间——若Time大于预设的最小启动时间OTP_POWERON_TIME,则使用Time,否则强制使用最小值,以此平衡供电稳定性与效率,避免因电源波动或启动时间不足导致OTP操作(如写入熔断)失败。
4.2 设置时间基准
OTP_SetTime()函数为OTP的写入(熔断或反熔丝)提供精确的控制电压施加的时间:
void OTP_SetTime(uint16_t Time)
{
OTP->OTP_10ns |= Time;
}
OTP_SetTime()函数通过将输入的Time参数按位或到OTP_10ns寄存器,以10纳秒为单位叠加配置OTP操作的时间参数(如写入脉冲宽度),确保电压/电流施加时间满足OTP物理状态改变的要求,从而保证数据写入的可靠性。该设计兼顾了时间配置的灵活性与安全性,允许开发者根据实际需求动态调整关键时序。
4.3 写入数据
OTP_WriteByte()函数用于向OTP指定地址写入一个字节的数据,内容如下:
void OTP_WriteByte(uint8_t Addr,uint8_t Data)
{
assert_param(IS_OTP_ADDRESS(Addr));
OTP->OTP_WR = (Addr << 8) | Data;
OTP->OTP_CTRL = BIT(0);
while(OTP->OTP_CTRL & BIT(2));
}
OTP_WriteByte()函数通过“地址验证→数据装载→触发写入→等待完成”的闭环流程,实现了向OTP指定地址写入一个字节数据的功能。其核心是通过操作OTP模块的寄存器,与硬件协同完成存储单元的物理状态修改,确保数据的一次性可靠写入。
4.4 OTP断电
OTP_PowerOff()函数用于关闭OTP模块的工作电源或使其进入低功耗模式,通常在OTP操作完成后调用,以降低系统功耗或防止意外写入。其核心逻辑是通过解锁保护寄存器并禁用相关时钟,切断OTP模块的供电或配置其进入休眠状态。函数内容如下:
void OTP_PowerOff(void)
{
SYSCFG->SYSCFG_LOCK = 0xAB12DFCD;
RCC->RCC_SYSCFG_CONFIG = 0x00;
}
函数首先向SYSCFG_LOCK写入解锁密钥以解除保护,然后通过RCC_SYSCFG_CONFIG禁用SYSCFG时钟,最终切断OTP的供电或使其进入休眠状态。
4.5 主函数main()
主函数main()如下:
int main(void)
{
RCC_ClocksTypeDef clocks;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
delay_init();
UART_Configuration(115200);
RCC_GetClocksFreq(&clocks);
printf("\n");
printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhz\n",
(float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,
(float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000);
printf("OTP Write Read Test.\n");
OTP_PowerOn(clocks.PCLK2_Frequency / 10); //100ms
OTP_SetTime(clocks.PCLK2_Frequency / 1000000); //1us
OTP_WriteByte(OTP_ADDRESS_0, 0x5A);
printf("OPT Data0 : 0x%x\n", OTP->OTP_DATA0);
printf("OPT Data1 : 0x%x\n", OTP->OTP_DATA1);
printf("OPT Data2 : 0x%x\n", OTP->OTP_DATA2);
printf("OPT Data3 : 0x%x\n", OTP->OTP_DATA3);
printf("OPT Data4 : 0x%x\n", OTP->OTP_DATA4);
printf("OPT Data5 : 0x%x\n", OTP->OTP_DATA5);
printf("OPT Data6 : 0x%x\n", OTP->OTP_DATA6);
printf("OPT Data7 : 0x%x\n", OTP->OTP_DATA7);
OTP_PowerOff();
while (1);
}
程序首先初始化系统时钟(启用PWR和BKP外设时钟)、延时函数及串口(波特率115200),并通过RCC_GetClocksFreq获取系统各时钟频率(如SYSCLK、PCLK2等),打印验证时钟配置;接着启动OTP电源(OTP_PowerOn,基于PCLK2频率配置100ms启动时间)、设置OTP写入时序(OTP_SetTime,基于PCLK2频率配置1μs时间参数),向OTP的0号地址写入数据0x5A;随后读取并打印OTP的8个数据寄存器(DATA0~DATA7),验证写入是否成功;最后关闭OTP电源(OTP_PowerOff)以降低功耗,进入无限循环保持运行。
整体通过初始化、时钟验证、OTP配置、写入-读取验证及电源管理,完成对OTP功能的测试。
5 下载验证
程序下载运行后,串口输出显示系统时钟(如SYSCLK 72MHz)配置正常,OTP测试中地址0(DATA0)写入0x5A成功,其余地址为默认0x0,验证了OTP写入和读取功能功能:
6 总结
W55MH32的OTP是一种专为“一次性关键数据存储”设计的非易失性存储器,其核心价值在于数据的不可篡改性。在实际应用中,需结合芯片型号的数据手册,严格遵循写入流程,确保数据的准确性和可靠性。