/**
* Device structure
*/
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
void *user_data; /**< device private data */
};
一、核心设计思想
RT-Thread设备模型基于面向对象思想构建,struct rt_device
作为所有设备的基类,通过继承机制实现设备驱动的统一管理。其设计融合了内核对象模型和多态特性,使不同设备(如串口、GPIO、I2C)可通过标准化接口接入系统。
二、成员字段详解
-
继承关系与内核对象 (
parent
)parent
成员继承自struct rt_object
,赋予设备内核对象属性(如名称、类型标识),实现设备树管理和资源调度。- 示例:PIN设备通过
rt_device_pin
结构体扩展基类,添加ops
指针实现GPIO操作。
-
设备类型标识 (
type
)- 枚举类型
rt_device_class_type
定义设备类别(如RT_Device_Class_Char
字符设备、RT_Device_Class_Miscellaneous
杂类设备),用于系统动态识别设备功能。 - 典型场景:串口设备标记为
RT_Device_Class_Char
,块设备(如SD卡)标记为RT_Device_Class_Block
。
- 枚举类型
-
设备状态控制 (
flag
/open_flag
/ref_count
)flag
:设备全局标志,如RT_DEVICE_FLAG_RDWR
表示可读写,RT_DEVICE_FLAG_INT_RX
使能中断接收。open_flag
:记录设备打开模式(如O_RDONLY
),控制并发访问权限。ref_count
:引用计数器,确保设备在多次open()
/close()
调用后资源正确释放。
-
操作接口实现 (
ops
与传统函数指针)- 条件编译设计:通过
RT_USING_DEVICE_OPS
宏选择使用ops
结构体或独立函数指针,增强代码灵活性。#ifdef RT_USING_DEVICE_OPS const struct rt_device_ops *ops; // 统一操作集 #else rt_err_t (*init)(rt_device_t dev); // 独立函数指针 rt_err_t (*open)(rt_device_t dev, rt_uint16_t oflag); // ...其他函数指针 #endif
- 多态体现:例如,串口设备的
write()
实现数据发送,而PIN设备的write()
控制GPIO电平。
- 条件编译设计:通过
-
异步通信机制 (
rx_indicate
/tx_complete
)rx_indicate
:数据到达回调(如串口接收中断触发应用层读取)。tx_complete
:发送完成通知(如DMA传输结束释放缓冲区)。- 应用场景:在CAN总线驱动中,这两个回调用于实现高效的双工通信。
-
扩展性与私有数据 (
user_data
)user_data
允许设备保存驱动私有数据(如硬件寄存器地址、DMA配置),实现业务逻辑与框架解耦。- 示例:STM32的UART驱动通过
user_data
存储USART_TypeDef
指针,操作时直接访问硬件寄存器。
三、设备模型运作流程
-
设备注册
调用rt_device_register()
将设备挂载到内核,关键步骤包括:- 设置
parent.type
标识设备类型 - 绑定
ops
或函数指针实现操作接口
- 设置
-
设备操作
通过标准化接口访问设备:rt_device_open(dev, RT_DEVICE_FLAG_RDWR); // 打开设备 rt_device_write(dev, 0, buffer, size); // 写入数据 rt_device_control(dev, RT_DEVICE_CTRL_RESET, NULL); // 发送控制命令
底层驱动根据设备类型实现具体行为,如串口的
write()
触发DMA传输,而GPIO的write()
直接操作端口寄存器。