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