RT-Thread 访问I/O设备

news2025/2/25 18:27:05

访问I/O设备

应用程序通过I/O设备管理接口来访问硬件设备,当设备驱动实现后,应用程序就可以访问该硬件。
在这里插入图片描述
查找设备:应用程序根据设备名称获取设备句柄,进而操作设备。

获得设备句柄后,应用程序可使用如下函数对设备进行初始化操作:

rt_err_t rt_device_init(rt_device_t device);

当一个设备已经初始化成功后,调用这个接口将不再重复做初始化。

打开和关闭设备:

通过设备句柄,应用程序可以打开和关闭设备,打开设备时,会检测设备是否已经初始化,没有初始化则会默认调用接口初始化设备。通过如下函数打开设备:

rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags);
  • oflags:设备打开模式。
    返回:
  • -RT_EBUSY:如果设备注册时指定的参数中包括RT_DEVICE_FLAG_STANDALONE参数,此设备将不允许重复打开。
#define RT_DEVICE_OFLAG_CLOSE 0x000   /* 设备已经关闭(内部使用)*/
#define RT_DEVICE_OFLAG_RDONLY 0x001  /* 以只读方式打开设备 */
#define RT_DEVICE_OFLAG_WRONLY 0x002  /* 以只写方式打开设备 */
#define RT_DEVICE_OFLAG_RDWR 0x003    /* 以读写方式打开设备 */
#define RT_DEVICE_OFLAG_OPEN 0x008    /* 设备已经打开(内部使用)*/
#define RT_DEVICE_FLAG_STREAM 0x040   /* 设备以流模式打开 */
#define RT_DEVICE_FLAG_INT_RX 0x100   /* 设备以中断接收模式打开 */
#define RT_DEVICE_FLAG_DMA_RX 0x200   /* 设备以 DMA 接收模式打开 */
#define RT_DEVICE_FLAG_INT_TX 0x400   /* 设备以中断发送模式打开 */
#define RT_DEVICE_FLAG_DMA_TX 0x800   /* 设备以 DMA 发送模式打开 */

如果上层应用程序需要设置设备的接收回调函数,则必须以RT_DEVICE_FLAG_INT_RX或者RT_DEVICE_FLAG_DMA_RX的方式打开设备,否则不会回调函数。

应用程序打开设备完成读写等操作后,如果不需要再对设备进行操作则可以关闭设备,通过如下函数完成:

rt_err_t rt_device_close(rt_device_t dev);

关闭设备接口和打开设备接口需配对使用,打开一次设备对应要关闭一次设备,这样设备才会被完全关闭,否则设备仍处于未关闭状态。

控制设备

通过命令控制字,应用程序也可以对设备进行控制,通过如下函数完成:

rt_err_t rt_device_control(rt_device_t dev,rt_uint8_t cmd,void *args);
  • dev:设备句柄
  • cmd:命令控制字,这个参数通常与设备驱动程序相关
  • arg:控制的参数
#define RT_DEVICE_CTRL_RESUME           0x01   /* 恢复设备 */
#define RT_DEVICE_CTRL_SUSPEND          0x02   /* 挂起设备 */
#define RT_DEVICE_CTRL_CONFIG           0x03   /* 配置设备 */
#define RT_DEVICE_CTRL_SET_INT          0x10   /* 设置中断 */
#define RT_DEVICE_CTRL_CLR_INT          0x11   /* 清中断 */
#define RT_DEVICE_CTRL_GET_INT          0x12   /* 获取中断状态 */

数据收发回调

当硬件设备收到数据时,可以通过如下函数回调另一个函数来设置数据接收指示,通知上层应用线程有数据到达:

rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size));

该函数的回调函数由调用者提供。

当硬件设备接收到数据时,会回调这个函数并把收到的数据长度放在size参数中传递给上层,上层应用线程在收到指示后,从设备中读取数据。

在应用程序调用rt_device_write()写入数据时,如果底层硬件能够支持自动发送,那么上层应用可以设置一个回调函数。这个回调函数会在底层硬件数据发送完成后 (例如 DMA 传送完成或 FIFO 已经写入完毕产生完成中断时) 调用。可以通过如下函数设置设备发送完成指示,函数参数及返回值见:

rt_err_t rt_device_set_tx_complete(rt_device_t dev, rt_err_t (*tx_done)(rt_device_t dev,void *buffer));

调用这个函数时,回调函数由调用者提供,当硬件设备发送完数据时,由驱动程序回调这个函数并把发送完成的数据块地址作为参数传递给上层。上层应用(线程)在收到指示时会根据发送 buffer 的情况,释放 buffer 内存块或将其作为下一个写数据的缓存。

设备访问示例

首先通过rt_device_find()找到看门狗设备,获得设备句柄,然后通过rt_device_init()口初始化设备,通过rt_device_control()口设置看门狗设备溢出时间。

在C语言中,将一个变量前面加上“static”关键字的意义取决于变量的上下文和声明位置。

  1. 在全局变量上下文中:表示该变量具有静态存储期和文件作用域。这意味着该变量在程序运行期间一直存在,不会被销毁,且只能在当前源文件中访问。其它源文件无法访问此变量。
  2. 在局部变量上下文中:表示该变量具有静态存储期,但它不会随着函数的调用而重复创建和销毁。相反,整个程序运行期间保持存在,但只能在声明它的函数内部访问。

在这里插入图片描述

#include <rtthread.h>
#include <rtdevice.h>

#define IWDG_DEVICE_NAME    "wdt"

static rt_device_t wdg_dev;

static void idle_hook(void)
{
    /* 在空闲线程的回调函数里喂狗 */
    rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
    rt_kprintf("feed the dog!\n ");
}

int main(void)
{
    rt_err_t res = RT_EOK;
    rt_uint32_t timeout = 10;    /* 溢出时间 */

    /* 根据设备名称查找看门狗设备,获取设备句柄 */
    wdg_dev = rt_device_find(IWDG_DEVICE_NAME);
    if (!wdg_dev)
    {
        rt_kprintf("find %s failed!\n", IWDG_DEVICE_NAME);
        return RT_ERROR;
    }
    /* 初始化设备 */
    res = rt_device_init(wdg_dev);
    if (res != RT_EOK)
    {
        rt_kprintf("initialize %s failed!\n", IWDG_DEVICE_NAME);
        return res;
    }
    /* 设置看门狗溢出时间 */
    res = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
    if (res != RT_EOK)
    {
        rt_kprintf("set %s timeout failed!\n", IWDG_DEVICE_NAME);
        return res;
    }
    /* 设置空闲线程回调函数 */
    rt_thread_idle_sethook(idle_hook);

    return res;
}

I/O设备模型框架补偿图

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

图中设备驱动框架层有很多RT-Thread写好的类,图中只列出2类,其它类用“xxx”来表示,这些省略的类及其管理接口。

该图横向看是分层思想,纵向看是各类派生继承关系。从下到上不断抽象、屏蔽下层差异,体现了面向对象的抽象的思想。
子类受到父类的接口约束,子类各自实现父类提供的统一接口,又体现了面向接口编程的思想。
比如从驱动层到驱动框架层,由不同厂商的相同硬件模块创建了很多子类对象,然后对接到同一个父类接口上,多对一,体现面向对象的抽象的威力。

以串口设备为例,不管下层是STM32,GD32还是别的平台,只要都是串口设备,都对接到RT-Thread的串口设备类——如图所示,多个硬件对象对接同一个父类对象接口。

同理,从设备驱动框架层到IO设备管理接口层,又是多对一,又是再一次的屏蔽差异,再一次的抽象。

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Verilog教程】2.4Verilog表达式

表达式 表达式由操作符和操作数构成&#xff0c;其目的是根据操作符的意义得到一个计算结果。表达式可以在出现数值的任何地方使用。 例如&#xff1a; a^b ; //a与b进行异或操作 address[9:0] 10b1 ; //地址累加 flag1 && flag2 ; //逻辑与操作操作数 …

2.驱动安装

链接&#xff1a;https://pan.baidu.com/s/1mYwSQvSjAiSzltrEbK3yAw?pwd43cd 提取码&#xff1a;43cd 仿真器驱动 右键此电脑&#xff0c;选择【管理】-【设备管理器】在其他设备中找到改驱动&#xff0c;鼠标右键&#xff0c;点击更新驱动程序 选择【浏览我的电脑移查找驱动…

SpringBoot+MyBatisPlus+MySQL不能储存(保存)emoji表情问题解决

1.之前在学习过程中不知道utf8和utf8mb4的区别&#xff0c;也没过多去了解&#xff0c;直到最近设置的数据库编码全是utf8后发现问题所在了&#xff0c;居然不能储存表情包&#xff01;&#xff01;&#xff01;整个人直接傻了&#xff0c;后面知道了utf8是3字节不能储存表情&a…

数据结构与算法之复杂度

时间复杂度 1.抓大头 2.常数用o(1),低阶函数也用o(1)代替&#xff08;直接去掉&#xff09; 3.取最坏情况 对数相关写法的规定

JUC第五讲:关键字synchronized详解

JUC第五讲&#xff1a;关键字synchronized详解 在C程序代码中我们可以利用操作系统提供的互斥锁来实现同步块的互斥访问及线程的阻塞及唤醒等工作。在Java中除了提供Lock API外&#xff0c;还在语法层面上提供了synchronized关键字来实现互斥同步原语, 本文是JUC第五讲&#xf…

天猫商品详情数据采集

天猫商品详情数据采集方法有很多种&#xff0c;可以从商品详情页采集&#xff0c;也可以从PC端的ajax采集&#xff0c;也可以从开放平台的API采集。不同的来源有不同的数据结构&#xff0c;可以收集的信息也不同。 天猫开放平台的API目前申请淘客API权限相对容易&#xff0c;淘…

部署和使用dinky问题总结

flink1.16 dinky&#xff08;dlink&#xff09;0.7.4 官方部署文档&#xff1a;http://www.dlink.top/docs/0.7/deploy_guide/build/ github部署文档&#xff1a;https://github.com/DataLinkDC/dinky/blob/v0.7.4/docs/docs/deploy_guide/deploy.md github issues&#xff1a;…

《Python等级考试(1~6级)历届真题解析》专栏总目录

❤️ 专栏名称&#xff1a;《Python等级考试&#xff08;1~6级&#xff09;历届真题解析》 &#x1f338; 专栏介绍&#xff1a;中国电子学会《全国青少年软件编程等级考试》Python编程&#xff08;1~6级&#xff09;历届真题解析。 &#x1f680; 订阅专栏&#xff1a;订阅后可…

拼多多商品详情API接口实时数据,获取到指定商品的详细信息,例如价格、标题、图片、描述、所属类目等信息

1.获取拼多多开发者账号 在使用拼多多 API 之前&#xff0c;需要先注册账号。注册成功后可以获取到相应的key 和Secret 用于调用 API。 2.了解拼多多商品详情 API 拼多多商品详情 API 提供了多种接口可以使用&#xff0c;其中最常用的是 pdd.ddk.goods.detail 接口。此接口可…

【力扣-每日一题】LCP 06. 拿硬币

class Solution { public:int minCount(vector<int>& coins) {int res0;for(auto i:coins){resi/2;res(i%2)?1:0;}return res;} };

使用自定义注解发布webservice服务

使用自定义注解发布webservice服务 概要代码自定义注解WebService接口服务发布配置使用 结果 概要 在springboot使用webservice&#xff0c;发布webservice服务的时候&#xff0c;我们经常需要手动在添加一些发布的代码&#xff0c;比如&#xff1a; Bean public Endpoint or…

侯捷老师C++课程:C++2.0 新特性

C 2.0 新特性 第一讲&#xff1a;语言 variatic templates 参数包 在类模板中&#xff0c;模板参数包必须是最后一个模板形参. 而在函数模板中则不必!!! 这个之前提过了&#xff0c;就不细谈了 下面那三个分别对应&#xff1a; typename... Types //模板参数包 const Type…

Linux进程【1】进程概念(超详解哦)

进程概念 引言&#xff08;操作系统如何管理&#xff09;基本概念描述与组织进程查看进程 进程pid与ppidgetpid与getppid 总结 引言&#xff08;操作系统如何管理&#xff09; 在冯诺依曼体系结构中&#xff0c;计算机由输入设备、输出设备、运算器、控制器和存储器组成。我们…

性能测试之使用Jemeter对HTTP接口压测

我们不应该仅仅局限于某一种工具&#xff0c;性能测试能使用的工具非常多&#xff0c;选择适合的就是最好的。笔者已经使用Loadrunner进行多年的项目性能测试实战经验&#xff0c;也算略有小成&#xff0c;任何性能测试&#xff08;如压力测试、负载测试、疲劳强度测试等&#…

【ArcGIS】土地利用变化分析详解(栅格篇)

土地利用变化分析详解-栅格篇 土地利用类型分类1 统计不同土地利用类型的面积/占比1.1 操作步骤 2 统计不同区域各类土地利用类型的面积2.1 操作步骤 3 土地利用变化转移矩阵3.1 研究思路3.2 操作步骤 4 分析不同时期土地利用类型及属性变化4.1 研究思路4.2 操作步骤 参考 土地…

2614. 对角线上的质数-c语言解法

给你一个下标从 0 开始的二维整数数组 nums 。 返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数&#xff0c;返回 0 。 注意&#xff1a; 如果某个整数大于 1 &#xff0c;且不存在除 1 和自身之外的正整数因子&#xff0c;则认为该整数是一个…

EPICS motor驱动程序实例

本驱动程序是控制https://blog.csdn.net/yuyuyuliang00/article/details/132483050中描述的模拟电机控制器。其余基于字符串通信方式的电机控制器&#xff0c;都可以使用这个模板进行修改&#xff0c;开发对应的EPICS电机驱动程序。 源程序如下&#xff1a; 头文件vm.h&#…

Python实现2048小游戏

简介 《2048》 [1] 是一款比较流行的数字游戏&#xff0c;最早于2014年3月20日发行。原版2048首先在GitHub上发布&#xff0c;原作者是Gabriele Cirulli&#xff0c;后被移植到各个平台。这款游戏是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏。以下是Python代码…

WPF handyControl 学习样例

​​​​​​​【1.8 HandyControl&#xff1a;80余种控件使用案例】WPF案例代码解析 - 知乎 给大家推荐一个学习handyControl的一个案例&#xff0c;虽然只是一个网站&#xff0c;但里面可以下载源码&#xff0c;&#xff0c; 注意的是&#xff1a;一定要把demo和GalaSoft.M…

G. Best ACMer Solves the Hardest Problem

Problem - G - Codeforces 有一天&#xff0c;一位优秀的ACMer将离开这个领域&#xff0c;面对新的挑战&#xff0c;就像前辈们所做的一样。他们中的一些人接管了家族企业&#xff0c;一些人在失业的边缘挣扎。一些人有勇气展示自己&#xff0c;成为专业的Ingress玩家&#xff…