RoutineControl (31 hex) service,例程控制服务主要功能是由客户端请求服务端开始、结束一个例程,以及获取例程执行的状态和结果。
一、主要功能和响应规则
1.例程 routine
例程,就是指的一段写好的具有一定功能的代码模块,通过例程控制服务,可以控制这段代码。ISO14229-1里对例程的接口已经定义好了,即可以控制例程的开始、结束和获取结果,以及相关的执行规则也定义的很清楚。
例程有两种,一种是完全有例程控制服务对例程的开始和结束进行控制,该例程开始之后会持续执行,由客户端对其进行控制,服务端仅负责接受和执行请求;另一种是由客户端请求例程开始执行,但例程结束由服务端控制,可以是在诊断响应之前就结束,也可以在给出诊断响应之后再结束。
那么,例程都用来做什么?最常见的应用场景如车钥匙学习,四轮胎压学习,ESP制动液注入,车窗防夹标定,存储器擦除,数据校验,StayInboot,程序升级前检测刷写条件是否满足,一些需要测试的功能检测,功能控制等等。
2.例程控制
乍一看,会有这样的疑问,例程控制和输入输出控制服务的功能是不是一样的?
实际上,输入输出控制的功能,都可以通过例程控制来实现,而且,例程控制服务可以实现更复杂的功能。按照标准对服务功能的定义,输入输出控制服务大部分都是对服务端的一些变量做临时控制,基本上都是静态的,也就是说不能形成有序的操作。而例程控制前面说过,是由一段代码来执行的,所以它是可以让服务端的某些接口按照一定的顺序执行一系列的控制,通过连贯操作,实现一些复杂场景的功能实施。该服务用于较复杂的控制,而InputOutputControlByIdentifier (2F hex) service用于相对简单的输出控制。
例程控制主要包含以下控制指令:
开始例程
服务端在接收到开始例程的请求后,应立即开始执行指定的例程(通过一个两个字节的ID来指定,后面格式里会看到),根据例程设计的不同,服务端应该在执行例程之后给出响应,有些例程如擦除寄存器、数据校验等,需要立即执行并且在执行完给出结果的,则需要在执行完给出肯定或者否定响应,而有些如钥匙学习、胎压学习等需要由客户端发送请求来控制,则在正常开始例程之后给出肯定响应,如不正常则给出否定响应。
停止例程
服务端在接收到停止例程的请求后,应立即停止指定的例程,如果例程停止成功,服务端应该给出肯定响应,如果例程停止失败,则需要给出否定响应。
请求例程结果
一般例程,在前面的两个指令的响应里,就会带有例程执行的结果。但是有一些由于例程的特殊性无法在响应里给出结果,所以需要单独请求例程执行的结果。
二、应用数据格式
1.请求报文
请求报文的格式比较简单,主要包括请求的服务ID,子功能,routineIdentifier和routineControlOptionRecord四个部分。服务ID和子功能这里就不再多说,固定格式必须包含的。routineIdentifier和输入输出控制服务的DID参数类似,也是用来标识具体的功能的,也是强制的参数。routineControlOptionRecord这个参数是可选的,根据实际的routine设计来决定,有些例程需要额外的数据,就需要通过这个参数来放入一些内容,如数据校验需要把校验标准发送给服务端,这样服务端就可以根据自身计算结果和接收到的校验数据进行校验比对,来判断校验结果。
2.响应报文
响应的格式同样,也比较简单,响应的服务ID和子功能(这里叫routineControlType)同样不再多说,routineIdentifier这里也不再说明。
第5个字节是routineInfo,这个参数的定义比较有意思,这是个固定格式,主要目的是为了能够让诊断仪更加通用。一般诊断仪分两种,OEM自己的和通用诊断仪,OEM自己的很容易理解,因为有OEM的数据支持,所以基本上所有的数据都可以识别,而通用的诊断仪则没有办法识别OEM定义的部分内容,如没办法识别例程的执行结果是成功和失败。所以这个字节提供了一个框架,把执行的结果统一放到这个地方,这样通用的诊断仪虽然不能识别结果的具体细节,但还是能够识别请求执行的成功与否。这个参数在一些OBD的标准里要求的例程是强制的,而对于OEM则是可选的。
最后这个参数routineStatusRecord则是实际的例程执行结果,根据具体的例程进行定义,可以是简单的成功失败,也可以是具体的执行后的数据。
————————————————
版权声明:本文为CSDN博主「ChenglimK」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:UDS诊断系列之十三 例程控制(31)服务 上
3.否定响应
例程控制服务的否定响应,是有子流程的,也就是说在本系列第三篇介绍的主流程之后,有自己的单独的格式和参数检查,ISO标准里的流程截图如下。
按从上到下的顺序,每一步的检查内容列举如下:
Minimum length check:这里最小长度检查包括了SID,SubFunction,RID,最少是4个字节;
第一个NRC31:这里检查在当前诊断会话模式,是否支持请求的RID,这里的RID即routineIdentifier;
NRC34:如果服务支持安全传输,这里检查安全传输的验证结果是否通过;
NRC33:如果DID支持安全校验,这里检查安全校验服务是否已经验证通过;
NRC12:这里校验请求里的子功能是否支持;
Total length check:总长度检查,即包括SID,SubFunction,RID,routineControlOptionRecord的总长度,routineControlOptionRecord的长度依据RID而定;
第二个NRC31:当检查逻辑执行到这里的时候,主要检查的是routineControlOptionRecord参数是否在RID定义的有效范围内;
NRC22:NRC22有两个,第一个检查的是请求的服务和子功能的执行条件是否满足,第二个检查的是请求数据的执行条件是否满足;
NRC24:31服务的子功能是有顺序的,即停止例程的请求必须是在开始例程的后面请求才可以,请求例程的执行结果也必须在开始例程之后才被允许,否则回复此NRC。
如果上面的检查内容都检查通过了,则回复肯定响应。
4.子功能
例程控制服务只有三个有效子功能,其他的都是保留值,其定义对应的就是上篇提到的三个功能。
子功能 定义
01 开始例程,即开始执行请求的例程
02 停止例程,即停止执行请求的例程
03 请求例程结果,即要求服务端响应请求的例程的执行结果
三、数据示例
例程控制服务的格式比输入输出控制服务的要简单很多,因此,我只摘抄一个示例进行说明。
下图示例为请求开始执行例程,可以看到请求里的子功能字节是1,之后是被请求的RID。给出的示例中请求是不带数据的,因此到RID就结束了,而有些例程是需要请求带数据的,如进行CRC校验的时候需要客户端发送CRC结果给服务端,然后服务端才能跟自己计算的结果进行比较,这时候就需要将CRC结果放到RID后面发送出去。
响应的routineControlType跟子功能保持一致是1,在RID之后加上了该RID需要的数据,这个数据的OEM或者供应商根据实际内容定义的。
————————————————
版权声明:本文为CSDN博主「ChenglimK」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:UDS诊断系列之十四 例程控制(31)服务下