[CP_AUTOSAR] CanTp模块通信服务详解(三)

目录

  • 3.3、内部行为
  • 3.3.2、N-SDU Transmission
  • 3.3.3、Buffer strategy
  • 3.3.4、Protocol parameter setting services
  • 3.3.5、Tx and Rx data flow
  • 3.3.6、Relationship between CAN NSduId and CAN LSduId
  • 3.3.7、Concurrent connection
  • 3.3.8、N-PDU padding
  • 3.3.9、Handling of unexpected N-PDU arrival
  • 3.4、Error Classification
  • 3.4.1、Development Errors
  • 3.4.2、Runtime Errors
  •   在前面
    《[CP_AUTOSAR]_通信服务_CanTp模块(一)》 和
    《[CP_AUTOSAR]_通信服务_CanTp模块(二)》 文章中介绍了CanTp 模块的主要功能、与其它模块的交互关系,以及功能规范。本文再接着介绍下CanTp 模块的其它功能规范。

    3.3、内部行为

    3.3.2、N-SDU Transmission

      如之前文章中描述,上层通过 CanTp_Transmit() 函数来请求发送 N-SDU,函数的参数描述了待发送消息的CAN NSduId 和 Tx N-SDU 长度。
      下表是关于 N- PDU 发送的一些功能需求描述:

    需求 描述
    [SWS_CanTp_00225] 对于那些不使用元数据的连接,函数 CanTp_Transmit 应该使用 SduLength 信息,而不使用 N-SDU 数据缓存,这样是为了准备单帧或者首帧的PCI。
    [SWS_CanTp_00334] 当为了发送带有元数据的 N -PDU去调用函数 CanTp_Transmit 时,CanTp 模块应该存储在 N-SDU 元数据中包含的地址信息,并用这个信息来发送单帧,首帧和连续帧 N – PDUs,在元数据中的地址信息依赖于地址格式:
    1、Normal: none;
    2、Extended: N_TA;
    3、Mixed 11 bit: N_AE;
    4、Normal fixed: N_SA, N_TA;
    5、Mixed 29 bit: N_SA, N_TA, N_AE;
    [SWS_CanTp_00335] 对于通用连接的SF,FF,CF去调用函数 CanTp_Transmit ,CanTp 模块应该通过 N – PDU的元数据提供存储的地址信息,这个地址信息依赖于以下地址格式:
    1、Normal, Extended, Mixed 11 bit: none;
    2、Normal fixed, Mixed 29 bit: N_SA, N_TA;
    [SWS_CanTp_00167] 上层请求发送消息之后,在调用函数 PduR_CanTpCopyTxData 之前,CanTp 模块应该开始 N_Cs 超时计时,在时间消逝之前如果未获得数据,则中止通信 ;
    [SWS_CanTp_00086] 发送SF/FF/CF,CanTp 模块应该调用 PduR_CanTpCopyTxData 服务,以便上层拷贝发送的数据到 PduInfoType 结构中;
    [SWS_CanTp_00272] API 接口函数 PduR_CanTpCopyTxData()包含了一个参数 ’retry’,此参数用于恢复机制。而在 ISO 15765-2 规范中不支持这种恢复机制,因此此参数总是设置为空指针;
    [SWS_CanTp_00087] 如果函数 PduR_CanTpCopyTxData() 返回值为 BUFREQ_E_NOT_OK,CanTp 模块应该终止发送请求,并回调 PduR_CanTpTxConfirmation() (函数返回值为 E_NOT_OK)去通知上层这个失效;
    注意:如果上层暂时没有足够Tx缓存空间,函数 PduR_CanTpCopyTxData() 返回值为 BUFREQ_E_BUSY;
    [SWS_CanTp_00184] 如果函数 PduR_CanTpCopyTxData() 返回值为 BUFREQ_E_BUSY,CanTp 模块应稍后重新尝试拷贝数据;
    [SWS_CanTp_00280] 在 N_Cs 超时结束之后仍未获得数据,CanTp 模块应该通过回调 PduR_CanTpTxConfirmation() (函数返回值为 E_NOT_OK)去通知上层这个失效;
    [SWS_CanTp_00310] 如果 N_As 超时发生,CanTp 模块应该通过回调 PduR_CanTpTxConfirmation() (函数返回值为 E_NOT_OK)去通知上层;
    [SWS_CanTp_00309] 如果 FS 被设置为 OVFLW 的流控帧被接收,CanTp 模块应该终止发送请求,并通过回调 PduR_CanTpTxConfirmation() (函数返回值为 E_NOT_OK)去通知上层;
    [SWS_CanTp_00317] 如果 无效FS 的流控帧被接收,CanTp 模块应该终止发送请求,并通过回调 PduR_CanTpTxConfirmation() (函数返回值为 E_NOT_OK)去通知上层;
    [SWS_CanTp_00315] 在确认首帧发送、block 中的最后一个连续帧和显示 FS=WT 的流控帧,CanTp 模块应该对 N_Bs 进行时间观测;
    [SWS_CanTp_00316] 如果 N_Bs 超时发生,CanTp 模块应该终止此消息的发送,并且通过回调 PduR_CanTpTxConfirmation() (函数返回值为 E_NOT_OK)去通知上层;
    [SWS_CanTp_00090] 当发送会话成功完成时,CanTp 模块应该通过回调 PduR_CanTpTxConfirmation() (函数返回值为 E_OK)去通知上层;
    [SWS_CanTp_00343] 在调用函数 CanIf_Transmit() 发送SF/FF/CF返回值为E_NOT_OK时,CanTp 模块应该终止当前发送连接;

    3.3.3、Buffer strategy

      由于 CanTp模块没有缓存能力,所以要发送的N-SDU数据载荷不会在内部复制,收到的 N-PDU 也不会在内部重新组装。CanTp 层直接工作在上层模块(如PduR, DCM 和 COM)的内存区域中,为了访问这些内存区域,CanTp 层使用了 PduR_CanTpCopyTxData() 或者是 PduR_CanTpCopyRxData()的函数。因此,为了保护数据一致性,上层应该锁住内存区域直到传输完成。当内存区域被锁住时,上层不可能会写入数据到内存区域中。
      下图是接收和发送缓存的锁状态:即发送过程中锁住内存区域,发送完成后,解锁内存区域;开始接收时锁住内存区域,完成接收时,解锁内存区域。

      接收时调用函数 PduR_CanTpStartOfReception() 或者发送时调用 CanTp_Transmit(),上层模块应该保持内存区域的buffer锁住,直到接收完成(调用 PduR_CanTpRxIndication())或者发送完成(调用 PduR_CanTpTxConfirmation())发生。
      下图就是一个例子,展示了发送一帧的过程,该帧长度为50个字节,使用CAN2.0协议。
      1、PduR 请求发送一个50字节的数据;
      2、CanTp 模块请求要传输的数据,并发送首帧;
      3、CanTp 模块以序列化的连续帧发送剩余数据,每个连续帧中7个字节数据;
      4、CanTp 模块调用 PduR_CanTpRxIndication() 确认传输数据的发送;

      下图是接受一个49个字节的N – PDU的案例,上层汇报25个字节作为 Tx 缓存空间。
      1、CanIf 模块使用 CanTp_RxIndication() 来通知 PduR 需要接受一个新的消息;
      2、 PduR 模块返回缓存空间为25字节,CanTp 模块发送一个流控帧(状态为 CTS);
      3、CanTp 模块提供每个接收到的帧数据给到 PduR 模块,并且检测剩余的缓存空间;在第二个连续帧传输之后,剩余空间剩余5个字节,不够容纳下一个 block (2个连续帧);
      4、CanTp 模块调用 PduR_CanTpCopyRxData() 函数,函数入参数据长度为0,另外一个入参数据为空指针,并发出一条FS为等待状态的流控帧,知道有足够下一个block大小的空间;
      5、当有足够下一个block大小的空间时,CanTp 发出一条FS为CTS状态的流控帧,并开始继续接收下一个连续帧 block ;
      6、当接收到 block 中的最后一条连续帧,剩余的缓存空间又不足以容纳下一个 block ,因此,CanTp 再次发送FS为等待状态的流控帧,并检测剩余的缓存空间;
      7、当缓存空间对最后一个 block 准备就绪时,CanTp 模块继续接收;
      8、CanTp 模块调用 PduR_CanTpRxIndication() 函数通知 PduR 接收结束;

    3.3.4、Protocol parameter setting services

    需求 描述
    [SWS_CanTp_00091] CanTp 模块应该支持一些传输层内部参数(STmin 和 BS)的动态设置。

    3.3.5、Tx and Rx data flow

      下图展示了单帧消息的发送过程:

      下图展示了被分割消息的发送过程:

      流控帧可以调整发送方来适应接收方的接收能力,

    需求 描述
    [SWS_CanTp_00092] CanTp 模块应该提供1对n的通信(即功能寻址)。
    [SWS_CanTp_00093] 如果多个被分割会话发生(在接收端和发送端),其句柄的通信类型是功能寻址,CanTp 模块应该拒绝这个请求,并向Default Error Tracer汇报运行时的错误代码 CanTp.CANTP_E_INVALID_TATYPE 。

    3.3.6、Relationship between CAN NSduId and CAN LSduId

      此部分描述了CAN NSduId 和 CAN LSduId之间存在的联系,

    需求 描述
    [SWS_CanTp_00035] CAN NSduId应该链接到一个 CAN LSduId,用于发送 SF / FF / FC 和 CF帧。
    [SWS_CanTp_00281] 如果消息被配置为扩展或者混合的地址模式, CanTp 模块应该填充每个发送部分(SF / FF / CF)第一个字节为 N_TA (扩展地址时)或者填充 N_AE (混合地址时)。因此, CAN NSduId 值与N_TA 或者 N_AE值有关。
    [SWS_CanTp_00282] FC PDUs 可以改变发送方发送的连续帧之间的延时。
    [SWS_CanTp_00283] 对于扩展地址格式,FC 的第一个数据字节包含了 N_TA值 或者是 N_TA 和 N_TAtype的唯一结合后的值。对于混合地址格式,FC 的第一个数据字节包含 N_AE值;
    [SWS_CanTp_0094] 因此流控帧的CAN LSduId 与它的 N_TA值相结合(比如,N_AI),或者与 N_AE 值相结合,那么结合后的 CAN LSduId 只能够区分一个 CAN NSduId。
    [SWS_CanTp_00284] 在接收方向,每个(SF / FF / CF) PDU 的第一个字节值应该被用来去决定相关的 N-PDU 。
    [SWS_CanTp_00095] 因此,扩展地址接收N-PDU,CanTp 模块应该提取 N_TA 值,来构建出对应的N-PDU 。

      下图描述了这些需求:

    3.3.7、Concurrent connection

      CanTp 层应该能够同时管理几个连接(比如同时接收 UDS 和 OBD的请求)。

    需求 描述
    [SWS_CanTp_00096] CanTp 模块应该同时支持几个连接 。
    [SWS_CanTp_00120] 在CanTp 模块中,可以配置同时连接 。
    [SWS_CanTp_00285] 外部无法访问连接通道,只能由 CanTp 模块内部访问 。
    [SWS_CanTp_00286] CanTp 层模块可以所有的参数(通道数量、时序参数)。
    [SWS_CanTp_00121] 每个 N – PDU静态链接到一个连接通道,其表示了接收和发送消息的内部路径,可以附着到一个或者多个N – PDU 。
    [SWS_CanTp_00122] 每个连接通道和其他的连接通道都是独立的,这意味着连接通道使用自己的资源,比如内部缓存,时序或者状态机。
    [SWS_CanTp_00190] CanTp 模块应该路由N-PDU到正确的连接通道 。
    [SWS_CanTp_00287] CanTp 模块不能并行接收同样ID的N-SDU,因为被接收的帧无法被分配给正确的通道 。
    [SWS_CanTp_00288] 如果一个连接通道被分配给多个 N – PDUs,那么资源就在N – PDUs中共享;如果没有空闲的连接通道,CanTp 模块会拒绝收发 。
    [SWS_CanTp_00289] 连接通道数不能直接配置,其取决于配置工具,取决于分析N-SDU/Channel 路由表 。
    [SWS_CanTp_00123] 如果配置的发送连接通道正在使用(CANTP_TX_PROCESSING),CanTp 模块应该拒绝新的发送请求链接到这个通道 。当上层使用函数 CanTp_Transmit() 请求发送消息时,CanTp 模块应该返回 E_NOT_OK。
    [SWS_CanTp_00124] 当接收到不带元数据的SF 或者 FF N-PDU时,并且对应的通道正在接收同样的连接(CANTP_TX_PROCESSING,相同的 N_AI),CanTp 模块应该停止正在接收中的接收,而开始处理新的接收帧。 当另外一个连接通道(不同的 N_AI)接收到不带元数据的SF 或者 FF N-PDU时,SF / FF应该被忽略。
    [SWS_CanTp_00337] 当接收到带元数据的SF 或者 FF N-PDU(表示通用连接)时,而相应的连接通道正在接收,SF / FF应该被忽略 。
    [SWS_CanTp_00248] 当一个Tx N-PDU 不同通道连接所使用时,应该使用TxConfirmation串行访问这个N-PDU。如果对该N-PDU使用扩展或混合寻址,或者当它具有元数据时,Rx N-PDU只能在两个或两个以上不同的连接通道上使用 。

    3.3.8、N-PDU padding

      所有的上层软件模块都会关注帧数据长度(比如OBD始终要求数据长度被设置为8字节,而UDS不是),为了保证这种兼容性,在预编译时期,对于 Rx N-SDU 使用 CanTpRxPaddingActivation ,对于 Tx N-SDU 使用CanTpTxPaddingActivation 去配置填充功能。

    需求 描述
    [SWS_CanTp_00116] CanTp 模块应该传输数据字节到上层,在填充和非填充模式下 。
    [SWS_CanTp_00059] 填充的字节值可以通过参数 CANTP_PADDING_BYTE 来配置 。
    [SWS_CanTp_00344] Rx N-SDU 帧字节数小于8字节,并且 CanTpRxPaddingActivation = CANTP_ON,CanTp 模块应该只能接收SF Rx N-PDUs 或者 最后一个 CF Rx NPDUs。
    [SWS_CanTp_00345] Rx N-SDU 帧字节数小于8字节,并且 CanTpRxPaddingActivation = CANTP_ON,CanTp 模块借助于回调函数 CanTp_RxIndication() 接收属于那个N-PDU的 SF Rx N-PDU,N-SDU 长度小于8字节,CanTp 模块应该拒绝接收。运行时,错误码 CanTp.CANTP_E_PADDING 应该汇报给Default Error Tracer。
    [SWS_CanTp_00346] Rx N-SDU 帧字节数小于8字节,并且 CanTpRxPaddingActivation = CANTP_ON,CanTp 模块借助于回调函数 CanTp_RxIndication() 接收属于那个N-PDU的最后一个 CF Rx N-PDU ,N-SDU 长度小于8字节,CanTp 模块应该回调 PduR_CanTpRxIndication() 函数(返回值为E_NOT_OK)丢弃正在进行中的接收,运行时,错误码 CanTp.CANTP_E_PADDING 应该汇报给Default Error Tracer。
    [SWS_CanTp_00347] Rx N-SDU的CanTpRxPaddingActivation = CANTP_ON, CanTp 模块应该发送 FC N-PDUs(长度为8字节),未使用的字节应该用CANTP_PADDING_BYTE 来填充 。
    [SWS_CanTp_00348] Tx N-SDU 帧数据载荷小于8字节,CanTpTxPaddingActivation = CANTP_ON,CanTp 模块应该借助于CanIf_Transmit() 函数来发送属于那个N-PDU的 SF Tx N-PDU 或者最后一个 CF Tx N-PDU ,字节长度为8字节,N-PDU 未使用的字节应该用CANTP_PADDING_BYTE 来填充 。
    [SWS_CanTp_00349] 借助于回调函数 CanTp_RxIndication() , Tx N-SDU 的 FC N-PDU被接收,且 CanTpTxPaddingActivation = CANTP_ON,且该FC 长度小于8字节。CanTp 模块通过回调 PduR_CanTpTxConfirmation() 函数(其返回值 E_NOT_OK)丢弃该传输会话,运行时,错误码 CanTp.CANTP_E_PADDING 应该汇报给Default Error Tracer。
    [SWS_CanTp_00351] CanIf_Transmit() 函数传输不符合DLC值(0…8, 12, 16, 20, 24, 32, 48, 64)数据长度的消息,CanTp 模块应该使用更高的DLC值用于传输,并且使用 CANTP_PADDING_BYTE 来初始化未使用的字节。

      以下图片表示 ISO 帧:

    3.3.9、Handling of unexpected N-PDU arrival

      CanTp 模块对于非预期的 N-PDU 报文,很大程度上取决于N-PDU的通信方向。

    需求 描述
    [SWS_CanTp_00057] 如果接收到非预期帧,CanTp 模块应该根据下表作出对应的操作,表中内容根据CanTp 内部状态,指定了 N-PDU 处理方式。

      接收到的 N-PDU 在传输或者发送中,包含了同样的地址信息(N_AI),在 N-PDU收到时,地址信息(N_AI)可能正在处理中。

      下表是N-PDU报文到达时的处理方法:

    状态 SF FF CF FC Unknown N-PDU
    Segmented
    Transmit
    in
    progress
    如果一个接收正在处理中,应根据以下单元处理,否则在开始接收时处理SF。 如果一个接收正在处理中,应根据以下单元处理,否则在开始接收时处理FF。 如果一个接收正在处理中,应根据以下单元处理,否则忽略它。 如果FS是等待状态,处理FC,否则忽略它; Ignore
    Segmented
    Receive
    in
    progress
    终止当前接收,通过 indication 函数(返回值为 E_NOT_OK)汇报给上层,并开始接收新的SF; 终止当前接收,通过 indication 函数(返回值为 E_NOT_OK)汇报给上层,并开始接收新的FF; 正在进行的接收中处理CF,并执行相应的检测(比如SN号) 如果传输正在处理中,应根据以上单元处理,否则忽略它 Ignore
    Idle 开始接收时处理SF 开始接收时处理FF Ignore Ignore Ignore

    3.4、Error Classification

      本部分描述了 CanTp 模块是如何管理一些错误类别的,其可能会在基础软件生命周期内发生。

    需求 描述
    [SWS_CanTp_00008] 一旦错误或者异常发生了,CanTp 模块不能修改当前的模块状态,而是应该汇报错误事件。
    [SWS_CanTp_00291] 如果是产品问题,DEM 模块应该通过 FIM 执行相应的后处理(比如回调模块进行状态修改)。

    3.4.1、Development Errors

      [SWS_CanTp_00293]

    错误类型 错误码
    API服务函数使用了错误的形参:当 CanTp 模块回调函数时使用了无效参数 CANTP_E_PARAM_CONFIG 0x01
    API服务函数使用了错误的形参:当 CanTp 模块回调函数时使用了无效参数ID CANTP_E_PARAM_ID 0x02
    API服务函数使用了空指针 CANTP_E_PARAM_POINTER 0x03
    模块初始化失败 CANTP_E_INIT_FAILED 0x04
    模块未初始化,调用了API函数 CANTP_E_UNINIT 0x20
    无效的发送 PDU ID CANTP_E_INVALID_TX_ID 0x30
    无效的接收 PDU ID CANTP_E_INVALID_RX_ID 0x40

    3.4.2、Runtime Errors

      [SWS_CanTp_00352]

    错误类型 错误码
    接收到的 PUD 数据长度小于8字节 CANTP_E_PADDING 0x70
    调用 CanTp_Transmit() 函数,使用功能寻址和长度参数来配置Tx I-PDU,则消息不能发送SF CANTP_E_INVALID_TATYPE 0x90
    请求操作不支持:一个 N-PDU 取消了发送/接收的请求,但它并不在接收/发送过程中; CANTP_E_OPER_NOT_SUPPORTED 0xA0
    在接收/发送中,如果是实现方面的错误而不是协议超时错误,应汇报错误事件 CANTP_E_COM 0xB0
    在接收中,发生了协议超时错误,应汇报错误事件 CANTP_E_RX_COM 0xC0
    在发送中,发生了协议超时错误,应汇报错误事件 CANTP_E_TX_COM 0xD0

      [SWS_CanTp_00229]:
      如果任务因为 As, Bs, Cs, Ar, Br, Cr 超时而停止了,CanTp 模块应该汇报开发实现层面的错误码 CanTp.CANTP_E_RX_COM (如果是接收过程)或者 CanTp.CANTP_E_TX_COM (如果是发送过程);如果任务因为其他协议层面错误而停止,CanTp 模块应该汇报运行时的错误码 CanTp.CANTP_E_COM 给 DET 模块。

       更多内容可参考 CP_AUTOSAR_总目录,点击跳转

    作者:三星小卤蛋

    物联沃分享整理
    物联沃-IOTWORD物联网 » [CP_AUTOSAR] CanTp模块通信服务详解(三)

    发表回复