【正点原子MP157连载】第二十章 硬件随机数实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南

本文主要是介绍【正点原子MP157连载】第二十章 硬件随机数实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1)实验平台:正点原子STM32MP157开发板
2)购买链接:https://item.taobao.com/item.htm?&id=629270721801
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-318813-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子STM32MP157技术交流群:691905614
在这里插入图片描述

第二十章 硬件随机数实验

本章,我们将介绍STM32MP157的硬件随机数发生器。我们使用KEY0按键来获取硬件随机数,并且将获取到的随机数值通过串口打印出来。同时,使用LED0指示程序运行状态。
本章分为如下几个小节:
20.1、 随机数发生器简介;
20.2、 硬件设计;
20.3、 软件设计;
20.4、 编译和测试;

20.1 随机数发生器简介
STM32MP157自带了硬件随机数发生器(RNG),其中RNG1给A7内核使用,RNG2给M4内核使用。RNG处理器是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个32位的随机数。
20.1.1 RNG框图
下面先来学习RNG框图,通过学习RNG框图会有一个很好的整体掌握,同时对之后的编程也会有一个清晰的思路。STM32MP157的随机数发生器框图如下图所示:
在这里插入图片描述

图20.1.1. 1随机数发生器(RNG)框图
随机数发生器有2个时钟域:AHB时钟域和RNG时钟域。AHB 时钟用于为 AHB 存储寄存器和调节组件提供时钟信号,RNG 时钟用于噪声源采样。如果 RNG_CR 寄存器中的 CED 位设置为“0”了,即启用时钟错误检测,那么 RNG 时钟频率 必须大于 AHB 时钟频率的32 分之一,否则时钟检查器会指示时钟错误,RNG 将停止生成随机数。在配置时钟时,注意此范围。
RNG时钟域时钟为rng_clk,rng_clk由RCC_RNG2CKSELR寄存器的RNG2SRC[1:0]位选择具体的时钟源,具体选择关系为:
0x0: csi_ker_ck
0x1: pll4_r_ck
0x2: lse_ck clock
0x3: lsi_ck
默认情况下STM32CubeMX会选择0x0: csi_ker_ck(4 MHz)作为rng_clk的时钟源,最大可通过PLL4配置为48MHz:
在这里插入图片描述

图20.1.1. 2 RNG2默认采用CSI作为时钟源
AHB时钟域的时钟来自AHB3(最大为209MHz),用于访问相关寄存器等,通过RCC_MC_AHB3ENSETR的RNG2EN位(bit6)使能。可见,4MHz小于209/32,如果开启时钟错误检测,注意配置RNG2的时钟范围。
在这里插入图片描述

图20.1.1. 3 RNG时钟
RCC_RNG2CKSELR和RCC_MC_AHB3ENSETR这两个寄存器我们就不做介绍了,大家参考手册。从RNG框图整体上知道,RNG有两个输入和一个输出。具体如下表:
在这里插入图片描述

表20.1.1. 1 RNG内部输入/输出信号
STM32MP157的随机数发生器(RNG)采用模拟电路实现,由内部两个模拟噪声源产生种子,经过采样和归一化处理,再经过线性移位寄存器和判断逻辑,最终输出到RNG_DR,生成32 位随机数。
每个模拟噪声源由3个环形振荡器组成,振荡器产生的输出经过异或运算产生种子,经过采样归一化处理后,输出到RNG内部的线性移位寄存器。采样频率由rng_clk时钟提供,因此,随机数质量与 HCLK 频率无关。当将大量种子引入线性移位寄存器后,经过判断逻辑,最终输出到数据寄存器 (RNG_DR)。
同时,系统会监视模拟种子和专用时钟 rng_clk,当种子上出现异常序列,或rng_clk时钟频率过低时,可以由RNG_SR寄存器的对应位读取到,如果设置了中断,则在检测到错误时,还可以产生中断。
20.1.2 RNG寄存器

  1. RNG控制寄存器(RNG_CR)
    RNG控制寄存器描述如下图所示:
    在这里插入图片描述

图20.1.2. 1 RNG_CR寄存器
该寄存器我们只关心RNGEN位,该位用于使能随机数发生器,所以必须设置为1。
2. RNG状态寄存器(RNG_SR)
RNG状态寄存器描述如下图所示:
在这里插入图片描述

图20.1.2. 2 RNG_SR寄存器
该寄存器我们仅关心最低位(DRDY位),该位用于表示RNG_DR寄存器包含的随机数数据是否有效,如果该位为1,则说明RNG_DR的数据是有效的,可以读取出来了。读RNG_DR后,该位自动清零。
3. RNG数据寄存器(RNG_DR)
RNG数据寄存器描述如下图所示:
在这里插入图片描述

图20.1.2. 3 RNG_DR寄存器
RNG_DR寄存器是只读寄存器,我们可以读取该寄存器获得32位随机数值。此寄存器在最多216个AHB时钟周期后,又可以提供新的随机数值。
20.1.3 RNG的HAL库驱动
RNG在HAL库中的驱动代码在stm32mp1xx_hal_rng.c文件(及其头文件)中。

  1. HAL_RNG_Init函数
    RNG的初始化函数,其声明如下:
HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng);
●函数描述:用于初始化RNG。
●函数形参:形参1是RNG_HandleTypeDef结构体类型指针变量,其定义如下:
typedef struct
{RNG_TypeDef                   *Instance;    /* RNG基地址 */RNG_InitTypeDef               Init;         /* RNG初始化配置结构体 */HAL_LockTypeDef               Lock;         /* RNG锁设置 */__IO HAL_RNG_StateTypeDef   State;        /* RNG设备访问状态 */__IO  uint32_t                ErrorCode;    /* RNG错误代码 */uint32_t                      RandomNumber; /* RNG最后生成的随机数 */
} RNG_HandleTypeDef;1)Instance:指向RNG寄存器基地址。2)Init:是的RNG初始化结构体,其结构体类型RTC_InitTypeDef定义如下:
typedef struct
{uint32_t            ClockErrorDetection; /* CED时钟错误检测 */
} RNG_InitTypeDef;
3)Lock:用于配置锁状态。
4)State:RNG设备访问状态。
5)ErrorCode :RNG错误代码
6)RandomNumber :该变量存储RNG最后生成的随机数

●函数返回值:
HAL_StatusTypeDef枚举类型的值。
2. HAL_RNG_GenerateRandomNumber函数
HAL_RNG_GenerateRandomNumber是RNG生成随机数函数。其声明如下:
HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng,
uint32_t *random32bit);
●函数描述:
该函数用于RNG生成随机数。
●函数形参:
形参1是RNG_HandleTypeDef结构体类型指针变量,即RNG的句柄。
形参2是uint32_t类型指针变量,随机32位指针,生成随机变量。
●函数返回值:
HAL_StatusTypeDef枚举类型的值。
20.2 硬件设计

  1. 例程功能
    本实验使用STM32MP157自带的硬件随机数生成器(RNG),获取随机数,并通过串口打印出来。按KEY0可以获取一次随机数。同时程序自动获取0~9范围内的随机数,显示在屏幕上。LED0闪烁用于提示程序正在运行。
  2. 硬件资源
    1)LED灯:LED0
    2)独立按键 KEY0
    3)串口4
    4)RNG(硬件随机数生成器)
    LED0 KEY0 UART4_TX UART4_RX
    PI0 PG3 PG11 PB2
    表20.2. 1 硬件资源
  3. 原理图
    RNG属于STM32MP157内部资源,通过软件设置好就可以了。
    20.3 软件设计
    本实验配置好的实验工程已经放到了开发板光盘中,路径为:开发板光盘A-基础资料\1、程序源码\11、M4 CubeIDE裸机驱动例程\CubeIDE_project\ 13 RNG。
    20.3.1 程序流程图
    下面看看本实验的程序流程图:
    在这里插入图片描述

图20.3.1. 1硬件随机数实验程序流程图
20.3.2 软件配置

  1. 新建和配置工程
    本节实验可以在前面的串口通信实验的基础上实现,因为用到串口UART4,也可以重新新建一个新的工程。这里新建工程RNG,然后配置串口UART4和按键KEY0以及LED0,具体的配置步骤我们前面的实验章节都有介绍过,如果不记得配置步骤,大家可以回顾前面相关的实验章节。本节实验中,LED和按键只用到LED0和KEY0,其它LED和按键没有用到,如果直接使用前面BSP文件夹里的led.c、led.h、ket.h和key.c文件的话,可以直接将其他LED和按键也一起配置了。
    (1)GPIO配置
    LED0和KEY0配置如下:
    在这里插入图片描述

图20.3.2. 1 LE0和KEY0配置
UART4配置如下:
在这里插入图片描述

图20.3.2. 2 UART4配置
(2)NVIC配置:
UART4参数使用默认配置:
在这里插入图片描述

图20.3.2. 3 UART4参数配置
我们使用串口中断,先开启串口全局中断,
在这里插入图片描述

图20.3.2. 4 开启UART4全局中断
串口中断优先级配置如下:
在这里插入图片描述

图20.3.2. 5 配置UART4中断优先级
下面,我们直接配置RNG2:
(3)配置RNG2
如果不知道RNG在哪里,可以直接搜索RNG2:
在这里插入图片描述

图20.3.2. 6 查找RNG2
在SecurityRNG2下找到RNG2的配置,按照如下图配置,先勾选Cortex-M4,再选择Activated,即激活随机数发生器。其它配置保持默认,实际上RNG没有其它参数需要配置的。这里,我们不开启时钟错误检测:
在这里插入图片描述

图20.3.2. 7 配置RNG2
(4)配置时钟
RRNG2时钟默认采用CSI的时钟,其它时钟也可以保持默认配置。这里就保持和前面一样的配置,配置PCLK1最大为104.5MHz:
在这里插入图片描述

图20.3.2. 8 配置时钟
(5)配置生成独立的.c和.h文件
在这里插入图片描述

图20.3.2. 9配置生成独立的文件
2. 生成工程
以上的配置检查无误后,按下键盘的“Ctrl+S”组合键保存配置并生成工程。将前面按键实验用到的BSP文件夹拷贝到本工程的Src目录下,只留下按键和LED相关的代码:
在这里插入图片描述

图20.3.2. 10生成工程
3. 添加用户代码
上一步操作中,我们已经将BSP文件夹拷贝到了工程中,因为本节实验只用到LED0和KEY0相关的代码,所以将其它LED1和按键的代码注释掉。当然,也可以在STM32CubeMX上将LED1和其它按键也一起配置了,这样就不需要注释这些代码了,或者也可以自己重新手动编写这部分代码。
(1)key.h、key.c、led.c和led.h的代码比较简单,这里就不列出来了,大家可以直接参考本工程中的代码。
(2)串口相关的代码可直接参考前面串口通信实验章节部分,这里就不再列出来了。
(3)RNG2初始化代码已经在rng.c文件中生成了,代码比较简单,如下:

#include "rng.h"RNG_HandleTypeDef hrng2; /* RNG2句柄 *//*** @brief       RNG底层驱动,初始化RNG2* @note        此函数会被HAL_RNG_Init()调用* @param       hrng:RNG句柄* @retval      无*/
void MX_RNG2_Init(void)
{hrng2.Instance = RNG2; /* RNG2 */hrng2.Init.ClockErrorDetection = RNG_CED_DISABLE; /* 关闭时钟错误检查 */if (HAL_RNG_Init(&hrng2) != HAL_OK) /* 初始化RNG2 */{Error_Handler();}}
/*** @brief       RNG底层驱动,时钟源设置和使能* @note        此函数会被HAL_RNG_Init()调用* @param       hrng:RNG2句柄* @retval      无*/
void HAL_RNG_MspInit(RNG_HandleTypeDef* rngHandle)
{RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};if(rngHandle->Instance==RNG2){if(IS_ENGINEERING_BOOT_MODE()){/* 外设外RNG2 */PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG2;/* 时钟源设置为CSI */PeriphClkInit.Rng2ClockSelection = RCC_RNG2CLKSOURCE_CSI;/* 初始化RCC扩展外设时钟,也就是RNG2时钟 */if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}}__HAL_RCC_RNG2_CLK_ENABLE(); /* 使能RNG2时钟 */}
}
/*** @brief       RNG底层驱动反初始化函数* @note        如果需要,可以调用此函数* @param       hrng:RNG句柄* @retval      无*/
void HAL_RNG_MspDeInit(RNG_HandleTypeDef* rngHandle)
{if(rngHandle->Instance==RNG2){__HAL_RCC_RNG2_CLK_DISABLE();/* 关闭RNG2时钟,即关闭RNG2 */}
}4)手动添加获取随机数的代码在rng.c文件中添加如下代码:
/* USER CODE BEGIN 1 */
/*** @brief       得到随机数* @param       无* @retval      获取到的随机数(32bit)*/
uint32_t rng_get_random_num(void)
{uint32_t randomnum;HAL_RNG_GenerateRandomNumber(&hrng2, &randomnum);return randomnum;
}/*** @brief       得到某个范围内的随机数* @param       min,max: 最小,最大值.* @retval      得到的随机数(rval),满足:min<=rval<=max*/
int rng_get_random_range(int min, int max)
{uint32_t randomnum;HAL_RNG_GenerateRandomNumber(&hrng2, &randomnum);return randomnum%(max-min+1) + min;
}
/* USER CODE END 1 */
以上代码比较简单,主要是通过HAL库中的HAL_RNG_GenerateRandomNumber函数获取随机数。rng_get_random_num函数主要是获取随机数,rng_get_random_range主要是返回某个范围内的随机数。
(5)修改main.c文件
#include "main.h"
#include "rng.h"
#include "usart.h"
#include "gpio.h"/* USER CODE BEGIN Includes */
#include "./BSP/Include/led.h"
#include "./BSP/Include/key.h"
/* USER CODE END Includes */void SystemClock_Config(void);int main(void)
{HAL_Init();if(IS_ENGINEERING_BOOT_MODE()){SystemClock_Config();}MX_GPIO_Init();MX_RNG2_Init();MX_UART4_Init();/* USER CODE BEGIN 2 *//* printf("请输入字符,并按下回车键结束\r\n"); */HAL_UART_Receive_IT(&huart4,&RxBuffer,1);/* 以中断方式接收函数 *//* USER CODE END 2 */while (1){/* USER CODE BEGIN 3 */uint32_t random;uint8_t t = 0, key;key = key_scan(0);if (key == KEY0_PRES){random = rng_get_random_num();printf("Random Num:%lu\r\n", random);}if ((t % 20) == 0){t = 0;LED0_TOGGLE();                    /* 每200ms,翻转一次LED0 */random = rng_get_random_range(0, 9);/* 取[0,9]区间的随机数 */printf("Random Num[0-9]:%lu\r\n", random);}HAL_Delay(10);t++;}/* USER CODE END 3 */
}
以上代码中,每隔200ms会自动打印一次[0,9]区间的随机数,同时LED0会翻转一次。如果有按键按下,那么串口就会打印获取到的随机数。

20.4 编译和测试
编译无报错,测试结果如下:
在这里插入图片描述

图20.4. 1测试结果

这篇关于【正点原子MP157连载】第二十章 硬件随机数实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/323711

相关文章

硬件基础知识——自学习梳理

计算机存储分为闪存和永久性存储。 硬盘(永久存储)主要分为机械磁盘和固态硬盘。 机械磁盘主要靠磁颗粒的正负极方向来存储0或1,且机械磁盘没有使用寿命。 固态硬盘就有使用寿命了,大概支持30w次的读写操作。 闪存使用的是电容进行存储,断电数据就没了。 器件之间传输bit数据在总线上是一个一个传输的,因为通过电压传输(电流不稳定),但是电压属于电势能,所以可以叠加互相干扰,这也就是硬盘,U盘

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

打造坚固的SSH防护网:端口敲门入门指南

欢迎来到我的博客,代码的世界里,每一行都是一个故事 🎏:你只管努力,剩下的交给时间 🏠 :小破站 打造坚固的SSH防护网:端口敲门入门指南 前言什么是端口敲门端口敲门的优点1. 增强安全性2. 动态防火墙规则3. 隐匿服务4. 改善日志管理5. 灵活性和兼容性6. 低资源消耗7. 防御暴力破解和扫描8. 便于合法用户访问9. 适用于不同类型的服务 端口敲

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统,而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备,并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线的 子设备。 标识和报告子设备的过程称为 总线枚举。 在总线枚举期间,总线驱动程序会为其子 设备创建设备对象 。  总线驱动程序本质上是同时处理总线枚

JavaWeb系列六: 动态WEB开发核心(Servlet) 上

韩老师学生 官网文档为什么会出现Servlet什么是ServletServlet在JavaWeb项目位置Servlet基本使用Servlet开发方式说明快速入门- 手动开发 servlet浏览器请求Servlet UML分析Servlet生命周期GET和POST请求分发处理通过继承HttpServlet开发ServletIDEA配置ServletServlet注意事项和细节 Servlet注

手把手教你入门vue+springboot开发(五)--docker部署

文章目录 前言一、前端打包二、后端打包三、docker运行总结 前言 前面我们重点介绍了vue+springboot前后端分离开发的过程,本篇我们结合docker容器来研究一下打包部署过程。 一、前端打包 在VSCode的命令行中输入npm run build可以打包前端代码,出现下图提示表示打包完成。 打包成功后会在前端工程目录生成dist目录,如下图所示: 把

高性能并行计算华为云实验五:

目录 一、实验目的 二、实验说明 三、实验过程 3.1 创建PageRank源码 3.2 makefile的创建和编译 3.3 主机配置文件建立与运行监测 四、实验结果与分析 4.1 采用默认的节点数量及迭代次数进行测试 4.2 分析并行化下节点数量与耗时的变化规律 4.3 分析迭代次数与耗时的变化规律 五、实验思考与总结 5.1 实验思考 5.2 实验总结 E

Sapphire开发日志 (十) 关于页面

关于页面 任务介绍 关于页面用户对我组工作量的展示。 实现效果 代码解释 首先封装一个子组件用于展示用户头像和名称。 const UserGrid = ({src,name,size,link,}: {src: any;name: any;size?: any;link?: any;}) => (<Box sx={{ display: "flex", flexDirecti

ROS2从入门到精通4-4:局部控制插件开发案例(以PID算法为例)

目录 0 专栏介绍1 控制插件编写模板1.1 构造控制插件类1.2 注册并导出插件1.3 编译与使用插件 2 基于PID的路径跟踪原理3 控制插件开发案例(PID算法)常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情:《ROS2从入门到精通》 1 控制插