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