IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> stm32-HAL使用usart发送中断判断发送库的一个问题 -> 正文阅读

[嵌入式]stm32-HAL使用usart发送中断判断发送库的一个问题

af904a45eb73ab7c4173dff48217ad9f.png

前言:

stm32是嵌入式MCU开发中最多应用的芯片,很早之前我们开发ST芯一般都是标准库开发,标准库简洁好读,现在要配合CubeMX生成代码,所以官方主推HAL库和LL库,但是HAL代码冗杂很绕,因为出来也不久,有些代码使用之后不是那么好用。

这次我就来分享两个实际使用过程中遇到的两个问题,一个是使用uart的发送中断进行数据发送产生的数组访问越界的问题。一个是stop模式下,dma相关的外设休眠唤醒需要注意重新初始化。

这篇是uart使用的介绍:

作者:良知犹存

转载授权以及围观:欢迎关注微信公众号:羽林君

或者添加作者个人微信:become_me


情节介绍:

串口是我们经常使用的一个外设,一般我们为了发送速度变快,会使用DMA或者中断发送接收。而CubeMX配置下,HAL调用了自己的一套函数 ?HAL_UART_IRQHandler 层层调用。

在官方提供的 stm32f4xx_hal_uart.c 文件中你可以看到如下函数:

void?HAL_UART_IRQHandler(UART_HandleTypeDef?*huart)

{

.....

??/*?UART?in?mode?Transmitter?------------------------------------------------*/
??if?(((isrflags?&?USART_SR_TXE)?!=?RESET)?&&?((cr1its?&?USART_CR1_TXEIE)?!=?RESET))
??{
????UART_Transmit_IT(huart);
????return;
??}

......

}

其中在UART_Transmit_IT 函数中 有一段 函数为

if?(--huart->TxXferCount?==?0U)
{
????/*?Disable?the?UART?Transmit?Complete?Interrupt?*/
????__HAL_UART_DISABLE_IT(huart,?UART_IT_TXE);

????/*?Enable?the?UART?Transmit?Complete?Interrupt?*/
????__HAL_UART_ENABLE_IT(huart,?UART_IT_TC);
}

这里会把发送的 TxXferCount 的计数值自减,并判断是否为零。正常工作都没有问题,可是我们的设备实际使用过程中,上层的部分断电之后,会给底层通讯串口带了一个中断,这个时候继续减下去就会出现出现一个很大值,这个是因为 TxXferCount ?是一个无符号的16位数据。

__IO?uint16_t?????????????????TxXferCount;??????/*!<?UART?Tx?Transfer?Counter?*/

debug看到如下数据,原因上文提到。就是我遇到我们Linux核心板掉电之后会产生一个中断,导致这里判断时候自动减1,TxXferCount从 0 变成 -1 因为是无符号数据,所以数据表现为65535。

6382b0e8685db5e1a43aa6f1938c086a.png

在全局搜索TxXferCount调用,我们可以看到TxXferSize 是发送buf的长度数据

HAL_StatusTypeDef?HAL_UART_Transmit_IT(UART_HandleTypeDef?*huart,?uint8_t?*pData,?uint16_t?Size)
{
??/*?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);

????huart->pTxBuffPtr?=?pData;
????huart->TxXferSize?=?Size;
????huart->TxXferCount?=?Size;

????huart->ErrorCode?=?HAL_UART_ERROR_NONE;
????huart->gState?=?HAL_UART_STATE_BUSY_TX;

????/*?Process?Unlocked?*/
????__HAL_UNLOCK(huart);

????/*?Enable?the?UART?Transmit?data?register?empty?Interrupt?*/
????__HAL_UART_ENABLE_IT(huart,?UART_IT_TXE);

????return?HAL_OK;
??}
??else
??{
????return?HAL_BUSY;
??}
}

此外我们还会发现一处 huart->TxXferCount 计数 自减 使用。

1cdf5362fc9e116e8ed7eca873633528.png

此处的函数如下, 伴随着一个很大的 TxXferCount开始自减, pdata16bits开始自加。刚开始越界的时候由于该内存被初始化过,所以没有问题,该循环执行一会之后,程序就会进入hardfault

HAL_StatusTypeDef?HAL_UART_Transmit(UART_HandleTypeDef?*huart,?uint8_t?*pData,?uint16_t?Size,?uint32_t?Timeout)
{
......

????huart->TxXferSize?=?Size;
????huart->TxXferCount?=?Size;

????while?(huart->TxXferCount?>?0U)
????{
??????if?(UART_WaitOnFlagUntilTimeout(huart,?UART_FLAG_TXE,?RESET,?tickstart,?Timeout)?!=?HAL_OK)
??????{
????????return?HAL_TIMEOUT;
??????}
??????if?(pdata8bits?==?NULL)
??????{
????????huart->Instance->DR?=?(uint16_t)(*pdata16bits?&?0x01FFU);
????????pdata16bits++;
??????}
??????else
??????{
????????huart->Instance->DR?=?(uint8_t)(*pdata8bits?&?0xFFU);
????????pdata8bits++;
??????}
??????huart->TxXferCount--;
????}
......
}

修改建议:

和硬件沟通过,他们的掉电机制,就是如此无法修改。所以我们进行软件的一些修改,因为会产生一个中断导致计数值自减,所以我们初步确认进行自减处进行限制,先增加一个零值判断。

huart->TxXferCount?==?0U

又考虑到我们单包数据单次不会超过150byte,所以又加上150字节的控制。(此处的数据流控制大家可以按照自己实际使用的情况进行酌情使用)

huart->TxXferCount???>?150U

原函数:

static?HAL_StatusTypeDef?UART_Transmit_IT(UART_HandleTypeDef?*huart)
{
......
????if?(--huart->TxXferCount?==?0U)
????{
??????/*?Disable?the?UART?Transmit?Complete?Interrupt?*/
??????__HAL_UART_DISABLE_IT(huart,?UART_IT_TXE);
????
??????/*?Enable?the?UART?Transmit?Complete?Interrupt?*/
??????__HAL_UART_ENABLE_IT(huart,?UART_IT_TC);
????}
?......
}

改为:

static?HAL_StatusTypeDef?UART_Transmit_IT(UART_HandleTypeDef?*huart)
{
......
????if?(huart->TxXferCount?==?0U?||?--huart->TxXferCount?==?0U?||?huart->TxXferCount???>?150U?)
????{
??????/*?Disable?the?UART?Transmit?Complete?Interrupt?*/
??????__HAL_UART_DISABLE_IT(huart,?UART_IT_TXE);
????
??????/*?Enable?the?UART?Transmit?Complete?Interrupt?*/
??????__HAL_UART_ENABLE_IT(huart,?UART_IT_TC);
????}
?......
}

最后代码可以正常的使用。

结语

这就是我分享的项目中遇到一个st官方库使用的问题,如果大家有更好的想法和需求,也欢迎大家加我好友交流分享哈。


作者:良知犹存,白天努力工作,晚上原创公号号主。公众号内容除了技术还有些人生感悟,一个认真输出内容的职场老司机,也是一个技术之外丰富生活的人,摄影、音乐 and 篮球。关注我,与我一起同行。

????????????????  END  ????????????????

推荐阅读

【1】C++的智能指针你了解吗?

【2】嵌入式底层开发的软件框架简述

【3】CPU中的程序是怎么运行起来的 必读

【4】cartographer环境建立以及建图测试

【5】设计模式之简单工厂模式、工厂模式、抽象工厂模式的对比

本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-06 12:23:33  更:2021-10-06 12:25:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:45:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码