Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
rt_mq_消息队列_msg_queue
串口V2使用消息队列接收,线程假死问题
发布于 2022-09-01 13:59:47 浏览:1037
订阅该版
硬件:STM32F429IGT6核心板 操作系统:RTT V4.1.5 串口框架:使用串口V2。配置如下  /* 以 DMA 接收及轮询发送方式打开串口设备 */ rt_device_open(serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING); 使用场景:使用MODBUSRTU通信协议。上位机1ms时间间隔发送数据,串口线程读取后处理并返回。 问题点:1.串口线程来不及接收消息队列内容,导致线程阻塞,假死。 复现情况:PWM中断开启,优先级为1. 串口中断优先级为2.DMA优先级为0. 发送100Khz以下频率,通信正常感受不到延时。 发送100KhZ以上频率,发送一小会,串口通信正常。持续发送,串口通信掉线。 调整PWM中断优先级为3.发送100khz频率以上,通信不掉线。 问题点:2.DEBUG的时候,触发断点不继续运行。上位机串口发送数据没有关闭,持续一会在继续运行程序。这时也会导致线程假死。甚至系统崩溃,触发看门狗。 问题点:3.下载代码的时候。上位机串口发送数据没有关闭,这时也会导致线程假死。甚至系统崩溃,触发看门狗。 使用DEBUG断点查看,线程假死后,上位机发送数据,可以进入接收回调函数。 但是断点在线程中,始终无法进入线程。 怀疑是消息队列满了,无法处理导致假死。尝试过对消息队列清空,失败了。 另一个是怀疑串口V2的缓存满了没有清空,尝试过清空对应的ringbuffer缓存,也失败了。 请不要说是串口线程太卡了,接收太慢处理不过来。 我想知道的是,线程假死后怎么恢复。 或者说是消息队列没处理过来的话怎么保证线程不会异常,可以抛弃消息队列内的所有内容。 代码如下。其中的信号量与互斥量取消过。没有改善。 ```c /** * @brief MODBUS线程 * @param p:无用,不定义创建线程有警告 * @retval None. * @note None. */ static void modbus_thread(void* p) { //初始化modbusRTU,从站地址为0x01,波特率为115200,无校验。 eMBRTUInit(&ucRTU_DCB,&ucMB_RTU_PORT,SLAVE_ADDRESS,BAUD_RATE,MB_PAR_NONE); eMBRTUStart(&ucRTU_DCB); //F4使能空闲中断不会立马进入中断函数进行状态转换,手动切换 ucRTU_DCB.eRcvState = STATE_RX_IDLE; while(1) { struct rx_msg msg; rt_memset(&msg, 0, sizeof(msg)); /* 从消息队列中读取消息 */ rt_err_t result = rt_mq_recv(rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER); if (result == RT_EOK) { /* 从串口读取数据 */ rt_uint32_t rx_length = rt_device_read(msg.dev, 0,(CHAR *)ucRTU_DCB.ucBuffer, msg.size); if(rx_length != msg.size) { LOG_W("Incorrect receive length"); break; } else { ucRTU_DCB.ucBufferCount = msg.size; //写入读取大小 xMBPortEventPost(&ucRTU_DCB,EV_FRAME_RECEIVED); //改变事件状态为接收事件 rt_mutex_take(mb_slave_mutex, RT_WAITING_FOREVER);//保存内存 eMBRTUPoll(&ucRTU_DCB); //读写内存 rt_mutex_release(mb_slave_mutex); //允许操作内存 rt_sem_release(mb_buff_sem); //释放MB处理线程信号量 } } } } /*******************************************串口收发处理函数*********************************************************************/ /** * @brief This function will set the reception indication callback function. This callback function * is invoked when this device receives data. * * @param dev is the pointer of device driver structure. * * @param rx_ind is the indication callback function. * * @return RT_EOK */ static rt_err_t uart_input(rt_device_t dev, rt_size_t size) { struct rx_msg msg; rt_err_t result; msg.dev = dev; msg.size = size; result = rt_mq_send(rx_mq, &msg, sizeof(msg)); if (result == -RT_EFULL) { /* 消息队列满 */ LOG_E("message queue full!"); } return 1; } /** * @brief 串口接收函数. * @param buf:接收缓存 * @param bufsz:接收缓存大小 * @retval 接收长度。-1表示接受失败 * @note 消息队列阻塞接收,一直等待消息到来 */ static int serial_receive(uint8_t *buf, int bufsz) { struct rx_msg msg; rt_err_t result; rt_uint32_t rx_length; while (1) { rt_memset(&msg, 0, sizeof(msg)); /* 从消息队列中读取消息 */ result = rt_mq_recv(rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER); if (result == RT_EOK) { /* 从串口读取数据 */ rx_length = rt_device_read(msg.dev, 0, buf, msg.size); /* 打印数据 */ // LOG_HEX(UART_NAME,8,buf,rx_length); return rx_length; } } } /** * @brief 串口发送函数.. * @param buf:发送缓存 * @param bufsz:发送缓存大小 * @retval 成功:1,失败:0 * @note None. */ static int serial_send(uint8_t *buf, int len) { rt_size_t send_len = 0; /* 通过串口设备 serial 输出读取到的消息 */ send_len = rt_device_write(serial, 0, buf, len); if(send_len == len) { return 1; } else { LOG_E("send failed"); return 0; } } /** * @brief modbus 从机1 初始化 * @param None. * @retval None. * @note None. */ static int Modbus_Slave1_Init(void) { rt_err_t ret = RT_EOK; struct rx_msg msg; /* 初始化消息队列 */ rx_mq = rt_mq_create("mbs1ave1", sizeof(struct rx_msg), /* 一条消息的最大长度 */ BSP_UART1_RX_BUFSIZE, /* 存放消息的缓冲区大小 */ RT_IPC_FLAG_FIFO); /* 查找串口设备 */ serial = rt_device_find(UART_NAME); if (!serial) { rt_mq_detach(rx_mq); LOG_E("find %s failed!", UART_NAME); return RT_ERROR; } /* 创建一个动态互斥量 */ mb_slave_mutex = rt_mutex_create("mb slave", RT_IPC_FLAG_PRIO); if (mb_slave_mutex == RT_NULL) { LOG_E("create mb_slave_mutex failed."); return -1; } /* 创建 MODBUS从机线程*/ rt_thread_t thread = rt_thread_create( UART_NAME, /* 线程名字 */ modbus_thread, /* 线程入口函数 */ RT_NULL, /* 线程入口函数参数 */ THREAD_STACK_SIZE, /* 线程栈大小 */ THREAD_PRIORITY, /* 线程的优先级 */ THREAD_TIMESLICE); /* 线程时间片 */ /* 创建成功则启动线程 */ if (thread != RT_NULL) { rt_thread_startup(thread); } else { ret = RT_ERROR; LOG_E("modbus slave created failed."); } return ret; } /* 导出到 msh 命令列表中 */ INIT_APP_EXPORT(Modbus_Slave1_Init); ```
查看更多
出出啊
2022-09-01
恃人不如自恃,人之为己者不如己之自为也
> 请不要说是串口线程太卡了,接收太慢处理不过来。 我想知道的是,线程假死后怎么恢复。 或者说是消息队列没处理过来的话怎么保证线程不会异常,可以抛弃消息队列内的所有内容。 别想了,没法恢复。线程内存可能被破坏了。说明有漏洞。 弱弱的问一句,为啥不试试 serialX 呢?
1
个回答
默认排序
按发布时间排序
撰写答案
登录
注册新账号
关注者
0
被浏览
1k
关于作者
用户名由3_15位
这家伙很懒,什么也没写!
提问
66
回答
256
被采纳
34
关注TA
发私信
相关问题
1
rt_object_init中报assertion failed错误?
2
在 MDK中的NANO 里创建消息队列失败,内存堆已开启
3
如何用消息队列传递结构体数据
4
消息队列满了以后接收乱码
5
消息队列传输不定长数据
6
使用消息队列在线程中发送总失败
7
初始化第二个消息队列时发生硬件错误
8
rtthread消息队列一对多的情况
9
消息队列为什么会出现获取到的内容有旧的数据?
10
通过消息队列名称,获取消息队列句柄
推荐文章
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组件
最新文章
1
Studio环境下ST M7系列USB主机(CheeryUSB)配置及踩坑
2
RTT串口查找函数使用过程中遇到的问题。
3
RT-Thread CI编译产物artifacts自动上传功能介绍
4
STM32G030移植RT-Thread
5
CubeMX & RT-Thread Studio 联合开发说明
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
rt-smart
RTC
FAL
I2C_IIC
cubemx
ESP8266
UART
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
GD32
定时器
ADC
flashDB
编译报错
socket
中断
rt_mq_消息队列_msg_queue
keil_MDK
Debug
SFUD
ulog
msh
C++_cpp
MicroPython
本月问答贡献
出出啊
1522
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
815
个答案
179
次被采纳
crystal266
555
个答案
162
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部