在我学习SOME/IP过程中,涉及到了AUTOSAR常用的数据类型定义,手头上正好有Vector 的DaVinci工具,想着能否从AUTOSAR层面再递进一个层次对这个话题的学习,研究研究能否用DaVinci复刻一个之前一直用的那个SOME/IP示例数据库。
我手头有DaVinci的Developer和Configurator的License,可我没有参与具体的项目没有SIP包,所以我的电脑连Configurator装都装不上去,联系Vector售后看是否有Demo版本的SIP,至少采购DaVinci的License花了钱的至少能让我熟悉熟悉,可惜是沟通了好久无果,遗憾只能只学习学习DaVinci Developer,暂时没机会去了解Configurator了。
详细研究了一段时间Developer这个工具,我意识到我并不能从0复刻出来之前那个数据库。根据AUTOSAR体系结构的定义最高抽象为三层:应用软件层(Application Layer),运行时环境层(Runtime Environment, RTE)和在微控制器上运行的基础软件层(Basic Software, BSW)。而DaVinci Developer更多是对应用软件层做接口设计,对于系统相关的设定是不在其负责的范围内。对于我想要做的事情:设定ADAS和CAMF两个SWC并位于两个ECU或两个域中,其通过SOME/IP进行连接,传输的内容是一个多层嵌套的复杂结构体,这三件事可能只有第三个可以在Developer工具中完成,甚至ADAS和CAMF之间的接口,都体现不出来这是一个SomeIP Service,下边会具体介绍。
我的是Classic AUTOSAR工具,其主要编程语言是C,在图形化界面设计完成各个功能模块SWC后,可以生成对应的Contract Phase Headers 和Implementation Templates,从中可以看到工具将其定义的数据类型整理成C语言支持的数据结构,以及通过大量的宏定义将一些常量命名为人类友好可读的形式。还有就是工具定义了很多的接口用于SWC与之后的RTE进行功能调用数据传输。对于功能模块SWC也生成了空函数,便于后期具体逻辑填入从而实现完整的功能。 整体来说我对Vector DaVinci Developer的理解是,帮助我们在一个C语言功能开发的项目中定义头文件,通过工具的严谨性来保证代码开发方式下人类容易发生的低级错误,在此同时也会对C语言的灵活性做出一定的限制,避免一些C语言骚操作的使用不当造成未知的隐患。整体能感受到工具的目是降低数据类型定义的复杂度和出错概率,提高C语言语法使用的正确性。我们一步一步看一下工具的使用吧。
首先在DaVinci Developer中新建一个Workspace,对于要使用的AUTOSAR的版本我选择了最新的,在这儿如果是具体项目使用,就需要和整个项目所用的版本保持一致。从这个下拉框我们也可以看到,对于AUTOSAR版本的定义之前是X.Y.Z的形式,从某一个节点后改成了RYY-MM的格式,现在这种形式感觉直观了很多。
接下来我们整体看下这个工具的主界面,比较常用到的就是下边的几个框,其中1是来查看我们定义的不同元素的视图切换按钮,通过Types/Packages/Files不同维度,来看我们定义的Data Types/ Constants/ Components 等不同层级的元素。框2即为查看具体内容的地方。这次学习笔记后边大部分内容主要就是介绍这里边的各个项。
图3的框是灰的,在手册中看到这是由于我的Workspace是单独由DaVinci Developer生成而造成的,如果是配合了DaVinci Configurator的话,框3的功能既可以解锁。不过通过其他的途径我们可以使用其部分内容比如Software Design,Data Type Mapping等,后边也会有提到。
框4是的按钮可以按照AUTOSAR标准来检查我们的设计和配置是否有错误。可以帮我们做一些标准一致性上的检查,还是很实用的。框5是看我们鼠标当下选中的元素的具体属性信息的。
模仿之前数据库我计划是设计ADAS/CAMF两个SWC,之间的数据接口使用的TrafficSignDetection结构体。我额外设计了一个叫做Preprocessing的SWC,来模拟一个DistanceToSign的输入。在DaVinci Developer设计SWC时候有Composition Component Types 和Application Component Types两个概念,主要的区别是Composition可以理解成功能整体,而Application是组成整体的最小模块。Composition可以包含其他的Composition和Application,而Application是最小逻辑单位了不能再继续拆分。在这里我配置了一个ADAS_CAMF_Composition,我们假设这即为摄像头自动驾驶系统,然后这个系统由三个子模块组成:ADAS, CAMF 和Preprocessing,如下图。
双击我们新建的Composition,即进入了Software Design的界面了。可以看下图我这里的结构,一个Composition下挂3个Application,选中顶层Composition可在中间Interface Graphic界面看整个功能的对外接口,当前我的示例中输入为一个DistanceToSign_Application_Port_Interface_Comp_Input, 输出为DistanceToSign_Application_Port_Interface_Comp_Output。
切换在Structure Graphic视图,可以直观看到整个功能里边的模块是信号怎么流传的。我的学习示例中整个功能唯一的输入先送到Preprocessing模块,然后再原封不动透传到ADAS模块,假设再ASAS里我们做了一些处理,然后输出一个TrafficSignDetection结构体到CAMF,再在CAMF里边做一些处理,输出一个DistanceToSign作为整个功能的输出。
接下来从0开始看下这个例程中数据类型是怎么配置的。以Speed和signDistance为例,下边截图是对于Speed的Unit、CompuMethod 以及 Int To Phys 页面的配置截图。
其中可以看到,Scaling相关的配置,在AUTOSAR架构以及Vector DaVinci软件中是被称作Compu Methods的。里边设置了数据集是开区间还是闭区间,以及物理量和总线值得换算关系是什么,即Factor和Offset的配置。
Data Constraints是对于数据物理值的限制,比如是之前SomeIP学习时候的Reliability,数据结构支持0-255,但是其意义上大于100的值就意义不大了。在DaVinci配置中,可以通过这个功能来进行设置。
再下来看下怎样将准备好的数据类型,运用到具体的Component的信号里边去的,在DaVinci中有Implementation Data Types (IDT)和Application Data Types(ADT)两种,其中的区别是Implementation 是与具体的硬件以及编译环境有关,只能使用环境支持的数据类型,若要对SWC进行硬件以及环境的迁移这一块需要适配;而Application是完全与硬件无关的,这里我们可以按照我们的需求使用Autosar支持的任意数据类型及其组合。在这两个之间需要走一个映射,这个映射叫做DataTypeMapping。我们在后边会看一下这个示例例程的Mapping配置。
上图中,在IDT的Unit/Compu Method以及Data Constraint的配置使用上有的一定的限制,需要是数据通用类型、基础类型或者ECU及编译环境确定支持的类型。
我们再看一个比较复杂的数据结构:TrafficSignDetection,如下截图。
首先DetectedTrafficSigns是一个长度为3的数组,其中数据的类型为DetectTrafficSign,而DetectTrafficSign在DaVinci中是一个Record类型,对应到C语言中是Struct结构体,其中又包括了SignType,DistanceToSign以及Reliability三个元素。点击我截图标识的按钮可以一层一层拆包看到DistanceToSign是使用的我们定义的signDistance的Data Type。
然后是下图在ADT里边的数据类型定义,主要区别可能是在signDistance中多了Compu Method设定,这个在IDT里边设置会报错,可能的原因如上。
接下来再看下在Component里边信号接口是怎么定义的,以CAMF具体为例,在这个SWC共有两个信号接口,一个是ADAS_CAMF_Interface输入,一个是叫做DistanceToSign_Application_Port_Interface的输出。并且这两个都是Application Ports的类型,并不是Service Ports。主要是的原因是Vector DaVinci Developer主要是设计应用层SWC的接口定义,对于下层系统承载方式是无所谓的。虽然我的期望是这个DetectTrafficSign通过SomeIP在两个ECU模块中传输,但是在SWC层级还是属于Applications Ports。真正的SomeIP承载映射成一个Event Notification是属于DaVinci Configurator 的事情了。
通过上图的初始值也可以看到TrafficSignDettection是一个嵌套了好几层的结构体{{{0,0,0},{0,0,0},{0,0,0}}}。
我们顺便看一下在定义SWC时候,这里的Service Ports都有些什么。
根据上边的截图,可以看到默认情况下有很多储存相关的服务接口,如果我没有理解错的话,通过这些服务在SWC应用层可以方便地对储存数据进行操作,而这个功能调用的背后,是RTE结合实际的硬件进行的具体实现。我自己定义了一个示例Service,可以自定义入参以及返回值,并且入参可以设置是In还是Out如下图。
在生成的代码中,可以看到传参的数据传入传出是通过是否传入的是否是一个地址信息来实现区分的。\
* Service Calls:
* ==============
* Service Invocation:
* ——————-
* Std_ReturnType Rte_Call_myCS_myOperation(float32 myInData, float32 *myOutData)
* Synchronous Service Invocation. Timeout: None
* Returned Application Errors: RTE_E_myCS_myError, RTE_E_myCS_myError
看完具体的一个SWC接口的示例后,我们看下一个Composition包含其中SWC以及外部接口在内所有的信号定义。其中DistanceToSign_Application_Port_Interface_Comp_Input是我命名的Compostion整体的输入,而DistanceToSign_Application_Port_Interface_Comp_Output是我命名的Composition整体的输出。其他的信号是SWC之间流转信号的名字。
最后看下ADT和IDT的映射是什么样,我们需要建议一个新的Type Mapping Sets,将硬件无关的ADT与硬件环境有关的IDT做一个关联,如下图。
其他的一些配置我没有截图了,比如是SWC的触发方式配置等。感兴趣小伙伴可以看我拿来学习用的这个工程文件。由于只有DaVinci Developer而没有DaVinci Configurator,可以学习到的以及了解的功能极为有限,生成的ARXML由于缺少必要的系统层描述也不能直接在CANoe里边用起来。对于生成的代码则只有一些头文件数据,离真正能够运行起来还差着十万八千里,一开始我想尝试看看能不能在x86跑起来,后来了解明白后感觉这难度就像是捡了一个鼠标垫然后打算配齐一台电脑的感觉,就没再继续了。
大致就记录这一些了,原计划是完整复刻SOME/IP学习时候的数据库,但是工具限制只能做一半。另外还有很多很多不清楚的地方,比如是设置Scaling(Factor, Offset)在多个地儿都能设置比如是在Unit,Compu Method, IDT, ADT等,在不同的地方设置有什么区别,只需要设置一次还是都需要设置,设置重复了会怎样等等问题,感觉不结合实际的项目很难了解清晰,看之后有没有机会跟着一个项目学习学习吧。我先把我截至目前的学习笔记整理了出来,希望对一些有需求的小伙伴能够有所帮助。