抽象 I/O设备模型

I/O设备模型框架

RT-Thread提供了一套简单的I/O设备模型框架。
在这里插入图片描述
如图所示,它位于硬件和应用程序之间,共分成三层,从上到下分别是I/O设备管理层、设备驱动框架层、设备驱动层。

应用程序通过I/O设备管理接口获得正确的设备驱动,然后通过这个设备驱动与底层I/O硬件设备进行数据交互。

I/O设备管理层实现了对设备驱动程序的封装。
应用程序通过图中的“I/O设备管理层”提供的标准接口访问底层设备,设备驱动程序的升级、更替不会对上层应用产生影响。这种方式使得设备的硬件操作相关的代码能够独立于应用程序而存在,双方只需要关注各自的功能实现,从而降低了代码的耦合性、复杂性,提高了系统的可靠性。

设备驱动框架层是对同类硬件设备驱动的抽象,将不同厂家的同类硬件设备驱动中相同的部分抽取出来,将不同部分留出接口,由驱动程序实现。

设备驱动层是一组驱使硬件设备工作的程序,实现访问硬件设备的功能。它负责创建和注册I/O设备,对于操作逻辑简单的设备,可以不经过设备驱动框架层,直接将设备注册到I/O设备管理器中,使用序列图如下图所示,主要有以下2点:

  • 设备驱动根据设备模型定义,创建出具备硬件访问能力的设备实例,将该设备通过rt_device_register()接口注册到I/O设备管理器中。
  • 应用程序通过rt_device_find()接口查找到设备,然后使用I/O设备管理接口来访问硬件。

在这里插入图片描述

对于另一些设备,如看门狗等,则会将创建的设备实例先注册到对应的设备驱动框架中,再由设备驱动框架向I/O设备管理器进行注册,主要有以下几点:

  • 看门狗设备驱动根据看门狗设备模型定义,创建出具备硬件访问能力的看门狗设备实例,并将该看门狗设备通过rt_hw_watchdog_register()接口注册到看门狗设备驱动框架中。
  • 看门狗设备驱动框架通过rt_device_register()接口将看门狗注册到I/O设备管理器中。
  • 应用程序通过I/O设备管理接口来访问看门狗设备硬件。

在这里插入图片描述

libraries->HAL_Drivers:是设备驱动程序层
rt-thread->components->drivers:设备驱动框架层

I/O设备模型

RT-Thread的设备模型是建立在内核对象模型基础之上的,**设备被认为是一类对象,**被纳入对象管理器的范畴。
每个设备对象都是由基对象派生而来,每个具体设备都可以继承其父类对象的属性,并派生出其私有属性。

struct rt_object
{
	char name[RT_NAME_MAX];
	rt_uint8_t type;
	rt_uint8_t flag;
	rt_list_t list;
};
typedef struct rt_object *rt_object_t;
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;                /**< 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);

	/* 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_size_t (*read)   (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
    rt_size_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);
    void                     *user_data;                /**< device private data */
};
enum rt_device_class_type
{
    RT_Device_Class_Char = 0,                           /**< character device */
    RT_Device_Class_Block,                              /**< block device */
    RT_Device_Class_NetIf,                              /**< net interface */
    RT_Device_Class_MTD,                                /**< memory device */
    RT_Device_Class_CAN,                                /**< CAN device */
    RT_Device_Class_RTC,                                /**< RTC device */
    RT_Device_Class_Sound,                              /**< Sound device */
    RT_Device_Class_Graphic,                            /**< Graphic device */
    RT_Device_Class_I2CBUS,                             /**< I2C bus device */
    RT_Device_Class_USBDevice,                          /**< USB slave device */
    RT_Device_Class_USBHost,                            /**< USB host bus */
    RT_Device_Class_USBOTG,                             /**< USB OTG bus */
    RT_Device_Class_SPIBUS,                             /**< SPI bus device */
    RT_Device_Class_SPIDevice,                          /**< SPI device */
    RT_Device_Class_SDIO,                               /**< SDIO bus device */
    RT_Device_Class_PM,                                 /**< PM pseudo device */
    RT_Device_Class_Pipe,                               /**< Pipe device */
    RT_Device_Class_Portal,                             /**< Portal device */
    RT_Device_Class_Timer,                              /**< Timer device */
    RT_Device_Class_Miscellaneous,                      /**< Miscellaneous device */
    RT_Device_Class_Sensor,                             /**< Sensor device */
    RT_Device_Class_Touch,                              /**< Touch device */
    RT_Device_Class_PHY,                                /**< PHY device */
    RT_Device_Class_Security,                           /**< Security device */
    RT_Device_Class_Unknown                             /**< unknown device */
};

创建和注册I/O设备

驱动层负责创建设备实例,并注册到I/O设备管理器中,可以通过静态申明的方式创建设备实例,也可以用下面的接口进行动态创建:

rt_device_t rt_device_create(int type, int attach_size);

调用该接口时,系统会从动态堆内存中分配一个设备控制块,大小为struct rt_device和attach_size的和,设备的类型由参数type设定。
设备被创建后,需要实现它访问硬件的操作方法。

struct rt_device_ops
{
    /* 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_size_t (*read)   (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
    rt_size_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);
};

  • init:初始化设备。设备初始化完成后,设备控制块的flag会被置成已激活状态(RT_DEVICE_FLAG_ACTIVATED)。如果设备控制块中的flag标志已经设置成激活状态,那么再运行初始化接口时会立刻返回,而不会重新进行初始化。
  • open:有些设备并不是系统一启动就已经打开开始运行,或者设备需要进行数据收发,但如果上层应用还未准备好,设备也不应默认已经使能并开始接收数据。所以建议在写底层驱动程序时,在调用 open 接口时才使能设备。
  • close:关闭设备。在打开设备时,设备控制块会维护一个打开计数,在打开设备时进行+1操作,在关闭设备时进行-1操作,当计数器变为0时,才会进行真正的关闭操作。
  • read:从设备读取数据。pos是读取数据的偏移量,但有些设备并不一定需要偏移量,如串口设备,设备驱动应忽略这个参数。这个接口返回的类型是rt_size_t,即读到的字节数或块数目。正常情况下应该会返回参数中size的数值,如果返回零要设置对应的errno值。
  • write:向设备写入数据。参数 pos 是写入数据的偏移量。与读操作类似,对于块设备来说,pos 以及 size 都是以块设备的数据块大小为单位的。这个接口返回的类型是 rt_size_t,即真实写入数据的字节数或块数目。正常情况下应该会返回参数中 size 的数值,如果返回零请设置对应的 errno 值。
  • control:根据cmd命令控制设备。根据cmd命令控制设备。命令往往是由底层各类设备驱动自定义实现。例如参数 RT_DEVICE_CTRL_BLK_GETGEOME,意思是获取块设备的大小信息。

设备被创建后,需要注册到I/O设备管理器中,应用程序才能够访问,注册设备的函数如下所示:

rt_err_t rt_device_register(rt_device_t dev,
                            const char *name,
                            rt_uint16_t flags)
{
    if (dev == RT_NULL)
        return -RT_ERROR;

    if (rt_device_find(name) != RT_NULL)
        return -RT_ERROR;

    rt_object_init(&(dev->parent), RT_Object_Class_Device, name);
    dev->flag = flags;
    dev->ref_count = 0;
    dev->open_flag = 0;

#ifdef RT_USING_POSIX_DEVIO
    dev->fops = RT_NULL;
    rt_wqueue_init(&(dev->wait_queue));
#endif /* RT_USING_POSIX_DEVIO */

    return RT_EOK;
}
RTM_EXPORT(rt_device_register);

在这里插入图片描述
图中各类的.c文件是各类对应的管理接口所在,比如设备基类rt_device的管理接口在device.c中。

开发者只需开发驱动层即可,设备驱动框架层和I/O设备管理层,RT-Thread已经写好了,无需改动

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/150107.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一题带你写出图论算法模板!!!

这题是道基础的图论算法题目 注释很重要&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 在做这道题之前&#xff0c;我们先了解一下基础的图论算法吧&#xff01;&#xff01;&#xff01; 1.floyd&#xff1a; 这样可以求出所有点…

闲聊从零开发一个2D数字人流程实战

.2D数字人技术 百度&#xff0c;腾讯&#xff0c;等大厂都有自己的数字平台制作&#xff08;套壳&#xff1a;api后台转发vue前端&#xff09;&#xff0c;国外也有出名的heygen&#xff08;非常厉害一个&#xff09;通过开源项目组合实现&#xff0c;再打通每个项目已api的形…

LCD1602命令代码整合

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

C语言查看main函数的参数

这里写自定义目录标题 argc 代表参数的个数argv 代表参数的具体值&#xff0c;其中argv[0]代表的是可执行文件的名字&#xff0c;参考上图

微信这4个功能容易暴露隐私,记得关闭

每天高频使用微信的我们&#xff0c;常常觉得安全无忧&#xff0c;然而这样的想法并不准确。尽管微信本身的安全性能极高&#xff0c;但若我们不主动设置相关功能&#xff0c;个人隐私和位置信息仍可能被暴露。 在微信朋友圈上&#xff0c;有些人喜欢分享生活的点滴&#xff0c…

爆款标题怎么出来的?媒介盒子揭秘产出技巧

用户点开一篇文案的主要因素取决于标题是否具有吸引力&#xff0c;直观判断可能只需要半秒钟&#xff0c;用户的操作也决定了文章的点击率与阅读完成率。 然而有许多人为了取标题想破脑袋也想不出来&#xff0c;甚至文案内容出来了标题还没出来&#xff0c;今天媒介盒子就来为…

Java GUI小程序之图片浏览器

以下是一个简单的图片浏览器示例代码&#xff0c;它包含了图片放大缩小、拖拽、上一张/下一张查看等功能。你可以根据它进行扩展&#xff0c;提高用户体验。 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.e…

土木非科班转码测开,斩获10家大厂offer

大家好&#xff0c;我是洋子 24届秋招基本已经落下了帷幕&#xff0c;各大互联网大厂基本也开奖完毕&#xff0c;还没有拿到满意offer的同学也不要灰心&#xff0c;积极备战明年的春招。另外&#xff0c;25届想要找暑期实习的同学也可以开始准备起来了&#xff0c;基本大厂在春…

UI自动化测试(弹出框,多窗口)

一、弹出框实战 1、在UI自动化测试中经常会遇到Alert弹出框的场景。Alert类是对话框的处理&#xff0c;主要是对alert警告框。confirm确认框&#xff0c;promp消息对话框。 text():获取alert的文本 dismiss ():点击取消 accept():接受 send-keys():输入 from selenium import …

split loop

// refactoringmotherfucker.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#include <iostream> #include <vector> #include <memory>// before refactoring of split loop class People { public:People(double _age,double _…

<C++> 优先级队列

目录 前言 一、priority_queue的使用 1. 成员函数 2. 例题 二、仿函数 三、模拟实现 1. 迭代器区间构造函数 && AdjustDown 2. pop 3. push && AdjustUp 4. top 5. size 6. empty 四、完整实现 总结 前言 优先级队列以及前面的双端队列基本上已经脱离了队列定…

单pipeline部署一套代码,多项目

单pipeline部署一套代码&#xff0c;多项目 pipeline {agent anyparameters {gitParameter(name: BRANCH_TAG, type: PT_BRANCH_TAG, branchFilter: origin/(.*), defaultValue: main, selectedValue: DEFAULT, sortMode: DESCENDING_SMART, description: 请选择需要部署的代码…

【Regulatory Genomics】Part2 BPNet、DeepLIFT

文章目录 Deep learning at base-resolution reveals cis-regulatory motif syntaxproblemBPNet: predicting base-resolution profiles from DNA sequenceInterpreting the predictions of BPNet1 DeepLIFT2 TF-MoDISCO3 motif syntax derived TF cooperativity Experimental …

人工智能基础_机器学习036_多项式回归升维实战3_使用线性回归模型_对天猫双十一销量数据进行预测_拟合---人工智能工作笔记0076

首先我们拿到双十一从2009年到2018年的数据 可以看到上面是代码,我们自己去写一下 首先导包,和准备数据 from sklearn.linear_model import SGDRegressor import numpy as np import matplotlib.pyplot as plt X=np.arange(2009.2020)#左闭右开,2009到2019 获取从2009到202…

Python如何使用Pyecharts+TextRank生成词云图?

Python如何使用PyechartsTextRank生成词云图&#xff1f; 1 应用场景2 关于Pyecharts2.1 Pyecharts简介2.2 Pyecharts安装2.3 Pyecharts支持的图形2.4 Pyecharts的一个示例 3 关于TextRank3.1 TextRank简介3.2 TextRank安装 4 词云图的生成过程4.1 导入需要的包4.2 目标文件4.3…

使用c++程序,实现图像平移变换,图像缩放、图像裁剪、图像对角线镜像以及图像的旋转

数字图像处理–实验三A图像的基本变换 实验内容 A实验&#xff1a; &#xff08;1&#xff09;使用VC设计程序&#xff1a;实现图像平移变换&#xff0c;图像缩放、图像裁剪、图像对角线镜像。 &#xff08;2&#xff09;使用VC设计程序&#xff1a;对一幅高度与宽度均相等的…

计算机网络五层协议的体系结构

计算机网络中两个端系统之间的通信太复杂&#xff0c;因此把需要问题分而治之&#xff0c;通过把一次通信过程中涉及的所有问题分层归类来进行研究和处理 体系结构是抽象的&#xff0c;实现是真正在运行的软件和硬件 1.实体、协议、服务和服务访问点 协议必须把所有不利条件和…

Java GUI实现五子棋游戏

五子棋是一种双人对弈的棋类游戏&#xff0c;通常在棋盘上进行。棋盘为 1515 的方格&#xff0c;黑白双方各执棋子&#xff0c;轮流在棋盘的格点上落子&#xff0c;先在横、竖、斜线上形成五个相连的同色棋子者获胜。五子棋规则简单&#xff0c;易学难精&#xff0c;兼具攻防和…

java,springboot钉钉开发连接器,自定义连接器配合流程使用,流程加入连接器,连接器发送参数,然后你本地处理修改值,返回给流程

1.绘制连接器&#xff0c;注意出餐入参的格式&#xff0c; 2.绘制流程&#xff0c;绑定连接器&#xff0c;是提交后出发还是表单值变化后 3.编写本地接口&#xff08;内网穿透&#xff09;&#xff0c;绑定连接器 钉钉开发连接器&#xff0c;自定义连接器配合流程使用&#x…

安防监控系统EasyCVR平台调用hls地址生成流的时间过长,该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台可拓展性强、…