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