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 RNGEx
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 RNGEx_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 RNGEx_Exported_Functions RNGEx Exported Functions
57   * @{
58   */
59 
60 /** @defgroup RNGEx_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     /* RNG noise source control in accordance with NIST */
133     WRITE_REG(hrng->Instance->NSCR, pConf->NoiseSource);
134 
135     /* Writing bit CONDRST=0*/
136     CLEAR_BIT(hrng->Instance->CR, RNG_CR_CONDRST);
137     /* Get tick */
138     tickstart = HAL_GetTick();
139 
140     /* Wait for conditioning reset process to be completed */
141     while (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
142     {
143       if ((HAL_GetTick() - tickstart) > RNG_TIMEOUT_VALUE)
144       {
145         /* New check to avoid false timeout detection in case of prememption */
146         if (HAL_IS_BIT_SET(hrng->Instance->CR, RNG_CR_CONDRST))
147         {
148           hrng->State = HAL_RNG_STATE_READY;
149           hrng->ErrorCode = HAL_RNG_ERROR_TIMEOUT;
150           return HAL_ERROR;
151         }
152       }
153     }
154 
155     /* Enable RNG */
156     __HAL_RNG_ENABLE(hrng);
157 
158     /* Initialize the RNG state */
159     hrng->State = HAL_RNG_STATE_READY;
160 
161     /* function status */
162     status = HAL_OK;
163   }
164   else
165   {
166     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
167     status = HAL_ERROR;
168   }
169 
170   /* Return the function status */
171   return status;
172 }
173 
174 /**
175   * @brief  Get the RNG Configuration and fill parameters in the
176   *         RNG_ConfigTypeDef.
177   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
178   *          the configuration information for RNG.
179   * @param  pConf pointer to a RNG_ConfigTypeDef structure that contains
180   *         the configuration information for RNG module
181 
182   * @retval HAL status
183   */
HAL_RNGEx_GetConfig(RNG_HandleTypeDef * hrng,RNG_ConfigTypeDef * pConf)184 HAL_StatusTypeDef HAL_RNGEx_GetConfig(RNG_HandleTypeDef *hrng, RNG_ConfigTypeDef *pConf)
185 {
186 
187   HAL_StatusTypeDef status ;
188 
189   /* Check the RNG handle allocation */
190   if ((hrng == NULL) || (pConf == NULL))
191   {
192     return HAL_ERROR;
193   }
194 
195   /* Check RNG peripheral state */
196   if (hrng->State == HAL_RNG_STATE_READY)
197   {
198     /* Change RNG peripheral state */
199     hrng->State = HAL_RNG_STATE_BUSY;
200 
201     /* Get  RNG parameters  */
202     pConf->Config1        = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG1) >> RNG_CR_RNG_CONFIG1_Pos) ;
203     pConf->Config2        = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG2) >> RNG_CR_RNG_CONFIG2_Pos);
204     pConf->Config3        = (uint32_t)((hrng->Instance->CR & RNG_CR_RNG_CONFIG3) >> RNG_CR_RNG_CONFIG3_Pos);
205     pConf->ClockDivider   = (hrng->Instance->CR & RNG_CR_CLKDIV);
206     pConf->NistCompliance = (hrng->Instance->CR & RNG_CR_NISTC);
207     pConf->AutoReset      = (hrng->Instance->CR & RNG_CR_ARDIS);
208     pConf->HealthTest     = (hrng->Instance->HTCR);
209 
210     /* Initialize the RNG state */
211     hrng->State = HAL_RNG_STATE_READY;
212 
213     /* function status */
214     status = HAL_OK;
215   }
216   else
217   {
218     hrng->ErrorCode |= HAL_RNG_ERROR_BUSY;
219     status = HAL_ERROR;
220   }
221 
222   /* Return the function status */
223   return status;
224 }
225 
226 /**
227   * @brief  RNG current configuration lock.
228   * @note   This function allows to lock RNG peripheral configuration.
229   *         Once locked, HW RNG reset has to be performed prior any further
230   *         configuration update.
231   * @param  hrng pointer to a RNG_HandleTypeDef structure that contains
232   *                the configuration information for RNG.
233   * @retval HAL status
234   */
HAL_RNGEx_LockConfig(RNG_HandleTypeDef * hrng)235 HAL_StatusTypeDef HAL_RNGEx_LockConfig(RNG_HandleTypeDef *hrng)
236 {
237   HAL_StatusTypeDef status;
238 
239   /* Check the RNG handle allocation */
240   if (hrng == NULL)
241   {
242     return HAL_ERROR;
243   }
244 
245   /* Check RNG peripheral state */
246   if (hrng->State == HAL_RNG_STATE_READY)
247   {
248     /* Change RNG peripheral state */
249     hrng->State = HAL_RNG_STATE_BUSY;
250 
251     /* Perform RNG configuration Lock */
252     MODIFY_REG(hrng->Instance->CR, RNG_CR_CONFIGLOCK, RNG_CR_CONFIGLOCK);
253 
254     /* Change RNG peripheral state */
255     hrng->State = HAL_RNG_STATE_READY;
256 
257     /* function status */
258     status = HAL_OK;
259   }
260   else
261   {
262     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
263     status = HAL_ERROR;
264   }
265 
266   /* Return the function status */
267   return status;
268 }
269 
270 
271 /**
272   * @}
273   */
274 
275 /** @defgroup RNGEx_Exported_Functions_Group2 Recover from seed error function
276   *  @brief   Recover from seed error function
277   *
278 @verbatim
279  ===============================================================================
280           ##### Recover from seed error function #####
281  ===============================================================================
282     [..]  This section provide function allowing to:
283       (+) Recover from a seed error
284 
285 @endverbatim
286   * @{
287   */
288 
289 /**
290   * @brief  RNG sequence to recover from a seed error
291   * @param  hrng: pointer to a RNG_HandleTypeDef structure.
292   * @retval HAL status
293   */
HAL_RNGEx_RecoverSeedError(RNG_HandleTypeDef * hrng)294 HAL_StatusTypeDef HAL_RNGEx_RecoverSeedError(RNG_HandleTypeDef *hrng)
295 {
296   HAL_StatusTypeDef status;
297 
298   /* Check the RNG handle allocation */
299   if (hrng == NULL)
300   {
301     return HAL_ERROR;
302   }
303 
304   /* Check RNG peripheral state */
305   if (hrng->State == HAL_RNG_STATE_READY)
306   {
307     /* Change RNG peripheral state */
308     hrng->State = HAL_RNG_STATE_BUSY;
309 
310     /* sequence to fully recover from a seed error */
311     status = RNG_RecoverSeedError(hrng);
312     if (status == HAL_ERROR)
313     {
314       /* Update the error code */
315       hrng->ErrorCode = HAL_RNG_ERROR_RECOVERSEED;
316     }
317   }
318   else
319   {
320     hrng->ErrorCode = HAL_RNG_ERROR_BUSY;
321     status = HAL_ERROR;
322   }
323 
324   /* Return the function status */
325   return status;
326 }
327 
328 /**
329   * @}
330   */
331 
332 /**
333   * @}
334   */
335 
336 #endif /* RNG_CR_CONDRST */
337 #endif /* HAL_RNG_MODULE_ENABLED */
338 /**
339   * @}
340   */
341 
342 #endif /* RNG */
343 
344 /**
345   * @}
346   */
347