Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
串口驱动
rt-thread 驱动篇 之 serial v1 v2 和 X
10.00
发布于 2022-04-10 16:10:25 浏览:5035
订阅该版
[tocm] ## 前言 本周笔者花了好多天的时间,计划从多个方面对串口驱动做个比较。下面就从以下几个角度做个对比测试。 1. 工作模式对照 2. close open 测试 3. poll 发送测试 4. flush 支持测试 5. 非阻塞收发测试 6. 阻塞收发测试 7. 回环测试数据丢失率 其它未测试项:stream 支持,因为 v1 v2 只有 poll 模式支持, serialX 可以全模式支持,这一项未进行对比。 ### 测试环境 - rt-thread 4.1.0 - STM32F429-ATK-APOLLO - 串口收发缓存均设定 128 字节 #### 工作模式对照 | 版本 | poll收发 | 阻塞/非阻塞 | 驱动层缓存 | DMA支持 | STREM 支持 | | :--: | :------: | :---------: | :--------: | :-----: | :--------: | | v1 | Y | - | - | Y | 仅poll | | v2 | Y | * | Y | Y | 仅poll | | X | Y | Y | Y | Y | 全模式 | > \* v2 对阻塞概念的认识,仅认为是降低 cpu 耗用。 #### close & open 测试 测试过程: 1. 先用 poll 模式打开,打开失败直接返回;成功输出 "POLL modeopen opened\n" 。 2. 输出 "CLOSE & REOPEN\n" 。关闭串口设备,再用中断收发模式打开,打开失败直接返回;成功输出 "INT mode opened\n" 。 3. 最后循环关闭打开 1百万次。打开失败直接返回。 4. 测试通过,使用 poll 模式打开串口设备,并输出 "REOPEN successfull\n"。准备进入下一项测试。 | 版本 | v1 | v2 | X | | :------: | :--: | :--: | :--: | | 测试结果 | 通过 | 通过 | 通过 | #### poll 发送测试 用 poll 模式打开串口,发送若干数据。 | 版本 | v1 | v2 | X | | :------: | :--: | :--: | :--: | | 测试结果 | 通过 | 通过 | 通过 | #### flush 支持测试 如果没有 flush ,驱动缓存的数据可能没有完全输出到外设,这个时候 close 设备可能出现丢失部分数据。 使用 flush 的目地就是保证驱动层缓存数据完全输出到外设,之后对设备的任何操作不会影响之前的数据。 | 版本 | v1 | v2 | X | | :------: | :----: | :----: | :--: | | 测试结果 | 不支持 | 不支持 | 通过 | > 因为 v1 不支持非阻塞发送,也没有驱动层缓存,write 总是把最后一个字节写到串口移位寄存器后才返回。所以 v1 不会出现丢失数据的现象。 > v2 在这一环节的表现和 v1 是一样的,大家可以猜猜原因是啥。 **注:本部分为了测试 flush 特性有效性,因此 X 出现 close 的时候出现丢数现象。使用版在 close 设备的时候应该强制 flush 一下的。** #### 非阻塞收发测试 使用中断非阻塞模式打开串口设备,发送 10k 左右数据量,同时测量一下时间。 | 数据量 | v1 | v2 | X | | :----: | :----------------: | :----------------: | :----------------: | | 102400 | 102400 / 9762ticks | 102400 / 8863ticks | 102400 / 8863ticks | | 10240 | 10240 / 976ticks | 10240 / 876ticks | 10240 / 876ticks | | 128 | 128 / 12ticks | 128 / 11ticks | 128 / 11ticks | 这部分测试大体上符合预期,因为有缓存,v2 和 X 先把数据放到缓存中就返回了。这样可以减少发送等待时间。 #### 阻塞收发测试 | 数据量 | v1 | v2 | X | | :----: | :----------------: | :----------------: | :----------------: | | 102400 | 102400 / 9762ticks | 102400 / 8902ticks | 102400 / 8866ticks | | 10240 | 10240 / 976ticks | 10240 / 890ticks | 10240 / 884ticks | | 128 | 128 / 12ticks | 128 / 11ticks | 128 / 11ticks | > v1 在非阻塞和阻塞两种模式下的表现是一样的,因为它没有阻塞概念。 > > v2 耗时比 v1 少,这是在预料中的,但是,它还是比 X 多了几个 tick 。这也是上文中工作模式对照部分对它的阻塞/非阻塞特性加 \* 的原因。 特别测试,当每次写小于串口驱动层缓存大小的数据时, | 数据量 | v2 | X | | :----: | :-----: | :----: | | 16 | 1ticks | 0ticks | | 32 | 5ticks | 0ticks | | 128 | 11ticks | 0ticks | 为什么出现了和上面表格不一样的结果,因为这次测试,每次写之前有个 1s 延时,保证串口缓存是空的。**当串口缓存大小是 N 前提下,每次 write 小于等于 N 数量的数据应该可以直接写到缓存,并立马返回!**所以,对于 X 来说耗时就是 **0**。 这个很重要,**当我们用串口调试程序,需要打印一些信息的时候,又不希望因为串口输出数据影响到其它业务的时序,或者,最大限度地降低因串口输出数据而影响其它程序执行时序**。 #### 回环测试数据丢失率 使用阻塞模式打开串口设备。这次通过串口调试助手以 20ms 的定时间隔,发送 384 字节数据。 | 版本 | v1 | v2 | X | | :----: | :--------------------: | :--------------------: | :----------------: | | 丢失率 | 671144 / 556848/17.03% | 1208816/1070464/11.45% | 2390800/2390800/0% | > v2 在这一步表现很差,第一次,笔者应用层缓存是 512 字节,想 `rt_device_read(uart, -1, recvbuf, 512);` 发现 read 不到任何数据,read 也不阻塞了,而是总能返回,单步进去看到,但接收的数据大于驱动缓存的时候,驱动拒绝处理,直接返回0!!!v2 的缺陷之一。 > > 鉴于以上原因,之后改成 `rt_device_read(uart, -1, recvbuf, 128);` 应用缓存和驱动缓存大小相等。 > > 手动单次发送,一次发送 344 字节数据(多于驱动缓冲大小),接收 256 字节,再次发送,接收 384 字节,第三次发送接收还是 256 字节,第四次又变成 384字节。 即便考虑到 v2 的上述缺陷,最多有 127 个字节数据被“滞留”串口驱动缓存里未及时返回。也弥补不了上述丢失率! ### 开启 DMA 的表现 很遗憾,v1 只支持 DMA 接收不支持 DMA 发送(估计以后也用不上 v1 了),由以上对比测试我们发现 v2 和 v1 很类似,在测试 v2 DMA 接收发送时也发现总体效果和使用中断没多少差异。 X 的表现如何呢?等待您的发现! > 遗憾的是,笔者对 STM32 的 HAL 极其不熟悉,又极其不想用 HAL 。花了很长时间想自己通过寄存器配置实现,最终没成功,还是放弃了。 > > HAL 有一个好处,那就是几乎可以适配 STM32 所有系列芯片。但是,HAL 不是为 OS 而生的 `#error "USE_RTOS should be 0 in the current HAL release"`,在 OS 上用终究有可能遇到失锁的问题。 > > 使用 HAL 还有个小小的瑕疵,那就是 `is_dma_txing` 判断变得不友好,无奈之下,笔者在 `struct stm32_uart` 中添加了个 `rt_bool_t dmaTxing;` 变量 —— ”HAL 中 gState 和 RxState 已经够多了“ 。算是目前的一个小遗憾吧。 ### 结束语 最后,依旧公开测试代码,本次测试使用的代码可以在 [serialX](https://gitee.com/thewon/serialX) 仓库找到。近期,笔者也会将 serialX 提交到 rt-thread 主仓库。 提前预告,下次我们来聊聊 serialX 在做控制台串口时遇到的问题已经解决方案(包括使用中断 DMA 收发模式打开的串口设备)。 相关文章: [rt-thread 驱动篇 之 serialX 全网公测](https://club.rt-thread.org/ask/article/3362.html)
15
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
出出啊
恃人不如自恃,人之为己者不如己之自为也
文章
43
回答
1518
被采纳
343
关注TA
发私信
相关文章
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
SFUD
msh
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
549
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
3
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部