【沁恒蓝牙MESH】CH582串口中断内存溢出导致MCU频繁重启

本文主要是介绍【沁恒蓝牙MESH】CH582串口中断内存溢出导致MCU频繁重启,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文主要记录了【沁恒蓝牙mesh】CH582串口中断内存溢出导致MCU频繁重启
由于开发疏忽,导致的数组内存溢出,是入门嵌入式开发经常忽视的错误,用以记录,共勉!!

目录

  • 1. 遇到问题描述以及解决
    • 1.1 问题一:串口中断导致MCU频繁重启
      • 1.1.1【场景描述】
      • 1.1.2 【问题描述】
      • 1.1.3 【问题定位】
      • 1.1.4 【问题解决】

  • 💖 作者简介:大家好,我是喜欢记录零碎知识点的小菜鸟。😎
  • 📝 个人主页:欢迎访问我的 Ethernet_Comm 博客主页🔥
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏:沁恒蓝牙mesh二次开发🍁
  • 💬格言:写文档啊不是写文章,重要的还是直白!🔥

1. 遇到问题描述以及解决

1.1 问题一:串口中断导致MCU频繁重启

1.1.1【场景描述】

硬件:沁恒的 CH582F 单片机, 海凌科 24G 雷达模组

引脚:海凌科雷达模组5个引脚和 CH582F 连,单片机PB4引脚(普通GPIO,下拉输入,采用IO查询的方式判断电平)

CH582F雷达模组
5vvcc
gndgnd
PB4out
RX3—PA4tx
RX3—PA5rx

1.1.2 【问题描述】

烧录程序后,发现 单片机一直 周期性的重启。。。。下图左侧为串口3的接受中断
在这里插入图片描述

1.1.3 【问题定位】

雷达:每间隔100ms 从TX引脚输出的数据为

[2023-12-01 07:58:27.167]# RECV HEX>
F4 F3 F2 F1 0D 00 02 AA 03 1E 00 5A 1E 00 64 00 00 55 00 F8 F7 F6 F5 
[2023-12-01 07:58:27.267]# RECV HEX>
F4 F3 F2 F1 0D 00 02 AA 03 1E 00 64 1E 00 64 00 00 55 00 F8 F7 F6 F5 
[2023-12-01 07:58:27.367]# RECV HEX>
F4 F3 F2 F1 0D 00 02 AA 03 1E 00 64 1E 00 64 00 00 55 00 F8 F7 F6 F5 
[2023-12-01 07:58:27.469]# RECV HEX>
F4 F3 F2 F1 0D 00 02 AA 03 1E 00 64 1E 00 64 00 00 55 00 F8 F7 F6 F5 
[2023-12-01 07:58:27.562]# RECV HEX>
F4 F3 F2 F1 0D 00 02 AA 03 1E 00 64 1E 00 64 00 00 55 00 F8 F7 F6 F5 

将雷达模组拿掉,程序就正常了,因此一个个引脚查问题,最终定位问题为:

软件中开启了串口3的接收中断,雷达模组频繁的发送数据导致单片机频繁进入中断,造成重启

检查软件中的中断咋写的,,,,,

1.1.4 【问题解决】

曾经在ESP32 开发中翻过这样一个错误:【esp32】解决以太网+mqtt堆栈溢出问题 报错 no mem for receive buffer,这个是由于动态申请的内存没有是释放导致栈空间不足,MCU反复重启

数组溢出导致的栈内存被冲刷掉,导致内存溢出而使得MCU重启

问题定位如下, 我的软件串口接收中断竟然是这么写的::::::令人发指!!!!

串口中断将接收到的数据存储到 uart_rx_buffer[]数组中, 但是,,我定义了一个 100 大小的数组,却 user_rx_buffer_write_index & user_rx_buffer_length_mask 去接收数据。。。。

本意是这样的 定义一个 1024 大小的数组,每接收到一个自己 user_rx_buffer_write_index 自加1,然后通过 user_rx_buffer_write_index & user_rx_buffer_length_mask 将范围限制在 1-1024 范围内,防止数组溢出。。。。当时应该是担心占用内存太大,手动将uart_rx_buffer[1024]改为了 uart_rx_buffer[100],但是忘记修改 user_rx_buffer_length_mask变量的值了。。

造成的结果就是,我定义了100维的数组,缺往里边存了 最大1024个字节,那剩下的900字节空间就把其他栈空间占用了,,冲掉了哪些变量的值???不得而知,但是造成的结果就是单片机不断重启了。。。。。。。。

解决方式:

将数组改为 1024 维的,或者数组100维不变,将掩码的值改为99,别造成内存溢出,就可以了,

实测修改后,就不会重启了

uint8_t uart_rx_buffer[100]={0}; 
uint16_t user_rx_buffer_length_mask = 1024-1;
uint16_t user_rx_buffer_write_index = 0;
uint8_t trigB = 7 ;
uint8_t uart_rx_done = 0;__INTERRUPT
__HIGH_CODE
void UART3_IRQHandler(void)
{uint16_t error;int i = 0;switch(UART3_GetITFlag()){case UART_II_LINE_STAT:  // 线路状态错误UART3_GetLinSTA();break;case UART_II_RECV_RDY: // 数据达到设置触发点while( R8_UART3_RFC > 1) {  // 这个方式必须保证uart的接收触发中断是大于1字节的uart_rx_buffer[user_rx_buffer_write_index & user_rx_buffer_length_mask] = R8_UART3_RBR;user_rx_buffer_write_index += 1;}break;case UART_II_RECV_TOUT: // 接收超时,暂时一帧数据接收完成for(i = 0; i < R8_UART3_RFC; i++){iRxBuff[i] = UART3_RecvByte();//UART3_SendByte(iRxBuff[i]);}  break;case UART_II_THR_EMPTY:break;case UART_II_MODEM_CHG:break;default:break;}
}

知识点:

当 b = 2^n 的时候:a % b = a & (b-1)

这篇关于【沁恒蓝牙MESH】CH582串口中断内存溢出导致MCU频繁重启的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/444225

相关文章

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

如何使用C#串口通讯实现数据的发送和接收

《如何使用C#串口通讯实现数据的发送和接收》本文详细介绍了如何使用C#实现基于串口通讯的数据发送和接收,通过SerialPort类,我们可以轻松实现串口通讯,并结合事件机制实现数据的传递和处理,感兴趣... 目录1. 概述2. 关键技术点2.1 SerialPort类2.2 异步接收数据2.3 数据解析2.

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

Golang基于内存的键值存储缓存库go-cache

《Golang基于内存的键值存储缓存库go-cache》go-cache是一个内存中的key:valuestore/cache库,适用于单机应用程序,本文主要介绍了Golang基于内存的键值存储缓存库... 目录文档安装方法示例1示例2使用注意点优点缺点go-cache 和 Redis 缓存对比1)功能特性

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

Linux内存泄露的原因排查和解决方案(内存管理方法)

《Linux内存泄露的原因排查和解决方案(内存管理方法)》文章主要介绍了运维团队在Linux处理LB服务内存暴涨、内存报警问题的过程,从发现问题、排查原因到制定解决方案,并从中学习了Linux内存管理... 目录一、问题二、排查过程三、解决方案四、内存管理方法1)linux内存寻址2)Linux分页机制3)

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常