RT-thread对象模型之device

RT-thread对象模型之device
1

RT-thread中采用了对容器的方式来存储系统中的各种类型的对象

今天来解析一下device对象,device对象是对系统中设备的一种抽象,同时也是从所有对象的基类object派生而来,定义的数据结构为:

struct rt_device
{
 struct rt_object parent;                        /**< inherit from rt_object                     */

 enum rt_device_class_type type;                 /**< device type                                */
 rt_uint16_t flag, open_flag;                    /**< device flag and device open flag           */

 /* 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);

#ifdef RT_USING_DEVICE_SUSPEND
 rt_err_t (*suspend) (rt_device_t dev);
 rt_err_t (*resumed) (rt_device_t dev);
#endif

 void *user_data;                                /**< device private data                        */
};

可以看出其结构中最前面的字段为struct rt_object parent,说明其也是一个rt_object 对象,这个相当于面向对象中的继承关系

同时在内部还定义了一套统一操作函数,类似于linux中把所有的设备操作看成文件操作一样,linux中也有一套操作文件的接口

device只是一种抽象,如果落实到具体的一种设备上时,根据继承的原理,只要从抽像的device设备派生就可以了,比如系统中有串口设备,则可以定义成如下的结构表示串口设备:

struct rt_at91serial
{
 struct rt_device parent;

 struct rt_at91serial_hw* hw_base;
 rt_uint16_t peripheral_id;
 rt_uint32_t baudrate;

 /* reception field */
 rt_uint16_t save_index, read_index;
 rt_uint8_t  rx_buffer[RT_UART_RX_BUFFER_SIZE];
};

如果你的设备有两个串口,则只要创建两个串口实例就ok了,比如:

#ifdef RT_USING_UART1
struct rt_at91serial serial1;
#endif
#ifdef RT_USING_UART2
struct rt_at91serial serial2;
#endif

但是C语言中不支持构造和析构函数,所以在创建实例的时候,不会自动调用到初始化函数,所以在创建完两个串口实例后,需要初始化一把,主要是把真正的处理函数挂接到统一的处理函数上,相当于是实现了面向对象中的多态,当上层应用程序调用统一的open、read、write接口时,实际上会调用到真的设备处理函数上,见下面的初始化函数:

rt_err_t rt_hw_serial_init()
{
 rt_device_t device;

#ifdef RT_USING_UART1
 device = (rt_device_t) &serial1;

 /* init serial device private data */
 serial1.hw_base   = (struct rt_at91serial_hw*)AT91C_BASE_US0;
 serial1.peripheral_id  = AT91C_ID_US0;
 serial1.baudrate  = 115200;

 /* set device virtual interface */
 device->init  = rt_serial_init;
 device->open  = rt_serial_open;
 device->close  = rt_serial_close;
 device->read  = rt_serial_read;
 device->write  = rt_serial_write;
 device->control = rt_serial_control;

 /* register uart1 on device subsystem */
 rt_device_register(device, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
#endif

#ifdef RT_USING_UART2
 device = (rt_device_t) &serial2;

 serial2.hw_base   = (struct rt_at91serial_hw*)AT91C_BASE_US1;
 serial2.peripheral_id  = AT91C_ID_US1;
 serial2.baudrate  = 115200;

 /* set device virtual interface */
 device->init  = rt_serial_init;
 device->open  = rt_serial_open;
 device->close  = rt_serial_close;
 device->read  = rt_serial_read;
 device->write  = rt_serial_write;
 device->control = rt_serial_control;

 /* register uart2 on device subsystem */
 rt_device_register(device, "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
#endif

 return RT_EOK;
}

所有到这里,一个设备的驱动程序编写可以转化实现以下几个处理函数

 device->init  = rt_serial_init;
 device->open  = rt_serial_open;
 device->close  = rt_serial_close;
 device->read  =rt_serial_read;
 device->write  = rt_serial_write;
 device->control = rt_serial_control

这也是RT-thread编写驱动程序的一个框架,其应该是借鉴了linux中的实现方式

linux设备驱动程序这本书没有怎么看过,找个时间要好好的研究一下!


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值