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