STM32H735xx HAL User Manual
stm32h7xx_hal_rng.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h7xx_hal_rng.c
00004   * @author  MCD Application Team
00005   * @brief   RNG HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the Random Number Generator (RNG) peripheral:
00008   *           + Initialization and configuration functions
00009   *           + Peripheral Control functions
00010   *           + Peripheral State functions
00011   *
00012   ******************************************************************************
00013   * @attention
00014   *
00015   * Copyright (c) 2017 STMicroelectronics.
00016   * All rights reserved.
00017   *
00018   * This software is licensed under terms that can be found in the LICENSE file
00019   * in the root directory of this software component.
00020   * If no LICENSE file comes with this software, it is provided AS-IS.
00021   *
00022   ******************************************************************************
00023   @verbatim
00024   ==============================================================================
00025                      ##### How to use this driver #####
00026   ==============================================================================
00027   [..]
00028       The RNG HAL driver can be used as follows:
00029 
00030       (#) Enable the RNG controller clock using __HAL_RCC_RNG_CLK_ENABLE() macro
00031           in HAL_RNG_MspInit().
00032       (#) Activate the RNG peripheral using HAL_RNG_Init() function.
00033       (#) Wait until the 32 bit Random Number Generator contains a valid
00034           random data using (polling/interrupt) mode.
00035       (#) Get the 32 bit random number using HAL_RNG_GenerateRandomNumber() function.
00036 
00037     ##### Callback registration #####
00038     ==================================
00039 
00040     [..]
00041     The compilation define USE_HAL_RNG_REGISTER_CALLBACKS when set to 1
00042     allows the user to configure dynamically the driver callbacks.
00043 
00044     [..]
00045     Use Function HAL_RNG_RegisterCallback() to register a user callback.
00046     Function HAL_RNG_RegisterCallback() allows to register following callbacks:
00047     (+) ErrorCallback             : RNG Error Callback.
00048     (+) MspInitCallback           : RNG MspInit.
00049     (+) MspDeInitCallback         : RNG MspDeInit.
00050     This function takes as parameters the HAL peripheral handle, the Callback ID
00051     and a pointer to the user callback function.
00052 
00053     [..]
00054     Use function HAL_RNG_UnRegisterCallback() to reset a callback to the default
00055     weak (surcharged) function.
00056     HAL_RNG_UnRegisterCallback() takes as parameters the HAL peripheral handle,
00057     and the Callback ID.
00058     This function allows to reset following callbacks:
00059     (+) ErrorCallback             : RNG Error Callback.
00060     (+) MspInitCallback           : RNG MspInit.
00061     (+) MspDeInitCallback         : RNG MspDeInit.
00062 
00063     [..]
00064     For specific callback ReadyDataCallback, use dedicated register callbacks:
00065     respectively HAL_RNG_RegisterReadyDataCallback() , HAL_RNG_UnRegisterReadyDataCallback().
00066 
00067     [..]
00068     By default, after the HAL_RNG_Init() and when the state is HAL_RNG_STATE_RESET
00069     all callbacks are set to the corresponding weak (surcharged) functions:
00070     example HAL_RNG_ErrorCallback().
00071     Exception done for MspInit and MspDeInit functions that are respectively
00072     reset to the legacy weak (surcharged) functions in the HAL_RNG_Init()
00073     and HAL_RNG_DeInit() only when these callbacks are null (not registered beforehand).
00074     If not, MspInit or MspDeInit are not null, the HAL_RNG_Init() and HAL_RNG_DeInit()
00075     keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
00076 
00077     [..]
00078     Callbacks can be registered/unregistered in HAL_RNG_STATE_READY state only.
00079     Exception done MspInit/MspDeInit that can be registered/unregistered
00080     in HAL_RNG_STATE_READY or HAL_RNG_STATE_RESET state, thus registered (user)
00081     MspInit/DeInit callbacks can be used during the Init/DeInit.
00082     In that case first register the MspInit/MspDeInit user callbacks
00083     using HAL_RNG_RegisterCallback() before calling HAL_RNG_DeInit()
00084     or HAL_RNG_Init() function.
00085 
00086     [..]
00087     When The compilation define USE_HAL_RNG_REGISTER_CALLBACKS is set to 0 or
00088     not defined, the callback registration feature is not available
00089     and weak (surcharged) callbacks are used.
00090 
00091   @endverbatim
00092   ******************************************************************************
00093   */
00094 
00095 /* Includes ------------------------------------------------------------------*/
00096 #include "stm32h7xx_hal.h"
00097 
00098 /** @addtogroup STM32H7xx_HAL_Driver
00099   * @{
00100   */
00101 
00102 #if defined (RNG)
00103 
00104 /** @addtogroup RNG
00105   * @brief RNG HAL module driver.
00106   * @{
00107   */
00108 
00109 #ifdef HAL_RNG_MODULE_ENABLED
00110 
00111 /* Private types -------------------------------------------------------------*/
00112 /* Private defines -----------------------------------------------------------*/
00113 /** @defgroup RNG_Private_Defines RNG Private Defines
00114   * @{
00115   */
00116 /*  Health test control register information to use in CCM algorithm */
00117 #define RNG_HTCFG_1   0x17590ABCU /*!< Magic number */
00118 #if defined(RNG_VER_3_1) || defined(RNG_VER_3_0)
00119 #define RNG_HTCFG     0x000CAA74U /*!< For best latency and to be compliant with NIST */
00120 #else /* RNG_VER_3_2 */
00121 #define RNG_HTCFG     0x00007274U /*!< For best latency and to be compliant with NIST */
00122 #endif /* RNG_VER_3_1 || RNG_VER_3_0 */
00123 /**
00124   * @}
00125   */
00126 /* Private variables ---------------------------------------------------------*/
00127 /* Private constants ---------------------------------------------------------*/
00128 /** @defgroup RNG_Private_Constants RNG Private Constants
00129   * @{
00130   */
00131 #define RNG_TIMEOUT_VALUE     2U
00132 /**
00133   * @}
00134   */
00135 /* Private macros ------------------------------------------------------------*/
00136 /* Private functions prototypes ----------------------------------------------*/
00137 /* Exported functions --------------------------------------------------------*/
00138 
00139 /** @addtogroup RNG_Exported_Functions
00140   * @{
00141   */
00142 
00143 /** @addtogroup RNG_Exported_Functions_Group1
00144   *  @brief   Initialization and configuration functions
00145   *
00146 @verbatim
00147  ===============================================================================
00148           ##### Initialization and configuration functions #####
00149  ===============================================================================
00150     [..]  This section provides functions allowing to:
00151       (+) Initialize the RNG according to the specified parameters
00152           in the RNG_InitTypeDef and create the associated handle
00153       (+) DeInitialize the RNG peripheral
00154       (+) Initialize the RNG MSP
00155       (+) DeInitialize RNG MSP
00156 
00157 @endverbatim
00158   * @{
00159   */
00160 
00161 /**
00162   * @brief  Initializes the RNG peripheral and creates the associated handle.
00163   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00164   *                the configuration information for RNG.
00165   * @retval HAL status
00166   */
00167 HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng)
00168 {
00169   uint32_t tickstart;
00170   /* Check the RNG handle allocation */
00171   if (hrng == NULL)
00172   {
00173     return HAL_ERROR;
00174   }
00175   /* Check the parameters */
00176   assert_param(IS_RNG_ALL_INSTANCE(hrng->Instance));
00177   assert_param(IS_RNG_CED(hrng->Init.ClockErrorDetection));
00178 
00179 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
00180   if (hrng->State == HAL_RNG_STATE_RESET)
00181   {
00182     /* Allocate lock resource and initialize it */
00183     hrng->Lock = HAL_UNLOCKED;
00184 
00185     hrng->ReadyDataCallback  = HAL_RNG_ReadyDataCallback;  /* Legacy weak ReadyDataCallback  */
00186     hrng->ErrorCallback      = HAL_RNG_ErrorCallback;      /* Legacy weak ErrorCallback      */
00187 
00188     if (hrng->MspInitCallback == NULL)
00189     {
00190       hrng->MspInitCallback = HAL_RNG_MspInit; /* Legacy weak MspInit  */
00191     }
00192 
00193     /* Init the low level hardware */
00194     hrng->MspInitCallback(hrng);
00195   }
00196 #else
00197   if (hrng->State == HAL_RNG_STATE_RESET)
00198   {
00199     /* Allocate lock resource and initialize it */
00200     hrng->Lock = HAL_UNLOCKED;
00201 
00202     /* Init the low level hardware */
00203     HAL_RNG_MspInit(hrng);
00204   }
00205 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
00206 
00207   /* Change RNG peripheral state */
00208   hrng->State = HAL_RNG_STATE_BUSY;
00209 
00210 #if defined(RNG_CR_CONDRST)
00211   /* Disable RNG */
00212   __HAL_RNG_DISABLE(hrng);
00213 
00214   /* Clock Error Detection Configuration when CONDRT bit is set to 1 */
00215   MODIFY_REG(hrng->Instance->CR, RNG_CR_CED | RNG_CR_CONDRST, hrng->Init.ClockErrorDetection | RNG_CR_CONDRST);
00216 
00217 #if defined(RNG_VER_3_2) || defined(RNG_VER_3_1) || defined(RNG_VER_3_0)
00218   /*!< magic number must be written immediately before to RNG_HTCRG */
00219   WRITE_REG(hrng->Instance->HTCR, RNG_HTCFG_1);
00220   /* for best latency and to be compliant with NIST */
00221   WRITE_REG(hrng->Instance->HTCR, RNG_HTCFG);
00222 #endif /* RNG_VER_3_2 || RNG_VER_3_1 || RNG_VER_3_0 */
00223 
00224   /* Writing bit CONDRST=0 */
00225   CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
00226 
00227   /* Get tick */
00228   tickstart = HAL_GetTick();
00229 
00230   /* Wait for conditioning reset process to be completed */
00231   while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
00232   {
00233     if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
00234     {
00235       /* New check to avoid false timeout detection in case of preemption */
00236       if (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
00237       {
00238         hrng->State = HAL_RNG_STATE_READY;
00239         hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
00240         return HAL_ERROR;
00241       }
00242     }
00243   }
00244 #else
00245   /* Clock Error Detection Configuration */
00246   MODIFY_REG(hrng->Instance->CR, RNG_CR_CED, hrng->Init.ClockErrorDetection);
00247 #endif /* RNG_CR_CONDRST */
00248 
00249   /* Enable the RNG Peripheral */
00250   __HAL_RNG_ENABLE(hrng);
00251 
00252   /* verify that no seed error */
00253   if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
00254   {
00255     hrng->State = HAL_RNG_STATE_ERROR;
00256     return HAL_ERROR;
00257   }
00258   /* Get tick */
00259   tickstart = HAL_GetTick();
00260   /* Check if data register contains valid random data */
00261   while (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) != RESET)
00262   {
00263     if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
00264     {
00265       /* New check to avoid false timeout detection in case of preemption */
00266       if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) != RESET)
00267       {
00268         hrng->State = HAL_RNG_STATE_ERROR;
00269         hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
00270         return HAL_ERROR;
00271       }
00272     }
00273   }
00274 
00275   /* Initialize the RNG state */
00276   hrng->State = HAL_RNG_STATE_READY;
00277 
00278   /* Initialise the error code */
00279   hrng->ErrorCode = HAL_RNG_ERROR_NONE;
00280 
00281   /* Return function status */
00282   return HAL_OK;
00283 }
00284 
00285 /**
00286   * @brief  DeInitializes the RNG peripheral.
00287   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00288   *                the configuration information for RNG.
00289   * @retval HAL status
00290   */
00291 HAL_StatusTypeDef HAL_RNG_DeInit(RNG_HandleTypeDef *hrng)
00292 {
00293 #if defined(RNG_CR_CONDRST)
00294   uint32_t tickstart;
00295 
00296 #endif /* RNG_CR_CONDRST */
00297   /* Check the RNG handle allocation */
00298   if (hrng == NULL)
00299   {
00300     return HAL_ERROR;
00301   }
00302 
00303 #if defined(RNG_CR_CONDRST)
00304   /* Clear Clock Error Detection bit when CONDRT bit is set to 1 */
00305   MODIFY_REG(hrng->Instance->CR, RNG_CR_CED | RNG_CR_CONDRST, RNG_CED_ENABLE | RNG_CR_CONDRST);
00306 
00307   /* Writing bit CONDRST=0 */
00308   CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
00309 
00310   /* Get tick */
00311   tickstart = HAL_GetTick();
00312 
00313   /* Wait for conditioning reset process to be completed */
00314   while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
00315   {
00316     if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
00317     {
00318       /* New check to avoid false timeout detection in case of preemption */
00319       if (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
00320       {
00321         hrng->State = HAL_RNG_STATE_READY;
00322         hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
00323         /* Process Unlocked */
00324         __HAL_UNLOCK(hrng);
00325         return HAL_ERROR;
00326       }
00327     }
00328   }
00329 
00330 #else
00331   /* Clear Clock Error Detection bit */
00332   CLEAR_BIT(hrng->Instance->CR, RNG_CR_CED);
00333 #endif /* RNG_CR_CONDRST */
00334   /* Disable the RNG Peripheral */
00335   CLEAR_BIT(hrng->Instance->CR, RNG_CR_IE | RNG_CR_RNGEN);
00336 
00337   /* Clear RNG interrupt status flags */
00338   CLEAR_BIT(hrng->Instance->SR, RNG_SR_CEIS | RNG_SR_SEIS);
00339 
00340 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
00341   if (hrng->MspDeInitCallback == NULL)
00342   {
00343     hrng->MspDeInitCallback = HAL_RNG_MspDeInit; /* Legacy weak MspDeInit  */
00344   }
00345 
00346   /* DeInit the low level hardware */
00347   hrng->MspDeInitCallback(hrng);
00348 #else
00349   /* DeInit the low level hardware */
00350   HAL_RNG_MspDeInit(hrng);
00351 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
00352 
00353   /* Update the RNG state */
00354   hrng->State = HAL_RNG_STATE_RESET;
00355 
00356   /* Initialise the error code */
00357   hrng->ErrorCode = HAL_RNG_ERROR_NONE;
00358 
00359   /* Release Lock */
00360   __HAL_UNLOCK(hrng);
00361 
00362   /* Return the function status */
00363   return HAL_OK;
00364 }
00365 
00366 /**
00367   * @brief  Initializes the RNG MSP.
00368   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00369   *                the configuration information for RNG.
00370   * @retval None
00371   */
00372 __weak void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng)
00373 {
00374   /* Prevent unused argument(s) compilation warning */
00375   UNUSED(hrng);
00376   /* NOTE : This function should not be modified. When the callback is needed,
00377             function HAL_RNG_MspInit must be implemented in the user file.
00378    */
00379 }
00380 
00381 /**
00382   * @brief  DeInitializes the RNG MSP.
00383   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00384   *                the configuration information for RNG.
00385   * @retval None
00386   */
00387 __weak void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng)
00388 {
00389   /* Prevent unused argument(s) compilation warning */
00390   UNUSED(hrng);
00391   /* NOTE : This function should not be modified. When the callback is needed,
00392             function HAL_RNG_MspDeInit must be implemented in the user file.
00393    */
00394 }
00395 
00396 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
00397 /**
00398   * @brief  Register a User RNG Callback
00399   *         To be used instead of the weak predefined callback
00400   * @param  hrng RNG handle
00401   * @param  CallbackID ID of the callback to be registered
00402   *         This parameter can be one of the following values:
00403   *          @arg @ref HAL_RNG_ERROR_CB_ID Error callback ID
00404   *          @arg @ref HAL_RNG_MSPINIT_CB_ID MspInit callback ID
00405   *          @arg @ref HAL_RNG_MSPDEINIT_CB_ID MspDeInit callback ID
00406   * @param  pCallback pointer to the Callback function
00407   * @retval HAL status
00408   */
00409 HAL_StatusTypeDef HAL_RNG_RegisterCallback(RNG_HandleTypeDef *hrng, HAL_RNG_CallbackIDTypeDef CallbackID,
00410                                            pRNG_CallbackTypeDef pCallback)
00411 {
00412   HAL_StatusTypeDef status = HAL_OK;
00413 
00414   if (pCallback == NULL)
00415   {
00416     /* Update the error code */
00417     hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00418     return HAL_ERROR;
00419   }
00420   /* Process locked */
00421   __HAL_LOCK(hrng);
00422 
00423   if (HAL_RNG_STATE_READY == hrng->State)
00424   {
00425     switch (CallbackID)
00426     {
00427       case HAL_RNG_ERROR_CB_ID :
00428         hrng->ErrorCallback = pCallback;
00429         break;
00430 
00431       case HAL_RNG_MSPINIT_CB_ID :
00432         hrng->MspInitCallback = pCallback;
00433         break;
00434 
00435       case HAL_RNG_MSPDEINIT_CB_ID :
00436         hrng->MspDeInitCallback = pCallback;
00437         break;
00438 
00439       default :
00440         /* Update the error code */
00441         hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00442         /* Return error status */
00443         status =  HAL_ERROR;
00444         break;
00445     }
00446   }
00447   else if (HAL_RNG_STATE_RESET == hrng->State)
00448   {
00449     switch (CallbackID)
00450     {
00451       case HAL_RNG_MSPINIT_CB_ID :
00452         hrng->MspInitCallback = pCallback;
00453         break;
00454 
00455       case HAL_RNG_MSPDEINIT_CB_ID :
00456         hrng->MspDeInitCallback = pCallback;
00457         break;
00458 
00459       default :
00460         /* Update the error code */
00461         hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00462         /* Return error status */
00463         status =  HAL_ERROR;
00464         break;
00465     }
00466   }
00467   else
00468   {
00469     /* Update the error code */
00470     hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00471     /* Return error status */
00472     status =  HAL_ERROR;
00473   }
00474 
00475   /* Release Lock */
00476   __HAL_UNLOCK(hrng);
00477   return status;
00478 }
00479 
00480 /**
00481   * @brief  Unregister an RNG Callback
00482   *         RNG callabck is redirected to the weak predefined callback
00483   * @param  hrng RNG handle
00484   * @param  CallbackID ID of the callback to be unregistered
00485   *         This parameter can be one of the following values:
00486   *          @arg @ref HAL_RNG_ERROR_CB_ID Error callback ID
00487   *          @arg @ref HAL_RNG_MSPINIT_CB_ID MspInit callback ID
00488   *          @arg @ref HAL_RNG_MSPDEINIT_CB_ID MspDeInit callback ID
00489   * @retval HAL status
00490   */
00491 HAL_StatusTypeDef HAL_RNG_UnRegisterCallback(RNG_HandleTypeDef *hrng, HAL_RNG_CallbackIDTypeDef CallbackID)
00492 {
00493   HAL_StatusTypeDef status = HAL_OK;
00494 
00495   /* Process locked */
00496   __HAL_LOCK(hrng);
00497 
00498   if (HAL_RNG_STATE_READY == hrng->State)
00499   {
00500     switch (CallbackID)
00501     {
00502       case HAL_RNG_ERROR_CB_ID :
00503         hrng->ErrorCallback = HAL_RNG_ErrorCallback;          /* Legacy weak ErrorCallback  */
00504         break;
00505 
00506       case HAL_RNG_MSPINIT_CB_ID :
00507         hrng->MspInitCallback = HAL_RNG_MspInit;              /* Legacy weak MspInit  */
00508         break;
00509 
00510       case HAL_RNG_MSPDEINIT_CB_ID :
00511         hrng->MspDeInitCallback = HAL_RNG_MspDeInit;          /* Legacy weak MspDeInit  */
00512         break;
00513 
00514       default :
00515         /* Update the error code */
00516         hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00517         /* Return error status */
00518         status =  HAL_ERROR;
00519         break;
00520     }
00521   }
00522   else if (HAL_RNG_STATE_RESET == hrng->State)
00523   {
00524     switch (CallbackID)
00525     {
00526       case HAL_RNG_MSPINIT_CB_ID :
00527         hrng->MspInitCallback = HAL_RNG_MspInit;              /* Legacy weak MspInit  */
00528         break;
00529 
00530       case HAL_RNG_MSPDEINIT_CB_ID :
00531         hrng->MspDeInitCallback = HAL_RNG_MspDeInit;          /* Legacy weak MspInit  */
00532         break;
00533 
00534       default :
00535         /* Update the error code */
00536         hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00537         /* Return error status */
00538         status =  HAL_ERROR;
00539         break;
00540     }
00541   }
00542   else
00543   {
00544     /* Update the error code */
00545     hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00546     /* Return error status */
00547     status =  HAL_ERROR;
00548   }
00549 
00550   /* Release Lock */
00551   __HAL_UNLOCK(hrng);
00552   return status;
00553 }
00554 
00555 /**
00556   * @brief  Register Data Ready RNG Callback
00557   *         To be used instead of the weak HAL_RNG_ReadyDataCallback() predefined callback
00558   * @param  hrng RNG handle
00559   * @param  pCallback pointer to the Data Ready Callback function
00560   * @retval HAL status
00561   */
00562 HAL_StatusTypeDef HAL_RNG_RegisterReadyDataCallback(RNG_HandleTypeDef *hrng, pRNG_ReadyDataCallbackTypeDef pCallback)
00563 {
00564   HAL_StatusTypeDef status = HAL_OK;
00565 
00566   if (pCallback == NULL)
00567   {
00568     /* Update the error code */
00569     hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00570     return HAL_ERROR;
00571   }
00572   /* Process locked */
00573   __HAL_LOCK(hrng);
00574 
00575   if (HAL_RNG_STATE_READY == hrng->State)
00576   {
00577     hrng->ReadyDataCallback = pCallback;
00578   }
00579   else
00580   {
00581     /* Update the error code */
00582     hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00583     /* Return error status */
00584     status =  HAL_ERROR;
00585   }
00586 
00587   /* Release Lock */
00588   __HAL_UNLOCK(hrng);
00589   return status;
00590 }
00591 
00592 /**
00593   * @brief  UnRegister the Data Ready RNG Callback
00594   *         Data Ready RNG Callback is redirected to the weak HAL_RNG_ReadyDataCallback() predefined callback
00595   * @param  hrng RNG handle
00596   * @retval HAL status
00597   */
00598 HAL_StatusTypeDef HAL_RNG_UnRegisterReadyDataCallback(RNG_HandleTypeDef *hrng)
00599 {
00600   HAL_StatusTypeDef status = HAL_OK;
00601 
00602   /* Process locked */
00603   __HAL_LOCK(hrng);
00604 
00605   if (HAL_RNG_STATE_READY == hrng->State)
00606   {
00607     hrng->ReadyDataCallback = HAL_RNG_ReadyDataCallback; /* Legacy weak ReadyDataCallback  */
00608   }
00609   else
00610   {
00611     /* Update the error code */
00612     hrng->ErrorCode = HAL_RNG_ERROR_INVALID_CALLBACK;
00613     /* Return error status */
00614     status =  HAL_ERROR;
00615   }
00616 
00617   /* Release Lock */
00618   __HAL_UNLOCK(hrng);
00619   return status;
00620 }
00621 
00622 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
00623 
00624 /**
00625   * @}
00626   */
00627 
00628 /** @addtogroup RNG_Exported_Functions_Group2
00629   *  @brief   Peripheral Control functions
00630   *
00631 @verbatim
00632  ===============================================================================
00633                       ##### Peripheral Control functions #####
00634  ===============================================================================
00635     [..]  This section provides functions allowing to:
00636       (+) Get the 32 bit Random number
00637       (+) Get the 32 bit Random number with interrupt enabled
00638       (+) Handle RNG interrupt request
00639 
00640 @endverbatim
00641   * @{
00642   */
00643 
00644 /**
00645   * @brief  Generates a 32-bit random number.
00646   * @note   This function checks value of RNG_FLAG_DRDY flag to know if valid
00647   *         random number is available in the DR register (RNG_FLAG_DRDY flag set
00648   *         whenever a random number is available through the RNG_DR register).
00649   *         After transitioning from 0 to 1 (random number available),
00650   *         RNG_FLAG_DRDY flag remains high until output buffer becomes empty after reading
00651   *         four words from the RNG_DR register, i.e. further function calls
00652   *         will immediately return a new u32 random number (additional words are
00653   *         available and can be read by the application, till RNG_FLAG_DRDY flag remains high).
00654   * @note   When no more random number data is available in DR register, RNG_FLAG_DRDY
00655   *         flag is automatically cleared.
00656   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00657   *                the configuration information for RNG.
00658   * @param  random32bit pointer to generated random number variable if successful.
00659   * @retval HAL status
00660   */
00661 
00662 HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit)
00663 {
00664   uint32_t tickstart;
00665   HAL_StatusTypeDef status = HAL_OK;
00666 
00667   /* Process Locked */
00668   __HAL_LOCK(hrng);
00669 
00670   /* Check RNG peripheral state */
00671   if (hrng->State == HAL_RNG_STATE_READY)
00672   {
00673     /* Change RNG peripheral state */
00674     hrng->State = HAL_RNG_STATE_BUSY;
00675 #if defined(RNG_CR_CONDRST)
00676     /* Check if there is a seed error */
00677     if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
00678     {
00679       /* Update the error code */
00680       hrng->ErrorCode = HAL_RNG_ERROR_SEED;
00681       /* Reset from seed error */
00682       status = RNG_RecoverSeedError(hrng);
00683       if (status == HAL_ERROR)
00684       {
00685         return status;
00686       }
00687     }
00688 #endif /* RNG_CR_CONDRST */
00689 
00690     /* Get tick */
00691     tickstart = HAL_GetTick();
00692 
00693     /* Check if data register contains valid random data */
00694     while (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET)
00695     {
00696       if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
00697       {
00698         /* New check to avoid false timeout detection in case of preemption */
00699         if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET)
00700         {
00701           hrng->State = HAL_RNG_STATE_READY;
00702           hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
00703           /* Process Unlocked */
00704           __HAL_UNLOCK(hrng);
00705           return HAL_ERROR;
00706         }
00707       }
00708     }
00709 
00710     /* Get a 32bit Random number */
00711     hrng->RandomNumber = hrng->Instance->DR;
00712 #if defined(RNG_CR_CONDRST)
00713     /* In case of seed error, the value available in the RNG_DR register must not
00714        be used as it may not have enough entropy */
00715     if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
00716     {
00717       /* Update the error code */
00718       hrng->ErrorCode = HAL_RNG_ERROR_SEED;
00719       /* Clear bit DRDY */
00720       CLEAR_BIT(hrng->Instance->SR, RNG_FLAG_DRDY);
00721     }
00722     else /* No seed error */
00723     {
00724       *random32bit = hrng->RandomNumber;
00725     }
00726 #else
00727     *random32bit = hrng->RandomNumber;
00728 
00729 #endif /* RNG_CR_CONDRST */
00730     hrng->State = HAL_RNG_STATE_READY;
00731   }
00732   else
00733   {
00734     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
00735     status = HAL_ERROR;
00736   }
00737 
00738   /* Process Unlocked */
00739   __HAL_UNLOCK(hrng);
00740 
00741   return status;
00742 }
00743 
00744 /**
00745   * @brief  Generates a 32-bit random number in interrupt mode.
00746   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00747   *                the configuration information for RNG.
00748   * @retval HAL status
00749   */
00750 HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng)
00751 {
00752   HAL_StatusTypeDef status = HAL_OK;
00753 
00754   /* Process Locked */
00755   __HAL_LOCK(hrng);
00756 
00757   /* Check RNG peripheral state */
00758   if (hrng->State == HAL_RNG_STATE_READY)
00759   {
00760     /* Change RNG peripheral state */
00761     hrng->State = HAL_RNG_STATE_BUSY;
00762 
00763     /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */
00764     __HAL_RNG_ENABLE_IT(hrng);
00765   }
00766   else
00767   {
00768     /* Process Unlocked */
00769     __HAL_UNLOCK(hrng);
00770 
00771     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
00772     status = HAL_ERROR;
00773   }
00774 
00775   return status;
00776 }
00777 
00778 /**
00779   * @brief  Handles RNG interrupt request.
00780   * @note   In the case of a clock error, the RNG is no more able to generate
00781   *         random numbers because the PLL48CLK clock is not correct. User has
00782   *         to check that the clock controller is correctly configured to provide
00783   *         the RNG clock and clear the CEIS bit using __HAL_RNG_CLEAR_IT().
00784   *         The clock error has no impact on the previously generated
00785   *         random numbers, and the RNG_DR register contents can be used.
00786   * @note   In the case of a seed error, the generation of random numbers is
00787   *         interrupted as long as the SECS bit is '1'. If a number is
00788   *         available in the RNG_DR register, it must not be used because it may
00789   *         not have enough entropy. In this case, it is recommended to clear the
00790   *         SEIS bit using __HAL_RNG_CLEAR_IT(), then disable and enable
00791   *         the RNG peripheral to reinitialize and restart the RNG.
00792   * @note   User-written HAL_RNG_ErrorCallback() API is called once whether SEIS
00793   *         or CEIS are set.
00794   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00795   *                the configuration information for RNG.
00796   * @retval None
00797 
00798   */
00799 void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng)
00800 {
00801   uint32_t rngclockerror = 0U;
00802 
00803   /* RNG clock error interrupt occurred */
00804   if (__HAL_RNG_GET_IT(hrng, RNG_IT_CEI) != RESET)
00805   {
00806     /* Update the error code */
00807     hrng->ErrorCode = HAL_RNG_ERROR_CLOCK;
00808     rngclockerror = 1U;
00809   }
00810   else if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
00811   {
00812     /* Check if Seed Error Current Status (SECS) is set */
00813     if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) == RESET)
00814     {
00815       /* RNG IP performed the reset automatically (auto-reset) */
00816       /* Clear bit SEIS */
00817       CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
00818     }
00819     else
00820     {
00821       /* Seed Error has not been recovered : Update the error code */
00822       hrng->ErrorCode = HAL_RNG_ERROR_SEED;
00823       rngclockerror = 1U;
00824       /* Disable the IT */
00825       __HAL_RNG_DISABLE_IT(hrng);
00826     }
00827   }
00828   else
00829   {
00830     /* Nothing to do */
00831   }
00832 
00833   if (rngclockerror == 1U)
00834   {
00835     /* Change RNG peripheral state */
00836     hrng->State = HAL_RNG_STATE_ERROR;
00837 
00838 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
00839     /* Call registered Error callback */
00840     hrng->ErrorCallback(hrng);
00841 #else
00842     /* Call legacy weak Error callback */
00843     HAL_RNG_ErrorCallback(hrng);
00844 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
00845 
00846     /* Clear the clock error flag */
00847     __HAL_RNG_CLEAR_IT(hrng, RNG_IT_CEI | RNG_IT_SEI);
00848 
00849     return;
00850   }
00851 
00852   /* Check RNG data ready interrupt occurred */
00853   if (__HAL_RNG_GET_IT(hrng, RNG_IT_DRDY) != RESET)
00854   {
00855     /* Generate random number once, so disable the IT */
00856     __HAL_RNG_DISABLE_IT(hrng);
00857 
00858     /* Get the 32bit Random number (DRDY flag automatically cleared) */
00859     hrng->RandomNumber = hrng->Instance->DR;
00860 
00861     if (hrng->State != HAL_RNG_STATE_ERROR)
00862     {
00863       /* Change RNG peripheral state */
00864       hrng->State = HAL_RNG_STATE_READY;
00865       /* Process Unlocked */
00866       __HAL_UNLOCK(hrng);
00867 
00868 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
00869       /* Call registered Data Ready callback */
00870       hrng->ReadyDataCallback(hrng, hrng->RandomNumber);
00871 #else
00872       /* Call legacy weak Data Ready callback */
00873       HAL_RNG_ReadyDataCallback(hrng, hrng->RandomNumber);
00874 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
00875     }
00876   }
00877 }
00878 
00879 /**
00880   * @brief  Read latest generated random number.
00881   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00882   *                the configuration information for RNG.
00883   * @retval random value
00884   */
00885 uint32_t HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef *hrng)
00886 {
00887   return (hrng->RandomNumber);
00888 }
00889 
00890 /**
00891   * @brief  Data Ready callback in non-blocking mode.
00892   * @note   When RNG_FLAG_DRDY flag value is set, first random number has been read
00893   *         from DR register in IRQ Handler and is provided as callback parameter.
00894   *         Depending on valid data available in the conditioning output buffer,
00895   *         additional words can be read by the application from DR register till
00896   *         DRDY bit remains high.
00897   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00898   *                the configuration information for RNG.
00899   * @param  random32bit generated random number.
00900   * @retval None
00901   */
00902 __weak void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit)
00903 {
00904   /* Prevent unused argument(s) compilation warning */
00905   UNUSED(hrng);
00906   UNUSED(random32bit);
00907   /* NOTE : This function should not be modified. When the callback is needed,
00908             function HAL_RNG_ReadyDataCallback must be implemented in the user file.
00909    */
00910 }
00911 
00912 /**
00913   * @brief  RNG error callbacks.
00914   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00915   *                the configuration information for RNG.
00916   * @retval None
00917   */
00918 __weak void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng)
00919 {
00920   /* Prevent unused argument(s) compilation warning */
00921   UNUSED(hrng);
00922   /* NOTE : This function should not be modified. When the callback is needed,
00923             function HAL_RNG_ErrorCallback must be implemented in the user file.
00924    */
00925 }
00926 /**
00927   * @}
00928   */
00929 
00930 
00931 /** @addtogroup RNG_Exported_Functions_Group3
00932   *  @brief   Peripheral State functions
00933   *
00934 @verbatim
00935  ===============================================================================
00936                       ##### Peripheral State functions #####
00937  ===============================================================================
00938     [..]
00939     This subsection permits to get in run-time the status of the peripheral
00940     and the data flow.
00941 
00942 @endverbatim
00943   * @{
00944   */
00945 
00946 /**
00947   * @brief  Returns the RNG state.
00948   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
00949   *                the configuration information for RNG.
00950   * @retval HAL state
00951   */
00952 HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng)
00953 {
00954   return hrng->State;
00955 }
00956 
00957 /**
00958   * @brief  Return the RNG handle error code.
00959   * @param  hrng: pointer to a RNG_HandleTypeDef structure.
00960   * @retval RNG Error Code
00961   */
00962 uint32_t HAL_RNG_GetError(RNG_HandleTypeDef *hrng)
00963 {
00964   /* Return RNG Error Code */
00965   return hrng->ErrorCode;
00966 }
00967 /**
00968   * @}
00969   */
00970 
00971 /**
00972   * @}
00973   */
00974 #if defined(RNG_CR_CONDRST)
00975 /* Private functions ---------------------------------------------------------*/
00976 /** @addtogroup RNG_Private_Functions
00977   * @{
00978   */
00979 
00980 /**
00981   * @brief  RNG sequence to recover from a seed error
00982   * @param  hrng pointer to a RNG_HandleTypeDef structure.
00983   * @retval HAL status
00984   */
00985 HAL_StatusTypeDef RNG_RecoverSeedError(RNG_HandleTypeDef *hrng)
00986 {
00987   __IO uint32_t count = 0U;
00988 
00989   /*Check if seed error current status (SECS)is set */
00990   if (__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_SECS) == RESET)
00991   {
00992     /* RNG performed the reset automatically (auto-reset) */
00993     /* Clear bit SEIS */
00994     CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
00995   }
00996   else  /* Sequence to fully recover from a seed error*/
00997   {
00998     /* Writing bit CONDRST=1*/
00999     SET_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
01000     /* Writing bit CONDRST=0*/
01001     CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
01002 
01003     /* Wait for conditioning reset process to be completed */
01004     count = RNG_TIMEOUT_VALUE;
01005     do
01006     {
01007       count-- ;
01008       if (count == 0U)
01009       {
01010         hrng->State = HAL_RNG_STATE_READY;
01011         hrng->ErrorCode |= HAL_RNG_ERROR_TIMEOUT;
01012         /* Process Unlocked */
01013         __HAL_UNLOCK(hrng);
01014 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
01015         /* Call registered Error callback */
01016         hrng->ErrorCallback(hrng);
01017 #else
01018         /* Call legacy weak Error callback */
01019         HAL_RNG_ErrorCallback(hrng);
01020 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
01021         return HAL_ERROR;
01022       }
01023     } while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST));
01024 
01025     if (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)
01026     {
01027       /* Clear bit SEIS */
01028       CLEAR_BIT(hrng->Instance->SR, RNG_IT_SEI);
01029     }
01030 
01031     /* Wait for SECS to be cleared */
01032     count = RNG_TIMEOUT_VALUE;
01033     do
01034     {
01035       count-- ;
01036       if (count == 0U)
01037       {
01038         hrng->State = HAL_RNG_STATE_READY;
01039         hrng->ErrorCode |= HAL_RNG_ERROR_TIMEOUT;
01040         /* Process Unlocked */
01041         __HAL_UNLOCK(hrng);
01042 #if (USE_HAL_RNG_REGISTER_CALLBACKS == 1)
01043         /* Call registered Error callback */
01044         hrng->ErrorCallback(hrng);
01045 #else
01046         /* Call legacy weak Error callback */
01047         HAL_RNG_ErrorCallback(hrng);
01048 #endif /* USE_HAL_RNG_REGISTER_CALLBACKS */
01049         return HAL_ERROR;
01050       }
01051     } while (HAL_IS_BIT_SET(hrng->Instance->SR, RNG_FLAG_SECS));
01052   }
01053   /* Update the error code */
01054   hrng->ErrorCode &= ~ HAL_RNG_ERROR_SEED;
01055   return HAL_OK;
01056 }
01057 
01058 /**
01059   * @}
01060   */
01061 #endif /* RNG_CR_CONDRST */
01062 
01063 
01064 #endif /* HAL_RNG_MODULE_ENABLED */
01065 /**
01066   * @}
01067   */
01068 
01069 #endif /* RNG */
01070 
01071 /**
01072   * @}
01073   */
01074