1 /**
2 ******************************************************************************
3 * @file stm32h5xx_hal_rng.c
4 * @author MCD Application Team
5 * @brief RNG HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the Random Number Generator (RNG) peripheral:
8 * + Initialization and configuration functions
9 * + Peripheral Control functions
10 * + Peripheral State functions
11 *
12 ******************************************************************************
13 * @attention
14 *
15 * Copyright (c) 2023 STMicroelectronics.
16 * All rights reserved.
17 *
18 * This software is licensed under terms that can be found in the LICENSE file
19 * in the root directory of this software component.
20 * If no LICENSE file comes with this software, it is provided AS-IS.
21 *
22 ******************************************************************************
23 @verbatim
24 ==============================================================================
25 ##### How to use this driver #####
26 ==============================================================================
27 [..]
28 The RNG HAL driver can be used as follows:
29
30 (#) Enable the RNG controller clock using __HAL_RCC_RNG_CLK_ENABLE() macro
31 in HAL_RNG_MspInit().
32 (#) Activate the RNG peripheral using HAL_RNG_Init() function.
33 (#) Wait until the 32 bit Random Number Generator contains a valid
34 random data using (polling/interrupt) mode.
35 (#) Get the 32 bit random number using HAL_RNG_GenerateRandomNumber() function.
36
37 ##### Callback registration #####
38 ==================================
39
40 [..]
41 The compilation define USE_HAL_RNG_REGISTER_CALLBACKS when set to 1
42 allows the user to configure dynamically the driver callbacks.
43
44 [..]
45 Use Function HAL_RNG_RegisterCallback() to register a user callback.
46 Function HAL_RNG_RegisterCallback() allows to register following callbacks:
47 (+) ErrorCallback : RNG Error Callback.
48 (+) MspInitCallback : RNG MspInit.
49 (+) MspDeInitCallback : RNG MspDeInit.
50 This function takes as parameters the HAL peripheral handle, the Callback ID
51 and a pointer to the user callback function.
52
53 [..]
54 Use function HAL_RNG_UnRegisterCallback() to reset a callback to the default
55 weak (overridden) function.
56 HAL_RNG_UnRegisterCallback() takes as parameters the HAL peripheral handle,
57 and the Callback ID.
58 This function allows to reset following callbacks:
59 (+) ErrorCallback : RNG Error Callback.
60 (+) MspInitCallback : RNG MspInit.
61 (+) MspDeInitCallback : RNG MspDeInit.
62
63 [..]
64 For specific callback ReadyDataCallback, use dedicated register callbacks:
65 respectively HAL_RNG_RegisterReadyDataCallback() , HAL_RNG_UnRegisterReadyDataCallback().
66
67 [..]
68 By default, after the HAL_RNG_Init() and when the state is HAL_RNG_STATE_RESET
69 all callbacks are set to the corresponding weak (overridden) functions:
70 example HAL_RNG_ErrorCallback().
71 Exception done for MspInit and MspDeInit functions that are respectively
72 reset to the legacy weak (overridden) functions in the HAL_RNG_Init()
73 and HAL_RNG_DeInit() only when these callbacks are null (not registered beforehand).
74 If not, MspInit or MspDeInit are not null, the HAL_RNG_Init() and HAL_RNG_DeInit()
75 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
76
77 [..]
78 Callbacks can be registered/unregistered in HAL_RNG_STATE_READY state only.
79 Exception done MspInit/MspDeInit that can be registered/unregistered
80 in HAL_RNG_STATE_READY or HAL_RNG_STATE_RESET state, thus registered (user)
81 MspInit/DeInit callbacks can be used during the Init/DeInit.
82 In that case first register the MspInit/MspDeInit user callbacks
83 using HAL_RNG_RegisterCallback() before calling HAL_RNG_DeInit()
84 or HAL_RNG_Init() function.
85
86 [..]
87 When The compilation define USE_HAL_RNG_REGISTER_CALLBACKS is set to 0 or
88 not defined, the callback registration feature is not available
89 and weak (overridden) callbacks are used.
90
91 @endverbatim
92 ******************************************************************************
93 */
94
95 /* Includes ------------------------------------------------------------------*/
96 #include "stm32h5xx_hal.h"
97
98 /** @addtogroup STM32H5xx_HAL_Driver
99 * @{
100 */
101
102 #if defined (RNG)
103
104 /** @addtogroup RNG
105 * @brief RNG HAL module driver.
106 * @{
107 */
108
109 #ifdef HAL_RNG_MODULE_ENABLED
110
111 /* Private types -------------------------------------------------------------*/
112 /* Private defines -----------------------------------------------------------*/
113 /* Private variables ---------------------------------------------------------*/
114 /* Private constants ---------------------------------------------------------*/
115 /** @defgroup RNG_Private_Constants RNG Private Constants
116 * @{
117 */
118 #define RNG_TIMEOUT_VALUE 4U
119 /**
120 * @}
121 */
122 /* Private macros ------------------------------------------------------------*/
123 /* Private functions prototypes ----------------------------------------------*/
124 /* Exported functions --------------------------------------------------------*/
125
126 /** @addtogroup RNG_Exported_Functions
127 * @{
128 */
129
130 /** @addtogroup RNG_Exported_Functions_Group1
131 * @brief Initialization and configuration functions
132 *
133 @verbatim
134 ===============================================================================
135 ##### Initialization and configuration functions #####
136 ===============================================================================
137 [..] This section provides functions allowing to:
138 (+) Initialize the RNG according to the specified parameters
139 in the RNG_InitTypeDef and create the associated handle
140 (+) DeInitialize the RNG peripheral
141 (+) Initialize the RNG MSP
142 (+) DeInitialize RNG MSP
143
144 @endverbatim
145 * @{
146 */
147
148 /**
149 * @brief Initializes the RNG peripheral and creates the associated handle.
150 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
151 * the configuration information for RNG.
152 * @retval HAL status
153 */
HAL_RNG_Init(RNG_HandleTypeDef * hrng)154 HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng)
155 {
156 uint32_t tickstart;
157 /* Check the RNG handle allocation */
158 if (hrng == NULL)
159 {
160 return HAL_ERROR;
161 }
162 /* Check the parameters */
163 assert_param(IS_RNG_ALL_INSTANCE(hrng->Instance));
164 assert_param(IS_RNG_CED(hrng->Init.ClockErrorDetection));
165
166 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
167 if (hrng->State == HAL_RNG_STATE_RESET)
168 {
169 /* Allocate lock resource and initialize it */
170 hrng->Lock = HAL_UNLOCKED;
171
172 hrng->ReadyDataCallback = HAL_RNG_ReadyDataCallback; /* Legacy weak ReadyDataCallback */
173 hrng->ErrorCallback = HAL_RNG_ErrorCallback; /* Legacy weak ErrorCallback */
174
175 if (hrng->MspInitCallback == NULL)
176 {
177 hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit */
178 }
179
180 /* Init the low level hardware */
181 hrng->MspInitCallback(hrng);
182 }
183 #else
184 if (hrng->State == HAL_RNG_STATE_RESET)
185 {
186 /* Allocate lock resource and initialize it */
187 hrng->Lock = HAL_UNLOCKED;
188
189 /* Init the low level hardware */
190 HAL_RNG_MspInit(hrng);
191 }
192 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
193
194 /* Change RNG peripheral state */
195 hrng->State = HAL_RNG_STATE_BUSY;
196
197 /* Disable RNG */
198 __HAL_RNG_DISABLE(hrng);
199
200 #if defined(RNG_CR_NIST_VALUE)
201 /* Recommended value for NIST compliance, refer to application note AN4230 */
202 WRITE_REG(hrng->Instance->CR, RNG_CR_NIST_VALUE | RNG_CR_CONDRST | hrng->Init.ClockErrorDetection);
203 #else
204 /* Clock Error Detection Configuration when CONDRT bit is set to 1 */
205 MODIFY_REG(hrng->Instance->CR, RNG_CR_CED | RNG_CR_CONDRST, hrng->Init.ClockErrorDetection | RNG_CR_CONDRST);
206 #endif /* RNG_CR_NIST_VALUE */
207 #if defined(RNG_HTCR_NIST_VALUE)
208 /* Recommended value for NIST compliance, refer to application note AN4230 */
209 WRITE_REG(hrng->Instance->HTCR, RNG_HTCR_NIST_VALUE);
210 #endif /* RNG_HTCR_NIST_VALUE */
211 #if defined(RNG_NSCR_NIST_VALUE)
212 WRITE_REG(hrng->Instance->NSCR, RNG_NSCR_NIST_VALUE);
213 #endif /* RNG_NSCR_NIST_VALUE */
214
215 /* Writing bit CONDRST=0 */
216 CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
217
218 /* Get tick */
219 tickstart = HAL_GetTick();
220
221 /* Wait for conditioning reset process to be completed */
222 while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
223 {
224 if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
225 {
226 /* New check to avoid false timeout detection in case of preemption */
227 if (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
228 {
229 hrng->State = HAL_RNG_STATE_READY;
230 hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
231 return HAL_ERROR;
232 }
233 }
234 }
235
236 /* Enable the RNG Peripheral */
237 __HAL_RNG_ENABLE(hrng);
238
239 /* verify that no seed error */
240 if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
241 {
242 hrng->State = HAL_RNG_STATE_ERROR;
243 return HAL_ERROR;
244 }
245 /* Get tick */
246 tickstart = HAL_GetTick();
247 /* Check if data register contains valid random data */
248 while (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) != SET)
249 {
250 if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
251 {
252 /* New check to avoid false timeout detection in case of preemption */
253 if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) != SET)
254 {
255 hrng->State = HAL_RNG_STATE_ERROR;
256 hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
257 return HAL_ERROR;
258 }
259 }
260 }
261
262 /* Initialize the RNG state */
263 hrng->State = HAL_RNG_STATE_READY;
264
265 /* Initialise the error code */
266 hrng->ErrorCode = HAL_RNG_ERROR_NONE;
267
268 /* Return function status */
269 return HAL_OK;
270 }
271
272 /**
273 * @brief DeInitializes the RNG peripheral.
274 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
275 * the configuration information for RNG.
276 * @retval HAL status
277 */
HAL_RNG_DeInit(RNG_HandleTypeDef * hrng)278 HAL_StatusTypeDef HAL_RNG_DeInit(RNG_HandleTypeDef *hrng)
279 {
280 uint32_t tickstart;
281
282 /* Check the RNG handle allocation */
283 if (hrng == NULL)
284 {
285 return HAL_ERROR;
286 }
287
288 /* Clear Clock Error Detection bit when CONDRT bit is set to 1 */
289 MODIFY_REG(hrng->Instance->CR, RNG_CR_CED | RNG_CR_CONDRST, RNG_CED_ENABLE | RNG_CR_CONDRST);
290
291 /* Writing bit CONDRST=0 */
292 CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
293
294 /* Get tick */
295 tickstart = HAL_GetTick();
296
297 /* Wait for conditioning reset process to be completed */
298 while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
299 {
300 if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
301 {
302 /* New check to avoid false timeout detection in case of preemption */
303 if (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
304 {
305 hrng->State = HAL_RNG_STATE_READY;
306 hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
307 /* Process Unlocked */
308 __HAL_UNLOCK(hrng);
309 return HAL_ERROR;
310 }
311 }
312 }
313
314 /* Disable the RNG Peripheral */
315 CLEAR_BIT(hrng->Instance->CR, RNG_CR_IE | RNG_CR_RNGEN);
316
317 /* Clear RNG interrupt status flags */
318 CLEAR_BIT(hrng->Instance->SR, RNG_SR_CEIS | RNG_SR_SEIS);
319
320 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
321 if (hrng->MspDeInitCallback == NULL)
322 {
323 hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspDeInit */
324 }
325
326 /* DeInit the low level hardware */
327 hrng->MspDeInitCallback(hrng);
328 #else
329 /* DeInit the low level hardware */
330 HAL_RNG_MspDeInit(hrng);
331 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
332
333 /* Update the RNG state */
334 hrng->State = HAL_RNG_STATE_RESET;
335
336 /* Initialise the error code */
337 hrng->ErrorCode = HAL_RNG_ERROR_NONE;
338
339 /* Release Lock */
340 __HAL_UNLOCK(hrng);
341
342 /* Return the function status */
343 return HAL_OK;
344 }
345
346 /**
347 * @brief Initializes the RNG MSP.
348 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
349 * the configuration information for RNG.
350 * @retval None
351 */
HAL_RNG_MspInit(RNG_HandleTypeDef * hrng)352 __weak void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
353 {
354 /* Prevent unused argument(s) compilation warning */
355 UNUSED(hrng);
356 /* NOTE : This function should not be modified. When the callback is needed,
357 function HAL_RNG_MspInit must be implemented in the user file.
358 */
359 }
360
361 /**
362 * @brief DeInitializes the RNG MSP.
363 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
364 * the configuration information for RNG.
365 * @retval None
366 */
HAL_RNG_MspDeInit(RNG_HandleTypeDef * hrng)367 __weak void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng)
368 {
369 /* Prevent unused argument(s) compilation warning */
370 UNUSED(hrng);
371 /* NOTE : This function should not be modified. When the callback is needed,
372 function HAL_RNG_MspDeInit must be implemented in the user file.
373 */
374 }
375
376 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
377 /**
378 * @brief Register a User RNG Callback
379 * To be used instead of the weak predefined callback
380 * @param hrng RNG handle
381 * @param CallbackID ID of the callback to be registered
382 * This parameter can be one of the following values:
383 * @arg @ref HAL_RNG_ERROR_CB_ID Error callback ID
384 * @arg @ref HAL_RNG_MSPINIT_CB_ID MspInit callback ID
385 * @arg @ref HAL_RNG_MSPDEINIT_CB_ID MspDeInit callback ID
386 * @param pCallback pointer to the Callback function
387 * @retval HAL status
388 */
HAL_RNG_RegisterCallback(RNG_HandleTypeDef * hrng,HAL_RNG_CallbackIDTypeDef CallbackID,pRNG_CallbackTypeDef pCallback)389 HAL_StatusTypeDef HAL_RNG_RegisterCallback(RNG_HandleTypeDef *hrng, HAL_RNG_CallbackIDTypeDef CallbackID,
390 pRNG_CallbackTypeDef pCallback)
391 {
392 HAL_StatusTypeDef status = HAL_OK;
393
394 if (pCallback == NULL)
395 {
396 /* Update the error code */
397 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
398 return HAL_ERROR;
399 }
400
401 if (HAL_RNG_STATE_READY == hrng->State)
402 {
403 switch (CallbackID)
404 {
405 case HAL_RNG_ERROR_CB_ID :
406 hrng->ErrorCallback = pCallback;
407 break;
408
409 case HAL_RNG_MSPINIT_CB_ID :
410 hrng->MspInitCallback = pCallback;
411 break;
412
413 case HAL_RNG_MSPDEINIT_CB_ID :
414 hrng->MspDeInitCallback = pCallback;
415 break;
416
417 default :
418 /* Update the error code */
419 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
420 /* Return error status */
421 status = HAL_ERROR;
422 break;
423 }
424 }
425 else if (HAL_RNG_STATE_RESET == hrng->State)
426 {
427 switch (CallbackID)
428 {
429 case HAL_RNG_MSPINIT_CB_ID :
430 hrng->MspInitCallback = pCallback;
431 break;
432
433 case HAL_RNG_MSPDEINIT_CB_ID :
434 hrng->MspDeInitCallback = pCallback;
435 break;
436
437 default :
438 /* Update the error code */
439 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
440 /* Return error status */
441 status = HAL_ERROR;
442 break;
443 }
444 }
445 else
446 {
447 /* Update the error code */
448 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
449 /* Return error status */
450 status = HAL_ERROR;
451 }
452
453 return status;
454 }
455
456 /**
457 * @brief Unregister an RNG Callback
458 * RNG callback is redirected to the weak predefined callback
459 * @param hrng RNG handle
460 * @param CallbackID ID of the callback to be unregistered
461 * This parameter can be one of the following values:
462 * @arg @ref HAL_RNG_ERROR_CB_ID Error callback ID
463 * @arg @ref HAL_RNG_MSPINIT_CB_ID MspInit callback ID
464 * @arg @ref HAL_RNG_MSPDEINIT_CB_ID MspDeInit callback ID
465 * @retval HAL status
466 */
HAL_RNG_UnRegisterCallback(RNG_HandleTypeDef * hrng,HAL_RNG_CallbackIDTypeDef CallbackID)467 HAL_StatusTypeDef HAL_RNG_UnRegisterCallback(RNG_HandleTypeDef *hrng, HAL_RNG_CallbackIDTypeDef CallbackID)
468 {
469 HAL_StatusTypeDef status = HAL_OK;
470
471
472 if (HAL_RNG_STATE_READY == hrng->State)
473 {
474 switch (CallbackID)
475 {
476 case HAL_RNG_ERROR_CB_ID :
477 hrng->ErrorCallback = HAL_RNG_ErrorCallback; /* Legacy weak ErrorCallback */
478 break;
479
480 case HAL_RNG_MSPINIT_CB_ID :
481 hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit */
482 break;
483
484 case HAL_RNG_MSPDEINIT_CB_ID :
485 hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspDeInit */
486 break;
487
488 default :
489 /* Update the error code */
490 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
491 /* Return error status */
492 status = HAL_ERROR;
493 break;
494 }
495 }
496 else if (HAL_RNG_STATE_RESET == hrng->State)
497 {
498 switch (CallbackID)
499 {
500 case HAL_RNG_MSPINIT_CB_ID :
501 hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit */
502 break;
503
504 case HAL_RNG_MSPDEINIT_CB_ID :
505 hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspInit */
506 break;
507
508 default :
509 /* Update the error code */
510 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
511 /* Return error status */
512 status = HAL_ERROR;
513 break;
514 }
515 }
516 else
517 {
518 /* Update the error code */
519 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
520 /* Return error status */
521 status = HAL_ERROR;
522 }
523
524 return status;
525 }
526
527 /**
528 * @brief Register Data Ready RNG Callback
529 * To be used instead of the weak HAL_RNG_ReadyDataCallback() predefined callback
530 * @param hrng RNG handle
531 * @param pCallback pointer to the Data Ready Callback function
532 * @retval HAL status
533 */
HAL_RNG_RegisterReadyDataCallback(RNG_HandleTypeDef * hrng,pRNG_ReadyDataCallbackTypeDef pCallback)534 HAL_StatusTypeDef HAL_RNG_RegisterReadyDataCallback(RNG_HandleTypeDef *hrng, pRNG_ReadyDataCallbackTypeDef pCallback)
535 {
536 HAL_StatusTypeDef status = HAL_OK;
537
538 if (pCallback == NULL)
539 {
540 /* Update the error code */
541 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
542 return HAL_ERROR;
543 }
544 /* Process locked */
545 __HAL_LOCK(hrng);
546
547 if (HAL_RNG_STATE_READY == hrng->State)
548 {
549 hrng->ReadyDataCallback = pCallback;
550 }
551 else
552 {
553 /* Update the error code */
554 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
555 /* Return error status */
556 status = HAL_ERROR;
557 }
558
559 /* Release Lock */
560 __HAL_UNLOCK(hrng);
561 return status;
562 }
563
564 /**
565 * @brief UnRegister the Data Ready RNG Callback
566 * Data Ready RNG Callback is redirected to the weak HAL_RNG_ReadyDataCallback() predefined callback
567 * @param hrng RNG handle
568 * @retval HAL status
569 */
HAL_RNG_UnRegisterReadyDataCallback(RNG_HandleTypeDef * hrng)570 HAL_StatusTypeDef HAL_RNG_UnRegisterReadyDataCallback(RNG_HandleTypeDef *hrng)
571 {
572 HAL_StatusTypeDef status = HAL_OK;
573
574 /* Process locked */
575 __HAL_LOCK(hrng);
576
577 if (HAL_RNG_STATE_READY == hrng->State)
578 {
579 hrng->ReadyDataCallback = HAL_RNG_ReadyDataCallback; /* Legacy weak ReadyDataCallback */
580 }
581 else
582 {
583 /* Update the error code */
584 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
585 /* Return error status */
586 status = HAL_ERROR;
587 }
588
589 /* Release Lock */
590 __HAL_UNLOCK(hrng);
591 return status;
592 }
593
594 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
595
596 /**
597 * @}
598 */
599
600 /** @addtogroup RNG_Exported_Functions_Group2
601 * @brief Peripheral Control functions
602 *
603 @verbatim
604 ===============================================================================
605 ##### Peripheral Control functions #####
606 ===============================================================================
607 [..] This section provides functions allowing to:
608 (+) Get the 32 bit Random number
609 (+) Get the 32 bit Random number with interrupt enabled
610 (+) Handle RNG interrupt request
611
612 @endverbatim
613 * @{
614 */
615
616 /**
617 * @brief Generates a 32-bit random number.
618 * @note This function checks value of RNG_FLAG_DRDY flag to know if valid
619 * random number is available in the DR register (RNG_FLAG_DRDY flag set
620 * whenever a random number is available through the RNG_DR register).
621 * After transitioning from 0 to 1 (random number available),
622 * RNG_FLAG_DRDY flag remains high until output buffer becomes empty after reading
623 * four words from the RNG_DR register, i.e. further function calls
624 * will immediately return a new u32 random number (additional words are
625 * available and can be read by the application, till RNG_FLAG_DRDY flag remains high).
626 * @note When no more random number data is available in DR register, RNG_FLAG_DRDY
627 * flag is automatically cleared.
628 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
629 * the configuration information for RNG.
630 * @param random32bit pointer to generated random number variable if successful.
631 * @retval HAL status
632 */
633
HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef * hrng,uint32_t * random32bit)634 HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit)
635 {
636 uint32_t tickstart;
637 HAL_StatusTypeDef status = HAL_OK;
638
639 /* Process Locked */
640 __HAL_LOCK(hrng);
641
642 /* Check RNG peripheral state */
643 if (hrng->State == HAL_RNG_STATE_READY)
644 {
645 /* Change RNG peripheral state */
646 hrng->State = HAL_RNG_STATE_BUSY;
647 /* Check if there is a seed error */
648 if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
649 {
650 /* Update the error code */
651 hrng->ErrorCode = HAL_RNG_ERROR_SEED;
652 /* Reset from seed error */
653 status = RNG_RecoverSeedError(hrng);
654 if (status == HAL_ERROR)
655 {
656 /* Update the error code */
657 hrng->ErrorCode = HAL_RNG_ERROR_RECOVERSEED;
658 return status;
659 }
660 }
661
662 /* Get tick */
663 tickstart = HAL_GetTick();
664
665 /* Check if data register contains valid random data */
666 while (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET)
667 {
668 if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
669 {
670 /* New check to avoid false timeout detection in case of preemption */
671 if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET)
672 {
673 hrng->State = HAL_RNG_STATE_READY;
674 hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
675 /* Process Unlocked */
676 __HAL_UNLOCK(hrng);
677 return HAL_ERROR;
678 }
679 }
680 }
681
682 /* Get a 32bit Random number */
683 hrng->RandomNumber = hrng->Instance->DR;
684 /* In case of seed error, the value available in the RNG_DR register must not
685 be used as it may not have enough entropy */
686 if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
687 {
688 /* Update the error code and status */
689 hrng->ErrorCode = HAL_RNG_ERROR_SEED;
690 status = HAL_ERROR;
691 }
692 else /* No seed error */
693 {
694 *random32bit = hrng->RandomNumber;
695 }
696 hrng->State = HAL_RNG_STATE_READY;
697 }
698 else
699 {
700 hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
701 status = HAL_ERROR;
702 }
703
704 /* Process Unlocked */
705 __HAL_UNLOCK(hrng);
706
707 return status;
708 }
709
710 /**
711 * @brief Generates a 32-bit random number in interrupt mode.
712 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
713 * the configuration information for RNG.
714 * @retval HAL status
715 */
HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef * hrng)716 HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng)
717 {
718 HAL_StatusTypeDef status = HAL_OK;
719
720 /* Process Locked */
721 __HAL_LOCK(hrng);
722
723 /* Check RNG peripheral state */
724 if (hrng->State == HAL_RNG_STATE_READY)
725 {
726 /* Change RNG peripheral state */
727 hrng->State = HAL_RNG_STATE_BUSY;
728
729 /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */
730 __HAL_RNG_ENABLE_IT(hrng);
731 }
732 else
733 {
734 /* Process Unlocked */
735 __HAL_UNLOCK(hrng);
736
737 hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
738 status = HAL_ERROR;
739 }
740
741 return status;
742 }
743
744 /**
745 * @brief Handles RNG interrupt request.
746 * @note In the case of a clock error, the RNG is no more able to generate
747 * random numbers because the PLL48CLK clock is not correct. User has
748 * to check that the clock controller is correctly configured to provide
749 * the RNG clock and clear the CEIS bit using __HAL_RNG_CLEAR_IT().
750 * The clock error has no impact on the previously generated
751 * random numbers, and the RNG_DR register contents can be used.
752 * @note In the case of a seed error, the generation of random numbers is
753 * interrupted as long as the SECS bit is '1'. If a number is
754 * available in the RNG_DR register, it must not be used because it may
755 * not have enough entropy. In this case, it is recommended to clear the
756 * SEIS bit using __HAL_RNG_CLEAR_IT(), then disable and enable
757 * the RNG peripheral to reinitialize and restart the RNG.
758 * @note User-written HAL_RNG_ErrorCallback() API is called once whether SEIS
759 * or CEIS are set.
760 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
761 * the configuration information for RNG.
762 * @retval None
763
764 */
HAL_RNG_IRQHandler(RNG_HandleTypeDef * hrng)765 void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng)
766 {
767 uint32_t rngclockerror = 0U;
768 uint32_t itflag = hrng->Instance->SR;
769
770 /* RNG clock error interrupt occurred */
771 if ((itflag & RNG_IT_CEI) == RNG_IT_CEI)
772 {
773 /* Update the error code */
774 hrng->ErrorCode = HAL_RNG_ERROR_CLOCK;
775 rngclockerror = 1U;
776 }
777 else if ((itflag & RNG_IT_SEI) == RNG_IT_SEI)
778 {
779 /* Check if Seed Error Current Status (SECS) is set */
780 if ((itflag & RNG_FLAG_SECS) != RNG_FLAG_SECS)
781 {
782 /* RNG IP performed the reset automatically (auto-reset) */
783 /* Clear bit SEIS */
784 CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
785 }
786 else
787 {
788 /* Seed Error has not been recovered : Update the error code */
789 hrng->ErrorCode = HAL_RNG_ERROR_SEED;
790 rngclockerror = 1U;
791 /* Disable the IT */
792 __HAL_RNG_DISABLE_IT(hrng);
793 }
794 }
795 else
796 {
797 /* Nothing to do */
798 }
799
800 if (rngclockerror == 1U)
801 {
802 /* Change RNG peripheral state */
803 hrng->State = HAL_RNG_STATE_ERROR;
804
805 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
806 /* Call registered Error callback */
807 hrng->ErrorCallback(hrng);
808 #else
809 /* Call legacy weak Error callback */
810 HAL_RNG_ErrorCallback(hrng);
811 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
812
813 /* Clear the clock error flag */
814 __HAL_RNG_CLEAR_IT(hrng, RNG_IT_CEI | RNG_IT_SEI);
815
816 return;
817 }
818
819 /* Check RNG data ready interrupt occurred */
820 if ((itflag & RNG_IT_DRDY) == RNG_IT_DRDY)
821 {
822 /* Generate random number once, so disable the IT */
823 __HAL_RNG_DISABLE_IT(hrng);
824
825 /* Get the 32bit Random number (DRDY flag automatically cleared) */
826 hrng->RandomNumber = hrng->Instance->DR;
827
828 if (hrng->State != HAL_RNG_STATE_ERROR)
829 {
830 /* Change RNG peripheral state */
831 hrng->State = HAL_RNG_STATE_READY;
832 /* Process Unlocked */
833 __HAL_UNLOCK(hrng);
834
835 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
836 /* Call registered Data Ready callback */
837 hrng->ReadyDataCallback(hrng, hrng->RandomNumber);
838 #else
839 /* Call legacy weak Data Ready callback */
840 HAL_RNG_ReadyDataCallback(hrng, hrng->RandomNumber);
841 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
842 }
843 }
844 }
845
846 /**
847 * @brief Read latest generated random number.
848 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
849 * the configuration information for RNG.
850 * @retval random value
851 */
HAL_RNG_ReadLastRandomNumber(const RNG_HandleTypeDef * hrng)852 uint32_t HAL_RNG_ReadLastRandomNumber(const RNG_HandleTypeDef *hrng)
853 {
854 return (hrng->RandomNumber);
855 }
856
857 /**
858 * @brief Data Ready callback in non-blocking mode.
859 * @note When RNG_FLAG_DRDY flag value is set, first random number has been read
860 * from DR register in IRQ Handler and is provided as callback parameter.
861 * Depending on valid data available in the conditioning output buffer,
862 * additional words can be read by the application from DR register till
863 * DRDY bit remains high.
864 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
865 * the configuration information for RNG.
866 * @param random32bit generated random number.
867 * @retval None
868 */
HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef * hrng,uint32_t random32bit)869 __weak void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
870 {
871 /* Prevent unused argument(s) compilation warning */
872 UNUSED(hrng);
873 UNUSED(random32bit);
874 /* NOTE : This function should not be modified. When the callback is needed,
875 function HAL_RNG_ReadyDataCallback must be implemented in the user file.
876 */
877 }
878
879 /**
880 * @brief RNG error callbacks.
881 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
882 * the configuration information for RNG.
883 * @retval None
884 */
HAL_RNG_ErrorCallback(RNG_HandleTypeDef * hrng)885 __weak void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng)
886 {
887 /* Prevent unused argument(s) compilation warning */
888 UNUSED(hrng);
889 /* NOTE : This function should not be modified. When the callback is needed,
890 function HAL_RNG_ErrorCallback must be implemented in the user file.
891 */
892 }
893 /**
894 * @}
895 */
896
897
898 /** @addtogroup RNG_Exported_Functions_Group3
899 * @brief Peripheral State functions
900 *
901 @verbatim
902 ===============================================================================
903 ##### Peripheral State functions #####
904 ===============================================================================
905 [..]
906 This subsection permits to get in run-time the status of the peripheral
907 and the data flow.
908
909 @endverbatim
910 * @{
911 */
912
913 /**
914 * @brief Returns the RNG state.
915 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
916 * the configuration information for RNG.
917 * @retval HAL state
918 */
HAL_RNG_GetState(const RNG_HandleTypeDef * hrng)919 HAL_RNG_StateTypeDef HAL_RNG_GetState(const RNG_HandleTypeDef *hrng)
920 {
921 return hrng->State;
922 }
923
924 /**
925 * @brief Return the RNG handle error code.
926 * @param hrng: pointer to a RNG_HandleTypeDef structure.
927 * @retval RNG Error Code
928 */
HAL_RNG_GetError(const RNG_HandleTypeDef * hrng)929 uint32_t HAL_RNG_GetError(const RNG_HandleTypeDef *hrng)
930 {
931 /* Return RNG Error Code */
932 return hrng->ErrorCode;
933 }
934 /**
935 * @}
936 */
937
938 /**
939 * @}
940 */
941 /* Private functions ---------------------------------------------------------*/
942 /** @addtogroup RNG_Private_Functions
943 * @{
944 */
945
946 /**
947 * @brief RNG sequence to recover from a seed error
948 * @param hrng pointer to a RNG_HandleTypeDef structure.
949 * @retval HAL status
950 */
RNG_RecoverSeedError(RNG_HandleTypeDef * hrng)951 HAL_StatusTypeDef RNG_RecoverSeedError(RNG_HandleTypeDef *hrng)
952 {
953 __IO uint32_t count = 0U;
954
955 /*Check if seed error current status (SECS)is set */
956 if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) == RESET)
957 {
958 /* RNG performed the reset automatically (auto-reset) */
959 /* Clear bit SEIS */
960 CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
961 }
962 else /* Sequence to fully recover from a seed error*/
963 {
964 /* Writing bit CONDRST=1*/
965 SET_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
966 /* Writing bit CONDRST=0*/
967 CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
968
969 /* Wait for conditioning reset process to be completed */
970 count = RNG_TIMEOUT_VALUE;
971 do
972 {
973 count-- ;
974 if (count == 0U)
975 {
976 hrng->State = HAL_RNG_STATE_READY;
977 hrng->ErrorCode |= HAL_RNG_ERROR_TIMEOUT;
978 /* Process Unlocked */
979 __HAL_UNLOCK(hrng);
980 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
981 /* Call registered Error callback */
982 hrng->ErrorCallback(hrng);
983 #else
984 /* Call legacy weak Error callback */
985 HAL_RNG_ErrorCallback(hrng);
986 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
987 return HAL_ERROR;
988 }
989 } while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST));
990
991 if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
992 {
993 /* Clear bit SEIS */
994 CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
995 }
996
997 /* Wait for SECS to be cleared */
998 count = RNG_TIMEOUT_VALUE;
999 do
1000 {
1001 count-- ;
1002 if (count == 0U)
1003 {
1004 hrng->State = HAL_RNG_STATE_READY;
1005 hrng->ErrorCode |= HAL_RNG_ERROR_TIMEOUT;
1006 /* Process Unlocked */
1007 __HAL_UNLOCK(hrng);
1008 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
1009 /* Call registered Error callback */
1010 hrng->ErrorCallback(hrng);
1011 #else
1012 /* Call legacy weak Error callback */
1013 HAL_RNG_ErrorCallback(hrng);
1014 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
1015 return HAL_ERROR;
1016 }
1017 } while (HAL_IS_BIT_SET(hrng->Instance->SR, RNG_FLAG_SECS));
1018 }
1019 /* Update the error code */
1020 hrng->ErrorCode &= ~ HAL_RNG_ERROR_SEED;
1021 return HAL_OK;
1022 }
1023
1024 /**
1025 * @}
1026 */
1027
1028
1029 #endif /* HAL_RNG_MODULE_ENABLED */
1030 /**
1031 * @}
1032 */
1033
1034 #endif /* RNG */
1035
1036 /**
1037 * @}
1038 */
1039