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

2024-03-03 08:36

本文主要是介绍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 bitin 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);}
}

这篇关于STM32F4 HAL库串口死锁问题调试记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

在IntelliJ IDEA中高效运行与调试Spring Boot项目的实战步骤

《在IntelliJIDEA中高效运行与调试SpringBoot项目的实战步骤》本章详解SpringBoot项目导入IntelliJIDEA的流程,教授运行与调试技巧,包括断点设置与变量查看,奠定... 目录引言:为良驹配上好鞍一、为何选择IntelliJ IDEA?二、实战:导入并运行你的第一个项目步骤1

Python错误AttributeError: 'NoneType' object has no attribute问题的彻底解决方法

《Python错误AttributeError:NoneTypeobjecthasnoattribute问题的彻底解决方法》在Python项目开发和调试过程中,经常会碰到这样一个异常信息... 目录问题背景与概述错误解读:AttributeError: 'NoneType' object has no at

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

Kotlin Map映射转换问题小结

《KotlinMap映射转换问题小结》文章介绍了Kotlin集合转换的多种方法,包括map(一对一转换)、mapIndexed(带索引)、mapNotNull(过滤null)、mapKeys/map... 目录Kotlin 集合转换:map、mapIndexed、mapNotNull、mapKeys、map

nginx中端口无权限的问题解决

《nginx中端口无权限的问题解决》当Nginx日志报错bind()to80failed(13:Permissiondenied)时,这通常是由于权限不足导致Nginx无法绑定到80端口,下面就来... 目录一、问题原因分析二、解决方案1. 以 root 权限运行 Nginx(不推荐)2. 为 Nginx

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例