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