rt-thread-official/bsp/hpmicro/libraries/drivers/drv_adc.c

220 lines
4.6 KiB
C

/*
* Copyright (c) 2021 - 2022 hpmicro
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Change Logs:
* Date Author Notes
* 2022-05-08 hpmicro the first version
*/
#include <rtthread.h>
#ifdef BSP_USING_ADC
#include <rtdevice.h>
#include "board.h"
#include "drv_adc.h"
#ifdef BSP_USING_ADC12
#include "hpm_adc12_drv.h"
#endif
#ifdef BSP_USING_ADC16
#include "hpm_adc16_drv.h"
#endif
#include "hpm_sysctl_drv.h"
typedef struct
{
char *adc_name;
struct rt_adc_device hpm_adc_device;
uint16_t channel;
#ifdef BSP_USING_ADC12
ADC12_Type *adc_base;
#endif
#ifdef BSP_USING_ADC16
ADC16_Type *adc_base;
#endif
}hpm_rtt_adc;
static hpm_rtt_adc hpm_adc_config_tbl[] =
{
#ifdef BSP_USING_ADC0
{
.adc_name = "adc0",
#ifdef BSP_USING_ADC12
.adc_base = HPM_ADC0,
#endif
#ifdef BSP_USING_ADC16
.adc_base = HPM_ADC0,
#endif
},
#endif
#ifdef BSP_USING_ADC1
{
.adc_name = "adc1",
#ifdef BSP_USING_ADC12
.adc_base = HPM_ADC1,
#endif
#ifdef BSP_USING_ADC16
.adc_base = HPM_ADC1,
#endif
},
#endif
#ifdef BSP_USING_ADC2
{
.adc_name = "adc2",
#ifdef BSP_USING_ADC12
.adc_base = HPM_ADC2,
#endif
#ifdef BSP_USING_ADC16
.adc_base = HPM_ADC2,
#endif
},
#endif
#ifdef BSP_USING_ADC3
{
.adc_name = "adc3",
#ifdef BSP_USING_ADC12
.adc_base = HPM_ADC3,
#endif
#ifdef BSP_USING_ADC16
.adc_base = HPM_ADC3,
#endif
},
#endif
};
static uint8_t adc_nums = sizeof(hpm_adc_config_tbl) / sizeof(hpm_rtt_adc);
static rt_err_t init_adc_config(hpm_rtt_adc *adc)
{
#ifdef BSP_USING_ADC12
adc12_config_t cfg;
hpm_stat_t ret;
adc12_get_default_config(&cfg);
cfg.res = adc12_res_12_bits;
cfg.conv_mode = adc12_conv_mode_oneshot;
cfg.adc_clk_div = 1;
ret = adc12_init(adc->adc_base, &cfg);
if (ret != status_success) {
return RT_ERROR;
}
#endif
#ifdef BSP_USING_ADC16
adc16_config_t cfg;
hpm_stat_t ret;
adc16_get_default_config(&cfg);
cfg.conv_mode = adc16_conv_mode_oneshot;
cfg.adc_clk_div = 3;
cfg.sel_sync_ahb = true;
ret = adc16_init(adc->adc_base, &cfg);
if (ret != status_success) {
return RT_ERROR;
}
#endif
return RT_EOK;
}
static rt_err_t init_channel_config(hpm_rtt_adc *adc)
{
#ifdef BSP_USING_ADC12
adc12_channel_config_t ch_cfg;;
hpm_stat_t ret;
ch_cfg.ch = adc->channel;
ch_cfg.diff_sel = adc12_sample_signal_single_ended;
ch_cfg.sample_cycle = 20;
ret = adc12_init_channel(adc->adc_base, &ch_cfg);
if (ret != status_success) {
return RT_ERROR;
}
#endif
#ifdef BSP_USING_ADC16
adc16_channel_config_t ch_cfg;;
hpm_stat_t ret;
ch_cfg.ch = adc->channel;
ch_cfg.sample_cycle = 20;
ret = adc16_init_channel(adc->adc_base, &ch_cfg);
if (ret != status_success) {
return RT_ERROR;
}
#endif
return RT_EOK;
}
static rt_err_t hpm_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
{
hpm_rtt_adc *hpm_adc_handler;
rt_err_t ret;
RT_ASSERT(device != RT_NULL);
hpm_adc_handler = (hpm_rtt_adc *)device->parent.user_data;
ret = init_adc_config(hpm_adc_handler);
if (ret != RT_EOK) {
return RT_ERROR;
}
hpm_adc_handler->channel = channel;
ret = init_channel_config(hpm_adc_handler);
if (ret != RT_EOK) {
return RT_ERROR;
}
return RT_EOK;
}
static rt_err_t hpm_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
hpm_rtt_adc hpm_adc_handler;
rt_err_t ret;
rt_uint16_t val;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(value != RT_NULL);
hpm_adc_handler = *(hpm_rtt_adc *)device->parent.user_data;
hpm_adc_handler.channel = channel;
#ifdef BSP_USING_ADC12
adc12_get_oneshot_result(hpm_adc_handler.adc_base, hpm_adc_handler.channel, &val);
*value = (val >> 4);
#endif
#ifdef BSP_USING_ADC16
adc16_get_oneshot_result(hpm_adc_handler.adc_base, hpm_adc_handler.channel, &val);
*value = val;
#endif
return RT_EOK;
}
static const struct rt_adc_ops hpm_adc_ops =
{
.enabled = hpm_adc_enabled,
.convert = hpm_get_adc_value,
};
int rt_hw_adc_init(void)
{
rt_err_t ret = RT_EOK;
for (uint32_t i = 0; i < adc_nums; i++) {
ret = rt_hw_adc_register(&hpm_adc_config_tbl[i].hpm_adc_device, hpm_adc_config_tbl[i].adc_name, &hpm_adc_ops, &hpm_adc_config_tbl[i]);
if (ret != RT_EOK) {
ret = RT_ERROR;
break;
}
}
return ret;
}
INIT_BOARD_EXPORT(rt_hw_adc_init);
#endif