123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-03-04 stevetong459 first version
- * 2022-07-15 Aligagago add APM32F4 series MCU support
- * 2022-12-26 luobeihai add APM32F0 series MCU support
- * 2023-03-27 luobeihai add APM32E1/S1 series MCU support
- */
- #include <board.h>
- #if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3)
- #define DBG_TAG "drv.adc"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #define DRV_ADC_CHANNEL_MAX_NUM 16
- #define DRV_ADC_TIME_OUT 0xFFF
- #define APM32_ADC_GET_PORT(pin_num) ((GPIO_T *)(GPIOA_BASE + (0x400u * (((pin_num) >> 4) & 0xFu))))
- #define APM32_ADC_GET_PIN(pin_num) ((uint16_t)(1u << ((pin_num) & 0xFu)))
- struct apm32_adc
- {
- const char *name;
- ADC_T *adc;
- ADC_Config_T adc_config;
- rt_base_t channel_pin[DRV_ADC_CHANNEL_MAX_NUM];
- struct rt_adc_device adc_dev;
- };
- #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1)
- static struct apm32_adc adc_config[] =
- {
- #ifdef BSP_USING_ADC1
- {
- "adc1",
- ADC1,
- {
- ADC_MODE_INDEPENDENT,
- DISABLE,
- DISABLE,
- ADC_EXT_TRIG_CONV_None,
- ADC_DATA_ALIGN_RIGHT,
- 1
- },
- {
- GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
- GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
- GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
- GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
- },
- },
- #endif
- #ifdef BSP_USING_ADC2
- {
- "adc2",
- ADC2,
- {
- ADC_MODE_INDEPENDENT,
- DISABLE,
- DISABLE,
- ADC_EXT_TRIG_CONV_None,
- ADC_DATA_ALIGN_RIGHT,
- 1
- },
- {
- GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
- GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
- GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
- GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
- },
- },
- #endif
- #ifdef BSP_USING_ADC3
- {
- "adc3",
- ADC3,
- {
- ADC_MODE_INDEPENDENT,
- DISABLE,
- DISABLE,
- ADC_EXT_TRIG_CONV_None,
- ADC_DATA_ALIGN_RIGHT,
- 1
- },
- {
- GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
- GET_PIN(F, 6), GET_PIN(F, 7), GET_PIN(F, 8), GET_PIN(F, 9),
- GET_PIN(F, 10)
- },
- },
- #endif
- };
- #elif defined(SOC_SERIES_APM32F4)
- static struct apm32_adc adc_config[] =
- {
- #ifdef BSP_USING_ADC1
- {
- "adc1",
- ADC1,
- {
- ADC_RESOLUTION_12BIT,
- DISABLE,
- DISABLE,
- ADC_EXT_TRIG_EDGE_NONE,
- ADC_EXT_TRIG_CONV_TMR1_CC1,
- ADC_DATA_ALIGN_RIGHT,
- 1
- },
- {
- GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
- GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
- GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
- GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
- },
- },
- #endif
- #ifdef BSP_USING_ADC2
- {
- "adc2",
- ADC2,
- {
- ADC_RESOLUTION_12BIT,
- DISABLE,
- DISABLE,
- ADC_EXT_TRIG_EDGE_NONE,
- ADC_EXT_TRIG_CONV_TMR1_CC1,
- ADC_DATA_ALIGN_RIGHT,
- 1
- },
- {
- GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
- GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
- GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
- GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
- },
- },
- #endif
- #ifdef BSP_USING_ADC3
- {
- "adc3",
- ADC3,
- {
- ADC_RESOLUTION_12BIT,
- DISABLE,
- DISABLE,
- ADC_EXT_TRIG_EDGE_NONE,
- ADC_EXT_TRIG_CONV_TMR1_CC1,
- ADC_DATA_ALIGN_RIGHT,
- 1
- },
- {
- GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
- GET_PIN(F, 6), GET_PIN(F, 7), GET_PIN(F, 8), GET_PIN(F, 9),
- GET_PIN(F, 10), GET_PIN(F, 3), GET_PIN(C, 0), GET_PIN(C, 1),
- GET_PIN(C, 2), GET_PIN(C, 3)
- },
- },
- #endif
- };
- #elif defined(SOC_SERIES_APM32F0)
- static struct apm32_adc adc_config[] =
- {
- #ifdef BSP_USING_ADC1
- {
- "adc1",
- ADC,
- {
- ADC_RESOLUTION_12B,
- ADC_DATA_ALIGN_RIGHT,
- ADC_SCAN_DIR_UPWARD,
- ADC_CONVERSION_SINGLE,
- ADC_EXT_TRIG_CONV_TRG0,
- ADC_EXT_TRIG_EDGE_NONE
- },
- {
- GET_PIN(A, 0), GET_PIN(A, 1), GET_PIN(A, 2), GET_PIN(A, 3),
- GET_PIN(A, 4), GET_PIN(A, 5), GET_PIN(A, 6), GET_PIN(A, 7),
- GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1),
- GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5)
- },
- },
- #endif
- };
- #endif
- static rt_err_t apm32_adc_channel_check(struct rt_adc_device *device, rt_uint32_t channel)
- {
- struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
- if ((adc_cfg->adc == ADC1) || (adc_cfg->adc == ADC2))
- {
- if (channel <= 15)
- {
- return RT_EOK;
- }
- }
- #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1)
- if (adc_cfg->adc == ADC3)
- {
- if (channel <= 8)
- {
- return RT_EOK;
- }
- }
- #endif
- #if defined(SOC_SERIES_APM32F4)
- if (adc_cfg->adc == ADC3)
- {
- if (channel <= 13)
- {
- return RT_EOK;
- }
- }
- #endif
- LOG_E("channel %d of %s is not supported.", channel, adc_cfg->name);
- return -RT_ERROR;
- }
- static rt_err_t apm32_adc_gpio_init(struct rt_adc_device *device, rt_uint32_t channel)
- {
- struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
- GPIO_Config_T hw_gpio_config;
- if (apm32_adc_channel_check(device, channel) != RT_EOK)
- {
- return -RT_ERROR;
- }
- #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1)
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu));
- hw_gpio_config.mode = GPIO_MODE_ANALOG;
- #elif defined(SOC_SERIES_APM32F4)
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu));
- hw_gpio_config.mode = GPIO_MODE_AN;
- #elif defined(SOC_SERIES_APM32F0)
- RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA << ((adc_cfg->channel_pin[channel] >> 4) & 0xFu));
- hw_gpio_config.mode = GPIO_MODE_AN;
- #endif
- hw_gpio_config.pin = APM32_ADC_GET_PIN(adc_cfg->channel_pin[channel]);
- GPIO_Config(APM32_ADC_GET_PORT(adc_cfg->channel_pin[channel]), &hw_gpio_config);
- return RT_EOK;
- }
- /**
- * @brief This function will control the adc to enable or disable.
- *
- * @param device is a pointer to adc device.
- *
- * @param channel is the adc channel.
- *
- * @param enabled is the status to indicate enable or disable.
- *
- * @return RT_EOK indicates successful enable or disable adc, other value indicates failed.
- */
- static rt_err_t apm32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
- {
- struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
- RT_ASSERT(device != RT_NULL);
- #if defined(SOC_SERIES_APM32F0)
- if (enabled)
- {
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
- if (apm32_adc_gpio_init(device, channel) != RT_EOK)
- {
- return -RT_ERROR;
- }
- ADC_Config(&adc_cfg->adc_config);
- ADC_Enable();
- }
- else
- {
- ADC_Disable();
- }
- #elif defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1) \
- || defined(SOC_SERIES_APM32F4)
- if (enabled)
- {
- if (adc_cfg->adc == ADC1)
- {
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
- }
- else if (adc_cfg->adc == ADC2)
- {
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC2);
- }
- #ifdef BSP_USING_ADC3
- else if (adc_cfg->adc == ADC3)
- {
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC3);
- }
- #endif /* BSP_USING_ADC3 */
- if (apm32_adc_gpio_init(device, channel) != RT_EOK)
- {
- return -RT_ERROR;
- }
- ADC_Config(adc_cfg->adc, &adc_cfg->adc_config);
- ADC_Enable(adc_cfg->adc);
- }
- else
- {
- ADC_Disable(adc_cfg->adc);
- }
- #endif /* SOC_SERIES_APM32F0 */
- return RT_EOK;
- }
- /**
- * @brief This function will get the adc conversion value.
- *
- * @param device is a pointer to adc device.
- *
- * @param channel is the adc channel.
- *
- * @param value is a pointer to the adc conversion value.
- *
- * @return RT_EOK indicates successful get adc value, other value indicates failed.
- */
- static rt_err_t apm32_adc_get_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
- {
- #if !defined(SOC_SERIES_APM32F0)
- struct apm32_adc *adc_cfg = ((struct apm32_adc *)device->parent.user_data);
- #endif
- volatile rt_uint32_t counter = 0;
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(value != RT_NULL);
- if (apm32_adc_channel_check(device, channel) != RT_EOK)
- {
- return -RT_ERROR;
- }
- #if defined(SOC_SERIES_APM32F1) || defined(SOC_SERIES_APM32E1) || defined(SOC_SERIES_APM32S1)
- ADC_ConfigRegularChannel(adc_cfg->adc, channel, 1, ADC_SAMPLETIME_13CYCLES5);
- ADC_StartCalibration(adc_cfg->adc);
- /* Check the end of ADC calibration */
- while (ADC_ReadCalibrationStartFlag(adc_cfg->adc))
- {
- if (++counter > DRV_ADC_TIME_OUT)
- {
- return -RT_ETIMEOUT;
- }
- }
- ADC_EnableSoftwareStartConv(adc_cfg->adc);
- while (!ADC_ReadStatusFlag(adc_cfg->adc, ADC_FLAG_EOC))
- {
- if (++counter > DRV_ADC_TIME_OUT)
- {
- return -RT_ETIMEOUT;
- }
- }
- *value = ADC_ReadConversionValue(adc_cfg->adc);
- #elif defined(SOC_SERIES_APM32F4)
- ADC_ConfigRegularChannel(adc_cfg->adc, channel, 1, ADC_SAMPLETIME_15CYCLES);
- ADC_SoftwareStartConv(adc_cfg->adc);
- while (!ADC_ReadStatusFlag(adc_cfg->adc, ADC_FLAG_EOC))
- {
- if (++counter > DRV_ADC_TIME_OUT)
- {
- return -RT_ETIMEOUT;
- }
- }
- *value = ADC_ReadConversionValue(adc_cfg->adc);
- #elif defined(SOC_SERIES_APM32F0)
- ADC_ConfigChannel((uint16_t)(1u << ((channel) & 0xFu)), ADC_SAMPLE_TIME_239_5);
- ADC_StartConversion();
- while (!ADC_ReadStatusFlag(ADC_FLAG_CC))
- {
- if (++counter > DRV_ADC_TIME_OUT)
- {
- return -RT_ETIMEOUT;
- }
- }
- *value = ADC_ReadConversionValue();
- #endif
- return RT_EOK;
- }
- static const struct rt_adc_ops apm32_adc_ops =
- {
- .enabled = apm32_adc_enabled,
- .convert = apm32_adc_get_value,
- };
- /**
- * @brief ADC initialization function.
- *
- * @return RT_EOK indicates successful initialization, other value indicates failed;
- */
- static int rt_hw_adc_init(void)
- {
- rt_err_t result = RT_EOK;
- rt_size_t obj_num = sizeof(adc_config) / sizeof(struct apm32_adc);
- rt_uint32_t i = 0;
- for (i = 0; i < obj_num; i++)
- {
- /* register ADC device */
- if (rt_hw_adc_register(&adc_config[i].adc_dev, adc_config[i].name, &apm32_adc_ops, &adc_config[i]) == RT_EOK)
- {
- LOG_D("%s init success", adc_config[i].name);
- }
- else
- {
- LOG_D("%s init failed", adc_config[i].name);
- result = -RT_ERROR;
- }
- }
- return result;
- }
- INIT_BOARD_EXPORT(rt_hw_adc_init);
- #endif /* BSP_USING_ADCX */
|