Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:58

0001 /*
0002  * Copyright (c) 2016, Freescale Semiconductor, Inc.
0003  * Copyright 2016-2020 NXP
0004  * All rights reserved.
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_adc.h"
0010 
0011 /* Component ID definition, used by tools. */
0012 #ifndef FSL_COMPONENT_ID
0013 #define FSL_COMPONENT_ID "platform.drivers.adc_12b1msps_sar"
0014 #endif
0015 
0016 /*******************************************************************************
0017  * Prototypes
0018  ******************************************************************************/
0019 /*!
0020  * @brief Get instance number for ADC module.
0021  *
0022  * @param base ADC peripheral base address
0023  */
0024 static uint32_t ADC_GetInstance(ADC_Type *base);
0025 
0026 /*******************************************************************************
0027  * Variables
0028  ******************************************************************************/
0029 /*! @brief Pointers to ADC bases for each instance. */
0030 static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS;
0031 
0032 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0033 /*! @brief Pointers to ADC clocks for each instance. */
0034 static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS;
0035 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0036 
0037 /*******************************************************************************
0038  * Code
0039  ******************************************************************************/
0040 static uint32_t ADC_GetInstance(ADC_Type *base)
0041 {
0042     uint32_t instance;
0043 
0044     /* Find the instance index from base address mappings. */
0045     for (instance = 0; instance < ARRAY_SIZE(s_adcBases); instance++)
0046     {
0047         if (s_adcBases[instance] == base)
0048         {
0049             break;
0050         }
0051     }
0052 
0053     assert(instance < ARRAY_SIZE(s_adcBases));
0054 
0055     return instance;
0056 }
0057 
0058 /*!
0059  * brief Initialize the ADC module.
0060  *
0061  * param base ADC peripheral base address.
0062  * param config Pointer to "adc_config_t" structure.
0063  */
0064 void ADC_Init(ADC_Type *base, const adc_config_t *config)
0065 {
0066     assert(NULL != config);
0067 
0068     uint32_t tmp32;
0069 
0070 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0071     /* Enable the clock. */
0072     CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]);
0073 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0074     /* ADCx_CFG */
0075     tmp32 = base->CFG & (ADC_CFG_AVGS_MASK | ADC_CFG_ADTRG_MASK); /* Reserve AVGS and ADTRG bits. */
0076     tmp32 |= ADC_CFG_REFSEL(config->referenceVoltageSource) | ADC_CFG_ADSTS(config->samplePeriodMode) |
0077              ADC_CFG_ADICLK(config->clockSource) | ADC_CFG_ADIV(config->clockDriver) | ADC_CFG_MODE(config->resolution);
0078     if (config->enableOverWrite)
0079     {
0080         tmp32 |= ADC_CFG_OVWREN_MASK;
0081     }
0082     if (config->enableLongSample)
0083     {
0084         tmp32 |= ADC_CFG_ADLSMP_MASK;
0085     }
0086     if (config->enableLowPower)
0087     {
0088         tmp32 |= ADC_CFG_ADLPC_MASK;
0089     }
0090     if (config->enableHighSpeed)
0091     {
0092         tmp32 |= ADC_CFG_ADHSC_MASK;
0093     }
0094     base->CFG = tmp32;
0095 
0096     /* ADCx_GC  */
0097     tmp32 = base->GC & ~(ADC_GC_ADCO_MASK | ADC_GC_ADACKEN_MASK);
0098     if (config->enableContinuousConversion)
0099     {
0100         tmp32 |= ADC_GC_ADCO_MASK;
0101     }
0102     if (config->enableAsynchronousClockOutput)
0103     {
0104         tmp32 |= ADC_GC_ADACKEN_MASK;
0105     }
0106     base->GC = tmp32;
0107 }
0108 
0109 /*!
0110  * brief De-initializes the ADC module.
0111  *
0112  * param base ADC peripheral base address.
0113  */
0114 void ADC_Deinit(ADC_Type *base)
0115 {
0116 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0117     /* Disable the clock. */
0118     CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]);
0119 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0120 }
0121 
0122 /*!
0123  * brief Gets an available pre-defined settings for the converter's configuration.
0124  *
0125  * This function initializes the converter configuration structure with available settings. The default values are:
0126  * code
0127  *  config->enableAsynchronousClockOutput = true;
0128  *  config->enableOverWrite =               false;
0129  *  config->enableContinuousConversion =    false;
0130  *  config->enableHighSpeed =               false;
0131  *  config->enableLowPower =                false;
0132  *  config->enableLongSample =              false;
0133  *  config->referenceVoltageSource =        kADC_ReferenceVoltageSourceAlt0;
0134  *  config->samplePeriodMode =              kADC_SamplePeriod2or12Clocks;
0135  *  config->clockSource =                   kADC_ClockSourceAD;
0136  *  config->clockDriver =                   kADC_ClockDriver1;
0137  *  config->resolution =                    kADC_Resolution12Bit;
0138  * endcode
0139  * param base   ADC peripheral base address.
0140  * param config Pointer to the configuration structure.
0141  */
0142 void ADC_GetDefaultConfig(adc_config_t *config)
0143 {
0144     assert(NULL != config);
0145 
0146     /* Initializes the configure structure to zero. */
0147     (void)memset(config, 0, sizeof(*config));
0148 
0149     config->enableAsynchronousClockOutput = true;
0150     config->enableOverWrite               = false;
0151     config->enableContinuousConversion    = false;
0152     config->enableHighSpeed               = false;
0153     config->enableLowPower                = false;
0154     config->enableLongSample              = false;
0155     config->referenceVoltageSource        = kADC_ReferenceVoltageSourceAlt0;
0156     config->samplePeriodMode              = kADC_SamplePeriod2or12Clocks;
0157     config->clockSource                   = kADC_ClockSourceAD;
0158     config->clockDriver                   = kADC_ClockDriver1;
0159     config->resolution                    = kADC_Resolution12Bit;
0160 }
0161 
0162 /*!
0163  * brief Configures the conversion channel.
0164  *
0165  * This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API
0166  * configures the channel while the external trigger source helps to trigger the conversion.
0167  *
0168  * Note that the "Channel Group" has a detailed description.
0169  * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one
0170  * group of status and control registers, one for each conversion. The channel group parameter indicates which group of
0171  * registers are used, for example channel group 0 is for Group A registers and channel group 1 is for Group B
0172  * registers. The
0173  * channel groups are used in a "ping-pong" approach to control the ADC operation.  At any point, only one of
0174  * the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and
0175  * hardware
0176  * trigger modes. Channel groups 1 and greater indicate potentially multiple channel group registers for
0177  * use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual
0178  * about the
0179  * number of SC1n registers (channel groups) specific to this device.  None of the channel groups 1 or greater are used
0180  * for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion.
0181  * Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and
0182  * vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
0183  * conversion aborts the current conversion.
0184  *
0185  * param base          ADC peripheral base address.
0186  * param channelGroup  Channel group index.
0187  * param config        Pointer to the "adc_channel_config_t" structure for the conversion channel.
0188  */
0189 void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config)
0190 {
0191     assert(NULL != config);
0192     assert(channelGroup < (uint32_t)FSL_FEATURE_ADC_CONVERSION_CONTROL_COUNT);
0193 
0194     uint32_t tmp32;
0195 
0196     tmp32 = ADC_HC_ADCH(config->channelNumber);
0197     if (config->enableInterruptOnConversionCompleted)
0198     {
0199         tmp32 |= ADC_HC_AIEN_MASK;
0200     }
0201     base->HC[channelGroup] = tmp32;
0202 }
0203 
0204 /*
0205  *To complete calibration, the user must follow the below procedure:
0206  *  1. Configure ADC_CFG with actual operating values for maximum accuracy.
0207  *  2. Configure the ADC_GC values along with CAL bit.
0208  *  3. Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC.
0209  *  4. When CAL bit becomes '0' then check the CALF status and COCO[0] bit status.
0210  */
0211 /*!
0212  * brief  Automates the hardware calibration.
0213  *
0214  * This auto calibration helps to adjust the plus/minus side gain automatically.
0215  * Execute the calibration before using the converter. Note that the software trigger should be used
0216  * during calibration.
0217  *
0218  * param  base ADC peripheral base address.
0219  *
0220  * return                 Execution status.
0221  * retval kStatus_Success Calibration is done successfully.
0222  * retval kStatus_Fail    Calibration has failed.
0223  */
0224 status_t ADC_DoAutoCalibration(ADC_Type *base)
0225 {
0226     status_t status = kStatus_Success;
0227 #if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
0228     bool bHWTrigger = false;
0229 
0230     /* The calibration would be failed when in hardwar mode.
0231      * Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/
0232     if (0U != (ADC_CFG_ADTRG_MASK & base->CFG))
0233     {
0234         bHWTrigger = true;
0235         ADC_EnableHardwareTrigger(base, false);
0236     }
0237 #endif
0238 
0239     /* Clear the CALF and launch the calibration. */
0240     base->GS = ADC_GS_CALF_MASK; /* Clear the CALF. */
0241     base->GC |= ADC_GC_CAL_MASK; /* Launch the calibration. */
0242 
0243     /* Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC. */
0244     while (0U != (base->GC & ADC_GC_CAL_MASK))
0245     {
0246         /* Check the CALF when the calibration is active. */
0247         if (0U != (ADC_GetStatusFlags(base) & (uint32_t)kADC_CalibrationFailedFlag))
0248         {
0249             status = kStatus_Fail;
0250             break;
0251         }
0252     }
0253 
0254     /* When CAL bit becomes '0' then check the CALF status and COCO[0] bit status. */
0255     if (0U == ADC_GetChannelStatusFlags(base, 0U)) /* Check the COCO[0] bit status. */
0256     {
0257         status = kStatus_Fail;
0258     }
0259     if (0U != (ADC_GetStatusFlags(base) & (uint32_t)kADC_CalibrationFailedFlag)) /* Check the CALF status. */
0260     {
0261         status = kStatus_Fail;
0262     }
0263 
0264     /* Clear conversion done flag. */
0265     (void)ADC_GetChannelConversionValue(base, 0U);
0266 
0267 #if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
0268     /* Restore original trigger mode. */
0269     if (true == bHWTrigger)
0270     {
0271         ADC_EnableHardwareTrigger(base, true);
0272     }
0273 #endif
0274 
0275     return status;
0276 }
0277 
0278 /*!
0279  * brief Set user defined offset.
0280  *
0281  * param base   ADC peripheral base address.
0282  * param config Pointer to "adc_offest_config_t" structure.
0283  */
0284 void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config)
0285 {
0286     assert(NULL != config);
0287 
0288     uint32_t tmp32;
0289 
0290     tmp32 = ADC_OFS_OFS(config->offsetValue);
0291     if (config->enableSigned)
0292     {
0293         tmp32 |= ADC_OFS_SIGN_MASK;
0294     }
0295     base->OFS = tmp32;
0296 }
0297 
0298 /*!
0299  * brief Configures the hardware compare mode.
0300  *
0301  * The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the
0302  * result
0303  * in the compare range is available. To compare the range, see "adc_hardware_compare_mode_t" or the appopriate
0304  * reference
0305  * manual for more information.
0306  *
0307  * param base ADC peripheral base address.
0308  * param Pointer to "adc_hardware_compare_config_t" structure.
0309  *
0310  */
0311 void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config)
0312 {
0313     uint32_t tmp32;
0314 
0315     tmp32 = base->GC & ~(ADC_GC_ACFE_MASK | ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK);
0316     if (NULL == config) /* Pass "NULL" to disable the feature. */
0317     {
0318         base->GC = tmp32;
0319         return;
0320     }
0321     /* Enable the feature. */
0322     tmp32 |= ADC_GC_ACFE_MASK;
0323 
0324     /* Select the hardware compare working mode. */
0325     switch (config->hardwareCompareMode)
0326     {
0327         case kADC_HardwareCompareMode0:
0328             break;
0329         case kADC_HardwareCompareMode1:
0330             tmp32 |= ADC_GC_ACFGT_MASK;
0331             break;
0332         case kADC_HardwareCompareMode2:
0333             tmp32 |= ADC_GC_ACREN_MASK;
0334             break;
0335         case kADC_HardwareCompareMode3:
0336             tmp32 |= ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK;
0337             break;
0338         default:
0339             assert(false);
0340             break;
0341     }
0342     base->GC = tmp32;
0343 
0344     /* Load the compare values. */
0345     tmp32    = ADC_CV_CV1(config->value1) | ADC_CV_CV2(config->value2);
0346     base->CV = tmp32;
0347 }
0348 
0349 /*!
0350  * brief Configures the hardware average mode.
0351  *
0352  * The hardware average mode provides a way to process the conversion result automatically by using hardware. The
0353  * multiple
0354  * conversion results are accumulated and averaged internally making them easier to read.
0355  *
0356  * param base ADC peripheral base address.
0357  * param mode Setting the hardware average mode. See "adc_hardware_average_mode_t".
0358  */
0359 void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode)
0360 {
0361     uint32_t tmp32;
0362 
0363     if (mode == kADC_HardwareAverageDiasable)
0364     {
0365         base->GC &= ~ADC_GC_AVGE_MASK;
0366     }
0367     else
0368     {
0369         tmp32 = base->CFG & ~ADC_CFG_AVGS_MASK;
0370         tmp32 |= ADC_CFG_AVGS(mode);
0371         base->CFG = tmp32;
0372         base->GC |= ADC_GC_AVGE_MASK; /* Enable the hardware compare. */
0373     }
0374 }
0375 
0376 /*!
0377  * brief Clears the converter's status falgs.
0378  *
0379  * param base ADC peripheral base address.
0380  * param mask Mask value for the cleared flags. See "adc_status_flags_t".
0381  */
0382 void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask)
0383 {
0384     uint32_t tmp32 = 0;
0385 
0386     if (0U != (mask & (uint32_t)kADC_CalibrationFailedFlag))
0387     {
0388         tmp32 |= ADC_GS_CALF_MASK;
0389     }
0390     if (0U != (mask & (uint32_t)kADC_ConversionActiveFlag))
0391     {
0392         tmp32 |= ADC_GS_ADACT_MASK;
0393     }
0394     base->GS = tmp32;
0395 }