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