RT-thread内核之IO设备管理系统

RT-Thread系统的IO设备管理模块为上层应用提供了一个对设备进行访问的通用抽象接口,而对于下层设备来说则提供了底层设备驱动框架,并通过定义的数据结构对设备信息和底层设备驱动进行管理。从系统整体位置来说I/O设备管理模块相当于底层设备驱动和上层应用之间的一个中间层。

I/O管理模块实现了对设备驱动程序的封装:设备驱动程序的实现与I/O管理模块独立,提高了模块的可移植性。应用程序通过I/O管理模块提供的标准接口访问底层设备,设备驱动程序的升级不会对上层应用产生影响。这种方式使得与设备的硬件操作相关的代码与应用相隔离,双方只需各自关注自己的功能,这降低了代码的复杂性,提高了系统的可靠性。

一、I/O设备管理控制块:在include/rtdef.h中:

typedef struct rt_device *rt_device_t;
/**
 * Device structure
 */
struct rt_device
{
    struct rt_object          parent;                   /**< inherit from rt_object *///内核对象

    enum rt_device_class_type type;                     /**< device type */           //IO设备类型
    rt_uint16_t               flag;                     /**< device flag */           //设备标志
    rt_uint16_t               open_flag;                /**< device open flag */      //设备打开标志  

    rt_uint8_t                ref_count;                /**< reference count */       //索引计数值。设备注册时初始为0,每打开一次加1,每关闭一次减1。主要用于设备多次打开后,要关闭时判断是否完全关闭。
    rt_uint8_t                device_id;                /**< 0 - 255 */               //设备ID 

    /* 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, rt_uint8_t cmd, void *args);                //控制通用接口

    void                     *user_data;                /**< device private data */   //私有数据
};

在以前版本的设备控制块中,还有以下:/* 用于支持电源管理的函数接口 */#ifdef RT_USING_DEVICE_SUSPEND    rt_err_t (*suspend) (rt_device_t dev);                                             //挂起设备    rt_err_t (*resumed) (rt_device_t dev);                                             //还原设备  #endif

从设备控制块,我们可以看到,每个设备对象都会在内核中维护一个设备控制块结构,这种结构是使设备对象继承rt_object基类,然后形成rt_device设备类型。

其中设备类型type为一枚举变量,在include/rtdef.h中定义:

/**
 * device (I/O) class type
 */
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 */          //CAN设备
    RT_Device_Class_RTC,                                /**< RTC device */          //RTC设备
    RT_Device_Class_Sound,                              /**< Sound device */        //音频设备
    RT_Device_Class_Graphic,                            /**< Graphic device */      //图形显示设备
    RT_Device_Class_I2CBUS,                             /**< I2C bus device */      //I2C总线设备
    RT_Device_Class_USBDevice,                          /**< USB slave device */    //USB从设备
    RT_Device_Class_USBHost,                            /**< USB host bus */        //USB主设备
    RT_Device_Class_SPIBUS,                             /**< SPI bus device */      //SPI总线设备
    RT_Device_Class_SPIDevice,                          /**< SPI device */          //SPI接口设备
    RT_Device_Class_SDIO,                               /**< SDIO bus device */     //SDIO总线设备
    RT_Device_Class_PM,                                 /**< PM pseudo device */    //电源管理伪设备
    RT_Device_Class_Pipe,                               /**< Pipe device */         //管道设备
    RT_Device_Class_Portal,                             /**< Portal device */       //传输设备
    RT_Device_Class_Miscellaneous,                      /**< Miscellaneous device *///其他设备
    RT_Device_Class_Unknown                             /**< unknown device */      //未知设备
};

二、I/O设备管理函数接口:在src/device.c中

注册设备:
rt_err_t rt_device_register(rt_device_t dev,               //设备句柄
                            const char *name,              //设备名称
                            rt_uint16_t flags);            //设备标志
一个设备能够被上层应用访问前,需要先把这个设备注册到系统中,并添加一些相应的属性。这些注册的设备均可以通过设备名,采用“查找设备口”的方式来查找,从而获得该设备控制块(或设备句柄)。
flags参数支持下列参数(可以采用或的方式支持多种参数):
#define RT_DEVICE_FLAG_DEACTIVATE       0x000           /**< device is not not initialized *///未初始化设备
#define RT_DEVICE_FLAG_RDONLY           0x001           /**< read only */                    //只读设备
#define RT_DEVICE_FLAG_WRONLY           0x002           /**< write only */                   //只写设备
#define RT_DEVICE_FLAG_RDWR             0x003           /**< read and write */               //读写设备
#define RT_DEVICE_FLAG_REMOVABLE        0x004           /**< removable device */             //可移除设备
#define RT_DEVICE_FLAG_STANDALONE       0x008           /**< standalone device */            //独立设备
#define RT_DEVICE_FLAG_ACTIVATED        0x010           /**< device is activated */          //已激活设备
#define RT_DEVICE_FLAG_SUSPENDED        0x020           /**< device is suspended */          //挂起设备
#define RT_DEVICE_FLAG_STREAM           0x040           /**< stream mode */                  //设备处于流模式
#define RT_DEVICE_FLAG_INT_RX           0x100           /**< INT mode on Rx */               //设备处于中断接收模式
#define RT_DEVICE_FLAG_DMA_RX           0x200           /**< DMA mode on Rx */               //设备处于DMA接收模式
#define RT_DEVICE_FLAG_INT_TX           0x400           /**< INT mode on Tx */               //设备处于中断发送模式
#define RT_DEVICE_FLAG_DMA_TX           0x800           /**< DMA mode on Tx */               //设备处于DMA发送模式
设备流模式RT_DEVICE_FLAG_STREAM参数用于向串口终端输出字符串:当输出的字符是“\n”时,自动在前面补一个“\r”做分行。警告:应当避免重复注册已经注册的设备,以及注册已有名字的设备驱动程序。

卸载设备:
rt_err_t rt_device_unregister(rt_device_t dev);
将设备从设备系统中卸载,被卸载的设备将不能再通过“查找设备接口”被查找到。注:卸载设备并不会释放设备控制块所占用的内存。
初始化所有设备:
rt_err_t rt_device_init_all(void);
初始化所有注册到设备对象管理器中的未初始化的设备。注:自版本1.2.x,该函数不再需要在系统初始化调用,因为在上层应用中打开设备时会进行相应设备初始化。

初始化设备:
rt_err_t rt_device_init(rt_device_t dev);
当一个设备初始化完成后它的flags域中的RT_DEVICE_FLAG_ACTIVATED应该被置位。如果设备的flags域已经是RT_DEVICE_FLAG_ACTIVATED,调用这个接口将不再重复做初始化。返回dev->init函数返回值RT_EOK。注:在设备打开时rt_device_open时会调用该函数先初始化需要打开的设备。
查找设备:
rt_device_t rt_device_find(const char *name);
使用这个函数接口时,系统会在设备对象类型所对应的对象容器中根据设备名称遍历寻找设备对象,然后返回该设备句柄,如果没有找到相应的设备对象,则返回RT_NULL。
打开设备:
rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag);
根据设备控制块来打开设备,其中访问模式oflags支持以下列表中的参数:
#define RT_DEVICE_OFLAG_CLOSE           0x000           /**< device is closed */ //已关闭模式
#define RT_DEVICE_OFLAG_RDONLY          0x001           /**< read only access */ //只读模式访问
#define RT_DEVICE_OFLAG_WRONLY          0x002           /**< write only access *///只写模式访问
#define RT_DEVICE_OFLAG_RDWR            0x003           /**< read and write */   //读写模式访问
#define RT_DEVICE_OFLAG_OPEN            0x008           /**< device is opened */ //已打开模式
返回dev->open函数返回值。注: 如果设备flags域包含RT_DEVICE_FLAG_STANDALONE参数,将不允许重复打开。

关闭设备:
rt_err_t rt_device_close(rt_device_t dev);
根据设备控制块来关闭设备。返回dev->close函数返回值。
读设备:
rt_size_t rt_device_read(rt_device_t dev,                     //设备句柄
                         rt_off_t    pos,                     //待读取数据的偏移量
                         void       *buffer,                  //读取的数据存放地址
                         rt_size_t   size)                    //读取数据的大小
根据设备控制块来读取设备。根据底层驱动的实现,通常这个接口并不会阻塞上层应用线程。
返回读到数据的实际大小(以字节为单位);如果返回0,则需要读取当前线程的errno来判断错误状态。

写设备:
rt_size_t rt_device_write(rt_device_t dev,                     //设备句柄
                          rt_off_t    pos,                     //待写入数据的存放偏移量
                          const void *buffer,                  //待写入数据源地址
                          rt_size_t   size)                    //待写入数据大小
根据设备控制块来写入设备。根据底层驱动的实现,通常这个接口也不会阻塞上层应用线程。
返回写入数据的实际大小(以字节为单位);如果返回0,则需要读取当前线程的errno来判断错误状态。
注: 在RT-Thread的块设备中,从1.0.0版本开始,rt_device_write()接口的pos、size参数按照以块为单位。0.3.x以前的版本则按字节为单位。
控制设备:
rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void *arg);
dev:设备句柄
cmd:命令控制字,这个参数通常与设备驱动程序相关
arg:控制的参数
返回dev->control函数返回值。

设置数据接收指示回调函数:
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))//接收回调函数
设置一个回调函数,当硬件设备收到数据时回调以通知用程序有数据到达,但一般只是进行些简单的操作,如发送信号量,而让另一个接收线程来处理接收到的数据
在调用这个函数时,回调函数rx_ind由调用者提供。当硬件设备接收到数据时,会回调这个函数并把收到的数据长度放在size参数中传递给上层应用。上层应用线程应在收到指示后,立刻从设备中读取数据。返回RT_EOK。

设置发送完成指示回调函数:
rt_err_trt_device_set_tx_complete(rt_device_t dev,     //设备句柄
    rt_err_t (*tx_done)(rt_device_t dev, void *buffer))//发送回调函数在上层应用调用rt_device_write写入数据时,如果底层硬件能够支持自动发送,那么上层应用可以设置一个回调函数。这个回调函数会在底层硬件给出的发送完成后(例如DMA传送完成或FIFO已经写入完毕产生完成中断时)被调用。
调用这个函数时,回调函数tx_done参数由调用者提供,当硬件设备发送完数据时,由驱动程序回调这个函数并把发送完成的数据块地址buffer做为参数传递给上层应用。上层应用(线程)在收到指示时应根据发送buffer的情况,释放buffer内存块或将其做为下一个写数据的缓存。返回RT_EOK。
时间: 2024-10-08 10:27:13

RT-thread内核之IO设备管理系统的相关文章

RT thread 设备驱动之串口设备

本文以stm32f4xx平台介绍串口驱动,主要目的是: 1.RTT中如何编写中断处理程序 2.如何编写RTT设备驱动接口代码 3.了解串行设备的常见处理机制 所涉及的主要源码文件有:usart.c,usart.h,serial.c,serial.h 一.RTT的设备驱动程序概述 编写uart的驱动程序,首先需要了解RTT的设备框架,这里以usart的驱动来具体分析RTT的IO设备管理.注:参考<RTT实时操作系统编程指南> I/O设备管理一章. 我们可以将USART的硬件驱动分成两个部分,如下

解决方案--java执行cmd命令ProcessBuilder--出错Exception in thread "main" java.io.IOException: Cannot run program "dir d:\": CreateProcess error=2(xjl456852原创)

当我尝试在java中通过ProcessBuilder运行window的cmd命令时出现错误: public static void main(String [] args) throws IOException { ProcessBuilder builder = new ProcessBuilder(); Process process = builder.command("dir d:\\").start(); InputStream inputStream = process.g

linux内核文件IO的系统调用实现分析(open)

http://blog.chinaunix.net/uid-23969156-id-3086824.html 1.          引言      从事Linux环境工作2年有余,一直懵懵懂懂,1年前拜读了<莱昂氏UNIX源代码分析>一书,感觉自己的学习道路漫漫且修远.最近受chinaunix的精华文帖启发,拟将近来的部分内核调用分析笔记拿出来与各前辈先进共同探讨学习,以壮个人学习之路.      本部分主要讲述的是文件I/O操作的2.6.11内核版本实现,包括了主要的数据结构.宏定义和函数

spark程序异常:Exception in thread &quot;main&quot; java.io.IOException: No FileSystem for scheme: hdfs

命令: java -jar myspark-1.0-SNAPSHOT.jar myspark-1.0-SNAPSHOT.jar hdfs://single:9000/input/word.txt hdfs://single:9000/output/out1 错误信息: .......... 14/11/23 06:14:18 INFO SparkDeploySchedulerBackend: Granted executor ID app-20141123061418-0011/0 on hos

RT Thread学习历程(1):串口乱码问题

因为学习实时系统,最近接触到RT Thread. 把RT Thread官网上的示例代码烧录到STM32的板子上之后,在串口软件上接收到的全是乱码,一开始以为是串口软件的问题,换了2个软件之后情况都一样,最后发现是晶振的问题,我用的是STM32F407VGT6,晶振要设为8MHz,代码相应的设置晶振的部分也要修改.

IT 资产管理系统/设备管理系统 B/S 结构

IT 资产管理系统/设备管理系统 企业永远在面临着--追踪一个动态的资产,资产天天都在变,如果用手工统计是跟不上的.设备的管理不规范,到底谁领用了设备,设备在哪里成为一个企业的一大困惑.这些难题让企业的IT领导工作难上加难. 同时企业也面临一系列资产管理的具体问题:如何更好地利用现有终端设备?如何更好地利用现有网络设备?到底现在库存里头还有多少设备?现在设备够用吗?需要买新的吗?有多少设备已经报废了?企业买了哪些软件?这些软件在哪?某一个厂家的设备好不好用,返修率高吗?这些年来的资产投入有多大?

spark运行java-jar:Exception in thread &quot;main&quot; java.io.IOException: No FileSystem for scheme: hdfs

今天碰到的一个 spark问题,困扰好久才解决 首先我的spark集群部署使用的部署包是官方提供的 spark-1.0.2-bin-hadoop2.tgz 部署在hadoop集群上. 在运行java jar包的时候使用命令 java -jar chinahadoop-1.0-SNAPSHOT.jar  chinahadoop-1.0-SNAPSHOT.jar  hdfs://node1:8020/user/ning/data.txt /user/ning/output 出现了如下错误 14/08

设备管理系统对企业的重要性

1.设备管理系统的背景分析 设备管理系统是企业内部的信息管理系统,是连接企业内部各生产部门的桥梁与纽带,起着核心作用.目前企业设备自动化管理水平不是很高.大多数设备管理办法是设备的采购进来以后,将设备的基本情况和相关信息登记存档,然后将档案存档.以后的档案基本就没人维护,如设备修改.删除情况.设备的当前运行状态等信息本不会呈现在管理工作人员面前,由于散乱.复杂.查找和整理不便,即设备跟踪信息不能及时体现在设备的档案上.某些企业采用专门人工整点,对设备的跟踪信息即使能记录在案,但无形中增加了繁重的

[Nutch]问题解决:Exception in thread &quot;main&quot; java.io.IOException: Job failed

1. 问题描述 在运行Nutch的时候会出现如下异常: Exception in thread "main" java.io.IOException: Job failed! 2. 问题原因 nutch-default.xml中的plugin.folders的配置问题. 3. 问题解决 在配置plugin目录的时候,一定要使用绝对路径. <property> <name>plugin.folders</name> <value>C:/Nu