RTT中对于IO设备的抽象是很有特点一个地方,是类似ucos,freertos都没有的一个地方。RTT提供了一个简单的IO设备管理框架,希望所有的IO设备驱动都通过这个框架编写,实现统一的管理,目前这框架还相对比较简陋,最重要的是缺少规范文档,随着兼容的设备越来越多,整个框架的规范文档势必需要给出,否则程序将变得越来越不干净。
应用程序通过RT-Thread的设备操作接口获得正确的设备驱动,然后通过这个设备驱动与底层I/O硬件设备进行数据(或控制)交互。RT-Thread提供给上层应用的是一个抽象的设备接口,给下层设备提供的是底层驱动框架。从系统整体位置来说I/O设备模块相当于设备驱动程序和上层应用之间的一个中间层。
I/O设备模块实现了对设备驱动程序的封装。应用程序通过I/O设备模块提供的标准接口访问底层设备,设备驱动程序的升级、更替不会对上层应用产生影响。这种方式使得设备的硬件操作相关的代码能够独立于应用程序而存在,双方只需关注各自的功能实现,从而降低了代码的耦合性、复杂性,提高了系统的可靠性。
现在我们就来看看与rt_device这个类的成员以及相关函数把。 ```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_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); endif if defined(RT_USING_POSIX) const struct dfs_file_ops *fops; struct rt_wqueue wait_queue; endif void *user_data; /**< device private data */ };```
1.parent rt_object的实例化,因为rt_device也是继承于rt_object
2.type设备的类型,RTT中支持以下一些设备类型的定义: 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_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_Unknown /**< unknown device */ };
3.flag rt_device的标志位,有如下取值 ```#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 / define RT_DEVICE_FLAG_INT_TX 0x400 /*< INT mode on Tx / define RT_DEVICE_FLAG_DMA_TX 0x800 /*< DMA mode on Tx /``` 4.open_flag 标志位,有如下取值 ```#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 / define RT_DEVICE_OFLAG_MASK 0xf0f /*< mask of open flag /``` 5.ref_count 引用计数,当device_open调用之后会使得其增加1
6.device_id 好像没被使用
7.rx_indicate 设备收到数据后的回调函数指针
8.tx_complete设备写入数据完成后的回调函数指针
init 设备初始化函数接口
open 设备打开函数接口
close 设备关闭函数接口
read 设备读数据函数接口
write 设备写数据函数接口
control 设备控制函数接口
10.user_data 用户保留数据
rt_device这个类中的所有成员都解释清楚了。
下面便是与rt_device相关的函数。 ```rt_device_t rt_device_find(const char *name);
rt_err_t rt_device_register(rt_device_t dev, const char *name, rt_uint16_t flags); rt_err_t rt_device_unregister(rt_device_t dev);
rt_device_t rt_device_create(int type, int attach_size); void rt_device_destroy(rt_device_t device);
rt_err_t rt_device_init_all(void);
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)); rt_err_t rt_device_set_tx_complete(rt_device_t dev, rt_err_t (tx_done)(rt_device_t dev, void *buffer));
rt_err_t rt_device_init (rt_device_t dev); rt_err_t rt_device_open (rt_device_t dev, rt_uint16_t oflag); rt_err_t rt_device_close(rt_device_t dev); rt_size_t rt_device_read (rt_device_t dev, rt_off_t pos, void buffer, rt_size_t size); rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos, const void buffer, rt_size_t size); rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg);```
这些函数的功能都相当的直白,且实现方式都与thread,或者timer类似一样。
rt_device_register就是把rt_device类添加到对象容器中管理起来。
其他诸如init,open,close,read,write,control基本可以看成是仅仅给出一个抽象接口,需要具体在对应的设备驱动中一一实现。
其实最后看来rt_device其实类似一个接口类,各种设备都应该包含这个接口中的所有函数,并在自身的驱动中重写这些函数。
原作者:yushigengyu
|