828eco基于GD32H7mcu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
5.8 KiB

5 months ago
/*
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2025-10-11 kurisaw first version
*/
#include "drv_dac.h"
#include "dac_config.h"
#ifdef RT_USING_DAC
#define DBG_TAG "drv.dac"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
static struct gd32_dac gd32_dac_obj[] = {
#ifdef BSP_USING_DAC0
DAC0_CONFIG,
#endif
#ifdef BSP_USING_DAC1
DAC1_CONFIG,
#endif
};
/* DAC initialization status */
typedef struct
{
uint32_t dac_periph;
rt_bool_t initialized;
} DAC_INIT_STATUS;
static DAC_INIT_STATUS dac_init_status[] = {
#if defined(DAC0)
{ DAC0, RT_FALSE },
#elif defined(DAC1)
{ DAC1, RT_FALSE },
#endif
};
/* Private functions */
static void gd32_dac_hw_init(struct gd32_dac *gd32_dac)
{
rt_uint32_t dac_port, dac_pin;
rcu_periph_enum dac_periph;
/* Get pin configuration */
if (get_pin_config(gd32_dac->pin_name, &dac_port, &dac_pin, &dac_periph) == -RT_ERROR)
{
LOG_E("Failed to get pin config for %s", gd32_dac->pin_name);
return;
}
/* Enable clocks */
rcu_periph_clock_enable(RCU_DAC);
rcu_periph_clock_enable(dac_periph);
/* Configure GPIO as analog mode for DAC output */
gpio_mode_set(dac_port, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, dac_pin);
LOG_D("DAC GPIO %s configured", gd32_dac->pin_name);
}
static void dac_initialize(uint32_t dac_periph)
{
/* Check if DAC is already initialized */
for (int i = 0; i < sizeof(dac_init_status) / sizeof(dac_init_status[0]); i++)
{
if (dac_init_status[i].dac_periph == dac_periph && !dac_init_status[i].initialized)
{
/* Initialize DAC */
dac_deinit(dac_periph);
/* DAC trigger disable for both channels */
dac_trigger_disable(dac_periph, gd32_dac_obj[i].channel);
/* DAC wave mode disable for both channels */
dac_wave_mode_config(dac_periph, gd32_dac_obj[i].channel, DAC_WAVE_DISABLE);
#if defined(SOC_SERIES_GD32F10x) || defined(SOC_SERIES_GD32F20x) || defined(SOC_SERIES_GD32F30x) || defined(SOC_SERIES_GD32F4xx) || defined(SOC_SERIES_GD32F5xx) || defined(SOC_SERIES_GD32E50x)
/* DAC output buffer enable */
dac_output_buffer_enable(dac_periph, gd32_dac_obj[i].channel);
#endif
#if defined(SOC_SERIES_GD32H7xx) || defined(SOC_SERIES_GD32H75E)
/* DAC mode configuration - normal mode with buffer enabled */
dac_mode_config(dac_periph, gd32_dac_obj[i].channel, NORMAL_PIN_BUFFON);
#endif
dac_init_status[i].initialized = RT_TRUE;
break;
}
}
}
static rt_err_t drv_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel)
{
struct gd32_dac *dac_dev = (struct gd32_dac *)device;
/* Validate channel */
if (channel != DAC_OUT0 && channel != DAC_OUT1)
{
LOG_E("Invalid DAC channel: %d", channel);
return -RT_EINVAL;
}
/* Enable DAC channel */
dac_enable(dac_dev->dac_periph, (uint8_t)channel);
LOG_D("DAC %s channel %d enabled", dac_dev->name, channel);
return RT_EOK;
}
static rt_err_t drv_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel)
{
struct gd32_dac *dac_dev = (struct gd32_dac *)device;
/* Validate channel */
if (channel != DAC_OUT0 && channel != DAC_OUT1)
{
LOG_E("Invalid DAC channel: %d", channel);
return -RT_EINVAL;
}
/* Disable DAC channel */
dac_disable(dac_dev->dac_periph, (uint8_t)channel);
LOG_D("DAC %s channel %d disabled", dac_dev->name, channel);
return RT_EOK;
}
static rt_err_t drv_dac_convert(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
struct gd32_dac *dac_dev = (struct gd32_dac *)device;
if (value == RT_NULL)
{
LOG_E("DAC value pointer is NULL");
return -RT_EINVAL;
}
/* Validate channel */
if (channel != DAC_OUT0 && channel != DAC_OUT1)
{
LOG_E("Invalid DAC channel: %d", channel);
return -RT_EINVAL;
}
/* Check value range for 12-bit DAC */
if (*value > 4095)
{
LOG_E("DAC value %u exceeds maximum 4095", *value);
return -RT_EINVAL;
}
/* Set DAC data with 12-bit right aligned */
dac_data_set(dac_dev->dac_periph, (uint8_t)channel, DAC_ALIGN_12B_R, (uint16_t)(*value));
LOG_D("DAC %s channel %d set to value %u", dac_dev->name, channel, *value);
return RT_EOK;
}
static rt_err_t drv_dac_set_mode(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t mode)
{
struct gd32_dac *dac_dev = (struct gd32_dac *)device;
if (channel != DAC_OUT0 && channel != DAC_OUT1)
{
return -RT_EINVAL;
}
dac_mode_config(dac_dev->dac_periph, channel, mode);
return RT_EOK;
}
static struct rt_dac_ops drv_ops = {
.disabled = drv_dac_disabled,
.enabled = drv_dac_enabled,
.convert = drv_dac_convert,
};
static int drv_dac_init(void)
{
int i, result = RT_EOK;
for (i = 0; i < sizeof(gd32_dac_obj) / sizeof(gd32_dac_obj[0]); i++)
{
/* Initialize DAC hardware - GPIO configuration */
gd32_dac_hw_init(&gd32_dac_obj[i]);
/* Initialize DAC peripheral if not already initialized */
dac_initialize(gd32_dac_obj[i].dac_periph);
/* Register DAC device */
if (rt_hw_dac_register(&gd32_dac_obj[i].dac_device, gd32_dac_obj[i].name,
&drv_ops, RT_NULL) == RT_EOK)
{
LOG_D("%s register success (channel %d)",
gd32_dac_obj[i].name, gd32_dac_obj[i].channel);
}
else
{
LOG_E("%s register failed", gd32_dac_obj[i].name);
result = -RT_ERROR;
}
}
return result;
}
INIT_DEVICE_EXPORT(drv_dac_init);
#endif /* RT_USING_DAC */