RTT设备驱动框架学习(CAN设备)

embedded/2024/10/10 13:50:38/

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

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

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

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

实例分析

设备对象在rtdef.h中的具体定义

struct rt_device
{struct rt_object parent;enum rt_device_class_type type;rt_uint16_t flag;rt_uint16_t open_flag;rt_uint8_t ref_count;rt_uint8_t device_id;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_OPSconst 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 */#ifdef RT_USING_POSIX_DEVIOconst struct dfs_file_ops *fops;struct rt_wqueue wait_queue;
#endif /* RT_USING_POSIX_DEVIO */void                     *user_data;                /**< device private data */
};
}

然后从struct rt_device中派生出新的CAN设备类型struct rt_can_device,其中依据CAN类型设备共有的特性新增了一些结构体成员,位于rt-thread\components\drivers\include\drivers\can.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_HDRstruct rt_can_hdr *hdr;
#endif
#ifdef RT_CAN_USING_BUS_HOOKrt_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,其中添加了这个设备类型的私有数据,便于底层驱动的对接:

struct stm32_can
{char *name;CAN_HandleTypeDef CanHandle;CAN_FilterTypeDef FilterConfig;struct rt_can_device;
};

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

操作方法

在struct rt_can_device中可以看到针对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);
};

在drv_can.c中,就实现了所有CAN设备的操作方法,并赋值给对应的函数指针,可以直接调用。并且通过static const修饰符,使结构体变量的内容是固定的,提高了代码的安全性和可维护性。然后通过rt_hw_can_register注册。

static const struct rt_can_ops _can_ops = 
{_can_config,_can_control,_can_sendmsg,_can_recvmsg,
};
rt_err_t rt_hw_can_register(struct rt_can_device *can, const char *name, const struct rt_can_ops *ops, void *data);
rt_hw_can_register(&drv_can1.device, drv_can1.name, &_can_ops, &_can_ops, &drv_can1);

其中最后一个参数为void类型指针,在注册同类型的不同设备时,就可以通过最后一个参数,在注册时传入其特有的私有数据。例如STM32的drv_can中传入的就是stm32_can结构体类型,其中就包含了stm_can的私有数据域,在对接底层硬件驱动的时候就会方便很多。


http://www.ppmy.cn/embedded/9641.html

相关文章

docker打包部署自己的应用

docker部署应用 当谈及使用 Docker 进行容器化部署应用时&#xff0c;可以想象它是一个能够将整个应用程序及其所有依赖项打包成一个独立、可移植的容器的工具。这个容器不仅包含了应用代码&#xff0c;还包括了操作系统、运行时环境以及所有依赖的库和组件。这样一来&#xf…

项目中,如何写 readme.md 文件 | 写项目总结

tips&#xff1a;注意写 1. readme文件&#xff1a;①项目文档&#xff08;项目需求和设计文档、项目系统架构和技术文档、接口文档&#xff09;、②项目结构、③启动项目。具体结构见下文。 2. 项目总结&#xff1a;技术栈、描述、主要工作&#xff01;&#xff01;需求及功…

java | junit | 基本+技巧

1.参考链接 1.1 单测概念 https://medium.com/lathasreeseeni/junit-2d9857773e8 1.2 高级技巧 https://symflower.com/en/company/blog/2023/how-to-write-junit-test-cases-advanced-techniques/ assertThrows&#xff1a; 有时候&#xff0c;我们的方法&#xff0c;需要抛出…

第八章_VLAN、Trunk和VLAN间路由

VLAN和 Trunk是企业局域网最基本和最核心的网络技术&#xff0c;在部著和实施局域网时应用广泛。VLAN技术可以很容易地控制广播域的大小。有了VLAN&#xff0c;交换机之间的级联链路就需要Trunk技术来保证该链路可以同时传输多个VLAN的数据。管理员可以手动配置交换机之间链路上…

[MySQL数据库] 索引与事务

1. 索引 1.1 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针.可以对表中的一列或多列创建索引,并指定索引的类型&#xff0c;各类索引有各自的数据结构实现. 1.2 作用 数据库中的表、数据、索引之间的关系&#xff0c;类似于书架上的图书、书籍…

nginx使用http2,并配置ssl证书

** nginx使用http2&#xff0c;并配置ssl证书 ** 想要使用http2&#xff0c;需要在安装nginx时安装http2模块和ssl模块 前置条件nginx版本需要在1.9.5以上 #解压nginx包 tar -zxvf nginx-1.18.0.tar.gz #进入nginx目录 cd nginx-1.18.0 #执行 ./configure --prefix/usr/lo…

SpringCloud系列(9)--将服务消费者Consumer注册进Eureka Server

前言&#xff1a;上一章节我们介绍了如何将服务提供者注册进Eureka服务里&#xff0c;本章节则介绍如何将服务消费者Consumer注册进Eureka服务里 Eureka架构原理图 1、修改consumer-order80子模块的pom.xml文件&#xff0c;引入Eureka Clinet的依赖&#xff0c;然后reolad一下&…

智慧公厕解决方案易集成好使用的智能硬件

在现代城市建设中&#xff0c;智慧公厕的需求日益增长。为了提供更好的用户体验和更高效的管理&#xff0c;易集成、好使用的智能硬件成为智慧公厕解决方案的关键组成部分。 1. 蹲位有人无人感应器&#xff1a;是用于检测厕位有人无人的设备&#xff0c;根据现场不同的安装条件…