Просмотр исходного кода

!442 添加ADC驱动
Merge pull request !442 from diskwu/adc

bernard 4 лет назад
Родитель
Сommit
6f59e43bc0

+ 20 - 0
bsp/imx6ull-artpi-smart/drivers/Kconfig

@@ -171,6 +171,26 @@ menu "Select PWM Driver"
     endif
 endmenu
 
+menu "Select ADC Driver"
+     config RT_USING_ADC
+        bool "Enable ADC"
+        default n
+    if RT_USING_ADC
+        config BSP_USING_ADC1_1
+            bool "Enable ADC1 CH1"
+            default n
+        config BSP_USING_ADC1_2
+            bool "Enable ADC1 CH2"
+            default n
+		config BSP_USING_ADC1_3
+            bool "Enable ADC1 CH3"
+            default n
+		config BSP_USING_ADC1_4
+            bool "Enable ADC1 CH4"
+            default n
+    endif
+endmenu
+
 menu "Select WDT Driver"
     if RT_USING_WDT
         config RT_USING_WDT1

+ 243 - 0
bsp/imx6ull-artpi-smart/drivers/drv_adc.c

@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-04-28     tyustli      first version
+ *
+ */
+
+#include <rtthread.h>
+#define RT_USING_ADC
+#ifdef RT_USING_ADC
+
+#define LOG_TAG             "drv.adc"
+#include <drv_log.h>
+
+#include <rtdevice.h>
+#include <ioremap.h>
+
+#include "fsl_adc.h"
+#include "drv_adc.h"
+#include <drv_common.h>
+#include <drivers/adc.h>
+
+static rt_err_t imx6ull_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
+{
+    return RT_EOK;
+}
+
+static rt_err_t imx6ull_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
+{
+    adc_channel_config_t adc_channel;
+    ADC_Type *base;
+    base = (ADC_Type *)(device->parent.user_data);
+
+    adc_channel.channelNumber = channel;
+    adc_channel.enableInterruptOnConversionCompleted = 0;
+
+    ADC_SetChannelConfig(base, 0, &adc_channel);
+
+    while (0U == ADC_GetChannelStatusFlags(base, 0))
+    {
+        continue;
+    }
+
+    *value = ADC_GetChannelConversionValue(base, 0);
+
+    return RT_EOK;
+}
+
+static struct rt_adc_ops imx6ull_adc_ops =
+{
+    .enabled = imx6ull_adc_enabled,
+    .convert = imx6ull_adc_convert,
+};
+
+
+int imx6ull_adc_gpio_init(void)
+{
+#ifdef BSP_USING_ADC1_1
+    do {
+        struct imx6ull_iomuxc gpio;
+        uint32_t pin_fun_id[5]={IOMUXC_GPIO1_IO01_GPIO1_IO01};
+
+        gpio.muxRegister = pin_fun_id[0];
+        gpio.muxMode = pin_fun_id[1];
+        gpio.inputRegister = pin_fun_id[2];
+        gpio.inputDaisy = pin_fun_id[3];
+        gpio.configRegister = pin_fun_id[4];
+        gpio.inputOnfield = 0;
+        gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
+
+        imx6ull_gpio_init(&gpio);
+    }while(0);
+#endif
+
+#ifdef BSP_USING_ADC1_2
+    do {
+        struct imx6ull_iomuxc gpio;
+        uint32_t pin_fun_id[5]={IOMUXC_GPIO1_IO02_GPIO1_IO02};
+
+        gpio.muxRegister = pin_fun_id[0];
+        gpio.muxMode = pin_fun_id[1];
+        gpio.inputRegister = pin_fun_id[2];
+        gpio.inputDaisy = pin_fun_id[3];
+        gpio.configRegister = pin_fun_id[4];
+        gpio.inputOnfield = 0;
+        gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
+
+        imx6ull_gpio_init(&gpio);
+    }while(0);
+#endif
+
+#ifdef BSP_USING_ADC1_3
+    do {
+        struct imx6ull_iomuxc gpio;
+        uint32_t pin_fun_id[5]={IOMUXC_GPIO1_IO03_GPIO1_IO03};
+
+        gpio.muxRegister = pin_fun_id[0];
+        gpio.muxMode = pin_fun_id[1];
+        gpio.inputRegister = pin_fun_id[2];
+        gpio.inputDaisy = pin_fun_id[3];
+        gpio.configRegister = pin_fun_id[4];
+        gpio.inputOnfield = 0;
+        gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
+
+        imx6ull_gpio_init(&gpio);
+    }while(0);
+#endif
+
+#ifdef BSP_USING_ADC1_4
+    do {
+        struct imx6ull_iomuxc gpio;
+        uint32_t pin_fun_id[5]={IOMUXC_GPIO1_IO04_GPIO1_IO04};
+
+        gpio.muxRegister = pin_fun_id[0];
+        gpio.muxMode = pin_fun_id[1];
+        gpio.inputRegister = pin_fun_id[2];
+        gpio.inputDaisy = pin_fun_id[3];
+        gpio.configRegister = pin_fun_id[4];
+        gpio.inputOnfield = 0;
+        gpio.configValue = IOMUXC_SW_PAD_CTL_PAD_DSE(2U) | IOMUXC_SW_PAD_CTL_PAD_SPEED(2U);
+
+        imx6ull_gpio_init(&gpio);
+    }while(0);
+#endif
+
+    return 0;
+}
+
+int rt_hw_adc_init(void)
+{
+    rt_err_t ret = RT_EOK;
+    imx6ull_adc_gpio_init();
+
+#if defined(BSP_USING_ADC1_1) || defined(BSP_USING_ADC1_2) || defined(BSP_USING_ADC1_3) || defined(BSP_USING_ADC1_4)
+    static adc_config_t ADC1_config_value;
+    static struct rt_adc_device adc1_device;
+    ADC_Type *adc1_base;
+
+    adc1_base = (ADC_Type *)rt_ioremap((void*)ADC1, 0x1000);
+
+    ADC_GetDefaultConfig(&ADC1_config_value);
+    ADC_Init(adc1_base, &ADC1_config_value);
+
+    ADC_DoAutoCalibration(adc1_base);
+
+    ret = rt_hw_adc_register(&adc1_device, "adc1", &imx6ull_adc_ops, adc1_base);
+
+    if (ret != RT_EOK)
+    {
+        LOG_E("register adc1 device failed error code = %d\n", ret);
+    }
+
+#endif
+
+    return ret;
+}
+
+INIT_DEVICE_EXPORT(rt_hw_adc_init);
+
+void set_adc_default(void *parameter)
+{
+    int result = 0;
+
+#ifdef BSP_USING_ADC1_1
+    do {
+        struct rt_adc_device *device = RT_NULL;
+        device = (struct rt_adc_device *)rt_device_find("adc1");
+        if (!device)
+        {
+            result = -RT_EIO;
+            return;
+        }
+
+        result = rt_adc_enable(device, 1);
+        result = rt_adc_read(device, 1);
+        rt_kprintf("adc ch1 read result is %d\n",result);
+    } while(0);
+
+#endif
+
+#ifdef BSP_USING_ADC1_2
+    do {
+        struct rt_adc_device *device = RT_NULL;
+        device = (struct rt_adc_device *)rt_device_find("adc1");
+        if (!device)
+        {
+            result = -RT_EIO;
+            return;
+        }
+
+        result = rt_adc_enable(device, 2);
+        result = rt_adc_read(device, 2);
+        rt_kprintf("adc ch2 read result is %d\n",result);
+    } while(0);
+#endif
+
+#ifdef BSP_USING_ADC1_3
+    do {
+        struct rt_adc_device *device = RT_NULL;
+        device = (struct rt_adc_device *)rt_device_find("adc1");
+        if (!device)
+        {
+            result = -RT_EIO;
+            return;
+        }
+
+        result = rt_adc_enable(device, 3);
+        result = rt_adc_read(device, 3);
+        rt_kprintf("adc ch3 read result is %d\n",result);
+    } while(0);
+#endif
+
+#ifdef BSP_USING_ADC1_4
+    do {
+        struct rt_adc_device *device = RT_NULL;
+        device = (struct rt_adc_device *)rt_device_find("adc1");
+        if (!device)
+        {
+            result = -RT_EIO;
+            return;
+        }
+
+        result = rt_adc_enable(device, 4);
+        result = rt_adc_read(device, 4);
+        rt_kprintf("adc ch4 read result is %d\n",result);
+    } while(0);
+#endif
+
+}
+
+static int set_adc_init(void)
+{
+    rt_thread_t tid = rt_thread_create("adc_loop", set_adc_default, RT_NULL, 1024, 16, 20);
+    RT_ASSERT(tid != RT_NULL);
+    rt_thread_startup(tid);
+    return(RT_EOK);
+}
+INIT_APP_EXPORT(set_adc_init);
+#endif /* BSP_USING_ADC */

+ 18 - 0
bsp/imx6ull-artpi-smart/drivers/drv_adc.h

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-04-20     Lee          the first version.
+ */
+
+#ifndef DRV_ADC_H__
+#define DRV_ADC_H__
+#include <rtdevice.h>
+
+int rt_hw_adc_init(void);
+
+#endif /* DRV_ADC_H__ */
+

+ 1 - 0
bsp/imx6ull-artpi-smart/drivers/imx6ull.h

@@ -205,6 +205,7 @@ enum _imx_interrupts
 #include "fsl_i2c.h"
 #include "fsl_ecspi.h"
 #include "fsl_snvs_hp.h"
+#include "fsl_adc.h"
 
 #define IMX6ULL_PERIPH_SIZE         (16 * 1024)
 

+ 285 - 0
bsp/imx6ull-artpi-smart/libraries/sdk/devices/MCIMX6Y2/drivers/fsl_adc.c

@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_adc.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.adc_12b1msps_sar"
+#endif
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*!
+ * @brief Get instance number for ADC module.
+ *
+ * @param base ADC peripheral base address
+ */
+static uint32_t ADC_GetInstance(ADC_Type *base);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*! @brief Pointers to ADC bases for each instance. */
+static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS;
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+/*! @brief Pointers to ADC clocks for each instance. */
+static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS;
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+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;
+}
+
+void ADC_Init(ADC_Type *base, const adc_config_t *config)
+{
+    assert(NULL != config);
+
+    uint32_t tmp32;
+
+#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
+    /* Enable the clock. */
+    CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]);
+#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
+    /* ADCx_CFG */
+    tmp32 = base->CFG & (ADC_CFG_AVGS_MASK | ADC_CFG_ADTRG_MASK); /* Reserve AVGS and ADTRG bits. */
+    tmp32 |= ADC_CFG_REFSEL(config->referenceVoltageSource) | ADC_CFG_ADSTS(config->samplePeriodMode) |
+             ADC_CFG_ADICLK(config->clockSource) | ADC_CFG_ADIV(config->clockDriver) | ADC_CFG_MODE(config->resolution);
+    if (config->enableOverWrite)
+    {
+        tmp32 |= ADC_CFG_OVWREN_MASK;
+    }
+    if (config->enableLongSample)
+    {
+        tmp32 |= ADC_CFG_ADLSMP_MASK;
+    }
+    if (config->enableLowPower)
+    {
+        tmp32 |= ADC_CFG_ADLPC_MASK;
+    }
+    if (config->enableHighSpeed)
+    {
+        tmp32 |= ADC_CFG_ADHSC_MASK;
+    }
+    base->CFG = tmp32;
+
+    /* ADCx_GC  */
+    tmp32 = base->GC & ~(ADC_GC_ADCO_MASK | ADC_GC_ADACKEN_MASK);
+    if (config->enableContinuousConversion)
+    {
+        tmp32 |= ADC_GC_ADCO_MASK;
+    }
+    if (config->enableAsynchronousClockOutput)
+    {
+        tmp32 |= ADC_GC_ADACKEN_MASK;
+    }
+    base->GC = tmp32;
+}
+
+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 */
+}
+
+void ADC_GetDefaultConfig(adc_config_t *config)
+{
+    assert(NULL != config);
+
+    config->enableAsynchronousClockOutput = true;
+    config->enableOverWrite = false;
+    config->enableContinuousConversion = false;
+    config->enableHighSpeed = false;
+    config->enableLowPower = false;
+    config->enableLongSample = false;
+    config->referenceVoltageSource = kADC_ReferenceVoltageSourceAlt0;
+    config->samplePeriodMode = kADC_SamplePeriod2or12Clocks;
+    config->clockSource = kADC_ClockSourceAD;
+    config->clockDriver = kADC_ClockDriver1;
+    config->resolution = kADC_Resolution12Bit;
+}
+
+void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config)
+{
+    assert(NULL != config);
+    assert(channelGroup < ADC_HC_COUNT);
+
+    uint32_t tmp32;
+
+    tmp32 = ADC_HC_ADCH(config->channelNumber);
+    if (config->enableInterruptOnConversionCompleted)
+    {
+        tmp32 |= ADC_HC_AIEN_MASK;
+    }
+    base->HC[channelGroup] = tmp32;
+}
+
+/*
+ *To complete calibration, the user must follow the below procedure:
+ *  1. Configure ADC_CFG with actual operating values for maximum accuracy.
+ *  2. Configure the ADC_GC values along with CAL bit.
+ *  3. Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC.
+ *  4. When CAL bit becomes '0' then check the CALF status and COCO[0] bit status.
+ */
+status_t ADC_DoAutoCalibration(ADC_Type *base)
+{
+    status_t status = kStatus_Success;
+#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
+    bool bHWTrigger = false;
+
+    /* The calibration would be failed when in hardwar mode.
+     * Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/
+    if (0U != (ADC_CFG_ADTRG_MASK & base->CFG))
+    {
+        bHWTrigger = true;
+        ADC_EnableHardwareTrigger(base, false);
+    }
+#endif
+
+    /* Clear the CALF and launch the calibration. */
+    base->GS = ADC_GS_CALF_MASK; /* Clear the CALF. */
+    base->GC |= ADC_GC_CAL_MASK; /* Launch the calibration. */
+
+    /* Check the status of CALF bit in ADC_GS and the CAL bit in ADC_GC. */
+    while (0U != (base->GC & ADC_GC_CAL_MASK))
+    {
+        /* Check the CALF when the calibration is active. */
+        if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag))
+        {
+            status = kStatus_Fail;
+            break;
+        }
+    }
+
+    /* When CAL bit becomes '0' then check the CALF status and COCO[0] bit status. */
+    if (0U == ADC_GetChannelStatusFlags(base, 0U)) /* Check the COCO[0] bit status. */
+    {
+        status = kStatus_Fail;
+    }
+    if (0U != (ADC_GetStatusFlags(base) & kADC_CalibrationFailedFlag)) /* Check the CALF status. */
+    {
+        status = kStatus_Fail;
+    }
+
+    /* Clear conversion done flag. */
+    ADC_GetChannelConversionValue(base, 0U);
+
+#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
+    /* Restore original trigger mode. */
+    if (true == bHWTrigger)
+    {
+        ADC_EnableHardwareTrigger(base, true);
+    }
+#endif
+
+    return status;
+}
+
+void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config)
+{
+    assert(NULL != config);
+
+    uint32_t tmp32;
+
+    tmp32 = ADC_OFS_OFS(config->offsetValue);
+    if (config->enableSigned)
+    {
+        tmp32 |= ADC_OFS_SIGN_MASK;
+    }
+    base->OFS = tmp32;
+}
+
+void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config)
+{
+    uint32_t tmp32;
+
+    tmp32 = base->GC & ~(ADC_GC_ACFE_MASK | ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK);
+    if (NULL == config) /* Pass "NULL" to disable the feature. */
+    {
+        base->GC = tmp32;
+        return;
+    }
+    /* Enable the feature. */
+    tmp32 |= ADC_GC_ACFE_MASK;
+
+    /* Select the hardware compare working mode. */
+    switch (config->hardwareCompareMode)
+    {
+        case kADC_HardwareCompareMode0:
+            break;
+        case kADC_HardwareCompareMode1:
+            tmp32 |= ADC_GC_ACFGT_MASK;
+            break;
+        case kADC_HardwareCompareMode2:
+            tmp32 |= ADC_GC_ACREN_MASK;
+            break;
+        case kADC_HardwareCompareMode3:
+            tmp32 |= ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK;
+            break;
+        default:
+            break;
+    }
+    base->GC = tmp32;
+
+    /* Load the compare values. */
+    tmp32 = ADC_CV_CV1(config->value1) | ADC_CV_CV2(config->value2);
+    base->CV = tmp32;
+}
+
+void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode)
+{
+    uint32_t tmp32;
+
+    if (mode == kADC_HardwareAverageDiasable)
+    {
+        base->GC &= ~ADC_GC_AVGE_MASK;
+    }
+    else
+    {
+        tmp32 = base->CFG & ~ADC_CFG_AVGS_MASK;
+        tmp32 |= ADC_CFG_AVGS(mode);
+        base->CFG = tmp32;
+        base->GC |= ADC_GC_AVGE_MASK; /* Enable the hardware compare. */
+    }
+}
+
+void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask)
+{
+    uint32_t tmp32 = 0;
+
+    if (0U != (mask & kADC_CalibrationFailedFlag))
+    {
+        tmp32 |= ADC_GS_CALF_MASK;
+    }
+    if (0U != (mask & kADC_ConversionActiveFlag))
+    {
+        tmp32 |= ADC_GS_ADACT_MASK;
+    }
+    base->GS = tmp32;
+}

+ 420 - 0
bsp/imx6ull-artpi-smart/libraries/sdk/devices/MCIMX6Y2/drivers/fsl_adc.h

@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _FSL_ADC_H_
+#define _FSL_ADC_H_
+
+#include "fsl_common.h"
+
+/*!
+ *  @addtogroup adc_12b1msps_sar
+ *  @{
+ */
+
+/*******************************************************************************
+* Definitions
+******************************************************************************/
+/*! @brief ADC driver version */
+#define FSL_ADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1. */
+
+/*!
+ * @brief Converter's status flags.
+ */
+typedef enum _adc_status_flags
+{
+    kADC_ConversionActiveFlag = ADC_GS_ADACT_MASK, /*!< Conversion is active,not support w1c. */
+    kADC_CalibrationFailedFlag = ADC_GS_CALF_MASK, /*!< Calibration is failed,support w1c. */
+    kADC_AsynchronousWakeupInterruptFlag =
+        ADC_GS_AWKST_MASK, /*!< Asynchronous wakeup interrupt occured, support w1c. */
+} adc_status_flags_t;
+
+/*!
+ * @brief Reference voltage source.
+ */
+typedef enum _adc_reference_voltage_source
+{
+    kADC_ReferenceVoltageSourceAlt0 = 0U, /*!< For external pins pair of VrefH and VrefL. */
+} adc_reference_voltage_source_t;
+
+/*!
+ * @brief Sample time duration.
+ */
+typedef enum _adc_sample_period_mode
+{
+    /* This group of enumeration is for internal use which is related to register setting. */
+    kADC_SamplePeriod2or12Clocks = 0U, /*!< Long sample 12 clocks or short sample 2 clocks. */
+    kADC_SamplePeriod4or16Clocks = 1U, /*!< Long sample 16 clocks or short sample 4 clocks. */
+    kADC_SamplePeriod6or20Clocks = 2U, /*!< Long sample 20 clocks or short sample 6 clocks. */
+    kADC_SamplePeriod8or24Clocks = 3U, /*!< Long sample 24 clocks or short sample 8 clocks. */
+    /* This group of enumeration is for a public user. */
+    /* For long sample mode. */
+    kADC_SamplePeriodLong12Clcoks = kADC_SamplePeriod2or12Clocks, /*!< Long sample 12 clocks. */
+    kADC_SamplePeriodLong16Clcoks = kADC_SamplePeriod4or16Clocks, /*!< Long sample 16 clocks. */
+    kADC_SamplePeriodLong20Clcoks = kADC_SamplePeriod6or20Clocks, /*!< Long sample 20 clocks. */
+    kADC_SamplePeriodLong24Clcoks = kADC_SamplePeriod8or24Clocks, /*!< Long sample 24 clocks. */
+    /* For short sample mode. */
+    kADC_SamplePeriodShort2Clocks = kADC_SamplePeriod2or12Clocks, /*!< Short sample 2 clocks. */
+    kADC_SamplePeriodShort4Clocks = kADC_SamplePeriod4or16Clocks, /*!< Short sample 4 clocks. */
+    kADC_SamplePeriodShort6Clocks = kADC_SamplePeriod6or20Clocks, /*!< Short sample 6 clocks. */
+    kADC_SamplePeriodShort8Clocks = kADC_SamplePeriod8or24Clocks, /*!< Short sample 8 clocks. */
+} adc_sample_period_mode_t;
+
+/*!
+ * @brief Clock source.
+ */
+typedef enum _adc_clock_source
+{
+    kADC_ClockSourceIPG = 0U,     /*!< Select IPG clock to generate ADCK. */
+    kADC_ClockSourceIPGDiv2 = 1U, /*!< Select IPG clock divided by 2 to generate ADCK. */
+#if !(defined(FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE) && FSL_FEATURE_ADC_SUPPORT_ALTCLK_REMOVE)
+    kADC_ClockSourceALT = 2U, /*!< Select alternate clock to generate ADCK. */
+#endif
+    kADC_ClockSourceAD = 3U, /*!< Select Asynchronous clock to generate ADCK. */
+} adc_clock_source_t;
+
+/*!
+ * @brief Clock divider for the converter.
+ */
+typedef enum _adc_clock_drvier
+{
+    kADC_ClockDriver1 = 0U, /*!< For divider 1 from the input clock to the module. */
+    kADC_ClockDriver2 = 1U, /*!< For divider 2 from the input clock to the module. */
+    kADC_ClockDriver4 = 2U, /*!< For divider 4 from the input clock to the module. */
+    kADC_ClockDriver8 = 3U, /*!< For divider 8 from the input clock to the module. */
+} adc_clock_driver_t;
+
+/*!
+ * @brief Converter's resolution.
+ */
+typedef enum _adc_resolution
+{
+    kADC_Resolution8Bit = 0U,  /*!< Single End 8-bit resolution. */
+    kADC_Resolution10Bit = 1U, /*!< Single End 10-bit resolution. */
+    kADC_Resolution12Bit = 2U, /*!< Single End 12-bit resolution. */
+} adc_resolution_t;
+
+/*!
+ * @brief Converter hardware compare mode.
+ */
+typedef enum _adc_hardware_compare_mode
+{
+    kADC_HardwareCompareMode0 = 0U, /*!< Compare true if the result is less than the value1. */
+    kADC_HardwareCompareMode1 = 1U, /*!< Compare true if the result is greater than or equal to value1. */
+    kADC_HardwareCompareMode2 = 2U, /*!< Value1 <= Value2, compare true if the result is less than value1 Or
+                                                          the result is Greater than value2.
+                                         Value1 >  Value2, compare true if the result is less than value1 And the
+                                                          result is greater than value2*/
+    kADC_HardwareCompareMode3 = 3U, /*!< Value1 <= Value2, compare true if the result is greater than or equal
+                                                          to value1 And the result is less than or equal to value2.
+                                         Value1 >  Value2, compare true if the result is greater than or equal to
+                                                          value1 Or the result is less than or equal to value2. */
+} adc_hardware_compare_mode_t;
+
+/*!
+ * @brief Converter hardware average mode.
+ */
+typedef enum _adc_hardware_average_mode
+{
+    kADC_HardwareAverageCount4 = 0U,   /*!< For hardware average with 4 samples. */
+    kADC_HardwareAverageCount8 = 1U,   /*!< For hardware average with 8 samples. */
+    kADC_HardwareAverageCount16 = 2U,  /*!< For hardware average with 16 samples. */
+    kADC_HardwareAverageCount32 = 3U,  /*!< For hardware average with 32 samples. */
+    kADC_HardwareAverageDiasable = 4U, /*!< Disable the hardware average function. */
+} adc_hardware_average_mode_t;
+
+/*!
+ * @brief Converter configuration.
+ */
+typedef struct _adc_config
+{
+    bool enableOverWrite;                                  /*!< Enable the overwriting. */
+    bool enableContinuousConversion;                       /*!< Enable the continuous conversion mode. */
+    bool enableHighSpeed;                                  /*!< Enable the high-speed mode. */
+    bool enableLowPower;                                   /*!< Enable the low power mode. */
+    bool enableLongSample;                                 /*!< Enable the long sample mode. */
+    bool enableAsynchronousClockOutput;                    /*!< Enable the asynchronous clock output. */
+    adc_reference_voltage_source_t referenceVoltageSource; /*!< Select the reference voltage source. */
+    adc_sample_period_mode_t samplePeriodMode; /*!< Select the sample period in long sample mode or short mode. */
+    adc_clock_source_t clockSource; /*!< Select the input clock source to generate the internal clock ADCK. */
+    adc_clock_driver_t clockDriver; /*!< Select the divide ratio used by the ADC to generate the internal clock ADCK. */
+    adc_resolution_t resolution;    /*!< Select the ADC resolution mode. */
+} adc_config_t;
+
+/*!
+ * @brief Converter Offset configuration.
+ */
+typedef struct _adc_offest_config
+{
+    bool enableSigned;    /*!< if false,The offset value is added with the raw result.
+                               if true,The offset value is subtracted from the raw converted value. */
+    uint32_t offsetValue; /*!< User configurable offset value(0-4095). */
+} adc_offest_config_t;
+
+/*!
+ * @brief ADC hardware compare configuration.
+ *
+ * In kADC_HardwareCompareMode0, compare true if the result is less than the value1.
+ * In kADC_HardwareCompareMode1, compare true if the result is greater than or equal to value1.
+ * In kADC_HardwareCompareMode2, Value1 <= Value2, compare true if the result is less than value1 Or the result is
+ * Greater than value2.
+ *                               Value1 >  Value2, compare true if the result is less than value1 And the result is
+ * Greater than value2.
+ * In kADC_HardwareCompareMode3, Value1 <= Value2, compare true if the result is greater than or equal to value1 And the
+ * result is less than or equal to value2.
+ *                               Value1 >  Value2, compare true if the result is greater than or equal to value1 Or the
+ * result is less than or equal to value2.
+ */
+typedef struct _adc_hardware_compare_config
+{
+    adc_hardware_compare_mode_t hardwareCompareMode; /*!< Select the hardware compare mode.
+                                                            See "adc_hardware_compare_mode_t". */
+    uint16_t value1;                                 /*!< Setting value1(0-4095) for hardware compare mode. */
+    uint16_t value2;                                 /*!< Setting value2(0-4095) for hardware compare mode. */
+} adc_hardware_compare_config_t;
+
+/*!
+ * @brief ADC channel conversion configuration.
+ */
+typedef struct _adc_channel_config
+{
+    uint32_t channelNumber;                    /*!< Setting the conversion channel number. The available range is 0-31.
+                                                    See channel connection information for each chip in Reference
+                                                    Manual document. */
+    bool enableInterruptOnConversionCompleted; /*!< Generate an interrupt request once the conversion is completed. */
+} adc_channel_config_t;
+/*******************************************************************************
+* API
+******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @name Initialization
+ * @{
+ */
+
+/*!
+ * @brief Initialize the ADC module.
+ *
+ * @param base ADC peripheral base address.
+ * @param config Pointer to "adc_config_t" structure.
+ */
+void ADC_Init(ADC_Type *base, const adc_config_t *config);
+
+/*!
+ * @brief De-initializes the ADC module.
+ *
+ * @param base ADC peripheral base address.
+ */
+void ADC_Deinit(ADC_Type *base);
+
+/*!
+ * @brief Gets an available pre-defined settings for the converter's configuration.
+ *
+ * This function initializes the converter configuration structure with available settings. The default values are:
+ * @code
+ *  config->enableAsynchronousClockOutput = true;
+ *  config->enableOverWrite =               false;
+ *  config->enableContinuousConversion =    false;
+ *  config->enableHighSpeed =               false;
+ *  config->enableLowPower =                false;
+ *  config->enableLongSample =              false;
+ *  config->referenceVoltageSource =        kADC_ReferenceVoltageSourceAlt0;
+ *  config->samplePeriodMode =              kADC_SamplePeriod2or12Clocks;
+ *  config->clockSource =                   kADC_ClockSourceAD;
+ *  config->clockDriver =                   kADC_ClockDriver1;
+ *  config->resolution =                    kADC_Resolution12Bit;
+ * @endcode
+ * @param base   ADC peripheral base address.
+ * @param config Pointer to the configuration structure.
+ */
+void ADC_GetDefaultConfig(adc_config_t *config);
+
+/*!
+ * @brief Configures the conversion channel.
+ *
+ * This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API
+ * configures the channel while the external trigger source helps to trigger the conversion.
+ *
+ * Note that the "Channel Group" has a detailed description.
+ * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one
+ * group of status and control registers, one for each conversion. The channel group parameter indicates which group of
+ * registers are used, for example channel group 0 is for Group A registers and channel group 1 is for Group B
+ * registers. The
+ * channel groups are used in a "ping-pong" approach to control the ADC operation.  At any point, only one of
+ * the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and
+ * hardware
+ * trigger modes. Channel groups 1 and greater indicate potentially multiple channel group registers for
+ * use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual
+ * about the
+ * number of SC1n registers (channel groups) specific to this device.  None of the channel groups 1 or greater are used
+ * for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion.
+ * Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and
+ * vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a
+ * conversion aborts the current conversion.
+ *
+ * @param base          ADC peripheral base address.
+ * @param channelGroup  Channel group index.
+ * @param config        Pointer to the "adc_channel_config_t" structure for the conversion channel.
+ */
+void ADC_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc_channel_config_t *config);
+
+/*!
+ * @brief  Gets the conversion value.
+ *
+ * @param  base         ADC peripheral base address.
+ * @param  channelGroup Channel group index.
+ *
+ * @return              Conversion value.
+ */
+static inline uint32_t ADC_GetChannelConversionValue(ADC_Type *base, uint32_t channelGroup)
+{
+    assert(channelGroup < ADC_R_COUNT);
+
+    return base->R[channelGroup];
+}
+
+/*!
+ * @brief Gets the status flags of channel.
+ *
+ * A conversion is completed when the result of the conversion is transferred into the data
+ * result registers. (provided the compare function & hardware averaging is disabled), this is
+ * indicated by the setting of COCOn. If hardware averaging is enabled, COCOn sets only,
+ * if the last of the selected number of conversions is complete. If the compare function is
+ * enabled, COCOn sets and conversion result data is transferred only if the compare
+ * condition is true. If both hardware averaging and compare functions are enabled, then
+ * COCOn sets only if the last of the selected number of conversions is complete and the
+ * compare condition is true.
+ *
+ * @param base         ADC peripheral base address.
+ * @param channelGroup Channel group index.
+ *
+ * @return             Status flags of channel.return 0 means COCO flag is 0,return 1 means COCOflag is 1.
+ */
+static inline uint32_t ADC_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup)
+{
+    assert(channelGroup < ADC_HC_COUNT);
+
+    /* If flag is set,return 1,otherwise, return 0. */
+    return (((base->HS) & (1U << channelGroup)) >> channelGroup);
+}
+
+/*!
+ * @brief  Automates the hardware calibration.
+ *
+ * This auto calibration helps to adjust the plus/minus side gain automatically.
+ * Execute the calibration before using the converter. Note that the software trigger should be used
+ * during calibration.
+ *
+ * @param  base ADC peripheral base address.
+ *
+ * @return                 Execution status.
+ * @retval kStatus_Success Calibration is done successfully.
+ * @retval kStatus_Fail    Calibration has failed.
+ */
+status_t ADC_DoAutoCalibration(ADC_Type *base);
+
+/*!
+ * @brief Set user defined offset.
+ *
+ * @param base   ADC peripheral base address.
+ * @param config Pointer to "adc_offest_config_t" structure.
+ */
+void ADC_SetOffsetConfig(ADC_Type *base, const adc_offest_config_t *config);
+
+/*!
+ * @brief Enables generating the DMA trigger when the conversion is complete.
+ *
+ * @param base   ADC peripheral base address.
+ * @param enable Switcher of the DMA feature. "true" means enabled, "false" means not enabled.
+ */
+static inline void ADC_EnableDMA(ADC_Type *base, bool enable)
+{
+    if (enable)
+    {
+        base->GC |= ADC_GC_DMAEN_MASK;
+    }
+    else
+    {
+        base->GC &= ~ADC_GC_DMAEN_MASK;
+    }
+}
+
+/*!
+ * @brief Enables the hardware trigger mode.
+ *
+ * @param base ADC peripheral base address.
+ * @param enable Switcher of the trigger mode. "true" means hardware tirgger mode,"false" means software mode.
+ */
+#if !(defined(FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE) && FSL_FEATURE_ADC_SUPPORT_HARDWARE_TRIGGER_REMOVE)
+static inline void ADC_EnableHardwareTrigger(ADC_Type *base, bool enable)
+{
+    if (enable)
+    {
+        base->CFG |= ADC_CFG_ADTRG_MASK;
+    }
+    else
+    {
+        base->CFG &= ~ADC_CFG_ADTRG_MASK;
+    }
+}
+#endif
+
+/*!
+ * @brief Configures the hardware compare mode.
+ *
+ * The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the
+ * result
+ * in the compare range is available. To compare the range, see "adc_hardware_compare_mode_t" or the appopriate
+ * reference
+ * manual for more information.
+ *
+ * @param base ADC peripheral base address.
+ * @param Pointer to "adc_hardware_compare_config_t" structure.
+ *
+ */
+void ADC_SetHardwareCompareConfig(ADC_Type *base, const adc_hardware_compare_config_t *config);
+
+/*!
+ * @brief Configures the hardware average mode.
+ *
+ * The hardware average mode provides a way to process the conversion result automatically by using hardware. The
+ * multiple
+ * conversion results are accumulated and averaged internally making them easier to read.
+ *
+ * @param base ADC peripheral base address.
+ * @param mode Setting the hardware average mode. See "adc_hardware_average_mode_t".
+ */
+void ADC_SetHardwareAverageConfig(ADC_Type *base, adc_hardware_average_mode_t mode);
+
+/*!
+ * @brief Gets the converter's status flags.
+ *
+ * @param base ADC peripheral base address.
+ *
+ * @return Flags' mask if indicated flags are asserted. See "adc_status_flags_t".
+ */
+static inline uint32_t ADC_GetStatusFlags(ADC_Type *base)
+{
+    return base->GS;
+}
+
+/*!
+ * @brief Clears the converter's status falgs.
+ *
+ * @param base ADC peripheral base address.
+ * @param mask Mask value for the cleared flags. See "adc_status_flags_t".
+ */
+void ADC_ClearStatusFlags(ADC_Type *base, uint32_t mask);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _FSL_ADC_H_ */