1 简介与概述
不同诊断通信协议的开发,调整,实施和维护会给车辆制造商,系统供应商和ECU供应商带来不必要的成本。为了解决此问题,将不同的技术协议和数据通信原理编译为一个国际ISO标准,通常称为统一诊断服务(ISO 14229-1)。
UDS ISO 14229-1:2013(UDS)和ISO 15765-3:2004(基于在CAN上的诊断)是互补标准,共同指定“ 基于CAN上的UDS”应用层协议。
对于基于CAN总线的乘用车,将参考ISO 15765-2和ISO 11898。对于基于CAN总线的卡车(总质量大于3500 kg的道路车辆)将参考ISO 11992-4和ISO 11992-J。它们指定了道路车辆及其牵引车辆之间的诊断数据通信。下图总结了相关的ISO标准以及相应OSI层
UDS服务的协议数据单元(PDU)包含地址信息和诊断消息(数据字段)。数据字段由服务标识符组成(SID)和可选的数据参数组成。数据字段由一字节长的服务标识符来控制服务的功能(这一个字节也可理解成为是Appliction layer的协议控制信息)。
应用协议层的下方是传输层/网络层,其PDU包含控制信息PCI,数据信息Data.即N_PDU =N_PCI+N_DATA。
如下表所示,N_PCI的值主要集中在前三个字节,N_DATA值主要集中在后面7位字节。其中,SF_DL 代表单帧中数据个数,FF_DL代表 连续帧中的数据总数,SN代表此帧为连续帧中的第几帧, FS参数控制发送端是否能继续传输数据,BS规定发送端允许持续传输连续帧数目的最大值,STmin限定连续帧相互之间所允许的最小值。
2 UDS诊断服务介绍
诊断服务根据功能处理目的被分类为各个不同的功能单元,下图总结了各种不同功能单元,UDS服务和及其服务ID。ISO 14229-1指定的25种统一诊断服务分为六个功能单元。
a. SID是服务标识符的缩写。
b. Def是默认会话层的缩写。ECU上电后会重置为默认会话层。
c. RoE是事件响应的简称。在此列中的“ x”表示该服务可作为事件响应机制的事件服务。
d. Sub-Fct是子功能的缩写。此服务支持子功能,因此支持肯定的响应抑制功能。
e. 这些服务如果在默认会话中可能需要安全访问服务才能请求。
f. 在默认会话中无法访问(某些数据标识符DID)。需要发出单独的$ 27(SecurityAccess)来解锁以访问这些数据。
2.1 根据服务的功能单元和请求服务标识符对服务进行分类
2.1.1 诊断和通信管理功能单元
$10 DiagnosticSessionControl 该服务请求ECU从活动会话过渡到其他会话。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | DiagnosticSessionControl Request Service Id | M | 10 |
2 | sub-function = [diagnosticSessionType ] | M | 01,02,03 |
$11 ECU重置
该服务请求ECU执行复位。ECUReset请求参数的示例包括hardReset,keyOffOnReset和softReset。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | ECUReset Request Service Id | M | 11 |
2 | sub-function = [resetType ] | M | 01,02,03 |
$27 SecurityAccess
此服务用于在活动诊断会话中达到更高的安全级别。可能需要SecurityAccess请求来解锁并访问受保护的功能及数据(例如通过DID读取ECU ID信息)。也可以用于从一个会话通过解锁以成功切换到其他会话。
Data byte数据字节 | Parameter name参数名称 | Cvt约定 | Hex value十六进制数值 |
---|---|---|---|
1 | SecurityAccess Request Service Id | M | 27 |
2 | sub-function = [securityAccessType = requestSeed ] | M | 01,05,09 |
Data byte数据字节 | Parameter name参数名称 | Cvt约定 | Hex value十六进制数值 | |
---|---|---|---|---|
1 | SecurityAccess Request Service Id | M | 27 | |
2 | sub-function = [ | securityAccessType = requestSeed ] | M | 02,06,0A |
securityKey = [ | ||||
3 | key#1 (byte 1) | M | 00-FF | |
4 | key#2 (byte 2) | M | 00-FF | |
5 | key#3 (byte 3) | M | 00-FF | |
6 | key#4 (byte 4) ] | M | 00-FF |
$28 CommunicationControl
该服务请求ECU控制其通信行为。一个典型的示例包括要求CAN总线中的ECU关闭车载通信,以提高诊断通信的效率。
Data byte数据字节 | Parameter name参数名称 | Cvt约定 | Hex value十六进制数值 |
---|---|---|---|
1 | CommunicationControl Request Service Id | M | 28 |
2 | sub-function = [controlType ] | M | 00, 01, 02, 03 |
3 | communicationType | M | 01, 02, 03 |
$3E TesterPresent
TesterPresent请求通常定期发送,并包含一个功能地址。它指示测试仪仍处于连接状态(存在),并请求ECU保持当前诊断状态(例如,除默认会话之外的其他会话处于活动状态,RoE机制仍处于活动状态)。对这个服务的正响应抑制可以减少总线负载。
$83 AccessTimingParameter
该请求用于读取和/或修改通信定时参数。
$84 SecuredDataTransmission
此请求用于传输受加密方法保护的诊断数据。为此,必须实现位于应用程序层与测试仪和ECU的应用程序之间的“安全子层”。数据根据ISO 15764(扩展数据链接安全性)进行处理。
$85 ControlDTC设置
该服务要求ECU停止/恢复DTC的设置。将此服务与车载通信切换 (服务$28通讯控制)相结合,可增加用于Flash编程的速度。
Data byte 数据字节 | Parameter name参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | ControlDTCSetting Request Service Id | M | 85 |
2 | sub-function = [DTCSettingType ] | M | 01,02 |
$86 ResponseOnEvent
事件响应(RoE)服务请求ECU自动传输指定事件的响应。
$87 LinkControl
该服务请求控制通信数据速率。对于CAN,它会影响ISO 11898中规定的数据链路层,从而影响用于板载通信以及诊断通信的数据速率。转换数据速率的请求分为(1)验证网络上的ECU是否允许特定的数据速率;(2)在验证结果为肯定的情况下请求转换;以及(3)执行转换。
2.2.2 数据传输功能单元
$22 ReadDataByldentifier
该服务请求读取由DID参数标识的数据记录值。DID用于标识特定的本地数据记录。数据标识符$F224可以包含诸如电池电压,歧管绝对压力,空气质量流量,车辆大气压以及计算出的负载值之类的数据。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | ReadDataByIdentifier Request Service Id | M | 22 |
23 | dataIdentifier[ ] = [byte #1byte #2 ] | M M | 00-FF00-FF |
$23 ReadMemory ByAddress
该服务请求读取指定内存范围的当前值。请求参数是内存地址和内存大小。用于请求参数的字节数在addressAndLengthFormatldentifier中指定。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | ReadMemoryByAddress Request Service Id | M | 23 |
2 | addressAndLengthFormatIdentifier | 24 | |
3: 6 | memoryAddress[ ] = [byte #1:byte #4 ] | M:M | 00-FF: 00-FF |
78 | memorySize[ ] = [byte #1byte #2 ] | M M | 00-FF00-FF |
$24 ReadScalingDataByidentifier
该服务请求ECU将缩放信息值传输到测试仪。测试人员使用定标信息值来转换数据。这项服务的实施增加了ECU软件的实用性。作为替代,测试器可以将缩放比例信息存储在数据库中。
$2A ReadDataUyPeriodicidentifier
该服务请求定期发送数据记录值。所请求的数据的传输速率由传输模式参数设置,例如“中等速率发送”,例如300 ms。
$2C DynamicallyDefineDataldentifier
该服务允许测试人员在ECU中动态定义新的数据标识符,其中包含对静态定义的标识符和/或内存地址的引用。测试人员随后可以通过服务请求()或2A(readDataByPeriodicIdentifier)读取此动态定义的数据记录。动态定义的标识符的一个优点是, 一次服务可以请求传输很多的的数据记录
$2E WriteDataByldentifier
通过此服务,可以将由标识符(DID)指定的数据记录写入ECU存储器。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | WriteDataByIdentifier Request Service Id | M | 2E |
23 | dataIdentifier[ ] = [byte #1byte #2 ] | M M | 00-FF00-FF |
4:(k-1)+4 | dataRecord[ ] = [data #1:data #k ] | M: U | 00-FF: 00-FF |
$3D WriteMemoryByAddress
该服务允许将数据记录直接写入ECU的内存。请求参数是内存地址和内存大小以及数据记录。用于参数内存地址和内存大小的字节数在addressAndLengthFormatidentifier中指定。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | WriteMemoryByAddress Request Service Id | M | 3D |
2 | addressAndLengthFormatIdentifier | M | 24 |
3: 6 | memoryAddress[ ] = [byte #1:byte #4 ] | M | 00-FF: 00-FF |
78 | memorySize[ ] = [byte #1byte #2 ] | M U | 00-FF00-FF |
9:(k-1)+9 | dataRecord[ ] = [data #1:data #k ] | M: U | 00-FF: 00-FF |
a 参数地址和长度格式标识符采用固定值0x24。 |
2.2.3 存储数据传输功能单元
$14清除诊断信息
此服务允许在一个或多个ECU中清除错误存储器的内容。因此,可以使用物理地址或功能地址来请求服务。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | ClearDiagnosticInformation Request Service Id | M | 14 |
234 | groupOfDTC = [groupOfDTCHighByte groupOfDTCMiddleByte groupOfDTCLowByte ] | M M M | 00-FF00-FF00-FF |
$19 ReadDTC信息
诊断故障代码(DTC)用于编码和识别检测到的与排放有关和与排放无关的故障。DTC通常为三个字节,这意味着最多可以定义16,777,216个不同的DTC。该服务从一个或多个ECU请求DTC信息的状态。因此,该服务可以用物理地址或功能地址查询。测试人员可以请求与DTC关联的已存储数据记录,也称为“ DTC快照”。DTC快照包含故障发生时的特定数据值。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | ReadDTCInformation Request Service Id | M | 19 |
2 | sub-function = [reportNumberOfDTCByStatusMask reportDTCByStatusMask ] | M | 0102 |
3 | DTCStatusMask a | M | 00-FF |
a 诊断故障代码状态掩码的定义等同于诊断故障代码状态字节的定义 |
Data byte数据字节 | Parameter name参数名称 | Cvt约定 | Hex value十六进制数值 |
---|---|---|---|
1 | ReadDTCInformation Request Service Id | M | 19 |
2 | sub-function = [reportDTCSnapshotRecordByDTCNumber ] | M | 04 |
3,4,5 | DTCMaskRecord[ ] = [DTCHighByte DTCLowByte DTCFailureTypeByte ] | M M M | 00-FF00-FF00-FF |
6 | DTCSnapshotRecordNumber | M | 00,01,02,FF |
Data byte数据字节 | Parameter name参数名称 | Cvt约定 | Hex value十六进制数值 |
---|---|---|---|
1 | ReadDTCInformation Request Service Id | M | 19 |
2 | sub-function = [reportDTCExtendedDataRecordByDTCNumber ] | M | 06 |
345 | DTCMaskRecord[ ] = [DTCHighByte DTCLowByte DTCFailureTypeByte ] | M M M | 00-FF00-FF00-FF |
6 | DTCExtendedDataRecordNumber | M | 01 |
Data byte数据字节 | Parameter name参数名称 | Cvt约定 | Hex value十六进制数值 |
---|---|---|---|
1 | ReadDTCInformation Request Service Id | M | 19 |
2 | sub-function = [reportSupportedDTC ] | M | 0A |
2.2.4 输入输出控制功能单元
$2F InputOutputControlByIdentifier
该服务主要用于代替输入信号的值和/或控制ECU的输出。通常,此服务会绕过ECU的应用程序软件并直接触发输出电路,然后直接读取连接到输入电路的传感器。
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | InputOutputControlByIdentifier Request Service Id | M | 2F |
2 . 3 | dataIdentifier[ ] = [byte#1 (MSB) byte#2 (LSB) ] | M | 00-FF .00-FF |
4 | inputOutputControlParameter = [returnControlToECU freezeCurrentState ] | 00 02 | |
5 .6 | controlEnableMaskRecord[ ] = [controlMask#1 controlMask#2 ] | M/ M | 00-FF .00-FF |
Data byte 数据字节 | Parameter name 参数名称 | Cvt 约定 | Hex value 十六进制数值 |
---|---|---|---|
1 | InputOutputControlByIdentifier Request Service Id | M | 2F |
2. 3 | dataIdentifier[ ] = [byte#1 (MSB) byte#2 (LSB) ] | M | 00-FF. 00-FF |
4 | inputOutputControlParameter = [shortTermAdjustment ] | M | 03 |
5. 6 | controlState[ ] = [controlState#1 controlState#2 ] | M | 00-FF. 00-FF |
7. 8 | controlEnableMaskRecord[ ] = [controlMask#1 controlMask#2 ] | M | 00-FF. 00-FF |
- 例程服务单元
$31例程控制
该服务用于维护和停止ECU内部例程。可以读取例程的结果以进行分析。该例程由两个字节的例程identifier标识。
1 | RoutineControl Request Service Id | M | 31 |
---|---|---|---|
2 | sub-function = [routineControlType ] | M | 01, 02 ,03 |
34 | routineIdentifier[ ] = [byte#1 (MSB) byte#2 (LSB) ] | M M | 00-FF00-FF |
5:(m-1)+5 | routineControlOptionRecord[ ] = [routineControlOption#1:routineControlOption#m ] | U: U | 00-FF: 00-FF |
2.2.5上传下载功能单元
$34请求下载
此服务启动从测试仪到ECU的数据传输。当ECU准备从测试仪接收数据时,它会发送肯定响应,其中包含用于后续数据传输的可用块大小(每个传输数据请求的数据字节数)
1 | RequestDownload Request Service Id | M | 34 | |
---|---|---|---|---|
2 | dataFormatIdentifier | M | 00 | |
3 | addressAndLengthFormatIdentifier | M | 44 | |
4 | memoryAddress[ ] = [ | byte #1:byte #4 ] | M | 00- FF |
︰ | ︰ | |||
7 | 00-FF | |||
8 | memorySize[ ] = [ | byte #1:byte #4 ] | M | 00-FF |
︰ | ︰ | |||
11 | 00-FF |
$35请求上传
此服务启动从ECU到测试仪的数据传输。当ECU准备好将数据发送到测试仪时,它会发送一个肯定的响应,其中包含用于后续数据传输的块大小(每个传输数据请求的数据字节数)
$36 TransferData
此服务用于在测试仪和ECU之间(下载)或在ECU和测试仪之间(向上)传输数据。如果需要一个以上的transferData请求来传输数据,则使用blockSequenceCounter对传输次数进行计数。计数器允许在传输损坏后重复传输块。因此,在出现通信问题时,不必再次传输完整的数据
1 | TransferData Request Service Id | M | 36 |
---|---|---|---|
2 | blockSequenceCounter | M | 00-FF |
3︰ 3+(m-1) | transferRequestParameterRecord[] = [transferRequestParameter#1:transferRequestParameter#m ] | C︰C | 00-FF︰00-FF |
$37 RequestTransferExit
该服务用于终止transferData服务。完整的数据传输从requestDownloadrequestUpload服务开始,再由几个transferData服务继续,并由requestTransferExit服务完成。
数据字节 | 参数名称 | 约定 | 十六进制值 |
---|---|---|---|
1 | RequestTransferExit Request Service Id | M | 37 |
2 | CRCType | M | 00,01 |
3 基于CAPL的诊断服务举例
3.1 CAPL介绍
“ CAPL”是通信访问编程语言的缩写。其目标是尽可能简单地解决特定任务。典型的任务是对接收到的消息做出反应,检查和设置信号值并发送消息。
CAPL程序是事件驱动的。这意味着它们由各自的功能组成,每个功能都对被分析系统中的事件做出反应:接收消息,信号的改变,定时器到期,甚至环境变量的变化。
例如,要对接收到的消息“ EngineState”作出反应,可以使用:
On message EngineState
{
//USER DEFINED FUNCTION
}
消息名称为“ EngineState”和该消息中的信号的名称为“ EngineSpeed” 。
// Used for display purposes.
on message EngineState
{
@sysvar::Display::SetRPM = this.EngineSpeed / 1000.0;
}
和C语言一样,可通过include和varibles去包含头文件和定义变量。但CAPL程序不向用户提供要使用的任何指针类型,而是通过this实现特定对象的绑定。
includes
{
//include head file
}
variables
{
message 0x100 DiagnosisID={dlc=8};
const byte PostiveResponse_0xF192[9] = {0x62,0xF1,0x92,0x33,0x31,0x32,0x34,0x41,0x42};
const byte P2_Timer = 200;
msTimer tFlashLightFrequency;
}
3.2 诊断服务实例分析
下面的例子使用多个不同服务来执行复杂的诊断过程,以完成在ECU的内存中编写一个新的变体信息和写入日期的目的。
- 步骤1:开启ECU
ECU上电后,诊断软件堆栈初始化,等到ECU中的诊断服务器初始化完成后,ECU处于默认会话中。测试仪在此之前应禁止其传输服务,否则服务会丢失。
但是诊断仪可以做一些内部的初始化工作。如启动CANOE后调用以下函数:
on start
{
// set DbgLevel = 1 to get more information in Write-Window
setWriteDbgLevel(0);
setTimer(Tick_timer, 1);
}
-步骤2:读取ECU识别码
必须读取ECU硬件的标识符,检查变体之后决定是否更新变体编码。服务 22(readDataByldentifier)【字节1】与数据标识符 Fl 92(systemSupplierECUHardwareNumberDataldentifier)【字节2和3】一起发送。
void ReadDID_0xF192 (void)
{ //Read ECU identification :公众号——糖果Autosar
write("Read ECU identification ");
DiagnosisID.byte(0)=0x03;
DiagnosisID.byte(1)=0x22;
DiagnosisID.byte(2)=0xFD;
DiagnosisID.byte(3)=0x92;
DiagnosisID.byte(4)=0x00;
DiagnosisID.byte(5)=0x00;
DiagnosisID.byte(6)=0x00;
DiagnosisID.byte(7)=0x00;
output(DiagnosisID);
}
on timer Tick_timer
{ //Check response
if(WaitResponseCnt < P2_Timer)
{
WaitResponseCnt ++;
}
else
{
write(" Response not received ,P2 Timeout");
}
}
肯定响应:服务标识符($ 62),字节2($ F1)和字节3($ 92)数据标识符。字节4至9,$ [33,31,32,34,41,42]包含六个ASCII字符“ 3124AB”,用于识别ECU软件。测试人员将此字符串与内部存储的参考值进行比较。
肯定的响应意味着ECU硬件与随后诊断操作兼容,这对于编写变体代码是必需的。
-步骤3:切换到Programmmg会话层
ECU收到从默认会话层切换到编程会话层的请求,子功能字节的数据参数指定了DiagnosticSessionType。ECU使用子功能字节$02指定编程会话层的类型。
ECU发送肯定响应服务标识符 50 以响应请求 50以响应请求 50以响应请求 10。$ 02反映了请求的会话类型,并表明ECU将执行转换到编程会话层。
-步骤4:安全访问
为了提高安全性,测试人员必须向ECU请求种子。为此,测试仪发送一个$ 27(securityAccess)以及子功能参数$ 01(requestSeed)。
ECU传输肯定响应服务标识符($ 67)和子功能字节($ 01)。 接下来的四个字节$[12,34,56,78)包含种子。
void SecurityAccess_0x2701 (void)
{
//Request ECU seed :糖果Autosar write(" Request ECU seed");
DiagnosisID.byte(0)=0x02;
DiagnosisID.byte(1)=0x27;
DiagnosisID.byte(2)=0x01;
DiagnosisID.byte(3)=0x00;
DiagnosisID.byte(4)=0x00;
DiagnosisID.byte(5)=0x00;
DiagnosisID.byte(6)=0x00;
DiagnosisID.byte(7)=0x00;
output(DiagnosisID);
}
void SecurityAccess_0x2703 (void)
{
//Request to send ECU key :糖果Autosar write(" Request to send ECU key");
DiagnosisID.byte(0)=0x06;
DiagnosisID.byte(1)=0x27;
DiagnosisID.byte(2)=0x02;
DiagnosisID.byte(3)=0x9A;
DiagnosisID.byte(4)=0xBC;
DiagnosisID.byte(5)=0xDE;
DiagnosisID.byte(6)=0xF0;
DiagnosisID.byte(7)=0x00;
output(DiagnosisID);
}
现在,测试人员必须使用机密算法从种子计算密钥。
然后,测试人员再次发送服务请求$ 27(securityAccess)。字节2现在包含值$02(sendKey),该值指示测试人员将发送密钥。字节3至6 $ [9A,BC,DE,FO]包含计算出的密钥。 ECU将密钥与内部计算的参考值进行比较,如果两个值相同,则接受密钥。如果是这样,则ECU传输带有子功能字节($ 02)的肯定响应($ 67)。
服务$ 27(securityAccess)在默认会话中不可用。
-步骤5:烧写变体编码
测试仪发送了带有数据参数$ 14(addressAndLengthFormatfdentifier)的请求$ 3D(writeMemoryByAddress)。数据参数包含以下信息:四个字节内存地址$ [00,FF,00,00]在字节3到6中发送。请求的内存大小字节7为一个字节,指示内存地址的长度,字节7的值为$ 10,这意味着将写入存储区16个字节。字节8到23包含变体编码$ [01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,FF]。
ECU发送肯定响应服务标识符($ 7D)和请求字节的参数$[14,00,FF,00,00,10]。
-步骤6:编写编程日期
出于归档和追溯的要求,最后一次编程(第5步)的日历日期将存储在ECU的内存中。测试器发送请求$ 2E(writeDataByidenlifier)和数据标识符$ [Fl,99](programmingDate)
字节4至10,$ [32,30,30,32,30,34,32,31]包含编程日期(2002年4月21日),编码为ASCII字符(20020421)。
ECU传输肯定响应服务标识符($ 6E)和对应的数据标识符。
-步骤7:重置ECU
在示例的最后一步,测试人员通过发送请求$ 1 1和子功能字节$ 81来重置ECU。
suppressPosRspMsgIndicationBit的值为1(TRUE),表示ECU将抑制对此服务的肯定响应。即ECU不发送响应并完成复位。
子功能字节的其他七个位指定了ECU进行复位的类型,本例中为hardReset。
重置后,ECU处于默认会话活动状态
4 UDS通信堆栈的状态机
- OSI模型的分层架构 UDS诊断通讯模块采用了类似OSI模型的分层架构。如下图所示。
CAN_DRV为系统的CAN硬件驱动。通过与硬件寄存器的交互,驱动提供了对CAN模块初始化以及收、发CAN Frame的接口函数。 CAN_IF通过对CAN底层驱动提供的接口进行封装,实现了网络层功能模块与硬件底层驱动之间的隔离。因此,当需要将该网络层移植到其他平台时,只需要依据新平台的CAN底层驱动对CAN_IF模块进行更新,而不需要对网络层主体功能模块作出修改,从而大大增强了模块的可移植性和可重用性。 TP_NL模块是网络层的主体功能模块,其功能是将来来自上层(应用层)的A_PDU解包成N_PDU, 并按照ISO-15765-2中描述的Segmented Message发送方式通过DC_CANIF接口与下层(CAN底层驱动)进行数据交换。或者将通过CAN_IF接收到的N_PDU封装成A_PDU,并向上(应用层)传递。TP_NLCFG是对网络层参数进行配置的模块。 TP_ALIF模块是网络层与应用层之间的接口模块。其作用是接收经过网络层打包后的A_PDU,并传递给指定服务功能模块,以及将各功能模块对请求的应答数据重新封装成A_PDU后,传递给网络层进行进一步的发送过程。TP_ALIFCFG模块维护了一张描述各应用层功能模块与A_PDU中SID的对应关系,TP_ALIF模块通过这张表格就能够快速地找到SID与应用层服务程序入口地址的映射关系,并跳转执行。
4.1 TP_ALIF应用层状态机
在程序初始化完成后,应用层接口处于空闲状态(AL_IDLE),并通过一个10ms的任务来查询是否有来自下层的诊断服务请求。当查询到网络层报告的服务请求时,应用层接口即进入AL_BULID_AND_TRANSMIT状态。在这个状态中,应用层接口根据A_PDU中的SID信息,执行特定的诊断服务函数,得到应答的A_PDU,并传递给网络层进行发送,同时应用层接口进入AL_WAIT_CONFIRMATION状态。在AL_WAI_CONFIRMATION状态中,应用层接口等待网络层反馈的发送状态,发送成功后(或超时)后,应用层重新回到AL_IDLE状态,并等待处理下一个服务请求。 若在AL_BULID_AND_TRANSMIT状态中,从某一个诊断服务程序处得到的应答为否定0x78(Response Pending),则状态机在进入AL_WAIT_CONFIRMATION后,自动重新回到AL_BUILD_AND_TRANSMIT状态,并重新进入这个未执行完毕的诊断服务程序中进行处理,如此往复直至服务执行完毕后,状态机进入AL_IDLE状态,并等待处理下一个服务请求。
4.2 TP_NL网络层接收状态机
当诊断仪没有发送任何服务请求时,网络层处于空闲状态(NL_IDLE)。 当接收SF时,网络层进入NL_RECEIVED_SF_FF状态。由于SF中已经包含了请求A_PDU中完整的数据信息,此时,网络层即可向通过与应用层的接口(DC_ALIF)向上层传递A_PDU已收到的消息,并有应用层依据A_PDU中的请求内容执行相应的服务程序。同时,网络层回到NL_IDLE状态,准备处理由上层传来的应答A_PDU。 当网络层在等待服务请求时,接收到的时FF时,网络层同样会进入NL_RECEIVED_SF_FF,依据ISO-15765-2中定义的Segmented Message发送方式,网络层需要发送FC来控制数据流的继续发送。因此,网络层会进入NL_TRANSMIT状态,并发送FC。在发送FC后,网络层进入NL_WAIT_CONFIRMATION状态,并判断FC发送成功后,网路层跳转到NL_RECEIVED_FC_CF状态,并进行后续CF的接收。若有必要,则重复NL_TRANMIT → NL_WAIT_CONFIRMATION → NL_RECEIVED_FC_CF的过程,直至接收完所有的Segmented Message, 并打包成A_PDU后,传递给应用层进行处理。 在UDS的应用层模块执行完服务请求的操作后,会将服务应答填充到A_PDU中,并经由DC_ALIF传递给网络层。网络层在接收到来自上层的发送请求后,便会对A_PDU进行解包成为N_PDU后。如下图所示的状态机,完成N_PDU的发送。
4.3 TP_NL网络层发送状态机
系统的网络层在1ms任务中,对CAN底层驱动的接收情况进行轮询,同时处理网络层的CAN报文发送请求。如下图所示描述了网络层处于接收状态时的基本工作过程状态机。 当A_PDU的数据内容较少时(小于7个字节),A_PDU可以被解包成1个SingleFrame。在经过NL_TRANSMIT状态发送,并在NL_WAIT_CONFIRMATION中确认发送成功后,网络层即可回到NL_IDLE状态,开始等待诊断仪的下一个请求。 若A_PDU的数据内容较多,则N_PDU的发送必须采用Segmented Message的方式。首先,网络层在NL_TRANSMIT状态中发送FF,并在NL_WAIT_CONFIRMATION中确认FF发送成功。然后进入NL_RECEIVED_FC_CF状态中等待诊断仪发送的FC。在接收到有效的FC后,才能重新进入NL_TRANSMIT→ NL_WAIT_CONFIRMATION的循环进行后续CF的发送,直至发送完所有的N_PDU后,网络层重新回到N_IDLE状态,开始等待下一个诊断请求。
5 基于UDS规范的工具支持
5.1 诊断测试仪
- Indigo
快速且易于操作的诊断测试仪,适用于单个ECU或整个车辆
- CANoe / CANalyzer
支持带有ECU诊断功能的仿真和测试工具
- CANape 支持带有ECU标定功能的测量和校准工具
5.2 Flash编程
- vFlash 通过CAN,CAN FD,LIN,FlexRay,以太网(DoIP)刷写ECU。
5.3 诊断验证
- CANoe.DiVa 通过数据驱动的测试案例生成,自动验证ECU中的诊断实现。
5.4 诊断规范/编写
- CANdelaStudio 基于CDD格式模板的ECU诊断数据规范。支持ODX数据的导入和导出。
- ODXStudio 支持查看,编辑和比较ODX 2.0.1和2.2.0数据文件
6 基础诊断软件堆栈
- MICROSAR.DIAG
MICROSAR.DIAG包含BSW模块,支持根据AUTOSAR Classic实现基于UDS协议ISO 14229-1:2006(分别是ISO 14229-1:2013)协议开发的ECU诊断功能。