【CP AUTOSAR】CanTp(CANTransportLayer)分析和使用
本文介绍CP AUTOSAR 架构下的CanTp组件,基于S32K312芯片、Vector提供的CBD包,使用DaVinci Configurator工具进行配置的经验。CanTp组件位于Communication Services层,是Can Interface的上层和PDURouter的下层。CanTp组件实现MCU的CAN数据流的拆分、重组、流控制等,即对CAN多帧进行组包拆包然后传给上层。
文章目录
前言
本文介绍CP AUTOSAR 架构下的CanTp组件,基于S32K312芯片、Vector提供的CBD包,使用DaVinci Configurator工具进行配置的经验。
CanTp组件位于Communication Services层,是Can Interface的上层和PDURouter的下层。
CanTp组件实现MCU的CAN数据流的拆分、重组、流控制等,即对CAN多帧进行组包拆包然后传给上层。

上图为CP AUTOSAR CAN网络架构。
一、网络架构、N-PDU、Sender和Receiver、通道、全双工和半双工

(一)、CAN网络架构
根据OSI参考模型,即定义了网络的七层架构,包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,AUTOSAR的CAN网络也参考了这个模型。
其中CanTp对应OSI分层里的网络层,基于ISO 15765-2协议,实现多帧数据打包、解包协调上下层工作。
所以CanTp也叫CAN的传输层或网络层。
CanTp本身没有缓冲区,通过向PduR请求缓冲区来发送接收数据。
(二)、N-PDU
N-PDU是CAN传输层的数据单元。
AUTOSAR规范里定义的N-PDU如下:
ISO 15765-2里定义的N-PDU如下:
再看代码里CanTp_Transmit()传入参数N-PDU类型为PduInfoType,根据AUTOSAR_SWS_CommunicationStackTypes的定义:
总的来说对CanTp而言需要处理的N-PDU包含唯一标识符(索引号)、数据长度、数据(包含N_PCI、N-SDU),其中N-SDU来自PduR层的数据,N_PCI为协议控制信息包含网络层的SF、FF、CF、FC的信息。
N_AI对应为CANID。
(三)、Sender和Receiver
发送方和接收方通信动作如下:
.req :
帧发送开始请求
.con :
帧发送完成确认
.ind :
帧接收完成指示
Sender N_USData.req:
发送方应用层向传输层输入的数据流。
Sender L_Data.req:
发送方传输层向数据链路层发出的一帧数据,并且N_As定时器启动。
Receiver L_USData.ind:
接收方从数据链路层收到的一帧数据输入给传输层。
Receiver N_USData.ind:
接收方从传输层组包完的数据流输送给应用层。
Sender L_Data.con:
发送方的数据链路层告诉传输层一帧数据已经发送完毕,N_As定时器停止。
Sender N_USData.con:
发送方的传输层通知应用层数据流已经发送完毕。
(四)、通道
通道属于CanTp的内部概念,可以配置为若干个通道,每个通道有自己的信息比如定时器参数、是否全双工、寻址信息等,每个可以链接一个或多个N-PDU,如果多个N-PDU使用同一个通道,那这个通道的资源会被共享,当一个N-PDU在传输时,另一个N-PDU想要传输时便不能传输。
(五)、全双工和半双工
CanTp的通道可以配置为全双工或半双工,为半双工时,当接收报文正在处理时,同一通道不能发送报文,同理正在发送报文时,同一通道内接收的报文会忽略,全双工则都支持。
二、SF、FF、CF、FC、N_WFTmax、非预期帧的处理
当CAN报文单帧或多帧时,发送方或者接收方就需要CAN报文里的包头进行识别来组包、拆包、流控制,这个动作由CanTp完成,包头对应着N_PCI。
AUTOSAR里N_PCI摘要如下:
本章描述的都是常规寻址下的帧格式,对于扩展寻址和混合寻址而言,需要占用Byte1为N_TA,PCI从Byte2开始。
对于CAN报文来说一帧小于等于7个字节的都是单帧否则是多帧,对于CANFD报文来说一帧小于等于62个字节的都是单帧否则是多帧。
(一)、SF
单帧,用于不需要分段传输数据和用于建立数据传输请求。
单帧的字段由PCItype、SF_DL、Data组成。
单帧的PCItype为00代表是单帧,在Byte1的高四位。
SF_DL代表数据长度,当CANDLC小于等于8时,SF_DL在Byte1的低四位,当CANDLC大于8时,Byte1的低四位为00,SF_DL在Byte2。
如果接收方收到的SF_DL为0或者是多帧的长度,那么接收方需忽略整个数据流并且接收方无Indication。
剩余的字节都为Data,Data长度不足CANDLC时,则用填充字节补满到CANDLC,填充字节一般根据客户需求定义。
(二)、FF
首帧,多帧里的第一帧,要传输多帧必须要先发第一帧,接收方收到第一帧后发送流控制帧给发送方。
首帧的字段由PCItype、FF_DL、Data组成。
首帧的PCItype为01代表是首帧,在Byte1的高四位。
FF_DL代表数据长度,当CANDLC小于等于4095时,FF_DL在Byte1的低四位和Byte2,当CANDLC大于4095时,Byte1的低四位和Byte2为00,FF_DL在Byte3、Byte4、Byte5、Byte6。
如果接收方收到的FF_DL超过了本身的接收数据缓存,则应该回流控制状态为Overflow并且接收方无Indication,发送方也中止传输。
如果接收方收到的FF_DL是单帧的长度,那么接收方需忽略整个数据流也不发送流控帧并且接收方无Indication。
剩余的字节都为Data,Data长度不足CANDLC时,则用填充字节补满到CANDLC,填充字节一般根据客户需求定义。
(三)、CF
连续帧,发送方接收到流控帧后开始发送后续的数据,每帧发送间隔和帧数量受流控帧控制,接收方接收完连续帧后应将全部数据组包完毕。
连续帧的字段由PCItype、SN、Data组成。
连续的PCItype为02代表是连续帧,在Byte1的高四位。
SN代表连续帧的序列号,在Byte1的低四位,发送方发完首帧收到流控帧后SN从1开始,往后每发一个连续帧则加1,最大为15,后面如果还有连续帧则重新变为0开始,SN不应受流控帧影响,接收方根据SN的顺序来组包,如果接收方发现序列号是错乱的则丢弃整个数据流并且N_USData.indication服务调用但是结果为N_WRONG_SN。
剩余的字节都为Data,Data长度不足CANDLC时,则用填充字节补满到CANDLC,填充字节一般根据客户需求定义。
(四)、FC
流控帧,接收方在收到发送方的第一帧后应当发送流控帧,流控帧就是接收方告诉发送方每帧发送的间隔、连续帧发送数量、接收方的状态。
流控帧的字段由PCItype、FS、BS、STmin组成。
流控帧的PCItype为03代表是流控帧,在Byte1的高四位。
FS代表接收方的状态表明发送方是否可以继续发送数据,在Byte1的低四位,由以下几个状态:
00,CTS状态,表示发送方可以继续发送数据,接收方准备接收BS个帧。
01,WAIT状态,表示发送方继续等待下一个流控帧,并且发送方重新启动N_BS定时器,FS为该状态后,发送方忽略后面的BS、STmin。
02:OVFLW状态,表示接收方收到的数据超过内部的数据缓冲区大小了,发送方接收到状态后应中止传输并且忽略后面的BS、STmin。
如果发送方收到无效的FS,则中止传输并且N_USData.confirm服务调用但是结果为N_INVALID_FS。
BS在Byte2,代表接收方需要接收多少个连续帧,如果为0,表示接收方不再发送流控帧,发送方可以一直发连续帧直到发完为止,如果为0x01-0xFF代表发送方的连续帧要多少个。
STmin在Byte3,表示接收方告诉发送方的两个连续帧之间的时间间隔最少是多少MS,值为0x00-0x7F表示0ms-127ms,值为0xF1-0xF9表示100us-900us,如果发送方收到的STmin不在这范围内则默认使用0x7F(127MS),
N_As+N_Cs的值不能比STmin小,否则不能保证接收方能正确的接收和处理数据流。
(五)、N_WFTmax
为了避免接收方持续发送流控帧状态为WAIT,导致发送方一直等待的情况,WFTmax表示接收方在数据流中最大只能发送多少个FS为1的流控帧。如果WFTmax参数为0,接收方则不能发送FS为1的流控帧。当WFTmax次数到达后,接收方中止接收本次数据流并且N_USData.indication服务调用但是结果为N_WFT_OVRN。
(六)、非预期帧的处理
ISO 15765-2协议里描述了多帧传输中,接收方如果收到非预期帧应该怎样处理,非预期帧即同一个N_AI未按预期的顺序或超出文档定义范围的帧即为非预期帧。
从图上可知,CAN的发送方和接收方对各类N-PDU的输入处理如下:
1、处于发送方时并且为全双工模式如果收到SF,则软件里开始进行多帧接收处理,如果为半双工则忽略。
2、处于发送方时并且为全双工模式如果收到FF,则软件里开始进行多帧接收处理,如果为半双工则忽略。
3、处于发送方时并且为全双工模式如果收到CF,则忽略,如果为半双工则忽略。
4、处于发送方时如果收到FC,如果之前发送过FF或者处于等待状态则处理否则忽略。
5、处于接收方正在接收多帧时如果收到相同CANID的SF,则中止当前接收并N_USData.indication服务调用但是结果为N_UNEXP_PDU,然后对当前接收到的SF作为新的开始。
6、处于接收方正在接收多帧时如果收到相同CANID的FF,则中止当前接收并N_USData.indication服务调用但是结果为N_UNEXP_PDU,然后对当前接收到的FF作为新的开始。
7、处于接收方收到CF时,如果之前发过流控帧或者收过连续帧,则处理CF并进行校验SN对不对,否则忽略。
8、处于接收方收到FC时,如果之前发送过FF或者处于等待状态则处理否则忽略。
9、收到其他不是规定类型的PDU都忽略。
单帧和多帧示意图如下:

三、N_As、N_Ar、N_Bs、N_Br、N_Cs、N_Cr
ISO 15765-2里规定了一些网络层定时参数,发送方和接收方的发送时间和超时时间需要遵守这些参数、
各个定时参数定义如下:
各个定时参数的执行流程如下:
(一)、N_As:
发送方的一帧数据从应用层开始经数据链路层发出的时间,最大超时时间为1000ms。
(二)、N_Ar:
接收方的一帧数据从应用层开始经数据链路层发出的时间,最大超时时间为1000ms。
(三)、N_Bs:
发送方发完一帧数据等待接收方发送流控帧的时间,最大超时时间为1000ms。
有三个场景:
1、发送方发完首帧到收到流控帧的时间。
2、发送方发完连续帧到收到流控帧的时间。
3、发送方收到流控帧(WAIT)到收到下一个流控帧的时间。
(四)、N_Br:
接收方发送流控帧的间隔时间,这个参数应该满足如下公式:
(N_Br+N_Ar)<(0.9*N_Bs)
有三个场景:
1、接收方收到首帧到应用层开始发送流控帧的时间。
2、接收方收到连续帧到应用层开始发送流控帧的时间。
3、接收方发完流控帧(WAIT)到应用层开始发送下一个流控帧的时间。
(五)、N_Cs:
发送方发送连续帧的间隔时间,这个参数应该满足如下公式:
(N_Cs+N_As)<(0.9*N_Cr)
有两个场景:
1、发送方收到流控帧到应用层开始发送连续帧的时间。
2、发送方发完连续帧到应用层开始发送下一个连续帧的时间。
(六)、N_Cr:
接收方接收连续帧的等待时间,最大超时时间为1000ms。
有两个场景:
1、接收方发完流控帧到收到连续帧的时间。
2、接收方收到连续帧到收到下一个连续帧的时间。
如果各个定时器参数超时了,那么处理动作如下:
N_As:
超时后,表示发送方未能发出首帧或连续帧,则中止本次传输,并且N_USData.confirm服务调用但是结果为N_TIMEOUT_A。
N_Ar:
超时后,表示接收方未能发出流控帧,则中止本次接收,并且N_USData.indication服务调用但是结果为N_TIMEOUT_A。
N_Bs:
超时后,表示发送方未能收到流控帧或者接收方未收到首帧或连续帧,则中止本次传输,并且N_USData.confirm服务调用但是结果为N_TIMEOUT_Bs。
N_Cr:
超时后,表示接收方未能收到连续帧或者发送方未收到流控帧,则中止本次接收,并且N_USData.indication服务调用但是结果为N_TIMEOUT_Cr。
四、CANTP_OFF、CANTP_ON
CanTp组件有两个状态机:CANTP_OFF、CANTP_ON,只有在CANTP_ON的情况下才可以执行组包、拆包的任务,状态的切换如下图所示:
五、数据一致性、静态配置
(一)、数据一致性
CanTp层没有缓冲区,因此,CanTp使用了PduR_CanTpCopyTxData() 或者是 PduR_CanTpCopyRxData()的函数来读取发送PduR的内存数据,上层也需要在发送接收期间锁住数据直到完成。

(二)、静态配置
CanTp管理所有连接通道的信息,CanTp的静态配置需要有以下属性:
1、CAN N-SDU 的数量;
2、每个 CAN N-SDU 的ID;
3、每个 CAN N-SDU 的传输方向(Tx or Rx);
4、每个 通道的寻址格式(普通、扩展、混合的11bit 或者是混合的29 bit):
5、每个N-SDU映射的L-SDU,即当前CanTp层的通道跟哪个CanIf层的通道关联。
6、是经典CAN还是CANFD。
六、CanTp和PduR交互
因为CanTp没有缓冲区,所有的数据来源于PduR。
(一)、发送流程
1、PduR请求传输50个数据字节触发CanTp执行CanTp_Transmit()。
2、CanTp调用PduR_CanTpCopyTxData()向PduR请求PDU缓冲区,通过CanIf_Transmit()发出去。
3、CanTp发送连续帧,每次发前向PduR Copy数据。
4、每帧报文发送完成后Can驱动调用CanTp_TxConfirmation(),CanTp 模块知道数据流已全部发完则调用 PduR_CanTpTxConfirmation() 通知上层已发送结束。
(二)、接收流程

1、Can驱动收到数据后通知CanIf用CanTp_RxIndication()通知CanTp有新的数据到来,CanTp调用PduR_CanTpStartOfReception()通知转发给PduR。
2、PduR返回一个25字节的可用缓冲区大小,CanTp发出一个FlowControl CTS。
3、CanTp将接收到的每一帧的数据提供给PduR,并监控剩余的缓冲区大小。
4、CanTp通过调用PduR_CanTpCopyRxData()知道PduR缓冲区不够了,则发出一条FS为等待的流控帧,直到上层有足够的缓冲区。
5、有足够的缓冲区后,CanTp发出一条FS为CTS的流控帧,并开始接收下一条连续帧。
6、接收到数据后,又发现PduR的缓冲区不够了,再发出一条FS为等待的流控帧,直到上层有足够的缓冲区。
7、当缓冲区够后,继续接收传给PduR.
8、CanTp认为接收完成调用 PduR_CanTpRxIndication() 函数通知 PduR 接收结束。
七、填充模式和非填充模式
CanTp里可以选择填充模式和非填充模式来处理DLC。
当为填充模式时,如果一帧的有效数据小于8字节,传输层将填充到满8字节止再发送。如果大于8字节而且为CANFD,传输层将数据无用数据到下一个合法长度值发送。DLC会相应改变。
当为非填充模式,传输层只发送有效数据,DLC是多少就是多少。
八、寻址方式
N-PDU由N_AI、N_PCI、N_Data组成,
N_TA是目标地址,N_SA是源地址,N_AE是扩展地址。
CanTp里会根据当前通道的寻址模式接收对应的帧,然后将N_PCI和N_Data提取出来传给上层。
根据ISO 15765-2里的定义将N-PDU映射到CAN数据帧的不同位置,构成了如下寻址格式:
(一)、常规寻址(Normal addressing)
N_AI映射到CANID里,
(二)、常规固定寻址(Normal fixed addressing)
仅允许用29位ID,N_AI分为N_TA和N_SA。
如果N_TA为物理寻址:
如果N_TA为功能寻址:
例子:
SA=0x01
TA=0x14
TAType=Physical
数据流为
0x36 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16
FS=0,BS=2,STmin=20ms
采用非填充方式
则总线上的实际数据流为:
ID: DLC: Data:
FF 0x18DA1401 8 0x10 0x17 0x36 0x01 0x02 0x03 0x04 0x05
FC 0x18DA0114 3 0x30 0x02 0x14
CF 0x18DA1401 8 0x21 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c
CF 0x18DA1401 8 0x22 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13
FC 0x18DA0114 3 0x30 0x02 0x14
CF 0x18DA1401 4 0x23 0x14 0x15 0x16
(三)、扩展寻址(Extended addressing)

仅允许用11位ID,N_AI里不包括N_TA,将N_TA放到Byte1里。
例子:
物理通信场景:

功能通信场景:

(四)、混合寻址(Mixed addressing)
如果是29位的CANID:
如果是11位的CANID:
九、主要函数
(一)、void CanTp_Init(const CanTp_ConfigType* CfgPtr)
初始化 CanTp 模块,CanTp状态机变成CANTP_ON。
(二)、Std_ReturnType CanTp_Transmit (PduIdType TxPduId, const PduInfoType* PduInfoPtr)
请求发送N-PDU。
(三)、Std_ReturnType CanTp_ChangeParameter (PduIdType id, TPParameterType parameter, uint16 value)
请求给一个PDU改变一个指定的传输层参数(BS、STMIN)。
(四)、Std_ReturnType CanTp_ReadParameter (PduIdType id, TPParameterType parameter, uint16 * value)
读取一个PDU的传输层参数(BS、STMIN)。
(五)、void CanTp_RxIndication(PduIdType RxPduId, const PduInfoType* PduInfoPtr)
CanIf层收到数据后调用该函数。
(六)、void CanTp_TxConfirmation(PduIdType RxPduId, Std_ReturnType result)
CanIf层发送数据后调用该函数。
(七)、void CanTp_MainFunction(void)
调度CanTp的主函数,用来处理N_As、N_Bs、N_Cs、N_Ar、N_Br等参数。
十、DaVinci Configurator主要配置
(一)、CanTpGeneral

此处配置的如是否支持寻址方式、是否支持CANFD、是否填充数据、是否开启CALLOUT测量两个CF的间隔时间、是否开启大数据传输、是否开启传输队列(当多个通道使用同一个N-PDU时开启此项,后面的通到则进入队列直到N-PDU释放)等。
(二)、CanTpConfig

此处添加CanTp的通道。
此处添加该通道的发送N-PDU和接收N-PDU
此处选择通道是全双工还是半双工。
上面两幅图是该通道的接收N-PDU和发送N-PDU的配置,配置传输层的参数如N_Ar、N_As、STmin等还有寻址方式。
并且选择对应哪个PDU,PDU的选择来自EcuC里,一般通过DBC或ARXML导入工具里,工具根据每个报文的类型自动将报文的传输路径给分配好,比如上图里的PDU是诊断报文,那么该通道的接收N-PDU自动会与下层的CanIf对应的L-PDU映射,与上层的PduR对应的通道映射并传到Dcm里。
通过查看Communication里的PDUs这项
再查看Routing Paths这项
可以看到该报文的上下映射关系,CanTp里映射到哪个创建的N-PDU。

如果该通道的N-PDU为非常规寻址,则可以添加AE、SA、TA的值。


上图是该通道的接收和发送N-PDU要必须要添加的选项。
总的来说CanTp的配置没有什么太难的东西,工具导入DBC或ARXML后,CanTp便会自动生成一堆PDU,主要是要理解CanTp的各个参数和功能,OEM会提供他们自己网络层的参数,这时候便把参数输入到CanTp里。
十一、使用范例
无,CanTp层主要起到承上启下的作用,报文的组包拆包主要在CanTp_RxIndication()、CanTp_TxConfirmation()、CanTp_MainFunction()里执行,CanTp_RxIndication()、CanTp_TxConfirmation()是CanIf层调用,CanTp_MainFunction()是需要周期调用。
十二、参考资料
AUTOSAR_SWS_CANTransportLayer
AUTOSAR_SRS_CAN
AUTOSAR_EXP_LayeredSoftwareArchitecture
AUTOSAR_SWS_CommunicationStackTypes
TechnicalReference_CanTp
ISO7498
ISO11898
ISO11519
ISO15765
ISO14229
can2.0
can_fd_spec
总结
本文文字描述多点,更像是本人的使用笔记,仅供参考,如有不对地方欢迎指教。另外也没描述元数据相关。
更多推荐



所有评论(0)