设备驱动模型
嵌入式软件通常需要操作各类外设(片内、片外),而外设的种类、操作方法纷繁复杂。
OneOS在各类外设的基础上抽象出了设备驱动模型,有效提高了代码可复用性、可移植性,模块分层解耦,降低了各层的开发难度。
设备驱动整体思想:
下层向上层提供统一的访问接口
分层设计,屏蔽硬件差异
每一层只跟其相邻的层建立联系
设备驱动模型分为:
系统调用接口、设备管理层、设备框架层、设备驱动层
系统调用接口
系统调用提供统一的 API 接口
接口 | 说明 |
---|---|
os_device_find() | 查找设备 |
os_device_open() | 打开设备 |
os_device_read_block() | 读取数据(阻塞) |
os_device_read_nonblock() | 读取数据(非阻塞) |
os_device_write_block() | 写入数据(阻塞) |
os_device_write_nonblock() | 写入数据(非阻塞) |
os_device_control() | 控制设备 |
os_device_close() | 关闭设备 |
os_device_find
该函数根据设备名查找对应的设备,函数原型如下:
os_device_t *os_device_find(const char *name);
参数 | 说明 |
---|---|
name | 设备名(uart1,i2c1,spi1 等) |
返回 | 说明 |
设备指针 | 成功返回对应的设备指针 |
OS_NULL | 没有找到指定的设备 |
os_device_open
该函数用于打开设备,第一次打开设备会调用设备初始化接口,函数原型如下:
os_err_t os_device_open(os_device_t *dev);
参数 | 说明 |
---|---|
dev | 设备指针 |
返回 | 说明 |
OS_EOK | 设备打开成功 |
其他错误码 | 设备打开失败 |
os_device_read_block
该函数用于从设备中阻塞读取数据,函数原型如下:
os_size_t os_device_read_block(os_device_t *dev, os_off_t pos, void *buffer, os_size_t size);
参数 | 说明 |
---|---|
dev | 设备指针 |
pos | 读取数据偏移量(字符设备,单位是 字节;块设备,单位是 块) |
buffer | 缓冲区指针,读取的数据将会被保存在缓冲区中 |
size | 读取数据的大小(字符设备,单位是 字节;块设备,单位是 块) |
返回 | 说明 |
大于 0 | 读到数据的实际大小(字符设备,单位是 字节;块设备,单位是 块) |
小于 0 | 错误码 |
如果设备有数据可读,函数立即返回,数据被读取到 buffer 中,返回值为实际读取的数据量。
如果设备没有准备好数据,读线程会睡眠阻塞,直到数据可读才被唤醒、返回。
os_device_read_nonblock
该函数用于从设备中非阻塞读取数据,函数原型如下:
os_size_t os_device_read_nonblock(os_device_t *dev, os_off_t pos, void *buffer, os_size_t size);
参数 | 说明 |
---|---|
dev | 设备指针 |
pos | 读取数据偏移量(字符设备,单位是 字节;块设备,单位是 块) |
buffer | 缓冲区指针,读取的数据将会被保存在缓冲区中 |
size | 读取数据的大小(字符设备,单位是 字节;块设备,单位是 块) |
返回 | 说明 |
大于 0 | 读到数据的实际大小(字符设备,单位是 字节;块设备,单位是 块) |
等于 0 | 设备没有数据可读 |
小于 0 | 错误码 |
如果设备有数据可读,函数立即返回,数据被读取到 buffer 中,返回值为实际读取的数据量。
如果设备没有准备好数据,函数立即返回,返回值为0。
os_device_write_block
该函数用于向设备中阻塞写入数据,函数原型如下:
os_size_t os_device_write_block(os_device_t *dev, os_off_t pos, const void *buffer, os_size_t size);
参数 | 说明 |
---|---|
dev | 设备指针 |
pos | 写入数据偏移量(字符设备,单位是 字节;块设备,单位是 块) |
buffer | 内存缓冲区指针,放置要写入的数据 |
size | 写入数据的大小(字符设备,单位是 字节;块设备,单位是 块) |
返回 | 说明 |
大于 0 | 写入数据的实际大小(字符设备,单位是 字节;块设备,单位是 块) |
小于 0 | 错误码 |
如果设备有空间可写,buffer 中的数据写入设备,函数立即返回,返回值为实际写入的数据量。
如果设备没有空间可写,写线程会睡眠阻塞,直到有空间可写才被唤醒,返回实际写入的数据量。
os_device_write_nonblock
该函数用于向设备中非阻塞写入数据,函数原型如下:
os_size_t os_device_write_nonblock(os_device_t *dev, os_off_t pos, const void *buffer, os_size_t size);
参数 | 说明 |
---|---|
dev | 设备指针 |
pos | 写入数据偏移量(字符设备,单位是 字节;块设备,单位是 块) |
buffer | 内存缓冲区指针,放置要写入的数据 |
size | 写入数据的大小(字符设备,单位是 字节;块设备,单位是 块) |
返回 | 说明 |
大于 0 | 写入数据的实际大小(字符设备,单位是 字节;块设备,单位是 块) |
等于 0 | 设备没有空间可写 |
小于 0 | 错误码 |
如果设备有空间可写,buffer 中的数据写入设备,函数立即返回,返回值为实际写入的数据量。
如果设备没有空间可写,函数立即返回,返回值为0。
os_device_control
该函数用于对设备进行配置,如串口波特率、spi工作模式等参数,函数原型如下:
os_err_t os_device_control(os_device_t *dev, int cmd, void *arg);
参数 | 说明 |
---|---|
dev | 设备指针 |
cmd | 命令控制字,可选值由具体驱动决定 |
arg | 控制的参数,可选值由具体驱动决定 |
返回 | 说明 |
OS_EOK | 函数执行成功 |
OS_ENOSYS | 执行失败,设备不支持 control 接口 |
其他错误码 | 执行失败 |
os_device_close
该函数用于关闭设备,函数原型如下:
os_err_t os_device_close(os_device_t *dev);
参数 | 说明 |
---|---|
dev | 设备指针 |
返回 | 说明 |
OS_EOK | 关闭设备成功 |
OS_ERROR | 设备已经完全关闭,不能重复关闭设备 |
其他错误码 | 关闭设备失败 |
设备管理层
设备管理层实现了对设备驱动程序的封装,向上对接系统调用接口。
设备框架层
设备驱动框架层是对同类硬件设备驱动的抽象,将不同厂家的同类硬件设备驱动中相同的部分抽取出来,将不同部分留出接口,由驱动程序实现。
设备驱动层
设备驱动层是一组驱使硬件设备工作的程序,实现访问硬件设备的功能,它负责创建和注册设备。