【ETAS CP AUTOSAR基础软件】DCM模块详解(诊断)

news2024/9/21 4:39:12

文章包含了AUTOSAR基础软件(BSW)中DCM模块相关的内容详解。本文从ISO标准,AUTOSAR规范解析,ISOLAR-AB配置以及模块相关代码分析四个维度来帮读者清晰的认识和了解DCM这一基础软件模块。文中涉及的ISOLAR-AB配置以及模块相关代码都是依托于ETAS提供的工具链来配置与生成的,与AUTOSAR规范之间可能会有些许的出入,但总体的功能要点与处理流程都应该是一致的。

DCM模块是汽车诊断的一个部分,这个部分主要包含了基于AUTOSAR通信栈的报文处理以及会话和安全等级管理,标准的网络层和会话层以及部分应用层都在这里实现,包括DID的读取,写入,控制也在这里实现。文章首先介绍了何为诊断,其次以IOS-15765以及ISO-14229基础介绍了DCM涉及的部分标准,再次解析了AUTOSAR规范DCM部分内容,然后基于ISOLAR讲述了完整的DCM配置过程,最后介绍了DCM相关的代码。

目录

诊断概述

ISO-15765与ISO-14229 

缩写与术语

网络层 

应用层 

10服务

11服务

27服务

28服务

3E服务 

22服务 

2E服务 

2F服务 

31服务 

AUTOSAR规范解析 

概述

总体设计元素

DCM子模块

否定响应码 

非易失数据

Diagnostic Session Layer (DSL)

Diagnostic Service Dispatcher (DSD)

Diagnostic Service Processing (DSP)

ISOLAR-AB配置

导入诊断报文

DCM

DcmGeneral

DcmRbGeneral 

DcmDslBuffer 

DcmDslDiagResp

DcmDslProtocolRow 

DcmDslMainConnection 

DcmDslProtocolRx 

DcmDslProtocolTx

DcmDsd 

DcmDsdServiceTable 

DcmDsp

DcmDspSecurity 

DcmDspSecurityRow 

DcmDspSession

DcmDspSessionRow 

DcmDsdService 

DcmDspComControlAllChannel

DcmDspCommonAuthorization 

DcmDspData

DcmDspDidInfo

DcmDspDid 

DcmDspRoutine

DcmPageBuffercfg 

CanTp

CanTpGeneral

CanTpChannel 

CanTpRxNSdu 

CanTpTxNSdu 

Components 

System 

RTE 

代码解析 

动态配置代码

集成代码

静态代码


诊断概述

汽车诊断的作用,就是在不对车进行进行解体的情况下,检查车的状况,如果有故障则可以通过汽车诊断来查明故障部位及原因。具体的操作过程需要通过诊断仪连接到汽车的OBD口读取车况信息,下图为博世的一款诊断仪。

诊断仪的另一端连接汽车的OBD口,一般在主驾的膝盖位置。

下图为OBD的引脚定义。

完成诊断仪和汽车的连接之后,检修人员就能够在诊断仪的屏幕获取车辆的数据信息,诊断仪和汽车之间的通信遵循特定的通信协议,针对OSI(Open System Interconnect)七层模型,诊断协议标准分别定义了各层实现的相关内容。

本文介绍的是UDS on CAN的诊断协议,也就是说物理层和数据链路层都是CAN,可以看到诊断也可以基于LIN或者FlexRay等物理链路层来实现,本文不介绍物理层和数据链路层的具体实现,着眼介绍在CAN总线上发生的诊断活动。

诊断协议对数据链路层会建议对于CAN帧中未使用字节通过某个特定值如0xAA进行填充,防止连续传输相同比特值导致的位填充。


ISO-15765与ISO-14229 

缩写与术语

  • ECU:Electronic Control Unit,电子控制单元。
  • ISO:International Standards Organization,国际标准组织。
  • EOL:End Of Line,产品下线。
  • SF_DL:Single Frame Data Length,单帧数据长度。
  • FF_DL:First Frame Data Length,第一帧数据长度。
  • SN:Sequence Number,帧序号。
  • FS:Flow Status,流控制状态。
  • BS:Block Size,块大小。
  • STmin:Minimum Separation Time,最小连续帧时间。
  • SID:Service Identifier,服务标识符。
  • DTC:Diagnostic Trouble Code,故障诊断码。
  • DID:Data Identifier,数据标识符。
  • NRC:Negative Response Code,否定影响标识符。

网络层 

下图示意诊断仪连接到汽车。

由上图可以看出,诊断仪为客户端,汽车(ECUs)为服务端。诊断仪发起请求,ECUs回复。这里就有有一个问题,汽车上有很多ECU都挂接到了一个CAN线上,怎么区分诊断仪请求的ECU是哪个?UDS on CAN通过CAN帧的帧ID来区分,Physical Request CAN ID(物理寻址)的请求针对的是某个具体的ECU,Functional Request CAN ID(功能寻址)的请求则针对某一类ECUs。很多UDS服务只支持物理寻址,功能寻址并不能访问。

经典CAN有8个字节,每一帧最大只能传输8个字节的数据,上层网络要想通过CAN帧来传递信息就会出现两种情况,有些消息长度很短,只需要CAN的一帧就可以解决;而有些消息长度很大,无法通过CAN的一帧来完整传输,那么就需要将该消息按照一定规则进行分割成若干个CAN帧进行传输。ISO15765-2为实现上一目标将CAN帧分成了以下四种类型。

  • SingleFrame (SF):单帧,第一个字节的高四位为0,低四位为接下来要传输的数据长度,后7个字节为要传输的数据。
  • FirstFrame (FF):首帧,第一个字节的高四位为1,第一个字节低四位与第二个字节合起来为接下来连续帧要传输的数据长度,从第三个字节byte2至最后一个字节byte7为首帧传输数据。
  • ConsecutiveFrame(CF):连续帧,第一个字节的高四位为2,第一个字节的低四位为连续帧编号(SN),表示当前连续帧的顺序,第一条连续帧的SN=1,后面每发出一帧连续帧SN加1,范围0~15,当SN=15时,下一条连续帧重新变成0。第二个字节byte1至最后一个字节byte7为剩余的数据。首帧已经传输了6个字节,则接下来就是通过连续帧继续传输剩下的数据。
  • FlowControl (FC):流控帧,第一个字节高四位为3,低四位为FlowSttatus(FS),第一个字节为BlockSize(BS),第二个字节为SeparationTimeMin(STmin),作用在于接收端告知发送端接收能力。
    • FS:0代表继续发送连续帧,1代表等待下一帧流控帧,3代表首帧说明的数据大小溢出。
    • BS:0代表发送端可以一致发送至数据发完,不必再等待流控帧,01~FF指示这个流控帧生效的连续帧数,发送端应发送完对应数量的连续帧之后等待新的流控帧。
    • STmin:表示发送端发送连续帧的最小间隔时间,00~7F,对应范围为0ms~127ms;F1~F9,对应范围为100us~900us。

单帧的发送过程比较简单,下图示例发送数据0x01~0x07到接收端的CAN帧数据。

多帧的发送过程就比较复杂了,如下图所示,是发送端利用多帧发送数据0x01~0x24,可以看出接收端通过流控帧实现了不同Block,不同STmin。

 

 ISO15765-2中还针对时间制定了严格的超时机制,在网络层中主要有如下几个时间参数:

  • N_As:发送端发送一条CAN消息的时间。
  • N_Ar:接收端发送一条CAN消息的时间。
  • N_Bs:发送端发送首帧后到接受到流控帧的时间。
  • N_Br:接收端收到首帧后到发送流控帧的时间。
  • N_Cs:发送端收到流控帧后到发送连续帧的时间。
  • N_Cr:接收端收下一个连续帧的时间。


应用层 

UDS协议是一种服务器-客户端交互模式,发送端发送请求,接收端返回响应。为了来实现这种通话模式,网络层负责的是数据的传输,而应用层则考虑的是服务的定义,所以ISO14229-1主要规定诊断服务定义以及应用层层面的超时控制。下面是应用层超时控制涉及的参数。

  • P2Client和P2Server是诊断仪(Tester)诊断请求与ECU响应间的时间间隔。
    • P2Client:在Tester成功发送诊断请求后等待ECU发送响应的超时时间,针对的是上位机Tester端。
    • P2Server:是ECU收到Tester请求报文后到发出响应的时间间隔,针对的是ECU端。
  • P2*Client与P2*Server是Tester收到否定应答NRC为78h的否定应答报文后等待的增强超时时间。
    • P2*Client:Tester在接收到ECU应答的NRC为0x78时,到收到ECU响应的单帧或首帧的超时时间,在收到0x78的NRC时,Tester将重置定时器到新的增强超时时间。
    • P2*Server:在ECU发出NRC为0x78的响应后,到ECU开始答复请求的时间要求,即需要在该时间段内响应上位机请求或再次发送0x78的NRC,再次重新计时。
  • P3Client_Phys与P3Client_Func诊断仪连续请求的时间间隔。
    • P3Client_Phys:Tester从成功发送物理寻址开始计时到下一次发送物理寻址的时间间隔 ,一般为P2Server_max。
    • P3Client_Func:Tester从成功发送功能寻址开始计时到下一次发送物理寻址的时间间隔 ,一般为P2Server_max。
  • S3Client与S3Server。
    • S3Client:发送下个TesterPresent(0x3E)以保持在非默认会话模式的时间。
    • S3Server:保持在非默认会话下的超时时间,超时后返回默认会话模式 。

UDS定义的诊断服务如下表所示。

下面针对后边涉及的相关诊断服务,进行说明。这里介绍的诊断服务是除了Boot升级程序以及DTC故障码相关的服务,这两类服务会在介绍Boot以及DEM模块时再具体讲解。


10服务

10服务用于控制诊断会话状态,不同的会话状态对应不同的服务访问权限,比如28服务在Default会话一般不能访问。

下图是三种模式之间的切换的示意图。可以看到编程模式没有切换到别的模式路径,一般切换到编程模式之后要不重新刷写程序重启,要么从Boot跳转APP重新初始化了DCM。

下图是两个10服务的实例,首先Tester发送了10 01,10是服务号,01是子功能,表示切换到默认会话。02为编程会话,如果ECU要做在线升级,那么首先就要切换到编程会话,03为扩展会话,这个会话一般会放一些读写数据或者控制外围设备的操作。

ECU回复报文50 01 00 32 01 F4,首先,50是10+0x40后的响应,所有服务的ID响应报文都是服务ID+0x40,01是对应的请求子服务,00 32和01 F4是P2Server_max和P2*Server_max,用于告知Tester其网络层能力。

下面这个是Tester发送错误请求的例子,它请求了错误的66子服务,ECU不认识,回复了7F 10 12,7F是否定响应服务标识符,表示回复的是一个否定响应,10是否定响应的请求ID,12为否定响应标识符(NRC)。

服务涉及的NRC标识符含义如下,可以看到0x12为子服务不支持。


11服务

11服务是重启的服务,诊断仪可以通过这个服务要求ECU重启,11服务也是有子功能的,如下图。

重启的具体行为需要上层应用决定,DCM在收到复位指令之后会根据子服务调用不同的上层实现,可以是看门狗复位,也可以是芯片自身提供的复位指令,也可以是电源断电复位。下图为实例。

可以看到诊断仪给Tester发送了02 11 01,其中02表示的是单帧+数据长度。11 01为对应的服务和子服务信息。诊断仪恢复了02 51 01,51 01即为11 01的正响应。

下图是长度不正确的实例。可以看到回复的NRC为13。

下面是11的NRC说明。


27服务

安全访问服务,这个服务用于在修改ECU关键参数和升级的时候使用,比如写汽车的VIN码之前。下图为子服务说明,ECU一般涉及两个安全等级,安全等级1一般用于应用程序运行时修改关键参数,安全等级3用于升级程序。

下图为实例, 可以看到Tester发送10 03首先进入扩展会话,ECU回复正响应之后,Tester发送27 01请求安全等级为1的种子,ECU回复的Seed为03 04 0A 01,然后Tester拿到种子经过计算之后发送密钥给ECU,如果密钥正确,则会回复正响应67 02。

下图是涉及的否定响应码,可以看到如果在接收到请求密钥子功能前没有先接收到请求种子报文,发送24。如果接收到密钥值与ECU内部存储或计算的密钥不相等,发送35。


28服务

通信控制服务,涉及的子服务如下图。它们用于使能和禁止通信。

28服务在子服务后边还会跟一个字节指示对应的控制通信的类型,可以看到控制的通信都是应用层以及网络管理报文,底层涉及通信的模块(XCP、DCM)还能正常。

下图为28服务的实例。首先Tester发送10 03进入扩展会话,然后发送28 00 03 能够使能应用和网络管理的报文发送与接收,而后又发送28 03 03,禁用了应用和网络管理的报文发送与接收。这个服务可以帮助我们在调试时,排除一些干扰报文。

下图为28服务涉及的NRC。


3E服务 

诊断仪在线服务,主要目的就是告知ECU,诊断仪正在与ECU连接,因为ECU在非默认会话的时候,内部有计数器,超时就会跳回到默认会话中,如果诊断仪以小于超时时间为周期发送3E,则会让ECU维持在当前的会话状态。下图为对应的子服务。

下图为具体的3E服务实例。


22服务 

DataByldentifier简称DID,意思为用一个数字标识的数据,22服务下可以访问众多用户自定义的DID。比如0xF190对应的是VIN码,ISO 14229-1定义了一些DID,当然,主机厂可以根据自己的情况自定义。

22服务没有子服务,下面是22服务的一个实例。读取的DID为FA 00,读取到的数据为03。

22服务支持的NRC如下。


2E服务 

22服务是读DID,2E服务是写DID。2E服务没有子服务,下面是一个具体的实例,DID为F1 99 写入01 02 03,使用22服务读取的结果也是01 02 03。

服务支持的NRC有:


2F服务 

2F服务是用来完成输入输出控制,他也是通过DID来区分要控制的东西。这个命令可以在DV实验或者ECU已经上车之后,需要测试某个具体的功能,不方便使用调试器等工具了,就可以使用这个服务。2F服务没有子功能。

下面是2F服务的一个实例,Tester首先发送10 03进入扩展会话,然后2F服务访问F0 13这个DID,参数是03 00 00。ECU接收到这个命令,首先解析DID,然后获取参数,进行对应的输入输出控制,下面的例子ECU返回了个不支持这个DID的负响应,正响应应该是6F F0 13。

下面是该服务支持的NRC。


31服务 

31服务是例程控制,主机厂可以利用这个服务完成EOL的某些功能,包括下线标定,校准,钥匙配对等动作。下面是服务涉及的子服务。

下图为ISO 14229-1对这三个子服务的解释。

下图是32服务的实例,先使用10 03进入扩展会话,然后使用31 01启动FF 01对应的例程,下面的例子ECU回复了NRC为33的负响应,正响应应该为71 01 FF 01 00。其中最后的字节00为制造商自定义的ECU返回的一些附加信息。


AUTOSAR规范解析 

概述

Dcm规范描述了AUTOSAR基本软件模块Dcm(Diagnostic Communication Manager)的功能API和配置。Dcm模块为诊断服务提供了通用API。DCM模块的功能在开发、制造或服务过程中由外部诊断工具(诊断仪)使用。

Dcm模块确保诊断数据流和管理诊断状态,特别是诊断会话和安全状态。此外,DCM模块根据诊断状态检查是否支持诊断服务请求以及是否可以在当前会话中执行服务。 

 在AUTOSAR体系结构中,诊断通信管理器位于通信服务(服务层)中。

Dcm模块与通信无关。所有通信特定功能(如CAN、LIN、FlexRay或MOST等通信的实现)都在Dcm模块之外处理。PDU路由器(PDUR)模块为Dcm模块提供了与网络无关的接口。Dcm模块接收来自PduR模块的诊断消息。Dcm模块在内部处理和检查诊断消息。作为处理诊断请求的一部分,DCM将与其他BSW模块或SW-Components(通过RTE)交互以获取请求的数据或执行请求的命令。这种处理是非常特定于服务的。通常,Dcm将收集到的信息集合起来,并通过PduR模块发送回消息。


总体设计元素

DCM子模块

为了定义Dcm模块的功能,AUTISAR将Dcm模块建模为由以下子块组成:

  • 诊断会话层(Diagnostic Session Layer,DSL)子模块:DSL子模块确保与诊断请求和响应有关的数据流,监督和保证诊断协议的时序,管理诊断状态(特别是诊断会话和安全)。
  • 诊断服务分派器(Diagnostic Service Dispatcher,DSD)子模块:DSD子模块处理诊断数据流:
    • 通过network接收新的诊断请求,并将其转发给数据处理器。
    • 当由数据处理器(DSP子模块)触发时,通过network传输诊断响应报文。
  • 诊断服务处理(Diagnostic Service Processing DSP)子模块:DSP子模块处理实际的诊断服务(各自的子服务)请求。

下图概述了Dcm模块中的子模块DSP、DSD和DSL之间以及对外模块的接口。注意这些子模块的实现和它们之间的接口不是强制性的。引入它们只是为了提高此规范的可读性。

否定响应码 

ISO标准规定了UDS服务和OBD服务的负响应代码(NRC)。DcmSWS在Dcm和其他BSW模块以及SW-Cs之间的接口中使用这些NRC。这些NRC是在数据类型DcmNegativeResponseCodeType中定义的。

非易失数据

Dcm的几个特性需要初始化非易失性信息。AUTOSAR没有说明如何访问这些信息,或者在Dcm初始化时这些信息是否已经可用。因此,对非易失性信息的访问是实现的具体问题,必须在集成过程中加以确保。


Diagnostic Session Layer (DSL)

DSL子模块的所有功能应符合ISO14229-1规范和与网络无关的IS015765-3规范部分。 DSL子模块提供以下功能:

  • 会话控制(符合ISO14229-1与ISO 15765-3 [4]标准)。
  • 应用层时序处理(符合ISO14229-1与ISO 15765-3 [4]标准)。
  • 诊断相应行为的实现(符合ISO14229-1与ISO 15765-3 [4]标准)。
  • 每个诊断连接的安全验证状态处理。
    • 为每个连接提供安全验证状态管理。
    • 管理安全验证状态转换。

DSL与其他模块有以下交互:

  • PduR module
    • PDUR模块提供传入诊断请求的数据。
    • DSL子模块触发诊断响应的输出。
  • DSD submodule
    • DSD子模块将传入请求通知DsD子模块并提供数据。
    • DSD子模块触发诊断响应输出。
  • SW-Cs / DSP子模块
    • DSL子模块提供对安全性和会话状态的访问。
  • ComM module
    • DSL子模块保证ComM模块所需的通信行为。

Diagnostic Service Dispatcher (DSD)

DSD子模块负责检查传入诊断请求的有效性(诊断会话/安全访问级别/应用许可的验证),并跟踪服务请求执行的进度。处理有效的请求并拒绝无效的请求。子模块涉及以下相关用例:

  • 接收请求消息并传送正响应消息:这是正常通信(“乒乓”)的标准用例。服务器接收诊断请求消息。DSD子模块保证了请求消息的有效性。在这个用例中,请求是有效的,响应将是肯定的。请求将被转发到DSP子模块中相应的数据处理器。当数据处理器完成所有数据处理操作后,它触发由DSD子模块发送响应消息。
  • 接收请求消息并且抑制正响应:这是前一个用例的子用例。在UDS协议中,可以通过在请求消息中设置一个特殊位来抑制正响应。这种特殊的抑制处理完全在DSD子模块中执行。
  • 接收请求消息且抑制负响应:在功能寻址的情况下,DSD子模块应抑制NRC0x11、0x12、0x31、0x7E和0x7F。
  • 接收请求消息并且传送负响应消息:拒绝请求消息和发送否定响应有许多不同的原因。如果诊断请求无效或在当前会话中可能无法执行请求,则DSD子模块将拒绝请求并返回否定的响应。DSP子模块将触发一个负响应,其中包括一个NRC,该NRC将提供更多信息,说明为什么该请求被拒绝。
  • 直接发送肯定响应消息:UDS协议中有两个服务,一个请求发送可能会对应多个响应。这些服务是:
    • ReadDataByPeriodicIdentifier (0x2A): 此服务允许客户端请求从服务器定期传输一个或多个periodicDataIdentifiers.。
    • ResponseOnEvent (0x86):此服务请求服务器启动或停止传输对指定事件的响应。
  • 分段响应:在诊断方案中,一些服务允许交换大量的数据,例如UDS服务读取DTC信息(0x19)和UDS服务传输数据(0x36)。在传统方法中,ECU内部缓冲区必须足够大,以保存要交换的最长数据消息(最坏的情况),并且在启动传输之前填充完整的缓冲区。ECU中的RAM存储器通常是一个关键资源,特别是在较小的微处理器中。在更节省内存的方法中,缓冲区只被部分填充,部分传输,然后部分重新填充,依此类推。这种分页机制只需要显著的内存量,但需要一个定义明确的缓冲区重新填充的反应时间。用户可以决定是使用linear buffer或者paged-buffer。当接收到诊断消息时,DSL子模块调用DSD子模块。DSD子模块执行以下操作:
  • 将请求的处理委托给DSP子模块或Dcm外的外部模块跟踪请求处理。
  • 跟踪请求处理,处理处理函数的返回状态。
  • 将诊断的响应传输到DSL子模块(传输功能性)。

最后总结一下DSD与DSL的主要功能交互:

  • DSD子模块到DSL子模块:获取当前的诊断会话和安全级别。
  • DSL子模块到DSD子模块:诊断信息传输的确认。

DSD与DSP的主要功能交互如下:

  • DSD子模块到DSP子模块:委托处理请求与诊断信息传输确认。
  • DSP子模块到DSD子模块:发出信号表示处理已完成。

Diagnostic Service Processing (DSP)

当从DSD子模块接收到要求DSP子模块处理诊断服务请求的函数调用时,DSP始终执行以下基本处理步骤:

  • 分析接收到的请求消息。
  • 检查格式以及是否支持寻址子函数。
  • 在DEM、SW-Cs或其他BSW模块上获取数据或执行所需的函数。
  • 构建服务响应

DSP子模块将在执行所请求的命令之前检查适当的消息长度和结构。当对请求消息的分析导致格式化或长度错误时,DSP子模块应触发NRC0x13(错误消息长度或无效格式)的负响应。

DSP子模块应根据响应服务标识符构建响应消息并确定响应消息长度。

除非指定了另一个特定NRC,否则当执行服务的API调用未返回OK时,DSP子模块应触发NRC0x10(一般拒绝)的负响应。当对请求消息的分析导致出现其他不支持的消息参数时,DSP子模块应触发NRC0x31(请求超出范围)的负响应。


ISOLAR-AB配置

导入诊断报文

导入诊断报文如下图所示。

点击 导入DBC,如下图所示两收一发。

之后使用RTA-BSW下的Automatically Configure BSW from System Description生成通信栈相关配置之后,就可以在配置DSL时引用到相关报文。


DCM

DcmGeneral

这个容器配置的是一些DCM的通用配置,如下图所示。


DcmRbGeneral 

该容器需要关心的配置如下:

  • DcmRbsuppressNRC:此参数用于配置当诊断请0求收到时,支持回复的NRC值。下图实例中配置了:
    • 11:服务不支持。
    • 12:子服务不支持。
    • 31:请求报文中包含的参数值超出了授权范围。
    • 7E:ECU在当前的会话模式下不支持请求的子服务,所以请求的动作不能被执行。
    • 7F:ECU在当前的会话模式下不支持请求的服务,所以请求的动作不能被执行。
  • DcmRbconfirmForDSDGeneratedNegRes:如果设置为真,DSD在产生否定响应的时候会调用DcmAppl_DcmConfirmation DcmNegResp()来进行确认。
  • DcmRbosTimerUse:DCM内部Timer的节拍来源,实例中选择CyclicCount,则节拍来自Dcm_mainfunction的调用周期,计时原理为调用次数*调用周期。
  • DcmRbRTEsupport: 如果参数为真,通信管理,诊断会话控制以及ECU重启相关的Ports会被生成。
  • DcmRbStoringEnabled:使能存储诊断信息(跳转到Boot)。


DcmDslBuffer 

建立两个DslBuffer,一个用于发送,另一个用于接收,大小为1024Bytes。


DcmDslDiagResp

设置针对每个诊断请求,最大的0x78否定响应(ECU正忙,未准备好接收此请求),超过此限制将回复0x10否定响应(拒绝执行请求)。


DcmDslProtocolRow 

该容器包含一种诊断协议的参数配置,主要的配置如下:

  • DcmDslProtocollD:诊断协议选择,下面的实例选择的是UDS_ON_CAN,还可以根据需要选择OBD_ON_CAN以及UDS_ON_IP等。
  • DcmDslProtocolPriority:用作协议抢占优先级配置,0是最高优先级。
  • DcmTimStrP2ServerAdjust:前文提到的P2Server超时时间。
  • DcmTimStrP2StarServerAdjust:前文提到的P2*Server超时时间。
  • DcmDslProtocolRxBufferRef:协议接收Buffer,引用在DcmDslBuffer处定义的接收Buffer。
  • DcmDslProtocolSlDTable:协议涉及的服务列表,引用在DcmDsdServiceTable处定义的。
  • DcmDslProtocolTxBufferRef:协议发送Buffer,引用在DcmDslBuffer处定义的发送Buffer。


DcmDslMainConnection 

DSL与通信的连接信息,它引用的是之前将诊断报文导入的CAN控制器。


DcmDslProtocolRx 

引用物理以及功能寻址两个PduR2Dcm,连接到当前的诊断协议中。


DcmDslProtocolTx

引用ECU诊断回复的PduR2Dcm,连接到当前的诊断协议中。


DcmDsd 

这个容器包含两个参数:

  • DcmDsdRequestManufacturerNotificationEnable:OEM可以通过此选项使能/失能诊断请求通知机制。
  • DcmDsdRequestsupplierNotificationEnabled:供应商可以通过此选项使能/失能诊断请求通知机制。


DcmDsdServiceTable 

服务不支持回复NRC,建议与标准一致:0x7F


DcmDsp

建立DCM子模块,并配置DcmDspDataDefaultEndianness为大端。


DcmDspSecurity 

配置安全等级管理参数,主要涉及下面两个:

  • DcmRbDspSecurityStoreseed:是否保存Seed,这里选择否,种子由应用层函数生成。
  • DcmDspSecurityMaxAttemptCounterReadoutTime:单位为秒,从启动到诊断模块启动延时。


DcmDspSecurityRow 

安全等级定义,这里只有安全等级1的定义,等级3是Boot使用。下面是它的主要参数说明。

  • DcmDspSecurityAttemptCounterEnabled:是否存储安全访问尝试次数。
  • DcmDspSecuritycompareKeyFnc:比较Key的函数名称,遵循生成的函数原型声明,集成开发商需要实现此函数具体实现。
  • DcmDspSecurityDelayTime:失败安全访问延时时间,以秒为单位。
  • DcmDspsecurityDelayTimeOnBoot:启动延时,以秒为单位。
  • DcmDspsecurityGetAttemptcounterFnc:获取安全访问尝试次数的函数名称,遵循生成的函数原型声明,集成开发商需要实现此函数具体实现。
  • DcmDspSecurityGetSeedFnc:获取Seed的函数名称,遵循生成的函数原型声明,集成开发商需要实现此函数具体实现。
  • DcmDspSecurityKeysize:安全密钥的长度,以字节为单位。
  • DcmDspSecurityLevel:安全等级。
  • DcmDspSecurityNumAttDelay:激活延迟时间内的失败安全访问次数。
  • DcmDspSecuritySeedsize:安全种子长度,以字节为单位。
  • DcmDspsecuritysetAttemptcounterFnc:设置安全访问尝试次数的函数名称,遵循生成的函数原型声明,集成开发商需要实现此函数具体实现。
  • DcmDspsecurityUsePort:定义安全访问使用何种Interface。


DcmDspSession

配置会话管理参数,默认参数即可。


DcmDspSessionRow 

建立三个会话,其中编程会话可以跳转到BOOT,这样Tester在切换到编程会话之后,程序会跳转到Boot。


DcmDsdService 

DCM支持的服务定义,一般需要支持以下服务:

  • DiagnosticSessionControl:0x10服务,诊断会话控制服务。
  • ECUReset:0x11服务,ECU重启服务。
  • SecurityAccess:0x27服务,安全访问。
  • CommunicationControl:0x28服务,通信控制。
  • TesterPresent:0x3E服务,诊断仪在线。
  • ControlDTCSetting:0x85服务,DTC控制服务。
  • ReadDataByIdentifier:0x22服务,DID读取。
  • WriteDataByIdentifier:0x2E服务,DID写入。
  • ClearDTC:0x14服务,清除故障码DTC服务。
  • ReadDTC:0x19服务,读取DTC服务。
  • RoutineControl:0x31服务,例程控制服务。
  • InputOutputControlByIdentifier:0x2F服务,输入输出控制服务。

我们以第一个0x10服务为例来介绍以下配置过程,首先如下图配置服务,我们来介绍以下重要的配置项:

  • DcmDsdSidTabFnc:诊断服务处理函数,用户可以通过摁下“Ctrl+Enter”来查找特定DCM支持的服务处理函数名。
  • DcmDsdSidTabServiceld:服务ID。
  • DcmDsdSidTabSubfuncAvail:是否包含子服务。
  • DcmRbDsdSidTabScheduler:服务处理函数调度函数,由DcmMainScheduler调度。
  • DcmRbDsdSidTabSidInitFunction:服务初始化函数,用户可以通过摁下“Ctrl+Enter”来查找特定DCM支持的服务初始化函数名。
  • DcmDsdSidTabSecurityLevelRef:服务需要的安全等级,空为不需要安全等级。
  • DcmDsdSidTabSessionLevelRef:服务需要的会话状态,全选即为在任何会话模式下都可以访问这个服务。

这个服务有三个,如下图所示,可以看到切换到编程模式的子服务只能在扩展模式下访问。


DcmDspComControlAllChannel

配置代表所有通信的ComM网络通道。


DcmDspCommonAuthorization 

 此容器配置常见的服务鉴权要求。


DcmRbDspReadDTC

这个容器主要涉及到两个参数。

  • DcmRbDspReadDTCMaxNumDTCRead:在一个服务中最大能读取的DTC数量。
  • DcmRbDspReadDTCMaxNumRecordRead:在一个服务中最大能读物的Record。


DcmDspData

这个容器包含了DID涉及的数据定义以及用户自定的读写函数名称,关键参数如下。

  • DcmDspDataReadFnc:请求读取DID数据的函数名称,集成商需要实现。
  • DcmDspDataSize:DID数据大小,以Bit为单位。
  • DcmDspDataType:DID数据类型。
  • DcmDspDataUsePort:定义访问数据使用的Interface,下面的示例用的是同步。
  • DcmDspDataWriteFnc:请求写入DID数据的函数名称,集成商需要实现。


DcmDspDidInfo

这个容器包含了DID的一些属性信息,包括会话和安全等级要求。首先通过DcmDspDidDynamicallyDefined参数配置DID可否动态配置,如下图。

然后,新建DcmDspDidRead,在DcmDspDidWriteSessionRef处引用默认和扩展会话,表示这个DID在这两个会话下才能访问。

然后再新建DcmDspDidWrite,在DcmDspDidWriteSecurityLevelRef处引用安全等级为1,在DcmDspDidWriteSessionRef引用扩展会话,这样针对F190这个DID(也就是VIN码)的写操作只有在安全等级为1且扩展模式下才能访问。


DcmDspDid 

这个容器定义一个具体的DID,它会引用到我们刚才定义的DidInfo以及Data信息,我们首先在DcmDspDidldentifier处填写DID值,然后再在DcmDspDidInfoRef处引用刚才定义的DidInfo。

最后我们新建一个DcmDspDidSignal,它包含以下两个参数。

  • DcmDspDidDataPos:在下边引用的DcmDspData中数据DID的起始位置。
  • DcmDspDidDataRef:DID引用的DcmDspData。


DcmDspRoutine

这个容器包含了例程相关的配置。重要的配置如下:

  • DcmDspRoutineldentifier:例程ID。
  • DcmDspRoutineUsePort:例程会生成一个Interface,应用层可以基于这个Interface建立一个Service类型端口实现例程执行内容。

建立一个启动例程的子服务。

最后我们定义一个单字节的ECU回复信息。新建一个DcmDspStartRoutineOut,下面是该容器的具体配置。


DcmPageBuffercfg 

禁用PageBuffer机制。


CanTp

CanTp(CAN Transport Layer)是在PDU Router与CAN Interface module中间的模块,如下图所示。CANTP模块的主要目的是分段和重新组装长度大于8字节或在CAN_FD情况下大于64字节的CANI-PDU(根据传输层定义,拼接CAN帧供应用层使用)。

PDU Router将AUTOSAR COM和DCM I-PDU部署到不同的通信协议上。通过网络系统类型(如CAN、LIN和FlexRay)的路由行为取决于I-PDU标识符。PDU Router还确定是否必须使用传输协议。最后,当没有速率转换时,该模块执行网关功能。

CAN Interface module(Canlf)提供同等的机制来访问CAN总线通道,而不论其位置(芯片内部或者外部)。它从CAN控制器的位置(芯片或者板载)中提取ECU硬件布局和CAN驱动程序的数目。由于CanTp只处理传输协议帧(即SF、FF、CF和FC PDU),根据N-PDU标识,CANIf必须将I-PDU转发给CanTp或PduR。下图中的红色箭头为DCM诊断协议的路径。

 根据AUTOSAR的基本软件架构,CanTp可以提供:

  • 在传输方向上的数据分割。
  • 沿接收方向重新拼接数据。
  • 数据流的控制。
  • 检测会话中的错误。
  • 发送与接收取消。

AUTOSAR决定将基本的软件模块规范建立在现有标准之上,因此本AUTOSAR CAN传输层规范以国际标准ISO-15765为基础,IS015765是汽车领域最常用的标准。

ISO-15765(包含四个部分)描述了两种适用的CAN传输层规范:ISO-15765-2用于OEM增强型诊断和ISO-15765-4标准用于OBD诊断。过CAN传输层配置,可以解决ISO-15765-2和SO-15765-4之间的兼容性问题。

虽然CAN传输协议主要用于车辆诊断系统,但它也被开发用于处理其他基于CAN的系统需要传输层协议的要求。


CanTpGeneral

此容器包含针对CanTP的一些通用配置。下面针对重要的参数进行解释。

  • CanTpChangeParameterApi:如果设置为真,则可以使用CanTp_ChangeParameterRequest在运行中改变参数。
  • CanTpDevErrorDetect:模块DET使能。
  • CanTpPaddingByte:未使用Bytes的默认值。
  • CanTpReadParameterApi::如果设置为真,则可以使用CanTp_ReadParameterApi读取运行中的参数配置。


CanTpChannel 

在CanTpConfig容器下配置CanTpMainFunctionPeriod为0.01。

在CanTpChannel容器下配置CanTpChannelMode为CANTP_MODE_FULL_DUPLEX全双工。 


CanTpRxNSdu 

为每个CanTp接收的N-SDU配置参数,这里DCM涉及两个报文,一个物理请求ID报文,一个功能请求ID报文,我们先介绍物理请求ID报文。

其中主要涉及的配置项包括:

  • CanTpNbr:下一个个FlowControl传输之前的时间。
  • CanTpRxAddressingFormat:接收帧ID类型,下面实例为标准帧。
  • CanTpRxPaddingActivation:定义接收的帧未使用字节是否填充。
  • CanTpRxTaType:定义当前Rx N-SDU的通信类型。
  • CanTpRxNSduRef:当前接收报文CanTp2PduR的引用。

我们还需要引用物理请求帧CanTp与CanIf之前来回的Pdu。

首先是物理请求帧对应的CanIf2CanTp的Pdu引用。

因为物理帧的请求一般需要回复,所以这里还需要引用诊断响应帧的CanTp2CanIf,如下图所示。

后边还需要配置功能请求帧的配置,如下如所示,与物理请求帧基本一致,不同的是CanTpRxNSduRef的引用为功能请求帧。

功能请求帧一般不需要回复,所以只需要引用功能帧的CanIf2CanTp即可。


CanTpTxNSdu 

为每个CanTp发送的N-SDU配置参数,DCM这边仅涉及一个诊断响应帧,其中涉及到的主要配置参数如下:

  • CanTpNas:发送任意CAN帧的时间。
  • CanTpTc:启用/禁止传输取消功能。
  • CanTpTxAddressingFormat:发送帧ID的类型,下面的示例为标准帧。
  • CanTpTxPaddingActivation:定义发送的帧未使用字节是否填充。
  • CanTpTxTaType:定义当前Tx N-SDU的通信类型。
  • CanTpTxNSduRef:当前发送报文PduR2CanTp的引用。

我们还需要引用诊断响应帧CanTp与CanIf之前来回的Pdu。因为诊断响应帧一般回复的是物理请求帧,所以CanTpRxFcNPdu引用物理请求帧的CanIf2CanTp。

然后是诊断响应帧本身的CanTp2CanIf。


Components 

使用CodeGen生成BSW代码以及ARXML成功之后,就可以在Components下看到生成的DCM服务组件。服务组件的东西都是生成的,不用更改,这里就不介绍了。

我们在测试建立的组件Test1中完成DCM相关服务的实现支持,首先建立三个端口如下图,并引用DTS_DcmEcuReset,它与端口使用的接口都是CodeGen生成的。

然后我们建立四个Functions:

  • RE_JumpToBootloader:实现跳转到BootLoader功能,可以增加对MDGP_DcmEcuReset的Mode Points访问,RTE会给它提供当前DcmEcuReset模式获取接口。
  • RE_Dcm_Reset_Hard:实现硬重启,访问EcuM提供的SelectShutdownTarget。
  • RE_Dcm_Reset_Soft:实现软重启,访问EcuM提供的SelectShutdownTarget。
  • RE_Swc_DcmDspRoutine_F001_Start:实现F001例程,可以连接必要的应用组件。

最后,建立对应的Events。


System 

将DCM增加部件中。

然后增加DCM服务组件到ECU中。

最后完成连接组件间的连接。


RTE 

将BSWSE DcmMainFunction添加到周期运行函数中,因为RE_JumpToBootloader,RE_Dcm_Reset Soft、RE_Dcm_Reset_Hard三个运行实体牵扯到模式的转换,所以需要将它们放到DcmMode切换的专用Task中,这个Task为RTE使用,用作本地的模式切换。


代码解析 

动态配置代码

DCM模块生成的动态代码如下图所示。

我们下面针对一些常用的进行说明:

  • Dcm_Cfg_DslDsd.h:它包含了Diagnostic Communication Manager (DCM)模块中Data Services (DSD)和Diagnostic Session Layer (DSLl)之间的数据结构和宏定义。该头文件定义了DSL和DSD之间交换的消息格式、DCM状态机的状态、DCM会话的类型、DCM数据的长度等信息。
  • Dcm_Cfg_DspUds.h:该文件定义了UDS协议中各种服务的标识符、支持的诊断服务、支持的协议控制信息、支持的诊断服务的请求和响应的最大长度、支持的DTCS(Diagnostic Trouble Code)格式等。
  • Dcm_Lcfg_DslDsd.c:它包含了DSD与DSL使用的服务列表、诊断协议支持等静态常量。
  • Dcm_Lcfg_DslDsd.h:包含了DCM函数原型定义。
    /*
    ***********************************************************************************************************************
    * 
    * Product Info
    * Isolar version: ISOLAR-AB 4.0.2
    * Product release version: RTA-BSW 3.1.0
    * 
    ***********************************************************************************************************************
    */
    
    
    #ifndef _DCM_LCFG_DSLDSD_H
    #define _DCM_LCFG_DSLDSD_H
    
    
    #define DCM_START_SEC_CODE /*Adding this for memory mapping*/
    #include "Dcm_Cfg_MemMap.h"
    extern FUNC(Std_ReturnType,DCM_CODE) Dcm_DcmDiagnosticSessionControl(VAR( Dcm_SrvOpStatusType,AUTOMATIC) OpStatus,P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_INTERN_DATA) pMsgContext,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) dataNegRespCode_u8);
    extern FUNC(Std_ReturnType,DCM_CODE) Dcm_DcmEcuReset(VAR( Dcm_SrvOpStatusType,AUTOMATIC) OpStatus,P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_INTERN_DATA) pMsgContext,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) dataNegRespCode_u8);
    extern FUNC(Std_ReturnType,DCM_CODE) Dcm_DcmSecurityAccess(VAR( Dcm_SrvOpStatusType,AUTOMATIC) OpStatus,P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_INTERN_DATA) pMsgContext,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) dataNegRespCode_u8);
    extern FUNC(Std_ReturnType,DCM_CODE) Dcm_DcmReadDataByIdentifier(VAR( Dcm_SrvOpStatusType,AUTOMATIC) OpStatus,P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_INTERN_DATA) pMsgContext,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) dataNegRespCode_u8);
    extern FUNC(Std_ReturnType,DCM_CODE) Dcm_DcmWriteDataByIdentifier(VAR( Dcm_SrvOpStatusType,AUTOMATIC) OpStatus,P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_INTERN_DATA) pMsgContext,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) dataNegRespCode_u8);
    extern FUNC(Std_ReturnType,DCM_CODE) Dcm_DcmRoutineControl(VAR( Dcm_SrvOpStatusType,AUTOMATIC) OpStatus,P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_INTERN_DATA) pMsgContext,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) dataNegRespCode_u8);
    extern FUNC(Std_ReturnType,DCM_CODE) Dcm_DcmCommunicationControl(VAR( Dcm_SrvOpStatusType,AUTOMATIC) OpStatus,P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_INTERN_DATA) pMsgContext,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) dataNegRespCode_u8);
    extern FUNC(void,DCM_CODE) Dcm_Dsp_DscIni(void);
    extern FUNC(void,DCM_CODE) Dcm_Dsp_EcuReset_Ini(void);
    extern FUNC(void,DCM_CODE) Dcm_Dsp_SecaIni(void);
    extern FUNC(void,DCM_CODE) Dcm_Dsp_RdbiIni(void);
    extern FUNC(void,DCM_CODE) Dcm_Dcm_WDBIInit(void);
    extern FUNC(void,DCM_CODE) Dcm_Dsp_RC_Ini(void);
    extern FUNC(void,DCM_CODE) Dcm_Dsp_CCIni(void);
    
    
    extern FUNC(Std_ReturnType,DCM_APPL_CODE) DcmAppl_UserServiceModeRuleService(P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) Nrc_u8, VAR(uint8,AUTOMATIC) Sid_u8);
    extern FUNC(Std_ReturnType,DCM_APPL_CODE) DcmAppl_UserSubServiceModeRuleService(P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) Nrc_u8, VAR(uint8,AUTOMATIC) Sid_u8,VAR(uint8,AUTOMATIC) Subfunc_u8);
    
    
    
    extern FUNC(Std_ReturnType,DCM_APPL_CODE) DcmAppl_UserDIDModeRuleService(P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) Nrc_u8, VAR(uint16,AUTOMATIC) did_u16,VAR(Dcm_Direction_t,AUTOMATIC) dataDirection_en);
    extern FUNC(Std_ReturnType,DCM_APPL_CODE) DcmAppl_UserRIDModeRuleService(P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) Nrc_u8, VAR(uint16,AUTOMATIC) rid_u16, VAR(uint8,AUTOMATIC) subfunction_u8);
    extern FUNC(Std_ReturnType,DCM_APPL_CODE) DcmAppl_UserCommCtrlReEnableModeRuleService(void);
    
    /* Extern declarations For DcmAppl SessionMode Switch function */
    extern FUNC(void,DCM_CODE)  DcmAppl_Switch_DcmDiagnosticSessionControl(VAR(Dcm_SesCtrlType,AUTOMATIC) SessionMode);
    extern FUNC(void,DCM_CODE)  DcmAppl_Switch_DcmExecuteDscReset(VAR(uint8,AUTOMATIC) SessionLevel_u8);
    
    /* Extern declarations For DcmAppl ResetMode Switch function */
    extern FUNC(void,DCM_CODE)  DcmAppl_Switch_DcmEcuReset(VAR(uint8,AUTOMATIC) ResetMode);
    extern FUNC(void,DCM_CODE)  DcmAppl_Switch_DcmExecuteReset(void);
    extern FUNC(void,DCM_CODE)  DcmAppl_Switch_DcmExecuteEcuReset(VAR(uint8,AUTOMATIC) ResetType_u8);
    extern FUNC(void,DCM_CODE)  DcmAppl_Switch_DcmBootLoaderReset(void);
    extern FUNC(void,DCM_CODE)  DcmAppl_Switch_DcmSysSupplierReset(void);
    
    extern FUNC(void,DCM_CODE)  DcmAppl_Switch_DcmDriveToDriveReset(void);
    #define DCM_STOP_SEC_CODE /*Adding this for memory mapping*/
    #include "Dcm_Cfg_MemMap.h"
    #endif /* _DCM_LCFG_DSLDSD_H */
    
    
  • Dcm_Lcfg_DspUds.c:包含会话与密钥管理配置以及DID,Routines相关Dsp配置。
  • Dcm_Lcfg_DspUds.h:DSP涉及的DID读写以及例程相关函数原型。
    /*
    ***********************************************************************************************************************
    * 
    * Product Info
    * Isolar version: ISOLAR-AB 4.0.2
    * Product release version: RTA-BSW 3.1.0
    * 
    ***********************************************************************************************************************
    */
    
    
    #ifndef DCM_LCFG_DSPUDS_H
    #define DCM_LCFG_DSPUDS_H
    /*
     ***************************************************************************************************
     *    DCM Appl API Prototyes generated from configuration
     ***************************************************************************************************
    */
    #define DCM_START_SEC_CODE /*Adding this for memory mapping*/
    #include "Dcm_Cfg_MemMap.h"
    extern FUNC(Std_ReturnType,DCM_APPL_CODE) Dcm_DidServices_F186_ReadData(P2VAR(uint8,AUTOMATIC,DCM_INTERN_DATA) adrData_pu8);
    #define DCM_STOP_SEC_CODE /*Adding this for memory mapping*/
    #include "Dcm_Cfg_MemMap.h"
    #define DCM_START_SEC_CODE /*Adding this for memory mapping*/
    #include "Dcm_Cfg_MemMap.h"
    
    /***Extern declarations to obtain NRC value from the application in case of E_NOT_OK return from ReadData API ***/
    extern FUNC(Std_ReturnType,DCM_APPL_CODE)  DcmAppl_DcmReadDataNRC(VAR(uint16,AUTOMATIC)Did,VAR(uint32,AUTOMATIC)DidSignalPosn,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) ErrorCode);
    
    
     /***Extern declarations for XXX_ReadData of type USE_DATA_SYNCH_FNC ***/
    extern FUNC(Std_ReturnType,DCM_APPL_CODE) DcmDspDataReadFnc_F190 (P2VAR(uint8,AUTOMATIC,DCM_INTERN_DATA) Data);
    extern FUNC(Std_ReturnType,DCM_APPL_CODE) DcmDspDataWriteFnc_F190 (P2CONST(uint8,AUTOMATIC,DCM_INTERN_DATA) Data,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) ErrorCode);
    
    /***Routine control Appl functions***/
    
    /***Seca dcmDspSecurityGetSeedFnc functions with Useport  USE_ASYNCH_FNC ***/
    extern FUNC(Std_ReturnType, DCM_APPL_CODE) DCM_SEC_LEV_L1_GetSeed(VAR(Dcm_SecLevelType,AUTOMATIC) SecLevel_u8,VAR(uint8,AUTOMATIC) Seedlen_u8,VAR(uint8,AUTOMATIC) AccDataRecsize_u8,P2VAR(uint8,AUTOMATIC,DCM_INTERN_DATA) SecurityAccessDataRecord,P2VAR(uint8,AUTOMATIC,DCM_INTERN_DATA) Seed,VAR(Dcm_OpStatusType,AUTOMATIC) OpStatus,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) ErrorCode);
    
    /***Seca dcmDspSecurityCompareKeyFnc functions with Useport  USE_ASYNCH_FNC ***/
    extern FUNC(Std_ReturnType, DCM_APPL_CODE) DCM_SEC_LEV_L1_CompareKey(VAR(uint8,AUTOMATIC) KeyLen,P2VAR(uint8,AUTOMATIC,DCM_INTERN_CONST) Key,VAR(Dcm_OpStatusType, AUTOMATIC) OpStatus,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) ErrorCode);
    
    /***Seca dcmDspSecurityGetAttemptCounterFnc functions with Useport  USE_ASYNCH_FNC ***/
    extern FUNC(Std_ReturnType, DCM_APPL_CODE) Dcm_SEC_LEV1_GetSecurityAttemptCounter( VAR(Dcm_OpStatusType, AUTOMATIC) OpStatus,P2VAR(uint8,AUTOMATIC,DCM_INTERN_DATA) AttemptCounter);
    /***Seca dcmDspSecuritySetAttemptCounterFnc functions with Useport  USE_ASYNCH_FNC ***/
    extern FUNC(Std_ReturnType, DCM_APPL_CODE) Dcm_SEC_LEV1_SetSecurityAttemptCounter( VAR(Dcm_OpStatusType, AUTOMATIC) OpStatus,VAR(uint8,AUTOMATIC) AttemptCounter);
    
    
    #define DCM_STOP_SEC_CODE /*Adding this for memory mapping*/
    #include "Dcm_Cfg_MemMap.h"
    #endif /* DCM_LCFG_DSPUDS_H */
    


集成代码

MemMap与SchM就不在这里赘述了。DCM提供了很多诊断通知函数的模板,它们会在DCM运行中在特定位置调用这些函数,诸如通知ECU重启类型,或者实现一些特殊接口,诸如实现内存读取。它们一般情况下都不会用到。它们涉及很多,下图截取了一部分

还有刚才提到的那四个函数RE_JumpToBootloade、RE_Dcm_Reset_Soft、RE_Dcm_Reset_Soft、RE_Swc_DcmDspRoutine_F001_Start实现,下面以JumpToBootload为例。

FUNC (void, Diag_SWC_CODE) RE_JumpToBootloader_func/* return value & FctID */
(
		void
)
{

	/* Local Data Declaration */

	/*PROTECTED REGION ID(UserVariables :RE_JumpToBootloader_func) ENABLED START */
	/* Start of user variable defintions - Do not remove this comment  */
	/* End of user variable defintions - Do not remove this comment  */
	/*PROTECTED REGION END */
	Std_ReturnType retValue = RTE_E_OK;
	/*  -------------------------------------- Data Read -----------------------------------------  */

	/*  -------------------------------------- Server Call Point  --------------------------------  */

	/*  -------------------------------------- CDATA ---------------------------------------------  */

	/*  -------------------------------------- Data Write ----------------------------------------  */

	/*  -------------------------------------- Trigger Interface ---------------------------------  */

	/*  -------------------------------------- Mode Management -----------------------------------  */

	/*  -------------------------------------- Port Handling -------------------------------------  */

	/*  -------------------------------------- Exclusive Area ------------------------------------  */

	/*  -------------------------------------- Multiple Instantiation ----------------------------  */

	/*PROTECTED REGION ID(User Logic :RE_JumpToBootloader_func) ENABLED START */
	/* Start of user code - Do not remove this comment */
	*(uint32 *)PROG_REQUEST_ADDR = (uint32)PROG_REQUEST_NUMBER;
	Mcu_PerformReset();
	/* End of user code - Do not remove this comment */
	/*PROTECTED REGION END */

}

可以看到跳转Boot的函数首先在内存的一个预设的位置配置为有编程请求,然后通过调用MCU提供的Mcu_PerformReset执行重启,因为Boot执行顺序在APP之前,所以先执行,然后再预设的位置获取了有编程请求的信息之后,即可以进入变成会话等待进一步的诊断协议。

最后,集成商还需要根据刚才的配置区实现具体的DID读/写函数。下面是一个F190的示例。集成商应该根据自己平台的特点来修改示例。

FUNC(Std_ReturnType,DCM_APPL_CODE) DcmDspDataReadFnc_F190 (P2VAR(uint8,AUTOMATIC,DCM_INTERN_DATA) Data)
{
	uint8 ptrdata[LENGTH_OF_F190] = {0};
	uint32 index = 0u;

	for(index = 0u; index < LENGTH_OF_F190 ; index++)
	{
		Data[index] = VIN[index];
	}

	return DIAG_E_OK;
}

FUNC(Std_ReturnType,DCM_APPL_CODE) DcmDspDataWriteFnc_F190 (P2CONST(uint8,AUTOMATIC,DCM_INTERN_DATA) Data,P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_INTERN_DATA) ErrorCode)
{
	uint8 u8CycleCnt = 0U;
	uint8 u8WriteRt = 1U;

	for (u8CycleCnt = 0U; u8CycleCnt<LENGTH_OF_F190; u8CycleCnt++)
	{
		VIN[u8CycleCnt] = Data[u8CycleCnt];
	}
    
    while(u8WriteRt)
    {
	    u8WriteRt = Rte_Call_RP_F190_NvM_WriteBlock(VIN);
    }

	return u8WriteRt;
}

静态代码

主要介绍常见的静态代码涉及API说明,具体详细完整的介绍读者可以参考《AUTOSAR_SWS_CANTransportLayer.pdf》以及《RTA-BSWReferenceGuide.pdf》。

  • Dcm_MainFunction:DCM模块主函数,需要循环调用处理DCM相关任务。
  • Dcm_ReadMemory:这是一个CallOut函数,集成商根据DCM提供的函数原型实现存储的读取操作。
  • Dcm_TxConfirmation:这是一个Callbcak函数,DCM发送完成时调用。
  • Dcm_Init:这是一个提供给别的BSW组件的函数,完成DCM初始化。
  • Dcm_GetSecurityLevel:这是一个提供给SW-Cs或者基础模块的函数,获取当前的安全等级。

十六宿舍 原创作品,转载必须标注原文链接。

©2023 Yang Li. All rights reserved.

欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1858236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JetBrains WebStorm 2024 mac/win版:效率至上,编码无忧

JetBrains WebStorm 2024 是一款专为前端开发者和全栈工程师打造的高 级集成开发环境(IDE)。它提供了对JavaScript、TypeScript、HTML5、CSS等技术的全面支持&#xff0c;帮助开发者更高效地进行前端开发。 WebStorm 2023 mac/win版获取 WebStorm 2024 拥有强大的智能代码补全…

SpringBoot+Vue集成富文本编辑器

1.引入 我们常常在各种网页软件中编写文档的时候&#xff0c;常常会有富文本编辑器&#xff0c;就比如csdn写博客的这个页面&#xff0c;包含了富文本编辑器&#xff0c;那么怎么实现呢&#xff1f;下面来详细的介绍&#xff01; 2.安装wangeditor插件 在Vue工程中&#xff0c;…

锐捷统一上网行为管理与审计系统 static_convert.php 前台RCE漏洞复现

0x01 产品简介 锐捷统一上网行为管理与审计RG-UAC系列是星网锐捷网络有限公司自主研发的上网行为管理与审计产品,具备的上网行为日志审计功能,能够全面、准确、细致的审计并记录多种上网行为日志,包括网页、搜索、外发文件、邮件、论坛、IM等等,并对日志数据进行统计分析,…

开发基于Java语言的SaaS(Software-as-a-Service,软件即服务)模式的HIS系统详解 HIS系统源码 支持二开

开发基于Java语言的SaaS&#xff08;Software-as-a-Service&#xff0c;软件即服务&#xff09;模式的HIS系统详解 HIS系统源码 支持二开 开发基于Java语言的SaaS&#xff08;Software-as-a-Service&#xff0c;软件即服务&#xff09;模式的HIS&#xff08;Hospital Informat…

深入探索Jetpack数据绑定(DataBinding)

Jetpack的数据绑定&#xff08;DataBinding&#xff09;库为我们提供了一个强大而灵活的工具&#xff0c;用于将UI组件与数据源绑定在一起。本文将深入探讨数据绑定的高级用法&#xff0c;包括双向绑定、自定义Binding Adapter、使用LiveData和ViewModel&#xff0c;以及如何处…

爬虫笔记15——爬取网页数据并使用redis数据库set类型去重存入,以爬取芒果踢V为例

下载redis数据库 首先需要下载redis数据库&#xff0c;可以直接去Redis官网下载。或者可以看这里下载过程。 pycharm项目文件下载redis库 > pip install redis 然后在程序中连接redis服务&#xff1a; from redis import RedisredisObj Redis(host127.0.0.1, port6379)…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-27含并行连结的网络GoogLeNet

27含并行连结的网络GoogLeNet import torch from torch import nn from torch.nn import functional as F import liliPytorch as lp import matplotlib.pyplot as pltclass Inception(nn.Module):# c1--c4是每条路径的输出通道数def __init__(self, in_channels, c1, c2, c3, …

Linux高并发服务器开发(一)GCC和Make

文章目录 1 工作流程2 静态库和动态库连接2.1 静态连接2.2 动态链接 3 静态库制作和使用4 动态库的制作和使用5 GDB 调试器6 Makefile 1 工作流程 第一步预处理&#xff0c;生成.i 第二部生成汇编文件.s 第三部生成目标代码.o 第四部生成可执行文件 2 静态库和动态库连接 2.1…

充电桩---特斯拉NACS接口介绍

一、NACS接口发展 NACS是由特斯拉内部开发的&#xff0c;作为交流和直流充电的专有充电解决方案。2022年11月11日&#xff0c;特斯拉在官网上开放了自家的充电接口设计&#xff0c;并将特斯拉充电接口更名为NACS&#xff08;North American Charging Standard&#xff09;&…

Python列表比较:判断两个列表是否相等的多种方法

&#x1f4d6; 正文 1 通过排序的方式实现判断 list_a [a, b, c, d] list_b [c, d, a, b]if sorted(list_a) sorted(list_b):print(list_a与list_b的元素相等) else:print(list_a与list_b的元素不相等)通过排序&#xff0c;让两组列表中元素一直后进行判断&#xff0c;得到…

LONGHEADS:无需训练的多头注意力长文本处理框架

大模型&#xff08;LLMs&#xff09;在处理海量文本数据时展现出了前所未有的能力。然而这些模型在面对超出其训练时所见序列长度的长文本时存在两个主要问题&#xff1a;一是模型对于超出预训练长度的文本难以有效泛化&#xff0c;二是注意力机制的二次方时间复杂度导致计算成…

Marin说PCB之如何在CST仿真软件中添加三端子的电容模型?--02

小编我在上期文章的结尾给大家留下一个小问题就是&#xff1a;在三端子电容创建模型中间的部分我有说了一句就是&#xff1a;&#xff08;其中有一个creat reference pin 设置我们也默认不勾选&#xff09;&#xff0c;这个勾选不勾选有啥区别呢&#xff1f;这期文章就来给大家…

『 Linux 』 进程间通信 - 匿名管道 (万字)

文章目录 什么是管道匿名管道的直接原理pipe( )系统调用接口匿名管道代码示例匿名管道的特征总结 什么是管道 管道(Pipe) 是一种基本的进程间通信(IPC)机制,允许一个进程与另一个进程之间进行数据传输; 管道工作方式类似于生活中的水管因此命名为管道,数据从一端流入另一段流出…

学习笔记——动态路由——RIP(距离矢量协议)

一、距离矢量协议 1、距离矢量协议 矢量行为&#xff1a;协议收到一个路由之后&#xff0c;查看是否可以加入到本地的路由表中&#xff0c;如果可以加入&#xff0c;则可以传递&#xff0c;如果不可以加入&#xff0c;则无法传递。 距离矢量路由协议 RIP基于距离矢量算法(又…

智慧语音助手学习

智慧语音助手 1 语音识别系统&#xff08;ASR&#xff09;2 语义理解1 传统的实现方法1. 音频信号处理和语音识别&#xff08;Automatic Speech Recognition, ASR&#xff09;2. 自然语言理解&#xff08;Natural Language Understanding, NLU&#xff09;3. 对话管理&#xff…

【高数强化】武忠祥高等数学辅导讲义+严选题错题整理

第一章 函数、极限和连续 高等数学辅导讲义 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 严选题 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 第二章 一元函数微分学 高等数学辅导讲义 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 严选…

港股再遭重挫,市场到底在恐慌什么?

恒指上周五挫逾300点后&#xff0c;今日早间延续低迷低开超百点&#xff0c;随后一路震荡下行&#xff0c;最低见17789.57点。整体市场都表现相当低迷&#xff0c;但17750附近有一定支撑。截至收盘&#xff0c;恒指收跌0.00%。 港股持续在万八关徘徊&#xff0c;国资委旗下国新…

8.12 矢量图层面要素单一符号使用六(SVG填充)

文章目录 前言SVG填充&#xff08;SVG fill&#xff09;QGis设置面符号为SVG填充&#xff08;SVG fill&#xff09;SVG填充&#xff08;SVG fill&#xff09; 总结 前言 本章介绍矢量图层线要素单一符号中使用SVG填充&#xff08;SVG fill&#xff09;的使用说明&#xff1a;文…

AI大模型之争:通用性与垂直性,哪个更具优势?

文章目录 每日一句正能量前言背景介绍能力分析通用大模型的能力&#xff1a;垂直大模型的能力&#xff1a;差异与互补性分析&#xff1a; 难点探究1. 算力挑战2. 数据挑战3. 算法挑战4. 泛化能力5. 可解释性和透明度6. 伦理和偏见问题7. 成本效益 后记 每日一句正能量 昨天已逝…

DIY灯光特效:霓虹灯动画制作教程

下面我们根据这张霓虹灯案例,教大家如何用智能动物霓虹灯闪烁的效果,大家可以根据思路,实现自己想要的动效效果,一起动手来做吧。 即时设计-可实时协作的专业 UI 设计工具 设置背景 新建画板尺寸为:800PX^600PX,设置背景色#120527。 绘制主题 输入自己喜欢文案,轮廓化,具体…