【研发日记】C/C++开发避坑秘籍(一)——CAN接收Buffer溢出Bug

这篇具有很好参考价值的文章主要介绍了【研发日记】C/C++开发避坑秘籍(一)——CAN接收Buffer溢出Bug。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

c++can接收,C/C++,C/C++,CAN总线,车载网络,嵌入式软件,MCU,域控制器,Bug调试

文章目录

背景介绍

问题描述

分析排查

解决方案

总结归纳


背景介绍

        在一个嵌入式软件项目中,有一段使用C语言写的嵌入式代码,功能是把CAN总线上的几帧报文接收进来,并解析出数据。示例如下:

c++can接收,C/C++,C/C++,CAN总线,车载网络,嵌入式软件,MCU,域控制器,Bug调试

        乍一看感觉挺简单,想着直接用一个while循环,周期提取CAN buffer中缓存的数据就行了。但是就这么一个小应用让我栽了跟头,在整个工程中排查了几个小时才找到问题,下面就来分享一下这一小段个人经历。

        一开始代码调试的时候很顺利,一共接收5帧报文,总共40个信号,相关代码大概是下面这个样子:

void main(void)
{
//省略若干行

	if(Timer10ms == 1){
		do{
			ret = GetCANFrame(1, &Ext, &ID, &Length, &DataBuf);
			if(ret){
				if(ID == 0x100){
					memcpy(&SignalArray[0], DataBuf, 8)
				}
				if(ID == 0x101){
					memcpy(&SignalArray[8], DataBuf, 8)
				}
				if(ID == 0x102){
					memcpy(&SignalArray[16], DataBuf, 8)
				}
				if(ID == 0x103){
					memcpy(&SignalArray[24], DataBuf, 8)
				}
				if(ID == 0x104){
					memcpy(&SignalArray[32], DataBuf, 8)
				}
			}
			
		}while(ret && (i <= 100))
	}
	
//省略若干行	
}

问题描述

        按照上述示例开发的软件,烧录到ECU中在实验室桌面上调试,使用Vector的CAN接口卡模拟残余总线发送0x100、0x101、0x102、0x103、0x104这五帧报文,ECU都能正常接收。但是把ECU集成到实车之后,却收到反馈ECU的CAN接收有丢帧现象。

分析排查

        把实车上的CAN报文Log打开之后,看到总线上除了0x100、0x101、0x102、0x103、0x104这五帧报文之外,还有几十个其他ID的报文,所以推测是这些残余总线报文干扰了ECU的CAN接收。所以在实验室桌面上把这些残余总线模拟出来,复现了实车上的CAN接收丢帧现象,这就锁定了是残余总线的问题。

        为了更具体的分析Bug机理,在代码中加入了一些调试信息,每个ID接收到之后都把相应的计数加1,示例如下:

void main(void)
{
//省略若干行

	if(Timer10ms == 1){
		do{
			ret = GetCANFrame(1, &Ext, &ID, &Length, &DataBuf);
			if(ret){
				if(ID == 0x100){
					memcpy(&SignalArray[0], DataBuf, 8)
					FrameCount[0]++;
				}
				if(ID == 0x101){
					memcpy(&SignalArray[8], DataBuf, 8)
					FrameCount[1]++;
				}
				if(ID == 0x102){
					memcpy(&SignalArray[16], DataBuf, 8)
					FrameCount[2]++;
				}
				if(ID == 0x103){
					memcpy(&SignalArray[24], DataBuf, 8)
					FrameCount[3]++;
				}
				if(ID == 0x104){
					memcpy(&SignalArray[32], DataBuf, 8)
					FrameCount[4]++;
				}
			}
			
		}while(ret && (i <= 100))
	}
	
//省略若干行	
}

        烧录上述软件后可以看到,发生CAN接收丢帧时都伴随着残余总线报文的集中突增,总线瞬时100%负载率会持续十多ms,所以推测可能是残余总线报文挤占了CAN接收buffer。翻了一下CAN接收buffer的配置,是40帧的size。根据CAN总线500k的波特率计算100%负载率持续十多ms总线上会有50帧左右的报文。而我的代码是10ms从CAN接收buffer提取一次数据,这样必然会导致CAN接收buffer塞满后无法继续接收,也就是丢帧的现象。

解决方案

        针对上述CAN接收buffer溢出的问题,解决方案可以从如下公式的每一个因子入手:


        Buffer占用空间 = 单位时间最多的报文数量 * 提取Buffer的周期                    公式(1)


        方案一:扩大buffer size配置其他条件不变,这里只要把原本40帧的size扩大到45帧左右即可。因为500k波特率的CAN总线,10ms时间内最多产生的报文不会超过45帧。这个方案需要MCU硬件资源的支持。

        方案二:避免报文突增其他条件不变,这里只要在CAN协议中约定好,各个ECU节点都按既定节拍发送报文,避免瞬时负载率拉升到100%,或者控制100%负载率持续时间要小于10ms。这样任何一个10ms周期内,总线上的报文最多也不会超过40帧,现有的40帧的Buffer size就够用了。这个方案需要总线上各个节点ECU的配合。

        方案三:降低波特率其他条件不变,这里只要把原本500k的波特率降下来,也就降低了单位时间最多的报文数量,实现的原理跟方案二一样。这个方案也需要总线上各个节点ECU配合变更波特率。

        方案四:CAN接收ID过滤其他条件不变,这里只要在底层CAN接收模块中做一个ID过滤,只允许0x100、0x101、0x102、0x103、0x104这五帧报文进入CAN接收buffer,实现的原理也跟方案二一样。这个方案只需要自己的ECU修改底层软件即可,不需要其他方面的支持和配合。

        方案五:缩短提取Buffer的周期其他条件不变,这里只要把原本10ms的提取周期改成5ms或者其他小于10ms的数值即可。因为因为500k波特率的CAN总线,5ms时间内最多产生的报文在20帧左右,远远低于40帧的buffer空间。这个方案只需要自己的ECU修改应用软件即可,不需要其他方面的支持和配合。

        上述五种解决方案各有优劣,适用于不同的项目开发情景。方案一适用于ECU开发的早期,在MCU选项时,或者在软件架构定型时,就根据CAN总线的应用需求为buffer size留出足够的资源空间。方案二和方案三适用于系统集成阶段,在制定整车的网络协议时,约定好各个ECU节点需要遵循的公共基础和公用策略。方案四和方案五适用于ECU的应用开发阶段,在开发具体功能时,更具其他已经设定的条件,决定如何设计ID过滤和报文提取周期。

总结归纳

        那么这个代码调试过程,发现的问题可以积累下来这么几条小经验以供自己将来使用,也给广大网友参考:

        1、CAN网络相关的模块设计与开发时,不光要考虑自身ECU节点的发送和接收,还要考虑其他节点不相关报文的实际存在。对于不能确定确定参数时,就要按照最严酷的情况来估算,比如残余总线瞬时负载率达到100%,而且还持续挺长一段时间。

        2、方案设计用的是等式(解决方案中的哪个等式),但是软件开发中用的是不等式,因为实际情况中要面对的有各种误差,所有在留下余量时,等式中的“=”就要变成“>”或者“<”。比如理论计算的buffer size是40帧,这里就应该使用>40帧。

        以上就是本人在解决CAN接收Buffer溢出Bug时,一些个人理解和分析的总结,首先介绍了基本的项目背景,然后描述了问题的想象,最后分析排查了Bug原因,并给出了问题解决方案。

        后续还会分享其他的,使用C/C++研发时遇到的Bug,欢迎评论区留言、点赞、收藏和关注,这些鼓励和支持都将成文本人持续分享的动力。

        述例程使用的Demo工程,可以到笔者的主页查找和下载。


        版权声明:原创文章,转载请注明出处与链接,违者必究!文章来源地址https://www.toymoban.com/news/detail-847413.html

到了这里,关于【研发日记】C/C++开发避坑秘籍(一)——CAN接收Buffer溢出Bug的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【研发日记】Matlab/Simulink技能解锁(三)——在Stateflow编辑窗口Debug

    文章目录 前言 State断点 Transition断点 条件断点 按State步进 Watch Data Value Sequence Viewer

    2024年03月18日
    浏览(31)
  • 【研发日记】Matlab/Simulink技能解锁(一)——在Simulink编辑窗口Debug

    文章目录 前言 时间阈值断点 信号阈值断点 周期步进 Signal Value Lable Data Inspector 分析和应用 总结         近期在一些研发项目中使用Matlab/Simulink时,遇到了挺多费时费力的事情。所以利用晚上和周末时间,在这些方面深入研究了一下,解锁了一些新技能。后面会用若干篇

    2024年03月28日
    浏览(34)
  • CAN接收不到数据时的处理方法

    在调试CAN通讯协议时,经常会遇到无法接收到数据的情况,这个时候可以采用单步调试DEBUG的方法,先观测CAN接收寄存器RFIFO0或者RFIFO1的值是否会发生变化,即是否真的接收到了数据。 如果寄存器RFIFO0或者RFIFO1如上图所示接收到了数据,但是仍旧没有收到数据,这个时候首先

    2024年02月16日
    浏览(25)
  • CAN通讯配置及接收报文--学习笔记1~2

    硬件设备 STM32F103C8T6工控板、USB转TLL接口、TLL转CAN串口小板,继电器,降压模块,警示灯 软件工具 CANPro协议分析平台、CubeMX、MDK-ARM 实现过程及功能 基础功能:PC端通过CANPro设置报文,发出串口信号经过USB和串口小板转成CAN信号,在单片机上接收特定ID的报文,通过判断需要

    2024年02月09日
    浏览(29)
  • CAN2无法发送和接收数据问题重要原因

    一、CAN2无法发送数据         在调试CAN2总线收发过程中,官方给的代码例程是是CAN1的,根据CAN1的直接转换为CAN2,是不能正常收发的。单独使用CAN2的时候,在确保硬件连接正常情况下,必须先要打开CAN1的时钟,再打开CAN2时钟,顺序不能反。 二、CAN2无法接收数据    

    2024年02月07日
    浏览(29)
  • STM32F407的CAN2无法进入can接收中断的解决办法

    这个问题困扰了我两天,今天偶然看到一篇文章有讲这个:STM32 CAN1 CAN2 不能同时工作,最后原因竟然是。。。。 看了之后恍然大悟。下面贴上我的初始化代码: 主函数进行中断优先级分组和CAN初始化调用及使能 初始化代码: 中断服务函数: 效果展示:  CAN逻辑分析仪数据

    2024年02月13日
    浏览(31)
  • 【项目典型案例】-1-如何加快接收的CAN信号处理能力,提高发送CAN信号的响应

    点击返回「《Autosar_BSW高阶配置》总目录」 案例背景( 共 5 页精讲 ): 在实际的项目当中,有时遇到这样一个问题: 当 ECU 接收到一个 CAN 信号 A ,经过 软件 APP 层

    2023年04月25日
    浏览(31)
  • stm32 can滤波器接收指定的ID

    (slave_id=0x18010001为只接收的id号): 这一步是为了从32位的slave_id中提取出高16位作为CAN过滤器的ID高位部分。 (u32)slave_id 3:首先将slave_id强制转换为32位的无符号整数(u32),然后将其左移3位。这是为了将slave_id向左移动3位,为后续的位运算做准备。 0xFFFF0000:然后将结果与

    2024年01月22日
    浏览(30)
  • STM32F407 CAN模块发送接收数据异常

    现象: 1、CAN模块初始化成CAN_MODE_LOOPBACK模式 CAN模块通过HAL_CAN_AddTxMessage发送数据时,TX管脚能够发出数据,示波器也可以测量到数据波形,CAN使用中断接收HAL_CAN_ActivateNotification或者查询接收HAL_CAN_GetRxMessage都可以接收到正确的数据(和发送的数据一致),但是CAN接口却没有波

    2024年02月12日
    浏览(25)
  • 【STM32】CAN过滤器配置----接收特定ID发来的数据

    滤波器详细配置 (slave_id为只接收的id号): 1、对扩展数据帧进行过滤:(只接收扩展数据帧) 2、对扩展远程帧过滤:(只接收扩展远程帧) 3、对标准远程帧过滤:(只接收标准远程帧) 4、对标准数据帧过滤:(只接收标准数据帧) 5、对扩展帧进行过滤:(只接收扩展帧) 6、对标准帧进行

    2024年02月12日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包