Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
串口
serial_V1
RTT串口V1版本的使用分析及问题排查指南(一)
发布于 2021-07-19 14:14:26 浏览:7870
订阅该版
[tocm] # RTT串口V1版本的使用分析及问题排查指南(一) ## 简述 无论是刚接触 RT-Thread 的新手,还是经验老道的大牛们,他们使用 RT-Thread 的时候,使用最频繁最广泛的外设,想必也非串口设备莫属。 回想大家在移植一个新的BSP或者芯片时,如何验证是否移植成功呢?是的,msh控制台窗口走一波 RTT 的 logo 信息,输出成功了就基本代表移植成功了。如下所示: ```c \ | / - RT - Thread Operating System / | \ 4.0.4 build Dec 32 2021 2006 - 2021 Copyright by rt-thread team msh > ``` 例如 finsh 组件,以命令行的方式实现人机交互的功能,在项目开发调试中有着举足轻重的作用,也是开发者们使用最为频繁的组件。 又例如 ULOG组件,AT组件,ymodem组件,RT_Link组件等,其底层数据流都有串口的踪迹。因此,作为使用最频繁,覆盖面最广泛的串口设备,如果把它搞懂,那将会在你的项目开发中如虎添翼,或对嵌入式系统也会有更深刻的理解。 既然串口设备如此重要,受众人群又如此之多,使用范围如此之广,那么有必要去理一理串口框架,汇总一下问题所在,为广大开发者们指一下解决问题的方向。这也是这篇文章的主要工作。 本文会先结合STM32为平台,以串口V1版本做分析说明 (第一部分),并总结遇到串口方面的问题该如何解决的方法(第二部分)。 (在此需要解释一下,`串口V1版本` 这个名字非官方冠名,是本人为了区分`串口V2版本` 而临时起的名字,当然后续会有串口V2版本的介绍说明,马不停蹄更新中) 由于串口V1版本已经历经多年的开发与迭代,也被多数开发者整理成文,广为流传,本文若重新对其做细致的分析显然是在浪费各位看官的宝贵时间。因此,**本文旨在总结串口使用过程中遇到的问题,弱化分析串口的执行流程**,如需详细的串口流程分析,可移步[文档中心串口章节](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/uart/uart_v1/uart),或者自行上网搜索,相信你一定能找到合适的答案。那么废话不多说,开整。 ## 串口设备使用说明 串口流程分析分为两部分,一部分是串口驱动,另一部分是串口框架,用户(应用层)使用串口时,是按照下图的模型进行操作的: ![image.png](https://oss-club.rt-thread.org/uploads/20210719/d074ae6d9d22dcfda8b6d755109595ad.png) 首先需要使用 Device 框架(源码位置在 `src/device.c` 中),什么是Device 框架,比如用到的 `rt_device_open/close/read/write/control()` 等API操作接口,就是使用的 Device 框架的接口。本文中不做深入探讨,了解即可。 其次是 UART 设备驱动框架 (源码位置在 `components\drivers\serial\serial.c`),串口设备驱动框架实现了Device框架的操作方法的接口`rt_serial_open/close/read/write/control()`。举个例子,例如Device框架的`rt_device_open()` 接口是打开一个设备对象,而对应到串口框架上,就是对接到了 `rt_serial_open()` 。 然后是串口设备驱动(源码位置在 `bsp/xxx/drivers/drv_usart.c`),串口设备驱动负责实例化串口设备 。这一层调用了 `rt_hw_serial_register()` 函数注册串口设备到操作系统中,也是与串口硬件直接打交道的媒介,这一层将会看到串口硬件的配置、读写寄存器、中断的操作等。 串口设备的使用序列如下所示: ![image.png](https://oss-club.rt-thread.org/uploads/20210720/f60f638e81d8b672eabfbeee49c3b5ce.png) ## 串口各个模式的流程分析 串口框架目前适配了三种硬件工作模式,即串口轮询(发送/接收)、串口中断(发送/接收)、串口DMA(发送/接收)。下面分别对三种模式进行介绍: ### 一:轮询模式 轮询模式即调用串口 接收/发送 的 API 后将一直占用CPU资源直到数据收发完成才返回,使用时需要用户主动调用 接收/发送 的API接口才会执行相应的操作。 #### 轮询接收 应用程序调用 `rt_device_read()` 接收数据,轮询接收模式下会调用到底层串口驱动提供的 `getc` 接口,每次接收一个字节,如果接收不到数据将一直占用CPU资源。 #### 轮询发送 应用程序调用 `rt_device_write()` 发送数据,轮询发送模式下会最终会调用到底层串口驱动提供的 `putc` 接口,每次发送一个字节,循环发送直到待发送的数据发送完成。 轮询接收和发送调用关系如下图所示: ![image.png](https://oss-club.rt-thread.org/uploads/20210720/ae80469513273d7a532745bb9ff1510f.png.webp) ### 二:中断模式 中断模式下收发数据时,将数据的收发过程放在中断中进行,不再持续占用CPU资源,应用程序只用负责将数据写入串口数据寄存器,然后线程就会让出资源,空出了程序等待串口硬件收发数据的时间。注意一点:中断接收和发送时,每次在中断中操作的还是单个字节。 #### 中断接收 串口硬件接收到一个字节的数据后会触发中断并调用串口驱动框架的 `rt_hw_serial_isr()` 函数,此函数会将这一字节数据写入环形缓冲区,用户设置的回调函数也会被调用。应用程序读取数据实际是从环形缓冲区读取。 中断接收调用关系如下图所示: ![image.png](https://oss-club.rt-thread.org/uploads/20210719/ee6524d06862214a806b5b483b6fdfff.png.webp) #### 中断发送 串口框架负责调用底层 `putc` 接口向串口寄存器写入待发送的数据,然后等待此数据发送完成的信号,此时当前线程会被挂起。上一个数据发送完成后会调用串口驱动框架的 `rt_hw_serial_isr()` 函数,此函数会发送完成信号唤醒发送数据线程,并重置完成信号状态为未完成。线程运行后会向串口寄存器写入下一个数据,然后等待完成信号,重复上一个流程,直到缓冲区数据发送完成。 该过程与中断接收流程很相像,再次不再贴图赘叙。 ### 三:DMA模式 DMA模式下收发数据与中断模式很相像,可以粗略的认为,两种模式唯一不同的就是,中断模式每次收发数据为单字节,而DMA模式则是多个字节进行收发的。 #### DMA接收 使用 DMA 接收模式时,首先应用程序打开串口设备会指定打开标志为 RT_DEVICE_FLAG_DMA_RX,此时串口驱动框架会创建环形缓冲区并调用串口驱动层 `control` 接口使能 DMA 接收完成中断。 DMA接收调用关系如下图所示: ![image.png](https://oss-club.rt-thread.org/uploads/20210719/32085a0345ec44c372414fb9c464aede.png.webp) 这里再啰嗦一句,在DMA中断处理流程中,有三种DMA接收中断,分别是DMA空闲中断(IDLE)、DMA半满中断(HFIT)和 DMA满中断(TCIT),这三个中断相辅相成,最后统一交由串口框架中断处理函数 `rt_hw_serial_isr(RT_SERIAL_EVENT_RX_DMA_DONE)`中做处理。其中DMA空闲中断是在uart_isr中触发的,另外两个是在DMA接收回调中触发的,这两个接收回调是在DMA接收使能启动的时候,由HAL库注册的,用户无需关心这两个DMA接收回调的注册逻辑,只需知道,**如果用户不想使用这两个DMA接收回调的时候,只要把函数里面的执行代码注释掉即可**。类似下图这样 : ```c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { struct stm32_uart *uart; RT_ASSERT(huart != NULL); // uart = (struct stm32_uart *)huart; // dma_isr(&uart->serial); } void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) { struct stm32_uart *uart; RT_ASSERT(huart != NULL); // uart = (struct stm32_uart *)huart; // dma_isr(&uart->serial); } ``` (至于为什么会有用户无需使用该回调函数的应用场景,这里先按下不表,后边会具体详细分析,而且这部分会很重要,该机制在串口V2上照样使用) #### DMA发送 应用程序发送数据流程如下图所示,应用程序调用 `rt_device_write()` 发送数据,最终待发送数据的地址和大小会被放入数据队列,如果此时 DMA 空闲,就会开始发送数据。当 DMA 发送完成触发中断时,`rt_hw_serial_isr()` 函数会判断数据队列是否有待传输的数据并开始下次 DMA 传输,用户设置的回调函数也会被调用。 ![image.png](https://oss-club.rt-thread.org/uploads/20210719/ad395621d63da0baec99bd68424444be.png.webp) 由上图我们可以看出,在使用DMA发送时,串口框架并未使用环形缓冲区,然而我们又知道,DMA发送时,肯定是需要缓冲区来存放数据的,那么DMA发送时候的数据块,存放在哪里呢?这里就需要注意了,DMA发送时候,数据缓冲区是由用户应用层定义的,在传给串口框架的时候,是将应用层定义的数据缓冲区的指针传递过来。**如果在发送过程中,该缓冲区的内容被意外修改了,那么将会导致DMA发送的数据出现错误**。我们可以再结合下面的图继续说明: ![image.png](https://oss-club.rt-thread.org/uploads/20210719/cd59e4c2ccde8c9a6a6e6f10ed6233d2.png) ## 串口相关问题解析 篇幅有限,本节内容见 RTT串口V1版本的使用分析及问题排查指南(二) 更多文章: [RTT串口V1版本的使用分析及问题排查指南(一)](https://club.rt-thread.org/ask/article/2894.html) [RTT串口V1版本的使用分析及问题排查指南(二)](https://club.rt-thread.org/ask/article/2898.html) [RTT串口V1版本的使用分析及问题排查指南(三)](https://club.rt-thread.org/ask/article/2904.html) [串口框架V1和V2版本对比](https://club.rt-thread.org/ask/article/2915.html) [串口 V2 适配指南](https://club.rt-thread.org/ask/article/2920.html)
17
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
123
这家伙很懒,什么也没写!
文章
6
回答
309
被采纳
68
关注TA
发私信
相关文章
1
串口DMA发送数据时,数据被覆盖
2
关于串口DMA模式下rt_device_close问题
3
利用stm32f427实现usb转串口,电脑端什么也没有识别到
4
finsh 控制台 适配 RS 485请大神指点????
5
uart_sample.c 中,读串口设备时偏移量pos要设置为-1而不是0?
6
【结贴】at_device软件包中对串口接收数据缺少判断导致数据接收异常
7
串口无法接受数据,但可以发送
8
串口如何有效的清除掉接收缓冲,而不必一个一个的去读取
9
串口接收使用方式问题
10
雅特力FINSH问题
推荐文章
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
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
8
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
3
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部