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

文章目录

背景介绍

问题描述

分析排查

解决方案

总结归纳


背景介绍

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

        乍一看感觉挺简单,想着直接用一个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工程,可以到笔者的主页查找和下载。


        版权声明:原创文章,转载请注明出处与链接,违者必究!

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

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

相关文章

全球前十大交易所KuCoin遭美司法部、CFTC起诉!违反银行保护法、反洗钱!交2200万“保护费”还不够?

昨&#xff08;26&#xff09;日晚间&#xff0c;美国司法部释出重磅消息&#xff0c;全球排名前十的中心化加密货币交易所KuCoin及其创始人Chun Gan和Ke Tang&#xff0c;遭到美国南区纽约地区检察官办公室起诉&#xff0c;理由是KuCoin及其两位创始人违反了美国反洗钱规范和未…

Mysql的高级语句3

目录 一、子查询 注意&#xff1a;子语句可以与主语句所查询的表相同&#xff0c;但是也可以是不同表。 1、select in 1.1 相同表查询 1.2 多表查询 2、not in 取反&#xff0c;就是将子查询结果&#xff0c;进行取反处理 3、insert into in 4、update…

el-table 表格全选

<template><div><el-checkbox v-model"checked" :disabledcheckedDis change"onAllSelectChange">全选</el-checkbox><el-table ref"multipleTable" :data"tableData" tooltip-effect"dark" sel…

面试八股文之JAVA基础

JAVA基础 DNS、CDN&#xff1f;如何实现对象克隆?父子类静态代码块, 非静态代码块, 构造方法执行顺序?String s new String("abc") 创建了几个对象, 分别放到哪里?OSI网络模型七层&#xff1f;应用层协议&#xff1f;http协议和https协议区别&#xff1f;传输层协…

Spring高级面试题-2024

Spring 框架中都用到了哪些设计模式&#xff1f; 1. 简单工厂&#xff1a; ○ BeanFactory&#xff1a;Spring的BeanFactory充当工厂&#xff0c;负责根据配置信息创建Bean实例。它是一种工厂模式的应用&#xff0c;根据指定的类名或ID创建Bean对象。2. 工厂方法&#xff…

插入排序和希尔排序:

插入排序 1. 算法思想&#xff1a; 由数组下标为1 开始的数值作为判断依据&#xff0c;与之前的数据从后往前比较定义tmp 暂存判断的数值&#xff0c;若前面的数据大于tmp&#xff0c;则将前面的数据向后移动 : arr[j1]arr[j]若对比的数据比tmp 大&#xff0c;则往后移&#…

展会邀约 |立仪科技邀您相聚四月

2024深圳国际传感器与应用技术展览会 2024年04月14日盛大开幕&#xff01; 立仪科技作为参展商 诚挚地邀请各地朋友莅临参观交流 2024成都国际工业展览会 2023年04月24-26日盛大开幕&#xff01; 立仪科技作为参展商 诚挚地邀请各地朋友莅临参观交流 深圳立仪科技有限公司…

Ubuntu上安装d4rl数据集

Ubuntu上安装d4rl数据集 D4RL的官方 github: https://github.com/Farama-Foundation/D4RL 一、安装Mujoco 1.1 官网下载mujoco210文件 如果装过可以跳过这步 链接&#xff1a;https://github.com/deepmind/mujoco/releases/tag/2.1.0 下载第一个文件即可。我这里是在windo…

拥抱C++的深度和复杂性,挖掘更多可能 !——《C++20高级编程(第5版)》

&#xff0c;C难以掌握&#xff0c;但其广泛的功能使其成为游戏和商业软件应用程序中最常用的语言。即使是有经验的用户通常也不熟悉许多高级特性&#xff0c;但C20的发布提供了探索该语言全部功能的绝佳机会。《C20高级编程(第5版)》为C的必要内容提供了一个代码密集型、面向解…

TF卡系统备份与还原

本文介绍一种用备份还原方法&#xff0c;快速实现TF启动卡制作&#xff0c;使用方便&#xff0c;无需安装linux系统&#xff0c;需要使用Diskgnius软件。 安装Diskgnius&#xff0c;64位绿色版本&#xff0c;无需安装&#xff0c;直接运行即可。运行Diskgnius软件&#xff0c;将…

【感悟《剑指offer》典型编程题的极练之路】02字符串篇!

​ 个人主页&#xff1a;秋风起&#xff0c;再归来~ 文章所属专栏&#xff1a;《剑指offer》典型编程题的极练之路 ​​​​​​ 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c…

可怜的百度人

可怜的百度股民 注意&#xff0c;这里说的是持有百度股票的股民&#xff0c;不是百度&#xff0c;百度没啥好可怜的。 前天&#xff08;3月25日&#xff09;中午&#xff0c;财联社爆料百度和 Apple 达成合作&#xff0c;百度将为苹果今年发布的 iPhone16、Mac 系统和 iOS18 提…

【SpringSecurity】基础入门

目录 权限管理什么是权限管理认证授权权限管理解决方案Shiro开发者自定义Spring Security Spring Security特性Spring、Spring Boot 和 Spring Security 三者的关系整体架构1.认证AuthenticationManagerAuthenticationSecurityContextHolder 2.授权AccessDecisionManagerAccess…

JRT菜单

上一章搭建了登录界面的雏形和抽取了登录接口。给多组使用登录和菜单功能提供预留&#xff0c;做到不强行入侵别人业务。任何产品只需要按自己表实现登录接口后配置到容器即可共用登录界面和菜单部分。最后自己的用户关联到JRT角色表即可。 登录效果 这次构建菜单体系 首先用…

错误记录

Packet for query is too large 错误原因 一般是没有修改Mysql允许传输的最大数据包大小&#xff0c;使用 SHOW VARIABLES LIKE %max_allowed_packet%;可以看到默认的大小&#xff0c;一般默认为1M。 处理方法 暂时修改&#xff1a;重启mysql后失效 --修改为10M set global…

使用 Web Components 实现输入法更换皮肤 (vue)

更换皮肤 (界面外观) 是拼音输入法的常见功能. 要实现更换皮肤, 有许多种不同的具体技术方案可以使用. 本文选择 Web Components 技术 (vue) 来实现这个功能. 目录 1 效果展示 1.1 发布新版本 2 Web Components 简介3 vue 使用 Web Components 3.1 使用 vue 实现 Web Compon…

比对word文档并提取差异片段(java版)

整体比较 有时候&#xff0c;我们想比对两个word文档&#xff0c;标记出两个文档之间的差异&#xff0c;这样一眼就能看出来修改了哪些地方&#xff0c;如下图,左边文档中的扩招2000人删除了&#xff0c;辞呈改成了说明&#xff0c;新增了并且加重处罚等文字&#xff0c;是否一…

DP背包模型

目录 采药&#xff08;01背包&#xff09;代码实现 装箱问题&#xff08;01背包&#xff09;代码实现 *宠物小精灵之收服&#xff08;二维费用01背包&#xff09;题目分析代码实现 数字组合&#xff08;01背包&#xff09;代码实现 买书&#xff08;完全背包&#xff09;代码实…

【学习】软件测试中误区汇总分析

大家有没有想过这个问题&#xff1a;软件测试中有哪些误区呢&#xff1f;想起这个题目&#xff0c;是因为最近遇到好几次关于这方面的讨论。发觉即便做过几年测试的老员工也或多或少有些这方面的困惑。当然一家之言&#xff0c;仅作抛砖引玉之谈。 误区一&#xff1a;测试就是…

git提交-分支开发合并-控制台操作

git提交-分支开发合并-控制台操作 git的基本概念工作区、暂存区和版本库工作区&#xff1a;就是你在电脑里能看到的目录&#xff08;隐藏目录 .git不算工作区&#xff09;。暂存区&#xff1a;英文叫 stage 或 index。一般存放在本地的.git目录下的index 文件&#xff08;.git/…