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