0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅析RT-Thread设备驱动框架

冬至子 来源:螺丝松掉的人 作者:螺丝松掉的人 2023-08-07 15:39 次阅读

前言介绍
RT-Thread 设备框架属于组件和服务层,是基于 RT-Thread 内核之上的上层软件。设备框架是针对某一类外设,抽象出来的一套统一的操作方法及接入标准,可以屏蔽硬件差异,为应用层提供统一的操作方法。

RT-Thread 设备框架分为三层:设备驱动层、设备驱动框架层、I/O 设备管理层。其中设备驱动层直接对接底层硬件设备;I/O 设备管理层向应用层提供了rt_device_find、open、read、write、close、register等访问设备的统一标准接口。而设备驱动框架层就是就是将同类型硬件设备的共同特特征提取抽象出来,并且还预留了接口,可以添加不同设备的独有特性。

其中的设备模型被认为是一类对象,每个设备对象都是由基对象派生的,每个设备都可以继承其父类对象的属性,并派生其私有属性。

正是这样的框架,使得 RT-Thread 设备框架中各模块高内聚低耦合,对于已有的设备类型,只要将底层硬件的驱动对接到设备驱动层,就可以在应用程序中,调用统一的标准接口,使用的不同厂家不同类型的硬件设备。

示例分析
下文将以 CAN 设备为例,并从 void 类型指针、结构体等方向,分析 RT-Thread 设备驱动框架。

设备对象
以下是设备对象在 rt-threadincludertdef.h 中的具体定义:(去除了其中一些扩展的功能,方便理解)

/**

Device structure
*/
struct rt_device
{
struct rt_object parent; / *< inherit from rt_object /
enum rt_device_class_type type; /
< device type */
rt_uint16_t flag; / < device flag /
rt_uint16_t open_flag; /
< device open flag */
rt_uint8_t ref_count; / < reference count /
rt_uint8_t device_id; /
< 0 - 255 /
/
device call back */
rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);
rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);
#ifdef RT_USING_DEVICE_OPS
const struct rt_device_ops ops;
#else
/
common device interface */
rt_err_t (*init) (rt_device_t dev);
rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
rt_err_t (*close) (rt_device_t dev);
rt_ssize_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
rt_ssize_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
rt_err_t (*control)(rt_device_t dev, int cmd, void args);
#endif /
RT_USING_DEVICE_OPS */
void *user_data; /
< device private data */
};

然后从 struct rt_device 中派生出新的 CAN 设备类型 struct rt_can_device ,其中依据 CAN 类型设备共有的特性新增了一些结构体成员,位于rt-threadcomponentsdriversincludedriverscan.h 中:

struct rt_can_device
{
struct rt_device parent;
const struct rt_can_ops *ops;
struct can_configure config;
struct rt_can_status status;
rt_uint32_t timerinitflag;
struct rt_timer timer;
struct rt_can_status_ind_type status_indicate;
#ifdef RT_CAN_USING_HDR
struct rt_can_hdr *hdr;
#endif
#ifdef RT_CAN_USING_BUS_HOOK
rt_can_bus_hook bus_hook;
#endif / RT_CAN_USING_BUS_HOOK /
struct rt_mutex lock;
void *can_rx;
void *can_tx;
};
stm32 的 CAN 设备驱动中,又从 struct rt_can_device 中派生出了新的 CAN 设备模型 struct stm32_can 其中添加了这个设备类型的私有数据,便于底层驱动的对接:

/* stm32 can device */
struct stm32_can
{
char name;
CAN_HandleTypeDef CanHandle;
CAN_FilterTypeDef FilterConfig;
struct rt_can_device device; /
inherit from can device */
};

可以看出,RT-Thread 通过结构体和函数指针使用 C 语言实现了一些面向对象编程的特性,如封装和继承等,这样面向对象、模块化的思维框架,有助于实现各模块之间高内聚低耦合,提高开发效率。

操作方法
在 rt-threadcomponentsdriversincludedriverscan.h 中可以看到针对 CAN 设备有以下操作方法,这些操作方法是需要我们在设备驱动层去针对不同的硬件设备进行对接实现的。对于一些特殊的设备类型,可以不用对接其所有的操作方法。

struct rt_can_ops
{
rt_err_t (*configure)(struct rt_can_device *can, struct can_configure *cfg);
rt_err_t (*control)(struct rt_can_device *can, int cmd, void *arg);
int (*sendmsg)(struct rt_can_device *can, const void *buf, rt_uint32_t boxno);
int (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t boxno);
};

在librariesHAL_Driversdrv_can.c中,就实现了所有 CAN 设备的操作方法,并赋值给对应的函数指针,可以直接调用。并且通过 static const 修饰符,使结构体变量_can_ops的值在编译时被确定,并且不能在程序运行时修改。这样可以确保该结构体变量的内容是固定的,提高了代码的安全性和可维护性。然后通过rt_hw_can_register注册。

static const struct rt_can_ops _can_ops =
{
_can_config,
_can_control,
_can_sendmsg,
_can_recvmsg,
};
/* register CAN1 device */
rt_hw_can_register(&drv_can1.device,
drv_can1.name,
&_can_ops,
&drv_can1);
可以看一下rt_hw_can_register函数的具体声明:

rt_err_t rt_hw_can_register(struct rt_can_device *can,
const char *name,
const struct rt_can_ops *ops,
void *data);
其中最后一个参数为 void 类型指针,在注册同类型的不同设备时,就可以通过最后一个参数,在注册时传入其特有的私有数据。例如 STM32 的 drv_can 中传入的就是 stm32_can结构体类型,其中就包含了 stm32 can 的私有数据域,在对接底层硬件驱动的时候就会方便很多。

总结
可以感受到,其中结构体和指针的运用是非常重要的。尽管C语言是一种面向过程的语言,但通过使用结构体和函数指针,可以模拟实现封装、继承和多态这三个面向对象编程的特性,享受面向对象编程的好处。

对于指针的运用,主要是 void 类型指针和函数指针。由于 void 指针没有特定的类型,因此它可以指向任何类型的数据。也就是说,任何类型的指针都可以直接赋值给 void 指针,而无需进行其他相关的强制类型转换,便于传递同类型的不同设备的私有数据。通过函数指针,也就是回调函数,可以大大提高程序的灵活性和并起到封装的作用。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动器
    +关注

    关注

    51

    文章

    7308

    浏览量

    142942
  • CAN总线
    +关注

    关注

    145

    文章

    1812

    浏览量

    129592
  • STM32
    +关注

    关注

    2239

    文章

    10671

    浏览量

    348738
  • C语言
    +关注

    关注

    180

    文章

    7530

    浏览量

    128586
  • RT-Thread
    +关注

    关注

    31

    文章

    1148

    浏览量

    38869
收藏 人收藏

    评论

    相关推荐

    基于RT-Thread的RoboMaster电控框架设计

    由于 RT-Thread 稳定高效的内核,丰富的文档教程,积极活跃的社区氛围,以及设备驱动框架、Kconfig、Scons、日志系统、海量的软件包……很难不选择
    发表于 09-06 15:21 408次阅读

    RT-Thread设备驱动开发指南基础篇—以先楫bsp的hwtimer设备为例

    RT-Thread设备驱动开发指南》书籍是RT-thread官方出品撰写,系统讲解RT-thread IO
    的头像 发表于 02-20 16:01 822次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>设备</b><b class='flag-5'>驱动</b>开发指南基础篇—以先楫bsp的hwtimer<b class='flag-5'>设备</b>为例

    RT-Thread 的 IO 设备模型框架是由哪些部分组成的呢

    RT-Thread 的 I/O 设备模型框架是由哪些部分组成的呢?接下来由小编给大家详细介绍一下。1、RT-Thread 的 I/O 设备
    发表于 03-11 18:17

    如何使用RT-Thread SPI设备驱动

    RT-Thread中引入了SPI设备驱动框架。本文说明了如何使用RT-Thread SPI设备
    发表于 10-25 14:20

    详细讲解RT-Thread I2C设备驱动框架及相关函数

    本应用笔记以驱动I2C接口的6轴传感器MPU6050为例,说明了如何使用I2C设备驱动接口开发应用程序,并详细讲解了RT-Thread I2C设备
    的头像 发表于 03-29 10:52 2w次阅读
    详细讲解<b class='flag-5'>RT-Thread</b> I2C<b class='flag-5'>设备</b><b class='flag-5'>驱动</b><b class='flag-5'>框架</b>及相关函数

    RT-Thread开源作品秀】基于RT-Thread的星务平台研究

    本作品为了验证星务软件在RT-Thread系统运行的可行性,底层是否能够驱动星务软件,同时扩展RT-Thread应用范围。ART-Pi作为卫星下位机,...
    发表于 01-25 18:26 5次下载
    【<b class='flag-5'>RT-Thread</b>开源作品秀】基于<b class='flag-5'>RT-Thread</b>的星务平台研究

    RT-Thread全球技术大会:RT-Thread上的单元测试框架与运行测试用例

    RT-Thread全球技术大会:RT-Thread上的单元测试框架与运行测试用例                 审核编辑:彭静
    的头像 发表于 05-27 16:21 1266次阅读
    <b class='flag-5'>RT-Thread</b>全球技术大会:<b class='flag-5'>RT-Thread</b>上的单元测试<b class='flag-5'>框架</b>与运行测试用例

    RT-Thread设备模型框架及创建注册设备的实现

    RT-Thread设备模型框架及创建注册设备的实现方式介绍如下:
    的头像 发表于 05-28 10:38 1811次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>设备</b>模型<b class='flag-5'>框架</b>及创建注册<b class='flag-5'>设备</b>的实现

    RT-Thread文档_RT-Thread 简介

    RT-Thread文档_RT-Thread 简介
    发表于 02-22 18:22 5次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> 简介

    RT-Thread文档_RT-Thread SMP 介绍与移植

    RT-Thread文档_RT-Thread SMP 介绍与移植
    发表于 02-22 18:31 7次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> SMP 介绍与移植

    RT-Thread文档_utest 测试框架

    RT-Thread文档_utest 测试框架
    发表于 02-22 18:43 2次下载
    <b class='flag-5'>RT-Thread</b>文档_utest 测试<b class='flag-5'>框架</b>

    送《RT-Thread设备驱动开发指南》,手慢无!

    过程中的第一选择!本书 也是RT-Thread第8本相关书籍了,本期我们将抽奖送给大家! 抽奖请移步文末↓↓↓ 随着RT-Thread被更广泛地应用于行业中,开发者对嵌入式驱动开发的需求越来越强烈,他们
    的头像 发表于 03-19 23:00 1047次阅读

    基于 RT-Thread 的 RoboMaster 电控框架(一)

    由于 RT-Thread 稳定高效的内核,丰富的文档教程,积极活跃的社区氛围,以及设备驱动框架、Kconfig、Scons、日志系统、海量的软件包……很难不选择
    的头像 发表于 09-19 19:55 416次阅读

    基于RT-Thread的RoboMaster电控框架(二)

    由于 RT-Thread 稳定高效的内核,丰富的文档教程,积极活跃的社区氛围,以及设备驱动框架、Kconfig、Scons、日志系统、海量的软件包
    的头像 发表于 09-20 15:16 471次阅读

    基于rt-thread的socket通信设计

    最近再研究 rt-thread 的通信 ,想设计出 eps8266(多个) rt-thread(作为中控) 服务器的通信框架,使用的开发板是 潘多拉
    的头像 发表于 10-13 15:02 688次阅读
    基于<b class='flag-5'>rt-thread</b>的socket通信设计