手写Autosar架构的CAN通讯协议栈2(CanIf模块详解-上)

目录

前言

参考资料介绍

Autosar架构Can通讯链路介绍

Can报文接收链路的理解与实现

功能实现1:软件过滤

功能实现2:接收报文查找算法(软件滤波类型)

功能实现3:Can邮箱索引在接收报文中的使用

功能实现4:接收报文为一段范围的CanId

源码展示

结语


前言

一直以来,我们都是以Autosar工具链使用者的角度去理解Autosar各个模块以及配置项,很多模块、配置项总感觉理解不够深入。

通过看Autosar标准规范去理解吧,规范又过于抽象

(Autosar标准规范举例)

看工具链的代码吧,代码量实在是太大,不知从何看起,实在是没办法从头到尾研究完某个模块的代码。

(HaloOS代码举例)

但仔细想了想,不理解或许是正常的。

因为人家Autosar工具链厂家设计的代码,是把Autosar标准的所有功能都实现了。

他们的目的,是把这套工具链卖给整个行业内的各个企业、匹配各种需求场景。

......

然而,如果我们以设计者的角度去理解Autosar模块,情况就完全不一样了。

这篇文章,我们就以设计者的角度,去从0去实现CanIf模块,从根源上理解Autosar CanIf模块功能、各个配置项的意义。

参考资料介绍

在我们进入正题之前,先把我们会用到的资料列一下:

1、Autosar标准规范-MCAL-Can模块规范

AUTOSAR_SWS_CANDriver.pdf

2、Autosar标准规范-Bsw-CanIf模块规范

AUTOSAR_SWS_CANInterface.pdf

3、HaloOs开源代码(Can模块代码、CanIf模块代码)

https://gitee.com/haloos/

Autosar架构Can通讯链路介绍

在深入了解CanIf模块之前,我们先从宏观视角了解一下CanIf模块在Autosar架构Can协议栈中的位置:

(图片来源:AUTOSAR_SWS_CANInterface.pdf)

可以看到,CanIf的上层模块非常多,比如CanTp(诊断报文)、PduR(应用报文)、CanNm(网管)等等。

下层模块我们主要关心2个:Can模块(Can控制器)、Can收发器模块。

好了,CanIf模块所处的位置及上下层模块有个概念就行,我们暂时不去纠结各个模块的作用。

接下来,我们就从微观角度,理解CanIf模块功能。

Can报文接收链路的理解与实现

功能实现1:软件过滤

我们在了解CanIf模块软件过滤的功能前,先来看看Can模块收到报文后,是怎么传给CanIf模块的:

当接收到CAN总线的Can报文时,Can模块会把CANID、报文类型、DLC这些内容一起传给CanIf模块,如下图所示:

其中Can报文类型已经包含在CanIf_RxIndication的CanId参数里面了。

举个栗子:

0x00000123则代表标准帧、CAN格式的0x123报文

0x01000123则代表标准帧、CANFD格式的0x123报文。

好了,了解了这些内容后,我们就可以来认识一下CanIf模块的软件过滤功能了。

我们从前面的Autosar架构图我们看到:"所有的Can报文都必须经过CanIf模块":

这句话实际上隐藏了很多信息:

为什么接收报文经过了CanIf模块,就知道要往哪个上层送?

如果是Can矩阵(或DBC)里面没有定义的报文,CanIf能知道上层模块是谁吗?

因此,对于接收报文来说,很重要的一个功能就出来了:软件过滤。

CanIf模块会定义Can矩阵(或DBC)里所有需要接收的报文的CANID报文类型DLC

具体怎么定义呢?

我们来看下CanIf模块的代码:

可以看到,上图中结构体数组大小为2,即定义了2条接收报文。(这个结构体数组我们下面会经常用到,hrh_rx_pdu_canif_hrh_cfg[ ]

数组中详细定义了2条接收报文对应的报文属性(CanID、DLC、报文类型)。

报文从Can模块送至CanIf模块后,CanIf模块会轮询上面这个数组,并把Can模块传过来的CanId跟数组中的每个报文的CanId进行对比。

情况1:如果在数组中找到了对应的CanId,那么就认为成功接收到了我们需要的报文,然后再根据用户需求决定是否进行报文DLC判断,如果需要判断DLC,且最后DLC检查通过了,则把报文送到对应的上层模块进行处理。

情况2:如果找完了一整个数组都没找到对应的CanId(实际上不是找完一整个数组,原因我们下面会讲到,我们这里暂时认为找完了一整个数组),或需要检查DLC,但DLC检查不通过,CanIf模块就会把这条报文丢掉,不再继续送到上层进行处理。

至于每条报文的上层模块是哪里,则取决于数组里面的这个参数:

朋友们,我们上面说的这么多内容,不就是对应Autosar工具链接收报文的这些配置项嘛:

功能实现2:接收报文查找算法( 软件滤波类型

好了,我们现在知道接收报文要进行软件过滤,从代码层面来说,就是要轮询CanIf模块的接收报文结构体数组hrh_rx_pdu_canif_hrh_cfg[ ],如下图所示(只有2条接收报文):

如果某个项目有几十条,上百条报文呢?

那么,如果还是一个简单的For循环从上到下轮询这个结构体数组,这样的查找方法就会导致浪费很多时间。

因此, CanIf模块中的**"SoftwareFilterType" (软件滤波类型)**功能就出来了。

于是,静态代码中把"线性查找"、"二分法查找 "等其它查找方式都实现了,然后用户开发时再根据项目报文数量,开启对应的滤波算法。

这就是软件滤波类型的由来了。

功能实现3:Can邮箱索引在接收报文中的使用

(额...,"邮箱索引的使用",这不能算功能,但这个内容很重要)

首先,我们假设要实现1路CAN总线,且共有5条接收报文

我们都知道,报文是通过CAN控制器的CAN邮箱收上来的,在开发的时候,每条报文都必须配置对应的CAN邮箱。

对应方式可以一条报文对应一个CAN邮箱,即FullCAN 。也可以多条报文对应一个邮箱,即BasicCAN。(关于FullCan和BasisCAN,这是属于CAN模块的内容,我们这里就不展开讲解了)

接下来,我们假设配置了3个接收邮箱。

CAN邮箱0(BasicCAN):接收2条报文(如:0x001,0x002)

CAN邮箱1(BasicCAN):接收2条报文(如:0x003,0x004)

CAN邮箱2(FullCAN):接收1条报文(如0x005)

我们前面说了,CanIf模块接收到报文后会轮询接收报文结构体数组hrh_rx_pdu_canif_hrh_cfg[ ],我们接收的5条报文的结构体数组如下示(代码省略部分内容)

于是,我们的问题就来了。

假设现在CAN模块收到了CAN报文的ID为0x005,然后送到了CanIf模块,如果我们不管CAN邮箱,直接轮询整个CanIf模块的接收报文结构体数组hrh_rx_pdu_canif_hrh_cfg[ ],如下图所示:

当然了,这里我们只有5条报文,报文少,轮询一下也没什么问题。

但是,如果情况变成这样:我们有100条报文要接收,Can邮箱0、Can邮箱1的报文加起来是99条,报文0x005还是在Can邮箱2里面,且还是只有1条

这种情况下,如果还是这样轮询,就实在太傻了,过于浪费时间了。

所以,为了避免这种情况,Can邮箱索引的作用就来了。

这个Can邮箱索引,是指每个Can邮箱都有1个对应的号码,即邮箱ID(邮箱ID从0开始递增),举例如下图所示:

然后,我们把CanIf模块定义好的每条接收报文,都对应上所属于CAN邮箱。

HaloOs它的实现方式如下:

使用"NofRxPdus"这个参数表示这个邮箱有多少条报文,再通过"RxPduList"这个参数指向接收报文结构体数组**hrh_rx_pdu_canif_hrh_cfg[ ]**中对应的首条报文。

于是,接收到Can模块在接收到CanId为0x005的报文后,由于是从Can邮箱2收上来的,且Can邮箱2是FullCan,只有1条报文。

因此,无论Can邮箱0、Can邮箱1有多少条报文,对于报文0x005来说,完全不用轮询数组,直接就能找到了CanIf模块报文结构体数组**hrh_rx_pdu_canif_hrh_cfg[ ]**所在的位置,如下图所示。

而如果Can模块在是接收到CanId为0x002的报文,由于Can邮箱0只有2条报文,则只需要轮询CanIf模块报文结构体数组**hrh_rx_pdu_canif_hrh_cfg[ ]**中的2个元素就可以了,如下图所示:

朋友们,这时候感受到Can邮箱Id的作用了吧。

我们再来看一下CanIf模块的标准接收接口:

从上图可以看到,CanIf_RxIndicaiton函数的参数里面就有报文对应的Can邮箱ID

朋友们,这就是为什么我们在工具链配置CanIf模块的接收报文时,接收报文要索引Can模块的Can邮箱(如下图所示)

功能实现4:接收报文为一段范围的CanId

接收一段范围的CanId这个功能一般情况下主要是用于接收Can网管报文

这个功能实际上很好理解,

比如Can网管报文ID范围为0x500-0x57F,我们不可能在CanIf模块定义0x500-0x57F中的每条报文吧?

因此,我们只需要在CanIf模块的报文结构体数组**hrh_rx_pdu_canif_hrh_cfg[ ]**中定义一个含CanIf范围的报文就可以了,如下图所示:

在接收到Can报文后,只需要判断一下Canid是否在指定的范围内即可。

对应的CanIf模块配置项如下图所示:

源码展示

在把我们上面讲的功能捋清楚后,我们再来看看源代码,这样就非常清晰了。

我们这里仅简单举例,具体大家可以去下载HaloOs的源码研究。

结语

大家有兴趣也可以打开Autosar工具链(HaloOs工具链)看看,与接收报文相关的功能与配置项,就是我们上面讲到的这些配置项,其实它没多少东西的。

下篇文章,我们继续讲解CanIf模块的功能。


返回目录:

Autosar BSW 开发笔记(目录)-CSDN博客

相关推荐
正午游巳8 天前
第二十节:MCAL GPT理论
汽车·嵌入式·autosar·车载嵌入式
正午游巳9 天前
第二十一节:MCAL GPT实操
汽车·autosar·汽车电子·车载嵌入式
酷酷的boy10 天前
AUTOSAR下网络时间(CAN)与本地 RTC 同步。
autosar·汽车电子
AUTOSAR组织1 个月前
AUTOSAR CP NvM 模块解析
汽车·autosar·软件架构·软件·标准
赞哥哥s1 个月前
2025年终总结简版
autosar
汽车软件工程师0011 个月前
ChatGpt指导嵌入式软件开发能力——2、TriCore深度专项训练
人工智能·chatgpt·autosar
汽车软件工程师0011 个月前
ChatGpt指导嵌入式软件开发能力
人工智能·chatgpt·autosar
汽车软件工程师0011 个月前
vector autosar,CAN 总线上能看到报文RTE 收不到信号COM 层 IPDU Callout 不触发
autosar
汽车软件工程师0011 个月前
vector autosar配置一个CAN接收报文,RTE层发现并未接收到信号,怎样查这个问题
开发语言·autosar
Dotrust东信创智1 个月前
汽车安全通信的行业标准密码-E2E
e2e·autosar·preevision