|
汽车零部件采购、销售通信录 填写你的培训需求,我们帮你找 招募汽车专业培训老师
AUTOSAR入门-Dcm模块
先复习下AS代码之前做过的试验:AUTOSAR入门-基于以太网诊断。我们通过网络发送DoIP报文,实现了对汽车EcuReset的功能,报文通过的模块依次为:网卡驱动-》网络接口-》LWIP网络协议栈-》SoAd模块-》DoIP模块-》PduR模块-》Dcm模块。
我们倒着从功能角度入手,结合AUTOSAR规范从Dcm模块开始讲解下AS里面里面的处理过程,Dcm模块是我们第一个讲的AUTOSAR的模块,其他模块的所有套路在AUTOSAR框架里面都是相通的,这里我希望能做到抛砖引玉的效果。
0. 准备工作
研究AUTOSAR规范,首先要知道官网:https://www.autosar.org
官网资料是其他资料的源头,最权威的内容, 通常工作中会像字典一样反复查阅。首先打开:
https://www.autosar.org/nc/document-search/
按下图下载规范:
AUTOSAR_SWS_DiagnosticCommunicationManager.pdf
或者直接输入如下网址查看:
https://www.autosar.org/fileadmin/user_upload/standards/classic/19-11/AUTOSAR_SWS_DiagnosticCommunicationManager.pdf
首先说下这个文档该怎么看,从这文件的名字上有SWS,这个意思是软件规范,也是我们作为开发人员主要看的内容。其他的前缀解释如下:
EXP: 即Explaination"解释",详细介绍论题MMOD: 即MetaModel"元模型",介绍 AUTOSAR元模型MOD: 即Model"建模",介绍建模的原理RS: 即RequirementSpecification"需求规范", 详细介绍需求SRS: 即SoftewareRequirement Specification"软件需求规范", 描述所有软件模块的规范SWS: 即SoftewareSpecification"软件规范", 介绍软件模块设计和实现的规范TPS: 即TemplateSpecification"模板规范", 详细介绍元模型TR: 即TechnicalSpecification"技术规范",详细介绍技术规范
然后SWS后面的
DiagnosticCommunicationManager就是功能模块的命名,首字母可以看出来就是DCM。
上图中红色标识出来的就是我们需要重点关注的,本文也是按照这个顺序进行展开,下面带着大家按这个文档来看一遍来,了解Dcm。
1. 简介和功能介绍
打开这个pdf文档,第一部分如下:
重点看下这个图,通过诊断工具连接到汽车上的板卡上,可以跟板卡里面的Dcm模块通信。那么通信干什么呢?接着往下看:
这段英语翻译过来为:
Dcm模块确保诊断数据流并管理诊断状态,特别是诊断会话和安全状态。此外,Dcm模块根据诊断状态检查是否支持诊断服务请求,以及服务是否可以在当前会话中执行。
那么提供什么服务呢?答案就是UDS和OBD服务,这是两种应用协议,这里我们以UDS为例说明,UDS(Unified Diagnostic Services)里面有什么服务呢?
查看ISO14229 手册(公众号回复ISO获取):
从第9章开始,有这么多服务,用到哪个就去查这个手册。
下面这个图更加直观一点:
诊断可以提供什么服务是不是一目了然,比如车坏了,要知道怎么坏的,可以去读数据。可以设置参数写数据,可以控制设备比如重启,总之跟车交互的功能基本都在里面。
下面继续以之前做的以太网诊断为例进行说明,我们发的DoIP报文如下:
报文里面的11 01就是包装的UDS报文的内容,通过查询上面的SID,我们知道11是复位,继续查01是硬件复位的意思:
上面说了挺多的介绍,业务方面介绍差不多了,大家应该知道Dcm是干什么的了,就是实现UDS里面规定的服务。但是只讲概念是没有灵魂的,对于程序员来说:
Talk is cheap,show me the code!
打开AS代码,先找到Dcm代码的位置:
Dcm_Dsd.c中selectServiceFunction()函数里面就是对于UDS报文id的处理,
例如我们上面的0x11如下:
然后01按照ISO14229标准是硬重启,查看DspUdsEcuReset()函数:
处理完毕,也是按照ISO14229的标准对外部诊断程序进行报文回应。其他的服务执行逻辑根据switch自己查看代码。可以自己加log打印,做实验看看代码是不是跑到这里了,应该是挺有意思的事情。跟打游戏一样,体验下代码被你控制的感觉。
在1简介和功能介绍中,有一个Dcm在AUTOSAR位置的图:
可以参考:汽车电子构架演进(二)AUTOSAR的组成和演进,了解Dcm的位置。
2. 缩略词: 看看拓展下知识面就可以,这里不说明。
3. 相关文档: 可以了解下
4 假定和约束: 这里不研究了。
5. 依赖模块
依赖模块这个列举出了,跟Dcm模块交互的其他模块,可以了解到Dcm在ATUOSAR中的位置:
Dcm和Dem的交互:
DEM模块提供了检索与故障内存相关的所有信息的功能,以便Dcm模块能够通过从故障内存中读取数据重新响应测试人员的请求,通俗的讲就是Dcm能够读取Dem记录的DTC信息。
Dcm和PduR的交互:
PduR模块接收和发送诊断数据。PduR为Dcm模块提供一个与具体通信协议无关的接口。
Dcm和ComM模块的交互:
Dcm模块可以指示状态“活动”和“非活动”用于诊断通信。Dcm模块提供了处理通信需求“完全/静默/无通信”的功能。此外,Dcm模块提供了在ComM模块要求时启用和禁用诊断通信的功能。
SWC通过和RTE接口和Dcm交互:
Dcm模块在完成诊断功能的时候需要通过RTE接口来读写/函数调用其他SWC的数据/服务。
BswM和Dcm模块的交互:
如果Dcm的初始化是从引导加载程序跳转的结果,则Dcm通知BswM应用程序已更新。Dcm也向BswM指示通信模式的改变。
上面的这些交互都是以函数为基础的,具体到代码里面,还是以:AUTOSAR入门-基于以太网诊断 为例子说明。
当报文到达PduR模块的时候,PduR模块需要调用Dcm模块的代码,把报文传递给Dcm模块:PduR模块-》Dcm模块。
在AS代码上需要处理PduR模块调用过来的两个函数,在Dcm.c中:
Dcm_ProvideRxBuffer()//开始传输报文
Dcm_RxIndication()//传输报文完毕
6. 需求跟踪暂时不关注
7. 功能规格
功能规格规定了Dcm的软件组成,
这里先打个比方,比如到医院看病,首先有接待的部门,导医台。然后知道去哪个科室看不了就挂号。最后到你了就去科室找医生看病。Dcm主要由三部分组成:Dsl(导医台)、Dsd(挂号系统)、Dsp(科室看病),如下图所示:
查看官网文档解释如下:
翻译如下:
为了定义Dcm模块的功能,Dcm SWS将Dcm模块建模为以下子模块:
1)Diagnostic Session Layer诊断会话层(DSL)子模块:
DSL子模块负责保证与诊断请求和响应相关的数据流,监督和保证诊断协议定时,管理诊断状态(特别是诊断会话和安全)。
2)Diagnostic Service Dispatcher诊断服务调度程序(DSD) 子模块:
DSD子模块处理诊断数据流。子模块:
-通过网络接收新的诊断请求并将其转发给数据处理器。
-当数据处理器(如DSP子模块)触发时,通过网络传输诊断响应。
3)Diagnostic Service Processing诊断服务处理 (DSP)子模块:
DSP子模块处理实际的诊断服务请求(分别为子服务请求)。
下面还是以PduR发来的报文为例,进行说明
1)Dsl(导医台)负责接待
例如接收到PduR模块过来的消息后,如何处理,代码:
Dcm_ProvideRxBuffer函数
Dcm_ProvideRxBufferDslProvideRxBufferToPdur(dcmRxPduId, tpSduLength, (constPduInfoType**)pduI nfoPtr);if (findRxPduIdParentConfigurationLeafs(dcmRxPduId,&protocolRx, &mainConnection, &conn ection, &protocolRow, &runtime)) {if (externalRxBuffer->pduInfo.SduLength >=tpSduLength) { /** @req DCM443 */if ((runtime->externalRxBufferStatus == NOT_IN_USE)&& (externalRxBuffer->externalBufferRuntimeData->status ==BUFFER_AVAILABLE)) { externalRxBuffer->externalBufferRuntimeData->status = BUFFER_BUSY; runtime->diagnosticRequestFromTester.SduDataPtr =externalRxBuffer->pduInfo.SduDataPtr; runtime->diagnosticRequestFromTester.SduLength = tpSduLength; *pduInfoPtr = &(runtime->diagnosticRequestFromTester); runtime->externalRxBufferStatus = PROVIDED_TO_PDUR; ret= BUFREQ_OK;}
根据dcmRxPduId在Dcm的配置文件(scons studio生成,10中会说明)中找到对应的配置,如果externalRxBuffer没被使用,有空间,那么runtime就指向这个externalRxBuffer 最后返回OK。整个处理过程在DSL,会话层面就处理完毕了。
Dcm_RxIndication函数
Dcm_RxIndicationDslRxIndicationFromPduR(dcmRxPduId, result); runtime->externalRxBufferStatus = PROVIDED_TO_DSD; /**@req DCM241 */if (runtime->externalTxBufferStatus == NOT_IN_USE) { ASLOG( DCM, ("ExternalTx buffer available, we can pass it to DSD.\n")); } DsdDslDataIndication( // qqq: We are inside a critical section. &(runtime->diagnosticRequestFromTester), rotocolRow->DslProtocolSIDTable, /** @req DCM035 */ protocolRx->DslProtocolAddrType, mainConnection->DslProtocolTx->DcmDslProtocolTxPduId, &(runtime->diagnosticResponseFromDsd), dcmRxPduId);}
2)Dsd(挂号系统)负责排队分配医生
下面进入Dsd模块进行分发处理
DsdDslDataIndication 传入参数操作 dsdDslDataIndication = TRUE; //挂号成功,等待排队
把全局变量dsdDslDataIndication 置位了,在Dcm模块的轮询函数,Dcm_MainFunction(void)中
Dcm_MainFunction(void)if (dsdDslDataIndication) { dsdDslDataIndication = FALSE; DsdHandleRequest(); //排队到了}
进行任务分发,
DsdHandleRequestcurrentSid = msgData.pduRxData->SduDataPtr[0];if (lookupSid(currentSid, &sidConfPtr)) { result =askApplicationForServicePermission(msgData.pduRxData->SduDataPtr,msgData.pduRxData->SduLength);if (result == E_OK) { selectServiceFunction(currentSid);//看病}
SduDataPtr 就是UDS报文11 01:02 fd 80 01 00 00 00 06 0e 80 00 22 1101
currentSid 就是报文中的11
selectServiceFunction(uint8 sid)switch (sid){case SID_ECU_RESET:DspUdsEcuReset(msgData.pduRxData, msgData.txPduId, msgData.pduTxData);//给出治疗方案}
到这里DSD完成了分发,接下来由DSP模块进行处理
3)Dsd(科室医生)负责看病干活
DspUdsEcuResetreqResetType = pduRxData->SduDataPtr[1];switch (reqResetType) { caseDCM_HARD_RESET: dspUdsEcuResetData.resetType = reqResetType;switch( DcmE_EcuReset(dspUdsEcuResetData.resetType) ) {case E_OK: pduTxData->SduDataPtr[1] = reqResetType; pduTxData->SduLength = 2; DsdDspProcessingDone(DCM_E_POSITIVE_RESPONSE);break;}
reqResetType就是11 01中的01,对应DCM_HARD_RESET
DcmE_EcuReset为功能实现函数,实现Ecu的重置,如果执行成功,则填充pduTxData信息,有DsdDspProcessingDone函数,按照收报顺序的逆序再发给客户端。上面按照收诊断报文的逻辑对Dcm模块的框架进行了说明。
8. API说明
对代码的实现进行了规范,主要分为两部分:类型定义,函数定义。
类型定义,下面看一个例子:
这对代码的规范,简直到了限定死了的地步,命名,取值范围,在那个文件中定义都规定好了。可以自己在AS代码里面Dcm.h里面看看有这个定义没。
函数定义,看一个例子:
返回Dcm模块的版本号。对函数的写法,参数的写法,返回值,在那个文件中声明都规定的明明白白。
查看代码,在Dcm.c里面,实现的函数比较少(AS代码中的arccore代码比较旧实现的比较少,最新的基本都实现了,见
https://github.com/openAUTOSAR/classic-platform,可以进行移植到AS平台),我们可以对照着研究下。
下面说下AUTOSAR模块代码运行的套路:
1)首先就是初始化:Dcm_Init(void)
2)然后就是轮询执行一个函数:Dcm_MainFunction(void)
3)如果有其他模块进行交互,先接待,挂到队列上,2中轮询到了进行处理。
例如医院看病挂号Dsl成功后,Dsd里面就是轮询一个一个的处理排队的病人,就靠的这个Dcm_MainFunction。
9. 时序图
规定了各个模块交互时候,函数按时间的调用情况,这里以收取PduR模块发来的包的情况说明:
各个模块间报文传递都需要调用三个函数
AAA_BBBTpStartOfReception:BBB发给AAA,准备接收报文
AAA_BBBTpCopyRxData:BBB发给AAA,拷贝报文
AAA_BBBTpRxIndication:BBB发给AAA,接收成功确认
10. 配置相关
规定了配置工具也就是工具链如何实现,AS平台有自己的工具链。下面介绍下:首先看下代码里面配置相关的部分,在初始化的时候,需要用到配置DCM_Config
DCM_Config在build/posix/x86/ascore/config/Dcm_LCfg.c中定义,
这个文件里面有一个大的全局结构体变量,结构体的子项还是结构体,一时无法看懂,不急,这个变量可以通过工具配置和生成,参考:
AUTOSAR入门-AS平台工具命令和目录介绍
AS平台输入命令scons studio启动工具链,如下:
配置完毕,点击File-》Generate就可以生成c代码了。
AUTOSAR的方法论就是,工具链生成配置代码+固定的BSW代码一块参与编译,最后在板子上运行。
后记:
再强调一遍,做下之前的实验:AUTOSAR入门-基于以太网诊断,然后自己动手打log调试,结合代码来看AUTOSAR的各个模块。另外多看几遍AUTOSAR官网文档 ,AUTOSAR的所有模块的文档都是按照这个格式写的,所以看完一个其他的模块就容易多了,后续就不吃力了。
满满的干货,看到这里,想学AUTOSAR又不知道怎么学,或者没动力的朋友,可以抽点时间操作下了,师傅领进门,修行靠个人。
Talk is cheap,show methe code!后续会继续更新,纯干货分享,无广告,不打赏,欢迎转载,欢迎评论交流!
往期见话题标签:AUTOSAR入门 |
|