汽车诊断工程师如何入门?
在汽车电子 UDS 诊断开发中,功能寻址(Functional Addressing)与多帧分段传输(Segmented Transmission)的边界处理,是考验基础软件(BSW)工程师协议功底的核心场景。
本文将从 ISO 15765-2 标准机理、AUTOSAR 规范原文(SWS_CanTp_00093) 以及 ECU 内部代码落地三个维度,深度拆解网络层如何实现精准的漏洞防御与会话隔离。
一、 底层机理:为什么网络层严格禁止功能寻址发多帧?
多帧传输的双向流控握手(Flow Control)机制与功能寻址的广播(Broadcast)属性存在天然的逻辑冲突。
- 点对点的物理多帧: 发送方发送首帧(FF),接收方(单个 ECU)根据自身硬件缓存能力回复点对点的流控帧(FC),告知其能接受的块大小(
BS)和分离时间(STmin)。 - 广播通道的功能多帧: 功能寻址在总线层面上是 1 对 N 广播。如果诊断仪(Tester)通过功能寻址发送了一个首帧(FF),总线上所有满足条件的 ECU 都会在同一瞬间接收到。随后,全车 ECU 将在同一时刻试图向总线砸出各自的流控帧(FC)。
这将引发灾难性的 CAN 总线突发性仲裁冲突与网络风暴,导致大量错误帧,甚至直接让节点因错误计数爆表而总线关闭(Bus-off)。因此,ISO 15765-2 在网络层协议模型上就进行了死锁:流控机制必须基于点对点(Peer-to-Peer)的物理通道,功能寻址严禁任何形式的多帧交互。
二、 规范对齐:深入拆解 SWS_CanTp_00093 核心代码逻辑
在 AUTOSAR Classic Platform 规范中,标准用极度严谨的字眼对这一行为进行了 ECU 内部的双向围堵:
[SWS_CanTp_00093] ⌈ If a multiple segmented session occurs (on both receiver and sender side) with a handle whose communication type is functional, the CanTp module shall reject the request and report the runtime error code CANTP_E_INVALID_TATYPE to the Default Error Tracer. ⌋ ( )注意原文中的 on both receiver and sender side(双向拦截),它精密指导了 CanTp 模块在作为两种运行角色时的 C 语言代码落地:
1. 当 ECU 作为接收端(Receiver Side)
当外部错误地通过功能寻址发送了 首帧(FF) 或 连续帧(CF) 时,ECU 的 CanTp 模块在接收中断(或主函数轮询)中判定会话非法,直接终止接收状态机。
- 外在表现: ECU 保持静默,绝对不会向总线回复任何流控帧(FC),从而切断了引发网络风暴的源头。
2. 当 ECU 作为发送端(Sender Side)
当 ECU 上层组件(如 Dcm)错误地调用 CanTp_Transmit(),企图通过配置为 Functional 的 Tx Handle 发送长数据时,CanTp 在入口处判定其数据长度超出了单帧最大载荷(Classic CAN 为 7 字节)。
- 外在表现: API 直接拒绝并返回
E_NOT_OK,底层直接掐断,绝对不会向总线发出首帧(FF)。
3. 运行时错误上报
无论哪种情况,底层严禁静默无视,必须调用 DET 模块上报运行时错误码 CANTP_E_INVALID_TATYPE(标准定义通常为 0x90)。
规范级 BSW 核心代码架构参考
C
/* ==================== 1. 接收端拦截逻辑 ==================== */
void CanTp_RxIndication(PduIdType RxPduId, const PduInfoType* PduInfoPtr)
{
// ... 解析 PCI 得到 FrameType ...
if (CanTp_RxCfg[RxPduId].TaType == CANTP_FUNCTIONAL)
{
// 功能寻址通道上,一旦收到非单帧(SF)的组包报文(如 FF、CF)
if (FrameType != CANTP_FRAME_TYPE_SF)
{
/* 命中 SWS_CanTp_00093:上报 DET 运行时错误 */
(void)Det_ReportRuntimeError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_API_RX_INDICATION, CANTP_E_INVALID_TATYPE);
/* 终止接收会话,拒绝分配缓存(外在表现:绝不回 FC 帧) */
CanTp_AbortRxSession(RxPduId);
return;
}
}
// ... 正常单帧接收逻辑 ...
}
/* ==================== 2. 发送端拦截逻辑 ==================== */
Std_ReturnType CanTp_Transmit(PduIdType TxPduId, const PduInfoType* PduInfoPtr)
{
if (CanTp_TxCfg[TxPduId].TaType == CANTP_FUNCTIONAL)
{
// 功能寻址通道上,若发送数据长度超过了单帧最大载荷限制
if (PduInfoPtr->SduLength > CANTP_SF_MAX_LENGTH)
{
/* 命中 SWS_CanTp_00093:上报 DET 运行时错误 */
(void)Det_ReportRuntimeError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_API_TRANSMIT, CANTP_E_INVALID_TATYPE);
/* 判为非法请求,强行拒绝(外在表现:内部直接拦截,绝不发 FF 帧) */
return E_NOT_OK;
}
}
// ... 正常发送状态机启动逻辑 ...
}三、 架构边界:功能寻址单帧请求 $\rightarrow$ 物理多帧回复的合法性分析
在实际工程中,工程师经常会遇到一个典型场景:诊断仪发送功能寻址单帧(SF,如 19 02 09 读取全车故障码),ECU 接收后,使用物理寻址多帧(FF $\rightarrow$ FC $\rightarrow$ CF)进行长数据回复。
结论是:在 ISO 标准与 AUTOSAR 网络层架构中,这完全合法且受到原生支持。
我们可以通过动态 Handle 审查机制来证明它为何完美绕过了 SWS_CanTp_00093 的拦截网:
- 请求接收阶段(Tester $\rightarrow$ ECU):
- ECU 的 CanTp 收到一帧功能 ID 报文,命中了属性为
CANTP_FUNCTIONAL的 Rx Handle。但由于该报文是单帧(SF),不满足“多帧分段会话(multiple segmented session)”的触发条件,00093 放行,数据成功递交 Dcm。 - 响应发送阶段(ECU $\rightarrow$ Tester):
- Dcm 发现回复数据很长,触发多帧发送。根据 UDS(ISO 14229)底线规定,ECU 对任何诊断请求的响应,必须切换为该 ECU 专属的物理寻址(Physical)ID。此时,Dcm 调用的是配置为
CANTP_PHYSICAL的 Tx Handle。虽然开启了多帧分段传输,但因为使用的是物理句柄,00093 根本不会被激活。 - 流控接收阶段(Tester $\rightarrow$ ECU):
- Tester 收到 ECU 发出的物理首帧(FF)后,用该 ECU 专属的物理请求 ID 回复流控帧(FC)。该报文流入 ECU,命中其内置的
CANTP_PHYSICALRx 句柄(与 Tx 通道绑定的流控接收单元)。同样,因为是物理通道交互,00093 完美绕过,网络层状态机全速运转,CF 顺利发出。
四、 BSW 配置与 DET 调试指南
在实际的 AUTOSAR 基础软件配置与系统集成中,对该规则的管控主要依赖于工具链的前置校验与运行时的断言监控:
1. 配置工具链的“防呆”校验(Validation Rules)
在自定义 CanTpConfig 时(如使用 DaVinci Configurator、EB Tresos 或 ISOLAR 等):
- 当某个
CanTpRxNSdu或CanTpTxNSdu的CanTpTaType被显式配置为FUNCTIONAL时,工具链内置的规则检查器(Validation)会自动切断其与多帧属性(如CanTpBs、CanTpSTmin等流控参数)的关联。 - 如果配置中出现功能通道指向多帧传输链路,生成工具在代码生成(Generation)前会直接报出 Error 并阻断编译,这在工具链阶段就强制落实了
SWS_CanTp_00093的前置要求。
2. 基于 DET 的网络层健壮性调试
在进行网络层合规性测试(TP Compliance Test)或健壮性恶意注入测试时:
- 如果外部故意向 ECU 注入了功能寻址的首帧,或者上层代码发生异常踩踏,ECU 在总线上会表现为“完全静默”(不回正负响应,也不回流控)。
- 此时,基础软件工程师的首要动作是挂上仿真器,直接监控
Det_RuntimeErrorBuffer。 - 如果在缓存中精准抓取到了
ModuleId == 35(CanTp 模块的标准 ID)且ErrorId == 0x90(CANTP_E_INVALID_TATYPE),则可瞬间定格原因:会话由于触犯了 00093 铁律,已被网络层状态机在最底层无害化销毁。
—— 唯有死磕一手标准与架构底层,才能写出最健壮的代码。与各位汽车电子同仁共勉! ——