I/O设备管理
IO设备管理层框架从下往上一次共三层:设备驱动层 –> 设备驱动框架层 –> IO设备管理层
IO设备框架向下操作硬件,向上提供统一的一套接口给应用程序调用,使得应用程序不用关系具体的硬件操作,更换硬件执行修改设备驱动操作硬件相关的代码。
- IO设备管理层
1.实现了对设备驱动程序的封装,使程序完全脱离了具体的硬件。
2.提供给应用程序的接口:
1 | /************** device.c *******************/ |

3.提供给驱动程序实现的:
1 | // 驱动程序实例化一个设备对象,并通过此接口注册到IO设备管理层 |
- 设备框架层
1.对同类硬件设备驱动做抽象:将不同厂家的同类硬件设备驱动中相同的部分抽取出来。
2.将不同的部分留出接口,由驱动程序实现。
3.负责创建和注册IO设备(就是设备框架层将不同部分留出的接口,设备驱动层需要去实现这些接口,注册给设备框架层使用)。
4.通过IO管理层提供的接口,注册一个串口设备到IO管理层:
5.设备驱动框架是对同类设备的抽象(这一层可以没有),例如:显示设备和ssd1306的关系,显示设备可以是ssd1306或者lcd显示屏,但它们都属于显示设备都能够显示一个字母、显示一个数字。
设备框架层就是对同类设备的抽象,同类设备的一些共性。
4.不同芯片厂家的串口操作方式是不一样的,但他们肯定都有putc、getc、config的这些功能。
1 | /*************** serial.c ******************/ |

对于逻辑操作简单的设备,可以跳过设备框架层,直接注册到IO设备管理层,将设备框架层必要的东西直接在设备驱动层实现。
- 设备驱动层
通常是直接调用厂家提供的操作硬件寄存器函数
1.是一组直接驱使硬件工作的程序,实现访问硬件提供的功能。
2.设备框架层提供的接口,注册一个串口设备到设备框架层。
硬件相关的:配置具体的外设、读、写等,硬件的功能实现函数。
这些硬件相关的操作函数都将被,驱动层使用注意不是调用(在驱动层封装成硬件设备对象的方法,再由驱动层注册到IO设备层),所以IO设备驱动层对设备对象的操作相当于直接调用了这些函数。
以上的这些层都是为应用程序服务的,宏观上这些层都可以叫做驱动,驱动只提供方法不会操作硬件,只有应用程序里面才会调用这些设备对象的方法操作硬件,可能进行设备初始化、打开、关闭、读、写,根据设备提供的方法不一样不一定所有的设备都有这些方法。
1 | /******************** drv_uart.c **************************/ |

- 应用程序
例如shell.c是一个应用程序,它和用户直接交互
应用程序:实现产品具体功能的代码,与用户交互的、显示用的、一个触摸的键盘,分别获取用户的输入做出反应、输出信息给用户看、得到用户的输入。
1 | /******************** shell.c ****************************/ |
从上面的代码可以看出,只有应用程序才会去操作硬件,驱动程序只提供操作硬件的方法。
小结:
分层思想的原则:
1.确定本层的职责,搞清承上启下的对象是谁。
2.实现本层职责时,提供好给上层调用的接口和对象。
3.如果超出本层职责(操作过于细节),那么提供注册函数给自己的下层调用,让下层提供一个实现具体细节的方法给自己使用。
4.一般方法和信息都是通过对象的形式在层与层之间传递。
- I/O设备对象
1 | // 设备类型 |
常见设备:字符设备:允许非结构数据传输,串行传输一次一个字节,块设备:每次传输一个数据块,如512byte,数据块是硬件强制性的,通常情况下操作,先读一个块数据,改变之中的一部分数据然后再写回去。
- 访问IO设备

设备的多种打开方式:
1 |
如果上层应用程序需要设置设备的接收回调函数,则必须以 RT_DEVICE_FLAG_INT_TX 或者 RT_DEVICE_FLAG_DMA_RX 的方式打开设备,否则不会回调函数。
- 打开IO设备
1 | // 该函数主要执行 dev->open(); |

rt_device_open() 和 rt_device_close() 需成对使用。
- 控制设备
1 | // 该函数主要执行 dev->control(); |
- 设备读写
1 | // pos:根据设备的不同有不同的意义,读串口设备底层会忽略这个参数,pos参数没有一样 |
- 数据收发回调
接收回调:
1 | // 设置接收数据回调:设置一个回调函数,当硬件设备接收到数据时, |
发送回调:
1 | // 设置发送完数据回调:当硬件设备发送完数据,驱动程序回调这个函数并把发送完成的数据块地址buffer作为参数传递给上层应用, |
上面两个函数都是应用程序注册给底层硬件驱动回调用的,相当于是底层驱动异步通知应用程序执行的操作结果。是一种层与层之间的沟通方式,和底层注册到上层类似。
本章小结:
1.没有提供驱动的设备,或者自己另外需要添加的设备,需要根据驱动框架自己实现设备的方法。
2.动态创建的设备销毁时要记得释放设备控制块占用的内存。
3.IO设备在应用程序的写使用示例:
1 | int xxx_writedata(uint8_t* buffer, size_t buff_size) |
- 本文作者: 龙兄嵌入式
- 本文链接: https://hexo.880755.xyz/1970/01/01/zblog/download/79.IO设备管理/