你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【NUCLEO-U083RC评测】④RNG随机数发生器

[复制链接]
小萝卜啦啦啦 发布时间:2024-5-14 00:30
U0具备硬件RNG随机数发生器,相比软件算法得到的随机数,这个硬件RNG是真随机数。在加密时用它生成IV或者随机数,可以使得加密更加的安全。! S- ]9 n* R6 c' j
  B' Z: L- Z3 J, z
一、CUBE配置及函数讲解* v/ v' o; N5 L6 K0 E
工程我们还是用之前生成的基础模板
0 _; ?/ J" }6 P  n首先在cube中开启RNG% l% \+ W; F3 Y; m6 ]& A+ j
1.png
' C. j# c' M; A$ ]
# D# ~$ ~$ ~  q- I
然后配置一下时钟,RNG的始终要求必须为48Mhz,我选择使用MSI(我一开始尝试了HSI48。但是初始化通不过,没跑通,那就只有换一个)

* I$ ^, T9 T4 ?( D
3.png 5 K! {2 _( J0 p& N
1 t  q- L, Z! u* g1 {
然后把MSI的频率改成48000(也就是48M
2.png
+ q1 c. l) Y- V
然后生成代码

$ G3 ^. T5 ?* Q& l- g+ h  B
4.png " h' A3 l: l+ m* e

  j! [' r! Y, z3 `4 n
接下来开始写代码,库函数我没有在cube中修改,使用的是默认的HAL
首先看一下自动生成的代码
CUBE帮我生成了RNG的初始化函数
5.png # R% Z+ f" h" \  O7 }, `1 C2 d
/ ?; w" F( d" P- H6 {5 i* a- ~
6.png
; H$ W( T. v2 ?; p6 |

; b) G4 x% R" e: r
HAL_RNG_Init我就不进去看了,里面主要是做一些参数配置和RNG时钟enable。如果有想仔细研究的可以自行查看。当然想要研究的跟底层,我推荐更换LL库,回头配合寄存器手册,可以学习到最底层的寄存器% J9 s" B  d' j* h( K! J* L( ]+ l
$ F  k% A# W9 P0 P9 T9 `- ]! U
( @( w% e/ g( M' B7 K# R: o
现在简单讲一下HAL库我们会调用的函数

" b  R8 y9 N0 t. _
10.png
. \$ t; j6 L; i" |
, V  Y/ t4 c7 d7 x& W
阻塞式获取到随机数的函数:HAL_RNG_GenerateRandomNumber
* k4 t# p/ L# z
通过中断得到随机数:HAL_RNG_GenerateRandomNumber_IT

7 j' ?' Z1 q9 H, J
获取上一次得到过的随机数:HAL_RNG_ReadLastRandomNumber

1 X3 v2 `  c; k. F) D7 g, w* r- `
' ]9 a7 X& _4 y
从参数可以看到,我们每次获取的随机数类型是uint32_t
4 {/ ~: k8 T0 Q% o9 Y  N' v

7 x3 z2 y8 ]' D! M. ?  w4 W+ P9 m
二、阻塞式获取到随机数及获取上一次得到过的随机数

0 G1 M" A/ n& v$ f: [
首先设置一个uint32_t类型的全局变量,用于保存得到的随机数
3 `- ]/ t: b6 y8 J
  1. uint32_t randomData;
    4 G* ^$ z- z9 c2 n& }' ^; k/ A
复制代码
11.png

2 C/ V  s! P$ X, s# P, O5 ~

2 K  M* L: j( M+ N! z: @
$ {8 v  i# \7 B! t8 W9 G
初始化后就可以直接调用获取随机数函数,我做了一个测试函数,会连续调用2次获取随机数函数,并且生成后再次调用获取上一次得到过的随机数函数,看看他会不会得到两个不同的随机数。
: R3 X' d) m; E0 |$ m, Q4 b
  1. void GenerateRandomNumber_test()! G  z2 R; `: w: v! p0 l
  2. {
    1 j( V& J7 M# z/ U! Q
  3.   uint32_t lastRandomData;
    5 f5 r) y  }' ^  m' A$ o$ X
  4.   printf("GenerateRandomNumber test\r\n");2 b/ x. ?  v; s9 J

  5. ' q2 n: i' d. x# B
  6.   HAL_RNG_GenerateRandomNumber(&hrng, &randomData);$ U/ c$ K/ a) p0 }2 p4 @' n$ S0 k1 v% i
  7.   printf("GenerateRandomNumber = %04X\r\n", randomData);, Y3 x: s8 U- q9 f" @! a1 T

  8. . p- t2 x# I" [  R9 _3 ~6 n
  9.   lastRandomData = HAL_RNG_ReadLastRandomNumber(&hrng);2 k2 x7 \! _3 \
  10.   printf("lastRandomData = %04X\r\n", lastRandomData);
    : D- |! d1 a8 V& D0 p7 p

  11. 5 m9 o# ]4 E9 w* M& V# V7 h
  12.   HAL_RNG_GenerateRandomNumber(&hrng, &randomData);0 |) I; Q8 p; y* V
  13.   printf("GenerateRandomNumber = %04X\r\n", randomData);5 D4 |# e( E  P5 V2 I
  14. }8 l9 w( h$ m% \4 B
复制代码

! ?7 b* l! t9 [
0 }( K0 I2 O/ \0 ]  ^" T4 P! d
7.png
: m/ I# y% h, a# V

5 B8 M. v2 e$ ^  x5 ^* w! K
然后在main中调用
% n) V  x' q* g
8.png 1 v' D, Z4 v7 ]/ I+ ^  a' \

4 _9 O! X( Z5 H
编译下载,日志如下

# y: d' F. u1 L) Z4 _
9.png 6 K9 h0 g) Z) @. d
' \$ {& i" F' w) x+ o
两个随机数已经生成,不重复。并且获取上一次得到的随机数也成功
* h6 o2 I' U, h7 p! ]4 x5 p

7 L+ q' {7 e+ v
三、通过中断得到随机数
/ d+ g0 i6 i5 a( g1 d
如果不想阻塞式获取随机数,那我们可以选择使用异步的通过中断获取随机数

) A2 _) X" B9 D/ j* w% q. b
首先需要修改一下CUBE,设置RNG的NVIC
# Y1 R, E/ \9 x
12.png " |. U/ t: J$ h! a, A: R
3 _: H, E3 g- i- [4 f: ~
然后点击右上角的生成代码按钮(图片略)
* m* P$ [9 G) ]7 w' U. ?# b9 T" o
刚才我们说了通过中断得到随机数为HAL_RNG_GenerateRandomNumber_IT。和之前的BSP的按键一样,中断相关的函数CUBE都帮我配置好了,用户层只要关注回调函数的实现即可。现在我们来看看成功生成随机数的回调函数、生成随机数失败的回调函数
. n$ P# L% Y3 ^7 A
' K( B" L4 e( p% |$ F
这两个函数在init时就注册好了
" ]- f$ z2 p  _$ H4 I, y
13.png " S# ?0 c) V& u7 {4 ^  p

; ~7 k* E) W. v7 M& j
这两个函数是HAL库中定义好的两个虚函数,回头我们就要来实现这两个函数。现在看看定义的虚函数

5 i; l% C# C" U/ H9 M
14.png ' g/ c* s, _. O

' O2 c) S3 m, _* A, M
接下来看看这两个函数是如何被调用的,首先来到stm32u0xx_it.c,看看RNG和CRYP的中断函数(他俩公用一个中断源)

4 D+ H( }$ S# ~* t7 q
15.png
+ \& e2 f* t$ ?% Q7 [: J  X) O

% [1 D) [0 f( [1 {$ z9 c  ?
在HAL_RNG_IRQHandler中判断各种寄存器和清除对应寄存器的值等,然后还会调用ReadyDataCallback或者ErrorCallback。

, ~* Z2 ~/ Q1 l$ w0 S- ^
16.png 6 @" [3 U: L0 X! F8 S
+ O, q% \) x6 I

% _4 M$ d0 B7 Y1 j
简单的了解完后,我们开始写代码

" O( E2 L% G/ X1 K2 M, a0 S/ \
先把按键测试给打开,这样当按键按下后,我们调用一次HAL_RNG_GenerateRandomNumber_IT

, M: _, Z7 A' ~  u5 M
17.png 2 i+ R0 q$ X8 i( U  s7 v+ j/ C

: U2 l  m0 L6 A7 A( D
while1中的按键测试函数中注释掉LED的翻转,添加HAL_RNG_GenerateRandomNumber_IT和打印
3 N8 F' ~& f4 A! a0 V
  1. #if BUTTON_TEST
    % x( P! \+ A; v6 T
  2.     /* BUTTON BSP测试 */
    , K0 ]" M. e! F& `# E# G3 u
  3.     if (UserButtonState == BUTTON_PRESSED)
    % S& j. f9 M7 R) w" Y  e
  4.     {
    . l- D5 H- R/ U% g6 r; ]
  5.       UserButtonState = BUTTON_RELEASED;
    ) F* s, `/ w, h. }8 _. x2 Q
  6.       // BSP_LED_Toggle(LED_GREEN);
    7 n' k9 H$ i  K% ?9 A7 [
  7.       printf("start GenerateRandomNumber_IT\r\n");1 r! G# x& v7 L4 i/ p
  8.       HAL_RNG_GenerateRandomNumber_IT(&hrng);
    + d4 j  m, i) S9 \- R
  9.     }3 \5 O6 a3 k7 Q2 K+ A  v
  10. #endif
复制代码
18.png

* i) d) c; r( ?# S
接下来实现一下之前说的两个虚函数

$ K, s3 t& W" u1 o4 A4 ~
  1. void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)) T- a  n0 `9 `4 c: E$ z
  2. {
    9 U+ `# {5 x9 |/ a
  3.   randomData = random32bit;' E4 o! ]- s% F6 @
  4.   printf("Generate RNG IT = %04X\r\n", randomData);. B- C: d6 _# t! ?( r7 G
  5. }! A1 f. |: n/ x* D7 O

  6. # M. d1 O5 B3 v2 T+ H
  7. void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng)+ T& z* r9 ]1 ^0 {7 i& x% m8 u
  8. {  m! {" i' V& w, `: g  Y& |
  9.   printf("Generate RNG IT ERROR\r\n");
    + ]; s: W$ l- C8 L  B1 H9 f
  10.   Error_Handler();: K& \1 U8 S. T) Y
  11. }* c8 j% {& ?) H* D
复制代码
19.png
) H, p5 m3 {! Q. f3 ]! y9 i
. G9 f, \; Z( @1 \# q" [" T
编译下载,日志如下
' C% O9 J5 U. s
20.png ( z; o% d* b9 C

: M6 {7 u7 b  F( [. q7 @8 y& G9 V: f1 a4 ^) B

3 _( [/ U# w7 S7 f
今日关于RNG的测试都顺利完成,ST的HAL库还是做得不错的,让用户就关注业务相关的函数,不需要去具体了解每个芯片的各个寄存器,对于开发很友好

' c5 Y8 l% _8 g( A+ ^. I+ ^5 `4 L9 n" z* o4 ^
今日工程: STM32U0_RNG_test.rar (5.16 MB, 下载次数: 0) 5 |3 }- Q) y/ ~1 l
1 收藏 评论1 发布时间:2024-5-14 00:30

举报

1个回答
STM1024 回答时间:2024-5-19 22:27:49

大佬分析测试的很不错👍,看来我得写点别的了😄

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版