目录
5.2 协议数据单元(Protocol data unit,PDU)规范
5.3.1 协议控制信息(PCI, Protocol Control Information)
5.3.2 服务ID(SI, Service Identifier)
5.3.3 否定响应服务ID(NR_SI, Negative response service identifier)
前言
书接上回,上一篇文章介绍了应用层的服务,还记得那些服务原语和服务格式么?哈哈哈,如果你是初学汽车诊断的小白,不记得没关系(像我一样),但是这次的内容可不能像上次一样含糊了,事先说明一下,从本篇内容开始就要正式进入14229-1的核心内容了,请大家从这篇文章开始务必要认真阅读每一个名词的概念,并尝试着去理解他。好,话不多说,我们进入正题。
5 应用层协议
5.1 一般定义
应用层协议应始终是一个已确认的消息传输,即对于客户端发送的每个服务请求,服务器应发送一个或多个相应的响应。本规则的唯一例外是使用功能寻址或请求/指示规定不应生成响应/确认的少数情况。为了不给系统带来许多不必要的消息,有些情况下,即使服务器未能完成请求的诊断服务,也不应发送否定响应消息。
应用层协议应与会话层协议并行处理。这意味着,即使客户端正在等待对先前请求的响应,它也应保持适当的会话层定时(例如,如果需要在其他服务器中保持诊断会话,则发送TesterPresent请求。实现取决于使用的数据链路层)。
5.2 协议数据单元(Protocol data unit,PDU)规范
A_PDU(Application layer Protocol Data Unit)直接由A_SDU(Application layer Service Data Unit)和应用层特定的控制信息A_PCI(Application layer Protocol Control Information)构成。A_PDU应采用以下一般格式:
其中:
--“Mtype, SA, TA, TA_type, RA, Length”与A_SDU中使用的参数相同;
--“A_Data”是为每个单独的应用层服务定义的字节数据的字符串。A_Data字符串应以A_PCI开头,然后是A_SDU中为每个服务指定的所有服务特定参数。方括号表示参数列表的这部分可能为空;
--“Length”决定A_Data的字节数;
5.3 应用程序协议控制信息
5.3.1 协议控制信息(PCI, Protocol Control Information)
A_PCI包括两种格式。由A_PCI参数的第一个字节的值所标识的格式。对于所有的服务请求和第一个字节不等于0x7F的服务响应,应适用以下定义:
其中:
--“SI”是参数服务ID
那么对于第一个字节是0x7F的服务响应,应适用以下定义:
其中
--“NR_SI”是识别否定服务响应/确认的特殊参数;
--“SI”是参数服务ID;
注意:对于服务ReadDataByPeriodicIdentifier(0x2A)中定义的周期性数据响应消息的传输,应用层协议数据单元(A_PDU)中不存在A_PCI。
5.3.2 服务ID(SI, Service Identifier)
类型:1字节无符号整数值
范围:0x00-0xFF,根据下表中的定义
注意:请求消息的服务标识符和肯定响应消息的服务标识之间存在一一对应关系,SI字节值的bit6指示服务类型。所有请求消息的SI bit6=0。除了ReadDataByPeriodicIdentifier(0x2A)服务的周期性数据响应消息外,所有肯定响应消息的SI bit6=1。这很好理解,例如0x10服务的请求消息的肯定响应消息是0x50,不正好是加了个0x40么?用二进制位直观地表示出来就是0001 0000-->0101 0000,正是bit6变成了1。
描述:SI应用于对服务原语中调用的特定服务进行编码。应为每个请求服务分配一个唯一的SI值。应为每个肯定响应服务分配相应的唯一SI值。
服务ID用于表示从应用程序层传递到下层(并从较低层返回)的A_Data数据字符串中的服务。什么?你说你看不懂?服务ID嘛,每个服务都有标识符,也就是服务ID,比如诊断会话控制服务的ID就是0x10,ECU重启服务的ID就是0x11,如果没有服务ID,就没办法识别不同的请求服务了不是么?
5.3.3 否定响应服务ID(NR_SI, Negative response service identifier)
类型:1字节无符号整数值
固定值:0x7F
描述:参数NR_SI是识别否定服务响应/确认的特殊参数。它应为否定响应/确认消息的A_PCI的一部分。
注意:NR_SI值与SI值相协调。为了简化A_Data的编码和解码,NR_SI值不被用作SI值。
5.4 否定响应/确认服务原语
根据下表,每个诊断服务都有一个否定响应/否定确认消息,该消息由消息A_Data字节指定。第一个A_Data字节(A_PCI.NR_SI)始终是特定的否定响应服务标识符。第二个A_Data字节(A_PCI.SI)应该是来自否定响应消息对应的服务请求/指示消息的服务标识符值的副本。
注意:A_Data表示否定响应消息的消息数据字节。参数responseCode用于否定响应消息中,以指示诊断服务失败或无法及时完成的原因。
5.5 服务器响应实现规则
5.5.1 一般定义
以下小节指定服务器的行为执行服务时,服务器和客户端应遵循这些实现规则。
缩写词:
--suppressPosRspMsgIndicationBit:肯定响应抑制位,TRUE=服务器不应发送肯定响应消息(一个例外是NRC 0x78,当服务器发送NRC 0x78的否定响应消息时,不管肯定响应抑制位是TRUE还是FALSE,都应发送最终肯定/否定响应);FALSE=服务器应该发送肯定或否定响应消息;
--PosRsp:肯定响应消息;
--NegRsp:否定响应消息;
--NoRsp:不发送肯定或否定响应消息;
--NRC:否定响应码;
--ALL:服务器支持客户端请求消息的所有请求数据参数;
--At least 1:服务器必须至少支持客户端请求消息的1个数据参数;
--None:服务器不支持客户端请求消息的任何请求数据参数。
功能寻址请求下,不发送相关不定响应吗 0x11、0x7F、 0x12、0x7E、0x31(例外情况还是回复NRC 0x78时)
5.5.2 一般的服务器响应行为
本子条款中规定的一般服务器响应行为对于所有请求消息都是强制性的。验证步骤从接收请求消息开始。下图分为3个子条款:
--mandatory(强制的):要通过每个请求消息进行评估;
--optional(可选的):可以根据每个请求消息来进行选择性的评估;
--manufacturer/supplier specific(特定于制造商/供应商):该程序可以通过额外的制造商/供应商特定检查来扩展。
注意:根据指定NRC处理的所有图中实现的选择,不能保证所有可能的测试模式序列都有特定的NRC。
上面的话是什么意思呢,我是这么理解的,就是说一般的服务器响应规则所有的供应商/制造商都应遵守,但是下图中的流程不是所有的服务都要走完,比如说不需要安全等级解锁的服务当然不需要验证安全等级,但有一些流程是所有的服务必须要走的,当然,供应商/制造商也可以自定义一些流程,但是记住一点,服务器的响应行为是必须要按照这个流程走的,但是对于不同的服务来说,mandatory是必须要走的流程,而optional就是可选择的流程,最后就是供应商/制造商可以自定义一部分流程了,如下图所示:
其中,图中的1(不是框框里的,是问你Service is busy?的那里)表示服务器无法接受诊断请求,因为其他客户端已请求并正在执行另一个诊断任务;图中的2(同1)表示的是参考每个服务的响应行为(支持的否定响应码)。
不要以为这张图到这里就完事了,注意到图中的下面有一个框框中的1了吗?他的条件是该服务具有子服务并且不是0x31服务,就会走到这个分支,你往下翻,会惊奇的发现还有一张图,而这张图就是描述带有子功能参数和服务器响应行为的请求消息的图,图中的上面有一个圈圈中有个1,这就是接上面的图。
5.5.3 带有子功能参数和服务器响应行为的请求消息
5.5.3.1 带有子功能参数的请求消息的一般服务器响应行为
本子条款中规定的一般服务器响应行为对于所有具有子功能参数的请求消息都是强制性的。
下图描述了带有子功能参数的请求消息的一般服务器响应行为。
其中,图中的1(不是框框里的)表示该请求消息的最小长度为2个字节,因为你这个服务既然具有子功能,那么肯定是有一个字节的SID和1个字节的子功能参数的,加在一起不就是2个字节嘛,如果你的长度小于2个字节,无需多言,该请求消息的长度肯定是不对滴;图中的2表示子功能是否需要进行序列检查,例如链路控制或安全访问;图中的3表示参考每个服务的响应行为(支持的否定响应代码)。
5.5.3.2 物理地址的客户端请求消息
本子条款中指定的服务器响应行为在每个服务的服务描述中引用,该服务描述支持从客户端接收的物理寻址请求消息中的子功能参数。
其实自己总结还不如解答官方图片(其实就是懒),那么我们一如既往地引用14229-1中的官方图表,并对图表进行说明,下表中描述了对于物理寻址的请求消息来说,服务器应该做出什么回应,是应该回复肯定响应啊还是否定响应啊还是不回复啊,都在这张表里头。
看到这个表的第一反应是不是一脸懵?这么复杂,还是英文的,别急,我们静下心来慢慢看,我尝试着把这些枯燥的东西用生动的语言描述出来,来吧,我们来一起看一下这张表中都提供了什么信息。
从上往下看吧,先看一下表头,是以一个大分类+小分类来展现出来的,从左往右来看,首先映入眼帘的是客户端请求消息,这里包含了2个小的分类,一个是寻址类型,就是请求的消息是用什么寻址方式来进行发送的,是功能寻址啊还是物理寻址,那么另一个是子功能参数里面包含的一个位,就是子功能的最高位也就是肯定响应抑制位,这里表示肯定响应抑制位为TRUE还是FALSE,这就是客户端请求消息提供的信息。再往下看是服务器功能栏,这一栏有3个小分类,第一个为是否支持该服务,字面意思,比如我这个ETC支持0x10(DiagnosticSessionControl)服务,但是不支持0x11(ECUReset)服务,就是这个意思,第二个为子功能是否支持,和第一个分类差不多意思,只不过是把服务换成了子功能而已,第三个为支持的数据参数(仅在适用时),就是说你这个请求的服务中有多少个数据参数,也就是除了服务ID和子功能之外的数据段,这就是服务器识别的功能。第三个栏升级服务响应栏,有两个小分类,第一个是服务器应该做出响应消息的类型,是应该回复肯定响应还是否定响应还是不应该回复响应消息,第二个是如果应该回复否定响应,那么否定响应码是什么,比如0x12(SubFunctionNotSupported)和0x13(IncorrectMessageLengthOrInvalidFormat)等,那么这是服务器应该做出的行为。最后一栏是对服务器响应的解释,这个没什么好说的,就是对前面含糊不清的回复消息进行说明。
OK,看完了表头后是不是还是感觉懵懵的?我知道你很急,但你先别急,看到第一列里的abcd...了吗,对喽,这些就是一个个不同的情况,相当于实例,光谈理论很枯燥并且晦涩难懂,那么下面我们结合实例来看一下:
a)首先来看a,我们从左往右看,本案例中请求消息的寻址方式为物理寻址,肯定响应抑制位为FALSE(0),服务器支持此服务,子功能也支持,支持至少一个数据参数,那么此时服务器应回复肯定响应,也就没有NRC喽,是不是很容易理解,我们接着往下看;
b)b这个情况,请求消息的寻址方式为物理寻址,肯定响应抑制位为FALSE(0),服务器支持此服务,子功能也支持,支持至少一个数据参数,此时服务器回复否定响应,到这里你是不是有个疑问?这个条件明明和案例a一样啊,为什么这里就回复否定响应呢?你看,后面的说明里面解释了这个情况,服务器发送负响应的原因是在读取请求消息的数据参数时发生了错误,就是在处理子功能的时候出现了其他错误,举个例子,PDU长度的错误,此时服务器回复NRC 0x13(incorrectMessageLengthOrIncorrectFormat);
c)c的情况是,本案例中请求消息的寻址方式为物理寻址,肯定响应抑制位为FALSE(0),服务器支持此服务,子功能也支持,但是服务器不支持数据参数,所以服务器回复否定响应,NRC为0x31(RequestOutOfRange),当然只有支持数据参数的请求服务才会走这个判断,表头里也说了嘛,仅在适用的情况下,如果不适用数据参数的话就可以忽略这个判断啦;
d)d的情况是,本案例中请求消息的寻址方式为物理寻址,肯定响应抑制位为FALSE(0),服务器不支持此服务,那么到这里服务器就有结论了,不管后面的数据是什么,都要回复否定响应,并且NRC为0x11(serviceNotSupported)或0x7F(serviceNotSupportedInActiveSession);
e)e的情况是,本案例中请求消息的寻址方式为物理寻址,肯定响应抑制位为FALSE(0),服务器支持此服务,但服务器不支持该服务的子功能,所以到这里就有结论了,不管后面的数据是什么,服务器都要回复否定响应,并且NRC为0x12(sub-functionNotSupported)或0x7E(sub-functionNotSupportedInActiveSession);
f)f的情况是,本案例中请求消息的寻址方式为物理寻址,肯定响应抑制位为TRUE(1),服务器支持此服务,子功能也支持,支持至少一个数据参数,那么此时服务器应不做回复,这么说吧,如果这里的肯定响应抑制位为FALSE(0),那么服务器就应该回复肯定响应,但是不巧的是它偏偏是TRUE(1),所以肯定响应抑制位的作用也就显而易见了,没错,就是抑制服务器的肯定响应的,让他把肯定响应给憋回去,啊哈哈哈!
g)g的情况同b,因为服务器要回复否定响应,而肯定响应抑制位是不抑制否定响应的,所以,就像其他国家的法律约束不到我们一样,否定响应不受抑制;
h)h的情况同c;
i)i的情况同d;
j)j的情况同e。
也不知道我说明白没有,我估计大概率是没有,如果哪里不清楚或者觉得我哪里说的不好,欢迎私信。
5.5.3.3 功能地址的客户端请求消息
物理寻址的请求消息看完了,功能寻址也别落下,同样的,下表描述了对于功能寻址的请求消息来说,服务器应该做出什么回应,是应该回复肯定响应啊还是否定响应啊还是不回复啊,都在这张表里头。
话不多说,直接上实例:
a)首先来看a,我们依旧是从左往右看,本案例中请求消息的寻址方式为物功能寻址,肯定响应抑制位为FALSE(0),服务器支持此服务,子功能也支持,支持至少一个数据参数,那么此时服务器应回复肯定响应;
b)b这个情况,请求消息的寻址方式为功能寻址,肯定响应抑制位为FALSE(0),服务器支持此服务,子功能也支持,支持至少一个数据参数,此时服务器回复否定响应,那么这种情况是和物理寻址中的b情况是一样的,这里不过多赘述;
c)c的情况是,本案例中请求消息的寻址方式为功能寻址,肯定响应抑制位为FALSE(0),服务器支持此服务,子功能也支持,但是服务器不支持数据参数,所以服务器回复否定响应,NRC为0x31(RequestOutOfRange),但是,but,前面有一句话不知道大家还是否有印象:功能寻址请求下,不发送相关不定响应吗 0x11、0x7F、 0x12、0x7E、0x31(例外情况还是回复NRC 0x78时)。这可是刚刚说过的呀,如果忘了的话这边建议您再看一遍呢,所以,显然服务器这时应不做回复;
d)d的情况是,本案例中请求消息的寻址方式为功能寻址,肯定响应抑制位为FALSE(0),服务器不支持此服务,那么到这里服务器就有结论了,不管后面的数据是什么,都要回复否定响应,并且NRC为0x11(serviceNotSupported)或0x7F(serviceNotSupportedInActiveSession),但是这里的寻址方式偏偏就是功能寻址,这次该不会不记得了吧,功能寻址是不发送0x11和0x7F的NRC的,所以,服务器这时应不做回复;
e)e的情况是,本案例中请求消息的寻址方式为功能寻址,肯定响应抑制位为FALSE(0),服务器支持此服务,但服务器不支持该服务的子功能,所以到这里就有结论了,不管后面的数据是什么,服务器都要回复否定响应,并且NRC为0x12(sub-functionNotSupported)或0x7E(sub-functionNotSupportedInActiveSession),但因为是功能寻址,所以,服务器这时应不做回复;
f)f的大部分情况可以参考物理寻址的f,但是这里有个特殊情况,如果回复的是NRC78,那么就应该忽略肯定响应抑制位和功能寻址对于部分NRC的屏蔽而给出最终响应,NRC78具体的规定可以参照14229-1的2013版本的附录A中,那里对于NRC78的说明很详细,而且简单地翻译后就很容易看懂。
g)g的情况同b;
h)h的情况同c;
i)i的情况同d;
j)j的情况同e。
那么以上就是服务器对于带有子功能参数的物理寻址和功能寻址的请求消息的相应行为,如果结合着上面的流程图来看,那么理解起来就会更加轻松了。
5.5.4 没有子功能参数的请求消息的服务器响应行为
5.5.4.1 客户端使用物理寻址发送请求消息
对于客户端使用物理寻址发送的请求消息,14229-1也给出了相应的表格进行说明,我们还是以分析图表的方式来学习,下表描述了服务器的响应行为:
表头这里就不过多介绍了,直接看实例:
a)寻址方式为物理寻址,服务器支持该服务,支持所有的参数,那么服务器应该回复肯定响应;
b)寻址方式为物理寻址,服务器支持该服务,支持至少一个参数,那么服务器应该回复肯定响应;
c)寻址方式为物理寻址,服务器支持该服务,支持至少一个参数,但是在获取请求消息的参数时发生错误,比如参数范围不正确,那么此时服务器应该回复否定响应,NRC视具体情况而定;
d)寻址方式为物理寻址,服务器支持该服务,不支持任何参数,那么服务器此时应该回复否定响应,NRC为0x31(RequestOutOfRange);
e)寻址方式为物理寻址,但是服务器不支持此服务,那么服务器此时应该回复否定响应,NRC为0x11(ServiceNotSupported)或0x7F(ServiceNotSupportedInActiveSession)。
5.5.4.2 客户端使用功能寻址发送请求消息
下表描述了服务器的响应行为:
a)寻址方式为功能寻址,服务器支持此服务,支持所有的参数,此时服务器应该回复肯定响应;
b)寻址方式为功能寻址,服务器支持该服务,支持至少一个参数,那么服务器应该回复肯定响应;
c)寻址方式为功能寻址,服务器支持该服务,支持至少一个参数,但是在获取请求消息的参数时发生错误,比如参数范围不正确,那么此时服务器应该回复否定响应,NRC视具体情况而定;
d)寻址方式为物理寻址,服务器支持该服务,不支持任何参数,那么服务器此时应该回复否定响应,NRC为0x31(RequestOutOfRange),但是别忘了,功能寻址下不回复NRC0x31的否定响应,所以此时服务器不做回复;
e)寻址方式为物理寻址,但是服务器不支持此服务,那么服务器此时应该回复否定响应,NRC为0x11(ServiceNotSupported)或0x7F(ServiceNotSupportedInActiveSession),同样的,功能寻址下不回复NRC为0x11和0x7F的否定响应消息,所以此时服务器不做回复。
注意:上述的四张表并非包含了所有的情况,具体情况还要根据具体的项目需求来变动,比如说功能寻址不支持0x22(ReadDataByDataIdentity)服务,那么就算客户端使用功能寻址请求的0x22服务的请求消息满足回复上述肯定响应消息或否定响应消息的条件,服务器也不应该做回复,也就是不回复任何消息。
5.5.5 服务器响应行为的伪代码示例
不得不说,有时候看看官方文档也觉得挺有意思,竟然还有伪代码,这是我没想到的,那就来看一下官方给出的伪代码是什么样子的。
这个代码的话逻辑还是非常清晰的,大致描述了服务器对于服务请求的响应行为,这里也不进行解读了,自行理解吧。
5.5.6 具有物理和功能寻址的多个并发请求消息
通用服务器实现在服务器中只有一个诊断协议实例可用。一个诊断协议实例一次只能处理一个请求。规则是,任何收到的消息(无论是物理寻址模式还是功能寻址模式)都会占用此资源,直到处理请求消息(发送最终响应或应用程序调用无响应)。
只有两个例外情况需要单独处理:
--客户端使用保持活动逻辑在一个或多个服务器中保持先前启用的会话活动。保持活动逻辑定义为功能寻址的有效TesterPresent消息,肯定响应抑制位SPRMIB=true,必须由旁路逻辑处理。服务器需要确保此特定消息不会“阻止”服务器的应用程序层,并且可以处理随后的寻址消息。
--如果服务器支持一个或多个法定诊断请求,并且在非法定服务(例如,增强诊断)处于活动状态时收到其中一个请求,则应中止活动服务,启动默认会话,并处理法定诊断服务。如果当前会话模式时编程会话,则此要求不适用。
小结
本篇文章我们介绍了应用层的协议内容,主要描述了服务器对于客户端请求的响应行为,那么对于此部分,14229-1的附件J对于处理多个客户端信息的行为做了进一步描述,这里就先不介绍了,以后有机会我会再补充的,本期的内容就到这啦,这次也是收获满满,期待和大家一起进步,加油,我们下期见!