从文章中您可以了解以下内容
顾名思义,它有“记录”(LOG)和“追踪”(trace)的两个主要功能。
下面提出几个问题,我们来一一解答,层层深入探索DLT模块。
首先,记录哪些内容呢?又追踪什么呢?
它记录的信息来自“Det”,“DEM”模块,以及一些SWC(软件组件)。追踪的信息来自RTE。
其次,这些信息到底是什么呢?这些信息保存在何处?以什么格式或方式保存?
最终,这些信息用来做什么呢?这些信息肯定是给人看的嘛,人是怎么看到的呢?
规范中写道:The Dlt module transmits this data via communication busses to make this
information visible outside the ECU.
说明这些信息是通过通信总线(例如CAN, 以太等)被传递出来给关心这些信息的人来阅读的(处理的)。为了这个目的,DLT定义了一些API去在车载网络上接收和发送特定的记录和追踪信息。此外,还可以通过NVM模块来保存DLT的更新滤波器设置,这样就不需要通过ECU上电后通过总线去进行显式设置,而自主地根据预设的等级去发送记录和追踪的数据。另外,DLT与外部设备的沟通,必须遵循一套特定的协议,DLT报文格式,DLT指令格式及内容等在文档《Dlt Protocol Specification》中进行描述,小伙伴们可以去找来参考。
通过下图我们可以清楚地了解到DLT所在AUTOSAR架构中的位置以及对其他模块的依赖关系。
来自DET模块的错误信息。
为了可以通过DLT去报告错误,DLT提供了与DET交互的接口,这些接口也是可选择的。SWC和BSW的错误会报告给DET,然后在通过DET将这些错误通过Dlt_DetForwardErrorTrace发给DLT模块。
各个模块通过DET的Det_ReportError将错误发给DLT的Dlt_DetForwardErrorTrace函数。换句话说,在Det_ReportError函数中调用Dlt_DetForwardErrorTrace这个接口。Det的记录报文需要包含如下值
ApplicationID = "Det"
ContextId = “STD”
MessageID = 0X00000002
LogLevel = “Error”
来自DEM的信息
DEM事件同样可以通过DLT发送到车载网路上。DLT提供了与DEM接口,同样也是可以选择的。
在DEM中,通过EventID来表征这些来自BSW和SWC的事件。这些事件都包含一些信息如DTC(Diagnostic Trouble Code),扩展数据记录,和冻结帧。DEM通过调用DLT接口Dlt_DemTriggerOnEventStatus来通知DLT这些事件状态变化。DEM会在接口中说明出现变化的事件的EventID,以此DLT会请求此事件的更多信息。DLT也会在Dlt_DemTriggerOnEventStatus
中比较事件新、旧状态是否一致,如果不一致,就会通过Dlt_SendLogMessage发送DLT LOG信息。
DEM事件的DLT LOG报文包括如下值
ApplicationID = "DEM"
ContextId = “STD0”
MessageID = 0X00000001
来自RTE的信息(VFB Trace)
包括VFB和BSW 调度器(scheduler)被用于与SWC的沟通,来生成记录和追踪信息,并周期地调用DLT模块的发送接口。实际上,DLT通过与RTE的接口来记录VFB trace并处理trace数据。这其中DLT作为client去获取server,也就是RTE提供的VFB trace数据。因此,在RTE的配置中有一个参数RteVfbTraceClientPrefix必须要设置为“Dlt”。
DLT命令是被用于在运行时改变DLT模块行为的。是以服务ID的方式来标识的。如下:
SWC通过DLT提供的接口发送LOG和TRACE信息。
如果用户希望在log level阈值和trace状态发生变化时再去记录这些信息,是可以实现的。SWC可以提供一个端口去针对上述变化进行通知,这个通知接口是DLT分别为每一个ApplicationId/ContextId单独提供的。这个机制可以避免在上游因重复生成LOG和TRACE数据而在DLT中去过滤掉它们。
DLT提供一个SessionId的参数,这个参数适用于区别同一个SWC的不同实例所产生的LOG/TRACE。因为DLT模块允许SWC的多重实例使用同一个ApplicationId/ContextId元。
这里解释一下 ApplicationId:它是用于识别Log和trace信息是源于哪个应用/SWC的,由8位ASCII字符组成。
ContextId指的是一个应用或SWC生成的一组log和trace的识别符,是用户自定义的,遵循如下原则:
这样看来,识别一个log或trace来自哪个应用,我们就根据ApplicationID和ContextID就好了,但是具体到来自于哪一次实例,我们就要看SessionID了。
在调用接口(Dlt_SendLogMessage、Dlt_SendTraceMessage)时,为了既将SWC彼此区别开,又避免SWC必须使用独一无二的SessionID,DLT为每个配置的SWC(参考参数DltSwc)都提供了特定的P-Port端口,SessionID则作为此端口的参数。因为一个session代表一个应用或SWC被实例化(被执行)了一次,SessionID是为了区别这个应用产生的log和trace是哪一次执行产生的,而且同一个SWC同时产生多个log和trace的情况是有的(因为此SWC开了多个端口给DLT),那不同端口间是允许存在相同的SessionID的。
如果配置的 SW-C 被标记为对日志级别和跟踪状态更改的通知感兴趣,则 Dlt 模块还提供相应的 R-Port来通知相应的 SW-C。
某一个SWC对应哪个ApplicationID/ContextID,这个可以在运行时该SWC通过调用RegisterContext和UnregisterContext服务去配置或更新。
下图表达了DLT和SWC之间的端口配置和交互行为
以下规范的内容描述了DLT与SWC交互的基础。
SWS_Dlt_00644,DLT模块应该通过DltService接口为每个在DltSwc中配置的SWC提供一个P-Port。SWS_Dlt_00645,接口定义的P-Port有一个SessionID参数。
SWS_Dlt_00646,Dlt模块应通过LogTraceSessionControl接口提供一个R-Port给每一个在DltSwc中配置的SWC,且配置参数DltSwcSupportLogLevelChangeNotification应被设置为TRUE.
SWS_Dlt_00647,某个SWC对应的ApplicationID/ContexID是通过配置参数DltSwcContext推断得来的,此SWC也因此须在log level或trace状态发生变化时被通知。
在软件运行过程中,Dlt可以通过端口去通知某个(或某些)SWC关于log level的变化。那么DLT是如果实时性地通知到需要这些信息的SWC呢?我们知道在run time, SWC可以通过“注册”来告知DLT它所对应的ApplicationID/ContextID的。规范中定义的机制如下。
SWS_Dlt_00765, DLT要记住所有SWC在DLT中注册的ApplicationID和ContextID的元组(理解为“不可变序列”,“元”为不可变序列的元素,也可理解为“对”)。
SWS_Dlt_00766, DLT要为每一个ApplicationID/ContextID元(或“对”)的log level和trace状态进行管理。
注意:动态的注册机制支持DLT模块搞清楚当前哪些SWC(或runnable)是处于活动状态。这是必要的,因为在发生log level或trace 状态变化时,DLT需要知道应该去通知哪个SWC。
那么DLT如何去知道当前哪些SWC是处于活动状态呢?因为单纯地用ApplicationID/ContextID元(或“对”)去推导,我们只能找到对应的SWC,但是这个SWC在不在运行,我们并不知道。如果再加上通过前文提到的SessionID,我们就能够知道具体是哪个实例了,换句话说,DLT就知道对应的哪个SWC是处于活动状态了。
当一个SWC调用了DLTSevice接口的Dlt_RegisterContext方法,SessionID是作为这个方法的实参存在的,它的值对应到SWC(或runnable)的LogTraceSessionControl接口,以此可以将log level和trace状态变化的信息告知SWC(或者runnable)
SWS_Dlt_00021,DLT模块应记住ApplicationID/ContextID元与此元注册的端口接口的对应关系。
SWS_Dlt_00768, 如果参数DltGeneralRegisterContextNotification设置为TRUE,那么SWC每次调用Dlt_RegisterContext,DLT模块都要发送包含ApplicationID/ContextID元的DLT控制报文GetLogInfo
上述的SWC注册是为了告知DLT“我是在工作的”。那么如果一个SWC结束了当前的活动,它应该在DLT模块中注销。注销信息可以用于告知外部设备(例如,外部的记录设备)当前的SWC状态。
SWS_Dlt_00773,当SWC从DLT中被注销,那么DLT模块需要删除掉所有有关于这个SWC的ApplicationID/ContextID元。针对被删除的这些元,DLT再也不会尝试去向他们通知任何关于LogLevel变化的信息。
SWS_Dlt_00774, 如果参数DltGeneralRegisterContextNotification被设置为TRUE,那么每次调用Dlt_UnregisterContext, DLT模块都应发送包含ApplicationID/ContextID元且“状态”为6的控制报文GetLogInfo
再简单介绍一下端口参数值(也就是SessionID)以及LogTraceSessionControl接口。调用以下这些函数都要提供SessionID
Dlt_SendLogMessage
Dlt_SendTraceMessage
Dlt_RegisterContext
Dlt_UnregisterContext
SessionID应起始于0x1000,如果是BSW模块,应采用module ID作为SessionID.
每个SWC连接到DLT的端口都拥有一个单独的SessionID作为端口参数。且SessionID的范围应是连续的。
什么是trace?
VFB trace的含义是将 SW-C 通信数据(通过 RTE 流动)隐式(系统固有)转发到 Dlt 模块。
这是RTE和DLT之间的交互。
VFB trace的提供者为RTE,那么作为VFB trace的接受者DLT应为RTE的客户端,因此RTE模块中的参数RteVfbTraceClientPrefix(RteGeneration container中)需要被设置为"Dlt",表示VFB的接收者为DLT模块。
是否支持VFB trace以及支持哪些可追组的事件,这些仅仅需要在RTE模块中进行配置即可。
Rte生成器在生成阶段为每个VFB trace钩函数更新BswModuleEntries中的RTE Basic Software Module Description。
BswModuleEntries准确描述函数原型,DLT模块需要提供如下:
SWS_Dlt_00284,DLT模块需要符合AUTOSAR_RTE_SWS中描述的VFB trace。未来越来越多的功能被集成在同一个ECU中,这样的话,SWC之间的通信越来越集中在本地而非通过外部总线进行,那么通过RTE/VFB追踪内部通信会越来越重要。
SWS_Dlt_00276,DLT模块应提供能力去追踪所有类型的RTE规范中描述的trace事件。
SWS_Dlt_00027,BswModuleEntry提供的事件都应该对应有DLT提供的钩函数,函数的名称由RTE的BswModuleDefinition提供,应有“Rte_Dlt”开头
SWS_Dlt_00335, 钩函数的原型需要从RTE的BSWModuleDescription的BswModuleEntry中得来。
SWS_Dlt_00285,Dlt_SendTraceMessage是一个SWC的接口,等同的内部函数应被生成的钩函数所调用。
SWS_Dlt_00277, Dlt_SendTraceMessage的在钩函数中的内部代表被调用,这个调用应该为“非冗长模式”的调用。
非冗长模式:通过不发送数据总线上的变量的元数据来降低总线上的流量。可以将外部解析文件FIBEX与接收到的数据合并保存。
SWS_Dlt_00278,此钩子函数调用的有效负载应由钩子函数提供的参数填充。应提供与参数一起传输的所有数据。
SWS_Dlt_00632,参数数据应用原始格式写到有效负载中。
SWS_Dlt_00279,每个钩函数应获得它自己的ContextId。在一些情况下一些事件可以捆绑进同样的ContextId,一版这样做是因为如果大量的信号需要被追踪。
SWS_Dlt_00337, ApplicationID应为“VFBT”
SWS_Dlt_00484, 生成的trace报文的报文类型(MSTP)条目应被设置为“DLT_TYPE_MW_TRACE”, 报文trace信息(MSTI)条目应被设为“DLT_NW_TRACE_IPC”
SWS_Dlt_00280, 因为使用了“非冗长模式”,单独的报文ID应被用于Dlt_SendTraceMessage的每一次调用,报文ID的定义参考SWS_Dlt_00031: DEM(0X00000001), DET(0X00000002), Trace Messages(0X00000003)
SWS_Dlt_00281, 在每个钩函数中,都要检查ContextID的trace状态。如下示例代码。
SWS_Dlt_00282, Dlt应针对每一个VFB trace 钩函数使用一个ContextID,并因此为每一个VFB trace ContextID赋一个单独的trace状态,这可以通过一个单独的变量来完成。
SWS_Dlt_00283, 一个单独的函数应该被执行用于修改VFB钩函数的trace状态,这个函数应该与SWC的LogTraceSessionControl接口相融合。
前文提过,DEM通过调用Dlt_DemTriggerOnEventStatus函数去通知DLT,告知其DEM事件发生变化。
SWS_Dlt_00747. DLT通过提供Dlt_DemTriggerOnEventStatus接口从DEM模块获取发生变化的事件的EventID,通过这个EventID,DLT可以进一步会请求关于这个事件的更多信息。
SWS_Dlt_00475,通过Dlt_DemTriggerOnEventStatus接口,DLT模块可以比较某事件的新旧状态,如果事件状态发生变化,DLT会通过调用Dlt_SendLogMessage去发送包含该事件最新状态的LOG报文。报文包含的参数可以参照如下表:
SWS_Dlt_00377,
ApplicationID = “DEM”
ContextID = "STD0"
MessageID= 0X00000001
SWS_Dlt_00477, 由Dlt_DemTriggerOnEventData提供的EventId,并且DTCFormatType置为适合DTC值的格式,DEM可通过调用Dem_GetDTCOfEvent函数去请求DTCOfEvent条目
SWS_Dlt_00478,DLT通过调用Dem_DltGetAllExtendedDataRecords函数,可以填充EventExtendedDataRecord,EventID由Dlt_DemTriggerOnEventData提供。
SWS_Dlt_00479,DLT通过调用Dem_DltGetMostRecentFreezeFrameRecordData可以填充EventFreezeFrameData,其中EventID由Dlt_DemTriggerOnEventData提供。
在ExtendedDataRecord及冻结帧中的数据不会被DLT模块所解析,这些数据以原始数据的方式发送并由外部客户端进行解析。并且会用到一些描述性的文件,例如ODX标准文件
无论是SWC还是BSW模块都会向DET模块去报告一些错误。这些错误可通过接口Dlt_DetForwardErrorTrace直接转发给DLT.
SWS_Dlt_00430, DLT模块可以提供Dlt_DetForwardErrorTrace函数给DET
SWS_Dlt_00376
ApplicationID = "DET"
ContextID = "STD"
MessageID = 0X00000002
LogLevel = “Error”
我利用LinIf模块制造一个未初始化的错误,来调试DET和DLT之间的接口,步骤如下
接口测试: