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