diff --git a/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_adc.c b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_adc.c new file mode 100644 index 0000000000..94c56fb672 --- /dev/null +++ b/bsp/nxp/mcx/mcxa/Libraries/drivers/drv_adc.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-16 shelton first version + * 2024-07-21 liujianhua added mcxa153 + * + */ +#include +#include +#include "fsl_lpadc.h" +#include "fsl_spc.h" + +#ifdef RT_USING_ADC + +#define DEFAULT_HW_AVG (kLPADC_HardwareAverageCount4) +#define DEFAULT_SAMPLE_TIME (kLPADC_SampleTimeADCK7) + +/* by default: cmd = chl+1 */ +static uint8_t adc_chl2cmd[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; +static uint8_t adc_cmd2trig[] = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}; + +struct mcx_adc +{ + struct rt_adc_device mcx_adc_device; + ADC_Type *adc_base; + clock_attach_id_t clock_attach_id; + clock_div_name_t clock_div_name; + uint8_t clock_div; + uint8_t referenceVoltageSource; /* 00, VREFH reference pin, 01, ANA_7(VREFI/VREFO) pin, 10, VDDA supply pin */ + uint8_t resolution; + char *name; +}; + +static struct mcx_adc mcx_adc_obj[] = +{ +#ifdef BSP_USING_ADC0 + { + .adc_base = ADC0, + .clock_attach_id = kFRO12M_to_ADC0, + .clock_div_name = kCLOCK_DivADC0, + .clock_div = 2, + .referenceVoltageSource = 0, + .name = "adc0", + }, +#endif +}; + +static rt_err_t a153_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled) +{ + struct mcx_adc *adc = (struct mcx_adc *)device->parent.user_data; + + if (enabled) + { + lpadc_config_t adc_config; + LPADC_GetDefaultConfig(&adc_config); + adc_config.enableAnalogPreliminary = true; + adc_config.referenceVoltageSource = adc->referenceVoltageSource; + adc_config.conversionAverageMode = kLPADC_ConversionAverage128; /* this is for calibartion avg mode */ + adc_config.powerLevelMode = kLPADC_PowerLevelAlt4; + adc_config.enableConvPause = false; + adc_config.convPauseDelay = 0; + + LPADC_Init(adc->adc_base, &adc_config); + LPADC_DoOffsetCalibration(adc->adc_base); + LPADC_DoAutoCalibration(adc->adc_base); + + lpadc_conv_command_config_t cmd_cfg; + LPADC_GetDefaultConvCommandConfig(&cmd_cfg); + + cmd_cfg.channelNumber = channel; + cmd_cfg.conversionResolutionMode = kLPADC_ConversionResolutionHigh; + cmd_cfg.hardwareAverageMode = DEFAULT_HW_AVG; + cmd_cfg.loopCount = 0; + cmd_cfg.sampleTimeMode = DEFAULT_SAMPLE_TIME; + cmd_cfg.sampleChannelMode = kLPADC_SampleChannelSingleEndSideA; + LPADC_SetConvCommandConfig(adc->adc_base, adc_chl2cmd[channel], &cmd_cfg); + + lpadc_conversion_resolution_mode_t resolution_mode = cmd_cfg.conversionResolutionMode; + if (resolution_mode == kLPADC_ConversionResolutionHigh) + adc->resolution = 16; + else + adc->resolution = 0; + + lpadc_conv_trigger_config_t trig_config; + LPADC_GetDefaultConvTriggerConfig(&trig_config); + trig_config.targetCommandId = adc_chl2cmd[channel]; + trig_config.enableHardwareTrigger = false; + LPADC_SetConvTriggerConfig(adc->adc_base, adc_cmd2trig[trig_config.targetCommandId], &trig_config); /* Configurate the trigger0. */ + } + else + { + LPADC_Deinit(adc->adc_base); + } + return RT_EOK; +} + +static rt_int16_t a153_get_vref(struct rt_adc_device *device) +{ + if (device == RT_NULL) + return -RT_ERROR; + + return 3300; +} + +static rt_err_t a153_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value) +{ + struct mcx_adc *adc = (struct mcx_adc *)device->parent.user_data; + + lpadc_conv_result_t mLpadcResultConfigStruct; + + LPADC_DoSoftwareTrigger(adc->adc_base, 1 << (adc_cmd2trig[adc_chl2cmd[channel]])); /* 1U is trigger0 mask. */ + while (!LPADC_GetConvResult(adc->adc_base, &mLpadcResultConfigStruct)); + *value = mLpadcResultConfigStruct.convValue; + return RT_EOK; +} + +static rt_uint8_t a153_adc_get_resolution(struct rt_adc_device *device) +{ + RT_ASSERT(device != RT_NULL); + struct mcx_adc *adc = (struct mcx_adc *)device->parent.user_data; + return adc->resolution; +} + +static const struct rt_adc_ops mcx_adc_ops = +{ + .get_resolution = a153_adc_get_resolution, + .enabled = a153_adc_enabled, + .convert = a153_get_adc_value, + .get_vref = a153_get_vref, +}; + +static int rt_hw_adc_init(void) +{ + int result = RT_EOK; + int i = 0; + + /* Enable VREF */ + SPC0->ACTIVE_CFG1 |= 0xFFFFFFFF; + SPC_SetActiveModeBandgapModeConfig(SPC0, kSPC_BandgapEnabledBufferEnabled); + + for (i = 0; i < sizeof(mcx_adc_obj) / sizeof(mcx_adc_obj[0]); i++) + { + CLOCK_SetClockDiv(mcx_adc_obj[i].clock_div_name, mcx_adc_obj[i].clock_div); + CLOCK_AttachClk(mcx_adc_obj[i].clock_attach_id); + + rt_hw_adc_register(&mcx_adc_obj[i].mcx_adc_device, mcx_adc_obj[i].name, &mcx_adc_ops, &mcx_adc_obj[i]); + } + + return result; +} +INIT_BOARD_EXPORT(rt_hw_adc_init); +#endif /* BSP_USING_ADC */ diff --git a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig index 802cfd2746..25b0fbb767 100644 --- a/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig +++ b/bsp/nxp/mcx/mcxa/frdm-mcxa153/board/Kconfig @@ -69,25 +69,9 @@ menu "On-chip Peripheral Drivers" default y if BSP_USING_ADC - config BSP_USING_ADC0_CH0 - bool "Enable ADC0 Channel0" + config BSP_USING_ADC0 + bool "Enable ADC0" default y - - config BSP_USING_ADC0_CH1 - bool "Enable ADC0 Channel1" - default n - - config BSP_USING_ADC0_CH8 - bool "Enable ADC0 Channel8" - default n - - config BSP_USING_ADC0_CH13 - bool "Enable ADC0 Channel13" - default n - - config BSP_USING_ADC0_CH26 - bool "Enable ADC0 Channel26" - default n endif config BSP_USING_FLASH