4. 软件组件SWC
ARXML,全称 AUTOSAR XML。说白了,它就是 AUTOSAR 世界的通用语言。所有工具链之间的数据交换,都靠它。
我刚接触 AUTOSAR 时,第一反应是:这玩意儿怎么这么复杂?一个配置文件动辄上万行。后来做项目多了才明白,ARXML 的结构其实非常规整。你只要掌握了它的骨架,剩下的就是往里面填内容。
4.1 ARXML 文件结构
一个标准的 ARXML 文件,长什么样?我直接给你看一个最小示例:
<?xml version="1.0" encoding="utf-8"?>
<AUTOSAR>
<AR-PACKAGES>
<AR-PACKAGE>
<SHORT-NAME>MyProject</SHORT-NAME>
<ELEMENTS>
<!-- 这里放具体的 AUTOSAR 元素 -->
</ELEMENTS>
</AR-PACKAGE>
</AR-PACKAGES>
</AUTOSAR>
根节点永远是 <AUTOSAR>。里面包着一层 <AR-PACKAGES>,再往下是具体的 <AR-PACKAGE>。每个 Package 就是一个命名空间,用来组织你的模块。
AR-PACKAGE 内部,核心是 <ELEMENTS> 标签。所有具体的定义——数据类型、组件、接口——都放在这里面。
4.2 数据类型定义
AUTOSAR 的数据类型体系,分三层。我画了张图,帮你理清关系:
为什么要分三层?我举个例子。你在应用层定义了一个"车速"变量,单位是 km/h。这是应用数据类型。到了底层,它可能被实现为一个 16 位无符号整数。这是实现数据类型。再往下,这个 16 位无符号整数在芯片上怎么存储?这是基础类型。
三层分离的好处是:应用层不用关心底层实现。你换了个芯片,基础类型变了,但应用层的"车速"定义不用改。
4.2.1 应用数据类型 (ApplicationDataType)
这是最上层,直接对应物理世界的概念。定义方式很简单:
<APPLICATION-DATA-TYPE>
<SHORT-NAME>EngineTemp</SHORT-NAME>
<CATEGORY>VALUE</CATEGORY>
<SW-DATA-DEF-PROPS>
<SW-IMPL-POLICY>STANDARD</SW-IMPL-POLICY>
</SW-DATA-DEF-PROPS>
</APPLICATION-DATA-TYPE>
CATEGORY 字段很关键。VALUE 表示标量,ARRAY 表示数组,RECORD 表示结构体。我见过不少新手把 RECORD 当 VALUE 用,结果工具链报错找半天。
4.2.2 实现数据类型 (ImplementationDataType)
这一层决定了变量在内存中的实际表示。看个例子:
<IMPLEMENTATION-DATA-TYPE>
<SHORT-NAME>uint16_Impl</SHORT-NAME>
<CATEGORY>VALUE</CATEGORY>
<BASE-TYPE-REF DEST="SW-BASE-TYPE">/BaseTypes/uint16</BASE-TYPE-REF>
</IMPLEMENTATION-DATA-TYPE>
这里引用了基础类型 uint16。基础类型通常由芯片厂商提供,你不需要自己定义。
4.3 组件描述
组件,就是 AUTOSAR 里的软件单元。一个组件可以是一个传感器驱动、一个控制算法、一个诊断模块。
组件描述的核心,是定义它的"接口"——它需要什么数据,输出什么数据。我习惯把组件想象成一个黑盒子。你不需要知道里面怎么实现的,只要知道它跟外界怎么交互。
4.3.1 原子软件组件 (Atomic SWC)
最常用的组件类型。一个 Atomic SWC 包含:
- 端口 (Ports):组件与外界的通信接口
- 内部行为 (Internal Behavior):组件的运行实体,比如 Runnable
- 数据映射:端口数据与内部变量的对应关系
看一个完整的组件定义示例:
<ATOMIC-SW-COMPONENT-TYPE>
<SHORT-NAME>SpeedController</SHORT-NAME>
<PORTS>
<R-PORT-PROTOTYPE>
<SHORT-NAME>SpeedInput</SHORT-NAME>
<REQUIRED-COM-SPECS>
<NONQUEUED-RECEIVER-COM-SPEC/>
</REQUIRED-COM-SPECS>
</R-PORT-PROTOTYPE>
<P-PORT-PROTOTYPE>
<SHORT-NAME>ControlOutput</SHORT-NAME>
</P-PORT-PROTOTYPE>
</PORTS>
<INTERNAL-BEHAVIORS>
<SWC-INTERNAL-BEHAVIOR>
<SHORT-NAME>Behavior</SHORT-NAME>
<EVENTS>
<TIMING-EVENT>
<SHORT-NAME>PeriodicRun</SHORT-NAME>
<START-ON-EVENT-REF DEST="RUNNABLE-ENTITY">/SpeedController/Runnable1</START-ON-EVENT-REF>
<PERIOD>0.01</PERIOD>
</TIMING-EVENT>
</EVENTS>
<RUNNABLES>
<RUNNABLE-ENTITY>
<SHORT-NAME>Runnable1</SHORT-NAME>
<CAN-BE-INVOKED-CONCURRENTLY>false</CAN-BE-INVOKED-CONCURRENTLY>
</RUNNABLE-ENTITY>
</RUNNABLES>
</SWC-INTERNAL-BEHAVIOR>
</INTERNAL-BEHAVIORS>
</ATOMIC-SW-COMPONENT-TYPE>
这个组件叫 SpeedController。它有一个输入端口 SpeedInput,一个输出端口 ControlOutput。内部有一个 Runnable,每 10 毫秒执行一次。
4.3.2 端口与接口
端口分两种:
| 端口类型 | 方向 | 典型用途 |
|---|---|---|
| R-Port (Required) | 输入 | 读取传感器数据、接收其他组件的计算结果 |
| P-Port (Provided) | 输出 | 发送控制指令、发布计算结果 |
| PR-Port (Required/Provided) | 双向 | 客户端-服务器通信中的请求/响应 |
端口必须绑定一个接口。接口定义了端口上传输的数据结构。常用的接口类型有:
- Sender-Receiver 接口:数据发布/订阅模式。一个发,多个收。适合周期性数据,比如车速、转速。
- Client-Server 接口:请求/响应模式。一个客户端调用,一个服务器响应。适合诊断请求、参数配置。
4.3.3 组件间的连接
组件定义好了,怎么把它们连起来?通过 <SW-CONNECTOR>:
<SW-CONNECTOR>
<SHORT-NAME>Conn_SpeedToControl</SHORT-NAME>
<STARTING-PORT-REF DEST="R-PORT-PROTOTYPE">/SpeedController/SpeedInput</STARTING-PORT-REF>
<ENDING-PORT-REF DEST="P-PORT-PROTOTYPE">/SensorComponent/SpeedOutput</ENDING-PORT-REF>
</SW-CONNECTOR>
这个连接把 SensorComponent 的输出端口 SpeedOutput,连到了 SpeedController 的输入端口 SpeedInput。数据流就通了。
嗯,这里要注意:连接时,两个端口的数据类型必须一致。否则工具链会报类型不匹配的错误。我见过有人把 uint8 连到 uint16 上,编译能过,但运行时数据截断了。
4.4 本章小结
ARXML 的核心就三件事:
- 文件结构:AUTOSAR 根节点 → AR-PACKAGES → 具体元素
- 数据类型:应用数据类型 → 实现数据类型 → 基础类型,三层映射
- 组件描述:定义端口、接口、内部行为,然后通过连接器组装