1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2023 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_lpadc.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.lpadc"
17 #endif
18
19 #ifndef ADC_VERID_DIFFEN_MASK
20 #define ADC_VERID_DIFFEN_MASK (0x2U)
21 #endif /* ADC_VERID_DIFFEN_MASK */
22
23 #ifndef ADC_VERID_NUM_SEC_MASK
24 #define ADC_VERID_NUM_SEC_MASK (0x800U)
25 #endif /* ADC_VERID_NUM_SEC_MASK */
26
27 #define ADC_CMDL_CHANNEL_MODE_MASK (0x60U)
28 #define ADC_CMDL_CHANNEL_MODE_SHIFT (5U)
29 #define ADC_CMDL_CHANNEL_MODE(x) \
30 (((uint32_t)(((uint32_t)(x)) << ADC_CMDL_CHANNEL_MODE_SHIFT)) & ADC_CMDL_CHANNEL_MODE_MASK)
31
32 #define GET_ADC_CFG_TPRICTRL_VALUE(val) (((uint32_t)val) & 0x3U)
33
34 #if defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES
35 #define GET_ADC_CFG_TRES_VALUE(val) ((((uint32_t)val) & 0x4U) >> 2U)
36 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES */
37
38 #if defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES
39 #define GET_ADC_CFG_TCMDRES_VALUE(val) ((((uint32_t)val) & 0x8U) >> 3U)
40 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES */
41
42 #if defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI
43 #define GET_ADC_CFG_HPT_EXDI_VALUE(val) ((((uint32_t)val) & 0x10U) >> 4U)
44 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI */
45
46 #if defined(LPADC_RSTS)
47 #define LPADC_RESETS_ARRAY LPADC_RSTS
48 #elif defined(ADC_RSTS)
49 #define LPADC_RESETS_ARRAY ADC_RSTS
50 #endif
51
52 /*******************************************************************************
53 * Prototypes
54 ******************************************************************************/
55 /*!
56 * @brief Get instance number for LPADC module.
57 *
58 * @param base LPADC peripheral base address
59 */
60 static uint32_t LPADC_GetInstance(ADC_Type *base);
61
62 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ
63 /*!
64 * @brief Get gain conversion result .
65 *
66 * @param gainAdjustment gain adjustment value.
67 */
68 static uint32_t LPADC_GetGainConvResult(float gainAdjustment);
69 #endif /* defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
70
71 /*******************************************************************************
72 * Variables
73 ******************************************************************************/
74 /*! @brief Pointers to LPADC bases for each instance. */
75 static ADC_Type *const s_lpadcBases[] = ADC_BASE_PTRS;
76 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
77 /*! @brief Pointers to LPADC clocks for each instance. */
78 static const clock_ip_name_t s_lpadcClocks[] = LPADC_CLOCKS;
79 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
80 #if defined(LPADC_RESETS_ARRAY)
81 /* Reset array */
82 static const reset_ip_name_t s_lpadcResets[] = LPADC_RESETS_ARRAY;
83 #endif
84
85 /*******************************************************************************
86 * Code
87 ******************************************************************************/
LPADC_GetInstance(ADC_Type * base)88 static uint32_t LPADC_GetInstance(ADC_Type *base)
89 {
90 uint32_t instance;
91
92 /* Find the instance index from base address mappings. */
93 /*
94 * $Branch Coverage Justification$
95 * (instance >= ARRAY_SIZE(s_lpadcBases)) not covered. The peripheral base
96 * address is always valid and checked by assert.
97 */
98 for (instance = 0; instance < ARRAY_SIZE(s_lpadcBases); instance++)
99 {
100 /*
101 * $Branch Coverage Justification$
102 * (s_lpadcBases[instance] != base) not covered. The peripheral base
103 * address is always valid and checked by assert.
104 */
105 if (MSDK_REG_SECURE_ADDR(s_lpadcBases[instance]) == MSDK_REG_SECURE_ADDR(base))
106 {
107 break;
108 }
109 }
110
111 assert(instance < ARRAY_SIZE(s_lpadcBases));
112
113 return instance;
114 }
115
116 #if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
117 /*!
118 * brief Get gain conversion Result .
119 *
120 * param gainAdjustment gain adjustment value.
121 */
LPADC_GetGainConvResult(float gainAdjustment)122 static uint32_t LPADC_GetGainConvResult(float gainAdjustment)
123 {
124 uint16_t i = 0U;
125 uint32_t tmp32 = 0U;
126 uint32_t GCRa[17] = {0};
127 uint32_t GCALR = 0U;
128
129 for (i = 0x11U; i > 0U; i--)
130 {
131 tmp32 = (uint32_t)((gainAdjustment) / ((float)(1.0 / (double)(1U << (0x10U - (i - 1U))))));
132 GCRa[i - 1U] = tmp32;
133 gainAdjustment = gainAdjustment - ((float)tmp32) * ((float)(1.0 / (double)(1U << (0x10U - (i - 1U)))));
134 }
135 /* Get GCALR value calculated */
136 for (i = 0x11U; i > 0U; i--)
137 {
138 GCALR += GCRa[i - 1U] * ((uint32_t)(1UL << (uint32_t)(i - 1UL)));
139 }
140
141 /* to return GCALR value calculated */
142 return GCALR;
143 }
144 #endif /* defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
145
146 /*!
147 * brief Initializes the LPADC module.
148 *
149 * param base LPADC peripheral base address.
150 * param config Pointer to configuration structure. See "lpadc_config_t".
151 */
LPADC_Init(ADC_Type * base,const lpadc_config_t * config)152 void LPADC_Init(ADC_Type *base, const lpadc_config_t *config)
153 {
154 /* Check if the pointer is available. */
155 assert(config != NULL);
156
157 uint32_t tmp32 = 0U;
158
159 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
160 /* Enable the clock for LPADC instance. */
161 (void)CLOCK_EnableClock(s_lpadcClocks[LPADC_GetInstance(base)]);
162 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
163
164 #if defined(LPADC_RESETS_ARRAY)
165 RESET_ReleasePeripheralReset(s_lpadcResets[LPADC_GetInstance(base)]);
166 #endif
167
168 /* Reset the module. */
169 LPADC_DoResetConfig(base);
170 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
171 LPADC_DoResetFIFO0(base);
172 LPADC_DoResetFIFO1(base);
173 #else
174 LPADC_DoResetFIFO(base);
175 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
176
177 /* Disable the module before setting configuration. */
178 LPADC_Enable(base, false);
179
180 /* Configure the module generally. */
181 if (config->enableInDozeMode)
182 {
183 base->CTRL &= ~ADC_CTRL_DOZEN_MASK;
184 }
185 else
186 {
187 base->CTRL |= ADC_CTRL_DOZEN_MASK;
188 }
189
190 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS
191 /* Set calibration average mode. */
192 base->CTRL |= ADC_CTRL_CAL_AVGS(config->conversionAverageMode);
193 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */
194
195 /* ADCx_CFG. */
196 #if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
197 if (config->enableInternalClock)
198 {
199 tmp32 |= ADC_CFG_ADCKEN_MASK;
200 }
201 #endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
202 #if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
203 if (config->enableVref1LowVoltage)
204 {
205 tmp32 |= ADC_CFG_VREF1RNG_MASK;
206 }
207 #endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
208 if (config->enableAnalogPreliminary)
209 {
210 tmp32 |= ADC_CFG_PWREN_MASK;
211 }
212 tmp32 |= (ADC_CFG_PUDLY(config->powerUpDelay) /* Power up delay. */
213 | ADC_CFG_REFSEL(config->referenceVoltageSource) /* Reference voltage. */
214 #if defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U)
215 | ADC_CFG_PWRSEL(config->powerLevelMode) /* Power configuration. */
216 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U) */
217 );
218
219 tmp32 |= ADC_CFG_TPRICTRL(GET_ADC_CFG_TPRICTRL_VALUE(config->triggerPriorityPolicy));
220
221 #if (defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES)
222 tmp32 |= ADC_CFG_TRES(GET_ADC_CFG_TRES_VALUE(config->triggerPriorityPolicy));
223 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES */
224
225 #if (defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES)
226 tmp32 |= ADC_CFG_TCMDRES(GET_ADC_CFG_TCMDRES_VALUE(config->triggerPriorityPolicy));
227 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES */
228
229 #if (defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI)
230 tmp32 |= ADC_CFG_HPT_EXDI(GET_ADC_CFG_HPT_EXDI_VALUE(config->triggerPriorityPolicy));
231 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI */
232
233 base->CFG = tmp32;
234
235 /* ADCx_PAUSE. */
236 if (config->enableConvPause)
237 {
238 base->PAUSE = ADC_PAUSE_PAUSEEN_MASK | ADC_PAUSE_PAUSEDLY(config->convPauseDelay);
239 }
240 else
241 {
242 base->PAUSE = 0U;
243 }
244
245 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
246 /* ADCx_FCTRL0. */
247 base->FCTRL[0] = ADC_FCTRL_FWMARK(config->FIFO0Watermark);
248 /* ADCx_FCTRL1. */
249 base->FCTRL[1] = ADC_FCTRL_FWMARK(config->FIFO1Watermark);
250 #else
251 /* ADCx_FCTRL. */
252 base->FCTRL = ADC_FCTRL_FWMARK(config->FIFOWatermark);
253 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
254
255 /* Enable the module after setting configuration. */
256 LPADC_Enable(base, true);
257 }
258
259 /*!
260 * brief Gets an available pre-defined settings for initial configuration.
261 *
262 * This function initializes the converter configuration structure with an available settings. The default values are:
263 * code
264 * config->enableInDozeMode = true;
265 * config->conversionAverageMode = kLPADC_ConversionAverage1;
266 * config->enableAnalogPreliminary = false;
267 * config->powerUpDelay = 0x80;
268 * config->referenceVoltageSource = kLPADC_ReferenceVoltageAlt1;
269 * config->powerLevelMode = kLPADC_PowerLevelAlt1;
270 * config->triggerPriorityPolicy = kLPADC_TriggerPriorityPreemptImmediately;
271 * config->enableConvPause = false;
272 * config->convPauseDelay = 0U;
273 * config->FIFO0Watermark = 0U;
274 * config->FIFO1Watermark = 0U;
275 * config->FIFOWatermark = 0U;
276 * endcode
277 * param config Pointer to configuration structure.
278 */
LPADC_GetDefaultConfig(lpadc_config_t * config)279 void LPADC_GetDefaultConfig(lpadc_config_t *config)
280 {
281 /* Initializes the configure structure to zero. */
282 (void)memset(config, 0, sizeof(*config));
283
284 #if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
285 config->enableInternalClock = false;
286 #endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
287 #if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
288 config->enableVref1LowVoltage = false;
289 #endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
290 config->enableInDozeMode = true;
291 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS
292 /* Set calibration average mode. */
293 config->conversionAverageMode = kLPADC_ConversionAverage1;
294 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */
295 config->enableAnalogPreliminary = false;
296 config->powerUpDelay = 0x80;
297 config->referenceVoltageSource = kLPADC_ReferenceVoltageAlt1;
298 #if defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U)
299 config->powerLevelMode = kLPADC_PowerLevelAlt1;
300 #endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U) */
301 config->triggerPriorityPolicy = kLPADC_TriggerPriorityPreemptImmediately;
302 config->enableConvPause = false;
303 config->convPauseDelay = 0U;
304 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
305 config->FIFO0Watermark = 0U;
306 config->FIFO1Watermark = 0U;
307 #else
308 config->FIFOWatermark = 0U;
309 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
310 }
311
312 /*!
313 * brief De-initializes the LPADC module.
314 *
315 * param base LPADC peripheral base address.
316 */
LPADC_Deinit(ADC_Type * base)317 void LPADC_Deinit(ADC_Type *base)
318 {
319 /* Disable the module. */
320 LPADC_Enable(base, false);
321
322 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
323 /* Gate the clock. */
324 (void)CLOCK_DisableClock(s_lpadcClocks[LPADC_GetInstance(base)]);
325 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
326 }
327
328 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
329 /*!
330 * brief Get the result in conversion FIFOn.
331 *
332 * param base LPADC peripheral base address.
333 * param result Pointer to structure variable that keeps the conversion result in conversion FIFOn.
334 * param index Result FIFO index.
335 *
336 * return Status whether FIFOn entry is valid.
337 */
LPADC_GetConvResult(ADC_Type * base,lpadc_conv_result_t * result,uint8_t index)338 bool LPADC_GetConvResult(ADC_Type *base, lpadc_conv_result_t *result, uint8_t index)
339 {
340 assert(result != NULL); /* Check if the input pointer is available. */
341
342 uint32_t tmp32 = 0U;
343
344 tmp32 = base->RESFIFO[index];
345
346 if (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
347 {
348 return false; /* FIFO is empty. Discard any read from RESFIFO. */
349 }
350
351 result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
352 result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
353 result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
354 result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
355
356 return true;
357 }
358 /*!
359 * brief Get the result in conversion FIFOn using blocking method.
360 *
361 * param base LPADC peripheral base address.
362 * param result Pointer to structure variable that keeps the conversion result in conversion FIFOn.
363 * param index Result FIFO index.
364 */
LPADC_GetConvResultBlocking(ADC_Type * base,lpadc_conv_result_t * result,uint8_t index)365 void LPADC_GetConvResultBlocking(ADC_Type *base, lpadc_conv_result_t *result, uint8_t index)
366 {
367 assert(result != NULL); /* Check if the input pointer is available. */
368
369 uint32_t tmp32 = 0U;
370
371 tmp32 = base->RESFIFO[index];
372
373 while (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
374 {
375 tmp32 = base->RESFIFO[index];
376 }
377
378 result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
379 result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
380 result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
381 result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
382 }
383 #else
384 /*!
385 * brief Get the result in conversion FIFO.
386 *
387 * param base LPADC peripheral base address.
388 * param result Pointer to structure variable that keeps the conversion result in conversion FIFO.
389 *
390 * return Status whether FIFO entry is valid.
391 */
LPADC_GetConvResult(ADC_Type * base,lpadc_conv_result_t * result)392 bool LPADC_GetConvResult(ADC_Type *base, lpadc_conv_result_t *result)
393 {
394 assert(result != NULL); /* Check if the input pointer is available. */
395
396 uint32_t tmp32 = 0U;
397
398 tmp32 = base->RESFIFO;
399
400 if (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
401 {
402 return false; /* FIFO is empty. Discard any read from RESFIFO. */
403 }
404
405 result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
406 result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
407 result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
408 result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
409
410 return true;
411 }
412 /*!
413 * @brief Get the result in conversion FIFO using blocking method.
414 *
415 * @param base LPADC peripheral base address.
416 * @param result Pointer to structure variable that keeps the conversion result in conversion FIFO.
417 */
LPADC_GetConvResultBlocking(ADC_Type * base,lpadc_conv_result_t * result)418 void LPADC_GetConvResultBlocking(ADC_Type *base, lpadc_conv_result_t *result)
419 {
420 assert(result != NULL); /* Check if the input pointer is available. */
421
422 uint32_t tmp32 = 0U;
423
424 tmp32 = base->RESFIFO;
425
426 while (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
427 {
428 tmp32 = base->RESFIFO;
429 }
430
431 result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
432 result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
433 result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
434 result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
435 }
436 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
437
438 /*!
439 * brief Configure the conversion trigger source.
440 *
441 * Each programmable trigger can launch the conversion command in command buffer.
442 *
443 * param base LPADC peripheral base address.
444 * param triggerId ID for each trigger. Typically, the available value range is from 0 to 3.
445 * param config Pointer to configuration structure. See to #lpadc_conv_trigger_config_t.
446 */
LPADC_SetConvTriggerConfig(ADC_Type * base,uint32_t triggerId,const lpadc_conv_trigger_config_t * config)447 void LPADC_SetConvTriggerConfig(ADC_Type *base, uint32_t triggerId, const lpadc_conv_trigger_config_t *config)
448 {
449 assert(triggerId < ADC_TCTRL_COUNT); /* Check if the triggerId is available in this device. */
450 assert(config != NULL); /* Check if the input pointer is available. */
451
452 uint32_t tmp32;
453
454 tmp32 = ADC_TCTRL_TCMD(config->targetCommandId) /* Trigger command select. */
455 | ADC_TCTRL_TDLY(config->delayPower) /* Trigger delay select. */
456 | ADC_TCTRL_TPRI(config->priority) /* Trigger priority setting. */
457 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
458 | ADC_TCTRL_FIFO_SEL_A(config->channelAFIFOSelect)
459 #if !(defined(FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B) && FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B)
460 | ADC_TCTRL_FIFO_SEL_B(config->channelBFIFOSelect)
461 #endif /* FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B */
462 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
463 ;
464 if (config->enableHardwareTrigger)
465 {
466 tmp32 |= ADC_TCTRL_HTEN_MASK;
467 }
468
469 base->TCTRL[triggerId] = tmp32;
470 }
471
472 /*!
473 * brief Gets an available pre-defined settings for trigger's configuration.
474 *
475 * This function initializes the trigger's configuration structure with an available settings. The default values are:
476 * code
477 * config->targetCommandId = 0U;
478 * config->delayPower = 0U;
479 * config->priority = 0U;
480 * config->channelAFIFOSelect = 0U;
481 * config->channelBFIFOSelect = 0U;
482 * config->enableHardwareTrigger = false;
483 * endcode
484 * param config Pointer to configuration structure.
485 */
LPADC_GetDefaultConvTriggerConfig(lpadc_conv_trigger_config_t * config)486 void LPADC_GetDefaultConvTriggerConfig(lpadc_conv_trigger_config_t *config)
487 {
488 assert(config != NULL); /* Check if the input pointer is available. */
489
490 /* Initializes the configure structure to zero. */
491 (void)memset(config, 0, sizeof(*config));
492
493 config->targetCommandId = 0U;
494 config->delayPower = 0U;
495 config->priority = 0U;
496 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
497 config->channelAFIFOSelect = 0U;
498 config->channelBFIFOSelect = 0U;
499 #endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
500 config->enableHardwareTrigger = false;
501 }
502
503 /*!
504 * brief Configure conversion command.
505 *
506 * note The number of compare value register on different chips is different, that is mean in some chips, some
507 * command buffers do not have the compare functionality.
508 *
509 * param base LPADC peripheral base address.
510 * param commandId ID for command in command buffer. Typically, the available value range is 1 - 15.
511 * param config Pointer to configuration structure. See to #lpadc_conv_command_config_t.
512 */
LPADC_SetConvCommandConfig(ADC_Type * base,uint32_t commandId,const lpadc_conv_command_config_t * config)513 void LPADC_SetConvCommandConfig(ADC_Type *base, uint32_t commandId, const lpadc_conv_command_config_t *config)
514 {
515 assert(commandId < (ADC_CMDL_COUNT + 1U)); /* Check if the commandId is available on this device. */
516 assert(config != NULL); /* Check if the input pointer is available. */
517
518 uint32_t tmp32 = 0;
519
520 commandId--; /* The available command number are 1-15, while the index of register group are 0-14. */
521
522 /* ADCx_CMDL. */
523 tmp32 = ADC_CMDL_ADCH(config->channelNumber); /* Channel number. */
524 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH
525 tmp32 |= ADC_CMDL_ALTB_ADCH(config->channelBNumber); /* Alternate channel B number. */
526 #endif
527 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
528 tmp32 |= ADC_CMDL_CSCALE(config->sampleScaleMode); /* Full/Part scale input voltage. */
529 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
530 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE
531 tmp32 |= ADC_CMDL_ALTB_CSCALE(config->channelBScaleMode); /* Alternate channel B full/Part scale input voltage. */
532 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
533
534 #if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
535 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF
536 assert(((config->sampleChannelMode >= kLPADC_SampleChannelDiffBothSideAB) &&
537 (((base->VERID) & ADC_VERID_DIFFEN_MASK) != 0U)) ||
538 (config->sampleChannelMode < kLPADC_SampleChannelDiffBothSideAB));
539 #endif /* defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF */
540
541 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_CTYPE) && FSL_FEATURE_LPADC_HAS_CMDL_CTYPE
542 assert(((config->sampleChannelMode == kLPADC_SampleChannelDiffBothSide) &&
543 (((base->VERID) & ADC_VERID_DIFFEN_MASK) != 0U)) ||
544 ((config->sampleChannelMode == kLPADC_SampleChannelDualSingleEndBothSide) &&
545 (((base->VERID) & ADC_VERID_NUM_SEC_MASK) != 0U)) ||
546 (config->sampleChannelMode < kLPADC_SampleChannelDualSingleEndBothSide));
547 #endif /* defined(FSL_FEATURE_LPADC_HAS_CMDL_CTYPE) && FSL_FEATURE_LPADC_HAS_CMDL_CTYPE */
548 #endif /* !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
549
550 tmp32 |= ADC_CMDL_CHANNEL_MODE(config->sampleChannelMode);
551
552 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_MODE) && FSL_FEATURE_LPADC_HAS_CMDL_MODE
553 tmp32 |= ADC_CMDL_MODE(config->conversionResolutionMode);
554 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_MODE */
555
556 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN) && FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN
557 /* Enable alternate channel B.*/
558 if (config->enableChannelB)
559 {
560 tmp32 |= ADC_CMDL_ALTBEN_MASK;
561 }
562 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN */
563
564 base->CMD[commandId].CMDL = tmp32;
565
566 /* ADCx_CMDH. */
567 tmp32 = ADC_CMDH_NEXT(config->chainedNextCommandNumber) /* Next Command Select. */
568 | ADC_CMDH_LOOP(config->loopCount) /* Loop Count Select. */
569 | ADC_CMDH_AVGS(config->hardwareAverageMode) /* Hardware Average Select. */
570 | ADC_CMDH_STS(config->sampleTimeMode) /* Sample Time Select. */
571 | ADC_CMDH_CMPEN(config->hardwareCompareMode); /* Hardware compare enable. */
572 #if (defined(FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG) && FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG)
573 if (config->enableWaitTrigger)
574 {
575 tmp32 |= ADC_CMDH_WAIT_TRIG_MASK; /* Wait trigger enable. */
576 }
577 #endif /* FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG */
578
579 if (config->enableAutoChannelIncrement)
580 {
581 tmp32 |= ADC_CMDH_LWI_MASK;
582 }
583 base->CMD[commandId].CMDH = tmp32;
584
585 /* Hardware compare settings.
586 * Not all Command Buffers have an associated Compare Value register. The compare function is only available on
587 * Command Buffers that have a corresponding Compare Value register. Therefore, assertion judgment needs to be
588 * made before setting the CV register.
589 */
590
591 if ((kLPADC_HardwareCompareDisabled != config->hardwareCompareMode) && (commandId < ADC_CV_COUNT))
592 {
593 /* Set CV register. */
594 base->CV[commandId] = (ADC_CV_CVH(config->hardwareCompareValueHigh) /* Compare value high. */
595 | ADC_CV_CVL(config->hardwareCompareValueLow)); /* Compare value low. */
596 }
597 }
598
599 /*!
600 * brief Gets an available pre-defined settings for conversion command's configuration.
601 *
602 * This function initializes the conversion command's configuration structure with an available settings. The default
603 * values are:
604 * code
605 * config->sampleScaleMode = kLPADC_SampleFullScale;
606 * config->channelBScaleMode = kLPADC_SampleFullScale;
607 * config->sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
608 * config->channelNumber = 0U;
609 * config->channelBNumber = 0U;
610 * config->chainedNextCommandNumber = 0U;
611 * config->enableAutoChannelIncrement = false;
612 * config->loopCount = 0U;
613 * config->hardwareAverageMode = kLPADC_HardwareAverageCount1;
614 * config->sampleTimeMode = kLPADC_SampleTimeADCK3;
615 * config->hardwareCompareMode = kLPADC_HardwareCompareDisabled;
616 * config->hardwareCompareValueHigh = 0U;
617 * config->hardwareCompareValueLow = 0U;
618 * config->conversionResolutionMode = kLPADC_ConversionResolutionStandard;
619 * config->enableWaitTrigger = false;
620 * config->enableChannelB = false;
621 * endcode
622 * param config Pointer to configuration structure.
623 */
LPADC_GetDefaultConvCommandConfig(lpadc_conv_command_config_t * config)624 void LPADC_GetDefaultConvCommandConfig(lpadc_conv_command_config_t *config)
625 {
626 assert(config != NULL); /* Check if the input pointer is available. */
627
628 /* Initializes the configure structure to zero. */
629 (void)memset(config, 0, sizeof(*config));
630
631 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
632 config->sampleScaleMode = kLPADC_SampleFullScale;
633 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
634 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE
635 config->channelBScaleMode = kLPADC_SampleFullScale;
636 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
637 config->sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
638 config->channelNumber = 0U;
639 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH
640 config->channelBNumber = 0U;
641 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
642 config->chainedNextCommandNumber = 0U; /* No next command defined. */
643 config->enableAutoChannelIncrement = false;
644 config->loopCount = 0U;
645 config->hardwareAverageMode = kLPADC_HardwareAverageCount1;
646 config->sampleTimeMode = kLPADC_SampleTimeADCK3;
647 config->hardwareCompareMode = kLPADC_HardwareCompareDisabled;
648 config->hardwareCompareValueHigh = 0U; /* No used. */
649 config->hardwareCompareValueLow = 0U; /* No used. */
650 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_MODE) && FSL_FEATURE_LPADC_HAS_CMDL_MODE
651 config->conversionResolutionMode = kLPADC_ConversionResolutionStandard;
652 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_MODE */
653 #if defined(FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG) && FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG
654 config->enableWaitTrigger = false;
655 #endif /* FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG */
656 #if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN) && FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN
657 config->enableChannelB = false; /* Enable alternate channel B.*/
658 #endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN */
659 }
660
661 #if defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) && FSL_FEATURE_LPADC_HAS_CFG_CALOFS
662 /*!
663 * brief Enable the calibration function.
664 *
665 * When CALOFS is set, the ADC is configured to perform a calibration function anytime the ADC executes
666 * a conversion. Any channel selected is ignored and the value returned in the RESFIFO is a signed value
667 * between -31 and 31. -32 is not a valid and is never a returned value. Software should copy the lower 6-
668 * bits of the conversion result stored in the RESFIFO after a completed calibration conversion to the
669 * OFSTRIM field. The OFSTRIM field is used in normal operation for offset correction.
670 *
671 * param base LPADC peripheral base address.
672 * param enable switcher to the calibration function.
673 */
LPADC_EnableCalibration(ADC_Type * base,bool enable)674 void LPADC_EnableCalibration(ADC_Type *base, bool enable)
675 {
676 LPADC_Enable(base, false);
677 if (enable)
678 {
679 base->CFG |= ADC_CFG_CALOFS_MASK;
680 }
681 else
682 {
683 base->CFG &= ~ADC_CFG_CALOFS_MASK;
684 }
685 LPADC_Enable(base, true);
686 }
687
688 #if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM
689 /*!
690 * brief Do auto calibration.
691 *
692 * Calibration function should be executed before using converter in application. It used the software trigger and a
693 * dummy conversion, get the offset and write them into the OFSTRIM register. It called some of functional API
694 * including: -LPADC_EnableCalibration(...) -LPADC_LPADC_SetOffsetValue(...) -LPADC_SetConvCommandConfig(...)
695 * -LPADC_SetConvTriggerConfig(...)
696 *
697 * param base LPADC peripheral base address.
698 */
LPADC_DoAutoCalibration(ADC_Type * base)699 void LPADC_DoAutoCalibration(ADC_Type *base)
700 {
701 assert(0u == LPADC_GetConvResultCount(base));
702
703 uint32_t mLpadcCMDL;
704 uint32_t mLpadcCMDH;
705 uint32_t mLpadcTrigger;
706 lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct;
707 lpadc_conv_command_config_t mLpadcCommandConfigStruct;
708 lpadc_conv_result_t mLpadcResultConfigStruct;
709
710 /* Enable the calibration function. */
711 LPADC_EnableCalibration(base, true);
712
713 /* Keep the CMD and TRG state here and restore it later if the calibration completes.*/
714 mLpadcCMDL = base->CMD[0].CMDL; /* CMD1L. */
715 mLpadcCMDH = base->CMD[0].CMDH; /* CMD1H. */
716 mLpadcTrigger = base->TCTRL[0]; /* Trigger0. */
717
718 /* Set trigger0 configuration - for software trigger. */
719 LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct);
720 mLpadcTriggerConfigStruct.targetCommandId = 1U; /* CMD1 is executed. */
721 LPADC_SetConvTriggerConfig(base, 0U, &mLpadcTriggerConfigStruct); /* Configurate the trigger0. */
722
723 /* Set conversion CMD configuration. */
724 LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct);
725 mLpadcCommandConfigStruct.hardwareAverageMode = kLPADC_HardwareAverageCount128;
726 LPADC_SetConvCommandConfig(base, 1U, &mLpadcCommandConfigStruct); /* Set CMD1 configuration. */
727
728 /* Do calibration. */
729 LPADC_DoSoftwareTrigger(base, 1U); /* 1U is trigger0 mask. */
730 while (!LPADC_GetConvResult(base, &mLpadcResultConfigStruct))
731 {
732 }
733 /* The valid bits of data are bits 14:3 in the RESFIFO register. */
734 LPADC_SetOffsetValue(base, (uint32_t)(mLpadcResultConfigStruct.convValue) >> 3UL);
735 /* Disable the calibration function. */
736 LPADC_EnableCalibration(base, false);
737
738 /* restore CMD and TRG registers. */
739 base->CMD[0].CMDL = mLpadcCMDL; /* CMD1L. */
740 base->CMD[0].CMDH = mLpadcCMDH; /* CMD1H. */
741 base->TCTRL[0] = mLpadcTrigger; /* Trigger0. */
742 }
743 #endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */
744 #endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */
745
746 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFS
747 /*!
748 * brief Do offset calibration.
749 *
750 * param base LPADC peripheral base address.
751 */
LPADC_DoOffsetCalibration(ADC_Type * base)752 void LPADC_DoOffsetCalibration(ADC_Type *base)
753 {
754 LPADC_EnableOffsetCalibration(base, true);
755 while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
756 {
757 }
758 }
759
760 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ
761 /*!
762 * brief Do auto calibration.
763 *
764 * param base LPADC peripheral base address.
765 */
LPADC_DoAutoCalibration(ADC_Type * base)766 void LPADC_DoAutoCalibration(ADC_Type *base)
767 {
768 LPADC_PrepareAutoCalibration(base);
769 LPADC_FinishAutoCalibration(base);
770 }
771
772 /*!
773 * brief Prepare auto calibration, LPADC_FinishAutoCalibration has to be called before using the LPADC.
774 * LPADC_DoAutoCalibration has been split in two API to avoid to be stuck too long in the function.
775 *
776 * param base LPADC peripheral base address.
777 */
LPADC_PrepareAutoCalibration(ADC_Type * base)778 void LPADC_PrepareAutoCalibration(ADC_Type *base)
779 {
780 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
781 assert((0U == LPADC_GetConvResultCount(base, 0)) && (0U == LPADC_GetConvResultCount(base, 1)));
782 #else /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 1)) */
783 assert(LPADC_GetConvResultCount(base) == 0U);
784 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2)) */
785
786 /* Request gain calibration. */
787 base->CTRL |= ADC_CTRL_CAL_REQ_MASK;
788 }
789
790 /*!
791 * brief Finish auto calibration start with LPADC_PrepareAutoCalibration.
792 *
793 * param base LPADC peripheral base address.
794 */
LPADC_FinishAutoCalibration(ADC_Type * base)795 void LPADC_FinishAutoCalibration(ADC_Type *base)
796 {
797 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE
798 int32_t GCCa;
799 int32_t GCCb;
800 float GCRa;
801 float GCRb;
802 #else
803 uint32_t GCCa;
804 float GCRa;
805 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
806 uint32_t GCCb;
807 float GCRb;
808 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
809 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */
810
811 while ((ADC_GCC_RDY_MASK != (base->GCC[0] & ADC_GCC_RDY_MASK))
812 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
813 || (ADC_GCC_RDY_MASK != (base->GCC[1] & ADC_GCC_RDY_MASK))
814 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
815 )
816 {
817 }
818
819 #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE
820 GCCa = (int32_t)(base->GCC[0] & ADC_GCC_GAIN_CAL_MASK);
821 GCCb = (int32_t)(base->GCC[1] & ADC_GCC_GAIN_CAL_MASK);
822 if (0U != ((base->GCC[0]) & 0x8000U))
823 {
824 GCCa = GCCa - 0x10000;
825 GCRa = (float)((131072.0) /
826 (131072.0 - (double)GCCa)); /* Gain_CalA = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[0]))*/
827 base->GCR[0] = LPADC_GetGainConvResult(GCRa); /* write A side GCALR. */
828 }
829
830 if (0U != ((base->GCC[1]) & 0x8000U))
831 {
832 GCCb = GCCb - 0x10000;
833 GCRb = (float)((131072.0) /
834 (131072.0 - (double)GCCb)); /* Gain_CalB = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[1]))*/
835 base->GCR[1] = LPADC_GetGainConvResult(GCRb); /* write B side GCALR. */
836 }
837 #else
838 /* Calculate gain offset. */
839 GCCa = (base->GCC[0] & ADC_GCC_GAIN_CAL_MASK);
840 GCRa = (float)((131072.0) /
841 (131072.0 - (double)GCCa)); /* Gain_CalA = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[0]))*/
842 base->GCR[0] = LPADC_GetGainConvResult(GCRa); /* write A side GCALR. */
843
844 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
845 GCCb = (base->GCC[1] & ADC_GCC_GAIN_CAL_MASK);
846 GCRb = (float)((131072.0) /
847 (131072.0 - (double)GCCb)); /* Gain_CalB = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[1]))*/
848 base->GCR[1] = LPADC_GetGainConvResult(GCRb); /* write B side GCALR. */
849 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
850 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */
851 /* Indicate the values are valid. */
852 base->GCR[0] |= ADC_GCR_RDY_MASK;
853 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
854 base->GCR[1] |= ADC_GCR_RDY_MASK;
855 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
856
857 while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
858 {
859 }
860 }
861 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
862
863 /*!
864 * brief Get calibration value into the memory which is defined by invoker.
865 *
866 * note Please note the ADC will be disabled temporary.
867 * note This function should be used after finish calibration.
868 *
869 * param base LPADC peripheral base address.
870 * param ptrCalibrationValue Pointer to lpadc_calibration_value_t structure, this memory block should be always powered
871 * on even in low power modes.
872 */
LPADC_GetCalibrationValue(ADC_Type * base,lpadc_calibration_value_t * ptrCalibrationValue)873 void LPADC_GetCalibrationValue(ADC_Type *base, lpadc_calibration_value_t *ptrCalibrationValue)
874 {
875 assert(ptrCalibrationValue != NULL);
876
877 bool adcEnabled = false;
878
879 /* Check if ADC is enabled. */
880 if ((base->CTRL & ADC_CTRL_ADCEN_MASK) != 0UL)
881 {
882 LPADC_Enable(base, false);
883 adcEnabled = true;
884 }
885
886 #if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
887 uint32_t i;
888 for (i = 0UL; i < 33UL; i++)
889 {
890 #if defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK)
891 ptrCalibrationValue->generalCalibrationValueA[i] =
892 (uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GAR0))) + i)) & 0xFFFFU);
893 #if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
894 ptrCalibrationValue->generalCalibrationValueB[i] =
895 (uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GBR0))) + i)) & 0xFFFFU);
896 #endif /* (defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
897 #else
898 ptrCalibrationValue->generalCalibrationValueA[i] =
899 (uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GAR[0]))) + i)) & 0xFFFFU);
900 #if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
901 ptrCalibrationValue->generalCalibrationValueB[i] =
902 (uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GBR[0]))) + i)) & 0xFFFFU);
903 #endif /* (defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
904
905 #endif /* defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK) */
906 }
907 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
908
909 ptrCalibrationValue->gainCalibrationResultA = (uint16_t)(base->GCR[0] & ADC_GCR_GCALR_MASK);
910 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
911 ptrCalibrationValue->gainCalibrationResultB = (uint16_t)(base->GCR[1] & ADC_GCR_GCALR_MASK);
912 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
913
914 if (adcEnabled)
915 {
916 LPADC_Enable(base, true);
917 }
918 }
919
920 /*!
921 * brief Set calibration value into ADC calibration registers.
922 *
923 * note Please note the ADC will be disabled temporary.
924 *
925 * param base LPADC peripheral base address.
926 * param ptrCalibrationValue Pointer to lpadc_calibration_value_t structure which contains ADC's calibration value.
927 */
LPADC_SetCalibrationValue(ADC_Type * base,const lpadc_calibration_value_t * ptrCalibrationValue)928 void LPADC_SetCalibrationValue(ADC_Type *base, const lpadc_calibration_value_t *ptrCalibrationValue)
929 {
930 assert(ptrCalibrationValue != NULL);
931
932 bool adcEnabled = false;
933
934 /* Check if ADC is enabled. */
935 if ((base->CTRL & ADC_CTRL_ADCEN_MASK) != 0UL)
936 {
937 LPADC_Enable(base, false);
938 adcEnabled = true;
939 }
940
941 #if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
942 for (uint32_t i = 0UL; i < 33UL; i++)
943 {
944 #if defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK)
945 *(((volatile uint32_t *)(&(base->CAL_GAR0))) + i) = ptrCalibrationValue->generalCalibrationValueA[i];
946 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
947 *(((volatile uint32_t *)(&(base->CAL_GBR0))) + i) = ptrCalibrationValue->generalCalibrationValueB[i];
948 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
949 #else
950 *(((volatile uint32_t *)(&(base->CAL_GAR[0]))) + i) = ptrCalibrationValue->generalCalibrationValueA[i];
951 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
952 *(((volatile uint32_t *)(&(base->CAL_GBR[0]))) + i) = ptrCalibrationValue->generalCalibrationValueB[i];
953 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
954 #endif /* defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK) */
955 }
956 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
957
958 base->GCR[0] = ADC_GCR_GCALR(ptrCalibrationValue->gainCalibrationResultA) | ADC_GCR_RDY_MASK;
959 #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
960 base->GCR[1] = ADC_GCR_GCALR(ptrCalibrationValue->gainCalibrationResultB) | ADC_GCR_RDY_MASK;
961 #endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
962 /*
963 * $Branch Coverage Justification$
964 * while ((base->STAT & ADC_STAT_CAL_RDY_MASK) == ADC_STAT_CAL_RDY_MASK) not covered. Test unfeasible,
965 * the calibration ready state is too short not to catch.
966 */
967 while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
968 {
969 }
970
971 if (adcEnabled)
972 {
973 LPADC_Enable(base, true);
974 }
975 }
976
977 #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFS */
978