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