1 /**
2   ******************************************************************************
3   * @file    stm32l0xx_hal_adc_ex.c
4   * @author  MCD Application Team
5   * @brief   This file provides firmware functions to manage the following
6   *          functionalities of the Analog to Digital Convertor (ADC)
7   *          peripheral:
8   *           + Peripheral Control functions
9   *          Other functions (generic functions) are available in file
10   *          "stm32l0xx_hal_adc.c".
11   *
12   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2016 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   ******************************************************************************
23   @verbatim
24   [..]
25   (@) Sections "ADC peripheral features" and "How to use this driver" are
26       available in file of generic functions "stm32l0xx_hal_adc.c".
27   [..]
28   @endverbatim
29   ******************************************************************************
30   */
31 
32 /* Includes ------------------------------------------------------------------*/
33 #include "stm32l0xx_hal.h"
34 
35 /** @addtogroup STM32L0xx_HAL_Driver
36   * @{
37   */
38 
39 /** @defgroup ADCEx ADCEx
40   * @brief ADC Extended HAL module driver
41   * @{
42   */
43 
44 #ifdef HAL_ADC_MODULE_ENABLED
45 
46 /* Private typedef -----------------------------------------------------------*/
47 /* Private define ------------------------------------------------------------*/
48 
49 /** @defgroup ADCEx_Private_Constants ADC Extended Private Constants
50   * @{
51   */
52 
53 /* Fixed timeout values for ADC calibration, enable settling time, disable  */
54 /* settling time.                                                           */
55 /* Values defined to be higher than worst cases: low clock frequency,       */
56 /* maximum prescaler.                                                       */
57 /* Unit: ms                                                                 */
58 #define ADC_CALIBRATION_TIMEOUT      10U
59 
60 /* Delay for VREFINT stabilization time. */
61 /* Internal reference startup time max value is 3ms  (refer to device datasheet, parameter TVREFINT). */
62 /* Unit: ms */
63 #define SYSCFG_BUF_VREFINT_ENABLE_TIMEOUT       (3U)
64 
65 /* Delay for TEMPSENSOR stabilization time. */
66 /* Temperature sensor startup time max value is 10us  (refer to device datasheet, parameter tSTART). */
67 /* Unit: ms */
68 #define SYSCFG_BUF_TEMPSENSOR_ENABLE_TIMEOUT    (1U)
69 
70 /* Private macro -------------------------------------------------------------*/
71 /* Private variables ---------------------------------------------------------*/
72 /* Private function prototypes -----------------------------------------------*/
73 /* Exported functions --------------------------------------------------------*/
74 
75 /** @defgroup ADCEx_Exported_Functions ADC Extended Exported Functions
76   * @{
77   */
78 
79 /** @defgroup ADCEx_Exported_Functions_Group1 Extended Input and Output operation functions
80   * @brief    Extended IO operation functions
81   *
82 @verbatim
83  ===============================================================================
84                       ##### IO operation functions #####
85  ===============================================================================
86     [..]  This section provides functions allowing to:
87       (+) Perform the ADC calibration.
88 @endverbatim
89   * @{
90   */
91 
92 /**
93   * @brief  Perform an ADC automatic self-calibration
94   *         Calibration prerequisite: ADC must be disabled (execute this
95   *         function before HAL_ADC_Start() or after HAL_ADC_Stop() ).
96   * @note   Calibration factor can be read after calibration, using function
97   *         HAL_ADC_GetValue() (value on 7 bits: from DR[6;0]).
98   * @param  hadc       ADC handle
99   * @param  SingleDiff Selection of single-ended or differential input
100   *          This parameter can be only of the following values:
101   *            @arg ADC_SINGLE_ENDED: Channel in mode input single ended
102   * @retval HAL status
103   */
HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef * hadc,uint32_t SingleDiff)104 HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc, uint32_t SingleDiff)
105 {
106   HAL_StatusTypeDef tmp_hal_status = HAL_OK;
107   uint32_t tickstart = 0U;
108   uint32_t backup_setting_adc_dma_transfer = 0U; /* Note: Variable not declared as volatile because register read is already declared as volatile */
109 
110   /* Check the parameters */
111   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
112 
113   /* Process locked */
114   __HAL_LOCK(hadc);
115 
116   /* Calibration prerequisite: ADC must be disabled. */
117   if (ADC_IS_ENABLE(hadc) == RESET)
118   {
119     /* Set ADC state */
120     ADC_STATE_CLR_SET(hadc->State,
121                       HAL_ADC_STATE_REG_BUSY,
122                       HAL_ADC_STATE_BUSY_INTERNAL);
123 
124     /* Disable ADC DMA transfer request during calibration */
125     /* Note: Specificity of this STM32 series: Calibration factor is           */
126     /*       available in data register and also transferred by DMA.           */
127     /*       To not insert ADC calibration factor among ADC conversion data   */
128     /*       in array variable, DMA transfer must be disabled during          */
129     /*       calibration.                                                     */
130     backup_setting_adc_dma_transfer = READ_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG);
131     CLEAR_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG);
132 
133     /* Start ADC calibration */
134     hadc->Instance->CR |= ADC_CR_ADCAL;
135 
136     tickstart = HAL_GetTick();
137 
138     /* Wait for calibration completion */
139     while (HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADCAL))
140     {
141       if ((HAL_GetTick() - tickstart) > ADC_CALIBRATION_TIMEOUT)
142       {
143         /* New check to avoid false timeout detection in case of preemption */
144         if (HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADCAL))
145         {
146           /* Update ADC state machine to error */
147           ADC_STATE_CLR_SET(hadc->State,
148                             HAL_ADC_STATE_BUSY_INTERNAL,
149                             HAL_ADC_STATE_ERROR_INTERNAL);
150 
151           /* Process unlocked */
152           __HAL_UNLOCK(hadc);
153 
154           return HAL_ERROR;
155         }
156       }
157     }
158 
159     /* Restore ADC DMA transfer request after calibration */
160     SET_BIT(hadc->Instance->CFGR1, backup_setting_adc_dma_transfer);
161 
162     /* Set ADC state */
163     ADC_STATE_CLR_SET(hadc->State,
164                       HAL_ADC_STATE_BUSY_INTERNAL,
165                       HAL_ADC_STATE_READY);
166   }
167   else
168   {
169     /* Update ADC state machine to error */
170     SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
171 
172     tmp_hal_status = HAL_ERROR;
173   }
174 
175   /* Process unlocked */
176   __HAL_UNLOCK(hadc);
177 
178   /* Return function status */
179   return tmp_hal_status;
180 }
181 
182 /**
183   * @brief  Get the calibration factor.
184   * @param  hadc ADC handle.
185   * @param  SingleDiff This parameter can be only:
186   *           @arg ADC_SINGLE_ENDED: Channel in mode input single ended.
187   * @retval Calibration value.
188   */
HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef * hadc,uint32_t SingleDiff)189 uint32_t HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef *hadc, uint32_t SingleDiff)
190 {
191   /* Check the parameters */
192   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
193   assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
194 
195   /* Return the ADC calibration value */
196   return ((hadc->Instance->CALFACT) & 0x0000007FU);
197 }
198 
199 /**
200   * @brief  Set the calibration factor to overwrite automatic conversion result.
201   *         ADC must be enabled and no conversion is ongoing.
202   * @param  hadc ADC handle
203   * @param  SingleDiff This parameter can be only:
204   *           @arg ADC_SINGLE_ENDED: Channel in mode input single ended.
205   * @param  CalibrationFactor Calibration factor (coded on 7 bits maximum)
206   * @retval HAL state
207   */
HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef * hadc,uint32_t SingleDiff,uint32_t CalibrationFactor)208 HAL_StatusTypeDef HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef *hadc, uint32_t SingleDiff, uint32_t CalibrationFactor)
209 {
210   HAL_StatusTypeDef tmp_hal_status = HAL_OK;
211 
212   /* Check the parameters */
213   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
214   assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));
215   assert_param(IS_ADC_CALFACT(CalibrationFactor));
216 
217   /* Process locked */
218   __HAL_LOCK(hadc);
219 
220   /* Verification of hardware constraints before modifying the calibration    */
221   /* factors register: ADC must be enabled, no conversion on going.           */
222   if ((ADC_IS_ENABLE(hadc) != RESET)                            &&
223       (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET))
224   {
225     /* Set the selected ADC calibration value */
226     hadc->Instance->CALFACT &= ~ADC_CALFACT_CALFACT;
227     hadc->Instance->CALFACT |= CalibrationFactor;
228   }
229   else
230   {
231     /* Update ADC state machine to error */
232     SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
233     /* Update ADC state machine to error */
234     SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
235 
236     /* Update ADC state machine to error */
237     tmp_hal_status = HAL_ERROR;
238   }
239 
240   /* Process unlocked */
241   __HAL_UNLOCK(hadc);
242 
243   /* Return function status */
244   return tmp_hal_status;
245 }
246 
247 /**
248   * @brief  Enables the buffer of Vrefint for the ADC, required when device is in mode low-power (low-power run, low-power sleep or stop mode)
249   *         This function must be called before function HAL_ADC_Init()
250   *         (in case of previous ADC operations: function HAL_ADC_DeInit() must be called first)
251   *         For more details on procedure and buffer current consumption, refer to device reference manual.
252   * @note   This is functional only if the LOCK is not set.
253   * @note   This API is obsolete. This configuration is done in HAL_ADC_ConfigChannel().
254   * @retval None
255   */
HAL_ADCEx_EnableVREFINT(void)256 HAL_StatusTypeDef HAL_ADCEx_EnableVREFINT(void)
257 {
258   uint32_t tickstart = 0U;
259 
260   /* Enable the Buffer for the ADC by setting ENBUF_SENSOR_ADC bit in the CFGR3 register */
261   SET_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ENBUF_VREFINT_ADC);
262 
263   /* Wait for Vrefint buffer effectively enabled */
264   /* Get tick count */
265   tickstart = HAL_GetTick();
266 
267   while (HAL_IS_BIT_CLR(SYSCFG->CFGR3, SYSCFG_CFGR3_VREFINT_RDYF))
268   {
269     if ((HAL_GetTick() - tickstart) > SYSCFG_BUF_VREFINT_ENABLE_TIMEOUT)
270     {
271       /* New check to avoid false timeout detection in case of preemption */
272       if (HAL_IS_BIT_CLR(SYSCFG->CFGR3, SYSCFG_CFGR3_VREFINT_RDYF))
273       {
274         return HAL_ERROR;
275       }
276     }
277   }
278 
279   return HAL_OK;
280 }
281 
282 /**
283   * @brief Disables the Buffer Vrefint for the ADC.
284   * @note This is functional only if the LOCK is not set.
285   * @note This API is obsolete. This configuration is done in HAL_ADC_ConfigChannel().
286   * @retval None
287   */
HAL_ADCEx_DisableVREFINT(void)288 void HAL_ADCEx_DisableVREFINT(void)
289 {
290   /* Disable the Vrefint by resetting ENBUF_SENSOR_ADC bit in the CFGR3 register */
291   CLEAR_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ENBUF_VREFINT_ADC);
292 }
293 
294 /**
295   * @brief  Enables the buffer of temperature sensor for the ADC, required when device is in mode low-power (low-power run, low-power sleep or stop mode)
296   *         This function must be called before function HAL_ADC_Init()
297   *         (in case of previous ADC operations: function HAL_ADC_DeInit() must be called first)
298   *         For more details on procedure and buffer current consumption, refer to device reference manual.
299   * @note   This is functional only if the LOCK is not set.
300   * @note   This API is obsolete. This configuration is done in HAL_ADC_ConfigChannel().
301   * @retval None
302   */
HAL_ADCEx_EnableVREFINTTempSensor(void)303 HAL_StatusTypeDef HAL_ADCEx_EnableVREFINTTempSensor(void)
304 {
305   uint32_t tickstart = 0U;
306 
307   /* Enable the Buffer for the ADC by setting ENBUF_SENSOR_ADC bit in the CFGR3 register */
308   SET_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ENBUF_SENSOR_ADC);
309 
310   /* Wait for Vrefint buffer effectively enabled */
311   /* Get tick count */
312   tickstart = HAL_GetTick();
313 
314   while (HAL_IS_BIT_CLR(SYSCFG->CFGR3, SYSCFG_CFGR3_VREFINT_RDYF))
315   {
316     if ((HAL_GetTick() - tickstart) > SYSCFG_BUF_TEMPSENSOR_ENABLE_TIMEOUT)
317     {
318       /* New check to avoid false timeout detection in case of preemption */
319       if (HAL_IS_BIT_CLR(SYSCFG->CFGR3, SYSCFG_CFGR3_VREFINT_RDYF))
320       {
321         return HAL_ERROR;
322       }
323     }
324   }
325 
326   return HAL_OK;
327 }
328 
329 /**
330   * @brief Disables the VREFINT and Sensor for the ADC.
331   * @note This is functional only if the LOCK is not set.
332   * @note This API is obsolete. This configuration is done in HAL_ADC_ConfigChannel().
333   * @retval None
334   */
HAL_ADCEx_DisableVREFINTTempSensor(void)335 void HAL_ADCEx_DisableVREFINTTempSensor(void)
336 {
337   /* Disable the Vrefint by resetting ENBUF_SENSOR_ADC bit in the CFGR3 register */
338   CLEAR_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ENBUF_SENSOR_ADC);
339 }
340 
341 /**
342   * @}
343   */
344 
345 /**
346   * @}
347   */
348 
349 /**
350   * @}
351   */
352 #endif /* HAL_ADC_MODULE_ENABLED */
353 /**
354   * @}
355   */
356 
357 /**
358   * @}
359   */
360 
361