详解AUTOSAR:CanXcp传输链路与PDU离线队列机制

2026-09-211

ECU 完成 XCP 初始化后,测量标定工具仍可能收不到任何响应。一个常见原因不是 CAN 通道或 A2L 文件错误,而是 CanXcp 初始化后处于 CANXCP_SET_OFFLINE:协议层可以产生响应,传输层却不会把帧发到总线。如果项目没有 CanSM,或者使用的状态管理器不会切换 CanXcp 的 PDU 模式,就必须由应用显式调用 CanXcp_SetPduMode() 进入在线状态。

这个启动细节揭示了 CanXcp 的核心职责。XCP Protocol Layer 负责命令和会话语义,CanXcp 作为 XCP on CAN Transport Layer,负责在协议层与 AUTOSAR CanIf 之间搬运 CTO/DTO、管理发送确认、缓存暂时无法发送的帧,并通过主函数重试队列和触发 DAQ 发送。

CanXcp 是硬件无关的传输协议实现,能够移植到不同 CAN 控制器,但微控制器、编译器和存储模型的组合很多,并不承诺在所有组合上都无需适配即可运行。这里所说的 Application 也不局限于用户应用代码,而是泛指调用 CanXcp 的任意上层软件。

1. CanXcp 的职责边界

XCP 栈可拆成协议语义和总线传输两层。协议层解析 CONNECT、测量、标定、DAQ 等 XCP 语义;CanXcp 不重复实现这些命令,而是把接收到的 XCP L-SDU 交给协议层,再把协议层产生的响应或异步数据交给 CanIf

层次 主要职责 与 CanXcp 的接口
XCP Master 发出命令、接收响应和测量数据 通过 CAN/CAN FD 报文与 ECU 通信
XCP Protocol Layer 命令解析、会话状态、DAQ/STIM 等协议处理 调用 CanXcp_Send,接收 Xcp_CommandXcp_SendCallBack
CanXcp XCP on CAN 报文收发、PDU 模式、发送队列、确认转发 对上连接协议层,对下连接 CanIf
CanIf CAN L-PDU 收发与确认 调用 Xcp_CanIfRxIndicationXcp_CanIfTxConfirmation

CAN 与 CAN FD 的差异直接体现在单个 XCP Packet 的长度上:经典 CAN PDU 最多承载 8 Byte;CAN FD Mode 2 最多承载 64 Byte。该上限还会影响全局 MaxCtoMaxDto 在各通道上的实际有效值。

总线类型 XCP Packet 长度 CanXcp 发送接口的 len 范围
Classical CAN 最多 8 Byte 1..8
CAN FD Mode 2 最多 64 Byte 1..64

2. 从命令接收到发送确认的完整链路

接收路径从 CanIf 回调开始。CAN Interface 收到 XCP L-PDU 后调用 Xcp_CanIfRxIndication(),CanXcp 根据接收 PDU ID 和 PduInfoType 中的长度、数据指针,把 Packet 交给 XCP Protocol Layer。协议层处理命令后调用 CanXcp_Send() 提交响应,CanXcp 再通过 CanIf_Send() 发送。

发送成功并不以 CanIf_Send() 返回为终点。CAN Interface 完成 L-PDU 发送后调用 Xcp_CanIfTxConfirmation(),CanXcp 再通过 Xcp_SendCallBack 把确认传回协议层。SERVEVDAQ 等异步 XCP Packet 也沿用这条发送与确认链路。

原文图示 1

这条链路中,Rx PDU ID 用于识别收到的 CAN L-PDU,Tx PDU ID 用于关联成功发送的 L-PDU。所有相关 API 都是 void,接口表没有定义返回错误码,因此链路推进依赖正确的 PDU 映射、回调配置和发送确认,而不是上层轮询返回值。

3. PDU 模式、发送队列与重试

CanXcp 初始化后的 PDU 模式固定为 CANXCP_SET_OFFLINE。通常由 CAN State Manager 把它切换为在线;没有 CanSM,或状态管理器来自其他供应商时,应由集成代码调用:

CanXcp_SetPduMode(XcpNwH, CANXCP_SET_ONLINE);

如果没有完成这一步,CanXcp 不会发送 XCP 帧。进入离线模式并不等价于立即丢弃待发送数据:帧会保存在 Send Queue 中,直到重新在线或队列发生 overrun。

原文图示 2

CanXcp_MainFunction() 负责处理未能立即发送而进入队列的消息,并触发 CAN 上的 DAQ 消息。一般情况下由 Schedule Manager(SchM)周期调用;没有 SchM 或使用第三方 SchM 时,应用必须自行周期调度。

原文图示 3

主函数周期有两种不同要求,不能只记住一个固定值。

场景 建议周期 原因
CanIf 具备正常发送排队能力 多数情况下 5 ms10 ms 足够 主函数主要处理未能立即发送的排队消息,并触发 DAQ
CanIf 的 transmit queue 被关闭 推荐 1 ms 总线忙时 XCP Slave 消息可能需要多次请求;调用越快,重新参与总线仲裁越早

CanIf 没有发送队列时,CanXcp 自身的主函数重试就成为关键补偿路径。周期不是越短越好,而是要在 XCP 响应延迟、DAQ 节拍和 ECU 任务负载之间选择;明确给出的参考值是常规场景 5/10 ms,关闭 CanIf transmit queue 时 1 ms

4. PDU Mode 与组件启停不是同一个开关

CanXcp 提供两组容易混淆的运行期控制:CanXcp_SetPduMode() 只控制 XCP 帧能否发送;XCP_ACTIVATE()XCP_DEACTIVATE() 控制 XCP Protocol Layer 与 Transport Layer 的整体功能。

控制接口 控制范围 被阻止的数据如何处理 典型用途
CanXcp_SetPduMode(..., CANXCP_SET_OFFLINE) 总线发送能力 帧保存在 Send Queue,直到在线或 overrun CAN 总线尚未可通信、网络切换
CanXcp_SetPduMode(..., CANXCP_SET_ONLINE) 总线发送能力 允许排队帧继续发送 CanSM 通知总线上线
XCP_DEACTIVATE() 协议层和传输层全部功能 组件功能被锁定 量产 ECU 默认关闭 XCP,由诊断条件解锁
XCP_ACTIVATE() 协议层和传输层全部功能 恢复组件功能 满足授权或诊断条件后启用 XCP

XCP 默认处于组件已激活状态,但 PDU 模式在初始化后是离线状态。也就是说,“组件可执行”与“允许向 CAN 发送”是两个正交状态。量产项目若同时使用诊断激活和网络状态管理,必须分别维护这两个状态,不能用一个接口代替另一个。

原文图示 4

4.1 Resume Mode 下为什么应使用 PDU Mode

Resume Mode 启用后,如果 CAN 总线尚未就绪,Resume Mode 触发的帧可能无法发送;随后 XCP 再次初始化,初始化过程又包含 Resume Mode 初始化,从而存在递归风险。对应的规避方法是使用 PDU Mode:总线未就绪时先保持 CANXCP_SET_OFFLINE,让帧进入队列;总线可通信后再切换为 CANXCP_SET_ONLINE

这一路径的关键不是“延后初始化”,而是把协议/会话初始化与总线可发送状态解耦。PDU Mode 能在总线未准备好时有效阻止发送,同时在队列未 overrun 的前提下保留帧。

5. MaxCto、MaxDto 配置与混合 CAN/CAN FD 通道

CanXcp 使用两个全局上限参数:

/MICROSAR/Xcp/XcpConfig/XcpTransportLayer/XcpOnCan/XcpOnCanMaxCto
/MICROSAR/Xcp/XcpConfig/XcpTransportLayer/XcpOnCan/XcpOnCanMaxDto

它们选择系统允许的最大 CTO/DTO 长度,但每个通道的实际值仍受该通道 PDU 大小限制。混合多通道系统可能同时存在 8 Byte Classical CAN PDU 和 64 Byte CAN FD PDU,此时全局 MaxCto/MaxDto 可以配置为 64,经典 CAN 通道会自动限制为 8

全局配置 通道 PDU 大小 通道实际最大值
MaxCto = 64MaxDto = 64 Classical CAN:8 Byte 自动限制为 8 Byte
MaxCto = 64MaxDto = 64 CAN FD Mode 2:64 Byte 最大可使用 64 Byte

因此,全局参数描述的是“最大可能值”,不是所有通道都强制使用同一帧长。协议层生成 Packet 时仍必须遵守当前逻辑通道对应的有效上限。

6. API、回调与协议层服务

6.1 协议层调用的 CanXcp 服务

API 参数 功能 返回值 上下文与可重入性
CanXcp_Send Xcp_Channel:逻辑通道;len:Packet 长度;msg:数据指针 请求发送 DTO 或 CTO 不可重入;可从 XcpEventXcpBackground 和 CAN Interface 上下文调用
CanXcp_MainFunction 处理传输层周期任务、队列重试和 DAQ 发送触发 不可重入;由 SchM 或应用周期调用

CanXcp_Send()Xcp_Channel 取值受 Multi Client 配置影响:Multi Client 关闭时始终为 0;开启时反映协议层逻辑 XCP 通道。len 在经典 CAN 上为 1..8,在 CAN FD 上为 1..64

6.2 CanIf 调用的传输层回调

API 参数 功能 返回值 上下文与可重入性
Xcp_CanIfRxIndication CanCanXcpRxPduId:接收目标 PDU ID;PduInfoPtr:数据指针和长度 通知收到 CTO/DTO Packet,并交给协议层 CAN Interface 上下文;不可重入
Xcp_CanIfTxConfirmation CanTxPduId:成功发送的 PDU ID 确认 CTO/DTO 已成功发送,并通知协议层 CAN Interface 上下文;不可重入

这两个函数需要在生成工具中配置为 CanIf 的接收通知和发送确认回调。漏配 TxConfirmation 会让 CanXcp 无法把发送完成事件传递给协议层;Rx PDU ID 映射错误则会让接收到的 XCP L-SDU 无法进入正确逻辑通道。

6.3 其他层调用的服务与宏

API/宏 参数 功能 Service ID 约束
CanXcp_Init ConfigPtr:Post-Build 配置指针 初始化 XCP on CAN Transport Layer 未给出 系统初始化期间调用;不可重入;仅 Post-Build 配置评估该指针
CanXcp_GetVersionInfo Versioninfo:版本信息输出地址 返回组件版本、Vendor ID 和 AUTOSAR Module ID,版本采用 BCD 编码 未给出 未列出额外限制
CanXcp_SetPduMode XcpNwH:通常为 0;PduMode:ONLINE/OFFLINE 控制 XCP 帧发送,离线时使用 Send Queue 7 Task level;同步;不可重入
XCP_ACTIVATE() 启用 XCP Protocol Layer 与 Transport Layer 全部功能 Task level;同步;不可重入
XCP_DEACTIVATE() 锁定 XCP Protocol Layer 与 Transport Layer 全部功能 Task level;同步;不可重入
CanXcp_InitMemory 启动代码未初始化 RAM 时完成显式内存初始化 未给出 AUTOSAR 外扩展;应在依赖已初始化内存的调用之前执行

6.4 CanXcp 调用的协议层接口

协议层服务 CanXcp 使用目的
Xcp_Command(uint8 Xcp_Channel, const uint32* pCommand) 把接收命令交给协议层处理
Xcp_SendCallBack(uint8 Xcp_Channel) 把发送确认传回协议层
Xcp_SetActiveTl(uint8 Xcp_Channel, uint8 Tl) 设置当前活动 Transport Layer
Xcp_GetActiveTl(uint8 Xcp_Channel) 读取当前活动 Transport Layer
Xcp_GetSessionStatus(uint8 Xcp_Channel) 读取 XCP 会话状态
Xcp_TlMainFunction(uint8 ActiveTl) 转发 Transport Layer 周期处理

这些接口属于 XCP Protocol Layer,CanXcp 只负责在 CAN 传输事件发生时调用它们,不定义其内部协议行为。

7. 并发保护与独占区

CanXcp 使用 CANXCP_EXCLUSIVE_AREA_0 保证关键区的原子性。该独占区必须映射到允许嵌套调用的 interrupt lock/unlock 函数,因为 Xcp_EventXcp_SendCallBackXcp_MainFunctionXcp_Command 可能相互打断。

原文图示 5

CanXcp_Send、两个 CanIf 回调和主函数都不可重入,独占区配置不能只保护某一个入口。调度分析应同时纳入 CAN ISR、DAQ 事件上下文、后台处理和周期 Task,确认嵌套锁不会在回调链中被错误释放。

8. 交付文件、版本与 A2L 集成

8.1 实现和生成文件

文件 作用 集成约束
CanXcp.c XCP on CAN Transport Layer 实现 用户不得修改
CanXcp.h 传输层 API 应先于 XcpProf.h 包含;应用不得修改
CanXcp_Types.h 传输层类型定义 内部使用,不应单独包含或修改
CanXcp_Cfg.h XCP on CAN 配置外部声明 由 GENy 生成
CanXcp_Lcfg.c Link-Time 参数定义 由 GENy 生成
CanXcp_PBcfg.c Post-Build 参数定义 由 GENy 生成

未使用 GENy 配置 AUTOSAR CAN Interface 时,与项目适配直接相关的是 CanXcp_Cfg.hCanXcp_Lcfg.cCanXcp_PBcfg.c 这些生成文件;其余实现文件仍不应手工改写。

8.2 BCD 版本常量

CanXcp 提供三个可由应用随时读取的外部常量,用 BCD 形式表达主版本、次版本和发布版本:

kXcpOnCanAsrMainVersion = (CP_XCPONCANASR_VERSION >> 8);
kXcpOnCanAsrSubVersion = (CP_XCPONCANASR_VERSION & 0x00ff);
kXcpOnCanAsrReleaseVersion = CP_XCPONCANASR_RELEASE_VERSION;

例如版本 1.00.00 对应主版本 0x01、次版本 0x00、发布版本 0x00CanXcp_GetVersionInfo() 返回的版本信息同样采用 BCD 编码,并同时提供 Vendor ID 和 AUTOSAR Module ID。

8.3 A2L 文件

GENy 会导出 CanXCPAsr.a2l,其中包含 XCP_ON_CAN IF_DATA 段,可供 CANape 等 XCP Master 的主 A2L 模板引用:

/begin IF_DATA XCP
  /include "CanXCPAsr.a2l"
/end IF_DATA

这个文件解决的是 Master 侧 XCP on CAN 传输参数接入,不替代 ECU 内 CanIf PDU、CanXcp 通道和 PDU Mode 的配置。

9. 限制与明确不支持的能力

CanXcp 对 CAN Identifier、Slave 发现和 Multiple Identity 有三项明确限制。

限制 具体边界 对标定系统的影响
DAQ List 分配 CAN Identifier 仅有一个 CAN Identifier 用于 CMD/STIM,另一个用于 RES/EV/DAQ;不支持 GET_DAQ_IDSET_DAQ_ID 不能为各 DAQ List 动态分配独立 CAN ID
网络内 Slave 自动发现 不支持 GET_SLAVE_ID Master 不能依靠该命令枚举网络中的全部 XCP Slave
Multiple Identity 只在单 CAN 通道配置下可用 多通道项目不能同时使用该 Multiple Identity 能力

这些限制应在 CANape 工程、A2L 组织和 ECU 通道规划阶段处理。特别是多通道方案,不能在集成后期再假设 Multiple Identity 或按 DAQ List 分配 CAN ID 可以由配置开关补上。

10. 集成与调试落点

观察点 正常条件 异常表现
初始化后的 PDU Mode CanSM 或应用切换到 CANXCP_SET_ONLINE 能接收命令但没有任何 XCP 帧发出
Rx 回调 CanIf 调用正确的 Xcp_CanIfRxIndication,PDU ID 与逻辑通道匹配 协议层看不到 CMD/STIM
Tx 回调 发送完成后调用 Xcp_CanIfTxConfirmation 协议层收不到 Xcp_SendCallBack,发送流程不能正确确认
Send Queue 主函数周期处理,队列不 overrun 总线忙或离线期间帧积压、后续新增帧无法保存
主函数周期 常规 5/10 ms;CanIf 无发送队列时推荐 1 ms XCP Slave 重新参与仲裁过慢,响应和 DAQ 延迟增大
报文长度 全局 MaxCto/Dto 与通道 PDU 上限一致 64 Byte 全局配置被经典 CAN 通道限制为 8 Byte
组件状态 XCP_ACTIVATE/DEACTIVATE 与 PDU ONLINE/OFFLINE 分别维护 误把总线离线当成组件停用,或量产 ECU 意外保留 XCP 功能
并发 CANXCP_EXCLUSIVE_AREA_0 使用可嵌套中断锁 事件、命令、发送确认和主函数之间出现共享状态竞争

排查“XCP 无响应”时,可以按固定方向缩小范围:先确认组件未被 XCP_DEACTIVATE(),再确认 PDU 已在线,然后检查 Rx PDU 是否进入 Xcp_CanIfRxIndication、协议层是否调用 CanXcp_Send、帧是否进入 Send Queue、主函数是否周期执行,最后确认 Xcp_CanIfTxConfirmation 是否返回。这个顺序与实际数据路径一致,能区分协议问题、网络状态问题和调度问题。

11. 小结

CanXcp 的关键不在 XCP 命令解析,而在传输状态的闭环:CanIf 接收回调把 Packet 送到协议层,CanXcp_Send 把 CTO/DTO 送回 CAN,发送确认再通过 Xcp_SendCallBack 返回协议层。PDU 离线或 CanIf 暂时无法发送时,Send Queue 与 CanXcp_MainFunction 共同维持重试路径。

集成风险主要集中在三处:初始化后没有切换到 CANXCP_SET_ONLINE,把组件启停与 PDU Mode 混用,以及主函数周期和独占区没有覆盖实际并发场景。再加上 MaxCto/Dto 的通道限制和三项协议能力边界,CanXcp 的运行行为就能在 CAN、CAN FD、单通道和多通道项目中被明确约束。


作者:不脱发的程序猿。本文同步自作者 CSDN 博客。

原文:https://handsome-man.blog.csdn.net/article/details/162874569

创作许可协议

本项目采用 CC BY(署名) 进行许可。

评论(0)
- 没有更多了 -