1 /**
2   ******************************************************************************
3   * @file    stm32wbaxx_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 Converter (ADC)
7   *          peripheral:
8   *           + Peripheral Control functions
9   *          Other functions (generic functions) are available in file
10   *          "stm32wbaxx_hal_adc.c".
11   *
12   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2022 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 "stm32wbaxx_hal_adc.c".
27   [..]
28   @endverbatim
29   ******************************************************************************
30   */
31 
32 /* Includes ------------------------------------------------------------------*/
33 #include "stm32wbaxx_hal.h"
34 
35 /** @addtogroup STM32WBAxx_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 value for ADC calibration.                                   */
54 /* Values defined to be higher than worst cases: maximum ratio between ADC    */
55 /* and CPU clock frequencies.                                                 */
56 /* Example of profile low frequency : ADC frequency at 31.25kHz (ADC clock    */
57 /* source PLL 8MHz, ADC clock prescaler 256), CPU frequency 100MHz.           */
58 /* Calibration time max = 116 / fADC (refer to datasheet)                     */
59 /*                      = 371 200 CPU cycles                                  */
60 #define ADC_CALIBRATION_TIMEOUT         (178176UL)   /*!< ADC calibration time-out value (unit: CPU cycles) */
61 
62 /**
63   * @}
64   */
65 
66 /* Private macro -------------------------------------------------------------*/
67 /* Private variables ---------------------------------------------------------*/
68 /* Private function prototypes -----------------------------------------------*/
69 /* Exported functions --------------------------------------------------------*/
70 
71 /** @defgroup ADCEx_Exported_Functions ADC Extended Exported Functions
72   * @{
73   */
74 
75 /** @defgroup ADCEx_Exported_Functions_Group1 Extended Input and Output operation functions
76   * @brief    Extended IO operation functions
77   *
78 @verbatim
79  ===============================================================================
80                       ##### IO operation functions #####
81  ===============================================================================
82     [..]  This section provides functions allowing to:
83 
84       (+) Perform the ADC self-calibration.
85       (+) Get calibration factors.
86       (+) Set calibration factors.
87 
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   * @retval HAL status
100   */
HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef * hadc)101 HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc)
102 {
103   HAL_StatusTypeDef tmp_hal_status;
104   __IO uint32_t wait_loop_index = 0UL;
105   uint32_t backup_setting_cfgr1;
106   uint32_t backup_setting_pwrr;
107 
108   /* Check the parameters */
109   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
110 
111   __HAL_LOCK(hadc);
112 
113   /* Calibration prerequisite: ADC must be disabled. */
114 
115   /* Disable the ADC (if not already disabled) */
116   tmp_hal_status = ADC_Disable(hadc);
117 
118   /* Check if ADC is effectively disabled */
119   if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
120   {
121     /* Set ADC state */
122     ADC_STATE_CLR_SET(hadc->State,
123                       HAL_ADC_STATE_REG_BUSY,
124                       HAL_ADC_STATE_BUSY_INTERNAL);
125 
126     /* Manage settings impacting calibration                                  */
127     /* - Disable ADC mode auto power-off                                      */
128     /* - Disable ADC DMA transfer request during calibration                  */
129     /* Note: Specificity of this STM32 series: Calibration factor is          */
130     /*       available in data register and also transferred by DMA.          */
131     /*       To not insert ADC calibration factor among ADC conversion data   */
132     /*       in array variable, DMA transfer must be disabled during          */
133     /*       calibration.                                                     */
134     backup_setting_pwrr   = READ_BIT(hadc->Instance->PWRR, ADC_PWRR_AUTOFF);
135     backup_setting_cfgr1 = READ_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG);
136     CLEAR_BIT(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG);
137     CLEAR_BIT(hadc->Instance->PWRR, ADC_PWRR_AUTOFF);
138 
139     /* Start ADC calibration */
140     SET_BIT(hadc->Instance->CR, ADC_CR_ADCAL);
141 
142     /* Wait for calibration completion */
143     while (LL_ADC_IsCalibrationOnGoing(hadc->Instance) != 0UL)
144     {
145       wait_loop_index++;
146       if (wait_loop_index >= ADC_CALIBRATION_TIMEOUT)
147       {
148         /* Update ADC state machine to error */
149         ADC_STATE_CLR_SET(hadc->State,
150                           HAL_ADC_STATE_BUSY_INTERNAL,
151                           HAL_ADC_STATE_ERROR_INTERNAL);
152 
153         __HAL_UNLOCK(hadc);
154 
155         return HAL_ERROR;
156       }
157     }
158 
159     /* Restore configuration after calibration */
160     SET_BIT(hadc->Instance->CFGR1, backup_setting_cfgr1);
161     SET_BIT(hadc->Instance->PWRR, backup_setting_pwrr);
162 
163     /* Set ADC state */
164     ADC_STATE_CLR_SET(hadc->State,
165                       HAL_ADC_STATE_BUSY_INTERNAL,
166                       HAL_ADC_STATE_READY);
167   }
168   else
169   {
170     SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
171 
172     /* Note: No need to update variable "tmp_hal_status" here: already set    */
173     /*       to state "HAL_ERROR" by function disabling the ADC.              */
174   }
175 
176   __HAL_UNLOCK(hadc);
177 
178   return tmp_hal_status;
179 }
180 
181 /**
182   * @brief  Get the calibration factor.
183   * @param hadc ADC handle.
184   * @retval Calibration value.
185   */
HAL_ADCEx_Calibration_GetValue(const ADC_HandleTypeDef * hadc)186 uint32_t HAL_ADCEx_Calibration_GetValue(const ADC_HandleTypeDef *hadc)
187 {
188   /* Check the parameters */
189   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
190 
191   /* Return the selected ADC calibration value */
192   return ((hadc->Instance->CALFACT) & 0x0000007FU);
193 }
194 
195 /**
196   * @brief  Set the calibration factor to overwrite automatic conversion result.
197   *         ADC must be enabled and no conversion is ongoing.
198   * @param hadc ADC handle
199   * @param CalibrationFactor Calibration factor (coded on 7 bits maximum)
200   * @retval HAL state
201   */
HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef * hadc,uint32_t CalibrationFactor)202 HAL_StatusTypeDef HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef *hadc, uint32_t CalibrationFactor)
203 {
204   HAL_StatusTypeDef tmp_hal_status = HAL_OK;
205   uint32_t tmp_adc_is_conversion_on_going_regular;
206 
207   /* Check the parameters */
208   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
209   assert_param(IS_ADC_CALFACT(CalibrationFactor));
210 
211   __HAL_LOCK(hadc);
212 
213   /* Verification of hardware constraints before modifying the calibration    */
214   /* factors register: ADC must be enabled, no conversion on going.           */
215   tmp_adc_is_conversion_on_going_regular = LL_ADC_REG_IsConversionOngoing(hadc->Instance);
216 
217   if ((LL_ADC_IsEnabled(hadc->Instance) != 0UL)
218       && (tmp_adc_is_conversion_on_going_regular == 0UL)
219      )
220   {
221     hadc->Instance->CALFACT &= ~ADC_CALFACT_CALFACT;
222     hadc->Instance->CALFACT |= CalibrationFactor;
223   }
224   else
225   {
226     /* Update ADC state machine */
227     SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
228     /* Update ADC error code */
229     SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
230 
231     /* Update ADC state machine to error */
232     tmp_hal_status = HAL_ERROR;
233   }
234 
235   __HAL_UNLOCK(hadc);
236 
237   return tmp_hal_status;
238 }
239 
240 /**
241   * @brief  Analog watchdog 2 callback in non-blocking mode.
242   * @param hadc ADC handle
243   * @retval None
244   */
HAL_ADCEx_LevelOutOfWindow2Callback(ADC_HandleTypeDef * hadc)245 __weak void HAL_ADCEx_LevelOutOfWindow2Callback(ADC_HandleTypeDef *hadc)
246 {
247   /* Prevent unused argument(s) compilation warning */
248   UNUSED(hadc);
249 
250   /* NOTE : This function should not be modified. When the callback is needed,
251             function HAL_ADCEx_LevelOutOfWindow2Callback must be implemented in the user file.
252   */
253 }
254 
255 /**
256   * @brief  Analog watchdog 3 callback in non-blocking mode.
257   * @param hadc ADC handle
258   * @retval None
259   */
HAL_ADCEx_LevelOutOfWindow3Callback(ADC_HandleTypeDef * hadc)260 __weak void HAL_ADCEx_LevelOutOfWindow3Callback(ADC_HandleTypeDef *hadc)
261 {
262   /* Prevent unused argument(s) compilation warning */
263   UNUSED(hadc);
264 
265   /* NOTE : This function should not be modified. When the callback is needed,
266             function HAL_ADCEx_LevelOutOfWindow3Callback must be implemented in the user file.
267   */
268 }
269 
270 
271 /**
272   * @brief  End Of Sampling callback in non-blocking mode.
273   * @param hadc ADC handle
274   * @retval None
275   */
HAL_ADCEx_EndOfSamplingCallback(ADC_HandleTypeDef * hadc)276 __weak void HAL_ADCEx_EndOfSamplingCallback(ADC_HandleTypeDef *hadc)
277 {
278   /* Prevent unused argument(s) compilation warning */
279   UNUSED(hadc);
280 
281   /* NOTE : This function should not be modified. When the callback is needed,
282             function HAL_ADCEx_EndOfSamplingCallback must be implemented in the user file.
283   */
284 }
285 
286 /**
287   * @brief  ADC internal voltage regulator ready callback in non-blocking mode.
288   * @param hadc ADC handle
289   * @retval None
290   */
HAL_ADCEx_LDOReadyCallback(ADC_HandleTypeDef * hadc)291 __weak void HAL_ADCEx_LDOReadyCallback(ADC_HandleTypeDef *hadc)
292 {
293   /* Prevent unused argument(s) compilation warning */
294   UNUSED(hadc);
295 
296   /* NOTE : This function should not be modified. When the callback is needed,
297             function HAL_ADCEx_LDOReadyCallback must be implemented in the user file.
298   */
299 }
300 
301 /**
302   * @}
303   */
304 
305 /**
306   * @brief  Disable ADC voltage regulator.
307   * @note   Disabling voltage regulator allows to save power. This operation can
308   *         be carried out only when ADC is disabled.
309   * @note   To enable again the voltage regulator, the user is expected to
310   *         resort to HAL_ADC_Init() API.
311   * @param hadc ADC handle
312   * @retval HAL status
313   */
HAL_ADCEx_DisableVoltageRegulator(ADC_HandleTypeDef * hadc)314 HAL_StatusTypeDef HAL_ADCEx_DisableVoltageRegulator(ADC_HandleTypeDef *hadc)
315 {
316   HAL_StatusTypeDef tmp_hal_status;
317 
318   /* Check the parameters */
319   assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
320 
321   /* Setting of this feature is conditioned to ADC state: ADC must be ADC disabled */
322   if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
323   {
324     LL_ADC_DisableInternalRegulator(hadc->Instance);
325     tmp_hal_status = HAL_OK;
326   }
327   else
328   {
329     tmp_hal_status = HAL_ERROR;
330   }
331 
332   return tmp_hal_status;
333 }
334 
335 /**
336   * @}
337   */
338 
339 /**
340   * @}
341   */
342 
343 #endif /* HAL_ADC_MODULE_ENABLED */
344 /**
345   * @}
346   */
347 
348 /**
349   * @}
350   */
351