STM32F4 HAL库串口死锁问题调试记录

文章目录

  • STM32F4 HAL库串口死锁问题调试记录
      • 调试方法
      • 结果
      • 分析
      • 解决
        • 方法一:
        • 方法二:

STM32F4 HAL库串口死锁问题调试记录

使用方法:通过串口DMA固定周期向外发送数据,同时开启串口DMA接收用于接收其它板卡发来的数据。
问题:在程序运行一段时间后会出现程序不再接收数据的情况,但向外发送数据正常。
分析:一开始认为是触发了串口ORE错误导致的这个问题呢,但奇怪的是并没有触发串口错误中断的回调函数,通过进一步分析排查发现是由__HAL_LOCK()引起的,而串口ORE错误是在触发这个问题之后出现的。

调试方法

  1. 通过如下函数开启串口DMA接收
HAL_UARTEx_ReceiveToIdle_DMA(&JOYSTICK_HUART, joystick_uart_buffer, JOYSTICK_UART_BUFFER_SIZE);
  1. 通过如下函数以10ms周期定时向外发送数据
HAL_UART_Transmit_DMA(&JOYSTICK_HUART,(uint8_t*)&joystick_display_frame,sizeof(JoystickDisplayFrame_t));
  1. 实现串口DMA+IDLE中断接收回调函数
uint32_t huart2_err_cnt = 0;
uint32_t aaa[10] = {0};
HAL_StatusTypeDef huart2_status1;
HAL_StatusTypeDef huart2_status2;

uint32_t tx_lock_cnt = 0;
uint32_t tx_unlock_cnt = 0;
uint8_t rx_irq_flag = 0;

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
  uart_rx_event_cnt++;

  huart2_status1 = HAL_UARTEx_ReceiveToIdle_DMA(&JOYSTICK_HUART, joystick_uart_buffer, JOYSTICK_UART_BUFFER_SIZE);
  if(huart2_status1 != HAL_OK) {
    huart2_err_cnt++;
    rx_irq_flag = 1;
    
    /* 根据相应的错误类型清除相应的错误标志 */
    if(__HAL_UART_GET_FLAG(&JOYSTICK_HUART, UART_FLAG_ORE) != RESET) {
      __HAL_UART_CLEAR_OREFLAG(&JOYSTICK_HUART); //清除ORE溢出错误标志,(读SR然后读DR,这里用于清除串口错误标志)
      aaa[0]++;
    } else if(__HAL_UART_GET_FLAG(&JOYSTICK_HUART, UART_FLAG_FE) != RESET) {
      __HAL_UART_CLEAR_FEFLAG(&JOYSTICK_HUART); //清除FE帧错误标志
      aaa[1]++;
    } else if(__HAL_UART_GET_FLAG(&JOYSTICK_HUART, UART_FLAG_PE) != RESET) {
      __HAL_UART_CLEAR_PEFLAG(&JOYSTICK_HUART); //清除PE奇偶校验错误标志
      aaa[2]++;
    } else if(__HAL_UART_GET_FLAG(&JOYSTICK_HUART, UART_FLAG_NE) != RESET) {
      __HAL_UART_CLEAR_NEFLAG(&JOYSTICK_HUART); //清除NE噪声错误标志
      aaa[3]++;
    }
    huart2_status2 = HAL_UARTEx_ReceiveToIdle_DMA(&JOYSTICK_HUART, joystick_uart_buffer, JOYSTICK_UART_BUFFER_SIZE);
  }
}
  1. 实现串口错误中断回调函数
uint32_t uart_error_cnt = 0; //记录是否进入串口错误中断
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
  uart_error_cnt++;
  // 其它处理
}
  1. 改造HAL库串口DMA发送函数来验证问题
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t *tmp;

  /* Check that a Tx process is not already ongoing */
  if (huart->gState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    /* Process Locked */
    __HAL_LOCK(huart);
    if(rx_irq_flag == 0) {
      tx_lock_cnt++;
    }

    // 省略中间的处理

    /* Process Unlocked */
    __HAL_UNLOCK(huart);
    if(rx_irq_flag == 0) {
      tx_unlock_cnt++;
    }

    /* Enable the DMA transfer for transmit request by setting the DMAT bit
       in the UART CR3 register */
    ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

结果

下图为出错时对应的变量值
第一次测试结果:
在这里插入图片描述
第二次测试结果:
在这里插入图片描述

分析

  1. 根据上面的结果可以看出:程序在执行发送函数中的__HAL_LOCK(huart)串口加锁函数后,__HAL_UNLOCK(huart)串口解锁函数前触发了串口IDLE中断,此时由于串口处于锁定状态,执行HAL_UARTEx_ReceiveToIdle_DMA()函数会直接返回HAL_BUSY(即2)的状态,导致出现了错误。
  2. 根据aaa[0]的值可以判定此时尚未出现串口ORE的报错,而usart2_sr串口状态寄存器的值显示当前出现了串口ORE错误,这个错误是由于后续又继续收到数据导致的。
  3. 根据usart2_cr串口控制寄存器1的值可以看出IDLEIE中断使能标志位现在为0,因而不会继续触发串口IDLE接收中断了,自然就不会继续执行回调函数的内容了

解决

STM32串口是支持全双工工作的,按理说收发可以做到完全互不干扰,但是串口锁定处理的这段时间确实会影响全双工的性能。程序同时高频接收和高频发送时可能会有比较高的概率出现该问题。

方法一:

屏蔽掉HAL库中关于串口锁的函数(不推荐)

方法二:

触发这种情况时添加串口解锁处理

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
  uart_rx_event_cnt++;

  huart2_status1 = HAL_UARTEx_ReceiveToIdle_DMA(&JOYSTICK_HUART, joystick_uart_buffer, JOYSTICK_UART_BUFFER_SIZE);
  if(huart2_status1 != HAL_OK) {
    huart2_err_cnt++;
    
    JOYSTICK_HUART.RxState = HAL_UART_STATE_READY;
    JOYSTICK_HUART.Lock = HAL_UNLOCKED; //或者调用 __HAL_UNLOCK(&JOYSTICK_HUART);
    huart2_status2 = HAL_UARTEx_ReceiveToIdle_DMA(&JOYSTICK_HUART, joystick_uart_buffer, JOYSTICK_UART_BUFFER_SIZE);
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/423483.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蜘蛛蜂优化算法SWO求解不闭合SD-MTSP,可以修改旅行商个数及起点(提供MATLAB代码)

1、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法(Spider wasp optimizer,SWO)由Mohamed Abdel-Basset等人于2023年提出,该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为,具有搜索速度快,求解精度高的优势。VRPTW&#x…

鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

“2024年是原生鸿蒙的关键一年,我们要加快推进各类鸿蒙原生应用的开发,集中打赢技术底座和三方生态两大最艰巨的战斗。”这是余承东在新年信中表达的决心。 随后在1月18日举行的鸿蒙生态千帆启航仪式上,华为宣布 HarmonyOS NEXT 鸿蒙星河版系…

Python用函数实现代码复用

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 生命对某些人来说是美丽的&#xff0c…

算法修炼-动态规划之路径问题(1)

62. 不同路径 - 力扣(LeetCode) 思路:选定一个网格为终点,走到这个网格的所有走法就是这个网格的上面一个网格的所有走法加上这个网格左边一个网格的所有走法,然后做好初始化工作就行。 class Solution { public:int…

马斯克指控OpenAI违背成立协议,要求恢复开源;Automattic否认向AI公司出售用户数据

🦉 AI新闻 🚀 马斯克指控OpenAI违背成立协议,要求恢复开源 摘要:马斯克近日在旧金山高等法院对OpenAI及其CEO阿尔特曼提起诉讼,指控他们违反最初促进AI技术造福人类非营利方向的成立协议。马斯克声称,Ope…

pycharm专业版本的安装

一 、到官网下载对应的pycharm安装包 也可以把安装软件(用物理机下载到共享文件夹) 然后进入Ubuntu系统把下载大的安装包剪贴到目标路径 1 在ubuntu中创建一个用来存放pycharm安装包的文件夹 rootzmq-virtual-machine:/home/zmq/Desktop# mkdir pycha…

爬虫的一些小技巧总结

一、在爬虫中,爬取的数据类型如下 1.document:返回的是一个HTML文档 2.png:无损的图片,jpg:压缩后的图片,wbep:有损压缩,比png差,比jpg好 3.avgxml图像编码字符串 4.script:脚本文件,依据一定格式编写的可执行的文…

小项目:2024/3/2

一、TCP机械臂测试 代码&#xff1a; #include <myhead.h> #define SER_IP "192.168.125.254" //服务器端IP #define SER_PORT 8888 //服务器端端口号#define CLI_IP "192.168.199.131" //客户端IP #define CLI_P…

面试笔记系列二之java基础+集合知识点整理及常见面试题

目录 Java面向对象有哪些特征&#xff0c;如何应用 Java基本数据类型及所占字节 Java中重写和重载有哪些区别 jdk1.8的新特性有哪些 内部类 1. 成员内部类&#xff08;Member Inner Class&#xff09;&#xff1a; 2. 静态内部类&#xff08;Static Nested Class&#…

project.config.json 文件内容错误] project.config.json: libVersion 字段需为 string, string

家人们&#xff0c;遇到了一个新的报错 于是从网上找了各种方法&#xff0c;有说把开发者工具关闭重启的&#xff0c;有说开发者工具下载重新下载的&#xff0c;有说开发者工具路径安装得在C盘的&#xff0c;均没有效果 解决方法&#xff1a; 1、运行项目&#xff0c;在开发者…

【MATLAB源码-第153期】基于matlab的OFDM系统插入导频和训练符号两种信道估计方式误码率对比仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OFDM&#xff08;Orthogonal Frequency Division Multiplexing&#xff0c;正交频分复用&#xff09;是一种高效的无线信号传输技术&#xff0c;广泛应用于现代通信系统&#xff0c;如Wi-Fi、LTE和5G。OFDM通过将宽带信道划分…

2月全志芯片开源项目分享合集

1、项目名称&#xff1a;全志T113-S3智能家居86屏 作者的上一个作品的V3s的随身终端&#xff0c;由于硬件解码一直无法完成适配&#xff0c;于是作者找了另一块性能更强&#xff0c;接口更丰富的T113-S3来替代&#xff0c;并将其应用在智能家居场景中的86型智能触控屏解决方案上…

【Web安全靶场】sqli-labs-master 38-53 Stacked-Injections

sqli-labs-master 38-53 Stacked-Injections 其他关卡和靶场看专栏… 文章目录 sqli-labs-master 38-53 Stacked-Injections第三十八关-报错注入第三十九关-报错注入第四十关-盲注第四十一关-盲注第四十二关-联合报错双查询注入第四十三关-报错注入第四十四关-盲注第四十五关-…

JVM调优,调整JVM参数

JDK8之后把-XX:PermSize和-XX:MaxPermGen移除了&#xff0c;取而代之的是XX:MetaspaceSize128m &#xff08;元空间默认大小&#xff09; -XX:MaxMetaspaceSize128m &#xff08;元空间最大大小&#xff09; JDK 8开始把类的元数据放到本地化的堆内存(native heap)中&#xff0…

基于yolov8与pyqt5的火焰烟雾实时检测系统设计

界面 权重&#xff1a;可以选择自己训练的yolov8模型&#xff0c;也可以用一些改进的yolov8模型作为系统的权重。 功能&#xff1a;单张图片的检测&#xff0c;视频文件的检测&#xff0c;多张图片同时检测&#xff0c;以及摄像头实时检测。 调整&#xff1a;可以调整置信度&…

AP8851H DC-DC降压恒压IC+协议芯片 USB PD快充方案电源驱动

产品描述 AP8851H 一款宽电压范围降压型DC-DC 电源管理芯片&#xff0c;内部集成使能开关控制、基准电源、误差放大器、过热保护、限流保护、短路保护等功能&#xff0c;非常适合在宽输入电压范围具有优良的负载和线性调整度。AP8851H 芯片包含每周期的峰值限流、软启动、过压保…

【Easyx】easyx从入门到精通 — 初步入门

easyx 初步入门 1 安装easyx图形库2 如何使用Easyx3 效果初试4 基本图形绘制4.1 绘制点4.2 绘制直线4.3 绘制圆形4.4 绘制矩形4.5 绘制椭圆4.6 绘制圆角矩形4.7 绘制扇形 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff01;下一篇…

科学家用乳清蛋白海绵高效环保提取电子废物中的黄金

科学家们发现乳制品加工产生的副产品——乳清蛋白在提取电子废弃物中的黄金方面表现出色&#xff0c;极大地提高了回收效率&#xff0c;并大幅降低了能源消耗成本。Raffaele Mezzenga教授领导的科研团队利用乳清蛋白质制造出一种有机海绵&#xff0c;通过酸浴和高温变性乳清蛋白…

论文里点击如图?-?如何跳转到图片的题注

写论文&#xff0c;如何点击如图?-?然后光标自己能跳转到指定图片的题注之前呢&#xff1f; 首先&#xff0c;你要确定自己已经列好了标题&#xff0c;如几点几&#xff0c;几点几&#xff0c;比如我写到第三个章节的标题为 3.2 XXXXXXXXX 那么接下来后面的操作会出现图3-&…

【饮食】日常零食 保健食品分类(附食品营养成分表与执行标准,Coursera营养学课程笔记)

程序员生活指南之 【饮食】日常零食 & 保健食品分类和推荐&#xff08;附食品营养成分表与执行标准&#xff09; 文章目录 一、保健食品1、什么是保健食品&#xff1f;2、常见保健食品分类3、常见保健食品推荐 二、日常零食&#xff08;食品营养成分表与执行标准&#xff0…