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