公司动态
CC13x2/CC26x2 WDT与TRNG寄存器级配置:嵌入式系统可靠性与安全基石
1. 项目概述与核心价值在嵌入式系统尤其是电池供电的无线物联网设备开发中系统的健壮性与安全性是产品能否成功落地的关键。想象一下一个部署在野外用于环境监测的传感器节点如果因为软件异常而“死机”可能需要人工现场复位成本高昂如果其通信数据因随机数质量不佳而被轻易破解则毫无安全可言。这正是看门狗定时器和真随机数生成器这两个外设存在的根本意义。看门狗定时器常被开发者亲切地称为“系统守护者”。它的工作原理简单而粗暴你需要定期去“喂狗”如果程序跑飞或陷入死循环而忘记了这项任务看门狗就会“咬人”——触发系统复位让设备从头再来。这就像给系统设置了一个必须按时完成的“心跳”任务丢失心跳则意味着生命终结并重启。在CC13x2/CC26x2这类面向低功耗无线应用的MCU中WDT的设计尤为关键因为它需要在极低功耗的睡眠模式下依然可靠工作确保设备能从任何异常中恢复。真随机数生成器则是安全体系的基石。与软件生成的伪随机数不同TRNG依赖于芯片内部的物理噪声源如环形振荡器的热噪声、半导体结噪声其输出在理论上是不可预测的。这对于生成加密密钥、初始化向量、会话随机数等至关重要。一个弱的随机源会直接导致整个加密体系形同虚设。CC13x2/CC26x2集成的TRNG模块基于24个自由运行振荡器为在资源受限的终端设备上实现高等级安全提供了硬件保障。本文将深入剖析TI CC13x2/CC26x2系列MCU中WDT与TRNG模块的寄存器级配置。我不会仅仅罗列寄存器字段而是结合我多年在低功耗无线产品开发中的实战经验带你理解每个配置位背后的设计意图分享从寄存器配置到稳定可靠、安全可用的实际代码之间的关键步骤与常见陷阱。无论你是正在评估该平台还是已经深陷调试泥潭相信这些细节都能为你提供直接的帮助。2. WDT模块从原理到可靠配置2.1 模块框图与工作流程解析CC13x2/CC26x2的看门狗定时器是一个32位递减计数器。其核心工作流程可以概括为加载初值 - 启动计数 - 定期“喂狗”重载- 超时则触发动作。模块框图清晰地展示了几个关键部分LOAD寄存器用于设置超时值VALUE寄存器用于实时读取当前计数值CTL寄存器控制中断使能、复位使能及中断类型RIS/MIS寄存器提供中断状态而LOCK寄存器则用于防止关键配置被意外修改。这里有一个至关重要的细节WDT的时钟源是MCU电源与时钟管理模块提供的INFRASTRUCTURE时钟。这意味着只要MCU没有进入完全的掉电模式WDT就会持续运行。即使在低功耗睡眠模式下只要该时钟存在WDT就在默默计数。这确保了看门狗在绝大多数异常情况下依然有效。注意在配置深度睡眠模式时务必确认PRCM模块对WDT时钟的配置。有些超低功耗场景可能会关闭部分时钟域需确保WDT时钟不受影响否则看门狗将失效。2.2 关键寄存器详解与配置策略2.2.1 LOAD与VALUE寄存器设定生命的“时长”LOAD寄存器是看门狗超时周期的设定器。它是一个可读写的32位寄存器复位值为0xFFFFFFFF。当你向LOAD寄存器写入一个新值时这个值会立即加载到32位递减计数器中并重新开始计数。计算公式与实例 假设INFRASTRUCTURE时钟频率为48 MHz你希望看门狗超时时间为1秒。计算所需计数值Timeout_Count Clock_Frequency * Timeout_Time 48,000,000 Hz * 1 s 48,000,000由于计数器递减至0触发LOAD值应为0xFFFFFFFF - Timeout_Count 1。但通常我们直接使用超时计数值因为计数器从LOAD值开始递减至0。更简单的做法LOAD_Value Timeout_Time (s) * Clock_Frequency (Hz)。因此LOAD_Value 1 * 48e6 48,000,000 (0x02DC6C00)。向LOAD写入0会导致立即产生中断。这是一个需要警惕的陷阱在初始化序列中如果先写LOAD为0再配置其他寄存器可能会立即触发看门狗中断。安全的做法是先配置CTL等寄存器最后再写入有效的LOAD值并解锁。VALUE寄存器是只读的用于读取当前计数器的值。这在调试时非常有用可以判断程序“喂狗”的间隔是否稳定或者查看在进入低功耗模式前计数器还剩多少时间。2.2.2 CTL寄存器控制行为的“大脑”CTL寄存器虽然只有3个有效控制位但每一个都至关重要INTEN (位0): 中断使能。置1后看门狗超时会先产生一个中断。一旦置位只有硬件复位才能清除此位。这意味着如果你使能了中断就必须在中断服务程序中进行关键的错误处理或系统状态保存因为无法通过软件禁止它来阻止后续的复位如果RESEN也使能了。RESEN (位1): 复位使能。置1后看门狗超时在中断之后如果中断使能将触发一个系统复位。这是看门狗最核心的功能。通常在需要捕获超时错误日志的场景可以同时使能INTEN和RESEN在中断服务程序中快速保存错误上下文到非易失存储器然后等待复位。INTTYPE (位2): 中断类型选择。0为可屏蔽中断1为非可屏蔽中断。NMI的优先级最高不能被全局中断开关禁止。在极其严苛的实时性要求下可以选择NMI以确保超时事件能被立即响应。但对于大多数应用标准中断即可。配置心得对于大多数需要高可靠性的应用我的建议是同时使能中断和复位。在中断服务程序中不要进行复杂操作仅记录关键错误码例如将程序计数器、栈指针或某个状态标志写入备份寄存器或Flash的特定区域然后等待复位。复位后启动代码可以检查这个错误码从而判断上次复位是否为看门狗触发并采取相应的恢复策略。2.2.3 ICR、RIS、MIS寄存器理解中断状态流这三个寄存器构成了完整的中断状态管理链RIS (Raw Interrupt Status): 原始中断状态位。只要计数器超时WDTRIS位就会置1无论INTEN是否使能。你可以通过轮询此位来实现一种“查询式”的看门狗超时检测但这通常不是好主意因为它违背了看门狗作为独立监控器的初衷。MIS (Masked Interrupt Status): 屏蔽后的中断状态位。WDTMIS WDTRIS INTEN。只有当中断使能时超时事件才会反映到这里。这是中断控制器实际“看到”的状态。ICR (Interrupt Clear): 中断清除寄存器。向该寄存器写入任意值即可清除WDTRIS位同时也会清除MIS位。这是清除看门狗中断标志的唯一方法。同时这个操作会自动将LOAD寄存器的值重新加载到计数器中。也就是说“喂狗”操作是通过写ICR寄存器完成的而不是重新写LOAD。关键操作“喂狗”的正确姿势是WDT-ICR 0x1;写入任何值均可。这个操作一举两得清除了挂起的中断并重置了计数器。2.2.4 LOCK寄存器最后的保险丝LOCK寄存器是配置安全的关键。向该寄存器写入0x1ACC_E551这个“魔法数字”后WDT配置寄存器如LOAD, CTL将被解锁允许写入。写入任何其他值则会立即重新上锁。为什么需要锁为了防止跑飞的程序意外修改看门狗的配置例如将超时时间设得极长或禁用复位导致看门狗形同虚设。因此标准的配置流程是解锁 - 配置 - 上锁。上锁后即使程序跑飞也无法篡改看门狗的核心设定了。2.2.5 TEST与INT_CAUS寄存器调试与测试的利器这两个寄存器主要用于芯片测试和高级调试。TEST.STALL: 当使用调试器暂停CPU时此位决定WDT计数器是否也暂停。在调试阶段建议启用此功能置1否则在你单步调试时看门狗可能超时导致系统复位无法调试。TEST.TEST_EN: 测试模式使能。置1时看门狗超时不会产生外部复位信号而是置位INT_CAUS.CAUSE_RESET并产生中断。这允许你在不引起系统复位的情况下测试看门狗中断服务程序。INT_CAUS: 用于在测试模式下区分中断是由复位事件模拟产生(CAUSE_RESET)还是常规超时产生(CAUSE_INTR即RIS的副本)。实操建议在产品开发阶段特别是调试与硬件测试阶段可以合理利用TEST寄存器。但在最终量产软件中应确保TEST寄存器保持复位默认值0以保证看门狗复位功能的绝对有效。2.3 WDT配置与使用实战代码理解了寄存器之后我们来看一个完整的、具备错误恢复能力的WDT初始化与使用流程。以下代码基于TI的DriverLib库风格但聚焦于寄存器操作原理。// 假设基地址定义 #define WDT_BASE 0x40085800 #define WDT_LOAD (*(volatile uint32_t *)(WDT_BASE 0x000)) #define WDT_CTL (*(volatile uint32_t *)(WDT_BASE 0x008)) #define WDT_ICR (*(volatile uint32_t *)(WDT_BASE 0x00C)) #define WDT_LOCK (*(volatile uint32_t *)(WDT_BASE 0xC00)) // 定义“魔法钥匙” #define WDT_LOCK_KEY 0x1ACCE551 // 系统时钟频率 (假设为48MHz) #define SYS_CLK_FREQ_HZ 48000000UL // 期望看门狗超时时间秒 #define WDT_TIMEOUT_S 2 void WDT_InitWithRecovery(void) { // 步骤1解锁WDT以进行配置 WDT_LOCK WDT_LOCK_KEY; // 步骤2计算并设置超时加载值 // 注意LOAD是32位递减计数器的初始值。超时时间 LOAD / Clock_Freq。 // 为防止立即超时先写一个较大的值最后再写实际值是一种安全做法。 uint32_t loadValue SYS_CLK_FREQ_HZ * WDT_TIMEOUT_S; // 检查是否溢出LOAD是32位寄存器 if (loadValue 0xFFFFFFFFUL) { // 处理错误超时时间过长 loadValue 0xFFFFFFFFUL; // 设置为最大可能值 } WDT_LOAD loadValue; // 步骤3配置控制寄存器 uint32_t ctlValue 0; ctlValue | (1 0); // INTEN 1, 使能中断以便记录错误 ctlValue | (1 1); // RESEN 1, 使能复位核心功能 // INTTYPE 0 (默认)使用标准中断 WDT_CTL ctlValue; // 步骤4清除任何可能已挂起的中断上电后或复位后 WDT_ICR 0x1; // 步骤5重新上锁防止配置被意外修改 WDT_LOCK 0x0; // 写入任何非钥匙值即可上锁 // 步骤6配置NVIC启用WDT中断假设使用标准中断 // NVIC_EnableIRQ(WDT_IRQn); // NVIC_SetPriority(WDT_IRQn, 0); // 通常设为最高或次高优先级 } // 看门狗中断服务程序 // 注意此函数应尽可能短小因为复位可能紧随其后发生。 void WDT_IRQHandler(void) { // 步骤1清除中断标志通过写ICR同时也完成了“喂狗” // 但注意在中断里“喂狗”会重置计数器延迟复位。 // 如果我们的目的是记录错误后立即复位则不应在此喂狗。 // WDT_ICR 0x1; // 通常不在中断里喂狗 // 步骤2记录错误上下文到非易失性存储如备份寄存器、Flash的一页 // 例如将程序计数器PC、链接寄存器LR或自定义错误码写入特定位置。 // *((volatile uint32_t *)0x20000000) 0xDEADBEEF; // 示例写入SRAM备份区域复位后会丢失 // 对于需要持久化的错误需要写入Flash或FRAM。 // 步骤3可选执行关键的安全关闭操作如断开外部电源、保存关键数据等。 // 步骤4由于CTL.RESEN1在中断服务程序退出后硬件会自动产生复位。 // 我们无需软件触发复位。 }“喂狗”的最佳位置 “喂狗”操作WDT_ICR 0x1;应该放在系统的主循环或主任务中确保在正常运行时定期执行。绝对不要放在定时器中断等可能因某个任务阻塞而依然会定期执行的地方因为这可能掩盖主循环卡死的故障。一个常见的模式是在多个关键任务完成后设置一个“任务完成”标志在主循环中检查所有标志后执行“喂狗”。3. TRNG模块从物理噪声到密码学安全随机数3.1 熵源原理与模块架构CC13x2/CC26x2的TRNG模块的熵源基于24个自由运行振荡器。每个FRO本质上是一个环形振荡器其振荡频率受制程、电压、温度以及最关键的——半导体噪声的影响。由于这些噪声在物理上是随机的因此每个FRO的输出边沿在时间上具有不可预测的“抖动”。模块的核心思想是并行采样与熵积累采样系统时钟以一定频率由CFG0.SMPL_DIV控制去异步采样这24个FRO的输出。由于FRO频率与采样时钟频率非整数倍关系且存在抖动采样结果0或1具有不确定性即熵。混合与积累采样到的24位数据经过一个复杂的非线性组合电路混合器进行混淆然后输入到一个81位的线性反馈移位寄存器中。LFSR在这里的作用不是生成伪随机序列而是作为一个熵池将多个时钟周期内产生的、微小的随机性每个采样点可能只有零点几比特的熵累积起来。输出当累积的熵达到足够量由CTL.STARTUP_CYCLES和CFG0.MIN_REFILL_CYCLES决定时LFSR中的状态被处理并转移到64位的输出寄存器OUT0和OUT1中供CPU读取。关键参数熵与周期启动周期模块从使能到产生第一个随机数所需的采样周期数。STARTUP_CYCLES* 28。最小/最大重填周期在读取一个随机数后生成下一个随机数所需的最小/最大采样周期数。MIN_REFILL_CYCLES* 64MAX_REFILL_CYCLES* 28。采样分频SMPL_DIV控制采样频率。设为0表示每个系统时钟都采样。为了确保能采集到FRO的跳变采样周期必须大于最慢FRO周期的一半。3.2 核心寄存器配置与熵管理策略3.2.1 控制与配置寄存器平衡速度与质量CTL寄存器TRNG_EN总使能位。为0时模块处于空闲状态功耗最低。STARTUP_CYCLES决定首次生成随机数所需的熵积累时间。TI手册建议所有24个FRO使能时约5ms的启动时间可产生64比特熵。计算示例若系统时钟48MHzSMPL_DIV0则每秒采样48M次。5ms内采样次数48e6 * 0.005 240,000次。STARTUP_CYCLES 采样次数 / 28 ≈ 8571 (0x217B)。这是高安全应用的关键配置点。CFG0寄存器SMPL_DIV采样分频。通常设为0以获得最高采样率从而最快积累熵。MIN_REFILL_CYCLES最小重填周期。如果设为0则使用MAX_REFILL_CYCLES的值这意味着每次生成的随机数都具有相同的熵由最大值保证。为了确保每个随机数质量一致建议将此值设为0。MAX_REFILL_CYCLES最大重填周期。它定义了两个关键时间1) 生成下一个随机数的最大等待时间2)模块空闲超时时间。如果随机数生成后在MAX_REFILL_CYCLES时间内未被读取TRNG将自动进入空闲模式以省电。配置策略高性能/低安全场景如生成随机延迟使用较小的STARTUP_CYCLES和MAX_REFILL_CYCLES例如STARTUP_CYCLES 1*28MAX_REFILL_CYCLES 1*28。这能在几十个时钟周期内产生随机数但熵极低。高安全场景如生成密钥必须使用足够大的周期。按照TI建议设置STARTUP_CYCLES使得启动时间≥5ms并将MIN_REFILL_CYCLES设为0MAX_REFILL_CYCLES设为与STARTUP_CYCLES相同或更大的值。3.2.2 FRO管理寄存器健康状态监控TRNG的健壮性依赖于足够多的FRO正常工作。模块内置了FRO告警机制。FROEN.FRO_MASK24位每位控制一个FRO的开关。默认全开0x00FFFFFF。ALARMCNT.ALARM_THR告警阈值。当一个FRO的输出在连续多个采样周期内呈现重复模式如0,1,0,1则认为该FRO可能与采样时钟发生“锁定”熵质量下降。连续检测到重复模式的次数超过此阈值则触发告警。ALARMMASK记录哪个FRO触发了告警。ALARMSTOP如果某个FRO在已经告警ALARMMASK对应位为1的情况下再次告警则其对应的ALARMSTOP位被置1并且该FRO被强制关闭FROEN中对应位被硬件清零。ALARMCNT.SHUTDOWN_THRFRO关闭数量阈值。当被关闭的FRO数量即ALARMSTOP中1的位数超过此阈值会触发SHUTDOWN_OVF中断提示系统TRNG的熵源质量可能已严重下降。FRO去调谐FRODETUNE寄存器。将某个FRO对应的位置1可使其运行频率加快约5%这有助于打破FRO与采样时钟之间的频率锁定。重要规则只能在该FRO被关闭FROEN对应位为0时修改其FRODETUNE位。3.2.3 中断与状态寄存器IRQFLAGSTAT.RDY随机数就绪标志。当新的64位随机数已存入OUT0/OUT1时置位。IRQFLAGSTAT.SHUTDOWN_OVFFRO关闭溢出标志。IRQFLAGMASK对应中断的使能位。IRQFLAGCLR写1清除对应的状态标志。3.3 TRNG实战编程轮询与中断模式3.3.1 初始化序列以下是基于寄存器操作的高安全级别TRNG初始化代码。假设系统时钟48MHz目标启动熵积累时间约5ms。#define TRNG_BASE 0x40028000 #define TRNG_SWRESET (*(volatile uint32_t *)(TRNG_BASE 0x1FF0)) #define TRNG_CTL (*(volatile uint32_t *)(TRNG_BASE 0x0014)) #define TRNG_CFG0 (*(volatile uint32_t *)(TRNG_BASE 0x0018)) #define TRNG_FROEN (*(volatile uint32_t *)(TRNG_BASE 0x0020)) #define TRNG_ALARMCNT (*(volatile uint32_t *)(TRNG_BASE 0x001C)) void TRNG_InitHighSecurity(void) { // 步骤1执行软件复位并等待复位完成 TRNG_SWRESET 0x1; while((TRNG_SWRESET 0x1) ! 0); // 轮询等待复位完成 // 步骤2配置采样分频每个时钟采样一次 uint32_t cfg0Value 0; cfg0Value ~(0xF 8); // 清除SMPL_DIV位域 cfg0Value | (0x0 8); // SMPL_DIV 0 TRNG_CFG0 cfg0Value; // 步骤3配置启动周期 (目标 ~5ms 48MHz) // 计算: 5ms * 48e6 Hz 240,000 次采样 // STARTUP_CYCLES 采样次数 / 28 240000 / 28 ≈ 8571 (0x217B) uint32_t startupCycles 8571; uint32_t ctlValue (startupCycles 16); // 步骤4配置重填周期使用最大值确保熵一致 // 设置 MIN_REFILL_CYCLES 0 使用 MAX_REFILL_CYCLES 控制 cfg0Value ~(0xFFFF 16); // 清除 MAX_REFILL_CYCLES cfg0Value | (startupCycles 16); // 使用与启动相同的周期 cfg0Value ~(0xFF); // 清除 MIN_REFILL_CYCLES // MIN_REFILL_CYCLES 0 表示使用 MAX_REFILL_CYCLES 作为固定重填周期 TRNG_CFG0 cfg0Value; // 步骤5配置告警阈值使用默认值0xFF较高的容错性 TRNG_ALARMCNT 0x000000FF; // ALARM_THR 0xFF // 步骤6配置FRO关闭阈值例如允许最多关闭6个FRO uint32_t alarmcnt TRNG_ALARMCNT; alarmcnt ~(0x1F 16); // 清除 SHUTDOWN_THR 位域 alarmcnt | (6 16); // SHUTDOWN_THR 6 TRNG_ALARMCNT alarmcnt; // 步骤7使能所有FRO TRNG_FROEN 0x00FFFFFF; // 24个FRO全开 // 步骤8使能TRNG模块开始熵积累 ctlValue | (1 10); // TRNG_EN 1 TRNG_CTL ctlValue; // 步骤9可选使能中断 // 如果需要中断方式获取随机数在此配置 NVIC 和 IRQFLAGMASK }3.3.2 轮询模式获取随机数轮询模式简单直接适用于不频繁获取随机数且对实时性要求不高的场景。uint64_t TRNG_GetRandomNumberPolling(void) { volatile uint32_t *pOut0 (volatile uint32_t *)(TRNG_BASE 0x0000); volatile uint32_t *pOut1 (volatile uint32_t *)(TRNG_BASE 0x0004); volatile uint32_t *pIrqFlagStat (volatile uint32_t *)(TRNG_BASE 0x0008); volatile uint32_t *pIrqFlagClr (volatile uint32_t *)(TRNG_BASE 0x0010); uint64_t randomValue 0; uint32_t status; // 轮询等待 RDY 标志置位 do { status *pIrqFlagStat; } while ((status 0x1) 0); // 等待 RDY (bit 0) 为1 // 读取随机数先读低字再读高字 randomValue (uint64_t)(*pOut0); randomValue | ((uint64_t)(*pOut1) 32); // 清除 RDY 标志启动下一次熵积累 *pIrqFlagClr 0x1; // 写1清除 RDY 位 return randomValue; }3.3.3 中断模式与健康状态监控对于需要高效、异步获取随机数或需要监控TRNG健康状态的应用中断模式更合适。// 全局变量用于传递随机数 volatile uint64_t g_trngRandomNumber 0; volatile bool g_trngDataReady false; volatile bool g_trngFroError false; void TRNG_EnableInterrupt(void) { volatile uint32_t *pIrqFlagMask (volatile uint32_t *)(TRNG_BASE 0x000C); // 使能 RDY 和 SHUTDOWN_OVF 中断 *pIrqFlagMask (1 1) | (1 0); // SHUTDOWN_OVF_MASK1, RDY_MASK1 // 配置并使能 NVIC 中断 (此处需根据具体CMSIS版本编写) NVIC_EnableIRQ(TRNG_IRQn); } void TRNG_IRQHandler(void) { volatile uint32_t *pIrqFlagStat (volatile uint32_t *)(TRNG_BASE 0x0008); volatile uint32_t *pIrqFlagClr (volatile uint32_t *)(TRNG_BASE 0x0010); volatile uint32_t *pOut0 (volatile uint32_t *)(TRNG_BASE 0x0000); volatile uint32_t *pOut1 (volatile uint32_t *)(TRNG_BASE 0x0004); volatile uint32_t *pAlarmMask (volatile uint32_t *)(TRNG_BASE 0x0028); volatile uint32_t *pAlarmStop (volatile uint32_t *)(TRNG_BASE 0x002C); volatile uint32_t *pFroDetune (volatile uint32_t *)(TRNG_BASE 0x0024); volatile uint32_t *pFroEn (volatile uint32_t *)(TRNG_BASE 0x0020); uint32_t status *pIrqFlagStat; // 处理随机数就绪中断 if (status 0x1) { // RDY g_trngRandomNumber (uint64_t)(*pOut0); g_trngRandomNumber | ((uint64_t)(*pOut1) 32); g_trngDataReady true; *pIrqFlagClr 0x1; // 清除 RDY 标志 } // 处理 FRO 关闭溢出中断健康状态告警 if (status 0x2) { // SHUTDOWN_OVF g_trngFroError true; uint32_t alarmMask *pAlarmMask; uint32_t alarmStop *pAlarmStop; // 处理策略尝试对已关闭的FRO进行去调谐并重新启用 for (int i 0; i 24; i) { if ((alarmStop i) 0x1) { // FRO i 已被关闭 // 1. 确保它在FROEN中被禁用硬件已做 // 2. 尝试去调谐加快5% uint32_t detune *pFroDetune; detune | (1 i); *pFroDetune detune; // 3. 重新启用该FRO uint32_t en *pFroEn; en | (1 i); *pFroEn en; } } // 清除告警记录 *pAlarmMask 0x0; *pAlarmStop 0x0; // 清除 SHUTDOWN_OVF 中断标志 *pIrqFlagClr 0x2; } }4. 系统集成与高级应用注意事项4.1 低功耗模式下的协同工作在物联网设备中MCU大部分时间处于睡眠状态。WDT和TRNG在此场景下的行为需要仔细考量。WDT与低功耗WDT时钟来自INFRASTRUCTURE只要该时钟域在睡眠模式下保持活动WDT就继续计数。在CC13x2/CC26x2中通常的待机模式下该时钟是活动的。在进入深度睡眠前必须评估WDT超时时间与预计睡眠时长。如果睡眠时间可能超过WDT超时时间则需要在进入睡眠前“喂狗”或者使用具有更长超时时间的低功耗定时器来唤醒并“喂狗”。切勿在中断服务程序中长期关闭全局中断而不“喂狗”这可能导致看门狗超时。TRNG与低功耗TRNG模块本身在空闲时会自动关闭FRO以省电由MAX_REFILL_CYCLES控制超时。当MCU进入深度睡眠时TRNG的模块时钟可能被关闭。TI手册指出直接关闭时钟不会破坏已积累的熵但重新上电后在生成新随机数前必须执行一次软件复位以确保随机性安全。推荐做法在进入深度睡眠前如果确定短期内不需要随机数可以写TRNG_CTL.TRNG_EN 0主动关闭TRNG然后关闭其时钟以最大化省电。唤醒后执行TRNG软件复位再重新初始化。4.2 安全应用实践从随机数到密钥获取到TRNG产生的随机数后直接将其作为加密密钥使用并不总是安全的还需要进行后处理。熵提取虽然TRNG内部有熵积累过程但输出可能仍存在微小偏差。对于极高安全要求应使用密码学安全的熵提取函数或确定性随机比特生成器。健康检查在生成关键密钥前应检查TRNG的健康状态。读取ALARMSTOP寄存器确认关闭的FRO数量未超过安全阈值例如24个中关闭数量少于6个。可以定期调用一个自检函数。连续随机数测试对于非关键应用可以简单地对连续生成的多个随机数进行统计测试如重复值检查作为基本的健康判断。bool TRNG_HealthCheck(void) { volatile uint32_t *pAlarmStop (volatile uint32_t *)(TRNG_BASE 0x002C); volatile uint32_t *pHwOpt (volatile uint32_t *)(TRNG_BASE 0x0078); uint32_t stoppedFros *pAlarmStop; uint32_t totalFros (*pHwOpt 6) 0x3F; // 读取 NR_OF_FROS 字段 int stoppedCount __builtin_popcount(stoppedFros); // 计算1的位数 // 如果超过1/4的FRO停止工作认为健康状态不佳 if (stoppedCount (totalFros / 4)) { return false; } return true; }4.3 常见问题与调试技巧WDT不复位检查时钟确认PRCM模块已正确使能WDT的外设时钟。检查LOCK确认配置后已正确上锁。可以读取LOCK寄存器若值为0x1表示已锁。检查复位源超时后查看PRCM:WARMRESET.WDT_STAT位是否被置位以确认复位是由WDT触发的。TRNG读取值总是0或固定值检查使能确认TRNG_EN位已置1并且已等待足够的启动时间检查IRQFLAGSTAT.RDY。检查时钟TRNG模块时钟必须使能PRCM:SECDMACLKGR.TRNG_CLK_EN。检查FRO读取FROEN寄存器确认不是所有FRO都被禁用。检查ALARMSTOP看是否大量FRO因告警被关闭。TRNG产生随机数的速度慢调整周期减小STARTUP_CYCLES和MAX_REFILL_CYCLES但这会牺牲熵质量。检查SMPL_DIV确保其为0以获得最高采样率。使用中断而非轮询轮询RDY标志会消耗CPU资源且可能引入延迟。系统异常复位后如何定位原因利用WDT中断服务程序在复位前将错误代码、程序计数器PC、链接寄存器LR等关键信息写入一个保留的RAM区域该区域在复位时不会被初始化或者被备份寄存器保留。在系统启动代码中首先检查这个保留区域是否有有效的错误码。如果有则通过串口或其他方式输出然后清除该区域再进行正常初始化。这能有效区分是看门狗复位、上电复位还是其他复位源。通过将WDT的“守护”特性与TRNG的“随机”特性结合你能够为CC13x2/CC26x2构建起一个既稳固又安全的应用基础。记住看门狗的配置关乎生死务必简单可靠随机数的质量关乎秘密务必谨慎对待。在实际项目中花费时间充分测试这两种外设在各种极端情况下的表现是避免现场故障的最佳投资。