手写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博客
