在开篇还是要感谢RT-Thread开发团队,感谢他们开发出这么优秀的物联网操作系统,当听到国产的操作系统,总是有一种自豪感。
在学习潘多拉开发板的第一个关于RT-Thread的例程时候,在程序里遇到**rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); rt_pin_write(LED_PIN, PIN_LOW);**函数。然后就像刨根问底,经过查阅资料,发现这是RT-Thread操作系统中PIN设备模型的内容。
首先说明一点,PIN设备在RT-Thread操作系统中是隶属于I/O设备模型,从PIN设备控制块的定义就可以看出来:
/* pin device and operations for RT-Thread */
struct rt_device_pin
{
struct rt_device parent;
const struct rt_pin_ops *ops;
};
因此,PIN设备也遵循I/O设备模型框架,具体框架如下图所示
一、设备对象继承关系
1、如下图所示,RT-Thread各控制块之间存在继承关系:
2、PIN设备控制块详解
/**
* 双向链表
*/
struct rt_list_node
{
struct rt_list_node *next; /**< 指向直接前去节点 */
struct rt_list_node *prev; /**< 指向直接后继节点 */
};
typedef struct rt_list_node rt_list_t; /**< 双向链表节点指针 */
/**
* 内核对象控制块
*/
struct rt_object
{
char name[RT_NAME_MAX]; /**< 内核对象名字 */
rt_uint8_t type; /**< 内核对象类型 */
rt_uint8_t flag; /**< 内核对象参数 */
#ifdef RT_USING_MODULE
void *module_id; /**< 应用模块id */
#endif
rt_list_t list; /**< 内核对象管理链表 */
};
typedef struct rt_object *rt_object_t; /**< Type for kernel objects. */
/**
* 内核对象类型取值
*/
enum rt_object_class_type
{
RT_Object_Class_Thread = 0, /**< 对象为线程 */
RT_Object_Class_Semaphore, /**< 对象为信号量 */
RT_Object_Class_Mutex, /**< 对象为互斥锁 */
RT_Object_Class_Event, /**< 对象为事件 */
RT_Object_Class_MailBox, /**< 对象为邮箱 */
RT_Object_Class_MessageQueue, /**< 对象为消息队列 */
RT_Object_Class_MemHeap, /**< 对象为内存堆 */
RT_Object_Class_MemPool, /**< 内存池 */
RT_Object_Class_Device, /**< 设备驱动 */
RT_Object_Class_Timer, /**< 时钟 */
RT_Object_Class_Module, /**< 模块 */
RT_Object_Class_Unknown, /**< 位置对象类型 */
RT_Object_Class_Static = 0x80 /**< 标识是否为系统的对象 */
};
/**
* 设备控制块
*/
struct rt_device
{
struct rt_object parent; /**< 继承 rt_object 结构体 */
enum rt_device_class_type type; /**< 设备类型,USB、CAN等设备,这是一个枚举*/
rt_uint16_t flag; /**< 参数 */
rt_uint16_t open_flag; /**< 设备开启标志,只读、读写等,具体在头文件rtdef中有定义,下面也有罗列 */
rt_uint8_t ref_count; /**< 设备引用计数 */
rt_uint8_t device_id; /**<设备ID号 0 - 255 */
/* device call back */
rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);//设备接收数据时,会调用该成员函数,该成员函数是通过rt_device_set_rx_indicate()函数进行注册。像串口的接收函数,网卡的接收函数等都会注册到该函数成员变量中
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;//POSIX文件和目录操作接口
struct rt_wqueue wait_queue;
#endif
void *user_data; /**< 设备的私有数据 */
};
/**
* device flags defitions
*/
#define RT_DEVICE_FLAG_DEACTIVATE 0x000 /**< 未初始化设备 */
//
#define RT_DEVICE_FLAG_RDONLY 0x001 /**< 只读方式 */
#define RT_DEVICE_FLAG_WRONLY 0x002 /**< 只写方式 */
#define RT_DEVICE_FLAG_RDWR 0x003 /**< 读写方式 */
#define RT_DEVICE_FLAG_REMOVABLE 0x004 /**< 可移除设备 */
#define RT_DEVICE_FLAG_STANDALONE 0x008 /**< 独立设备 */
#define RT_DEVICE_FLAG_ACTIVATED 0x010 /**< 已激活设备 */
#define RT_DEVICE_FLAG_SUSPENDED 0x020 /**< 已挂起设备 */
#define RT_DEVICE_FLAG_STREAM 0x040 /**<