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