这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 软件与操作系统 » 瑞萨已适配的DAC框架分析

共3条 1/1 1 跳转至

瑞萨已适配的DAC框架分析

助工
2024-09-07 15:42:02     打赏

驱动层适应框架层的通用模板

   分析完rtthread的通用框架,我们基本上可以得到以下dac驱动实现模板。

struct dac_param
{
    // 驱动内部维护参数
};

struct rt_dac_ops dac_ops =
{
    .disabled = dac禁用接口实现,
    .enabled  = dac使能接口实现,
    .convert  = dac写电压值对应的寄存器值函数,
    .get_resolution = 返回dac精度函数,
};

static int dac_init(void)
{
    struct dac_param *param;
    struct rt_dac_dev *dev;

    const char *device_name = "xxxx";
    
    dev = (struct rt_dac_dev *)rt_malloc(sizeof(struct rt_dac_dev));
    param = (struct dac_param *)rt_malloc(sizeof(struct dac_param));

    // DAC 硬件资源初始化
    
    // 系统注册DAC驱动
    if (RT_EOK != rt_hw_dac_register(dev, device_name, &dac_ops, (void *)param))
    {
        LOG_E("%s register failed", device_name);
        return -RT_ERROR;
    }

    return RT_EOK;
}
INIT_DEVICE_EXPORT(dac_init);

瑞萨适配框架层的实现

驱动注册接口

struct ra_dac_map ra_dac[] =
{
#ifdef BSP_USING_DAC0
    {'0', &g_dac0_cfg, &g_dac0_ctrl},
#endif
#ifdef BSP_USING_DAC1
    {'1', &g_dac1_cfg, &g_dac1_ctrl},
#endif
};

#ifdef BSP_USING_DAC0
struct rt_dac_device dac0_device;
struct ra_dac_dev _ra_dac0_device = {.ra_dac_device_t = &dac0_device, .ra_dac_map_dev = &ra_dac[0]};
#endif

#ifdef BSP_USING_DAC1
struct rt_dac_device dac1_device;
struct ra_dac_dev _ra_dac1_device = {.ra_dac_device_t = &dac1_device, .ra_dac_map_dev = &ra_dac[1]};
#endif

struct rt_dac_ops ra_dac_ops =
{
    .disabled = ra_dac_disabled,
    .enabled  = ra_dac_enabled,
    .convert  = ra_dac_write,
};

static int ra_dac_init(void)
{
#ifdef BSP_USING_DAC0
    _ra_dac0_device.ra_dac_device_t->ops = &ra_dac_ops;
    R_DAC_Open((dac_ctrl_t *)_ra_dac0_device.ra_dac_map_dev->g_ctrl, (dac_cfg_t const *)_ra_dac0_device.ra_dac_map_dev->g_cfg);
    if (FSP_SUCCESS != rt_hw_dac_register(_ra_dac0_device.ra_dac_device_t, "dac0", &ra_dac_ops, (void *)_ra_dac0_device.ra_dac_map_dev))
    {
        LOG_E("dac0 register failed");
        return -RT_ERROR;
    }
#endif

#ifdef BSP_USING_DAC1
    _ra_dac1_device.ra_dac_device_t->ops = &ra_dac_ops;
    R_DAC_Open((dac_ctrl_t *)_ra_dac1_device.ra_dac_map_dev->g_ctrl, (dac_cfg_t const *) _ra_dac1_device.ra_dac_map_dev->g_cfg);
    if (FSP_SUCCESS != rt_hw_dac_register(_ra_dac1_device.ra_dac_device_t, "dac1", &ra_dac_ops, (void *)_ra_dac1_device.ra_dac_map_dev))
    {
        LOG_E("dac1 register failed");
        return -RT_ERROR;
    }
#endif

    return RT_EOK;
}
INIT_DEVICE_EXPORT(ra_dac_init);

DAC的适配,并未像ADC那样采用for循环的方式编写,这也导致了如果后面存在dac2,甚至dacx时,不得不修改ra_dac_init和数组结构体定义,修改面相较于ADC驱动会大一些。另外,从这里我们可以看出,如果我们要适配已有的dac驱动配置,则需要按照struct ra_dac_map ra_dac[]中的内容生成RASC配置,否则会出现编译报错。另外,这注册接口有个小问题,rt_hw_dac_register的返回值居然是用FSP_SUCCESS来判断的,虽然从功能上来说这不是问题,但是从理解上来说,FSP_SUCCESS是FSP特有的定义,不是RTT的定义,若两方有任何一方突然更新这块,就会存在不匹配的情况。

使能/禁用dac接口

   之所以放一起,是因为ADC那部分就是放一起实现的。

rt_err_t ra_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel)
{
    RT_ASSERT(device != RT_NULL);
    struct ra_dac_map *dac = (struct ra_dac_map *)device->parent.user_data;
    if (FSP_SUCCESS != R_DAC_Stop((dac_ctrl_t *)dac->g_ctrl))
    {
        LOG_E("dac%c stop failed.", dac->name);
        return -RT_ERROR;
    }
    return RT_EOK;
}

rt_err_t ra_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel)
{
    RT_ASSERT(device != RT_NULL);
    struct ra_dac_map *dac = (struct ra_dac_map *)device->parent.user_data;
    if (FSP_SUCCESS != R_DAC_Start((dac_ctrl_t *)dac->g_ctrl))
    {
        LOG_E("dac%c start failed.", dac->name);
        return -RT_ERROR;
    }
    return RT_EOK;
}

这部分上实现其实很精简,直接对接dac的FSP代码,而对接的参数就是RASC生成的配置。

DAC电压值写实现

rt_err_t ra_dac_write(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value)
{
    RT_ASSERT(device != RT_NULL);
    struct ra_dac_map *dac = (struct ra_dac_map *)device->parent.user_data;
    if (FSP_SUCCESS != R_DAC_Write((dac_ctrl_t *)dac->g_ctrl, *value))
    {
        LOG_E("dac%c set value failed.", dac->name);
        return -RT_ERROR;
    }
    return RT_EOK;
}

这接口的实现也特别精简,甚至都不需要细看代码就已经知道了需要干嘛了。实际上就是将寄存器值通过FSP接口设下去。

总结

   相比较于瑞萨适配ADC驱动的实现,DAC实现上有那么一点点小瑕疵(注册驱动函数),但目前来说,并不影响驱动的使用,可以暂时不去优化。





关键词: 瑞萨     适配     驱动     DAC    

专家
2024-09-07 19:29:47     打赏
2楼

很详细了


专家
2024-09-08 12:17:13     打赏
3楼

感谢楼主分享


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]