AUTOSAR CanXcp传输链路详解:PDU离线队列与在线状态切换

2026-10-18 10:09:14 23阅读

ECU 完成 XCP 初始化后,测量标定工具仍可能收不到任何响应。一个常见原因不是 CAN 通道或 A2L 文件错误,而是 CanXcp 初始化后处于CANXCP_SET_OFFLINE:协议层可以产生响应,传输层却不会把帧发到总线。如果项目没有 CanSM,或者使用的状态管理器不会切换 CanXcp 的 PDU 模式,就必须由应用显式调用CanXcp_SetPduMode()进入在线状态。这个启动细节揭示了 CanXcp 的核心职责。XCP Protocol Layer 负责命令和会话语义,CanXcp 作为 XCP on CAN Transport Layer,负责在协议层与 AUTOSARCanIf之间搬运 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_Command和Xcp_SendCallBack
CanXcpXCP on CAN 报文收发、PDU 模式、发送队列、确认转发对上连接协议层,对下连接CanIf
CanIfCAN L-PDU 收发与确认调用Xcp_CanIfRxIndication、Xcp_CanIfTxConfirmation

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

总线类型XCP Packet 长度CanXcp 发送接口的len范围
Classical CAN最多 8 Byte1..8
CAN FD Mode 2最多 64 Byte1..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把确认传回协议层。SERV、EV和DAQ等异步 XCP Packet 也沿用这条发送与确认链路。

这条链路中,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。

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

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

场景建议周期原因
CanIf具备正常发送排队能力多数情况下5 ms或10 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,直到在线或 overrunCAN 总线尚未可通信、网络切换
CanXcp_SetPduMode(..., CANXCP_SET_ONLINE)总线发送能力允许排队帧继续发送CanSM 通知总线上线
XCP_DEACTIVATE()协议层和传输层全部功能组件功能被锁定量产 ECU 默认关闭 XCP,由诊断条件解锁
XCP_ACTIVATE()协议层和传输层全部功能恢复组件功能满足授权或诊断条件后启用 XCP

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

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 = 64、MaxDto = 64Classical CAN:8 Byte自动限制为 8 Byte
MaxCto = 64、MaxDto = 64CAN FD Mode 2:64 Byte最大可使用 64 Byte

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

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

6.1 协议层调用的 CanXcp 服务

API参数功能返回值上下文与可重入性
CanXcp_SendXcp_Channel:逻辑通道;len:Packet 长度;msg:数据指针请求发送 DTO 或 CTO无不可重入;可从XcpEvent、XcpBackground和 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_CanIfRxIndicationCanCanXcpRxPduId:接收目标 PDU ID;PduInfoPtr:数据指针和长度通知收到 CTO/DTO Packet,并交给协议层无CAN Interface 上下文;不可重入
Xcp_CanIfTxConfirmationCanTxPduId:成功发送的 PDU ID确认 CTO/DTO 已成功发送,并通知协议层无CAN Interface 上下文;不可重入

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

6.3 其他层调用的服务与宏

API/宏参数功能Service ID约束
CanXcp_InitConfigPtr:Post-Build 配置指针初始化 XCP on CAN Transport Layer未给出系统初始化期间调用;不可重入;仅 Post-Build 配置评估该指针
CanXcp_GetVersionInfoVersioninfo:版本信息输出地址返回组件版本、Vendor ID 和 AUTOSAR Module ID,版本采用 BCD 编码未给出未列出额外限制
CanXcp_SetPduModeXcpNwH:通常为 0;PduMode:ONLINE/OFFLINE控制 XCP 帧发送,离线时使用 Send Queue7Task 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_Event、Xcp_SendCallBack、Xcp_MainFunction和Xcp_Command可能相互打断。

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

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

8.1 实现和生成文件

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

未使用 GENy 配置 AUTOSAR CAN Interface 时,与项目适配直接相关的是CanXcp_Cfg.h、CanXcp_Lcfg.c和CanXcp_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、发布版本0x00。CanXcp_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_ID、SET_DAQ_ID不能为各 DAQ List 动态分配独立 CAN ID
网络内 Slave 自动发现不支持GET_SLAVE_IDMaster 不能依靠该命令枚举网络中的全部 XCP Slave
Multiple Identity只在单 CAN 通道配置下可用多通道项目不能同时使用该 Multiple Identity 能力

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

10. 集成与调试落点

观察点正常条件异常表现
初始化后的 PDU ModeCanSM 或应用切换到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 msXCP 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、单通道和多通道项目中被明确约束。


作者:不脱发的程序猿
链接:https://www.aiddithome.com/p/fdeb6a4b44c0e.html
本作遵循 [CC BY 4.0 署名] 许可,版权归作者所有。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
3条评论
深圳打工人Alan
1楼 · 2026-10-18 10:11:43

AUTOSAR里离线队列这块最容易绕晕,能拆成链路讲清楚的很实用。

板砖搬不动
2楼 · 2026-10-18 10:11:43

XCP走CAN底层那一层的各种状态和队列机制,记下来方便查。

阿强焊点总飞
3楼 · 2026-10-18 10:11:43

做标定遇到PDU收不下包,多半就是离线缓冲和状态切换没弄对,这篇讲到位了。