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