Sunday, 12 April 2020 00:34

UDS诊断入门

UDS实践性强,逻辑复杂,很多服务非要体验过一次才能理解,导致包括我在内的初学者感觉晦涩难懂,不明觉厉,因此将自己的理解写下来、整理下来,与君共勉。

零、UDS诊断命令备忘录

uds 001

一、简介

UDS(Unified Diagnostic Services,统一的诊断服务)诊断协议是在汽车电子ECU环境下的一种诊断通信协议,在ISO 14229中规定。它是从ISO 14230-3(KWP2000)和ISO 15765-3协议衍生出来的。“统一”这个词意味着它是一个“国际化的”而非”公司特定的”标准。到目前为止,这种通信协议被用在几乎所有由OEM一级供应商所制造的新ECU上面。这些ECU控制车辆的各种功能,包括电控燃油喷射系统(EFI),发动机控制系统,变速箱,防抱死制动系统(ABS),门锁,制动器等。

诊断工具与车内的所有控制单元均有连接,且这些控制单元均启用了UDS服务。不同于仅使用OSI模型第一层、第二层的CAN协议,UDS服务使用OSI模型的第五层和第七层(会话层和应用层)。服务ID(SID)和与服务相关的参数包含在CAN数据帧的8个数据字节中,这些数据帧是从诊断工具发出的。

目前市面上的新车都具有用于车外诊断的诊断接口,这使得我们可以用电脑或诊断工具(业内称为测试器Tester)连接到车辆的总线系统上。因此,UDS中定义的消息可以发送到支持UDS服务的控制器(业内称ECU)。这样我们就可以访问各个控制单元的故障存储器或用新的固件更新ECU的程序。除此之外,UDS还用于下线检测时把一些信息(如VIN码)写入到汽车的各个零部件中。这些功能也是UDS最为核心的功能。

为什么我们要设计UDS这样的诊断协议呢?在汽车诊断协议诞生之前,修车只能靠师傅的经验,因为汽车零部件不会告诉你它哪里出了问题。但有了诊断协议之后,一旦零部件出了问题或者出过问题,它们会把故障信息保存在内存里面,维修师傅就可以通过通信总线读取这些故障信息,比如一个ECU经历欠压故障之后,它会将欠压故障代表的DTC(诊断故障码)存储起来,可选择性保存的还有发生故障时的快照信息(比如此时的车速、读到的电压值等)。快照信息有助于测试工程师和售后技师查找发生故障的原因。

除了CAN总线以外,UDS也可在不同的汽车总线(例如 LIN, Flexray, Internet 和K-line)上实现。

如下图所示,ISO 14229也就是UDS协议仅对应用层、会话层做出了定义。这里有个疑问,UDS专指ISO 14229-1吗?这种说法是不对的,UDS包含了ISO 14229下属的7个子协议,其中ISO 14229-2还是会话层的,所以UDS仅包括应用层的说法也是错误的

说明下,我们本篇文章我们仅使用CAN来描述UDS。对于CAN来说,物理层和数据链路层遵循ISO 11898协议;网络层方面,Classical CAN仅有8个字节的数据场与应用层处理多帧数据的需求构成了矛盾,ISO 15765-2协议解决了该问题,我们用CAN的8字节数据场会腾出一到两个字节的做法,来体现网络层的控制信息。

排放相关的诊断内容,即ISO 15031-5主要针对OBD协议,为法规强制要求燃油车满足的协议,电动车是无需满足的。燃油车通常既满足UDS协议,又满足OBD协议,这两个协议不冲突。小伙伴们有没有发现UDS协议的服务ID(SID)最小的是0x10,那是因为小于0x10的服务是OBD协议中规定的。

学习UDS之前,希望您对CAN的基础知识有初步的了解,知道一个CAN帧的基本构成,熟悉至少一种CAN盒的使用方法。协议方面,应通过PPT、论文、原版英文协议重点学习ISO 15765-2和ISO 14229-1的协议内容,之后可以将Git上的开源UDS协议栈移植到你熟悉的嵌入式平台上,进行数据收发;或使用CAN盒与支持UDS诊断的设备进行数据收发,对UDS有一个大致的认识。切记知行合一,实践很重要。

uds 002
摘自ISO 14229-1-2013
uds 003
摘自ISO 14229-1-2013
uds 004
摘自恒润科技公开资料
uds 005
摘自恒润科技公开资料

二、UDS的服务

UDS本质上是一系列服务的集合。UDS的服务包含6大类,共26种。每种服务都有自己独立的ID,即SID。

SID:Service Identifier,诊断服务ID。UDS本质上是一种定向的通信,是一种交互协议(Request/Response),即诊断方(Tester)给ECU发送指定的请求数据(Request),这条数据中需要包含SID,且SID处于该应用层数据的第一个字节。如果是肯定的响应(Positive Response),首字节回复[SID+0x40],举例子就是请求0x10,响应0x50;请求0x22,响应0x62。如果是否定的响应(Negative Response),首字节回复0x7F,第二字节回复刚才询问的SID。比如Tester请求0x10服务,我想进入编程模式,ECU给出否定响应,首字节0x7F,第二字节回复0x10,代表我否定你的0x10服务请求,第三字节是NRC(否定响应码),代表我否定你的依据。

肯定响应否定响应的形式一定要熟悉。

通常,在CAN总线中,Addressing information寻址信息会在CAN的帧ID中体现出来,例外是远程寻址,但不常使用。所谓的寻址信息包含了源地址(Source Address)和目标地址(Target Address),就是这条信息是由谁发给谁的,类似于收件人和发件人。当然,ECU回信给Tester时,ECU就变成源地址了。因此源地址和目标地址在UDS中并不是一成不变的。

UDS的寻址模式分两种,一种是物理寻址点对点、一对一),根据物理地址的不同进行访问,但只能访问单个ECU节点,Tester为SA源地址,ECU作为TA目标地址;对应的,另一种是功能寻址广播、一对多),根据功能的不同进行访问,它能访问多个ECU节点,对于标准帧来说,通常是0x7DF。

每一个ECU都有2个CAN的诊断帧ID,分别对应物理寻址的收与发。通常由主机厂来确定不同ECU的这两个特定的诊断ID。比如0x701对应接收Tester的消息,0x709对应发给Tester的消息。

UDS的26种服务

UDS的服务分为6大类,但常用的服务是加背景色的15种。这15种服务又可粗略地划分为权限控制、读取数据/信息、写入数据/信息、通信控制、功能控制这几类(注:这几类是我自己划分的)。

ISO14229-1英文原文中大篇幅的对26种服务进行了解释,英文原文链接如下。学习时如果遇到困惑可以找标准中的相关语句进行翻译,协议是所有学习材料的根本。

ISO14229-1-2006-汽车诊断协议

 

本文重点介绍以下几个服务:$10 Diagnostic Session Control(诊断会话),$14 Clear Diagnostic Information(清除诊断信息),$19 Read DTC Information,$22 Read Data By Identifier(通过ID读数据),$27 Security Access(安全访问),$2E Write Data By Identifier(通过ID写数据),$3E Tester Present(待机握手)。其他的服务楼主有时间会补齐,敬请期待。

uds 006
26种服务,其中15种较为常用
uds 007
少了0x38

$10诊断会话 Diagnostic Session Control

$10包含3个子功能,01 Default默认会话,02 Programming编程会话,03 Extended扩展会话,ECU上电时,进入的是默认会话(Default)

为什么设计三个会话模式呢?因为权限问题。默认会话权限最小,可操作的服务少;扩展模式通常用于解锁高权限诊断服务,例如写入数据/参数、读写诊断码;编程模式用于解锁bootloader相关的诊断服务,即程序烧录。

题外话,讲个故事。这三个会话模式好比普通项目成员(默认会话)、项目组长(扩展会话)和会计(编程会话)的关系,小职员权限最小,小职员有的权限项目组长全有,项目组长还多了些其他的高端权限(如写数据、例程控制)。会计则不同,它有些自己独有的权限(刷写程序),但项目组的很多权限它没有(读/擦故障码),因为它只干会计相关的事,本身不参与项目。

这里来一张权限表格。带颜色的区域代表需要解锁操作。

uds 008
15个服务在不同会话中的权限情况(本表仅作参考)

如果您进入了一个非默认会话的状态,一个定时器会运转,如果一段时间内没有请求,那么到时间后,诊断退回到默认会话01(最低权限)。当然,我们有一个$3E的服务,可以使诊断保持在非默认的状态。

UDS的请求命令有4种构成方式,即SID,SID+SF(Sub-function),SID+DID(Data Identifier)(读写用),SID+SF+DID。每种服务都有自己不同的构成方式,查看服务说明即可,不用死记硬背。

NRC:Negative Response Code(否定响应码)。如果ECU拒绝了一个请求,做出否定响应(Negative Response),它会在第三字节回复一个NRC。不同的NRC有不同的含义。后文中我会补一个NRC的中文版本链接。

uds 009
14229-1协议第329页

例子:以CAN总线网络举例。CAN帧一共8个字节,第一字节被网络层占用。(ISO 15765-2的知识)

uds 010
进入01会话成功,进入02会话失败,进入03会话成功

请求(Request):02 10 02 xx xx xx xx xx ; 02是网络层单帧SF,表示应用层包含有2个字节,10是服务ID(SID),02是子功能——进入编程会话。但ECU婉拒了它的请求。

uds 011
摘自ISO 14229-1:2013 p39

我们看下上面的图表,这个是ISO 14229定义的0x10服务应具有的请求报文格式,M意为Mandatory 强制。可以看到0x10服务仅有两个字节,整条报文是“服务ID+子功能”,比较简单。

肯定响应:02 50 02 xx xx xx xx xx;02即应用层含两个字节,50=10+40表示对SID的肯定回复,02是子功能。

否定响应:03 7F 10 7E xx xx xx xx;03同上,7F表示否定响应,10是SID,7E是NRC(否定响应码)。

$3E待机握手

$3E服务用于向服务器指示诊断仪仍然连接在网络上,之前已经激活的诊断服务功能可以仍然保持激活状态。


uds 012

例子:02 3E 80 00 00 00 00 00,发送一个3E服务的报文,保持非默认会话状态。80表示无需回复。

$27安全访问

$27安全访问:ECU当中有很多数据是整车厂独有的,并不希望开放给所有客户,它需要做一个保密的设定。我们在读取一些特殊数据的时候,要先进行一个安全解锁ECU上电之后是一个锁定的状态(Locked),我们通过$27服务,加上一个子服务,再加上一个钥匙,这样的服务请求可以进行解锁。比如下面的例子,2n-1是一个子服务,通过首轮种子的请求,首轮ECU会返回67+01+AA+BB+CC+DD,AA~DD就是种子了。之后第二轮,诊断端会利用种子进行运算(利用整车厂的算法),生成k1(不一定是1个字节),那么发送请求,27+02+[k1]。ECU同样也会通过种子算出k2。当k1和k2匹配时,解锁(Unlocked)成功。

uds 013

$27安全访问服务的否定响应服务ID也是7F。还记得刚才否定响应的格式吗?7F+27+NRC(否定响应码)。

uds 014
实际通信的截图,黄色位置是密钥区域

例子:

Tester: 02 27 05 00 00 00 00 00 安全访问,05子功能

ECU: 06 67 05 08 27 11 F0 00 肯定响应,回复了对应安全级别的种子

Tester: 06 27 06 FF FF FF FF 00 发送密钥,4个FF。注意06是与05成对使用的。

ECU: 03 7F 27 78 00 00 00 00 若为否定响应,7F+27+NRC

ECU: 02 67 06 00 00 00 00 00 若为肯定响应,通过安全校验

细说下安全验证算法。安全验证算法包括1个核心,3个主体

第一个主体通常和ECU有关。比如我们先用22服务读取ECU的SN,取其中4个字节,作为“调味料”参与,显然这个“调味料”对于这个ECU来说是不变的,也能通过22服务方便的读取到。

第二个主体seed,通常与ECU的运行时间有关系,是主料,在27服务发送奇数子功能时回复。seed通常一直在发生变化,无法发现其规律。

第三个主体是执行次数,就是算法要执行几轮。执行1轮和2轮得到的结果肯定是不一样的对吧。

最大的核心就是算法了。举个简单的算法,比如seed和ECU SN前4个字节加一下,循环左移两位,执行3轮,return这个数作为key,结束。安全验证就是一把锁,算法越复杂,短时间解开的成本越高,越不易被破解掉。如果失败次数过多还会触发惩罚机制,一段时间内都无法再尝试解锁,防止人为的破解。

$22读数据

$22读数据,Request(请求):22+DID(Data Identifier,通常是两个字节)

Response(响应):62+DID+Data

uds 015

DID有一部分已经被ISO 14229-1规定了。比如0xF186就是当前诊断会话数据标识符,0xF187就是车厂备件号数据标识符,0xF188就是车厂ECU软件号码数据ID,0xF189就是车厂ECU软件版本号数据标识符。

uds 016
14229-1协议第339页

$2E写数据

$2E写数据,Request(请求):2E+DID+Data

Response(响应):6E+DID

uds 017
写入一个17字节的VIN码,模拟的不好,第四条应该在第二条的位置上方

上面这个例子的发送接收顺序是有问题的,是会产生误解的,我有时间更换一下。

正确的顺序是10开头的帧请求、30开头的帧回复、21开头再请求、22开头继续请求、03开头回复确认。我们一帧一帧来看。

  • 10 14根据ISO15765-2代表这是一组多帧中的首帧(属于传输层的信息),一会要发0x14=20个字节的有效数据。之后是2E+F190(代表这是VIN码)+VIN码的前3个字节。意思是作为外部工具,想写入一个VIN码数据。这件事情正常是发生在车辆下线时。
  • 30 00 14是TP层(传输层)的信息,表示这是一个流控帧,ECU发出的,表示可以一直连续发,但连续帧最短的间隔时间要求是20ms。
  • 21是TP层的信息,表示这是一个连续帧,序号为1。后面是VIN码的第4字节到第10字节。
  • 22是TP层的信息,表示这是一个连续帧,序号为2。后面是VIN码的第11字节到第17字节。
  • 03是TP层的信息,这里说的这个TP层的信息是传不到应用层的,即这是一个用完就会抛弃的信息。03的0表示这是一个单帧,3表示后面有3个有效字节。6E表示我们确认执行了2E服务的请求,这个请求写入的ID是F1 90,即VIN码。

注意,比如0xF190等DID不支持直接写入数据,需要用$10来进行会话转换。也就是说,对于写数据的请求,一般来说需要在一个扩展会话,和安全等级1的状态下才能进行。

$19 读DTC

19服务是一套诊断服务中的重中之重。协议中篇幅长达63页,通信举例达到了18个。可以说没有19服务,就没有完整的UDS。

DTC(diagnostic trouble code):如果系统检测到了一个错误,它将存储为DTC。DTC可表现为:一个显而易见的故障;通讯信号的丢失(不会使故障灯亮起);排放相关的故障;安全相关的错误等。DTC可以揭示错误的位置和错误类型。通常DTC占用3个字节,OBD II占用两个字节。图中FTB为Fault Type Byte。

uds 018

故障码包括四个大类,分别是PCBU,P是powertrain动力系统,C是Chassis底盘,B是Body车身,U是network通信系统。一个DTC信息占用4个字节。最后一个字节是DTC的状态。DTMMiddleByte和DTCLowByte两个字节是我们熟知的类似P0047(ISO15031中的故障码)中“0047”的纯数字故障码。第一个字节在乘用车中,前两个bit代表P/C/B/U(动力/底盘/车身/网络)中的一个,之后六个bit是数字,合在一起的样子形如“C01”。第一个字节的前2个bit中,用00/01/10/11分别表示P/C/B/U。(感谢aymjwwl007)

举个例子,U312345这个故障码(我杜撰的),它的状态是Test failed叠加Confirmed,那么DTC信息这四个字节就应该是0xF1(二进制11110001),0x23,0x45,0x09。

uds 019
uds 020
这是ISO15031中的故障码,和UDS中的故障码在长度上有一定的不同

$19拥有28个子服务(Sub-Function)。常用的子服务有:

01 (读取符合掩码条件的DTC数量)(必须支持),后面的参数是DTC状态掩码,若为01表示我想读当前故障,若为08表示我想读历史故障,若为09表示当前故障和历史故障都想读。

在肯定回复时,组合应该是59(19+40) - 01 (子功能) - 09 (本ECU所支持的掩码条件)-01 DTC的格式(ISO14229-1为01) - 00 01 (目前满足条件的DTC有一个)

02(读取符合掩码条件的DTC列表及其状态)(必须支持),后面的参数是DTC状态掩码,解读同上。

在肯定回复是,59 - 02(子功能)- 09(本ECU所支持的掩码条件) - XX XX XX ( DTC,车厂定义 ) - 01 (这个故障码怎么了,01表示当前故障)

04(读取快照信息),也叫冻结帧。

06(读取扩展信息)。

0A(读取ECU支持的所有DTC列表及其状态)(必须支持)。这个就不必发DTC状态掩码了。所有支持的DTC列表及其状态都会打印出来。

uds 021
黄色框是DTC,紧跟着的是DTC状态
uds 022
同时读取当前/历史故障,黄色框是DTC,紧跟着的是DTC状态

刚才提到,一个DTC除了它自己的3个字节,还有一个字节专门用于表达DTC的状态,这个字节我们叫它DTC状态掩码。这个状态字节每个位的含义下面列举出来。注意,在实际项目中,并不是所有的DTC状态都是支持的。DTC状态掩码前7个位的理解是UDS的一个难点。

关于DTC状态掩码更详细的解释参见文末的学习资料22,张老师有详细的解答。

uds 023
DTC状态掩码
uds 024
Request/Response。括号标识循环,可以读出很多DTC

$14清除DTC

清除(复位)DTC格式,它可以改变DTC的状态。DTC状态中的八个位,除bit4和bit6外均会被清零,包含当前故障(TestFailed)和历史故障(ConfirmedDTC)。bit4和bit6这两个testNotCompleted开头的会被强制置1。

3个FF代表清除所有DTC。

Request:14+FF+FF+FF;

Response:54 。

uds 025
14服务

$2F IO控制

该服务可以通过DID(数据标识符)来进行输入信号的替换和控制零部件负载输出。这是一个用在产线上较多的服务。该报文的请求至少由4个字节组成。第一个字节是2F,第二第三字节是DID,其中第二字节是高位。第四字节是子功能,IO控制类型。

IO控制类型分为4类,

00是控制权还给ECU,Return Control To ECU。

01是复位为默认值,Reset to Default。

02是冻结当前的状态,Freeze Current State。

03是短暂接管控制权,Short Term Adjustment。

若控制类型是00-02这三种,请求报文是4个字节。

若控制类型是03,请求报文的第五字节是控制代码,可以是数字量,比如01是开,00是关;也可以是模拟量,比如空调风门的开度。

uds 026
2F服务,黄色区域为2个字节的DID

上面这个图可以理解为,关闭开关,之后打开开关,之后控制权还给ECU,之后想复位回默认值,但是发现ECU不支持。这里NRC用0x22是否准确,还望大神告知。

2F服务有一个问题,如果通过2F服务修改了某个值,后续也不把控制权还给ECU,那么这个修改的有效时间是一直持续下去?

正确的做法是如果扩展会话超时,即切回默认会话,此时控制权应还给ECU,毕竟 2F的03子功能是"暂时接管控制权"。

6种模式的配置

非默认会话在实际中又细分为编程会话(Programming Diagnostic Session)和扩展会话(Extended)。在UDS的实际应用中,我们需要对26种服务针对不同会话、不同寻址模式的支持度进行配置。

也就是说,物理寻址+默认会话、物理寻址+编程会话、物理寻址+扩展会话、功能寻址+默认会话、功能寻址+编程会话、功能寻址+扩展会话,共6个模式。那么我们可以脑补一个26行、6列的表格了。

举个例子,对于10、11、3E、22(22有分歧)服务,它们需要支持所有的6个模式(物理+功能寻址)。

对于14、19服务,DTC相关,要求支持默认+扩展会话的4个模式(物理+功能寻址)。

对于27服务,即安全访问服务,仅支持扩展+物理、编程+物理2个模式。

对于2E、2F服务,仅支持扩展+物理1个模式,且要求安全等级为1

对于34、36、37服务,涉及程序下载,仅支持编程+物理1个模式,且要求安全等级为2

对于28、85服务,有些要求支持编程+扩展会话的4个模式,有些则要求仅支持扩展会话的2个模式。

对于31服务,要求安全等级为1,有些要求支持扩展+物理、编程+物理2个模式,有些则要求仅支持扩展+物理1种模式。

抑制肯定响应指示位的配置

抑制肯定响应指示位(Suppress Positive Response Message Indication Bit)顾名思义,这个位是用来抑制肯定响应的。即本应回复肯定响应帧,但是发出方要求对方静默,不需要对方回复肯定响应。这个位的位置和子服务在同一个字节(应用层数据第二字节),为bit7,高位。

比如SID是0x10,子服务是0x01,如果是抑制肯定响应的话,子服务这个字节要改成0x81。这样发下去ECU就不会回复肯定响应了。

通常,10、28、3E、85服务是需要支持抑制肯定响应这个功能的。11服务部分厂家也是要求支持的。

Read 13003 times Last modified on Sunday, 12 April 2020 00:59