Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
serial_V1
串口
RTT串口v1使用分析以及问题排查指南 (二)
发布于 2021-07-21 21:22:36 浏览:4050
订阅该版
[tocm] # RTT串口V1版本的使用分析及问题排查指南(二) ## 串口相关问题解析 承接[RTT串口V1版本的使用分析及问题排查指南(一)](https://club.rt-thread.org/ask/article/2894.html)文章。 结合串口使用过程的反馈信息,本章节将结合 **FinSH组件的串口相关问题** 和 **应用层上使用串口设备的相关问题** 这两个方面进行分析。这一章节探讨FinSH组件上的串口问题。 由于串口外设所涉及的方面过于广泛,分析时不可能涵盖全部应用场景(以上两个方面应该能涵盖了串口使用过程中的七八成的应用场景),但是,结合本章的分析问题的方法,相信其他方面的问题也将会迎刃而解。 ### FinSH 组件上的串口问题 说起FinSH组件,肯定是离不开串口的,FinSH组件的底层数据流默认由串口外设提供(当然也可以选择网络、USB、蓝牙等方式,**本节只讨论和串口相关的问题**)。 RT-Thread的FinSH组件,提供了一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息,类似于Linux下的Terminal。其执行序列如下图所示(抄袭的文档中心的序列图) ![image.png](https://oss-club.rt-thread.org/uploads/20210721/ed684bec8695a07e0f13acd02cbd531a.png) 结合上图,可以粗略的讲, FinSH就有点类似于在RT-Thread系统中创建了一个串口线程,它用来接收(监听)用户数据,并对数据进行解析,然后执行结果,并把需要显示的结果通过串口发送给用户。再简言之,就是串口外设的收发任务。 那么就简化成了三点:1.FinSH 线程是如何启动并工作的? 2. FinSH 是如何接收到数据的? 3. FinSH 是如何显示执行结果给用户的? #### FinSH 工作流程分析 ![image.png](https://oss-club.rt-thread.org/uploads/20210721/4b742ae98908f6780ee9881db072e63d.png.webp) 在图中最关键的就是(1)、(2)和(3)这三个关键语句。 (1)语句是设置FinSH线程的shell设备,在这里这个shell设备就是串口设备,查看它的函数原形如下: ```c /* finsh_set_device 的关键代码 */ void finsh_set_device(const char *device_name) { dev = rt_device_find(device_name); ... ... /* open this device and set the new device in finsh shell */ if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | \ RT_DEVICE_FLAG_STREAM) == RT_EOK) { rt_device_set_rx_indicate(dev, finsh_rx_ind); } ... ... } ``` **可以看到,该设备的打开模式是`RT_DEVICE_FLAG_INT_RX`,对于发送并未指明是中断`RT_DEVICE_FLAG_INT_TX`或是`RT_DEVICE_FLAG_DMA_TX`,那就代表设备发送是轮询模式。也就是说,FinSH的接收是接收中断模式,FinSH的发送是轮询模式**。这个很重要,一定要记住。 (2)语句是FinSH的接收函数,结合最下边`finsh_getchar()`函数实体,我们可以清晰的知道,原来FinSH的数据接收是靠信号量传递的:当执行 `finsh_getchar()` 的时候,会去通过调用 `rt_device_read()`读**一个字节的数据**,这个时候只要返回值不为1(返回值为1则代表有数据被读出),则将通过信号量的将该线程永久挂起 ,直到接收到FinSH数据为止。而如果有数据接收到的话,那么将通过FinSH的数据接收回调 `finsh_rx_ind()`来释放一个信号量,这样 FinSH 线程就会开始执行,开始读取一个字节数据。 ```c /* FinSH的接收回调很简单,就是触发回调后释放一个信号量就结束 */ static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size) { RT_ASSERT(shell != RT_NULL); /* release semaphore to let finsh thread rx data */ rt_sem_release(&shell->rx_sem); return RT_EOK; } ``` (3)语句是发送语句。Finsh线程执行(2)语句之后便拿到了一个字节的数据,然后经过数据解析,就会把这一个字节数据回显到终端上,也就是把数据通过 `rt_kprintf`发送到终端上。`rt_kprintf`底层是如何发送串口数据的,这里由于篇幅有限,不再细说,直接说结论就是,`rt_kprintf`底层对接的是串口的轮询发送模式。 #### FinSH总结 由上文可以得出一些结论: 1. FinSH 用串口外设作数据流时,其发送模式为轮询模式,接收模式为中断模式。 2. 接收靠的是信号量做数据通信,且每次进接收中断时,只能接收单字节数据。 3. 接收端当没有接收到数据时,FinSH将通过信号量挂起自身,因此属于非阻塞接收模式。 4. 发送端 (也包括rt_kprintf)为轮询发送,因此属于阻塞发送模式。(这里延伸一下,rt_kprintf能在中断环境下使用么?答案是可以的,因为该函数没有影响中断环境状态的变化,亦没有等待信号量或者挂起线程等操作。不过还是尽量少在中断环境下打印数据,因为中断执行时间要尽可能短,加入打印将会使得中断执行时间超过预期,从而出现不安全的意外风险) #### 其他问题探讨 结合FinSH的一些特性,以及日常遇到的问题,总结了一下几个频发的点以供参考: 1. FinSH 打开后接收不到数据: 由于FinSH是中断接收模式,既然接收不到数据,那就直接定位以下几个点: 1. `finsh_thread_entry` 线程是否初始化成功并在`finsh_getchar()`处等待? 2. 输入任意字符时,`finsh_getchar()`能否立刻返回数据? 3. 输入任意字符时,`finsh_rx_ind()`接收中断回调是否得到执行? 4. 输入任意字符时,对应的串口是否能进入串口中断,并查看串口对应的 接收数据寄存器(RDR) 是否有值(该值就是你输入的字符对应的ASCII码值)? 5. 如果连 接收数据寄存器都没有数据,那么排查串口配置的原因(包括时钟、引脚、中断等配置),或者是硬件的问题 2. 硬件复位后系统无法输出: 其实这个问题和FinSH无关,但是很多人觉得这个是控制台无输出,应该是FinSH相关的问题 ,因此我干脆把这个问题放在这里。 这个问题和 问题1 很像,但是本质区别还是有的,就是复现的场景是复位后出现问题,那么基本可以定位到是和复位有关的。经验告诉我们,一些开发板由于考虑一键下载的功能,因此在开发板的串口上集成了`一键下载电路`,导致系统复位时直接改变了BOOT模式,从而进入串口ISP下载模式。这里给出解决办法的参考链接:[硬件复位程序无法正常运行](https://club.rt-thread.org/ask/question/431772.html) 3. FinSH输出乱码: 出现这样的问题,要么是电脑终端控制台软件的问题,要么是波特率等配置不对,要么就是硬件没有接地。 4. 默认FinSH输出正常,切换其他串口后就无法工作: 这个问题按照问题1去排查就行,大概率是第5点,配置有问题,串口输出重定向错误等等。 5. 打开FinSH后系统就hardfault了: 这种问题其实没有特别的方法,就按照普通的hardfault去查就行了。也可以参照这个链接[Cortex-M内核硬件故障问题的分析方法](https://blog.csdn.net/fhqlongteng/article/details/112756689) #### 个人调试总结 本人在调试finsh的时候,通常是采用比较直接的手段,首先关注FinSH线程是否启动,如果是正常的话就直接拉出串口的发送数据寄存器TDR和接收数据寄存器RDR(根据MCU的版本和型号不同,这两个寄存器有的统一叫做DR数据寄存器,不过功能是一样的)。个人觉得这样的方式是最有效率的,下面以STM32F4为例,以MDK调试环境进行说明。 如何判定串口FinSH接收是正常的? 上文已经总结过,FinSH的接收是中断接收,那么很简单就在串口接收中断的位置打个断点,然后键盘输入一个字符看中断是否触发,并判断接收数据寄存器是否是输入的字符对应的ASCII码值。如图所示: ![image.png](https://oss-club.rt-thread.org/uploads/20210721/0c282d7d258a57c8121fbf3a4f8c71ba.png.webp) 左边方框断点位置就是串口接收中断触发的位置,右边DR寄存器就是串口接收到的字符存放的位置,此时让程序全速运行。当不输入字符时,这个断点处的代码是不会执行到的,现在敲击键盘一个数字 “1”,如果是正常的情况的话,将会得到如下图所示的效果: ![image.png](https://oss-club.rt-thread.org/uploads/20210721/c705f4868b3ee15f6b7246db731472c1.png.webp) 输入数字 “1” 后,可以看到程序执行到断点的位置了,此时的DR数据寄存器也获得了数字 “1”对应的ASCII码值,这就代表FinSH接收数据是正常的。 如何判定串口FinSH发送是正常的? 按照接收的测试方法类推,发送数据时,是使用的轮询发送模式,那么直接在`stm32_getc()`函数位置设置断点,如下图所示: ![image.png](https://oss-club.rt-thread.org/uploads/20210721/e235e13b40e59104f40bf22e28dfa4a6.png) 你可以利用`rt_kprintf`,或者是FinSH的回显功能,最终都会执行到此处代码段,然后查看DR寄存器数据是否是正确的即可。 ![image.png](https://oss-club.rt-thread.org/uploads/20210721/31b39219264386a18f7700abe71b3c7f.png) ### 应用层的串口问题 未完待续,见下一章节。。。 更多文章: [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)
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
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
MicroPython
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
15
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部