1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019, 2021 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 #include "fsl_adc12.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.adc12"
17 #endif
18
19 /*! @brief Transform raw signed calibration result to unified type int32_t. */
20 #define ADC12_TRANSFORM_CALIBRATION_RESULT(resultValue, bitWidth) \
21 (((resultValue) >= (int32_t)(uint32_t)(1UL << ((bitWidth)-1))) ? \
22 ((resultValue) - (int32_t)(uint32_t)(1UL << (bitWidth))) : \
23 (resultValue));
24
25 /*******************************************************************************
26 * Prototypes
27 ******************************************************************************/
28 /*!
29 * @brief Get instance number for ADC12 module.
30 *
31 * @param base ADC12 peripheral base address
32 */
33 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
34 static uint32_t ADC12_GetInstance(ADC_Type *base);
35 #endif
36
37 /*!
38 * @brief Check calibration failed status.
39 *
40 * Check if the calibration is failed by comparing the calibration result value with its limit range.
41 * 1. Each calibration result value's limit range is:
42 * Symbol Min Typ Max
43 * ______________________________________________________________________________________
44 * OFS -48 -8 22
45 * CLP9 -12 4 20
46 * CLPX -16 0 16
47 * CLPS 30 72 120
48 * CLP0 CLPS-14 CLPS CLPS+14
49 * CLP1 Typ1-16 Typ1=CLP0+CLP0 Typ1+16
50 * CLP2 Typ2-20 Typ2=CLP1+CLP1-26 Typ2+20
51 * CLP3 Typ3-36 Typ3=CLP2+CLP2 Typ3+36
52 * 2. To get the accurate calibration value, following conditions should be met.
53 * 1). Enable hardware average and set average number to 32.
54 * 2). No parallel calibration of ADCs because they will disturb each other.
55 * 2). For VREFH pin on PCB, use 3 bypass capacitance in the range: 1uF, 100nF and 1nF and place them as close as
56 * possible to the VREFH pin.
57 * @param base ADC12 peripheral base address.
58 * @retval kStatus_Success Calibration is done successfully.
59 * @retval kStatus_Fail Calibration is failed.
60 */
61 static status_t ADC12_GetCalibrationStatus(ADC_Type *base);
62
63 /*******************************************************************************
64 * Variables
65 ******************************************************************************/
66 /*! @brief Pointers to ADC12 bases for each instance. */
67 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
68 static ADC_Type *const s_adc12Bases[] = ADC_BASE_PTRS;
69 /*! @brief Pointers to ADC12 clocks for each instance. */
70 static const clock_ip_name_t s_adc12Clocks[] = ADC12_CLOCKS;
71 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
72
73 /*******************************************************************************
74 * Code
75 ******************************************************************************/
76 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
ADC12_GetInstance(ADC_Type * base)77 static uint32_t ADC12_GetInstance(ADC_Type *base)
78 {
79 uint32_t instance;
80
81 /* Find the instance index from base address mappings. */
82 for (instance = 0; instance < ARRAY_SIZE(s_adc12Bases); instance++)
83 {
84 if (s_adc12Bases[instance] == base)
85 {
86 break;
87 }
88 }
89
90 assert(instance < ARRAY_SIZE(s_adc12Bases));
91
92 return instance;
93 }
94 #endif
95
ADC12_GetCalibrationStatus(ADC_Type * base)96 static status_t ADC12_GetCalibrationStatus(ADC_Type *base)
97 {
98 /* Get raw calibration result. OFS, CLP9, CLPX are signed number. The highest position bit is the signal bit.
99 Other calibration value registers are unsigned number. */
100 int32_t OFS = (int32_t)(uint32_t)((base->OFS & ADC_OFS_OFS_MASK) >> ADC_OFS_OFS_SHIFT);
101 int32_t CLP9 = (int32_t)(uint32_t)((base->CLP9 & ADC_CLP9_CLP9_MASK) >> ADC_CLP9_CLP9_SHIFT);
102 int32_t CLPX = (int32_t)(uint32_t)((base->CLPX & ADC_CLPX_CLPX_MASK) >> ADC_CLPX_CLPX_SHIFT);
103 uint32_t CLPS = ((base->CLPS & ADC_CLPS_CLPS_MASK) >> ADC_CLPS_CLPS_SHIFT);
104 uint32_t CLP0 = ((base->CLP0 & ADC_CLP0_CLP0_MASK) >> ADC_CLP0_CLP0_SHIFT);
105 uint32_t CLP1 = ((base->CLP1 & ADC_CLP1_CLP1_MASK) >> ADC_CLP1_CLP1_SHIFT);
106 uint32_t CLP2 = ((base->CLP2 & ADC_CLP2_CLP2_MASK) >> ADC_CLP2_CLP2_SHIFT);
107 uint32_t CLP3 = ((base->CLP3 & ADC_CLP3_CLP3_MASK) >> ADC_CLP3_CLP3_SHIFT);
108 uint32_t Typ1 = (CLP0 + CLP0);
109 uint32_t Typ2 = (CLP1 + CLP1 - 26U);
110 uint32_t Typ3 = (CLP2 + CLP2);
111 status_t ret = kStatus_Success;
112
113 /* Transform raw calibration result to unified type int32_t when the conversion result value is signed number. */
114 OFS = ADC12_TRANSFORM_CALIBRATION_RESULT(OFS, 16);
115 CLP9 = ADC12_TRANSFORM_CALIBRATION_RESULT(CLP9, 7);
116 CLPX = ADC12_TRANSFORM_CALIBRATION_RESULT(CLPX, 7);
117
118 /* Check the calibration result value with its limit range. */
119
120 if ((OFS < -48) || (OFS > 22) || (CLP9 < -12) || (CLP9 > 20) || (CLPX < -16) || (CLPX > 16) || (CLPS < 30U) ||
121 (CLPS > 120U) || (CLP0 < (CLPS - 14U)) || (CLP0 > (CLPS + 14U)) || (CLP1 < (Typ1 - 16U)) ||
122 (CLP1 > (Typ1 + 16U)) || (CLP2 < (Typ2 - 20U)) || (CLP2 > (Typ2 + 20U)) || (CLP3 < (Typ3 - 36U)) ||
123 (CLP3 > (Typ3 + 36U)))
124 {
125 ret = kStatus_Fail;
126 }
127
128 return ret;
129 }
130
131 /*!
132 * brief Initialize the ADC12 module.
133 *
134 * param base ADC12 peripheral base address.
135 * param config Pointer to "adc12_config_t" structure.
136 */
ADC12_Init(ADC_Type * base,const adc12_config_t * config)137 void ADC12_Init(ADC_Type *base, const adc12_config_t *config)
138 {
139 assert(config);
140
141 uint32_t tmp32;
142
143 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
144 /* Enable the clock. */
145 CLOCK_EnableClock(s_adc12Clocks[ADC12_GetInstance(base)]);
146 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
147
148 /* ADCx_CFG1. */
149 tmp32 = (base->CFG1 & ~(ADC_CFG1_ADICLK_MASK | ADC_CFG1_ADIV_MASK | ADC_CFG1_MODE_MASK));
150 tmp32 |= (ADC_CFG1_ADICLK(config->clockSource) | ADC_CFG1_ADIV(config->clockDivider) |
151 ADC_CFG1_MODE(config->resolution));
152 base->CFG1 = tmp32;
153
154 /* ADCx_CFG2. */
155 tmp32 = (base->CFG2 & ~ADC_CFG2_SMPLTS_MASK);
156 tmp32 |= ADC_CFG2_SMPLTS(config->sampleClockCount - 1U);
157 base->CFG2 = tmp32;
158
159 /* ADCx_SC2. */
160 tmp32 = (base->SC2 & ~ADC_SC2_REFSEL_MASK);
161 tmp32 |= ADC_SC2_REFSEL(config->referenceVoltageSource);
162 base->SC2 = tmp32;
163
164 /* ADCx_SC3. */
165 tmp32 = (base->SC3 & ~ADC_SC3_ADCO_MASK);
166 if (true == config->enableContinuousConversion)
167 {
168 tmp32 |= ADC_SC3_ADCO_MASK;
169 }
170 base->SC3 = tmp32;
171 }
172
173 /*!
174 * brief De-initialize the ADC12 module.
175 *
176 * param base ADC12 peripheral base address.
177 */
ADC12_Deinit(ADC_Type * base)178 void ADC12_Deinit(ADC_Type *base)
179 {
180 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
181 /* Disable the clock. */
182 CLOCK_DisableClock(s_adc12Clocks[ADC12_GetInstance(base)]);
183 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
184 }
185
186 /*!
187 * brief Gets an available pre-defined settings for converter's configuration.
188 *
189 * This function initializes the converter configuration structure with an available settings. The default values are:
190 *
191 * Example:
192 code
193 config->referenceVoltageSource = kADC12_ReferenceVoltageSourceVref;
194 config->clockSource = kADC12_ClockSourceAlt0;
195 config->clockDivider = kADC12_ClockDivider1;
196 config->resolution = kADC12_Resolution8Bit;
197 config->sampleClockCount = 12U;
198 config->enableContinuousConversion = false;
199 endcode
200 * param config Pointer to "adc12_config_t" structure.
201 */
ADC12_GetDefaultConfig(adc12_config_t * config)202 void ADC12_GetDefaultConfig(adc12_config_t *config)
203 {
204 assert(config);
205
206 /* Initializes the configure structure to zero. */
207 (void)memset(config, 0, sizeof(*config));
208
209 config->referenceVoltageSource = kADC12_ReferenceVoltageSourceVref;
210 config->clockSource = kADC12_ClockSourceAlt0;
211 config->clockDivider = kADC12_ClockDivider1;
212 config->resolution = kADC12_Resolution8Bit;
213 config->sampleClockCount = 13U;
214 config->enableContinuousConversion = false;
215 }
216
217 /*!
218 * brief Configure the conversion channel.
219 *
220 * This operation triggers the conversion in software trigger mode. In hardware trigger mode, this API configures the
221 * channel while the external trigger source helps to trigger the conversion.
222 *
223 * Note that the "Channel Group" has a detailed description.
224 * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC can have more than one
225 * group of status and control register, one for each conversion. The channel group parameter indicates which group of
226 * registers are used, channel group 0 is for Group A registers and channel group 1 is for Group B registers. The
227 * channel groups are used in a "ping-pong" approach to control the ADC operation. At any time, only one of the
228 * channel groups is actively controlling ADC conversions. Channel group 0 is used for both software and hardware
229 * trigger modes of operation. Channel groups 1 and greater indicate potentially multiple channel group registers for
230 * use only in hardware trigger mode. See the chip configuration information in the MCU reference manual about the
231 * number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used
232 * for software trigger operation and therefore writes to these channel groups do not initiate a new conversion.
233 * Updating channel group 0 while a different channel group is actively controlling a conversion is allowed and
234 * vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
235 * conversion aborts the current conversion.
236 *
237 * param base ADC12 peripheral base address.
238 * param channelGroup Channel group index.
239 * param config Pointer to "adc12_channel_config_t" structure.
240 */
ADC12_SetChannelConfig(ADC_Type * base,uint32_t channelGroup,const adc12_channel_config_t * config)241 void ADC12_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc12_channel_config_t *config)
242 {
243 assert(channelGroup < ADC_SC1_COUNT);
244 assert(config);
245
246 uint32_t tmp32;
247
248 /* ADCx_SC1n. */
249 tmp32 = (base->SC1[channelGroup] & ~(ADC_SC1_ADCH_MASK | ADC_SC1_AIEN_MASK));
250 tmp32 |= ADC_SC1_ADCH(config->channelNumber);
251 if (true == config->enableInterruptOnConversionCompleted)
252 {
253 tmp32 |= ADC_SC1_AIEN_MASK;
254 }
255 base->SC1[channelGroup] = tmp32;
256 }
257
258 /*!
259 * brief Get the status flags of channel.
260 *
261 * param base ADC12 peripheral base address.
262 * param channelGroup Channel group index.
263 *
264 * return Flags' mask if indicated flags are asserted. See to "_adc12_channel_status_flags".
265 */
ADC12_GetChannelStatusFlags(ADC_Type * base,uint32_t channelGroup)266 uint32_t ADC12_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup)
267 {
268 assert(channelGroup < ADC_SC1_COUNT);
269
270 uint32_t tmp32 = base->SC1[channelGroup];
271 uint32_t result = 0U;
272
273 /* ADCx_SC1n. */
274 if (ADC_SC1_COCO_MASK == (tmp32 & ADC_SC1_COCO_MASK))
275 {
276 result |= (uint32_t)kADC12_ChannelConversionCompletedFlag;
277 }
278
279 return result;
280 }
281
282 /*!
283 * brief Automate the hardware calibration.
284 *
285 * This auto calibration helps to adjust the gain automatically according to the converter's working environment.
286 * Execute the calibration before conversion. Note that the software trigger should be used during calibration.
287 *
288 * param base ADC12 peripheral base address.
289 * retval kStatus_Success Calibration is done successfully.
290 * retval kStatus_Fail Calibration is failed.
291 */
ADC12_DoAutoCalibration(ADC_Type * base)292 status_t ADC12_DoAutoCalibration(ADC_Type *base)
293 {
294 bool enabledHardwareTrigger = false;
295 bool enabledHardwareAverage = false;
296 uint32_t averageMode;
297 uint32_t tmp32;
298 uint32_t saveCFG1;
299 status_t ret = kStatus_Success;
300
301 /* Save current clock divider. */
302 saveCFG1 = base->CFG1;
303 /* Set ADCK (ADC clock) to half the maximum specified frequency for calibration. */
304 base->CFG1 |= ADC_CFG1_ADIV(1);
305
306 /* Save current trigger mode. Then set to software trigger mode. */
307 tmp32 = base->SC2;
308 if (ADC_SC2_ADTRG_MASK == (tmp32 & ADC_SC2_ADTRG_MASK))
309 {
310 enabledHardwareTrigger = true;
311 tmp32 &= ~ADC_SC2_ADTRG_MASK;
312 base->SC2 = tmp32;
313 }
314 /* Save current average mode. Then enable hardware average and set average number to be maximum value. */
315 tmp32 = base->SC3;
316 averageMode = ((tmp32 & ADC_SC3_AVGS_MASK) >> ADC_SC3_AVGS_SHIFT);
317 if (ADC_SC3_AVGE_MASK == (tmp32 & ADC_SC3_AVGE_MASK))
318 {
319 enabledHardwareAverage = true;
320 }
321 tmp32 &= ~ADC_SC3_AVGS_MASK;
322 tmp32 |= (ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(((uint32_t)ADC_SC3_AVGS_MASK >> (uint32_t)ADC_SC3_AVGS_SHIFT)));
323
324 /* Trigger calibration and wait until it complete. */
325 tmp32 |= ADC_SC3_CAL_MASK;
326 base->SC3 = tmp32;
327 while ((uint32_t)kADC12_ChannelConversionCompletedFlag !=
328 (ADC12_GetChannelStatusFlags(base, 0U) & (uint32_t)kADC12_ChannelConversionCompletedFlag))
329 {
330 }
331
332 if ((uint32_t)kADC12_CalibrationFailedFlag == (ADC12_GetStatusFlags(base) & (uint32_t)kADC12_CalibrationFailedFlag))
333 {
334 ret = kStatus_Fail;
335 }
336 /* Clear conversion done flag. */
337 (void)ADC12_GetChannelConversionValue(base, 0U);
338
339 /* Restore original trigger mode. */
340 if (true == enabledHardwareTrigger)
341 {
342 base->SC2 |= ADC_SC2_ADTRG_MASK;
343 }
344 /* Restore original average mode. */
345 tmp32 = base->SC3;
346 if (false == enabledHardwareAverage)
347 {
348 tmp32 &= ~ADC_SC3_AVGE_MASK;
349 }
350 tmp32 |= ADC_SC3_AVGS(averageMode);
351 base->SC3 = tmp32;
352
353 /* Restore adc clock divider. */
354 base->CFG1 = saveCFG1;
355
356 return ret;
357 }
358
359 /*!
360 * brief Configure the hardware compare mode.
361 *
362 * The hardware compare mode provides a way to process the conversion result automatically by hardware. Only the result
363 * in compare range is available. To compare the range, see "adc12_hardware_compare_mode_t", or the reference manual
364 * document for more detailed information.
365 *
366 * param base ADC12 peripheral base address.
367 * param config Pointer to "adc12_hardware_compare_config_t" structure. Pass "NULL" to disable the feature.
368 */
ADC12_SetHardwareCompareConfig(ADC_Type * base,const adc12_hardware_compare_config_t * config)369 void ADC12_SetHardwareCompareConfig(ADC_Type *base, const adc12_hardware_compare_config_t *config)
370 {
371 uint32_t tmp32;
372
373 /* Disable hardware compare. */
374 if (NULL == config)
375 {
376 base->SC2 &= ~(ADC_SC2_ACFE_MASK | ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK);
377 }
378 else
379 {
380 /* Set the compare mode. */
381 tmp32 = (base->SC2 & ~(ADC_SC2_ACFE_MASK | ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK));
382 switch (config->hardwareCompareMode)
383 {
384 case kADC12_HardwareCompareMode0:
385 break;
386 case kADC12_HardwareCompareMode1:
387 tmp32 |= ADC_SC2_ACFGT_MASK;
388 break;
389 case kADC12_HardwareCompareMode2:
390 tmp32 |= ADC_SC2_ACREN_MASK;
391 break;
392 case kADC12_HardwareCompareMode3:
393 tmp32 |= (ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK);
394 break;
395 default:
396 assert(false);
397 break;
398 }
399 tmp32 |= ADC_SC2_ACFE_MASK;
400 base->SC2 = tmp32;
401
402 /* Set the compare value. */
403 base->CV1 = (uint32_t)config->value1;
404 base->CV2 = (uint32_t)config->value2;
405 }
406 }
407
408 /*!
409 * brief Set the hardware average mode.
410 *
411 * Hardware average mode provides a way to process the conversion result automatically by hardware. The multiple
412 * conversion results are accumulated and averaged internally. This aids to get more accurate conversion result.
413 *
414 * param base ADC12 peripheral base address.
415 * param mode Setting hardware average mode. See to "adc12_hardware_average_mode_t".
416 */
ADC12_SetHardwareAverage(ADC_Type * base,adc12_hardware_average_mode_t mode)417 void ADC12_SetHardwareAverage(ADC_Type *base, adc12_hardware_average_mode_t mode)
418 {
419 uint32_t tmp32 = base->SC3;
420
421 /* ADCx_SC3. */
422 tmp32 &= ~(ADC_SC3_AVGS_MASK | ADC_SC3_AVGE_MASK);
423 switch (mode)
424 {
425 case kADC12_HardwareAverageCount4:
426 case kADC12_HardwareAverageCount8:
427 case kADC12_HardwareAverageCount16:
428 case kADC12_HardwareAverageCount32:
429 tmp32 |= (ADC_SC3_AVGS(mode) | ADC_SC3_AVGE_MASK);
430 break;
431 case kADC12_HardwareAverageDisabled:
432 break;
433 default:
434 assert(false);
435 break;
436 }
437 base->SC3 = tmp32;
438 }
439
440 /*!
441 * brief Get the status flags of the converter.
442 *
443 * param base ADC12 peripheral base address.
444 *
445 * return Flags' mask if indicated flags are asserted. See to "_adc12_status_flags".
446 */
ADC12_GetStatusFlags(ADC_Type * base)447 uint32_t ADC12_GetStatusFlags(ADC_Type *base)
448 {
449 uint32_t result = 0;
450
451 /* ADCx_SC2. */
452 if (ADC_SC2_ADACT_MASK == (base->SC2 & ADC_SC2_ADACT_MASK))
453 {
454 result |= (uint32_t)kADC12_ActiveFlag;
455 }
456
457 if (kStatus_Fail == ADC12_GetCalibrationStatus(base))
458 {
459 result |= (uint32_t)kADC12_CalibrationFailedFlag;
460 }
461
462 return result;
463 }
464