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