文章目录
- 一、RNG 随机数生成器原理
- 1.1 什么是 RNG?
- 1.2 工作原理与寄存器操作
- 二、偏差纠正
- 2.1 偏差纠正机制
- 2.2 配置与影响
- 三、速度
- 四、常用函数
- 4.1 random_vector_generate
- 4.1.1 函数原型
- 4.1.2 参数说明
- 五、示例代码
- 5.1 bsp_rng.c
- 5.1.1 错误处理说明
- 5.2 bsp_rng.h
- 六、常见问题与排查
- 6.1 VALRDY 一直不置位
- 6.2 随机数全为 0xFF
- 6.3 偏差校正后速度过慢
- 6.4 随机数分布不均匀
- 七、总结
- 八、参考资料
一、RNG 随机数生成器原理
1.1 什么是 RNG?
随机数生成器(RNG)基于芯片内部热噪声生成真正的非确定性随机数,适用于加密、安全认证、防重放攻击等对随机性要求较高的场景。与伪随机数生成器(PRNG)不同,RNG 不需要种子值,每次生成的随机数都不可预测,安全性更高。
应用场景:RNG 常用于密钥生成、安全 Token、防重放攻击、随机延时、测试数据填充等场景。在物联网设备中,硬件 RNG 是保障通信安全的重要基础组件。
1.2 工作原理与寄存器操作
通过触发START任务启动 RNG,通过触发STOP任务停止 RNG。当启动时,新的随机数将连续生成,并在准备就绪时写入VALUE寄存器。每个写入VALUE寄存器的新随机数都会生成一个VALRDY事件。这意味着在生成VALRDY事件后,CPU 有时间直到下一个VALRDY事件从VALUE寄存器读出随机数,然后再被一个新的随机数覆盖。
| 寄存器/任务 | 作用 |
|---|---|
TASKS_START | 启动 RNG,开始生成随机数 |
TASKS_STOP | 停止 RNG,停止生成随机数 |
VALUE | 存放最新生成的随机数值(8 位) |
EVENTS_VALRDY | 新随机数就绪事件标志 |
CONFIG | 配置偏差校正等参数 |
提示:
VALRDY事件是读取随机数的关键信号,建议在驱动中通过中断或轮询方式及时响应,避免数据被覆盖导致随机数丢失。
二、偏差纠正
2.1 偏差纠正机制
在内部比特流上使用偏差校正算法,以消除对'1'或'0'的任何偏差。然后,这些位被排到一个 8 位寄存器中,以便从VALUE寄存器并行读出。偏差校正算法基于冯·诺依曼(von Neumann)校正器原理,通过丢弃连续相同的比特对来消除统计偏差,从而保证输出的随机数在统计上均匀分布。
2.2 配置与影响
可以在CONFIG寄存器中启用偏差校正。这将导致较慢的值生成,但将确保随机值的统计均匀分布。开发者需要根据实际应用场景权衡:对于安全敏感场景(如密钥生成、Token 生成),建议启用偏差校正以保证随机性质量;对于对速度要求较高、随机性要求相对宽松的场景(如噪声填充、测试数据),可以关闭偏差校正以提升生成速度。
三、速度
生成一个随机字节数据所需的时间是不可预测的,并且可能随字节的不同而变化。当启用偏差校正时尤其如此,因为校正算法会丢弃部分比特,导致有效比特率下降。因此,RNG 不适合用于对时序要求严格的场景(如高速数据流加密),更适合用于低频次、高安全性的随机数获取场景。
四、常用函数
4.1 random_vector_generate
4.1.1 函数原型
voidrandom_vector_generate(uint8_t*pbuff,uint8_tsize);4.1.2 参数说明
| 参数 | 说明 |
|---|---|
| pbuff | 指向存储随机数的缓冲区 |
| size | 需要生成的随机数个数 |
五、示例代码
5.1 bsp_rng.c
/******************************************************************************** * @file bsp_rng.c * @author jianqiang.xue * @version V1.0.0 * @date 2021-07-09 * @brief 随机数生成 ********************************************************************************//* Includes ------------------------------------------------------------------*/#include<stdint.h>#include<stdbool.h>#include"RTE_Components.h"#includeCMSIS_device_header#include"nrf_rng.h"#include"nrf_error.h"#include"bsp_rng.h"/* Private macro --------------------------------------------------------------*/#defineRNG_TIMEOUT_LOOPS1000000u/* 超时保护:等待 VALRDY 的最大循环次数 *//* Private function prototypes -----------------------------------------------*//** * @brief 启动硬件随机数,并返回一个随机数值 * @note 增加超时保护,防止硬件异常时死循环 * @retval 0-255 随机数;超时返回 0xFF */staticuint8_tget_random_vector(void){uint8_tvalue;uint32_ttimeout=RNG_TIMEOUT_LOOPS;NRF_RNG->CONFIG=1;NRF_RNG->TASKS_START=1;// 生成新的随机数并写入VALUE寄存器。NRF_RNG->EVENTS_VALRDY=0;while(NRF_RNG->EVENTS_VALRDY==0){if(--timeout==0u){// 超时:停止 RNG 并返回错误标志,避免死循环NRF_RNG->TASKS_STOP=1;NRF_RNG->INTENCLR=0;NRF_RNG->CONFIG=0;return0xFFu;/* 0xFF 作为超时错误标志 */}}value=NRF_RNG->VALUE;NRF_RNG->TASKS_STOP=1;NRF_RNG->INTENCLR=0;NRF_RNG->CONFIG=0;returnvalue;}/** * @brief 得到一组随机数 * @note 超时保护:若硬件异常导致 get_random_vector 返回 0xFF,则填充 0xFF 并继续 * @param *pbuff: 缓存区 * @param size: 数量 * @retval None */voidrandom_vector_generate(uint8_t*pbuff,uint8_tsize){uint8_ti;for(i=0;i<size;i++){pbuff[i]=get_random_vector();}}5.1.1 错误处理说明
- 超时保护:
get_random_vector内部通过RNG_TIMEOUT_LOOPS宏(默认 1000000 次循环)限制等待VALRDY事件的时间。若硬件异常导致VALRDY一直未置位,循环会在超时后退出,避免程序死锁。 - 超时返回值:超时后函数返回
0xFF作为错误标志。调用方random_vector_generate会将0xFF写入缓冲区,上层应用可通过判断0xFF来识别本次随机数获取失败。 - 资源清理:无论正常返回还是超时退出,函数都会执行
TASKS_STOP、INTENCLR、CONFIG复位操作,确保 RNG 外设处于停止状态,避免影响后续调用。 - 适用场景:该保护机制在硬件异常、时钟配置错误或外设未正确初始化时尤为重要,可显著提升系统的健壮性与可维护性。
5.2 bsp_rng.h
/******************************************************************************** * @file bsp_rng.h * @author jianqiang.xue * @version V1.0.0 * @date 2021-07-09 * @brief 随机数生成 ********************************************************************************/#ifndef__BSP_RNG_H#define__BSP_RNG_H/* Includes ------------------------------------------------------------------*/#include<stdint.h>/* Public Function Prototypes ------------------------------------------------*/voidrandom_vector_generate(uint8_t*pbuff,uint8_tsize);#endif六、常见问题与排查
在实际开发中,RNG 外设的使用可能会遇到各种异常情况。下面列举几个典型问题,并给出对应的排查步骤与解决方案。
6.1 VALRDY 一直不置位
现象:调用get_random_vector后,EVENTS_VALRDY始终为 0,程序一直停留在等待循环中(若未加超时保护则会死锁)。
可能原因:
- RNG 外设时钟未使能,导致外设无法工作;
- 未正确触发
TASKS_START,或触发后立即被复位; - 芯片处于低功耗模式,RNG 外设被关闭;
- 硬件异常或芯片损坏。
排查步骤:
- 检查时钟配置,确认 RNG 外设的时钟源已使能;
- 确认
TASKS_START已正确写入 1,且未被后续代码误清零; - 检查是否在低功耗模式下调用 RNG,必要时先唤醒外设;
- 使用调试器读取
POWER、CLOCK相关寄存器,确认外设供电正常。
解决方案:
- 确保在调用 RNG 前完成外设初始化与时钟使能;
- 在驱动中增加超时保护(如本文
RNG_TIMEOUT_LOOPS宏),避免死循环; - 若确认硬件异常,可考虑切换到软件伪随机数生成器(PRNG)作为降级方案。
6.2 随机数全为 0xFF
现象:random_vector_generate填充的缓冲区全部为0xFF。
可能原因:
get_random_vector超时退出,返回0xFF作为错误标志;VALUE寄存器读取时序错误,读到复位默认值;- 偏差校正配置异常,导致输出被截断。
排查步骤:
- 在
get_random_vector超时分支处打断点,确认是否超时退出; - 检查
CONFIG寄存器配置,确认偏差校正位设置是否正确; - 用调试器直接读取
VALUE寄存器,验证硬件是否正常输出随机数; - 检查
EVENTS_VALRDY是否在读取前被正确清零。
解决方案:
- 若为超时导致,按 6.1 节排查硬件与时钟问题;
- 若为读取时序问题,确保在
VALRDY置位后立即读取VALUE,并在读取前清零事件标志; - 上层应用可增加对
0xFF的校验,若连续多次失败则报错并重试。
6.3 偏差校正后速度过慢
现象:启用偏差校正后,生成随机数的速度明显下降,无法满足应用需求。
可能原因:
- 偏差校正算法会丢弃部分比特对,导致有效比特率下降;
- 应用对随机数的需求量较大,而 RNG 本身吞吐有限;
- 轮询方式读取
VALRDY事件,CPU 空转浪费大量时间。
排查步骤:
- 统计单位时间内生成的随机数字节数,评估实际吞吐;
- 对比关闭偏差校正前后的速度差异,确认瓶颈是否在偏差校正;
- 检查是否使用中断方式读取
VALRDY,避免轮询空转。
解决方案:
- 对于安全敏感场景,保留偏差校正以保证随机性质量;
- 对于速度敏感场景,可关闭偏差校正(
CONFIG寄存器清零); - 改用中断或 DMA 方式读取随机数,减少 CPU 等待时间;
- 若吞吐仍不足,可考虑在系统初始化时预生成一批随机数缓存备用。
6.4 随机数分布不均匀
现象:生成的随机数在统计上出现明显偏向,某些值出现频率过高。
可能原因:
- 未启用偏差校正,内部比特流存在统计偏差;
- 读取时序错误,导致部分比特丢失;
- 外部干扰影响热噪声源质量。
排查步骤:
- 采集大量随机数样本,进行简单的分布统计;
- 确认
CONFIG寄存器中偏差校正位已正确使能; - 检查 PCB 布局,确认 RNG 相关引脚无强干扰源。
解决方案:
- 启用偏差校正,消除统计偏差;
- 确保读取时序正确,避免数据覆盖或丢失;
- 若为硬件干扰,优化 PCB 布局或增加屏蔽措施。
七、总结
本文围绕 nRF5 系列芯片的硬件随机数生成器(RNG)展开,从原理到代码实现进行了系统梳理,核心要点如下:
- 工作原理:RNG 基于芯片内部热噪声生成真正的非确定性随机数,无需种子值。通过触发
START任务启动、STOP任务停止,新随机数在就绪后写入VALUE寄存器,并产生VALRDY事件通知 CPU 读取。 - 偏差纠正:内部比特流经偏差校正算法处理后,可消除对
'1'或'0'的统计偏差,确保随机值均匀分布。该功能通过CONFIG寄存器启用,代价是生成速度变慢。 - 速度特性:生成单个随机字节所需时间不可预测,启用偏差纠正后尤为明显,因此不适合对时序要求严格的场景。
- 代码实现要点:
- 封装了
random_vector_generate接口,通过get_random_vector逐字节获取随机数并填充缓冲区; - 为
get_random_vector增加了超时保护机制(RNG_TIMEOUT_LOOPS),防止硬件异常时陷入死循环,超时返回0xFF作为错误标志; - 无论正常返回还是超时退出,均会复位
TASKS_STOP、INTENCLR、CONFIG,确保外设状态干净,提升系统健壮性。
- 封装了
八、参考资料
- Nordic Semiconductor 官方文档 - RNG 外设说明
- nRF5 SDK 官方文档与 API 手册
- nRF52832 数据手册(Product Specification)
- CSDN 博客:nRF5 系列 RNG 随机数生成器使用详解
- CSDN 博客:nRF52832 外设驱动开发实战——RNG 篇