猿小A : 小B快开门,我发现了你上一篇讲的一个大bug,哈哈哈。。。
猿小B :你发现什么了。。。
猿小A : 上次你讲的应该是pin设备吧,我仔细研究了一下,并不是所有的驱动都是注册到IO设备管理器中,也有的之注册到了设备驱动层中,像你昨天讲的pin设备。。。
猿小B : 你讲的是对的,可那又怎样呢,构架都是我写的,难免表达会有错误。。。
猿小A : ....
猿小B : 这一篇开始讲一下用的比较多的uart设备吧。。。
猿小A : 接下来是不是该讲讲我发现的问题了,是不?
猿小B :接下来来讨论下,你提出的问题,首先那的确是个问题,对比一下两个sample的代码就会发现,其接口API的提供者并不来源于同一层,先讲一下层的概念,这里的可以理解为4层,每一层其实只是虚化的概念,这里用实体来代替,更好理解一些:
项目工程: PIN应用 Uart应用
应用程序: pin_beep_sample uart_sample.c
I/O设备管理层: 无 device.c
设备驱动框架层: pin.c serial.c
设备驱动层: drv_gpio.c drv_usart.c
也就是真的是有的驱动没有注册到device.c 也就是IO设备管理层,而是通过设备驱动框架层直接应用,like Pin设备。
猿小B:接下来介绍一下uart设备,IO设备管理层对外提供的API接口:
1.查找串口设备
rt_device_t rt_device_find(const char* name);
参数: 描述:
name 设备名称
返回 ————————————
设备句柄 查找到对象设备将返回相应的设备句柄。
2.打开串口设备:rt_err_t rt_device_open(rt_device_t dev,rt_uint16_t oflags);
参数: 描述:
dev 设备句柄
oflags 设备模式标志
返回 ————————————
RT_EOK 设备打开成功
-RT_EBUSY 如果设备注册时指定的参数中包括RT_DEVICE_FLAG_STANDALONE参数,此 设备将不允许重复打开
其它错误码 设备打开失败
oflags参数支持下列取值(可以采用或的方式支持多种取值):
#define RT_DEVICE_FLAG_STREAM 0X040/*流模式*/
#define RT_DEVICE_FLAG_INT_RX 0X100/*中断接收模式*/
#define RT_DEVICE_FLAG_DMA_RX 0x200/*DMA接收模式*/
#define RT_DEVICE_FLAG_INT_TX 0X400/*中断发送模式*/
#define RT_DEVICE_FLAG_DMA_TX 0X800/*DMA发送模式*/
3.控制串口设备:rt_err_t rt_device_control(rt_device_t dev,rt_uint8_t cmd,void* arg);
参数: 描述:
dev 设备句柄
cmd 命令控制字,可取值:RT_DEVICE_CTRL_CONFIG
arg 控制的参数,可取类型:struct serial_configure
返回 ————————
RT_EOK 函数执行成功
-RT_ENOSYS 执行失败,dev为空
其它错误码 执行失败
cmd 和 arg 参数是被限定的参数,只能是一个值和一种类型。
4.发送数据:rt_size_t rt_device_write(rt_device_t dev,rt_off_t pos,const void* buffer,
rt_size_t size);
参数: 描述:
dev 设备句柄
pos 写入数据偏移量,此参数串口设备未使用,默认为0
buffer 内存缓冲区指针,放置要写入的数据
size 写入数据的大小
返回 ——————————
写入数据的实际大小 如果是字符设备,返回大小以字节为单位;
0 需要读取当前线程的errno来判断错误状态
5.设置发送完成回调函数:rt_err_t rt_device_set_tx_complete(rt_device_t dev,rt_err_t (*tx_done)(rt_device_t,void* buffer));
参数: 描述:
dev 设备句柄
tx_done 回调函数指针
返回 ——————————
RT_EOK 设置成功
使用DMA发送模式才会调用这个回调函数
6.设置接收回调函数:rt_err_t rt_device_set_rx_indicate(rt_device_t dev,rt_err_t(*rx_ind)(rt_device_t dev,rt_size_t size));
参数: 描述:
dev 设备句柄
rx_ind 回调函数指针
dev 设备句柄(回调函数参数)
size 缓冲区数据大小(回调函数参数)
返回 ——————————
RT_EOK 设置成功
该回调函数在DMA接收完成和中断接收一个字节的数据时都会被调用,这个很重要,有时候官方文档说的也不是特别清楚。
7.接收数据:rt_size_t rt_device_read(rt_device_t dev,rt_off_t pos,void* buffer,rt_size_t size);
参数: 描述:
dev 设备句柄
pos 数据读取偏移量,块设备中使用,串口设备未使用
buffer 缓冲区指针,读取的数据会被保存在缓冲区中
size 读取数据的大小
返回 ————————————————
读到数据的实际大小 如果是字符设备,返回大小以字节为单位
0 需要读取当前线程的errno来判断错误状态。
一般读取操作配合回调函数来使用为佳,因为在读取之前确保串口缓冲区的确收到了数据,这样可以降低读数据的时间开销及不需要处理无效数据等操作。
8. 关闭串口设备:rt_err_t rt_device_close(rt_device_t dev);
参数: 描述:
dev 设备句柄
返回 ————————
RT_EOK 关闭设备成功
-RT_ERROR 设备已经完全关闭,不能重复关闭设备
其它错误码 关闭设备失败
有打开设备,就会有关闭设备操作,为了降低误操作,退出设备驱动对于资源的占用,等工作,虽然在这里其实没什么太大的意义,她远不如xp一样的灵活,但是该有的理念还是得有的。