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) 2022 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 (surcharged) 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 (surcharged) functions:
70 example HAL_RNG_ErrorCallback().
71 Exception done for MspInit and MspDeInit functions that are respectively
72 reset to the legacy weak (surcharged) 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 (surcharged) 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 /* Clock Error Detection Configuration when CONDRT bit is set to 1 */
201 MODIFY_REG(hrng->Instance->CR, RNG_CR_CED | RNG_CR_CONDRST, hrng->Init.ClockErrorDetection | RNG_CR_CONDRST);
202
203
204 /* Writing bit CONDRST=0 */
205 CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
206
207 /* Get tick */
208 tickstart = HAL_GetTick();
209
210 /* Wait for conditioning reset process to be completed */
211 while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
212 {
213 if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
214 {
215 /* New check to avoid false timeout detection in case of preemption */
216 if (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
217 {
218 hrng->State = HAL_RNG_STATE_READY;
219 hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
220 return HAL_ERROR;
221 }
222 }
223 }
224
225 /* Enable the RNG Peripheral */
226 __HAL_RNG_ENABLE(hrng);
227
228 /* verify that no seed error */
229 if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
230 {
231 hrng->State = HAL_RNG_STATE_ERROR;
232 return HAL_ERROR;
233 }
234 /* Get tick */
235 tickstart = HAL_GetTick();
236 /* Check if data register contains valid random data */
237 while (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) != RESET)
238 {
239 if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
240 {
241 /* New check to avoid false timeout detection in case of preemption */
242 if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) != RESET)
243 {
244 hrng->State = HAL_RNG_STATE_ERROR;
245 hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
246 return HAL_ERROR;
247 }
248 }
249 }
250
251 /* Initialize the RNG state */
252 hrng->State = HAL_RNG_STATE_READY;
253
254 /* Initialise the error code */
255 hrng->ErrorCode = HAL_RNG_ERROR_NONE;
256
257 /* Return function status */
258 return HAL_OK;
259 }
260
261 /**
262 * @brief DeInitializes the RNG peripheral.
263 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
264 * the configuration information for RNG.
265 * @retval HAL status
266 */
HAL_RNG_DeInit(RNG_HandleTypeDef * hrng)267 HAL_StatusTypeDef HAL_RNG_DeInit(RNG_HandleTypeDef *hrng)
268 {
269 uint32_t tickstart;
270
271 /* Check the RNG handle allocation */
272 if (hrng == NULL)
273 {
274 return HAL_ERROR;
275 }
276
277 /* Clear Clock Error Detection bit when CONDRT bit is set to 1 */
278 MODIFY_REG(hrng->Instance->CR, RNG_CR_CED | RNG_CR_CONDRST, RNG_CED_ENABLE | RNG_CR_CONDRST);
279
280 /* Writing bit CONDRST=0 */
281 CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
282
283 /* Get tick */
284 tickstart = HAL_GetTick();
285
286 /* Wait for conditioning reset process to be completed */
287 while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
288 {
289 if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
290 {
291 /* New check to avoid false timeout detection in case of preemption */
292 if (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
293 {
294 hrng->State = HAL_RNG_STATE_READY;
295 hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
296 /* Process Unlocked */
297 __HAL_UNLOCK(hrng);
298 return HAL_ERROR;
299 }
300 }
301 }
302
303 /* Disable the RNG Peripheral */
304 CLEAR_BIT(hrng->Instance->CR, RNG_CR_IE | RNG_CR_RNGEN);
305
306 /* Clear RNG interrupt status flags */
307 CLEAR_BIT(hrng->Instance->SR, RNG_SR_CEIS | RNG_SR_SEIS);
308
309 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
310 if (hrng->MspDeInitCallback == NULL)
311 {
312 hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspDeInit */
313 }
314
315 /* DeInit the low level hardware */
316 hrng->MspDeInitCallback(hrng);
317 #else
318 /* DeInit the low level hardware */
319 HAL_RNG_MspDeInit(hrng);
320 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
321
322 /* Update the RNG state */
323 hrng->State = HAL_RNG_STATE_RESET;
324
325 /* Initialise the error code */
326 hrng->ErrorCode = HAL_RNG_ERROR_NONE;
327
328 /* Release Lock */
329 __HAL_UNLOCK(hrng);
330
331 /* Return the function status */
332 return HAL_OK;
333 }
334
335 /**
336 * @brief Initializes the RNG MSP.
337 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
338 * the configuration information for RNG.
339 * @retval None
340 */
HAL_RNG_MspInit(RNG_HandleTypeDef * hrng)341 __weak void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
342 {
343 /* Prevent unused argument(s) compilation warning */
344 UNUSED(hrng);
345 /* NOTE : This function should not be modified. When the callback is needed,
346 function HAL_RNG_MspInit must be implemented in the user file.
347 */
348 }
349
350 /**
351 * @brief DeInitializes the RNG MSP.
352 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
353 * the configuration information for RNG.
354 * @retval None
355 */
HAL_RNG_MspDeInit(RNG_HandleTypeDef * hrng)356 __weak void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng)
357 {
358 /* Prevent unused argument(s) compilation warning */
359 UNUSED(hrng);
360 /* NOTE : This function should not be modified. When the callback is needed,
361 function HAL_RNG_MspDeInit must be implemented in the user file.
362 */
363 }
364
365 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
366 /**
367 * @brief Register a User RNG Callback
368 * To be used instead of the weak predefined callback
369 * @param hrng RNG handle
370 * @param CallbackID ID of the callback to be registered
371 * This parameter can be one of the following values:
372 * @arg @ref HAL_RNG_ERROR_CB_ID Error callback ID
373 * @arg @ref HAL_RNG_MSPINIT_CB_ID MspInit callback ID
374 * @arg @ref HAL_RNG_MSPDEINIT_CB_ID MspDeInit callback ID
375 * @param pCallback pointer to the Callback function
376 * @retval HAL status
377 */
HAL_RNG_RegisterCallback(RNG_HandleTypeDef * hrng,HAL_RNG_CallbackIDTypeDef CallbackID,pRNG_CallbackTypeDef pCallback)378 HAL_StatusTypeDef HAL_RNG_RegisterCallback(RNG_HandleTypeDef *hrng, HAL_RNG_CallbackIDTypeDef CallbackID,
379 pRNG_CallbackTypeDef pCallback)
380 {
381 HAL_StatusTypeDef status = HAL_OK;
382
383 if (pCallback == NULL)
384 {
385 /* Update the error code */
386 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
387 return HAL_ERROR;
388 }
389 /* Process locked */
390 __HAL_LOCK(hrng);
391
392 if (HAL_RNG_STATE_READY == hrng->State)
393 {
394 switch (CallbackID)
395 {
396 case HAL_RNG_ERROR_CB_ID :
397 hrng->ErrorCallback = pCallback;
398 break;
399
400 case HAL_RNG_MSPINIT_CB_ID :
401 hrng->MspInitCallback = pCallback;
402 break;
403
404 case HAL_RNG_MSPDEINIT_CB_ID :
405 hrng->MspDeInitCallback = pCallback;
406 break;
407
408 default :
409 /* Update the error code */
410 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
411 /* Return error status */
412 status = HAL_ERROR;
413 break;
414 }
415 }
416 else if (HAL_RNG_STATE_RESET == hrng->State)
417 {
418 switch (CallbackID)
419 {
420 case HAL_RNG_MSPINIT_CB_ID :
421 hrng->MspInitCallback = pCallback;
422 break;
423
424 case HAL_RNG_MSPDEINIT_CB_ID :
425 hrng->MspDeInitCallback = pCallback;
426 break;
427
428 default :
429 /* Update the error code */
430 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
431 /* Return error status */
432 status = HAL_ERROR;
433 break;
434 }
435 }
436 else
437 {
438 /* Update the error code */
439 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
440 /* Return error status */
441 status = HAL_ERROR;
442 }
443
444 /* Release Lock */
445 __HAL_UNLOCK(hrng);
446 return status;
447 }
448
449 /**
450 * @brief Unregister an RNG Callback
451 * RNG callback is redirected to the weak predefined callback
452 * @param hrng RNG handle
453 * @param CallbackID ID of the callback to be unregistered
454 * This parameter can be one of the following values:
455 * @arg @ref HAL_RNG_ERROR_CB_ID Error callback ID
456 * @arg @ref HAL_RNG_MSPINIT_CB_ID MspInit callback ID
457 * @arg @ref HAL_RNG_MSPDEINIT_CB_ID MspDeInit callback ID
458 * @retval HAL status
459 */
HAL_RNG_UnRegisterCallback(RNG_HandleTypeDef * hrng,HAL_RNG_CallbackIDTypeDef CallbackID)460 HAL_StatusTypeDef HAL_RNG_UnRegisterCallback(RNG_HandleTypeDef *hrng, HAL_RNG_CallbackIDTypeDef CallbackID)
461 {
462 HAL_StatusTypeDef status = HAL_OK;
463
464 /* Process locked */
465 __HAL_LOCK(hrng);
466
467 if (HAL_RNG_STATE_READY == hrng->State)
468 {
469 switch (CallbackID)
470 {
471 case HAL_RNG_ERROR_CB_ID :
472 hrng->ErrorCallback = HAL_RNG_ErrorCallback; /* Legacy weak ErrorCallback */
473 break;
474
475 case HAL_RNG_MSPINIT_CB_ID :
476 hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit */
477 break;
478
479 case HAL_RNG_MSPDEINIT_CB_ID :
480 hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspDeInit */
481 break;
482
483 default :
484 /* Update the error code */
485 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
486 /* Return error status */
487 status = HAL_ERROR;
488 break;
489 }
490 }
491 else if (HAL_RNG_STATE_RESET == hrng->State)
492 {
493 switch (CallbackID)
494 {
495 case HAL_RNG_MSPINIT_CB_ID :
496 hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit */
497 break;
498
499 case HAL_RNG_MSPDEINIT_CB_ID :
500 hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspInit */
501 break;
502
503 default :
504 /* Update the error code */
505 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
506 /* Return error status */
507 status = HAL_ERROR;
508 break;
509 }
510 }
511 else
512 {
513 /* Update the error code */
514 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
515 /* Return error status */
516 status = HAL_ERROR;
517 }
518
519 /* Release Lock */
520 __HAL_UNLOCK(hrng);
521 return status;
522 }
523
524 /**
525 * @brief Register Data Ready RNG Callback
526 * To be used instead of the weak HAL_RNG_ReadyDataCallback() predefined callback
527 * @param hrng RNG handle
528 * @param pCallback pointer to the Data Ready Callback function
529 * @retval HAL status
530 */
HAL_RNG_RegisterReadyDataCallback(RNG_HandleTypeDef * hrng,pRNG_ReadyDataCallbackTypeDef pCallback)531 HAL_StatusTypeDef HAL_RNG_RegisterReadyDataCallback(RNG_HandleTypeDef *hrng, pRNG_ReadyDataCallbackTypeDef pCallback)
532 {
533 HAL_StatusTypeDef status = HAL_OK;
534
535 if (pCallback == NULL)
536 {
537 /* Update the error code */
538 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
539 return HAL_ERROR;
540 }
541 /* Process locked */
542 __HAL_LOCK(hrng);
543
544 if (HAL_RNG_STATE_READY == hrng->State)
545 {
546 hrng->ReadyDataCallback = pCallback;
547 }
548 else
549 {
550 /* Update the error code */
551 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
552 /* Return error status */
553 status = HAL_ERROR;
554 }
555
556 /* Release Lock */
557 __HAL_UNLOCK(hrng);
558 return status;
559 }
560
561 /**
562 * @brief UnRegister the Data Ready RNG Callback
563 * Data Ready RNG Callback is redirected to the weak HAL_RNG_ReadyDataCallback() predefined callback
564 * @param hrng RNG handle
565 * @retval HAL status
566 */
HAL_RNG_UnRegisterReadyDataCallback(RNG_HandleTypeDef * hrng)567 HAL_StatusTypeDef HAL_RNG_UnRegisterReadyDataCallback(RNG_HandleTypeDef *hrng)
568 {
569 HAL_StatusTypeDef status = HAL_OK;
570
571 /* Process locked */
572 __HAL_LOCK(hrng);
573
574 if (HAL_RNG_STATE_READY == hrng->State)
575 {
576 hrng->ReadyDataCallback = HAL_RNG_ReadyDataCallback; /* Legacy weak ReadyDataCallback */
577 }
578 else
579 {
580 /* Update the error code */
581 hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
582 /* Return error status */
583 status = HAL_ERROR;
584 }
585
586 /* Release Lock */
587 __HAL_UNLOCK(hrng);
588 return status;
589 }
590
591 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
592
593 /**
594 * @}
595 */
596
597 /** @addtogroup RNG_Exported_Functions_Group2
598 * @brief Peripheral Control functions
599 *
600 @verbatim
601 ===============================================================================
602 ##### Peripheral Control functions #####
603 ===============================================================================
604 [..] This section provides functions allowing to:
605 (+) Get the 32 bit Random number
606 (+) Get the 32 bit Random number with interrupt enabled
607 (+) Handle RNG interrupt request
608
609 @endverbatim
610 * @{
611 */
612
613 /**
614 * @brief Generates a 32-bit random number.
615 * @note This function checks value of RNG_FLAG_DRDY flag to know if valid
616 * random number is available in the DR register (RNG_FLAG_DRDY flag set
617 * whenever a random number is available through the RNG_DR register).
618 * After transitioning from 0 to 1 (random number available),
619 * RNG_FLAG_DRDY flag remains high until output buffer becomes empty after reading
620 * four words from the RNG_DR register, i.e. further function calls
621 * will immediately return a new u32 random number (additional words are
622 * available and can be read by the application, till RNG_FLAG_DRDY flag remains high).
623 * @note When no more random number data is available in DR register, RNG_FLAG_DRDY
624 * flag is automatically cleared.
625 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
626 * the configuration information for RNG.
627 * @param random32bit pointer to generated random number variable if successful.
628 * @retval HAL status
629 */
630
HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef * hrng,uint32_t * random32bit)631 HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit)
632 {
633 uint32_t tickstart;
634 HAL_StatusTypeDef status = HAL_OK;
635
636 /* Process Locked */
637 __HAL_LOCK(hrng);
638
639 /* Check RNG peripheral state */
640 if (hrng->State == HAL_RNG_STATE_READY)
641 {
642 /* Change RNG peripheral state */
643 hrng->State = HAL_RNG_STATE_BUSY;
644 /* Check if there is a seed error */
645 if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
646 {
647 /* Update the error code */
648 hrng->ErrorCode = HAL_RNG_ERROR_SEED;
649 /* Reset from seed error */
650 status = RNG_RecoverSeedError(hrng);
651 if (status == HAL_ERROR)
652 {
653 return status;
654 }
655 }
656
657 /* Get tick */
658 tickstart = HAL_GetTick();
659
660 /* Check if data register contains valid random data */
661 while (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET)
662 {
663 if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
664 {
665 /* New check to avoid false timeout detection in case of preemption */
666 if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET)
667 {
668 hrng->State = HAL_RNG_STATE_READY;
669 hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
670 /* Process Unlocked */
671 __HAL_UNLOCK(hrng);
672 return HAL_ERROR;
673 }
674 }
675 }
676
677 /* Get a 32bit Random number */
678 hrng->RandomNumber = hrng->Instance->DR;
679 /* In case of seed error, the value available in the RNG_DR register must not
680 be used as it may not have enough entropy */
681 if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
682 {
683 /* Update the error code */
684 hrng->ErrorCode = HAL_RNG_ERROR_SEED;
685 /* Clear bit DRDY */
686 CLEAR_BIT(hrng->Instance->SR, RNG_FLAG_DRDY);
687 }
688 else /* No seed error */
689 {
690 *random32bit = hrng->RandomNumber;
691 }
692 hrng->State = HAL_RNG_STATE_READY;
693 }
694 else
695 {
696 hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
697 status = HAL_ERROR;
698 }
699
700 /* Process Unlocked */
701 __HAL_UNLOCK(hrng);
702
703 return status;
704 }
705
706 /**
707 * @brief Generates a 32-bit random number in interrupt mode.
708 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
709 * the configuration information for RNG.
710 * @retval HAL status
711 */
HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef * hrng)712 HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng)
713 {
714 HAL_StatusTypeDef status = HAL_OK;
715
716 /* Process Locked */
717 __HAL_LOCK(hrng);
718
719 /* Check RNG peripheral state */
720 if (hrng->State == HAL_RNG_STATE_READY)
721 {
722 /* Change RNG peripheral state */
723 hrng->State = HAL_RNG_STATE_BUSY;
724
725 /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */
726 __HAL_RNG_ENABLE_IT(hrng);
727 }
728 else
729 {
730 /* Process Unlocked */
731 __HAL_UNLOCK(hrng);
732
733 hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
734 status = HAL_ERROR;
735 }
736
737 return status;
738 }
739
740 /**
741 * @brief Handles RNG interrupt request.
742 * @note In the case of a clock error, the RNG is no more able to generate
743 * random numbers because the PLL48CLK clock is not correct. User has
744 * to check that the clock controller is correctly configured to provide
745 * the RNG clock and clear the CEIS bit using __HAL_RNG_CLEAR_IT().
746 * The clock error has no impact on the previously generated
747 * random numbers, and the RNG_DR register contents can be used.
748 * @note In the case of a seed error, the generation of random numbers is
749 * interrupted as long as the SECS bit is '1'. If a number is
750 * available in the RNG_DR register, it must not be used because it may
751 * not have enough entropy. In this case, it is recommended to clear the
752 * SEIS bit using __HAL_RNG_CLEAR_IT(), then disable and enable
753 * the RNG peripheral to reinitialize and restart the RNG.
754 * @note User-written HAL_RNG_ErrorCallback() API is called once whether SEIS
755 * or CEIS are set.
756 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
757 * the configuration information for RNG.
758 * @retval None
759
760 */
HAL_RNG_IRQHandler(RNG_HandleTypeDef * hrng)761 void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng)
762 {
763 uint32_t rngclockerror = 0U;
764
765 /* RNG clock error interrupt occurred */
766 if (__HAL_RNG_GET_IT(hrng, RNG_IT_CEI) != RESET)
767 {
768 /* Update the error code */
769 hrng->ErrorCode = HAL_RNG_ERROR_CLOCK;
770 rngclockerror = 1U;
771 }
772 else if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
773 {
774 /* Check if Seed Error Current Status (SECS) is set */
775 if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) == RESET)
776 {
777 /* RNG IP performed the reset automatically (auto-reset) */
778 /* Clear bit SEIS */
779 CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
780 }
781 else
782 {
783 /* Seed Error has not been recovered : Update the error code */
784 hrng->ErrorCode = HAL_RNG_ERROR_SEED;
785 rngclockerror = 1U;
786 /* Disable the IT */
787 __HAL_RNG_DISABLE_IT(hrng);
788 }
789 }
790 else
791 {
792 /* Nothing to do */
793 }
794
795 if (rngclockerror == 1U)
796 {
797 /* Change RNG peripheral state */
798 hrng->State = HAL_RNG_STATE_ERROR;
799
800 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
801 /* Call registered Error callback */
802 hrng->ErrorCallback(hrng);
803 #else
804 /* Call legacy weak Error callback */
805 HAL_RNG_ErrorCallback(hrng);
806 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
807
808 /* Clear the clock error flag */
809 __HAL_RNG_CLEAR_IT(hrng, RNG_IT_CEI | RNG_IT_SEI);
810
811 return;
812 }
813
814 /* Check RNG data ready interrupt occurred */
815 if (__HAL_RNG_GET_IT(hrng, RNG_IT_DRDY) != RESET)
816 {
817 /* Generate random number once, so disable the IT */
818 __HAL_RNG_DISABLE_IT(hrng);
819
820 /* Get the 32bit Random number (DRDY flag automatically cleared) */
821 hrng->RandomNumber = hrng->Instance->DR;
822
823 if (hrng->State != HAL_RNG_STATE_ERROR)
824 {
825 /* Change RNG peripheral state */
826 hrng->State = HAL_RNG_STATE_READY;
827 /* Process Unlocked */
828 __HAL_UNLOCK(hrng);
829
830 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
831 /* Call registered Data Ready callback */
832 hrng->ReadyDataCallback(hrng, hrng->RandomNumber);
833 #else
834 /* Call legacy weak Data Ready callback */
835 HAL_RNG_ReadyDataCallback(hrng, hrng->RandomNumber);
836 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
837 }
838 }
839 }
840
841 /**
842 * @brief Read latest generated random number.
843 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
844 * the configuration information for RNG.
845 * @retval random value
846 */
HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef * hrng)847 uint32_t HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef *hrng)
848 {
849 return (hrng->RandomNumber);
850 }
851
852 /**
853 * @brief Data Ready callback in non-blocking mode.
854 * @note When RNG_FLAG_DRDY flag value is set, first random number has been read
855 * from DR register in IRQ Handler and is provided as callback parameter.
856 * Depending on valid data available in the conditioning output buffer,
857 * additional words can be read by the application from DR register till
858 * DRDY bit remains high.
859 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
860 * the configuration information for RNG.
861 * @param random32bit generated random number.
862 * @retval None
863 */
HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef * hrng,uint32_t random32bit)864 __weak void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
865 {
866 /* Prevent unused argument(s) compilation warning */
867 UNUSED(hrng);
868 UNUSED(random32bit);
869 /* NOTE : This function should not be modified. When the callback is needed,
870 function HAL_RNG_ReadyDataCallback must be implemented in the user file.
871 */
872 }
873
874 /**
875 * @brief RNG error callbacks.
876 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
877 * the configuration information for RNG.
878 * @retval None
879 */
HAL_RNG_ErrorCallback(RNG_HandleTypeDef * hrng)880 __weak void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng)
881 {
882 /* Prevent unused argument(s) compilation warning */
883 UNUSED(hrng);
884 /* NOTE : This function should not be modified. When the callback is needed,
885 function HAL_RNG_ErrorCallback must be implemented in the user file.
886 */
887 }
888 /**
889 * @}
890 */
891
892
893 /** @addtogroup RNG_Exported_Functions_Group3
894 * @brief Peripheral State functions
895 *
896 @verbatim
897 ===============================================================================
898 ##### Peripheral State functions #####
899 ===============================================================================
900 [..]
901 This subsection permits to get in run-time the status of the peripheral
902 and the data flow.
903
904 @endverbatim
905 * @{
906 */
907
908 /**
909 * @brief Returns the RNG state.
910 * @param hrng pointer to a RNG_HandleTypeDef structure that contains
911 * the configuration information for RNG.
912 * @retval HAL state
913 */
HAL_RNG_GetState(RNG_HandleTypeDef * hrng)914 HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng)
915 {
916 return hrng->State;
917 }
918
919 /**
920 * @brief Return the RNG handle error code.
921 * @param hrng: pointer to a RNG_HandleTypeDef structure.
922 * @retval RNG Error Code
923 */
HAL_RNG_GetError(RNG_HandleTypeDef * hrng)924 uint32_t HAL_RNG_GetError(RNG_HandleTypeDef *hrng)
925 {
926 /* Return RNG Error Code */
927 return hrng->ErrorCode;
928 }
929 /**
930 * @}
931 */
932
933 /**
934 * @}
935 */
936 /* Private functions ---------------------------------------------------------*/
937 /** @addtogroup RNG_Private_Functions
938 * @{
939 */
940
941 /**
942 * @brief RNG sequence to recover from a seed error
943 * @param hrng pointer to a RNG_HandleTypeDef structure.
944 * @retval HAL status
945 */
RNG_RecoverSeedError(RNG_HandleTypeDef * hrng)946 HAL_StatusTypeDef RNG_RecoverSeedError(RNG_HandleTypeDef *hrng)
947 {
948 __IO uint32_t count = 0U;
949
950 /*Check if seed error current status (SECS)is set */
951 if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) == RESET)
952 {
953 /* RNG performed the reset automatically (auto-reset) */
954 /* Clear bit SEIS */
955 CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
956 }
957 else /* Sequence to fully recover from a seed error*/
958 {
959 /* Writing bit CONDRST=1*/
960 SET_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
961 /* Writing bit CONDRST=0*/
962 CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
963
964 /* Wait for conditioning reset process to be completed */
965 count = RNG_TIMEOUT_VALUE;
966 do
967 {
968 count-- ;
969 if (count == 0U)
970 {
971 hrng->State = HAL_RNG_STATE_READY;
972 hrng->ErrorCode |= HAL_RNG_ERROR_TIMEOUT;
973 /* Process Unlocked */
974 __HAL_UNLOCK(hrng);
975 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
976 /* Call registered Error callback */
977 hrng->ErrorCallback(hrng);
978 #else
979 /* Call legacy weak Error callback */
980 HAL_RNG_ErrorCallback(hrng);
981 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
982 return HAL_ERROR;
983 }
984 } while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST));
985
986 if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
987 {
988 /* Clear bit SEIS */
989 CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
990 }
991
992 /* Wait for SECS to be cleared */
993 count = RNG_TIMEOUT_VALUE;
994 do
995 {
996 count-- ;
997 if (count == 0U)
998 {
999 hrng->State = HAL_RNG_STATE_READY;
1000 hrng->ErrorCode |= HAL_RNG_ERROR_TIMEOUT;
1001 /* Process Unlocked */
1002 __HAL_UNLOCK(hrng);
1003 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
1004 /* Call registered Error callback */
1005 hrng->ErrorCallback(hrng);
1006 #else
1007 /* Call legacy weak Error callback */
1008 HAL_RNG_ErrorCallback(hrng);
1009 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
1010 return HAL_ERROR;
1011 }
1012 } while (HAL_IS_BIT_SET(hrng->Instance->SR, RNG_FLAG_SECS));
1013 }
1014 /* Update the error code */
1015 hrng->ErrorCode &= ~ HAL_RNG_ERROR_SEED;
1016 return HAL_OK;
1017 }
1018
1019 /**
1020 * @}
1021 */
1022
1023
1024 #endif /* HAL_RNG_MODULE_ENABLED */
1025 /**
1026 * @}
1027 */
1028
1029 #endif /* RNG */
1030
1031 /**
1032 * @}
1033 */
1034
1035