文章包含了AUTOSAR基础软件(BSW)中CanIf模块相关的内容详解。本文从AUTOSAR规范解析,ISOLAR-AB配置以及模块相关代码分析三个维度来帮读者清晰的认识和了解CanIf这一基础软件模块。文中涉及的ISOLAR-AB配置以及模块相关代码都是依托于ETAS提供的工具链来配置与生成的,与AUTOSAR规范之间可能会有些许的出入,但总体的功能要点与处理流程都应该是一致的。
CanIf模块作为AUTOSOR的CAN栈最下层模块,向CAN栈的上层提供了不同CAN控制器与收发器的统一抽象接口。CanIf模块主要的作用是将上层需要发送的数据转化为对应CAN帧格式之后通过CAN驱动对应的MailBox发送出去,并将底层驱动接收的数据转发到对应的上层接收模块,CanIf还提供控制器与收发器模式控制的接口给其余基础软件模块。这部分配置由RTA-BSW自动生成,但是由于可能底层的HW Object数目不足以满足通信矩阵中所有的Message用FullCan收发,我们就需要在CanIf这里将多个PDU映射到一个MailBox。CanIf还提供了动态L-PDU的功能来支持运行时根据特定条件动态创建的L-PDU,利用同一个MailBox传输可变CANID与数据长度的CAN帧。
目录
Transmit request (single CAN Driver)
Transmit confirmation (interrupt mode)
Transmit confirmation (with buffering)
Receive indication (interrupt mode)
AUTOSAR规范解析
概述
如下图所示,CAN接口模块位于下层CAN设备驱动(控制器与收发器驱动)和上面的通信服务层(即CAN状态管理器、CAN网络管理、CAN传输协议,PDU路由器)。它是上层通信层与CAN驱动程序之间的抽象接口。
CAN 接口模块提供了一个独特的接口,用于管理不同的CAN硬件设备,类型包含CAN控制器与CAN收发器。因此多个芯片的内部或者外部CAN控制器或者CAN收发器可以根据与物理CAN通道完成映射后由CAN状态管理模块控制。
CAN接口模块由所有独立的CAN硬件功能组成,这些功能属于相应的ECU的CAN通信设备驱动程序。这些功能在CAN接口模块中实现一次,因此底层的CAN设备驱动程序只专注于访问和控制相应的特定CAN硬件设备。
Canlf模块满足PduR和COM堆栈等上层通信模块的主控制流和数据流要求,它包括:发送请求处理、发送确认/接收指示/错误通知和CAN控制器的启动/停止,并参与到休眠唤醒与网络管理等功能中。它的数据处理和通知APIs是基于CAN的L-SDU,而控制和模式处理APIs源自CAN控制器提供的机制。
在传输请求的情况下,Canlf用相应的参数完成L-PDU传输,并通过适当的CanDr将CANL-PDU中继到对应CAN控制器。在接收端,Canlf将接收到的L-PDU作为L-SDU分发给上层。接收的L-SDU和上层之间的对应关系是静态配置的。在发送确认时,Canlf负责向上层通知成功传输。
Canlf模块提供了对CAN驱动程序和CAN收发器驱动程序服务的抽象访问,用于控制和监视CAN网络。Canlf模块向下将CAN状态管理器发出的状态更改请求转发给下层CAN设备驱动程序,向上将CAN驱动程序/CAN收发器驱动程序事件转发给相应的NM模块。
缩略语与概念
- CAN L-PDU:CAN协议数据单元。由标识符、数据长度和数据(SDU)组成,CAN驱动程序可见。
- CAN L-SDU:CAN服务数据单元。在CAN L-PDU内传输的数据。对CAN接口的上层(例如PDU Router)可见。
- CanDrv:CAN驱动模块。
- CAN FD:具有可变数据速率的CAN。
- CanId:CAN标识符。
- CanIf:CAN接口模块。
- CanNm:CAN网络管理模块。
- CanSm:CAN状态管理模块。
- CanTp:CAN传输层模块。
- CanTrcv:CAN收发器驱动模块。
- CanTSyn:CAN上的全局时间同步。
- ComM:通信管理模块。
- DCM:诊断通信管理模块。
- EcuM:ECU状态管理模块。
- HOH:CAN硬件对象句柄。
- HRH:CAN硬件接收句柄。
- HTH:CAN硬件发送句柄。
- J1939Nm:J1939网络管理模块。
- J1939Tp:J1939传输层模块。
- PduR:PDU路由模块。
- PN:部分特定网络。
- SchM:调度模块。
- Buffer:固定大小的单个数据单元(如CANID、数据长度、SDU等)存储在RAM中的专用存储地址。
- CAN communication matrix:描述整个CAN网络,包括:
- 网络中的CAN节点。
- 所有CAN PDU的定义(标识符,数据长度等)。
- 所有所有CAN PDU的发送以及接收方。
- CAN Controller:CAN控制器是一个CPU片上或外部独立的硬件设备。一个CAN控制器对应到一个物理通道。
- CAN Device Driver:CAN驱动程序和CAN收发器驱动程序的通用术语。
- CAN Hardware Unit:CAN硬件单元可以由一个或多个相同类型的CAN控制器和一个两个或多个CAN RAM区域组成。CAN硬件单元位于芯片上或作为外部设备。CAN硬件单元由一个CAN驱动器表示。
- CanIf Controller mode state machine:这实际上不是一个受传输请求影响的状态机。这是一个适当的CAN控制器当前的状态抽象。状态转换只能通过CanSM之类的上层模块或BusOff之类的外部事件来实现。
- CanIf Receive L-PDU / CanIf Rx L-PDU:被设置为“从下到上层”的L-PDU。
- CanIf Receive L-PDU buffer / CanIfRxBuffer:位于Canlf中的单个RAM缓冲区,用于存储整个接收的L-PDU。
- CanIf Transmit L-PDU / CanIf Tx L-PDU:被设置为“从上到下层”的L-PDU。
- CanIf Transmit L-PDU buffer / CanIfTxBuffer:位于Canlf中的单个CanlfTxBuffer元素,用于存储一个或多个Canlf Tx L-PDU。如果将单个CanlffTxBuffer元素的缓冲区大小设置为0,则CanlfTxBuffer元素仅用于引用 HTH。
- Hardware object / HW object:CAN硬件对象被定义为CAN硬件单元或者CAN控制器的CAN RAM中的PDU缓冲区。
- Hardware Receive Handle(HRH):硬件接收句柄(HRH)由CAN驱动程序定义和提供。每个HRH通常仅表示一个硬件对象。HRH用作Canlf的功能参数(例如软件过滤)。
- Hardware Transmit Handle(HTH):硬件发送句柄(HTH)由CAN驱动程序定义并提供。每个HTH通常代表一个或多个配置为CAN硬件发送缓冲池的CAN硬件对象。
- Inner priority inversion:由于同一传输硬件对象中存在待处理的低优先级L-PDU所以高优先级L-PDU的传输被阻止。
- Integration Code:集成商需要管理的代码,以适应非标准化的功能。例如,ECU状态管理的调用和各种其他BSW模块的回调。I/O硬件抽象也称为集成代码。
- Lowest In - First Out / LOFO:这是一个数据存储过程,它总是会提取值最低的元素。
- Outer priority inversion:两个连续传输L-PDU之间存在的时间间隔。在这种情况下,来自另一个节点的较低优先级的L-PDU可以阻止发送自己的较高优先级的L-PDU。在这种情况下,较高优先级的L-PDU无法在网络访问期间参与仲裁,因为较低优先级的L-PDU已经赢得了仲裁。
- Physical channel:物理信道表示从CAN控制器到CAN网络的接口。CAN硬件单元的不同物理信道可以访问不同的网络。
- Tx request:从Canlf的上层模块向CAN接口模块申请发送。
模块依赖
本节描述了与AUTOSAR基本软件体系结构中的其他模块的关系。它包含了对CAN接口层从其他模块中所需配置信息和服务(见下图)的简要描述。
CanIf上层模块
在AUTOSAR的基础软件架构中,CAN接口模块的上层由PDU路由器模块(缩写PduR)、CAN网络管理模块(缩写:CanNm)、CAN传输层模块(缩写CanTp)、CAN状态管理器模块(缩写:CanSm)ECU状态管理器模块(缩写:EcuM)、复杂驱动程序模块(缩写:CDD)通用校准协议模块(缩写XCP)、CAN全局时间同步模块(缩写CanTSyn)、J1939传输层模块(缩写J1939Tp)和J1939网络管理模块(缩写J1939Nm)组成。
AUTOSAR的基础软件架构表明,应用程序数据缓冲区位于上层,它们属于上层。禁止直接访问这些缓冲区。缓冲区位置在传输和接收期间通过Canlf传递给CAN驱动程序模块(缩写:CanDrv)。在执行这些发送/接收指示服务期间传递缓冲区位置(指针)。每次访问缓冲区时,使用锁定机制确保数据完整性。
Canlf使用的APIs包括通知服务,作为将CAN相关数据(例如数据长度等)传输到目标上层的基本代理。这些服务的调用参数指向CanDrv中缓冲的信息,或者直接指向CAN硬件。
EcuM初始化CanIf模块,CanSm模块负责所有支持的CAN控制器和CAN收发器的模式控制管理。
CanIf下层模块
主要的下层CAN设备驱动程序由CanDrv表示。由于Canlf在AUTOSAR基本软件体系结构中的位置,它与CanDrv密切相关。CanDrv仅提供对CAN控制器的硬件抽象访问,但CAN控制器模式的控制仅在CanSm中完成。CanDrv检测并处理CAN控制器的事件,并将这些事件通知Canlf。Canlf将CanSm的控制模式请求传递给相应的底层CAN控制器。
CanDrv提供了一个标准化的L-PDU,以确保Canlf的硬件独立性。指向这个标准化L-PDU的指针要么指向临时缓冲区,要么指向依赖于CAN硬件的CanDrv。对于Canlf,L-PDU缓冲区的类型是不可见的。
Canlf提供CanDrv在所有通知场景下的通知服务,例如:传输确认、接收指示、传输取消通知和控制器模式更改通知。如果使用多个CanDrv服务于不同的中断向量表,则上述回调服务必须是可重入的。CanDrv调用的回调服务在Canlf中声明并实现,Canlf调用的回调服务在适当的上层通信服务层中声明并放置,例如 PduR、CanNm、CanTp。
配置的CAN控制器的数量不一定等于使用的CAN收发器的数量。如果不同类型的CAN控制器需要在同一CAN网络上运行,则就需要一个CanTrcv和多个CAN控制器即可,而取决于CAN控制器设备的类型,需要一个或多个不同的CanDrv。
第二个可用的下层CAN设备驱动程序由CanTrcv表示,每个CanTrcv本身都执行CAN收发器设备的模式控制。Canlf只需将底层CanTrcv的所有API映射到一个唯一的CanSm,从而使CanSm能够触发相应的CAN收发器模式的转换。在Canlf中不会执行任何属于CanTrcv的控制或处理功能。
Canlf将所有底层CanTrcv的以下服务映射到一个唯一的接口。这些服务在CAN收发器驱动程序中进一步描述:
- 独特的CanTrcv模式请求和读取服务,以管理每个底层CAN收发器设备的模式。
- 读取CAN收发器服务,用于支持唤醒原因查询。
- 模式请求服务,用于启用/禁用/清除每个使用的CAN收发器的唤醒事件状态(Canlf SetTrcvMode())。
配置概述
Canlf设计经过优化,以管理CAN协议特定功能和使用的底层CAN控制器。Canlf能够在不重新构建的情况下更改CAN配置。因此,Canlf Init()函数从配置容器和参数中检索所需的CAN配置信息,例如:
- CAN控制器的数量。CAN控制器的数量对于传输和接收L-PDU的调度以及控制可用CAN驱动器的状态是必要的。
- 硬件对象句柄的数量。为了监督传输请求,CAN接口需要知道HTH的数量以及每个HTH和相应的CAN控制器之间的分配。
- 每个硬件对象的接收CANID的范围。CAN接口使用HRH和L-PDU之间的固定映射关系,以便在相应的硬件对象中接收,以执行搜索过滤算法。
Canlf需要有关所有使用的上层通信服务层和L-SDUs的信息。在AUTOSAR的COM堆栈内集成Canlf时,必须在配置时间设置以下信息:
- CanIfTxPduId:绑定上层发送模块和每个发送L-SDU传输的I-PDU,参数用于分派发送确认服务。
- CanIfRxPduId:绑定上层接收模块和每个接收L-SDU上传的I-PDU,参数用于L-SDU接收期间的指示调度。
Canlf需要控制器和自己的ECU的描述,该ECU连接到一个或多个 CAN 网络。因此,从 AUTOSAR系统配置的一部分CAN通信矩阵中检索以下信息:
- 针对ECU每个物理通道所有接收的L-PDUs,它用于软件过滤和接收L-SDU的分派。
- 针对ECU每个物理通道所有应该被发送的L-SDUs,用于发送请求和传输L-PDU调度。
- L-PDUs的属性信息(例如ID,数据长度),它被用于软件过滤,接收指示服务,数据长度检测。
- 每一个发送L-SDU的发送者(例如PduR,CanNm,CanTp),它被用作发送确认服务。
- 每一个接收L-SDU的接收者(例如PduR, CanNm, CanTp),它被用作L-PDU的分发。
- L-PDU/L-SDU的符号名称,用作用于表示Rx/Tx数据缓冲区地址。
文件结构
因为CanIf模块文件结构较为复杂,文件结构示意图如下:
下面我们来简要描述一个各个文件包含的内容信息:
- Can_<vendorID>_<Vendor specific name>.h:用于CanDrv的服务和类型定义(例如Can_99_Ext1.h, Can_99_Ext2.h)。
- CanTrcv_<vendorID>_<Vendor specific name>.h:用于CanTrcv的服务和类型定义(例如:CanTrcv_99_Ext1.h)。
- Can_GeneralTypes.h:对于一般的CAN栈类型声明。
- ComStack_Types.h:用于COM相关类型定义。
- PduR_CanIf.h:对于PduR的服务和回调声明。
- SchM_CanIf.h:用于SchM的服务和回调声明。
- CanSM_Cbk.h/CanNm_Cbk.h/CanTp_Cbk.h/EcuM_Cbk.h/<CDD>_Cbk.h/Xcp_Cbk.h/CanTSyn_Cbk.h/J1939Tp_Cbk.h/J1939Nm_Cbk.h:对应模块回调函数声明。
- Can_<vendorID>_<Vendor specific name>.h:用于CanDrv的配置数据(Can_99_Ext1.h)。
- CanTrcv_<Vendor Id>_<Vendor specific name>.h:用于CanTrcv的配置数据(CanTrcv_99_Ext1.h)。
- PduR.h/CanNm.h/CanTp.h/Xcp.h/J1939Tp.h/J1939Nm.h:对应模块的配置数据。
功能说明
一般功能
Canlf提供的服务可分为以下主要组别:
- 初始化
- 发送请求服务
- 发送确认服务
- 接收指示服务
- 控制器模式控制服务
- PDU模式控制服务
CanIf的可能服务:
- Interrupt Mode:CanDrv处理由CAN控制器触发的中断。事件驱动的Canlf在事件发生时得到通知。在这种情况下,相关Canlf服务在CanDrv的相应ISR中调用。
- Polling Mode:CanDrv由SchM触发并执行后续过程(轮询模式)。在这种情况下,必须在定义的时间间隔内定期调用Can_MainFunction_<Write/Read/BusOff/Wakeup/Transceiver>()函数。Canlf由CanDrv通知事件(接收、传输总线关闭、传输取消、超时),这些事件发生在CAN控制器之一中,但是在轮询中处理。CanDrv负责更新CAN控制器中属于已发生事件的相应信息,例如接收L-PDU。
- Mixed Mode:中断和轮询驱动CanDrv根据所使用的CAN控制器,功能可分为中断驱动和轮询驱动两种操作式。示例:轮询驱动的FuIICAN接收和中断驱动的BasicCAN接收,轮询驱动的传输和中断驱动接收等。
总结一下,Canlf以相同的方式工作,无论是否在中断、轮询(任务级别)或混合上处理任何事件。唯一的区别是调用上下文和通知的中断方式:抢占式或协作式。所有服务也均按照配置执行。
硬件对象句柄
传输(HTH)和接收(HRH)的硬件对象句柄(HOH)代表对包含CAN帧相关参数(例如Canld、DLC和数据)的CAN邮箱结构的抽象引用。基于CAN硬件缓冲区抽象,每个硬件对象都独立于CAN硬件缓冲区布局被CanIf所引用。HoH在CanDrv接口服务的调用中用作参数,由CanDrv的配置提供,并由CanDrv作为CAN邮箱通信缓冲区的标识符使用。Canlf仅作为硬件对象处理的用户,而不是基于硬件特定信息来解释它。因此,Canlf仍然独立于硬件。下图体现了PDU Ids与硬件对象句柄的映射路径。可以从下图中看出,一个MailBox中可以包含多个硬件对象,当一个HRH配置为接收时,它可以只接收一个CAN帧ID(FullCAN),或者一组CAN帧ID(BasicCAN)。
静动态L-PDUs
Canlf支持激活和停用属于一个CAN控制器的所有L-PDU的传输和接收。每个L-PDU都与上层模块相关联,以确保在接收、传输确认和数据访问期间正确分配。每个上层模块都可以使用L-PDUs来为不同的CAN控制器服务。
根据为整个AUTOSAR通信堆栈定义的PDU结构,L-PDU的使用有两种不同的方式:
- 对于传输请求和传输/接收轮询API,上层模块使用由Canlf定义的L-SDU ID(CanTxPduld/CanRxPduld)作为参数。
- 对于Canlf在上层模块调用的所有回调API,Canlf传递每个上层模块目标的PduId作为参数。
原则是调用者必须使用被调用者指定的目标L-PDU/L-SDU。如果在上电的时候没有执行相关的初始化,上层对Canlf执行传输请求时,将不会将L-SDUs传输到下层,且会调用DET。因此,网络中不能传输未初始化的数据。
Canlf应支持使用CanlfRxPdu-CanldMask过滤传入消息的能力。过滤应通过将传入的Canld在与CanIfRxPduCanIdMask相与之后,与CanIfRxPduCanId跟CanIfRxPduCanIdMask相与之后进行比较。这应该在未应用掩码的常规Canlds过滤之后进行,以便区别处理。
此外,应支持动态Tx和Rx的L-SDUs,其中Canld位于L-SDU的MetaData中。在传输动态L-SDUs时,当定义了CanlfTxPduCanldMask时,通过元数据提供的Canld的变量部分必须使用此掩码与Canld合并。如果没有配置CanlfTxPduCanldMask和CanlfTxPdu-Canld,则元数据应直接用作Canld。在接收动态L-SDU时,接收到的Canld应放置在L-SDU的MetaData中。MetaData的内容独立于CanlfRxPduCanld-Mask参数。
物理通道
一个物理信道与一个CAN控制器和一个CAN收发器连接,而一个或多个物理信道可以连接到单个网络。Canlf提供控制所有CAN设备的服务,如所有支持的ECU的CAN通道的CAN控制器和CAN收发器。这些APls由CanSm用于向ComM提供网络结构,并用于对所有连接到单个网络的物理通道执行唤醒和睡眠请求。Canlf将CanDrv和CanTrcv为每个物理信道分别提供的状态信息传递为CanSm的状态信息(<User ControllerBusOff>())。下面这个例子展示同一个CanDrv驱动两个控制器,每个控制器对应一个收发器并连接到一个CAN网络。
下面这个例子则展示了更复杂的物理通道形式,包括多个控制器对应一个收发器。
CAN硬件单元
CAN硬件单元将一个或多个相同类型的CAN控制器模块组合在一起,这些模块可以位于芯片上或作为外部独立设备。每个CAN硬件单元都由相应的CanDrv提供服务(一对一)。如果使用不同类型的CAN控制器,则必须使用统一的API与Canlf一起来实现不同类型的CanDrvs。Canlf在配置期间收集有关CAN控制器及其硬件对象的数量和类型的信息。这允许上层模块使用HOHs来透明且独立于硬件地访问CAN控制器。下图显示了一个CAN硬件单元,该单元由两个相同类型的CAN控制器组成,这些控制器连接到两个物理信道:
BasicCAN和FulICAN接收
Canlf在激活软件接收过滤时区分BasicCAN和FulCAN来进行不同处理。仅用于FulCAN操作的CAN邮箱只能传输或接收单个Canld。对应来说,BasicCAN的一个硬件对象可以发送或接收一系列 Canlds。配置的BasicCAN的接收硬件对象通过其硬件接受过滤器的Canlds范围完成接收。此范围可能超过由HRH接收的预定义Rx L-PDU列表。因此,Canlf随后应执行软件过滤,仅将预定义的Rx L-PDU列表传递给相应的上层块。
CanIf初始化
EcuM调用Canlf的函数Canlf_Init()对整个Canlf进行初始化。在初始化过程中,包括标志和缓冲区在内的所有全局变量和数据结构都进行了初始化。EcuM通过调用相应的初始化服务,分别执行CanDrvs和CanTrcvs的初始化。
Canlf期望CAN控制器在初始化过程完成后保持STOPPED模式,就像在开机复位后一样。在这种模式下,Canlf和CanDry都无法传输或接收CAN L-PDUS。如果在运行时需要重新初始化整个CAN模块,则EcuM应通过CanSm调用CAN接口模块的API服务Canlf_SetControllerMode()来启动CAN 控制器的所需状态转换。Canlf将来自CanSm的调用映射到相应的CanDrvs的调用。
CanIf发送
CanIf的发送请求函数CanIf_Transmit()是上层模块传输L-PDU的通用接口。上层通信层模块需要通过CanIf的服务启动传输,无法直接访问CanDrv。如果CanDrv能够将L-PDU数据写入CAN硬件传输对象中,则发起的传输请求成功完成。上层模块使用API服务CanIf_Transmit ()来发起一个传输请求。CanIf在调用服务CanIf_Transmit()时对L-PDU传输执行以下操作:
- 检查,初始化CanIf的状态。
- 当使用多个CanDrv时,识别CanDrv。
- 确定访问CAN硬件传输对象的HTH。
- 调用CanDrv的Can_Write()。
如果传输请求服务CanIf_Transmit()返回E_OK,则传输成功完成。如果一个L-PDU被请求通过一个PDU通道来传输,但是当前通道的模式为CANIF_OFFLINE,那么CanIf应该向DET通过Det_ReportRuntimeError()服务报告运行时的错误代码CANIF_E_STOPPED,而CanIf_Transmit() 将返回E_NOT_OK。
发送请求服务CanIf_Transmit ()是基于L-PDU的。对L-SDU特定数据的访问按以下参数组织:
- 发送的L-PDU =>L-SDU ID
- 引用包含L-SDU相关数据的数据结构(包括指向L-SDU的指针,指向元数据的指针和L-SDU长度)
对L-SDU数据结构的引用被用作几个CanIf的API服务中的参数,例如CanIf_Transmit()或回调服务<User RxIndication>()。如果L-PDU配置为触发传输,则L-SDU指针为空指针。下图展示了发送的数据流。
CanIf会存储为传输而配置的硬件对象信息。函数CanIf_Transmit()将CanTxPduId映射到对应的HTH,并调用函数Can_Write()。如果总线镜像是全局启用的CanIfBusMirroringSupport(),并且通过调用CAN控制器的CanIf_EnableBusMirroring()来激活,那么CanIf通过Can_Write()在控制器上传输每帧内容之前将其存储。只有在实际发送时,才提供总线镜像模块。因此,为了能够从CanIf_TxConfirmation()将其提供给总线镜像模块,必须考虑存储内容。
对CanIf而言, 传输过程从调用CanIf_Transmit()开始,到调用上层模块的回调服务结束。 在传输过程中,CanIf、CanDrv和CAN Mailbox一起存储L-PDU,只在一个位置传输一次。根据传送方式的不同,分为:
- CAN硬件传输对象
- 如果发送缓冲使能,发送L-PDU缓冲区在CanIf内。
对于触发传输,CanIf只需要存储给定L-PDU的传输请求,而不需要存储它的数据。当HTH空闲时,数据将会通过触发发送函数及时获取。请求传输的单个TxLPDU永远不会被存储两次。这种行为对应于CAN网络上的周期性通信的通常方式。如果CanIf在传输请求时被CanDrv拒绝,CanIf将启用传输缓冲,并将在传输L-PDU缓冲区(CanIfBufferCfg)中存储一个发送L-PDU。
基本上,用于缓冲发送L-PDU的整个CanIf中的缓冲区包含一个或多个CanIfBufferCfg。而每个CanIfBufferCfg被分配给一个或多个专用的CanIfBufferHthRef,可以配置为缓冲一个或多个发送I-PDU。但是,在CanIfBufferCfg的总体数量中,针对每个发送L-PDU只能缓冲一个实例。
根据在相应的发送L-PDU配置中是否启用传输缓冲,CanIf在L-PDU传输期间对应的行为是不同的。 如果发送缓冲被禁用,并且发送到CanDrv的请求失败,那么L-PDU不会被复制到CAN控制器,CanIf_Transmit()将返回值E_NOT_OK 。如果启用了传输缓冲,并且发送到CanDrv的请求失败,根据CanIfTxBuffer配置,L-PDU可以存储在CanIfTxBuffer中。在这种情况下,尽管无法执行传输,CanIf_Transmit()也会返回E_OK值 。在这种情况下,CanIf通过CanIf_TxConfirmation()回调和处理L-PDU未完成的传输,而上层不必重新提出传输请求。CanIf发送L-PDU缓冲区的数量,可以独立于CAN网络描述文件中定义的传输L-PDU的数量来配置。如果不需要缓存,则可以将CanIfBufferCfg的缓冲区大小设置为0。
如果前一个传输请求成功完成,CanDrv会通过调用CanIf_TxConfirmation()将其通知给CanIf。如果对于CAN控制器,启用了全局总线镜像CanIfBusMirroringSupport和激活调用CanIf_EnableBusMirroring(), CanIf将会调用Mirror_ReportCanFrame()对每一帧传输控制器确认过的CanIf_TxConfirmation()帧数据,提供存储内容和实际的ID。
调用回调函数CanIf_TxConfirmation()时,CanIf标识与成功传输L-PDU相连的上层通信层,通过调用CanIf的传输确认服务<User TxConfirmation>(E OK)来通知其传输执行情况。可以配置上层通信层模块,通过对不同的I-PDU或I-PDU组使用单个或多个(一般我们使用的是单个)回调服务来处理发送确认。所有那些服务在发送L-PDU传输请求确认发送之后,会被CanIf调用。传输L-PDU允许分派与目标上层模块关联的不同确认服务,该分配是在静态配置期间完成。一个发送L-PDU只能分配给一个发送确认回调服务。如果启用了CanlfPublicTxConfirmPollingSupport,则当CAN控制器的控制器模式处于CAN_CS_STARTED状态时,Canlf应缓冲有关接收到的TxConfirmation的信息。
CanIf接收
根据AUTOSAR的基础软件架构,接收到的数据将在上层通信模块,即COM、CanNm、CanTp和 DCM中进行评估和处理。这意味着,上层模块既不能使用CanDrv的缓冲区,也不能访问CanIf的缓冲区。只有当CANIF_PUBLIC_READRXPDU_DATA_API设置为TRUE时,CanIf才会在接收路径中提供内部缓冲。如果接收到CanDrv的L-PDU,则调用CanIf的CanIf_RxIndication ()。对L-PDU特定数据的访问由以下参数组织:
- 硬件接收手柄(HRH)
- 接收CAN标识符(CanId)
- 接收数据长度
- 已收到的L-PDU引用。
接收到的L-PDU依赖于硬件,并分配给通信系统的最低层CanDrv。 HRH是CanDrv和使用L-PDU的上层模块之间的链接 。HRH标识CAN硬件接收句柄,接收新的CAN L-PDU。在CanDrv调用CanIf_RxIndication(),指示接收到的L-PDU后,CanIf将进行处理。CanIf无法识别CanDrv是使用临时缓冲还是直接访问硬件。它期望在调用CanIf_RxIndication()时得到标准化的L-PDU数据。CAN硬件接收句柄会被锁定,直到复制到临时或上层模块缓冲区的过程结束。硬件对象将在CanIf的CanIf_RxIndication()返回后立即释放。CanDrv、CanIf和接收到L-PDU对应的上层模块访问相同的临时缓冲区,该临时缓冲区可以位于CAN控制器的硬件接收对象中,也可以位于CanDrv中的临时缓冲区中。下图为CanIf的接收流图。
底层驱动调用CanIf_RxIndication()引用新接收到的L-PDU的参数,如果调用了函数CanIf_RxIndication(),CanIf将对CAN L-PDU进行评估接收,并准备L-SDU供上层通信层访问。CanIf使用<User_RxIndication>()通知上层模块这个异步事件。
如果总线镜像是全局启用的,并且通过调用CAN控制器的CanIf_EnableBusMirroring()激活,那么CanIf应该为该控制器上用CanIf_RxIndication()来通知的每一帧接收调用Mirror_ReportCanFrame()。
如果调用函数CanIf_RxIndication(),CanIf会按照指定的方式处理接收到的L-PDU。如果软件过滤拒绝接收到的L-PDU,CanIf会结束对CanIf_RxIndication调用的进一步接收通知。
如果CanIf在软件过滤过程中接受通过CanIf_RxIndication()接收到的L-PDU, CanIf随后会进行数据长度检查。如果CanIf在数据长度检查期间底层又使用CanIf_RxIndication()接收L-PDU, CanIf将根据配置的数据长度的字节数暂时将其复制到静态接收缓冲区。
如果为接收的L-SDU配置了元数据,CanIf将PDU有效负载复制到静态接收缓冲区,并将CANID复制到类型为CAN_ID_32的Meta-DataItem。
在数据长度检查期间,如果CanIf接受到了通过CanIf_RxIndication()的L-PDU,CanIf会识别是否配置了目标上层模块(CanIfRxPduUserRxIndicationUL,CanIfRxPduUserRxIndicationName),并为接收到的L-SDU提供接收通知服务。
如果目标上层模块被配置为提供接收通知服务,CanIf应该调用配置的接收通知回调服务,并提供所需的参数至上层通知回调函数。
CanIf在底层调用CanIf_RxIndication()时执行以下步骤:
- 软件过滤(只有Basic CAN),如果配置了。
- 数据长度检查。
- 缓冲接收L-SDU。
- 调用上层接收通知回调服务。
读取接收到的数据通过CanIf_ReadRxPduData(),其是上层模块读取最近从CAN网络接收到的CANL-SDU的公共接口。上层模块只通过CanIf服务发起接收请求,而不直接访问CanDrv。发起的接收请求成功完成,CanIf将接收到的L-SDU写入上层模块I-PDU缓冲区。
函数CanIf_ReadRxPduData()使得在不依赖接收事件的情况下读取数据成为可能。在配置时启用它,他不会为相同的L-SDU配置接收通知服务。如果需要,可以启用接收通知服务。
在底层调用CanIf_RxIndication()并通过软件过滤和数据长度检查后,CanIf将接收到的L-SDU存储在这个接收到的L-SDU缓冲区中。如果调用CanIf_ReadRxPduData()将数据复制到指定的接收L-SDU缓冲区时,CanIf应避免抢占指定的接收L-SDU缓冲区的访问事件。
CanIf提供用于控制由CanDrv支持的CAN控制器通信模式的服务。这意味着所有CAN控制器都由相应的API服务来控制,以请求和读取当前控制器模式。
可以通过调用CanIf_SetControllerMode()服务,来根据上层的请求更改CAN控制器状态。请求通过CanIf经过CanDrv的API传递到指定的CAN控制器。在CAN网络上对所有CAN控制器的一致性管理是CanSm的任务。通过这种方式, CanSm负责将CAN网络的所有CAN控制器按顺序设置为睡眠模式或唤醒 。CanIf通过调用函数CanIf_SetControllerMode()或CanIf_ControllerBusOff()接受每个状态转换请求。CanIf不决定CAN控制器请求的模式转换是否有效。CanIf仅通过获取当前模式和执行请求的模式转换来与CanDrv交互,仅提供一个桥梁的工作。网络相关状态机在CanSm中实现。CanIf只存储请求的模式并执行请求的转换。
如果ControllerId引用的控制器模式处于CAN_CS_STOPPED状态,并且如果CanIf_Transmit()调用中的PduIdType参数被分配给该CAN控制器,那么CanIf_Transmit()调用不会导致Can_Write()调用,而是返回E_NOT_OK。如果ControllerId引用的控制器模式进入CAN_CS_STOPPED状态,
CanIf会清除分配给CAN控制器相应的CanIf传输缓冲区。
如果ControllerId引用的控制器模式进入CAN_CS_STOPPED状态,那么CanIf通过调用<User TxConfirmation>(id,E NOT OK)为分配给CAN控制器的每个未完成的TxConfirmation,通知相应的上层模块传输失败。如果启用了CanIfPublicTxConfirmPollingSupport,那么CanIf还会清除关于TxConfirmation的信息。这确保了对于每个PDU,都会调用一个<User TxConfirmation>。
当底层调用回调CanIf_ControllerBusOff(ControllerId)时,CanIf会调用CanSm或CDD的CanSM_ControllerBusOff(ControllerId)。
PDU通道模式控制
每个L-PDU都分配到一个专用的物理CAN通道,该通道连接到一个CAN控制器和一个CAN网络。通过这种方式,属于一个物理通道的所有L-PDU都可以通过处理逻辑上的单个L-PDU通道组来控制。这些逻辑组表示连接到底层CAN网络的一个ECU上的所的L-PDU。
下图显示了L-PDU通道群组的一种可能用途及其与上层网络的关系。
L-PDU只能分配给一个通道组。PduR或网络管理器等典型用户负责控制PDU操作模式。
只允许在对应的控制器模式等于CAN_CS_STARTED时,更改PDU通道模式。虽然CANIF_ONLINE和CANIF_OFFLINE在PDU信道模式下影响整个通信,但是可以分别启用和禁用CANIF_TX_OFFLINE和CANIF_TX_OFFLINE_ACTIVE传输路径。CanIf通过服务CanIf_GetPduMode()提供关于当前PDU通道模式的信息。
在初始化期间,CanIf应该将每个通道切换到CANIF_OFFLINE。对于切换到CANIF_OFFLINE模式的物理通道,CanIf应该:
- 防止将相关L-PDU的传输请求CanIf_Transmit()转发给CanDrv。
- 清除相应的CanIf传输缓冲区。
- 防止调用上层模块的接收通知回调服务。
- 防止调用上层模块的传输确认回调服务。
如果底层调用CanIf_SetControllerMode()或CanIf_ControllerBusOff(),则CanIf应将相应通道的PDU通道模式设置为CANIF_TX_OFFLINE。对于切换到CANIF_ONLINE模式的物理信道,CanIf应该:
- 允许将相关L-PDU的传输请求CanIf_Transmit()转发到CanDrv。
- 支持调用上层模块的接收指示回调服务。
- 允许调用上层模块的传输确认回调服务。
如果CanIfTxOfflineActiveSupport为TRUE,CanIf提供通过CANIF_TX_OFFLINE_ACTIVE模式来模拟成功传输。对于每个被分配到CANIF_TX_OFFLINE_ACTIVE模式信道的L-PDU, CanIf会立即调用上层模块的传输确认回调服务,而不是在调用CanIf_Transmit()时将L-PDU缓冲或转发到CanDrv。
时序图
这里只介绍部分常用的功能时序图,详细完整的CanIf模块时序图见《AUTOSAR_SWS_CANInterface.pdf》。
Transmit request (single CAN Driver)
可以看到他在Busy的时候将L-PDU存放在在发送buffer中。
Transmit confirmation (interrupt mode)
Transmit confirmation (with buffering)
针对利用TX Buffer的发送确认动态图。
Trigger Transmit Request
触发试发送,发送数据不在调用CanIf_Transmit的时候往下层送,而是底层触发发送的时候拷贝数据过去。
Receive indication (interrupt mode)
可以看到,针对Tempoary buffer使用与否,有两种不同的处理方式。
Read received data
可以看到这种处理方式会在接收中断来临的时候把数据放在CanIf的buffer中,用户主动读取。
Start CAN network
下图展示了启动CAN控制器的流程,并针对当前控制器状态体现了不同的动态动作。
BusOff notification
BusOff的通知动态图如下。
BusOff recovery
BusOff的恢复动态图,CanIf仅改变内部状态,真正的BusOff的恢复逻辑由CanSm提供,其简单概述为尝试重新配置控制器为Start。
ISOLAR-AB配置
CanIf
这里的配置在导入DBC之后,经过RTA-BSW工序之后会自动根据DBC中包含的报文进行生成,但是不免会因为要使用BasicCan或者别的其他原因更改这部分的配置。我们下边介绍一下这个CAN栈模块的各个配置项。
CanIfPublicCfg
这个容器中包含CanIf的公共信息,能对各个模块产生影响的部分,如下图所示。
我们下边介绍几个比较重要的配置:
- CanIfMetaDataSupport:是否使能动态ID处理L-SDU Metadata。
- CanIfPublicCancelTransmitSupport:该参数允许请求取消I-PDU的发送支持。但是可以由下面的代码截图看出,ETAS的静态代码并没有实现这个部分。
- CanIfPublicHandleTypeEnum:Can_HwHandleType表示CAN的硬件单元,当HW object大于255的时候,需要是UINT16的数据类型。
- CanIfPublicIcomSupport:是否支持虚拟CAN网络功能,ETAS尚未实现此功能。
- CanIfPublicReadRxPduDataApi:打开Canlf_ReadRxPduData()。此函数用于读取CAN的SDU信息。传入CanIfRxSduId,为PDU ID,函数回填指针,指向CanIf_PduInfoType。
- CanIfTriggerTransmitSupport:COM层面要是由触发传输,此处会设置为Ture。Canlf_TriggerTransmit()会被使能。
CanIfCtrlDrvCfg
这个容器不仅包含了下边CanIfInitHohCfg容器的引用CanlfCtrlDrvInitHohConfigRef配置,以及驱动程序的类型参考CanlfCtrlDrvNameRef配置项,配置项CanlfRbCtrlDryPrefix方便集成第三方驱动,其中包含供应商前缀和API中缀,方便使用对应的接口和变量。
子容器CanIfCtrlDrvCfg中包含对CAN模块中定义的控制器引用。
CanIfDispatchCfg
本容器主要包含Canlf的上层模块相关的回调函数,其对所有配置的CAN驱动程序/CAN收发器驱动程序模块都是通用的。下图主要涉及的配置项有CanlfDispatchUserCtrlBusOffUL、CanlfDispatchUserCtrlModelndicationUl与CanlfDispatchUserTrcvModelndicationName。他们的配置都是CAN_SM,这些参数分别定义了当CAN控制器BusOff,CAN控制器模式变化以及收发器模式变化时,通知的上层模块。
CanIfPrivateCfg
此容器包含CAN接口模块的初始化参数。它主要包含四个子容器,我们逐一来分析。
首先是CanlfBufferCfgs。默认RTA-BSW生成的Mailbox都是FullCan的,每个Mailbox包含一个HW object,但是这个子容器依然会针对每个发送的Mailbox生成对应的Buffer配置,方便用户修改成BasicCan,如果用户使用的为FullCan,则CanlfBufferSize应配置为0。
然后是CanIfInitHohCfg子容器,其中包含CanlfHrhCfg与CanlfHthCfg两个子容器,分别对应CAN模块接收以及发送的MailBox引用和CanIf定义的CanlfCtrlCfg引用,CanlfHrhCfg如果对应多个PDU,则可以在CanIfHrhListCfg配置PDUs的CANID。
然后我们介绍CanlfRxPduCfg容器,它包含接收PDU的属性配置(接收CanId,DLC,CanId类型,接收上层的模块以及接收通知名称),还包含刚才提到的HRH引用,如果要实现BasicCan则需要多个CanlfRxPduCfg引用同一个HRH,还有EcuC的Pdu路径等引用。
最后的是CanlfTxPduCfg,它其中包含一个PDU属性(CanId,CanId类型,DLC,静态还是动态PDU,以及上层的使用模块),还包含CanIf模块的buffer引用,以及PduR的路径等引用。
CanIfPrivateCfg
这个容器包含CanIf模块的私有配置,其中CanlfPrivateDlcCheck用作开启/关闭DLC的检查。
代码解析
动态配置代码
CanIf生成的动态配置代码如下。
我们针对一些常用的文件内容说明:
- CanIf_Cfg_SymbolicNames.h: 文件包含一些符号化的值,包括 Rx Receive Handles,TxPduIds以及RxPduIds。
/* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ /*<VersionHead> * This Configuration File is generated using versions (automatically filled in) as listed below. * * $Generator__: CanIf / AR42.4.0.1 Module Package Version * $Editor_____: 9.0 Tool Version * $Model______: 2.0.2.1 ECU Parameter Definition Version * </VersionHead>*/ #ifndef CANIF_Cfg_SymbolicNames_H #define CANIF_Cfg_SymbolicNames_H /**************************************************************************/ /* Include Section */ /**************************************************************************/ /* ************************************************************************** * Defines ************************************************************************** */ /* Definition of Rx Receive Handles (HRH) for __KW_COMMON*/ #define CanIfConf_CanIfHrhCfg_Can_Network_CANNODE_ECAN_Rx_Std_MailBox_1_Config 0 #define CanIfConf_CanIfHrhCfg_Can_Network_CANNODE_ECAN_Rx_Std_MailBox_2_Config 1 #define CanIfConf_CanIfHrhCfg_Can_Network_CANNODE_ECAN_Rx_Std_MailBox_3_Config 2 /* Definition of TxPduIds for Precompile */ #define CanIfConf_CanIfTxPduCfg_DV_Test_Message_1_Can_Network_CANNODE_ECAN 0 #define CanIfConf_CanIfTxPduCfg_Tx_Test_Message_01_Can_Network_CANNODE_ECAN 1 #define CanIfConf_CanIfTxPduCfg_Diag_VCU_Resp_Can_Network_CANNODE_ECAN 2 /* Definition of RxPduIds for Precompile*/ #define CanIfConf_CanIfRxPduCfg_Rx_Test_Message_01_Can_Network_CANNODE_ECAN 0 #define CanIfConf_CanIfRxPduCfg_Diag_VCU_ReqPhsy_Can_Network_CANNODE_ECAN 1 #define CanIfConf_CanIfRxPduCfg_Diag_ECAN_ReqFunc_Can_Network_CANNODE_ECAN 2 #endif /* CANIF_Cfg_SymbolicNames_H */
- CanIf_Cfg.h:CanIf的一些通用配置,包括一些功能与API的开关宏定义。
/* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ /*<VersionHead> * This Configuration File is generated using versions (automatically filled in) as listed below. * * $Generator__: CanIf / AR42.4.0.1 Module Package Version * $Editor_____: 9.0 Tool Version * $Model______: 2.0.2.1 ECU Parameter Definition Version * </VersionHead>*/ #ifndef CANIF_CFG_H #define CANIF_CFG_H /**************************************************************************/ /* Include Section */ /**************************************************************************/ #include "CanIf_Cfg_SymbolicNames.h" /* ************************************************************************** * Defines ************************************************************************** */ /**************************************************************************/ /* Common Published Information */ /**************************************************************************/ /** * @ingroup CANIF_H * * Vendor Id */ #define CANIF_VENDOR_ID 6u /** * @ingroup CANIF_H * * Module Id */ #define CANIF_MODULE_ID 60u /** * @ingroup CANIF_H * * Autosar Release Major Version */ #define CANIF_AR_RELEASE_MAJOR_VERSION 4u /** * @ingroup CANIF_H * * Autosar Release Minor Version */ #define CANIF_AR_RELEASE_MINOR_VERSION 2u /** * @ingroup CANIF_H * * Autosar Release revised version */ #define CANIF_AR_RELEASE_REVISION_VERSION 2u /** * @ingroup CANIF_H * * Software Release Major Version */ #define CANIF_SW_MAJOR_VERSION 4u /** * @ingroup CANIF_H * * Software Release Minor Version */ #define CANIF_SW_MINOR_VERSION 0u /** * @ingroup CANIF_H * * Software Release Patch Version */ #define CANIF_SW_PATCH_VERSION 1u #define CANIF_CONFIGURATION_VARIANT MODULE_VARIANT_PRE_COMPILE /*Number of variants configured in CanIf*/ #define CANIF_TOTAL_CFG_SETS 1 /**************************************************************************/ /* Description : Enables or disables the development error detection & */ /* notification mechanism */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_DEV_ERROR_DETECT STD_OFF /**************************************************************************/ /* Description : Enables or disables BaudRateChange in the CanDriver */ /* */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_PUBLIC_CHANGE_BAUDRATE_SUPPORT STD_OFF /**************************************************************************/ /* Description : Enables or disables CanIf_SetBaudrate API */ /* */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_PUBLIC_SET_BAUDRATE_SUPPORT STD_OFF /**************************************************************************/ /* Description : Enables or disables the API CanIf_CancelTransmit() */ /* */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_PUBLIC_CANCEL_TRANSMIT_SUPPORT STD_OFF /**************************************************************************/ /* Description : Enables or disables Rx indication for busoff recovery */ /* */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_PUBLIC_BUSOFF_RECOVERY_FROM_RXINDICATION STD_OFF /*******************************************************************************************************/ /* Description : Enables or disables the API CanIf_DirectHw_Write() & CanIf_Get_DirectHw_Info() */ /* */ /* Range : STD_ON/STD_OFF */ /*******************************************************************************************************/ #define CANIF_DIRECT_HW_WRITE STD_OFF /***************************************************************************/ /* Description : Enables/disables API for reading received L-PDU data */ /* Range : STD_OFFD_ON/STD_OFF */ /***************************************************************************/ #define CANIF_READRXPDU_DATA_API STD_OFF /**************************************************************************/ /* Description : Enables/disables API for reading the notification status*/ /* of transmit and receive L-PDU */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_READRXPDU_NOTIFY_STATUS_API STD_ON /**************************************************************************/ /* Description : Enables/disables API for reading the notification status*/ /* of transmit and receive L-PDU */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_READTXPDU_NOTIFY_STATUS_API STD_ON /***************************************************************************/ /* Description : Enables / Disables the APIs CanIf_ReadTxmsgId() and */ /* CanIf_ReadRxmsgId() for reading configured CanId for */ /* configured hardware object (HOH). */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_READMSGID_API STD_OFF /***************************************************************************/ /* Description : Enables / Disables the call back for reading received */ /* CanId for configured hardware object (HOH). */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_READBUFFERID STD_OFF /**********************************************************************************************/ /* Description : Enables/disables the user notification when a PDU in the TxBuffer is cleared */ /* due to CAN driver couldn't accept the transmission request */ /* Range : STD_ON/STD_OFF */ /**********************************************************************************************/ #define CANIF_USER_TXBUFCLEARNOTIFY_API STD_OFF /**************************************************************************/ /* Description : Configure Error Passive support */ /* Range STD_OFF : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_ERROR_PASSIVE_SUPPORT STD_OFF /**************************************************************************/ /* Description : Configure Wakeup support */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_WAKEUP_SUPPORT STD_OFF /**************************************************************************/ /* Description : Configure Controller Wakeup support */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_CTRL_WAKEUP_SUPPORT STD_OFF /**************************************************************************/ /* Description : Configure Transceiver Wakeup support */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_TRCV_WAKEUP_SUPPORT STD_OFF /**************************************************************************/ /* Description : Configure Wakeup support */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_TRCV_DRV_CFG STD_OFF /**************************************************************************/ /* Description : Configure Wakeup Validation */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_PUBLIC_WAKEUP_CHECK_VALIDATION_API STD_OFF /**************************************************************************/ /* Description : Configure Wakeup Validation */ /* Range : 0....Num of transceivers */ /**************************************************************************/ #define CANIF_NUM_TRANSCEIVERS 0 /**************************************************************************/ /* Description : Enables/disables API for reading the version information*/ /* . about the CAN interface */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_VERSION_INFO_API STD_OFF /**************************************************************************/ /* Description : Enables/disables usage of dynamic IDs */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_DYNAMIC_ID STD_OFF /**************************************************************************/ /* Description : Enables/disables API for reconfiguration of the CAN */ /* Identifier for each transmit L-PDU */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_SETDYNAMICTXID_API STD_OFF /**************************************************************************/ /* Description : Enables/disables Metadata Support */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_METADATA_SUPPORT STD_OFF /**************************************************************************/ /* Description : Enables/disables use of transmit buffers */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_TRANSMIT_BUFFER STD_OFF /**************************************************************************/ /* Description : Enables/disables use of receive buffers */ /* Range : STD_ON/STD_OFF */ /**************************************************************************/ #define CANIF_RECEIVE_BUFFER STD_OFF /**********************************************************************************************************/ /* Description : Max Pdu Index for FULL CAN Pdus based on ecuC.ecucPduCollection.pduIdTypeEnum selection */ /* Range : 0xFFu/ 0xFFFFu */ /**********************************************************************************************************/ #define CANIF_MAX_PDU_INDEX 0xFFFFu /**************************************************************************/ /* Description : Total Number of Dynamic CanTxPduIds to be handled */ /* Range : 1..Max Number of defined CanTxPduIds */ /**************************************************************************/ #define CANIF_NUM_DYNAMIC_CANTXPDUIDS 0 /**************************************************************************/ /* Description : Total Number of CanRxPduIds to be handled */ /* Range : 1..Max Number of defined CanRxPduIds */ /**************************************************************************/ #define CANIF_NUM_CANRXPDUIDS 3 /**************************************************************************/ /* Description : Total Number of Static CanTxPduIds to be handled */ /* Range : 1..Max Number of defined CanTxPduIds */ /**************************************************************************/ #define CANIF_NUM_STATIC_CANTXPDUIDS 3 /**************************************************************************/ /* Description : Define Number of transmit buffers. */ /* The L-PDU buffers shall store DLC and max of 8bytes */ /* of data. */ /* Range : 0..Max Number of Tx buffers */ /**************************************************************************/ #define CANIF_NUM_TXBUFFERS 0 /**************************************************************************/ /* Description : Gives the Number of BASIC CAN HTHs. */ /* Range : 0..Max Number of BASIC CAN HTHs */ /**************************************************************************/ #define CANIF_NUM_BASIC_HTH 0 /******************** Parameters Newly Introduced *************************/ /*Total number of Tx-Pdus configured in CanIf*/ #define CANIF_TOTAL_TXPDUS 3 /*Total number of Rx-Pdus configured in CanIf*/ #define CANIF_TOTAL_RXPDUS 3 /*Number of entries in CanIf_TxPduId_CustId_LUT[][]*/ #define CANIF_NUM_CUSTID_ENTRIES 3 /**************************************************************************/ /* Description : Selects whether the DLC check is supported */ /* Range : STD_ON/STD_STD_OFF */ /**************************************************************************/ #define CANIF_DLC_CHECK STD_OFF /* Total number of Controllers present in one or more drivers */ #define CANIF_NUM_CONTROLLERS 1 /* Configuration for the Tx and Rx buffer size */ #define CANIF_TXBUFFER_SIZE 0 #define CANIF_RXBUFFER_SIZE 0 /* Configuration for retransmission of PDU */ #define CANIF_MAX_RETRY_TIMES 1 /* Configure the number of HRH handles */ #define CANIF_NUM_HRH_HANDLES 3 /* Configure total number of CanIds to be received in the list */ #define CANIF_NUM_LIST_CANID 0 /**************************************************************************/ /* Description : Number of served CAN hardware units */ /* Range : 1..Max Number of underlying supportted CAN HW units */ /**************************************************************************/ #define CANIF_NUM_CAN_DRIVERS 1 /* Configuration for use of extended CAN identifiers */ #define CANIF_EXTENDED_ID STD_OFF /* Configuration for use of extended CAN identifiers */ #define CANIF_FD_SUPPORT STD_OFF /* Instance ID */ #define CANIF_INSTANCE_ID 1 /* Configure CanIf Lite */ #define CANIF_LITE_CONFIGURATION STD_OFF /* Configure transmission of CANTP/USER Pdus when the Tx Pdu mode is OFFLINE */ #define CANIF_USER_TP_TX_OFFLINE_MODE STD_OFF /* Configuration for enabling/disabling the API CanIf_GetTxConfirmationState() */ #define CANIF_PUBLIC_TXCONFIRM_SUPPORT STD_OFF /*PN support*/ #define CANIF_PUBLIC_PN_SUPPORT STD_OFF /* CanIf variant info */ #define CANIF_VARIANT_INFO 1 /* PRE-COMPILE */ /* Configure support of filtering of CanNm transmit CanIds during reception */ #define CANIF_CANNM_TXID_FILTER STD_OFF /* Enable/Disable CanNm Support */ #define CANIF_CANNM_ENABLED STD_OFF /* Enable/Disable J1939Nm Support */ #define CANIF_J1939NM_ENABLED STD_OFF /* Enable/Disable CanTp Support */ #define CANIF_CANTP_ENABLED STD_ON /* Enable/Disable CAN_TSYN Support */ #define CANIF_CANTSYN_ENABLED STD_OFF /* Enable/Disable PduR Support */ #define CANIF_PDUR_ENABLED STD_ON /* Enable/Disable CDD Support */ #define CANIF_CDD_RX_ENABLED STD_OFF /* Enable/Disable USER Support */ #define CANIF_USER_RX_ENABLED STD_OFF /* Enable/Disable USER or CDD Support */ #define CANIF_USER_CDD_TX_ENABLED STD_OFF /* Enable/Disable XCP Support */ #define CANIF_XCP_ENABLED STD_OFF /* Enable/Disable XCP Support */ #define CANIF_J1939TP_ENABLED STD_OFF /*Wakeup Validation by NM-Pdu*/ #define CANIF_PUBLIC_WAKEUP_CHECK_VALID_BY_NM STD_OFF /* Configure support of BASIC CAN Reception */ #define CANIF_BASIC_CAN_SUPPORT STD_OFF /* Configure support of CanId List for reception */ #define CANIF_BASIC_CAN_SUPPORT_LIST STD_OFF /* Macro generated via scripts when multiple Ranges of CanIds are configured under a HRH */ #define CANIF_RXPDU_CANID_RANGE STD_OFF /* Calibration Enabled/Disabled */ #define CANIF_CALIBRATION STD_OFF /* Include the Controller name */ typedef enum { CANIF_Can_Network_CANNODE_ECAN = 0 }CanIf_ControllerName; #endif /* CANIF_CFG_H */
- CanIf_PBcfg.c:这个文件中包含CanIf_Callback的映射信息,还有CanIf_TxPduConfig,其包含了针对每个TxPdu的Id等配置信息,其中最重要的是Hth_Ref_Id这个值,它会需要我们集成工程师手动定义这个宏定义,映射到MCAL生成的MailBox的ID,诸如在Can_17_MCanP_Cfg.h定义预留的发送MailBox的ID。
文件还有CanIf_HrhConfig,其包含接收Mailbox中的诸如CanId、HrhRangeMask等属性信息,这个结构体数据会的排序应该与MCAL中的mailbox的排序一致。对于接收还有CanIf_RxPduConfig结构体数据,它包含一个PDU的关系信息,向下为HrhRef,它应该与MCAL中对应接收MailBox的Object ID保持一致,向上为TargetRxPduId与RxPduId两个属性,分别对应向上的接收PDUID和CanIf本模块的接收ID。最后有一个完整的CanIf结构体,名为CanIf_Config。注意不要用ETAS生成的注释来理解结构体中值对应的属性,要实际看到当前的结构体定义来一一对应。
新的Isolar版本提供了tx和rx的映射关系,我们可以基于此修改pdu和mailbox的映射关系,从而支持启动时采用不同的mcal初始化参数。注意不要用ETAS生成的注释来理解结构体中值对应的属性,要实际看到当前的结构体定义来一一对应。 /* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ /*<VersionHead> * This Configuration File is generated using versions (automatically filled in) as listed below. * * $Generator__: CanIf / AR42.4.0.1 Module Package Version * $Editor_____: 9.0 Tool Version * $Model______: 2.0.2.1 ECU Parameter Definition Version * </VersionHead>*/ /******************************************************************************/ /* Include Section */ /******************************************************************************/ /* CanIf Private header */ #include "CanIf_Priv.h" /* CanIf post build header */ #include "CanIf_PBcfg.h" /* CanIf post build header */ #include "CanIf_Cfg_Internal.h" /* BusOff callback functions to Can State Manager */ #include "CanSM_Cbk.h" #if (!defined(CANSM_AR_RELEASE_MAJOR_VERSION) || (CANSM_AR_RELEASE_MAJOR_VERSION != CANIF_AR_RELEASE_MAJOR_VERSION)) #error "AUTOSAR major version undefined or mismatched" #endif #if (!defined(CANSM_AR_RELEASE_MINOR_VERSION) || (CANSM_AR_RELEASE_MINOR_VERSION != CANIF_AR_RELEASE_MINOR_VERSION)) #error "AUTOSAR minor version undefined or mismatched" #endif /* ****************************************************************************** * Variables ****************************************************************************** */ /* CANIF callback configuration */ #if(CANIF_VARIANT_INFO != 2) && (CANIF_VARIANT_INFO != 3) #define CANIF_START_SEC_CONST_UNSPECIFIED #else #define CANIF_START_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #endif #include "CanIf_MemMap.h" CONST(CanIf_CallbackFuncType, CANIF_CONST) CanIf_Callback = { &CanSM_ControllerBusOff, NULL_PTR, &CanSM_ControllerModeIndication, NULL_PTR, NULL_PTR, NULL_PTR }; #if(CANIF_VARIANT_INFO != 2) && (CANIF_VARIANT_INFO != 3) #define CANIF_STOP_SEC_CONST_UNSPECIFIED #else #define CANIF_STOP_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #endif #include "CanIf_MemMap.h" /* Tx PDUs Configuration */ #if(CANIF_VARIANT_INFO != 2) && (CANIF_VARIANT_INFO != 3) #define CANIF_START_SEC_CONST_UNSPECIFIED #else #define CANIF_START_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #endif #include "CanIf_MemMap.h" CONST(CanIf_TxPduInfo, CANIF_CONST) CanIf_TxPduConfig[]= { /* CanTxPduId, TargetTxPduId, CanTxPduId, Hth_Ref_Id, Controller, CanIdType, User, ReadTxPdu, CbkIdx ,Tx_Buffer Offset , Start Indx , End Indx, HTHIndex, CanId, DLC, Type Notify Status */ { CanIfConf_CanIfTxPduCfg_DV_Test_Message_1_Can_Network_CANNODE_ECAN, 0 , CANIF_STATIC, (uint8)CanConf_CanHardwareObject_Can_Network_CANNODE_ECAN_Tx_Std_MailBox_1, (uint8)CANIF_Can_Network_CANNODE_ECAN, 0x00, PDUR, FALSE , 0, 0x5DF, 8 }, { CanIfConf_CanIfTxPduCfg_Tx_Test_Message_01_Can_Network_CANNODE_ECAN, 1 , CANIF_STATIC, (uint8)CanConf_CanHardwareObject_Can_Network_CANNODE_ECAN_Tx_Std_MailBox_2, (uint8)CANIF_Can_Network_CANNODE_ECAN, 0x00, PDUR, FALSE , 0, 0x5DC, 8 }, { CanIfConf_CanIfTxPduCfg_Diag_VCU_Resp_Can_Network_CANNODE_ECAN, CanTpConf_CanTpTxNPdu_CanTpTxNPdu , CANIF_STATIC, (uint8)CanConf_CanHardwareObject_Can_Network_CANNODE_ECAN_Tx_Std_MailBox_3, (uint8)CANIF_Can_Network_CANNODE_ECAN, 0x00, CANTP, FALSE , 0, 0x7EA, 8 }}; #if(CANIF_VARIANT_INFO != 2) && (CANIF_VARIANT_INFO != 3) #define CANIF_STOP_SEC_CONST_UNSPECIFIED #else #define CANIF_STOP_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #endif #include "CanIf_MemMap.h" /* Rx Handle configuration */ #define CANIF_START_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #include "CanIf_MemMap.h" CONST(CanIf_HrhConfigType, CANIF_CONST) CanIf_HrhConfig[] = { /* HRHInfo , Pdu/ListIdx, NumCanIds/NumRanges, Controller, ReadRxPduInfo, CanId, HrhRangeMask */ { CANIF_FULL, 0 , 1 , (uint8)CANIF_Can_Network_CANNODE_ECAN, CANIF_READ_NOTIFSTATUS, 0x5DE, 0x1FFFFFFFU }/*Can_Network_CANNODE_ECAN_Rx_Std_MailBox_1*/, { CANIF_FULL, 1 , 1 , (uint8)CANIF_Can_Network_CANNODE_ECAN, CANIF_READ_NOTIFSTATUS, 0x7E2, 0x1FFFFFFFU }/*Can_Network_CANNODE_ECAN_Rx_Std_MailBox_2*/, { CANIF_FULL, 2 , 1 , (uint8)CANIF_Can_Network_CANNODE_ECAN, CANIF_READ_NOTIFSTATUS, 0x7DF, 0x1FFFFFFFU }/*Can_Network_CANNODE_ECAN_Rx_Std_MailBox_3*/ }; #define CANIF_STOP_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #include "CanIf_MemMap.h" /* Rx PDUs Configuration */ #define CANIF_START_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #include "CanIf_MemMap.h" CONST(CanIf_RxPduConfigType, CANIF_CONST) CanIf_RxPduConfig[]= { /* RxBufferOffset, target ID, RxPduId , HRH , CbkIdx, User, CanIdType, DLC, RxPduCanId */ { PduRConf_PduRSrcPdu_Rx_Test_Message_01_Can_Network_CANNODE_ECAN_CanIf2PduR , CanIfConf_CanIfRxPduCfg_Rx_Test_Message_01_Can_Network_CANNODE_ECAN, 0, 0, PDUR, 0x20u, 8, 0x5DE }, { CanTpConf_CanTpRxNPdu_CanTpRxPyNPdu , CanIfConf_CanIfRxPduCfg_Diag_VCU_ReqPhsy_Can_Network_CANNODE_ECAN, 1, 0, CANTP, 0x20u, 1, 0x7E2 }, { CanTpConf_CanTpRxNPdu_CanTpRxFyNPdu , CanIfConf_CanIfRxPduCfg_Diag_ECAN_ReqFunc_Can_Network_CANNODE_ECAN, 2, 0, CANTP, 0x20u, 1, 0x7DF } }; #define CANIF_STOP_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #include "CanIf_MemMap.h" #if(CANIF_VARIANT_INFO == 3) /* Generate an instance of structure Std_VersionInfoType in CanIf_PBcfg_c.xpt*/ #define CANIF_START_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #include "CanIf_MemMap.h" static CONST(Std_VersionInfoType, CANIF_CONST) CanIf_VersionInfo = { 6, /* Vendor Id */ 60, /* Module Id */ 4, /* Sw Major Version */ 0, /* Sw Minor Version */ 1 /* Sw Patch Version */ }; #define CANIF_STOP_SEC_CONFIG_DATA_POSTBUILD_UNSPECIFIED #include "CanIf_MemMap.h" #endif /* Global configuration structure */ #define CANIF_START_SEC_CONST_UNSPECIFIED #include "CanIf_MemMap.h" CONST(CanIf_ConfigType, CANIF_CONST) CanIf_Config = { CanIf_TxPduConfig, /* MR12 RULE 1.1 VIOLATION:This is a known defect in CChecker 2.1.0 tool.No fix required in the component.*/ CanIf_RxPduConfig, CanIf_HrhConfig, CANIF_NUM_STATIC_CANTXPDUIDS, CANIF_NUM_CANRXPDUIDS, CANIF_NUM_DYNAMIC_CANTXPDUIDS, CANIF_NUM_CONTROLLERS }; #define CANIF_STOP_SEC_CONST_UNSPECIFIED #include "CanIf_MemMap.h"
集成代码
下图为CanIf模块包含的集成代码,其中SchM、MemMap和APPL文件这里就不赘述了。
CanIf_RxIndication_Integration.c这个文件包含了CanIf_RxIndication()函数的实现,底层代码在接收到报文之后会调用CanIf_RxIndication这个函数,把底层的L-PDU相关信息送上来。一般在调试CAN栈之间会在这里做一些测试代码,确保底层CAN驱动确实将报文传了上来。
静态代码
主要介绍常见的静态代码涉及API说明,具体详细完整的介绍读者可以参考《AUTOSAR_SWS_CANInterface.pdf》以及《RTA-BSWReferenceGuide.pdf》。注意CanIf本身并没有周期调用的函数,但是如果接收,发送或者busoff选择Polling而非Interrupt,则需要将驱动中对应的Can_MainFunction_Read/Can_MainFunction_Write/Can_MainFunction_BusOff放在对应的周期任务中。
- CanIf_Init/CanIf_DeInit:CanIf模块的初始化与去初始化API。
- CanIf_SetControllerMode/CanIf_GetControllerMode:CanIf模块设置和获取。
- CanIf_Transmit:CanIf模块发送报文。
- CanIf_SetPduMode/CanIf_GetPduMode:设置/获取当前Pdu状态。
- CanIf_TxConfirmation:此函数当驱动已成功处理的CANTxPDU传输之后调用。
- CanIf_RxIndication:此函数当驱动已接收到CAN帧之后调用。
- CanIf_ControllerBusOff:此函数指示一个控制器BusOff事件,该事件引用了抽象的 CanlfControllerld所对应的CAN Controller。
十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。