XCP学习
-
XCP介绍
XCP是一种通用的测量和标定协议,C代表Calibration,P代表Protocol,X代表总线类型,可以是CAN、ETHERNET、USB等等,最常用的就是XCP on CAN。通过XCP可以在系统运行时进行参数修改和信号测量,从而最优化ECU的参数配置,避免了以前传统的“修改代码-编译-烧写-测试”方式,提高效率的同时也减少了出错几率。
XCP是一种主从式通信,上位机工具作为Master,目标ECU则是Slave,所有功能都是通过主从之间的通信交互实现。
从上图能够看到,主从之间的交互信息可以分为两类,一类是命令报文CTO(Command Transfer Objects),由Master发送命令(CMD),Slave进行应答(RES/ERR/EV/SERV);一类是数据报文DTO(Data Transfer Objects),包括数据采集(DAQ)及激励(STIM)。
-
XCP报文定义
XCP报文由三部分组成:Header、Packet和Tail,其中Header及Tail由使用的传输层协议决定,比如对于CAN总线来讲,Header为空,Tail则为填充部分。XCP Packet分为标识域(Identification Field)、时间戳域(Timestamp Field)和数据域(Data Field),见下图所示:
标识域(Identification Field)
标识域由PID、FILL和DAQ组成,PID(Packet Identifier)顾名思义标识了整个Packet的作用,对CTO来讲就是命令码/应答码,CMD报文取值0xC0~0xFF(例如PID=0xFF时表示CONNECT命令),SERV、EV、ERR和RES取值0xFC~0xFF,对DTO来讲就是ODT编号,DAQ报文取值0x00~0xFB,STIM报文取值0x00~0xBF;FILL和DAQ只在DTO下才有,FILL用于特定情况下的字节对齐填充,DAQ则表示列表编号;关于ODT和DAQ后面还会提到。
时间戳域(Timestamp Field)
CTO没有时间戳,DTO有但也是可选的,时间戳只在每次DAQ读取的首个ODT中存在。
数据域(Data Field)
在CTO中存放命令参数或者应答信息,在DTO中存放数据信息。
-
CTO
XCP的命令分为两类,一类是协议固定要求的,必须实现/支持,一类则是可选的,可以不用实现/支持,比如下表是XCP部分的命令说明:
Command
PID
Optional
CONNECT
0xFF
No
DISCONNECT
0xFE
No
GET_STATUS
0xFD
No
SYNCH
0xFC
No
GET_COMM_MODE_INFO
0xFB
Yes
GET_ID
0xFA
Yes
SET_REQUEST
0xF9
Yes
GET_SEED
0xF8
Yes
UNLOCK
0xF7
Yes
SET_MTA
0xF6
Yes
UPLOAD
0xF5
Yes
SHORT_UPLOAD
0xF4
Yes
BUILD_CHECKSUM
0xF3
Yes
TRANSPORT_LAYER_CMD
0xF2
Yes
USER_CMD
0xF1
Yes
像CONNECT、DISCONNECT、GET_STATUS、SYNCH都是必须要支持的,其它诸如GET_ID、SET_REQUEST、GET_SEED则是可选的,限于篇幅,本文不会讨论所有的命令及其参数细节,相关信息可以参考XCP的传输层协议规范。
XCP支持主从之间三种不同的命令/应答交互方式:标准通信、块传输和交叉通信。
标准通信(Standard)
标准通信即是经典的一问一答方式,Master发送请求,Slave发送应答,并且在Slave响应前一个请求前,Master不能发送下一个请求。
块传输(Block)
块传输类似多问一答或者一问多答,指在有大量数据交互的情况下(如上载、下载及flash编程)能够缩短传输时间,提高效率。
交叉通信(Interleaved)
交叉通信类似多问多答,Master发送请求时不需要等到前一个请求被Slave应答。
-
DTO
ODT&DAQ
通常目标观测量都是内存中的变量Element,每个Element都有自己的地址和长度,根据这些地址和长度信息可以将多个Element拼在一起成为ODT(Object Description Table)条目,相应的这些Element就称为ODT_ENTRY,然后将多个ODT条目排列在一起成为DAQ(Data AcQuisition),多个DAQ组成DAQ list,最终,ODT_ENTRY、ODT和DAQ构成了一个三维空间(见下图),当然这空间并不是无限延申的,各个维度都有自身限制。
DAQ既可以静态配置也可以动态配置,动态配置需要使用FREE_DAQ、ALLOC_DAQ、ALLOC_ODT和ALLOC_ODT_ENTRY四个命令。
动态分配遵循从大到小的原则,首先释放DAQ,接着分配DAQ,然后分配DAQ下的ODT,再来是ODT下的ODT_ENTRY,分配完了之后,ODT_ENTRY内容还是空的,还需要将其和内存中的Element进行赋值绑定。
测量模式
上面说的DAQ有什么用呢,在说明之前,先来看下如果想通过XCP观测一个变量,最简单的方式大概就像下图所示采用查询方法了:
这里为了获取观测量的最新状态,Master需要周期不断的发送请求命令,Slave则通过响应命令将值发回给Master,采用这种方式首先效率不高,如果同时观测多个不同量的话数据一致性也无法保证,timestamp机制也没法使用。
如果使用DAQ的话,在启动测量后Slave根据内部DAQ的trigger event发送观测量,不再需要Master去主动请求,并且可以实现不同级别的数据一致性,比如实现ODT级别的数据一致性,一个ODT内的所有ODT_ENTRY会在同一时间进行采样:
也可以实现DAQ级别的数据一致性,DAQ内的所有ODT会在同一时间进行采样:
XCP还提供了一种低性能的测量方式,该模式只会用来观测ECU内部那些对资源消耗不大的数据:
事件通道(EVENT CHANNELS)
每个事件通道对应一个周期时间,决定了该通道下数据传输的频率,一个通道下可以有多个DAQ:
-
在线标定
标定量一般都是放在Flash内的,而Flash中的数据在运行时是无法修改的,那要如何去进行在线动态标定呢,实际上XCP会将Flash中的标定数据映射到RAM中,在程序运行时使用的是RAM中的数据,这样在线标定改的是RAM里的内容,从而可以动态体现变量修改前后的行为变化。
XCP甚至可以将一份标定数据映射为多份,每份可以进行不同的参数配置,从而方便在不同标定配置间灵活切换。
-
-
-
-