STM32CubeIDE开发(十四), stm32的RNG随机数发生器CubeMX配置及HAL库底层实现分析

本文详细介绍了STM32的随机数发生器(RNG)的工作原理,包括RNG的结构、配置方法,以及如何在CubeMX中开启RNG功能和设置时钟。接着,文章展示了如何创建RNG测试工程,分析了HLA库源码,特别是MX_RNG_Init和HAL_RNG_MspInit函数的作用。在测试部分,文章描述了编译、下载过程,并通过按键触发不同方式获取随机数的实现,同时展示了串口输出的测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、STM32的随机数发生器

        1.1 RGN 简介

        1.2 RNG配置说明

 二、创建RNG测试工程及HLA源码分析

         2.1 工程创建

        2.3 RNG的HLA库源码分析

         2.3 RNG使用设计

三、编译及测试

        3.1 编译及下载

         3.2 测试


一、STM32的随机数发生器

        1.1 RGN 简介

        STM32的RGN(Random Number Generator,随机数发生器),是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个由模拟量发生器产生的 32 位随机数。

        RGN由实时熵源(模拟)和内部调节组件组成,它将全熵输出作为32位样本提供给应用程序。通常MCU中去读取两个连续随机数的间隔为 40 个 PLL48CLK时钟信号周期。产生随机数的模拟量发生器,由几个环形振荡器组成,振荡器的输出进行异或运算以产生馈入线性反馈移位寄存器(RNG_LFSR)种子,这些种子用于生成 32 位随机数。RGN支持中断功能,通过检测状态位(RNG_SR 寄存器),检测种子异常(RNG_FLAG_SECS)、时钟异常(RNG_SR_CECS)等现象,检测到错误时生成中断。

        1.2 RNG配置说明

        在CubeMX上开启RNG功能非常简单,只需要激活即可,在其参数栏设置无任何参数需要设置,在NVIC栏可以开启中断功能。

         RNG依赖时钟源可有在时钟树选择器设置,时钟频率大小可以通过倍频器、分频器设置,例如本文采用STM32L496VGTx芯片时,设置其PLL48CLK时钟依赖源PLLSAl1Q,输出时钟频率是48MHz,如下图所示。

         STM32的RGN内部通信通常是通过AHB总线实现,例如STM32L496VGTx芯片通过AHB2总线。

         RNG在STM32芯片正常、睡眠的工作模式下有效。

         在STM32L496VGTx芯片中,RNG的寄存器空间大小为0X3FF(1024),用于存储RNG的数据寄存器、状态寄存器、控制寄存器以及缓存参数、组件信息等。

 二、创建RNG测试工程及HLA源码分析

         2.1 工程创建

        本文为采用的是stm32L496VGTx-ali开发板来建立测试工程,并按本专栏前面的博文移植好了lpuart1串口调试及按键功能,请自行参考。

cubeIDE开发, stm32调试信息串口通信输出显示_py_free的博客-CSDN博客_调试信息输出到串口
现双击.ioc文件,打开CubeMX配置界面,开启RNG功能,并开启中断,时钟树上设置最终输出频率48MHz。

         保存生成输出代码。

        2.3 RNG的HLA库源码分析

        cubeMX生成代码时,会在Core源码目录下的Inc及Src目录,分别生成rng.h和rng.c驱动文件。

        在rng.c文件中,主要定义了MX_RNG_Init函数和HAL_RNG_MspInit函数。MX_RNG_Init主要做两件事情,一是生成RNG句柄Instance(寄存器),二是调用HLA库的HAL_RNG_Init来实现真正的初始化设定。HAL_RNG_MspInit是HLA内的弱函数,根据实际配置CubeMX会生成新的函数,完成真正的MCU底层设置任务(MspInit,MCU Specific Package init,即指和MCU相关的初始化),覆盖原来的弱函数,而在HAL_RNG_Init函数中会调用到HAL_RNG_MspInit函数。

         在stm32l4xx_hal_rng.c源文件中定义了HAL_RNG_Init函数,它做以下事情:诊断配置参数是否合规;

         以及调用HAL_RNG_MspInit函数完成CRC时钟开启及中断设置与开启(如果cubeMX配置开启中断功能的话);

        最后开启RNG,检测种子、数据寄存器的有效性。

         再回到rng.c内,HAL_RNG_MspInit函数实现了RNG外设时钟设置(如果配置依赖外设的话)与开启,以及中断设置与开启(如果cubeMX配置开启中断功能的话)。

         在stm32l4xx_hal_rng.c源文件除了定义初始化功外,还定义了RNG的MSP初始化及删除函数,各种方式读取随机数函数,状态读取函数,中断请求及中断回调函数等。较常用的是:读取随机数函数如HAL_RNG_GetRandomNumber、HAL_RNG_GetRandomNumber_IT、HAL_RNG_ReadLastRandomNumber,状态读取函数HAL_RNG_GetState,以及回调函数HAL_RNG_ReadyDataCallback和HAL_RNG_ErrorCallback。

         2.3 RNG使用设计

        由于本文开启了RNG中断功能,在rng.c源码中,重新编码HAL_RNG_ReadyDataCallback函数如下:

/* USER CODE BEGIN 1 */
void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
{
	printf("RNG_ReadyDataCallback:%lu\r\n",random32bit);
}
/* USER CODE END 1 */

         在main.c源码文件中,添加各个外设及功能模块的头文件依赖。

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "../../ICore/key/key.h"
#include "../../ICore/led/led.h"
#include "../../ICore/print/print.h"
#include "../../ICore/usart/usart.h"
#include "../../ICore/delay/delay.h"
/* USER CODE END Includes */

         在main.c源码文件中,添加RNG句柄声明,用于读取随机数时使用。

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
extern RNG_HandleTypeDef hrng;
/* USER CODE END 0 */

         在main函数内,启动串口中断功能及初始化其他辅助参数。

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LPUART1_UART_Init();
  MX_RNG_Init();
  /* USER CODE BEGIN 2 */
  ResetPrintInit(&hlpuart1);
  HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
  HLPUSART_RX_STA = 0;
  //
  printf("app restart now!\r\n");
  uint32_t rng_val = 0;
  /* USER CODE END 2 */

        在main函数循环体内,通过按键触发调用不同的随机数获取函数,并打印输出到lpuart1上。

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  	  if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始
  		  //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
  		  HLPUSART_RX_STA=0;//接收错误,重新开始
  		  HAL_Delay(100);//等待
  	  }
	  if(KEY_0())
	  {
		  rng_val = HAL_RNG_GetRandomNumber(&hrng);
		  printf("KEY_0->RNG_GetRandomNumber:%lu\r\n",rng_val);
	  }
	  if(KEY_1())
  	  {
		  rng_val = HAL_RNG_GetRandomNumber_IT(&hrng);
		  printf("KEY_1->RNG_GetRandomNumber_IT:%lu\r\n",rng_val);
  	  }
	  if(KEY_2())
  	  {
		  rng_val = HAL_RNG_ReadLastRandomNumber(&hrng);
		  printf("KEY_2->RNG_ReadLastRandomNumber:%lu\r\n",rng_val);
  	  }
    /* USER CODE END WHILE */

三、编译及测试

        3.1 编译及下载

        点击编译按钮确保编译正确输出,并配置运行配置后,点击运行完成下载

         3.2 测试

        串口助手链接到开发板上,分别按键KEY0、KEY1、KEY2输出log如下图:

         由于KEY1是中断方式读取随机数,因此我们前面重写的回调函数也会生效,但需要注意的是HAL_RNG_GetRandomNumber_IT先于HAL_RNG_ReadyDataCallback,读取了数据寄存器,连个函数是分别读取数据寄存器,因此得到的随机数是不一致的,实际项目中按需选择来应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

py_free-物联智能

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值