3. SOME/IP服务接口设计与ARXML导入
SOME/IP 仿真的第一步不是打开 CANoe 建节点,而是先把“服务长什么样”用机器可读的方式定义清楚。在 AUTOSAR 体系里,这份定义就是 ARXML(AUTOSAR XML)。它描述服务接口由哪些方法、事件、字段组成,每个成员的 ID、数据类型、触发方式是什么。CANoe 通过导入 ARXML,把这些定义自动转换成工程里的数据库对象,后续的 CAPL 节点、仿真面板、测试用例都基于这些对象展开。因此本节的核心是:先理解服务接口四类成员的语义差异,再看懂 ARXML 的层级结构,最后完成一次可验证的导入。
服务接口的四类成员
SOME/IP 服务接口(Service Interface)由四种成员构成,它们的通信语义完全不同,设计时必须区分清楚。
方法(Method)是请求—响应式的调用。客户端发请求,服务端回响应,分为 Fire&Forget(只发不等)、Request/Response(等响应)两类。方法有明确的输入参数和输出参数,例如 GetVehicleSpeed() 返回 uint16 speed。
事件(Event)是服务端主动推送的通知,单向、无响应。客户端通过订阅(Subscribe)来接收,服务端在数据变化时发送。事件只携带数据,不携带请求语义,例如 SpeedChanged 事件携带当前车速。
字段(Field)是“带状态的数据成员”,它比事件更强:字段自动隐含 Getter、Setter、Notifier 三种可选访问方式。Getter 是方法,Setter 是方法,Notifier 是事件。设计时通过 hasGetter、hasSetter、hasNotifier 三个开关决定暴露哪些访问方式。字段适合表达“有当前值、可读可写、变化时通知”的量,如车速、档位、车门状态。
触发方式决定了成员何时被调用或发送:方法由客户端调用触发;事件由服务端在数据变化或周期触发;字段的 Notifier 在值变化时触发。理解这一点,才能正确选择用事件还是字段。
ARXML 文件结构解析
ARXML 是分层嵌套的 XML。顶层是 <AR-PACKAGE>,包内通过 <ELEMENTS> 容纳各类定义。服务接口对应 <SERVICE-INTERFACE> 元素,其下分三块:<METHODS>、<EVENTS>、<FIELDS>。每个方法内部用 <ARGUMENTS> 声明输入输出,方向由 DIRECTION 属性区分(IN / OUT / INOUT)。事件和字段内部用 <DATA-ELEMENT> 或 <TYPE-TREF> 引用数据类型。
数据类型通常单独定义在另一个 AR-PACKAGE 中,通过 <TYPE-TREF> 引用,例如 DEST="APPLICATION-TYPE" 指向 uint16 的应用类型。这种“定义与引用分离”的结构,使得同一数据类型可被多个服务复用。ID 分配是设计的关键:Service ID、Method ID、Event ID、Field ID 必须全局唯一且符合 SOME/IP 规范——Method ID 范围 0x0000–0x7FFF,Event ID 范围 0x8000–0xFFFF,Field 的 Notifier 占用 Event ID 空间。
下面是一段可直接参考的 ARXML 片段,描述一个带方法、事件、字段的服务接口:
<SERVICE-INTERFACE>
<SHORT-NAME>VehicleStatusService</SHORT-NAME>
<METHODS>
<METHOD>
<SHORT-NAME>GetVehicleSpeed</SHORT-NAME>
<ARGUMENTS>
<ARGUMENT>
<SHORT-NAME>speed</SHORT-NAME>
<DIRECTION>OUT</DIRECTION>
<TYPE-TREF DEST="APPLICATION-TYPE">/DataType/uint16</TYPE-TREF>
</ARGUMENT>
</ARGUMENTS>
</METHOD>
</METHODS>
<EVENTS>
<EVENT>
<SHORT-NAME>SpeedChanged</SHORT-NAME>
<DATA-ELEMENT>
<TYPE-TREF DEST="APPLICATION-TYPE">/DataType/uint16</TYPE-TREF>
</DATA-ELEMENT>
</EVENT>
</EVENTS>
<FIELDS>
<FIELD>
<SHORT-NAME>VehicleSpeed</SHORT-NAME>
<HAS-GETTER>true</HAS-GETTER>
<HAS-SETTER>true</HAS-SETTER>
<HAS-NOTIFIER>true</HAS-NOTIFIER>
<TYPE-TREF DEST="APPLICATION-TYPE">/DataType/uint16</TYPE-TREF>
</FIELD>
</FIELDS>
</SERVICE-INTERFACE>
在 CANoe 中导入并生成数据库对象
导入路径是:CANoe 工程 → Simulation Setup 或 Communication Setup → 右键 Databases → Add → 选择 ARXML 文件。CANoe 会解析文件并生成 SOME/IP 数据库对象。导入后需要检查三件事:
- 服务是否出现在 SOME/IP 服务列表中:在 Communication Setup 的 SOME/IP 视图下,应能看到
VehicleStatusService,Service ID 为 0x1234。 - 成员 ID 是否正确映射:展开服务,方法
GetVehicleSpeed应显示 Method ID 0x0001,事件SpeedChanged显示 Event ID 0x8001,字段VehicleSpeed显示 Field ID 0x4001 及三个访问开关。 - 数据类型是否解析成功:若
TYPE-TREF指向的类型未找到,CANoe 会报 unresolved reference,此时需确认数据类型所在的 ARXML 是否一并导入。
导入成功后,数据库对象即可在 CAPL 中使用。例如在服务端节点中,可以用 SomeIpSetFieldValue 更新字段值,用 SomeIpSendEvent 发送事件;在客户端节点中,用 SomeIpCallMethod 发起方法调用。这些 API 的参数直接对应 ARXML 中定义的成员名和数据类型,因此 ARXML 定义的准确性直接决定后续仿真代码能否编译通过。
完成导入后,建议在 CANoe 的 SOME/IP Service Explorer 中做一次快速验证:手动触发一次方法调用,观察 Trace 窗口是否出现 Request/Response 报文;再触发一次字段更新,观察是否产生 Notifier 事件报文。若两者都能在 Trace 中看到正确的 Service ID、Method ID / Event ID 和负载数据,说明 ARXML 定义与 CANoe 数据库对象已经一致,可以进入下一步的节点仿真与测试用例设计。