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