三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

AUTOSAR架构下UDS诊断服务的实现、配置与工程实践

AUTOSAR架构下UDS诊断服务的实现、配置与工程实践

1. 项目概述:AUTOSAR与UDS诊断的深度耦合

在汽车电子开发领域,尤其是嵌入式软件工程师的日常工作中,AUTOSAR和UDS诊断是两个绕不开的核心话题。前者是汽车软件架构的“宪法”,定义了从应用层到基础软件的标准化接口与模块化设计;后者则是车辆与外部诊断仪沟通的“世界语”,规定了从读取故障码到刷写程序的标准化服务。当我们将两者结合,谈论“AUTOSAR-UDS诊断”时,我们实际上是在探讨如何在AUTOSAR这一标准化框架下,高效、可靠地实现符合ISO 14229标准的统一诊断服务。这不仅仅是功能的堆叠,更是架构、通信、内存、调度等多维度的深度集成。对于开发者而言,理解这种集成背后的设计哲学与实现细节,意味着能够驾驭从需求分析到代码落地的完整链条,避免在复杂的模块交互中迷失方向。无论是负责应用层诊断功能开发的软件工程师,还是负责底层通信栈配置的ECU工程师,亦或是进行系统集成的测试工程师,掌握AUTOSAR-UDS诊断的脉络都至关重要。它直接关系到诊断功能的可靠性、ECU软件的可维护性,以及最终车辆售后服务的效率与成本。

2. AUTOSAR架构下的诊断通信栈解析

2.1 分层模型与模块职责

AUTOSAR将整个软件架构进行了严格的分层,诊断功能贯穿其中。理解各层的职责是进行有效开发和问题排查的基础。最上层是应用层(Application Layer),这里的SWC(Software Component)通过端口(Port)和接口(Interface)来调用诊断服务,例如,一个电池管理SWC可能会请求读取某个电池电压相关的诊断数据。应用层不关心数据如何传输,它只发出服务请求并等待响应。

紧接其下的是运行时环境(RTE),它是AUTOSAR的核心,负责SWC之间以及SWC与基础软件(BSW)之间的通信。对于诊断而言,RTE将应用层的服务调用,路由到对应的基础软件模块。再往下就是复杂的基础软件层,诊断相关的主要模块包括:

  • DCM(Diagnostic Communication Manager,诊断通信管理器):这是UDS服务在AUTOSAR中的“大脑”。它负责接收来自通信接口(如CAN、LIN)的诊断请求,解析UDS报文(服务ID、子功能、数据),并调用相应的诊断服务处理程序。同时,它也负责构建符合UDS格式的肯定或否定响应,并下发回复。DCM内部实现了会话层、安全访问层等状态管理。
  • DEM(Diagnostic Event Manager,诊断事件管理器):它是故障信息的“管家”。负责存储、管理诊断故障码(DTC)、快照信息(Snapshot)和扩展数据(Extended Data)。当SWC或BSW模块检测到故障时,会通过接口报告给DEM,DEM则根据配置决定DTC的状态(待定、确认、已修复等),并可供DCM通过UDS服务(如0x19 ReadDTCInformation)读取。
  • FIM(Function Inhibition Manager,功能抑制管理器):这是一个与功能安全密切相关的模块。当某些诊断事件(DTC)发生时,DEM可以通知FIM,FIM则根据配置去抑制(关闭或降级)特定的SWC功能,以实现安全的故障响应。
  • 通信驱动与接口(如CanIf, LinIf, FrIf):这些模块负责与具体的总线控制器打交道,收发原始的报文数据。PDU Router(PduR)模块则像交通枢纽,负责在不同通信模块(如CanIf, Com)与上层模块(如DCM)之间路由协议数据单元(PDU)。

注意:在配置时,务必理清DCM与Com模块的交互。对于诊断报文,通常配置为绕过Com模块,由PduR直接将来自CanIf/LinIf的诊断PDU路由给DCM,以提高实时性和减少开销。这是AUTOSAR诊断通信的一个关键配置点。

2.2 诊断数据流与模块交互

一个典型的UDS请求-响应流程,例如通过CAN总线发送一个0x22(ReadDataByIdentifier)服务来读取车辆VIN码,其在AUTOSAR中的数据流是这样的:

  1. 接收:CAN控制器收到报文 -> CanDrv中断处理 -> CanIf传递原始L-PDU -> PduR根据配置的路由表,识别该L-PDU ID为诊断ID,将其路由至DCM模块。
  2. 处理:DCM接收到PDU,解析出服务ID 0x22和数据标识符(如VIN码对应的DID)。DCM检查当前会话状态、安全等级是否满足该服务要求。若满足,DCM调用与该DID绑定的应用层回调函数(RTE接口)或直接访问NvM中存储的VIN数据。
  3. 响应:应用层或NvM返回数据给DCM,DCM按照UDS标准格式组装肯定响应(0x62 + DID + 数据),并通过PduR、CanIf、CanDrv的路径,将响应报文发送回CAN总线。
  4. 事件记录:如果在处理过程中或应用层检测到错误(如DID不支持),DCM会组装否定响应码(NRC),并可能通过Det(Default Error Tracer)报告错误,或触发DEM记录相关DTC。

这个流程清晰展示了模块间的协作。配置错误常发生在PduR的路由配置、DCM的服务表与DID映射配置、以及RTE为SWC生成的诊断接口上。

3. 核心UDS服务在AUTOSAR中的实现与配置

3.1 诊断会话与安全控制(0x10, 0x27, 0x28, 0x85, 0x83)

这是诊断的“大门”和“锁”。在AUTOSAR中,这些服务的状态管理主要由DCM模块负责。

  • 0x10 Diagnostic Session Control:DCM内部维护一个会话状态机,通常包含默认会话(Default)、扩展诊断会话(Extended)和编程会话(Programming)等。不同会话下,可用的服务集合(通过Dcm_DspSessionControl配置)和通信时序参数(如P2Server_max)不同。从默认会话切换到非默认会话,是激活大多数诊断服务的前提。
  • 0x27 Security Access:安全访问服务用于解锁敏感操作(如刷写)。DCM负责处理“请求种子”和“发送密钥”的流程。关键在于“算法”的实现。AUTOSAR标准并未规定算法,这需要OEM或供应商自行实现。通常做法是,在Dcm配置中关联一个安全算法库(SecOC或自定义库),DCM在收到0x27 01子功能时,调用算法库生成一个随机种子;收到0x27 02子功能时,将收到的密钥传递给算法库进行验证。实操心得:算法的复杂度要平衡安全性与ECU算力。务必确保种子生成有足够的随机性(可利用硬件随机数发生器),并且算法本身和密钥存储要有防破解考量。
  • 0x28 Communication Control 与 0x85 Control DTC Setting:这两个服务控制诊断通信和DTC记录。它们的实现需要DCM与其他模块联动。例如,0x28服务关闭非诊断报文,需要DCM通知Com模块;0x85服务关闭DTC记录,需要DCM通知DEM模块。在配置时,需要正确设置这些模块间的关联和回调接口。

3.2 数据读写与内存操作(0x22, 0x2E, 0x23, 0x3D)

这些服务直接操作ECU内部数据,是诊断功能的核心。

  • 0x22 ReadDataByIdentifier / 0x2E WriteDataByIdentifier:在AUTOSAR中,每个DID(Data Identifier)都需要在Dcm模块中配置,并关联一个数据源。数据源可以是:
    • 直接回调函数:关联一个C函数,当服务请求到来时,DCM直接调用该函数获取或设置数据。
    • RTE接口:关联一个SWC提供的Runnable,通过RTE触发SWC内部的逻辑来提供数据。
    • NvM块:直接映射到NvM管理的非易失性数据块,如VIN码、标定数据。配置要点:必须仔细配置DID的长度、读写权限、以及在不同诊断会话下的可用性。对于0x2E写服务,通常还需要配置数据验证函数,确保写入的数据在合理范围内。
  • 0x23 ReadMemoryByAddress / 0x3D WriteMemoryByAddress:这两个服务允许直接读写内存地址,功能强大但危险,通常仅在编程会话下可用。在AUTOSAR中实现时,安全是首要考虑。除了会话和安全访问控制,还必须进行内存地址范围检查,防止越界访问导致系统崩溃。通常需要配置一个允许访问的内存区域表,并在DCM中调用地址验证函数。

3.3 输入输出控制与例程(0x2F, 0x31)

  • 0x2F InputOutputControlByIdentifier:此服务用于替代ECU正常的输入信号或控制其输出,常用于产线测试或售后检修。在AUTOSAR中实现,关键在于“控制权”的切换。例如,控制一个PWM输出引脚。正常模式下,该引脚由某个SWC控制;当诊断仪发送0x2F服务请求控制时,DCM需要能通过RTE或其他机制,暂时“夺过”该引脚的控制权,并输出指定占空比。这通常需要硬件抽象层(Port、Dio)和驱动层(Pwm)的支持,以及一个清晰的状态机来管理正常模式与诊断覆盖模式的切换。
  • 0x31 RoutineControl:例程控制用于触发一个ECU内部的特定函数,例如擦除内存、执行自检、重置适配值等。在AUTOSAR Dcm中,每个例程ID(Routine Identifier)需要配置一个对应的回调函数。这个函数里可以包含任何需要的逻辑。注意事项:例程执行可能是耗时的。UDS协议要求ECU在P2Server_max时间内给出响应。对于长耗时例程,必须在例程开始时立即返回“0x31 01”的肯定响应(表明请求被接收),然后通过0x3E TesterPresent服务保持会话,并通过0x31 03(请求例程结果)子功能来查询执行进度和结果。这需要在应用层实现一个后台任务或状态机来管理例程的执行过程。

3.4 故障码与事件管理(0x19, 0x14)

这是与DEM模块交互最紧密的部分。

  • 0x19 ReadDTCInformation:这是最复杂的UDS服务之一,有多个子功能。DCM在收到该服务请求后,大部分子功能(如读取DTC状态、读取快照、读取扩展数据)都需要向DEM模块查询信息。因此,Dcm和Dem的配置必须完全匹配,特别是DTC编号(DTC Number)、故障类型(DTC Kind)、存储位置等。例如,配置一个DTC,需要在Dem中定义其属性(如老化机制、事件内存存储),同时需要在Dcm中配置该DTC对诊断仪是否可见以及关联的DID。
  • 0x14 ClearDiagnosticInformation:清除DTC信息。DCM收到请求后,会调用Dem的清除接口。这里的关键点是“清除范围”的配置。可以清除所有DTC,也可以清除特定DTC组。在AUTOSAR Dem中,DTC可以分组配置,这需要与整车厂的诊断规范严格对齐。

4. 基于AUTOSAR工具链的UDS诊断开发实战

4.1 需求分析与诊断规范导入

开发始于一份详细的诊断需求规范(通常由OEM提供,格式可能是ODX、CDD或Excel)。这份规范定义了该ECU需要支持的所有UDS服务、会话参数、安全算法、DID列表、DTC列表、例程等。现代AUTOSAR配置工具(如Vector的DaVinci Configurator & Developer, ETAS的ISOLAR-A/B)都支持直接导入ODX或CDD文件。强烈建议使用此功能,它能自动生成Dcm、Dem、PduR等模块的大量基础配置,避免手动输入带来的错误,并确保与规范的一致性。导入后,务必进行人工核对,检查服务映射、DID/DTC参数、通信参数等关键项是否正确。

4.2 DCM模块深度配置要点

工具导入提供了骨架,但血肉仍需手动填充和调整。

  • 服务配置(DcmDspService):检查每个UDS服务(SID)是否已正确创建。重点配置其可用会话(Session)、安全等级(Security Level)以及响应行为(如是否支持抑制肯定响应位SuppressPosRspMsgIndicationBit)。
  • DID配置(DcmDspData):为每个DID配置其长度、读写属性、数据源。如果数据源是回调函数,需要在这里关联函数名。如果数据源是NvM,需要关联NvM Block ID。一个常见的坑:DID的数据长度定义必须与实际数据源的长度完全一致,否则会导致响应报文长度错误。
  • 会话与安全配置:配置各个诊断会话(如默认、扩展、编程)的定时参数(P2Server_min, P2Server_max, P2*Server_max)。配置安全等级与算法的映射关系。这里需要填入你实现的算法库的接口函数。
  • 路由配置(与PduR关联):这是通信畅通的关键。确保Dcm已经正确添加了对应的诊断Pdu,并且PduR模块中配置了从CanIf/LinIf到Dcm的完整路由路径,且诊断报文的寻址方式(物理寻址/功能寻址)配置正确。

4.3 DEM模块配置与DTC管理

DEM的配置相对独立但至关重要。

  • 事件内存配置:配置DEM事件内存的大小,它决定了能存储多少个DTC实例。需要根据诊断规范中DTC的数量和快照数据大小来合理估算。
  • DTC属性配置:为每个DTC配置其状态位(如testFailed, confirmed, testNotCompletedSinceLastClear等)的管理策略、老化算法(aging)、存储周期等。快照记录和扩展数据记录也需要在此关联相应的数据元素和触发条件。
  • 使能条件配置:配置DTC在什么条件下可以被检测和存储(例如,依赖特定的诊断会话或DTC设置状态)。这通常与0x85服务联动。

4.4 代码生成与集成

配置完成后,使用工具生成BSW模块的配置代码(C语言头文件和源文件)。对于DCM、DEM等模块,工具会生成完整的、符合AUTOSAR接口规范的代码框架。开发者的主要工作集中在:

  1. 实现回调函数:对于0x22/0x2E服务的DID数据访问、0x31服务的例程、0x27服务的算法等,需要根据工具生成的头文件中声明的函数原型,实现具体的业务逻辑。
  2. SWC诊断接口实现:如果诊断功能由应用层SWC实现,需要在SWC中定义供RTE调用的Runnable,并在工具中完成SWC与RTE、RTE与BSW的端口连接配置。
  3. 初始化与集成:将生成的BSW代码、你自己实现的回调函数代码、以及其他的MCAL(微控制器抽象层)代码、OS代码一起编译链接。确保在Dcm_InitDem_Init等初始化函数中,正确传递了所有配置好的参数结构体。

5. 诊断测试、问题排查与性能优化

5.1 测试策略与常用工具

开发完成后,系统化的测试是保证诊断功能质量的唯一途径。

  • 单元测试/模块测试:使用Cantata、Tessy等工具或自写测试桩,对DCM/DEM的回调函数、安全算法等进行白盒测试。
  • 集成测试:在HIL(硬件在环)台架或真实ECU上,使用诊断测试工具进行黑盒测试。常用工具有:
    • Vector CANoe/CANape:行业标杆,功能强大,支持CAPL编程进行自动化测试,能直接导入ODX数据库,自动生成测试用例。
    • PEAK PCAN-UDS:性价比高,适合中小团队。
    • Intrepid Control Systems Vehicle Spy 3:灵活性强,协议支持广泛。
  • 测试重点
    1. 协议符合性:所有请求的响应格式、NRC码是否正确。
    2. 会话与安全:会话切换、安全访问的流程是否严密,非法请求是否被正确拒绝。
    3. 功能正确性:读写DID、清除DTC、控制IO、执行例程等功能是否达到预期。
    4. 鲁棒性:发送错误格式报文、异常时序报文、洪泛报文等,系统是否稳定,无内存泄漏或死锁。
    5. 时序与性能:响应时间是否满足P2/P2*时间要求,在总线负载高时诊断功能是否正常。

5.2 典型问题排查实录

在实际项目中,以下问题非常常见:

  • 问题一:诊断仪发送请求后无任何响应。
    • 排查思路
      1. 物理层/数据链路层:用示波器或总线分析仪确认报文是否真的被ECU接收?CAN终端电阻是否正确?波特率是否匹配?
      2. PDU路由:检查PduR配置,诊断报文的Rx Pdu是否正确路由到了DCM模块?可以在PduR代码中添加调试信息,打印收到的PDU ID。
      3. DCM服务表:确认请求的服务ID(SID)是否在当前的诊断会话下被启用?检查Dcm_DspService配置。
      4. 会话状态:ECU是否处于非默认会话?发送0x10 01切换到扩展会话再试。
  • 问题二:读取DID(0x22)返回否定响应NRC 0x22(条件不满足)。
    • 排查思路
      1. 会话与安全:该DID是否要求特定的诊断会话或安全等级?用0x10和0x27服务确认当前状态。
      2. DID配置:在Dcm配置中,检查该DID是否正确定义,且关联的数据源(回调函数或NvM块)是否存在且可访问。
      3. 回调函数:如果数据源是回调函数,检查该函数是否被正确实现和链接。函数内部是否有条件判断导致返回失败?添加调试日志。
  • 问题三:清除DTC(0x14)后,马上读取(0x19)发现DTC状态未清除。
    • 排查思路
      1. DEM配置:检查该DTC在DEM中的“存储条件”和“清除条件”配置。是否配置了不允许清除?或者清除后,故障条件依然满足,导致DTC立即被重新存储?
      2. 依赖事件:该DTC是否依赖于其他事件或条件?主事件未清除,从属DTC也无法清除。
      3. NvM操作:DTC信息可能存储在NvM中。清除操作后,DEM是否成功写入了NvM?检查NvM的写入回调或错误状态。

5.3 性能优化与资源管理

诊断功能在资源受限的嵌入式系统中运行,需要精心优化。

  • 内存优化
    • 诊断缓冲区:DCM内部有用于组装请求和响应的缓冲区。根据最长的诊断请求/响应PDU长度来合理配置缓冲区大小,避免浪费。
    • DEM事件内存:根据DTC数量和快照数据大小精确计算所需内存,可采用分级存储策略,重要DTC存储完整快照,次要DTC只存储状态。
  • CPU负载优化
    • 中断处理:诊断报文接收在CAN/LIN中断中处理,应保持中断服务程序(ISR)简短,仅做接收和放入队列操作,复杂的解析交给DCM的主函数(如Dcm_MainFunction)处理。
    • 主函数周期:合理设置Dcm_MainFunction的调用周期。周期太短增加CPU负载,周期太长可能导致响应超时。需要根据P2Server_min时间和总线负载来权衡。
    • 长耗时操作异步化:对于0x31例程、0x2E写入NvM等耗时操作,一定要采用异步模式,避免在DCM上下文中长时间阻塞,影响其他诊断请求的处理。
  • 通信优化
    • 功能寻址与广播:谨慎使用功能寻址和广播,避免网络风暴。
    • 流控与多帧传输:对于长数据(如0x23读内存),ISO-TP流控参数(BS, STmin)要设置合理,平衡传输效率和总线负载。

6. 进阶话题:Autosar与UDS诊断的未来挑战

随着汽车电子架构向域控制器和中央计算平台演进,AUTOSAR-UDS诊断也面临新的挑战和机遇。

  • Adaptive AUTOSAR与诊断:Classic AUTOSAR(CP)主要面向实时性强的微控制器,而Adaptive AUTOSAR(AP)面向高性能处理器,支持POSIX操作系统和更复杂的应用。在AP平台上,UDS诊断如何实现?一种常见架构是,在AP侧运行一个诊断代理(Diagnostic Agent),它通过ARA::COM等机制与CP侧的传统DCM通信,或者直接实现一个面向服务的UDS/DoIP(Diagnostic over IP)服务器。这带来了跨域诊断、服务发现等新问题。
  • 网络安全与SecOC:传统的0x27安全访问算法可能不足以应对日益严峻的车载网络安全威胁。AUTOSAR SecOC(Secure Onboard Communication)模块为安全通信提供了基础,未来诊断通信,特别是刷写(0x34, 0x36, 0x37服务)和关键数据访问,可能会与SecOC深度集成,实现基于密码学的身份认证和报文新鲜性验证。
  • OTA与诊断:空中升级(OTA)极大地依赖诊断协议(尤其是0x34, 0x36, 0x37, 0x31服务)。在AUTOSAR框架下实现OTA,需要将下载管理器、Flash驱动、诊断通信、安全加密等模块紧密协同。如何设计一个支持断点续传、滚动升级、安全验证的OTA诊断流程,是当前的热点。
  • 工具链与自动化:手动配置复杂的诊断栈效率低下且易错。未来的趋势是更强大的工具链,能够从系统级设计(SysML)自动生成或无缝对接诊断配置,并实现测试用例的自动化生成和回归测试,形成需求-设计-实现-测试的闭环。

我个人在实际项目中的体会是,AUTOSAR-UDS诊断开发是一个“三分编码,七分配置和调试”的工作。对标准的深刻理解、对工具链的熟练使用、以及一套严谨的测试排查方法,远比写出精巧的代码更重要。初期多花时间在需求分析和配置验证上,后期就能省下大量的调试时间。另外,建立一份详尽的、团队共享的诊断问题排查手册,记录下每一个踩过的坑和解决方案,这对于团队能力提升和项目效率提升是无价的。最后,永远不要忽视最底层的通信:当一切诊断逻辑都看似正确却不通时,回头用最原始的工具去看看总线上的波形和原始报文,往往会有意想不到的发现。

← 返回列表