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