前面已经对XCP协议做了非常细致的介绍,接下来就来看看XCP是怎样在CAN总线上进行工作的吧。参考资料:XCP协议规范2003。
XCP在CAN上的实现也是非常的简单,首先得分配两个CAN ID,对于Master这一方来说,一个作为发,即CMD和STIM,一个作为收,即RES/ERR/EV/SERV和DAQ。这里需要注意的是STIM和DAQ可以有自己独立的CAN ID,但是需要使用SET_DAQ_ID命令CMD进行配置。
之前文章里已经提到过,在CAN上的XCP是不支持交互通信模式的,一般都是采用标准通信模式和块传输模式两者配合。
XCP在CAN上的协议包的体现为:
首先XCP Header为空,至于XCP Packet则与XCO协议一模一样。而XCP Tail则根据经典CAN的MAX_DLC(经典CAN的MAX_DLC固定为8)和XCP Packet长度LEN有以下两种情况:
对于CAN-FD,MAX_DLC只有以下值有效:8、12、16、20、24、32、48和64。这个时候有的朋友就要问了,那如果LEN > MAX_DLC的时候怎么办,不可能,这种事情在XCP on CAN上是不可能发生的,你放心吧。
接下来来看看XCP的一些常用操作在CAN上的体现。当我将CANape配置完之后,点击Start,Master和Slave会进行怎样的交互呢?
具体流程如下:
首先使用CONNECT命令与Slave建立XCP连接。CONNECT的正响应具体描述如下:
根据上表就可以解析出Flash programming available,stimulation available,DAQ lists available, calibration/paging available,Intel format,AG为BYTE,不支持Slave Block Mode,支持命令GET_COMM_MODE_INFO命令获取通信配置,MAX_CTO = 8,MAX_DTO = 8, 还有协议层和传输层的版本号。
其中Slave Block Mode意思就是说,Slave可以发起块传输,就是连续发送好几个XCP包。而Master Block Mode就是Master可以发起块传输。
再使用GET_COMM_MODE_INFO和GET_STATUS获取Slave的XCP协议信息以及当前XCP运行状态信息。
GET_COMM_MODE_INFO的正响应具体描述如下:
这里就不一一对着解析,稍微说一下一些参数的含义吧:
1.MAX_BS 表示在PGM命令中所运行下载的最大Block大小。
2.MIN_ST表示在块传输过程中,两个XCP包允许相隔的最小时间。
3.QUEUE_SIZE表示在支持交互模式下,Master连续发送CMD的最大数量。
GET_STATUS的正响应具体描述如下:
1.Current session status中表示了一些行为状态,有STORE_CAL_REQ,STORE_DAQ_REQ ,CLEAR_DAQ_REQ,DAQ_RUNNING,RESUME。
2.Current Resource Protection Status中则表示了当前有哪些CMD是被SEED&KEY锁着的。在XCP中,有一种保护机制叫做SEED&KEY保护机制,它会按照功能具体分成了CAL/PAG,DAQ,STIM,PGM四类,如下:
每一类都有一套单独的SEED&KEY机制(算法也可以不同),需要单独解锁,只有使用GET_SEED和UNLOCK进行解锁后,然后才能发送其相对应的CMD。
再使用GET_SEED和UNLOCK命令对所有的CMD进行解锁,GET_SEED命令具体描述如下:
当Mode=0时,第二个字节表示Resource,也就是说这次解锁的对象是哪一类CMD,具体请参考Current Resource Protection Status的描述。
再使用GET_DAQ_PROCESSOR_INFO, GET_DAQ_RESOLUTION_INFO和GET_CAL_PAGE命令获取Slave的DAQ信息,为后面配置DAQ做准备。
GET_DAQ_PROCESSOR_INFO正响应具体描述如下:
GET_DAQ_RESOLUTION_INFO正响应具体描述如下:
这个命令可以获取当前Slave支持的ODT_Entry的数量和大小,以及Timestamp的大小和分辨率,在这里就不多做解释了,感兴趣的朋友请参考协议规范。
GET_CAL_PAGE正响应具体描述如下:
Logical data page number表示当前(XCP或者ECU,由该CMD中的Mode字节区分)激活的PAGE编号。
再使用SET_MTA设置MTA(Memory Transfer Address)和Address extension,随后使用BUILD_CHECKSUM获取MTA处,大小为6610的Block的Check Sum。
接下来就可以设置DAQ了,设置DAQ的过程比较复杂,总的来说,其实就是设置ODT_Entry,设置ODT,再设置DAQ-List,随后再将DAQ与Event Channel绑定,随后再开启DAQ。具体流程如下:
由于在前面配置DAQ中,将DAQ_List与Event Channel 2绑定,而在Slave中,Event Channel 2是一个100ms的周期性事件,所以可以看到DAQ报文每100ms发送一次。
首先DTO包的格式如下:
多帧DTO构成的DAQ格式如下:
根据在上面DAQ配置步骤中,使用了SET_DAQ_LIST_MODE将Identification Field的格式配置为relative ODT number and absolute DAQ list number (BYTE),所以Identification Field的格式为PID为一个字节表示ODT Number,DAQ一个字节表示DAQ-List Number:
根据在上面DAQ配置步骤中,使用SET_DAQ_LIST_MODE命令开启了Timestamp,以及在前面的GET_DAQ_RESOLUTION_INFO得知Timestamp的大小是4字节,编码为Intel模式,所以
拿出一帧数据如下:
红色框:表示ODT Number。
蓝色框:表示DAQ-List Number。
黑色框:分别代表数据部分,分别对应前面配置的2,6,4个字节大小的3个ODT_Entry。
在之前文章提到过,除了可以使用DAQ进行数据测量,还可以使用Master周期发送CMD去主动读取,这里一般采用的是SHORT_UPLOAD命令去读取。
找不到合理素材,先欠着,嘿嘿嘿~来年再见!!!
到这里,XCP就差不多都介绍完了,下期再见。