diff --git a/bsp/cvitek/README.md b/bsp/cvitek/README.md index 143d848246..d9c7ae1077 100755 --- a/bsp/cvitek/README.md +++ b/bsp/cvitek/README.md @@ -32,9 +32,10 @@ | 驱动 | 支持情况 | 备注 | | :--- | :------- | :---------------- | -| UART | 支持 | 默认波特率115200 | +| uart | 支持 | 默认波特率115200 | | gpio | 支持 | | - +| i2c | 支持 | | +| adc | 支持 | | ## 支持开发板 - milk-v duo: [https://milkv.io/duo](https://milkv.io/duo) diff --git a/bsp/cvitek/c906_little/board/Kconfig b/bsp/cvitek/c906_little/board/Kconfig index feecf2d72a..3e0bc027c8 100755 --- a/bsp/cvitek/c906_little/board/Kconfig +++ b/bsp/cvitek/c906_little/board/Kconfig @@ -39,4 +39,10 @@ menu "General Drivers Configuration" int default 32 endif + + menuconfig BSP_USING_ADC + bool "Using ADC" + select RT_USING_ADC + default n + endmenu diff --git a/bsp/cvitek/cv1800b/board/Kconfig b/bsp/cvitek/cv1800b/board/Kconfig index d2d557ef5d..a5305cbd24 100755 --- a/bsp/cvitek/cv1800b/board/Kconfig +++ b/bsp/cvitek/cv1800b/board/Kconfig @@ -31,5 +31,10 @@ menu "General Drivers Configuration" default n endif + + menuconfig BSP_USING_ADC + bool "Using ADC" + select RT_USING_ADC + default n endmenu diff --git a/bsp/cvitek/drivers/SConscript b/bsp/cvitek/drivers/SConscript index 27c24ff764..0fa4fa9c54 100755 --- a/bsp/cvitek/drivers/SConscript +++ b/bsp/cvitek/drivers/SConscript @@ -15,6 +15,9 @@ if GetDepend('BSP_USING_CV1800B'): if GetDepend('BSP_USING_I2C'): src += ['drv_hw_i2c.c'] +if GetDepend('BSP_USING_ADC'): + src += ['drv_adc.c'] + CPPDEFINES += ['-DCONFIG_64BIT'] group = DefineGroup('drivers', src, depend = [''], CPPDEFINES = CPPDEFINES, CPPPATH = CPPPATH) diff --git a/bsp/cvitek/drivers/drv_adc.c b/bsp/cvitek/drivers/drv_adc.c new file mode 100644 index 0000000000..17bb3f8994 --- /dev/null +++ b/bsp/cvitek/drivers/drv_adc.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024/02/22 flyingcys first version + */ +#include +#include +#include "drv_adc.h" + +#ifdef BSP_USING_ADC + +#define DBG_LEVEL DBG_LOG +#include +#define LOG_TAG "DRV.ADC" + +struct cvi_adc_dev +{ + struct rt_adc_device device; + const char *name; + rt_ubase_t base; +}; + +static struct cvi_adc_dev adc_dev_config[] = +{ + { + .name = "adc1", + .base = SARADC_BASE + }, +}; + +static rt_err_t _adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled) +{ + struct cvi_adc_dev *adc_dev = (struct cvi_adc_dev *)device->parent.user_data; + uint32_t value; + + RT_ASSERT(adc_dev != RT_NULL); + + if (channel > SARADC_CH_MAX) + return -RT_EINVAL; + + if (enabled) + { + //set channel + cvi_set_saradc_ctrl(adc_dev->base, (rt_uint32_t)channel << (SARADC_CTRL_SEL_POS + 1)); + + //set saradc clock cycle + cvi_set_cyc(adc_dev->base); + + //start + cvi_set_saradc_ctrl(adc_dev->base, SARADC_CTRL_START); + LOG_D("enable saradc..."); + } + else + { + cvi_reset_saradc_ctrl(adc_dev->base, (rt_uint32_t)channel << (SARADC_CTRL_SEL_POS + 1)); + LOG_D("disable saradc..."); + } + return RT_EOK; +} + +static rt_err_t _adc_convert(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value) +{ + struct cvi_adc_dev *adc_dev = (struct cvi_adc_dev *)device->parent.user_data; + rt_uint32_t result; + rt_uint32_t cnt = 0; + + RT_ASSERT(adc_dev != RT_NULL); + + if (channel > SARADC_CH_MAX) + return -RT_EINVAL; + + while (cvi_get_saradc_status(adc_dev->base) & SARADC_STATUS_BUSY) + { + rt_thread_delay(10); + LOG_D("wait saradc ready"); + cnt ++; + if (cnt > 100) + return -RT_ETIMEOUT; + } + + result = mmio_read_32(adc_dev->base + SARADC_RESULT(channel - 1)); + if (result & SARADC_RESULT_VALID) + { + *value = result & SARADC_RESULT_MASK; + LOG_D("saradc channel %d value: %04x", channel, *value); + } + else + { + LOG_E("saradc channel %d read failed. result:0x%04x", channel, result); + return -RT_ERROR; + } + return RT_EOK; +} + +static const struct rt_adc_ops _adc_ops = +{ + .enabled = _adc_enabled, + .convert = _adc_convert, +}; + +int rt_hw_adc_init(void) +{ + rt_uint8_t i; + for (i = 0; i < sizeof(adc_dev_config) / sizeof(adc_dev_config[0]); i ++) + { + if (rt_hw_adc_register(&adc_dev_config[i].device, adc_dev_config[i].name, &_adc_ops, &adc_dev_config[i]) != RT_EOK) + { + LOG_E("%s register failed!", adc_dev_config[i].name); + return -RT_ERROR; + } + } + + return RT_EOK; +} +INIT_BOARD_EXPORT(rt_hw_adc_init); + +#endif /* BSP_USING_ADC */ diff --git a/bsp/cvitek/drivers/drv_adc.h b/bsp/cvitek/drivers/drv_adc.h new file mode 100644 index 0000000000..7539ab5604 --- /dev/null +++ b/bsp/cvitek/drivers/drv_adc.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024/02/22 flyingcys first version + */ +#ifndef __DRV_ADC_H__ +#define __DRV_ADC_H__ + +#include "pinctrl.h" +#include "mmio.h" + +#define SARADC_BASE 0x030F0000 +#define SARADC_CH_MAX 3 + +#define SARADC_CTRL_OFFSET 0x04 +#define SARADC_CTRL_START (1 << 0) +#define SARADC_CTRL_SEL_POS 0x04 + +#define SARADC_STATUS_OFFSET 0x08 +#define SARADC_STATUS_BUSY (1 << 0) + +#define SARADC_CYC_SET_OFFSET 0x0C +#define SARADC_CYC_CLKDIV_DIV_POS (12U) +#define SARADC_CYC_CLKDIV_DIV_MASK (0xF << SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_1 (0U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_2 (1U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_3 (2U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_4 (3U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_5 (4U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_6 (5U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_7 (6U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_8 (7U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_9 (8U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_10 (9U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_11 (10U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_12 (11U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_13 (12U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_14 (13U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_15 (14U<< SARADC_CYC_CLKDIV_DIV_POS) +#define SARADC_CYC_CLKDIV_DIV_16 (15U<< SARADC_CYC_CLKDIV_DIV_POS) + +#define SARADC_RESULT_OFFSET 0x014 +#define SARADC_RESULT(n) (SARADC_RESULT_OFFSET + (n) * 4) +#define SARADC_RESULT_MASK 0x0FFF +#define SARADC_RESULT_VALID (1 << 15) + +rt_inline void cvi_set_saradc_ctrl(unsigned long reg_base, rt_uint32_t value) +{ + value |= mmio_read_32(reg_base + SARADC_CTRL_OFFSET); + mmio_write_32(reg_base + SARADC_CTRL_OFFSET, value); +} + +rt_inline void cvi_reset_saradc_ctrl(unsigned long reg_base, rt_uint32_t value) +{ + value = mmio_read_32(reg_base + SARADC_CTRL_OFFSET) & ~value; + mmio_write_32(reg_base + SARADC_CTRL_OFFSET, value); +} + +rt_inline rt_uint32_t cvi_get_saradc_status(unsigned long reg_base) +{ + return((rt_uint32_t)mmio_read_32(reg_base + SARADC_STATUS_OFFSET)); +} + +rt_inline void cvi_set_cyc(unsigned long reg_base) +{ + rt_uint32_t value; + + value = mmio_read_32(reg_base + SARADC_CYC_SET_OFFSET); + + value &= ~SARADC_CYC_CLKDIV_DIV_16; + mmio_write_32(reg_base + SARADC_CYC_SET_OFFSET, value); + + value |= SARADC_CYC_CLKDIV_DIV_16; //set saradc clock cycle=840ns + mmio_write_32(reg_base + SARADC_CYC_SET_OFFSET, value); +} + +int rt_hw_adc_init(void); + +#endif /* __DRV_ADC_H__ */