1 /**
2   ******************************************************************************
3   * @file    stm32u5xx_hal_rng_ex.c
4   * @author  MCD Application Team
5   * @brief   Extended RNG HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Random Number Generator (RNG) peripheral:
8   *           + Lock configuration functions
9   *           + Reset the RNG
10   *
11   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2021 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file
18   * in the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   *
21   ******************************************************************************
22   */
23 
24 /* Includes ------------------------------------------------------------------*/
25 #include "stm32u5xx_hal.h"
26 
27 /** @addtogroup STM32U5xx_HAL_Driver
28   * @{
29   */
30 
31 #if defined(RNG)
32 
33 /** @addtogroup RNG_Ex
34   * @brief RNG Extended HAL module driver.
35   * @{
36   */
37 
38 #ifdef HAL_RNG_MODULE_ENABLED
39 #if defined(RNG_CR_CONDRST)
40 /* Private types -------------------------------------------------------------*/
41 /* Private defines -----------------------------------------------------------*/
42 /* Private variables ---------------------------------------------------------*/
43 /* Private constants ---------------------------------------------------------*/
44 /** @addtogroup RNG_Ex_Private_Constants
45   * @{
46   */
47 #define RNG_TIMEOUT_VALUE     2U
48 /**
49   * @}
50   */
51 /* Private macros ------------------------------------------------------------*/
52 /* Private functions prototypes ----------------------------------------------*/
53 /* Private functions  --------------------------------------------------------*/
54 /* Exported functions --------------------------------------------------------*/
55 
56 /** @defgroup RNG_Ex_Exported_Functions RNG_Ex Exported Functions
57   * @{
58   */
59 
60 /** @defgroup RNG_Ex_Exported_Functions_Group1 Configuration and lock functions
61   *  @brief   Configuration functions
62   *
63 @verbatim
64  ===============================================================================
65           ##### Configuration and lock functions #####
66  ===============================================================================
67     [..]  This section provides functions allowing to:
68       (+) Configure the RNG with the specified parameters in the RNG_ConfigTypeDef
69       (+) Lock RNG configuration Allows user to lock a configuration until next reset.
70 
71 @endverbatim
72   * @{
73   */
74 
75 /**
76   * @brief  Configure the RNG with the specified parameters in the
77   *         RNG_ConfigTypeDef.
78   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
79   *          the configuration information for RNG.
80   * @param  pConf pointer to a RNG_ConfigTypeDef structure that contains
81   *         the configuration information for RNG module
82 
83   * @retval HAL status
84   */
HAL_RNGEx_SetConfig(RNG_HandleTypeDef * hrng,const RNG_ConfigTypeDef * pConf)85 HAL_StatusTypeDef HAL_RNGEx_SetConfig(RNG_HandleTypeDef *hrng, const RNG_ConfigTypeDef *pConf)
86 {
87   uint32_t tickstart;
88   uint32_t cr_value;
89   HAL_StatusTypeDef status ;
90 
91   /* Check the RNG handle allocation */
92   if ((hrng == NULL) || (pConf == NULL))
93   {
94     return HAL_ERROR;
95   }
96 
97   /* Check the parameters */
98   assert_param(IS_RNG_ALL_INSTANCE(hrng->Instance));
99   assert_param(IS_RNG_CLOCK_DIVIDER(pConf->ClockDivider));
100   assert_param(IS_RNG_NIST_COMPLIANCE(pConf->NistCompliance));
101   assert_param(IS_RNG_CONFIG1(pConf->Config1));
102   assert_param(IS_RNG_CONFIG2(pConf->Config2));
103   assert_param(IS_RNG_CONFIG3(pConf->Config3));
104   assert_param(IS_RNG_ARDIS(pConf->AutoReset));
105 
106   /* Check RNG peripheral state */
107   if (hrng->State == HAL_RNG_STATE_READY)
108   {
109     /* Change RNG peripheral state */
110     hrng->State = HAL_RNG_STATE_BUSY;
111 
112     /* Disable RNG */
113     __HAL_RNG_DISABLE(hrng);
114 
115     /* RNG CR register configuration. Set value in CR register for :
116         - NIST Compliance setting
117         - Clock divider value
118         - Automatic reset to clear SECS bit
119         - CONFIG 1, CONFIG 2 and CONFIG 3 values */
120     cr_value = (uint32_t)(pConf->ClockDivider | pConf->NistCompliance | pConf->AutoReset
121                           | (pConf->Config1 << RNG_CR_RNG_CONFIG1_Pos)
122                           | (pConf->Config2 << RNG_CR_RNG_CONFIG2_Pos)
123                           | (pConf->Config3 << RNG_CR_RNG_CONFIG3_Pos));
124 
125     MODIFY_REG(hrng->Instance->CR, RNG_CR_NISTC | RNG_CR_CLKDIV | RNG_CR_RNG_CONFIG1
126                | RNG_CR_RNG_CONFIG2 | RNG_CR_RNG_CONFIG3 | RNG_CR_ARDIS,
127                (uint32_t)(RNG_CR_CONDRST | cr_value));
128 
129     /* RNG health test control in accordance with NIST */
130     WRITE_REG(hrng->Instance->HTCR, pConf->HealthTest);
131 
132     /* Writing bit CONDRST=0*/
133     CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
134     /* Get tick */
135     tickstart = HAL_GetTick();
136 
137     /* Wait for conditioning reset process to be completed */
138     while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
139     {
140       if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
141       {
142         /* New check to avoid false timeout detection in case of prememption */
143         if (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
144         {
145           hrng->State = HAL_RNG_STATE_READY;
146           hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
147           return HAL_ERROR;
148         }
149       }
150     }
151 
152     /* Enable RNG */
153     __HAL_RNG_ENABLE(hrng);
154 
155     /* Initialize the RNG state */
156     hrng->State = HAL_RNG_STATE_READY;
157 
158     /* function status */
159     status = HAL_OK;
160   }
161   else
162   {
163     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
164     status = HAL_ERROR;
165   }
166 
167   /* Return the function status */
168   return status;
169 }
170 
171 /**
172   * @brief  Get the RNG Configuration and fill parameters in the
173   *         RNG_ConfigTypeDef.
174   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
175   *          the configuration information for RNG.
176   * @param  pConf pointer to a RNG_ConfigTypeDef structure that contains
177   *         the configuration information for RNG module
178 
179   * @retval HAL status
180   */
HAL_RNGEx_GetConfig(RNG_HandleTypeDef * hrng,RNG_ConfigTypeDef * pConf)181 HAL_StatusTypeDef HAL_RNGEx_GetConfig(RNG_HandleTypeDef *hrng, RNG_ConfigTypeDef *pConf)
182 {
183 
184   HAL_StatusTypeDef status ;
185 
186   /* Check the RNG handle allocation */
187   if ((hrng == NULL) || (pConf == NULL))
188   {
189     return HAL_ERROR;
190   }
191 
192   /* Check RNG peripheral state */
193   if (hrng->State == HAL_RNG_STATE_READY)
194   {
195     /* Change RNG peripheral state */
196     hrng->State = HAL_RNG_STATE_BUSY;
197 
198     /* Get  RNG parameters  */
199     pConf->Config1        = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG1) >> RNG_CR_RNG_CONFIG1_Pos) ;
200     pConf->Config2        = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG2) >> RNG_CR_RNG_CONFIG2_Pos);
201     pConf->Config3        = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG3) >> RNG_CR_RNG_CONFIG3_Pos);
202     pConf->ClockDivider   = (hrng->Instance->CR & RNG_CR_CLKDIV);
203     pConf->NistCompliance = (hrng->Instance->CR & RNG_CR_NISTC);
204     pConf->AutoReset      = (hrng->Instance->CR & RNG_CR_ARDIS);
205     pConf->HealthTest     = (hrng->Instance->HTCR);
206 
207     /* Initialize the RNG state */
208     hrng->State = HAL_RNG_STATE_READY;
209 
210     /* function status */
211     status = HAL_OK;
212   }
213   else
214   {
215     hrng->ErrorCode |= HAL_RNG_ERROR_BUSY;
216     status = HAL_ERROR;
217   }
218 
219   /* Return the function status */
220   return status;
221 }
222 
223 /**
224   * @brief  RNG current configuration lock.
225   * @note   This function allows to lock RNG peripheral configuration.
226   *         Once locked, HW RNG reset has to be performed prior any further
227   *         configuration update.
228   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
229   *                the configuration information for RNG.
230   * @retval HAL status
231   */
HAL_RNGEx_LockConfig(RNG_HandleTypeDef * hrng)232 HAL_StatusTypeDef HAL_RNGEx_LockConfig(RNG_HandleTypeDef *hrng)
233 {
234   HAL_StatusTypeDef status;
235 
236   /* Check the RNG handle allocation */
237   if (hrng == NULL)
238   {
239     return HAL_ERROR;
240   }
241 
242   /* Check RNG peripheral state */
243   if (hrng->State == HAL_RNG_STATE_READY)
244   {
245     /* Change RNG peripheral state */
246     hrng->State = HAL_RNG_STATE_BUSY;
247 
248     /* Perform RNG configuration Lock */
249     MODIFY_REG(hrng->Instance->CR, RNG_CR_CONFIGLOCK, RNG_CR_CONFIGLOCK);
250 
251     /* Change RNG peripheral state */
252     hrng->State = HAL_RNG_STATE_READY;
253 
254     /* function status */
255     status = HAL_OK;
256   }
257   else
258   {
259     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
260     status = HAL_ERROR;
261   }
262 
263   /* Return the function status */
264   return status;
265 }
266 
267 
268 /**
269   * @}
270   */
271 
272 /** @defgroup RNG_Ex_Exported_Functions_Group2 Recover from seed error function
273   *  @brief   Recover from seed error function
274   *
275 @verbatim
276  ===============================================================================
277           ##### Recover from seed error function #####
278  ===============================================================================
279     [..]  This section provide function allowing to:
280       (+) Recover from a seed error
281 
282 @endverbatim
283   * @{
284   */
285 
286 /**
287   * @brief  RNG sequence to recover from a seed error
288   * @param  hrng: pointer to a RNG_HandleTypeDef structure.
289   * @retval HAL status
290   */
HAL_RNGEx_RecoverSeedError(RNG_HandleTypeDef * hrng)291 HAL_StatusTypeDef HAL_RNGEx_RecoverSeedError(RNG_HandleTypeDef *hrng)
292 {
293   HAL_StatusTypeDef status;
294 
295   /* Check the RNG handle allocation */
296   if (hrng == NULL)
297   {
298     return HAL_ERROR;
299   }
300 
301   /* Check RNG peripheral state */
302   if (hrng->State == HAL_RNG_STATE_READY)
303   {
304     /* Change RNG peripheral state */
305     hrng->State = HAL_RNG_STATE_BUSY;
306 
307     /* sequence to fully recover from a seed error */
308     status = RNG_RecoverSeedError(hrng);
309   }
310   else
311   {
312     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
313     status = HAL_ERROR;
314   }
315 
316   /* Return the function status */
317   return status;
318 }
319 
320 /**
321   * @}
322   */
323 
324 /**
325   * @}
326   */
327 
328 #endif /* RNG_CR_CONDRST */
329 #endif /* HAL_RNG_MODULE_ENABLED */
330 /**
331   * @}
332   */
333 
334 #endif /* RNG */
335 
336 /**
337   * @}
338   */
339