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