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