/* * Copyright (c) 2016, Freescale Semiconductor, Inc. * Copyright 2016-2019, 2022~2023 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_adc.h" #include "fsl_clock.h" /* Component ID definition, used by tools. */ #ifndef FSL_COMPONENT_ID #define FSL_COMPONENT_ID "platform.drivers.lpc_adc" #endif #if defined(ADC_RSTS) #define ADC_RESETS_ARRAY ADC_RSTS #elif defined(ADC_RSTS_N) #define ADC_RESETS_ARRAY ADC_RSTS_N #endif static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS; #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS; #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ #if defined(ADC_RESETS_ARRAY) /* Reset array */ static const reset_ip_name_t s_adcResets[] = ADC_RESETS_ARRAY; #endif #define FREQUENCY_1MHZ (1000000UL) static uint32_t ADC_GetInstance(ADC_Type *base) { uint32_t instance; /* Find the instance index from base address mappings. */ for (instance = 0; instance < ARRAY_SIZE(s_adcBases); instance++) { if (s_adcBases[instance] == base) { break; } } assert(instance < ARRAY_SIZE(s_adcBases)); return instance; } /*! * brief Initialize the ADC module. * * param base ADC peripheral base address. * param config Pointer to configuration structure, see to #adc_config_t. */ void ADC_Init(ADC_Type *base, const adc_config_t *config) { assert(config != NULL); uint32_t tmp32 = 0U; #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable clock. */ CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]); #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ #if defined(ADC_RESETS_ARRAY) RESET_ReleasePeripheralReset(s_adcResets[ADC_GetInstance(base)]); #endif /* Disable the interrupts. */ base->INTEN = 0U; /* Quickly disable all the interrupts. */ /* Configure the ADC block. */ tmp32 = ADC_CTRL_CLKDIV(config->clockDividerNumber); #if (defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) && FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) /* Async or Sync clock mode. */ switch (config->clockMode) { case kADC_ClockAsynchronousMode: tmp32 |= ADC_CTRL_ASYNMODE_MASK; break; default: /* kADC_ClockSynchronousMode */ break; } #endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE. */ #if (defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) && FSL_FEATURE_ADC_HAS_CTRL_RESOL) /* Resolution. */ tmp32 |= ADC_CTRL_RESOL(config->resolution); #endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL. */ #if (defined(FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) && FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) /* Bypass calibration. */ if (config->enableBypassCalibration) { tmp32 |= ADC_CTRL_BYPASSCAL_MASK; } #endif /* FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL. */ #if (defined(FSL_FEATURE_ADC_HAS_CTRL_TSAMP) && FSL_FEATURE_ADC_HAS_CTRL_TSAMP) /* Sample time clock count. */ #if (defined(FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL) && FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL) if (config->clockMode == kADC_ClockAsynchronousMode) { #endif /* FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL */ tmp32 |= ADC_CTRL_TSAMP(config->sampleTimeNumber); #if (defined(FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL) && FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL) } #endif /* FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL */ #endif /* FSL_FEATURE_ADC_HAS_CTRL_TSAMP. */ #if (defined(FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) && FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) if (config->enableLowPowerMode) { tmp32 |= ADC_CTRL_LPWRMODE_MASK; } #endif /* FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE. */ base->CTRL = tmp32; #if defined(FSL_FEATURE_ADC_HAS_GPADC_CTRL0_LDO_POWER_EN) && FSL_FEATURE_ADC_HAS_GPADC_CTRL0_LDO_POWER_EN base->GPADC_CTRL0 |= ADC_GPADC_CTRL0_LDO_POWER_EN_MASK; if (config->clockMode == kADC_ClockSynchronousMode) { base->GPADC_CTRL0 |= ADC_GPADC_CTRL0_PASS_ENABLE(config->sampleTimeNumber); } SDK_DelayAtLeastUs(300, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); #endif /* FSL_FEATURE_ADC_HAS_GPADC_CTRL0_LDO_POWER_EN */ #if defined(FSL_FEATURE_ADC_HAS_GPADC_CTRL1_OFFSET_CAL) && FSL_FEATURE_ADC_HAS_GPADC_CTRL1_OFFSET_CAL tmp32 = *(uint32_t *)FSL_FEATURE_FLASH_ADDR_OF_TEMP_CAL; if (tmp32 & FSL_FEATURE_FLASH_ADDR_OF_TEMP_CAL_VALID) { base->GPADC_CTRL1 = (tmp32 >> 1); } #if !(defined(FSL_FEATURE_ADC_HAS_STARTUP_ADC_INIT) && FSL_FEATURE_ADC_HAS_STARTUP_ADC_INIT) base->STARTUP = ADC_STARTUP_ADC_ENA_MASK; /* Set the ADC Start bit */ #endif /* FSL_FEATURE_ADC_HAS_GPADC_CTRL1_OFFSET_CAL */ #endif /* FSL_FEATURE_ADC_HAS_GPADC_CTRL1_OFFSET_CAL */ #if (defined(FSL_FEATURE_ADC_HAS_TRIM_REG) && FSL_FEATURE_ADC_HAS_TRIM_REG) base->TRM &= ~ADC_TRM_VRANGE_MASK; base->TRM |= ADC_TRM_VRANGE(config->voltageRange); #endif /* FSL_FEATURE_ADC_HAS_TRIM_REG. */ } /*! * brief Gets an available pre-defined settings for initial configuration. * * This function initializes the initial configuration structure with an available settings. The default values are: * code * config->clockMode = kADC_ClockSynchronousMode; * config->clockDividerNumber = 0U; * config->resolution = kADC_Resolution12bit; * config->enableBypassCalibration = false; * config->sampleTimeNumber = 0U; * endcode * param config Pointer to configuration structure. */ void ADC_GetDefaultConfig(adc_config_t *config) { /* Initializes the configure structure to zero. */ (void)memset(config, 0, sizeof(*config)); #if (defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) && FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) config->clockMode = kADC_ClockSynchronousMode; #endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE. */ config->clockDividerNumber = 0U; #if (defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) && FSL_FEATURE_ADC_HAS_CTRL_RESOL) config->resolution = kADC_Resolution12bit; #endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL. */ #if (defined(FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) && FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) config->enableBypassCalibration = false; #endif /* FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL. */ #if (defined(FSL_FEATURE_ADC_HAS_CTRL_TSAMP) && FSL_FEATURE_ADC_HAS_CTRL_TSAMP) config->sampleTimeNumber = 0U; #endif /* FSL_FEATURE_ADC_HAS_CTRL_TSAMP. */ #if (defined(FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) && FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) config->enableLowPowerMode = false; #endif /* FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE. */ #if (defined(FSL_FEATURE_ADC_HAS_TRIM_REG) && FSL_FEATURE_ADC_HAS_TRIM_REG) config->voltageRange = kADC_HighVoltageRange; #endif /* FSL_FEATURE_ADC_HAS_TRIM_REG. */ } /*! * brief Deinitialize the ADC module. * * param base ADC peripheral base address. */ void ADC_Deinit(ADC_Type *base) { #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]); #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } #if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) && FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) #if defined(FSL_FEATURE_ADC_HAS_CALIB_REG) && FSL_FEATURE_ADC_HAS_CALIB_REG /*! * brief Do the hardware self-calibration. * deprecated Do not use this function. It has been superceded by @ref ADC_DoOffsetCalibration. * * To calibrate the ADC, set the ADC clock to 500 kHz. In order to achieve the specified ADC accuracy, the A/D * converter must be recalibrated, at a minimum, following every chip reset before initiating normal ADC operation. * * param base ADC peripheral base address. * retval true Calibration succeed. * retval false Calibration failed. */ bool ADC_DoSelfCalibration(ADC_Type *base) { uint32_t frequency = 0U; uint32_t delayUs = 0U; bool ret = true; /* Enable the converter. */ /* This bit can only be set 1 by software. It is cleared automatically whenever the ADC is powered down. This bit should be set after at least 10 ms after the ADC is powered on. */ base->STARTUP = ADC_STARTUP_ADC_ENA_MASK; SDK_DelayAtLeastUs(1U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); if (0UL == (base->STARTUP & ADC_STARTUP_ADC_ENA_MASK)) { ret = false; /* ADC is not powered up. */ } /* Get the ADC clock frequency in synchronous mode. */ frequency = CLOCK_GetFreq(kCLOCK_BusClk) / (((base->CTRL & ADC_CTRL_CLKDIV_MASK) >> ADC_CTRL_CLKDIV_SHIFT) + 1UL); #if defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) && FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE /* Get the ADC clock frequency in asynchronous mode. */ if (ADC_CTRL_ASYNMODE_MASK == (base->CTRL & ADC_CTRL_ASYNMODE_MASK)) { frequency = CLOCK_GetAdcClkFreq(); } #endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE */ assert(0U != frequency); /* If not in by-pass mode, do the calibration. */ if ((ADC_CALIB_CALREQD_MASK == (base->CALIB & ADC_CALIB_CALREQD_MASK)) && (0U == (base->CTRL & ADC_CTRL_BYPASSCAL_MASK))) { /* A calibration cycle requires approximately 81 ADC clocks to complete. */ delayUs = (120UL * FREQUENCY_1MHZ) / frequency + 1UL; /* Calibration is needed, do it now. */ base->CALIB = ADC_CALIB_CALIB_MASK; SDK_DelayAtLeastUs(delayUs, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); if (ADC_CALIB_CALIB_MASK == (base->CALIB & ADC_CALIB_CALIB_MASK)) { ret = false; /* Calibration timeout. */ } } /* A “dummy” conversion cycle requires approximately 6 ADC clocks */ delayUs = (10UL * FREQUENCY_1MHZ) / frequency + 1UL; base->STARTUP |= ADC_STARTUP_ADC_INIT_MASK; SDK_DelayAtLeastUs(delayUs, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); if (ADC_STARTUP_ADC_INIT_MASK == (base->STARTUP & ADC_STARTUP_ADC_INIT_MASK)) { ret = false; } return ret; } /*! * brief Do the hardware offset-calibration. * * To calibrate the ADC, set the ADC clock to 500 kHz. In order to achieve the specified ADC accuracy, the A/D * converter must be recalibrated, at a minimum, following every chip reset before initiating normal ADC operation. * * param base ADC peripheral base address. * param frequency The clock frequency that ADC operates at. * retval true Calibration succeed. * retval false Calibration failed. */ bool ADC_DoOffsetCalibration(ADC_Type *base, uint32_t frequency) { assert(frequency != 0U); uint32_t delayUs = 0U; uint32_t tmp32 = base->CTRL; /* The maximum ADC clock frequency during calibration is 30 MHz. */ const uint32_t maxCalibrationFrequency = 30000000UL; bool ret = true; /* Enable the converter. */ /* This bit should be set after at least 10 us after the ADC is powered on. */ SDK_DelayAtLeastUs(10U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* This bit can only be set 1 by software. It is cleared automatically whenever the ADC is powered down. */ base->STARTUP = ADC_STARTUP_ADC_ENA_MASK; if (0UL == (base->STARTUP & ADC_STARTUP_ADC_ENA_MASK)) { ret = false; /* ADC is not powered up. */ } if (frequency >= maxCalibrationFrequency) { /* The divider should round up to ensure the frequency be lower than the maximum frequency. */ uint8_t divider = (frequency % maxCalibrationFrequency > 0UL) ? (uint8_t)(frequency / maxCalibrationFrequency + 1UL) : (uint8_t)(frequency / maxCalibrationFrequency); /* Divide the system clock to yield an ADC clock of about 30 MHz. */ base->CTRL &= ~ADC_CTRL_CLKDIV_MASK; base->CTRL |= ADC_CTRL_CLKDIV(divider - 1UL); frequency /= divider; } /* Launch the calibration cycle or "dummy" conversions. */ if (ADC_CALIB_CALREQD_MASK == (base->CALIB & ADC_CALIB_CALREQD_MASK)) { /* Calibration is required, do it now. */ base->CALIB = ADC_CALIB_CALIB_MASK; /* A calibration cycle requires approximately 81 ADC clocks to complete. */ delayUs = (120UL * FREQUENCY_1MHZ) / frequency + 1UL; SDK_DelayAtLeastUs(delayUs, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); if (ADC_CALIB_CALIB_MASK == (base->CALIB & ADC_CALIB_CALIB_MASK)) { base->CTRL = tmp32; ret = false; /* Calibration timeout. */ } } else { /* If a calibration is not performed, launch the conversion cycle. */ base->STARTUP |= ADC_STARTUP_ADC_INIT_MASK; /* A “dummy” conversion cycle requires approximately 6 ADC clocks */ delayUs = (10UL * FREQUENCY_1MHZ) / frequency + 1UL; SDK_DelayAtLeastUs(delayUs, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); if (ADC_STARTUP_ADC_INIT_MASK == (base->STARTUP & ADC_STARTUP_ADC_INIT_MASK)) { base->CTRL = tmp32; ret = false; /* Initialization timeout. */ } } base->CTRL = tmp32; return ret; } #else /*! * brief Do the hardware self-calibration. * * To calibrate the ADC, set the ADC clock to 500 kHz. In order to achieve the specified ADC accuracy, the A/D * converter must be recalibrated, at a minimum, following every chip reset before initiating normal ADC operation. * * param base ADC peripheral base address. * param frequency The clock frequency that ADC operates at. * retval true Calibration succeed. * retval false Calibration failed. */ bool ADC_DoSelfCalibration(ADC_Type *base, uint32_t frequency) { assert(frequency != 0U); uint32_t tmp32 = 0U; /* Store the current contents of the ADC CTRL register. */ tmp32 = base->CTRL; /* Divide the system clock to yield an ADC clock of about 500 kHz. */ base->CTRL &= ~ADC_CTRL_CLKDIV_MASK; base->CTRL |= ADC_CTRL_CLKDIV((frequency / 500000U) - 1U); /* Clear the LPWR bit. */ base->CTRL &= ~ADC_CTRL_LPWRMODE_MASK; /* Start ADC self-calibration. */ base->CTRL |= ADC_CTRL_CALMODE_MASK; /* Delay for 300 uSec @ 500KHz ADC clock */ SDK_DelayAtLeastUs(300U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); /* Check the completion of calibration. */ if (ADC_CTRL_CALMODE_MASK == (base->CTRL & ADC_CTRL_CALMODE_MASK)) { /* Restore the contents of the ADC CTRL register. */ base->CTRL = tmp32; return false; /* Calibration timeout. */ } /* Restore the contents of the ADC CTRL register. */ base->CTRL = tmp32; return true; } #endif /* FSL_FEATURE_ADC_HAS_CALIB_REG */ #endif /* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC*/ /*! * brief Configure the conversion sequence A. * * param base ADC peripheral base address. * param config Pointer to configuration structure, see to #adc_conv_seq_config_t. */ void ADC_SetConvSeqAConfig(ADC_Type *base, const adc_conv_seq_config_t *config) { assert(config != NULL); uint32_t tmp32; tmp32 = ADC_SEQ_CTRL_CHANNELS(config->channelMask) /* Channel mask. */ #if (defined(FSL_FEATURE_ADC_HAS_SEQ_CTRL_TSAMP) && FSL_FEATURE_ADC_HAS_SEQ_CTRL_TSAMP) | ADC_SEQ_CTRL_TSAMP(config->seqSampleTimeNumber) /* Sequence A sampling time.*/ #endif /* FSL_FEATURE_ADC_HAS_SEQ_CTRL_TSAMP*/ | ADC_SEQ_CTRL_TRIGGER(config->triggerMask); /* Trigger mask. */ /* Polarity for tirgger signal. */ switch (config->triggerPolarity) { case kADC_TriggerPolarityPositiveEdge: tmp32 |= ADC_SEQ_CTRL_TRIGPOL_MASK; break; default: /* kADC_TriggerPolarityNegativeEdge */ break; } /* Bypass the clock Sync. */ if (config->enableSyncBypass) { tmp32 |= ADC_SEQ_CTRL_SYNCBYPASS_MASK; } /* Interrupt point. */ switch (config->interruptMode) { case kADC_InterruptForEachSequence: tmp32 |= ADC_SEQ_CTRL_MODE_MASK; break; default: /* kADC_InterruptForEachConversion */ break; } /* One trigger for a conversion, or for a sequence. */ if (config->enableSingleStep) { tmp32 |= ADC_SEQ_CTRL_SINGLESTEP_MASK; } base->SEQ_CTRL[0] = tmp32; } #if !(defined(FSL_FEATURE_ADC_HAS_SINGLE_SEQ) && FSL_FEATURE_ADC_HAS_SINGLE_SEQ) /*! * brief Configure the conversion sequence B. * * param base ADC peripheral base address. * param config Pointer to configuration structure, see to #adc_conv_seq_config_t. */ void ADC_SetConvSeqBConfig(ADC_Type *base, const adc_conv_seq_config_t *config) { assert(config != NULL); uint32_t tmp32; tmp32 = ADC_SEQ_CTRL_CHANNELS(config->channelMask) /* Channel mask. */ #if (defined(FSL_FEATURE_ADC_HAS_SEQ_CTRL_TSAMP) && FSL_FEATURE_ADC_HAS_SEQ_CTRL_TSAMP) | ADC_SEQ_CTRL_TSAMP(config->seqSampleTimeNumber) /* Sequence B sampling time.*/ #endif /* FSL_FEATURE_ADC_HAS_SEQ_CTRL_TSAMP*/ | ADC_SEQ_CTRL_TRIGGER(config->triggerMask); /* Trigger mask. */ /* Polarity for tirgger signal. */ switch (config->triggerPolarity) { case kADC_TriggerPolarityPositiveEdge: tmp32 |= ADC_SEQ_CTRL_TRIGPOL_MASK; break; default: /* kADC_TriggerPolarityPositiveEdge */ break; } /* Bypass the clock Sync. */ if (config->enableSyncBypass) { tmp32 |= ADC_SEQ_CTRL_SYNCBYPASS_MASK; } /* Interrupt point. */ switch (config->interruptMode) { case kADC_InterruptForEachSequence: tmp32 |= ADC_SEQ_CTRL_MODE_MASK; break; default: /* kADC_InterruptForEachConversion */ break; } /* One trigger for a conversion, or for a sequence. */ if (config->enableSingleStep) { tmp32 |= ADC_SEQ_CTRL_SINGLESTEP_MASK; } base->SEQ_CTRL[1] = tmp32; } #endif /* FSL_FEATURE_ADC_HAS_SINGLE_SEQ */ /*! * brief Get the global ADC conversion infomation of sequence A. * * param base ADC peripheral base address. * param info Pointer to information structure, see to #adc_result_info_t; * retval true The conversion result is ready. * retval false The conversion result is not ready yet. */ bool ADC_GetConvSeqAGlobalConversionResult(ADC_Type *base, adc_result_info_t *info) { assert(info != NULL); uint32_t tmp32 = base->SEQ_GDAT[0]; /* Read to clear the status. */ bool ret = true; if (0U == (ADC_SEQ_GDAT_DATAVALID_MASK & tmp32)) { ret = false; } info->result = (tmp32 & ADC_SEQ_GDAT_RESULT_MASK) >> ADC_SEQ_GDAT_RESULT_SHIFT; info->thresholdCompareStatus = (adc_threshold_compare_status_t)(uint32_t)((tmp32 & ADC_SEQ_GDAT_THCMPRANGE_MASK) >> ADC_SEQ_GDAT_THCMPRANGE_SHIFT); info->thresholdCorssingStatus = (adc_threshold_crossing_status_t)(uint32_t)( (tmp32 & ADC_SEQ_GDAT_THCMPCROSS_MASK) >> ADC_SEQ_GDAT_THCMPCROSS_SHIFT); info->channelNumber = (tmp32 & ADC_SEQ_GDAT_CHN_MASK) >> ADC_SEQ_GDAT_CHN_SHIFT; info->overrunFlag = ((tmp32 & ADC_SEQ_GDAT_OVERRUN_MASK) == ADC_SEQ_GDAT_OVERRUN_MASK); return ret; } #if !(defined(FSL_FEATURE_ADC_HAS_SINGLE_SEQ) && FSL_FEATURE_ADC_HAS_SINGLE_SEQ) /*! * brief Get the global ADC conversion infomation of sequence B. * * param base ADC peripheral base address. * param info Pointer to information structure, see to #adc_result_info_t; * retval true The conversion result is ready. * retval false The conversion result is not ready yet. */ bool ADC_GetConvSeqBGlobalConversionResult(ADC_Type *base, adc_result_info_t *info) { assert(info != NULL); uint32_t tmp32 = base->SEQ_GDAT[1]; /* Read to clear the status. */ bool ret = true; if (0U == (ADC_SEQ_GDAT_DATAVALID_MASK & tmp32)) { ret = false; } info->result = (tmp32 & ADC_SEQ_GDAT_RESULT_MASK) >> ADC_SEQ_GDAT_RESULT_SHIFT; info->thresholdCompareStatus = (adc_threshold_compare_status_t)(uint32_t)((tmp32 & ADC_SEQ_GDAT_THCMPRANGE_MASK) >> ADC_SEQ_GDAT_THCMPRANGE_SHIFT); info->thresholdCorssingStatus = (adc_threshold_crossing_status_t)(uint32_t)( (tmp32 & ADC_SEQ_GDAT_THCMPCROSS_MASK) >> ADC_SEQ_GDAT_THCMPCROSS_SHIFT); info->channelNumber = (tmp32 & ADC_SEQ_GDAT_CHN_MASK) >> ADC_SEQ_GDAT_CHN_SHIFT; info->overrunFlag = ((tmp32 & ADC_SEQ_GDAT_OVERRUN_MASK) == ADC_SEQ_GDAT_OVERRUN_MASK); return ret; } #endif /* FSL_FEATURE_ADC_HAS_SINGLE_SEQ */ /*! * brief Get the channel's ADC conversion completed under each conversion sequence. * * param base ADC peripheral base address. * param channel The indicated channel number. * param info Pointer to information structure, see to #adc_result_info_t; * retval true The conversion result is ready. * retval false The conversion result is not ready yet. */ bool ADC_GetChannelConversionResult(ADC_Type *base, uint32_t channel, adc_result_info_t *info) { assert(info != NULL); assert(channel < ADC_DAT_COUNT); uint32_t tmp32 = base->DAT[channel]; /* Read to clear the status. */ bool ret = true; if (0U == (ADC_DAT_DATAVALID_MASK & tmp32)) { ret = false; } info->result = (tmp32 & ADC_DAT_RESULT_MASK) >> ADC_DAT_RESULT_SHIFT; #if (defined(FSL_FEATURE_ADC_DAT_OF_HIGH_ALIGNMENT) && FSL_FEATURE_ADC_DAT_OF_HIGH_ALIGNMENT) switch ((base->CTRL & ADC_CTRL_RESOL_MASK) >> ADC_CTRL_RESOL_SHIFT) { case kADC_Resolution10bit: info->result >>= kADC_Resolution10bitInfoResultShift; break; case kADC_Resolution8bit: info->result >>= kADC_Resolution8bitInfoResultShift; break; case kADC_Resolution6bit: info->result >>= kADC_Resolution6bitInfoResultShift; break; default: assert(false); break; } #endif info->thresholdCompareStatus = (adc_threshold_compare_status_t)(uint32_t)((tmp32 & ADC_DAT_THCMPRANGE_MASK) >> ADC_DAT_THCMPRANGE_SHIFT); info->thresholdCorssingStatus = (adc_threshold_crossing_status_t)(uint32_t)((tmp32 & ADC_DAT_THCMPCROSS_MASK) >> ADC_DAT_THCMPCROSS_SHIFT); info->channelNumber = (tmp32 & ADC_DAT_CHANNEL_MASK) >> ADC_DAT_CHANNEL_SHIFT; info->overrunFlag = ((tmp32 & ADC_DAT_OVERRUN_MASK) == ADC_DAT_OVERRUN_MASK); return ret; } #if defined(FSL_FEATURE_ADC_ASYNC_SYSCON_TEMP) && (FSL_FEATURE_ADC_ASYNC_SYSCON_TEMP) void ADC_EnableTemperatureSensor(ADC_Type *base, bool enable) { if (enable) { SYSCON->ASYNCAPBCTRL = SYSCON_ASYNCAPBCTRL_ENABLE_MASK; ASYNC_SYSCON->TEMPSENSORCTRL = kADC_NoOffsetAdded; ASYNC_SYSCON->TEMPSENSORCTRL |= ASYNC_SYSCON_TEMPSENSORCTRL_ENABLE_MASK; base->GPADC_CTRL0 |= (kADC_ADCInUnityGainMode | kADC_Impedance87kOhm); } else { /* if the temperature sensor is not turned on then ASYNCAPBCTRL is likely to be zero * and accessing the registers will cause a memory access error. Test for this */ if (SYSCON->ASYNCAPBCTRL == SYSCON_ASYNCAPBCTRL_ENABLE_MASK) { ASYNC_SYSCON->TEMPSENSORCTRL = 0x0; base->GPADC_CTRL0 &= ~(kADC_ADCInUnityGainMode | kADC_Impedance87kOhm); base->GPADC_CTRL0 |= kADC_Impedance55kOhm; } } } #endif