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