AUTOSAR CP Software Component Template — 零基础学习教程

面向嵌入式软件工程师的 AUTOSAR 入门指南

本教程基于 AUTOSAR CP R25-11 Software Component Template 官方文档编写,
适合有 C 语言嵌入式开发经验、但零 AUTOSAR 基础的工程师。
技术术语保留英文原文,便于对照官方文档和工具链。


前言:为什么嵌入式工程师需要学习 AUTOSAR

如果你是一名嵌入式工程师,你可能会问:我写裸机代码或者用 RTOS 写了好多年了,为什么要学 AUTOSAR?

想象这样一个场景:你的公司为不同车厂做控制器,每个车厂要求不同的功能组合。每次换平台,整个软件几乎要重写。更糟糕的是,不同项目的代码风格、架构、通信方式完全不同,维护成本极高。

AUTOSAR(AUTomotive Open System ARchitecture)就是为了解决这个问题而生的。它定义了一套标准化的软件架构,让软件组件(Software Component)可以像乐高积木一样,在不同的 ECU 上复用、替换、组合。

对于嵌入式工程师来说,学习 AUTOSAR 意味着:

  • 理解汽车电子行业的"通用语言"
  • 能够设计可复用、可移植的应用层软件
  • 掌握从功能需求到 ARXML 配置的完整流程
  • 在职业发展中获得更强的竞争力

本教程将带你从零开始,逐步掌握 AUTOSAR Software Component Template 的核心概念。不需要任何 AUTOSAR 前置知识,只需要你有 C 语言基础和基本的嵌入式开发经验。


第1课:AUTOSAR 全景概览

学习目标

  • 理解 AUTOSAR 是什么、解决什么问题
  • 区分 Classic Platform (CP) 和 Adaptive Platform (AP)
  • 掌握 AUTOSAR 分层架构的全局视图
  • 理解 Software Component Template 在其中的位置

1.1 什么是 AUTOSAR

AUTOSAR 全称是 AUTomotive Open System ARchitecture(汽车开放系统架构)。它不是一个具体的软件产品,而是一套标准和规范

打个比方:USB 标准定义了设备如何连接电脑——不管你是鼠标、键盘还是U盘,只要遵循 USB 标准就能即插即用。AUTOSAR 对于汽车软件也是类似的——它定义了软件组件如何通信、如何配置、如何部署,使得不同供应商的软件可以协同工作。

AUTOSAR 要解决的核心问题:

  • 可移植性:同一份应用层代码可以在不同 ECU 硬件上运行
  • 可扩展性:新功能可以像插件一样添加,不需要推翻现有架构
  • 可维护性:标准化的接口和架构让代码更容易理解和修改
  • 多供应商协作:OEM 和不同 Tier-1 供应商可以独立开发各自的软件模块

1.2 Classic Platform vs Adaptive Platform

AUTOSAR 有两个主要平台:

Classic Platform (CP) — 本教程的主题

适用于资源受限的实时 ECU(如发动机控制、制动系统、车身控制)。特点包括:

  • 静态配置(编译时确定所有行为)
  • 强实时性保证
  • 运行在微控制器(MCU)上
  • 使用 C 语言实现
  • OS 基于 OSEK/VDX

Adaptive Platform (AP)

适用于高性能计算平台(如自动驾驶、车载信息娱乐)。特点包括:

  • 动态配置(运行时可以更新服务)
  • 基于 POSIX 操作系统(如 Linux)
  • 使用 C++14/17 实现
  • 支持面向服务通信(SOME/IP, DDS)

对于嵌入式工程师来说,Classic Platform 是最常见的起点。

1.3 AUTOSAR 分层架构

+-----------------------------------------------------------+
|              Application Layer (应用层)                     |
|   +----------+  +----------+  +----------+                |
|   | SWC-A    |  | SWC-B    |  | SWC-C    |                |
|   | (传感器) |  | (控制算法)|  | (执行器) |                |
|   +----RTE---+--+---RTE----+--+---RTE----+                |
+-----------------------------------------------------------+
|              RTE (Runtime Environment)                     |
|        运行时环境 — 应用层与底层之间的桥梁                     |
+-----------------------------------------------------------+
|              BSW (Basic Software)                          |
|  +----------+  +----------+  +----------+  +----------+   |
|  | Services |  | ECU      |  | COM      |  | Memory   |   |
|  | Layer    |  | Abstract |  | Stack    |  | Stack    |   |
|  +----------+  +----------+  +----------+  +----------+   |
|  +----------+  +----------+                               |
|  | Complex  |  | RTE      |                               |
|  | Drivers  |  |          |                               |
|  +----------+  +----------+                               |
+-----------------------------------------------------------+
|              Microcontroller (MCU Hardware)                |
+-----------------------------------------------------------+

各层的职责:

应用层(Application Layer):由一个个 Software Component(SWC)组成,实现具体的控制功能。工程师在这里设计算法、处理信号。

RTE(Runtime Environment):应用层和底层之间的"中间件"。SWC 不直接调用底层驱动,而是通过 RTE 提供的 API 进行通信。这就像你写代码时不直接操作寄存器,而是调用 HAL 库一样——RTE 提供了类似的抽象。

BSW(Basic Software):提供系统级服务,包括通信协议栈(CAN/LIN/ETH)、内存管理(NVRAM)、诊断(UDS)、ECU 状态管理等。

Software Component Template 的位置:它定义的是应用层 SWC 的元数据模型——即如何用标准化的方式描述一个 SWC 的端口、接口、行为、数据类型等。这些描述最终会序列化为 ARXML 文件,供工具链生成 RTE 代码和 BSW 配置。

1.4 Software Component Template 是什么

Software Component Template 是 AUTOSAR 规范中的一份文档(你正在学习的这份),它定义了:

  • 如何描述一个 Software Component 的结构(端口、接口)
  • 如何描述 SWC 的内部行为(Runnable、事件触发)
  • 如何定义数据类型(Application 层和 Implementation 层)
  • 如何描述 SWC 之间的连接(Composition)
  • 如何描述 SWC 对系统服务的需求(Service Dependencies)

你可以把它理解为"应用层软件的蓝图规范"——它不关心你怎么用 C 代码实现,而是关心你怎么形式化描述你的软件架构。

1.5 关键概念速览

在后续课程中,你会频繁遇到以下概念。现在只需要有个印象,后续会逐一展开:

概念 一句话解释 类比
Software Component (SWC) 应用层的一个功能模块 一个 .c 文件中的功能集合
Port SWC 与外界交互的接口点 MCU 的 GPIO 引脚
Interface 端口上通信的数据/操作定义 UART/SPI 协议格式
RunnableEntity SWC 内部的可执行代码单元 一个 C 函数
TimingEvent 定时触发 Runnable 的事件 定时器中断
RTE 连接所有 SWC 的通信中间件 片上总线/消息队列
Composition 多个 SWC 的组合封装 一个子系统/模块
ARXML 描述整个配置的 XML 文件 项目的配置文件

小结

  • AUTOSAR 是汽车电子的标准化软件架构
  • CP 适用于实时嵌入式 MCU,AP 适用于高性能计算
  • 分层架构:应用层 → RTE → BSW → 硬件
  • Software Component Template 定义应用层 SWC 的描述规范
  • 核心概念:SWC、Port、Interface、Runnable、RTE

思考题

  1. 在你目前的项目中,应用层代码和底层驱动是如何划分的?有没有用到类似 RTE 的分层思想?
  2. 如果你的项目要移植到另一款 MCU 上,哪些代码需要修改?AUTOSAR 的方式能减少多少改动?
  3. 你认为 AUTOSAR 的标准化会带来哪些额外的开销?在什么规模的项目中值得引入?

第2课:Software Component 基础

学习目标

  • 理解 Software Component 的定义和本质
  • 掌握 SWC 的主要类型及其适用场景
  • 理解 Port(端口)的概念和分类
  • 理解 Interface(接口)的基本类型

2.1 什么是 Software Component

在 AUTOSAR 中,Software Component(简称 SWC)是应用层的基本构建单元。

用嵌入式的思维来理解:想象你把一个复杂的发动机控制程序拆分成多个独立的功能模块——传感器采集模块、PID 控制模块、PWM 输出模块、故障诊断模块。每个模块有明确的输入输出,可以独立开发和测试。在 AUTOSAR 中,这样的每个模块就是一个 Software Component。

SWC 的关键特征:

  • 封装性:SWC 的内部实现对其他 SWC 不可见,只通过端口暴露交互接口。就像封装一个 C 结构体,外部只通过 API 访问,不直接操作内部变量。

  • 可复用性:同一个 SWC 类型可以在不同的 ECU 上实例化使用,就像同一个 .c 文件可以在不同项目中引用。

  • 可配置性:SWC 的参数(如标定数据)可以在编译时或甚至运行时配置。

2.2 SWC 的类型

AUTOSAR 定义了几种不同类型的 SWC,每种有不同的用途:

SwComponentType
├── ApplicationSwComponentType (应用层组件)
│   ├── ApplicationComplexDeviceDriverSwComponentType
│   ├── AtomicSwComponentType
│   │   ├── ServiceSwComponentType (服务组件)
│   │   └── 普通 Atomic (传感器/执行器/算法等)
│   └── CompositionSwComponentType (组合组件)
├── EcuAbstractionSwComponentType (ECU抽象组件)
├── ComplexDeviceDriverSwComponentType (复杂设备驱动)
├── SensorActuatorSwComponentType (传感器/执行器组件)
├── NvBlockSwComponentType (NV数据组件)
├── ServiceSwComponentType (服务组件)
├── ServiceProxyComponentType (服务代理)
└── ParameterSwComponentType (参数组件)

对于初学者,最重要理解的是以下几种:

AtomicSwComponentType(原子组件)

最基本的 SWC 类型,包含实际的代码实现。"原子"意味着它不能再被拆分为更小的 SWC。

类比:一个具体的 C 源文件,包含具体的函数实现。

// 这就是一个"原子"的功能单元
void EngineControl_Run(void) {
    float rpm = Rte_Read_EngineRpm();
    float throttle = Rte_Read_ThrottlePos();
    float output = PID_Calculate(rpm, throttle);
    Rte_Write_FuelInjection(output);
}

CompositionSwComponentType(组合组件)

不直接包含代码实现,而是包含多个子 SWC 的连接关系。它就像一个"容器"或"子系统"。

类比:一个头文件 + 多个源文件组成的模块。Composition 定义了这些子模块如何连接。

+-- Composition: EngineManagement ----+
|  +----------+      +----------+    |
|  | SensorSWC|----->| ControlSWC|---+--> 输出
|  +----------+      +----------+    |
|       ^                  |         |
+-------|------------------+---------+
        |                  |
    传感器输入         执行器输出

ServiceSwComponentType(服务组件)

代表一个 AUTOSAR 服务(如 NVRAM 管理、通信管理)。它既有服务提供方的行为,也有服务使用方的接口。

类比:操作系统提供的系统调用接口。

NvBlockSwComponentType(NV 数据组件)

专门用于管理非易失性(Non-Volatile)数据的 SWC。比如标定参数、故障码、里程数等需要断电保存的数据。

类比:EEPROM/Flash 读写驱动层。

2.3 Port(端口)

Port 是 SWC 与外界交互的"接口点"。

用嵌入式的类比:Port 就像 MCU 的引脚。一个 GPIO 引脚可以是输入也可以是输出,同样地,一个 Port 可以是"请求"也可以是"提供"。

AUTOSAR 定义了三种 Port 类型:

PPortPrototype(Provided Port,提供端口)

SWC 通过这个端口提供数据或服务。相当于"我是数据源,你可以从我这里读取"。

// 类比:这个函数通过全局变量"提供"传感器数据
// 其他模块可以来读取
float Sensor_GetTemperature(void) {
    return cached_temp;  // PPort: 提供数据
}

RPortPrototype(Required Port,请求端口)

SWC 通过这个端口请求数据或服务。相当于"我需要数据,请给我"。

// 类比:这个函数"请求"其他模块的数据
void Display_Update(void) {
    float temp = Sensor_ReadTemperature();  // RPort: 请求数据
    LCD_Show(temp);
}

PRPortPrototype(Provided-Required Port,提供-请求端口)

一个端口同时具有提供和请求的能力。用于双向通信场景。

SWC-A                        SWC-B
+-------+                  +-------+
|       |--- PPort --->    |       |
|  SWC  |                  |  SWC  |
|       |<--- RPort ---    |       |
+-------+                  +-------+

或者使用 PRPort:

SWC-A                        SWC-B
+-------+                  +-------+
|       |<== PRPort ==>    |       |
|  SWC  |    (双向通信)     |  SWC  |
|       |<== PRPort ==>    |       |
+-------+                  +-------+

2.4 Interface(接口)基础

Port 定义了"在哪里通信",Interface 定义了"通信什么"。

继续引脚的类比:Port 是物理引脚,Interface 是通信协议(UART、SPI、I2C)。两个引脚要能通信,它们必须使用相同的协议。

AUTOSAR 定义了多种 Interface 类型:

Interface 类型 用途 嵌入式类比
SenderReceiverInterface 周期性数据交换 共享变量 / 消息队列
ClientServerInterface 请求-响应式调用 函数调用
ModeSwitchInterface 模式切换 状态机切换信号
ParameterInterface 参数传递 const 全局变量
NvDataInterface NV 数据读写 EEPROM 读写
TriggerInterface 触发信号 中断信号

最常用的两种是 SenderReceiverInterfaceClientServerInterface,后续课程会详细展开。

2.5 SWC 的生命周期

一个 SWC 从设计到运行,经历以下阶段:

1. 设计阶段
   └── 工程师定义 SWC 的端口、接口、行为
   └── 工具中建模(如 MATLAB/Simulink, Enterprise Architect)

2. 配置阶段
   └── 生成 ARXML 描述文件
   └── 配置 SWC 的参数、连接关系

3. 代码生成阶段
   └── RTE 生成器根据 ARXML 生成 RTE 头文件和代码
   └── 生成 Rte.h, Rte_Type.h 等

4. 实现阶段
   └── 工程师编写 SWC 的 C 代码(Runnable 函数)
   └── 代码通过 RTE API 与外界通信

5. 集成与部署
   └── 编译器 + 链接器生成最终可执行文件
   └── 下载到 ECU 运行

2.6 一个完整的 SWC 示例

让我们用一个简单的温度控制 SWC 来串联所有概念:

+-- TemperatureController SWC --+
|                                |
|  RPort: TempSensor             |  <-- 从传感器读取温度
|    Interface: SenderReceiver   |
|    DataElement: Temperature    |
|                                |
|  RPort: TargetTemp             |  <-- 读取目标温度(标定参数)
|    Interface: Parameter        |
|    Parameter: TargetValue      |
|                                |
|  PPort: HeaterControl          |  <-- 输出加热器控制信号
|    Interface: SenderReceiver   |
|    DataElement: ControlOutput  |
|                                |
|  Internal Behavior:            |
|    Runnable: TempCtrl_Run      |
|    Trigger: TimingEvent (10ms) |
|                                |
+--------------------------------+

对应的 C 代码骨架:

/* TemperatureController.c */
#include "Rte_TemperatureController.h"

/* 这个 Runnable 每 10ms 被 RTE 调度一次 */
void TempCtrl_Run(void) {
    /* 通过 RPort 读取传感器温度 */
    float currentTemp = Rte_Read_TempSensor_Temperature();

    /* 通过 RPort 读取目标温度参数 */
    float targetTemp = Rte_Param_TargetTemp_TargetValue;

    /* 简单的 PID 控制 */
    float error = targetTemp - currentTemp;
    static float integral = 0.0f;
    integral += error * 0.01f;  /* dt = 10ms */
    float derivative = (error - prevError) / 0.01f;
    prevError = error;

    float output = Kp * error + Ki * integral + Kd * derivative;

    /* 限幅 */
    if (output > 100.0f) output = 100.0f;
    if (output < 0.0f) output = 0.0f;

    /* 通过 PPort 输出控制信号 */
    Rte_Write_HeaterControl_ControlOutput(output);
}

这个例子展示了:

  • SWC 通过 RPort 获取输入(传感器数据、标定参数)
  • SWC 通过 PPort 提供输出(控制信号)
  • 内部 Runnable 由 TimingEvent 周期触发
  • 代码通过 RTE API(Rte_Read_xxx, Rte_Write_xxx)与外界通信

小结

  • SWC 是 AUTOSAR 应用层的基本构建单元
  • 主要类型:Atomic(原子)、Composition(组合)、Service(服务)、NvBlock(NV 数据)
  • Port 分三种:PPort(提供)、RPort(请求)、PRPort(双向)
  • Interface 定义通信内容,最常用的是 SenderReceiver 和 ClientServer
  • SWC 通过 RTE API 与外界通信,不直接访问底层

思考题

  1. 在你熟悉的项目中,哪些功能模块可以被建模为独立的 SWC?
  2. 一个控制算法 SWC 应该有哪些 Port?分别是什么类型?
  3. Composition 和 Atomic SWC 的关系,类似于嵌入式开发中什么概念?

第3课:Port 与 Interface 深入

学习目标

  • 深入理解每种 Port 类型的属性和用途
  • 掌握各种 Interface 类型的详细特征
  • 理解 DataElement、Operation、ModeDeclaration 等接口元素
  • 学会选择合适的 Interface 类型

3.1 SenderReceiverInterface 详解

SenderReceiverInterface 是最常用的 Interface 类型,用于周期性数据交换。

核心概念:

Sender (PPort)                    Receiver (RPort)
+-----------+                    +-----------+
|           |--- DataElement --> |           |
|  Sender   |    (周期性数据)     |  Receiver |
|  SWC      |                    |  SWC      |
+-----------+                    +-----------+

一个 SenderReceiverInterface 可以包含一个或多个 DataElement(数据元素)。每个 DataElement 代表一个可交换的数据信号。

SenderReceiverInterface: VehicleData
├── DataElement: EngineSpeed     (uint16, rpm)
├── DataElement: VehicleSpeed    (uint16, km/h)
├── DataElement: EngineTemp      (float32, °C)
└── DataElement: BatteryVoltage  (float32, V)

通信模式:

SenderReceiverInterface 支持多种通信模式:

1. 周期性通信(最常见)

Sender 每隔一定周期写入数据,Receiver 每隔一定周期读取数据。

/* Sender 侧 - 每 10ms 执行 */
void Sensor_Read(void) {
    uint16 rpm = ADC_ReadEngineSpeed();
    Rte_Write_VehicleData_EngineSpeed(rpm);
}

/* Receiver 侧 - 每 20ms 执行 */
void Control_Calculate(void) {
    uint16 rpm;
    Rte_Read_VehicleData_EngineSpeed(&rpm);
    // 使用 rpm 进行计算...
}

2. 隐式通信(数据一致性)

AUTOSAR 提供了数据一致性机制,确保 Receiver 读到的数据是完整的。这通过 DataInvalidPolicyInitValue 等属性配置。

数据有效性:

每个 DataElement 都可以标记为"有效"或"无效":

/* Sender 标记数据无效 */
Rte_Invalidate_VehicleData_EngineSpeed();

/* Receiver 检查数据有效性 */
if (Rte_IsValid_VehicleData_EngineSpeed()) {
    Rte_Read_VehicleData_EngineSpeed(&rpm);
    // 使用有效数据
} else {
    // 使用默认值或上次有效值
}

3.2 ClientServerInterface 详解

ClientServerInterface 用于请求-响应式通信,类似于函数调用。

核心概念:

Client (RPort)                    Server (PPort)
+-----------+                    +-----------+
|           |-- Operation() ---> |           |
|  Client   |                    |  Server   |
|  SWC      |<-- Return/Error -- |  SWC      |
+-----------+                    +-----------+

一个 ClientServerInterface 包含一个或多个 ClientServerOperation(操作)。每个 Operation 可以有参数(arguments)和返回值。

ClientServerInterface: DiagnosticService
├── Operation: ReadDTC
│   ├── argument: dtcNumber (in, uint32)
│   ├── argument: dtcStatus (out, uint8)
│   └── possibleError: DTCNotFound
├── Operation: ClearDTC
│   ├── argument: dtcNumber (in, uint32)
│   └── possibleError: ClearFailed
└── Operation: GetDTCCount
    └── argument: count (out, uint16)

使用方式:

/* Client 侧 - 调用服务 */
void FaultDisplay_Update(void) {
    uint8 dtcStatus;
    Std_ReturnType ret;

    ret = Rte_Call_DiagnosticService_ReadDTC(0x0100, &dtc_status);
    if (ret == RTE_E_OK) {
        // 显示 DTC 状态
    } else if (ret == RTE_E_SEVERE) {
        // 服务不可用
    }
}

/* Server 侧 - 提供服务 */
/* Server 的 Runnable 中处理请求 */
Std_ReturnType Diagnostic_ReadDTC(uint32 dtcNumber, uint8* dtcStatus) {
    if (DTC_Exists(dtcNumber)) {
        *dtcStatus = DTC_GetStatus(dtcNumber);
        return RTE_E_OK;
    }
    return RTE_E_SEVERE;  // DTC not found
}

3.3 ModeSwitchInterface 详解

ModeSwitchInterface 用于模式切换通信。

核心概念:

模式(Mode)是一种离散的状态值,比如"正常模式"、"降级模式"、"休眠模式"。ModeSwitchInterface 允许一个 SWC 请求切换模式,另一个 SWC 响应模式切换。

ModeSwitchInterface: EcuMode
├── ModeDeclarationGroup: EcuModeGroup
│   ├── ModeDeclaration: Startup
│   ├── ModeDeclaration: Normal
│   ├── ModeDeclaration: Degraded
│   ├── ModeDeclaration: Sleep
│   └── ModeDeclaration: Shutdown

使用方式:

/* Mode Sender 侧 - 请求切换模式 */
void StateManager_Run(void) {
    if (fault_detected) {
        Rte_Mode_EcuMode_EcuModeGroup(Degraded);
    }
}

/* Mode Receiver 侧 - 响应模式切换 */
void App_Run(void) {
    EcuModeGroup_Type currentMode;
    Rte_Mode_EcuMode_EcuModeGroup(&currentMode);

    switch (currentMode) {
        case Normal:
            // 正常运行
            break;
        case Degraded:
            // 降级运行 - 关闭部分功能
            break;
        case Sleep:
            // 准备休眠
            break;
    }
}

3.4 ParameterInterface 详解

ParameterInterface 用于传递标定参数(calibration parameters)。

参数是那些在运行时可能需要调整但不经常变化的值,比如 PID 参数、阈值、系数等。

/* 标定参数在 SWC 中的使用 */
void Controller_Run(void) {
    /* 直接读取标定参数 */
    float kp = Rte_Param_PIDController_Kp;
    float ki = Rte_Param_PIDController_Ki;
    float kd = Rte_Param_PIDController_Kd;

    /* 使用参数进行计算 */
    // ...
}

参数与 SenderReceiver 数据的区别:

  • 参数变化频率低(可能几秒甚至几分钟才变一次)
  • 参数通常用于标定(calibration)
  • 参数可以存储在 NV 内存中,断电不丢失

3.5 NvDataInterface 详解

NvDataInterface 用于读写非易失性(Non-Volatile)数据。

/* 读取 NV 数据 */
void Init_Run(void) {
    uint32 mileage;
    Rte_Read_NvData_Mileage_Value(&mileage);
    totalMileage = mileage;
}

/* 写入 NV 数据 */
void Update_Run(void) {
    totalMileage += distanceThisCycle;
    Rte_Write_NvData_Mileage_Value(totalMileage);
}

NV 数据的特殊之处:

  • 写入操作是异步的(实际写入 Flash/EEPROM 需要时间)
  • 有写入次数寿命限制(特别是 Flash)
  • 需要通过 NvBlockSwComponentType 管理

3.6 如何选择合适的 Interface 类型

场景 推荐 Interface 原因
传感器数据周期传递 SenderReceiverInterface 简单高效,支持数据一致性
调用远程服务/函数 ClientServerInterface 请求-响应模式,支持错误处理
ECU 工作模式切换 ModeSwitchInterface 语义清晰,支持模式转换事件
标定参数 ParameterInterface 支持标定工具在线修改
断电保存数据 NvDataInterface 与 NvM 服务集成
触发信号 TriggerInterface 简单的事件通知

3.7 Port Annotation(端口标注)

Port Annotation 用于在 Composition 层面为端口指定具体的实现细节。

打个比方:Port 定义了一个"插座"的规格(几孔、什么形状),Port Annotation 则指定了这个插座"实际连接到哪里"。

Composition: ClimateControl
├── PPort: TempOutput
│   └── Annotation: 映射到内部 HeaterSWC.PPort:HeatSignal
├── RPort: SensorInput
│   └── Annotation: 映射到内部 SensorSWC.RPort:RawTemp
└── RPort: NvM_Read
    └── Annotation: 映射到 NvM 服务接口

小结

  • SenderReceiverInterface:最常用,适合周期性数据交换
  • ClientServerInterface:请求-响应模式,适合服务调用
  • ModeSwitchInterface:模式切换,适合状态管理
  • ParameterInterface:标定参数,支持在线调整
  • NvDataInterface:NV 数据读写,与 NvM 集成
  • 选择 Interface 类型取决于通信模式和数据特性

思考题

  1. 一个发动机控制 SWC 需要与哪些外部模块通信?分别适合用什么 Interface?
  2. SenderReceiver 和 ClientServer 的核心区别是什么?什么场景下不能用 SenderReceiver 替代 ClientServer?
  3. 为什么标定参数要用专门的 ParameterInterface 而不是 SenderReceiverInterface?

第4课:通信模式详解

学习目标

  • 深入理解 Sender-Receiver 通信的各种模式
  • 掌握 Client-Server 通信的错误处理机制
  • 理解数据一致性(Data Consistency)的建模方式
  • 学会配置 Communication Specification(ComSpec)

4.1 Sender-Receiver 通信深度解析

4.1.1 通信行为模型

Sender-Receiver 通信的核心特点是解耦——Sender 和 Receiver 不需要知道对方的存在,它们各自独立运行,通过 RTE 进行数据中转。

时间线:
         10ms     20ms     30ms     40ms
Sender:   |W1------|W2------|W3------|W4
          |        |        |        |
RTE:      |  [缓冲]|  [缓冲]|  [缓冲]|  [缓冲]
          |        |        |        |
Receiver: |---R1---|---R2---|---R3---|---R4
         15ms     25ms     35ms     45ms

W = Write, R = Read

4.1.2 数据一致性策略

当 Sender 和 Receiver 运行在不同的上下文(如不同的 Task 或 Interrupt)中时,数据一致性是一个关键问题。

AUTOSAR 提供了三种数据一致性策略:

1. 无保护(No Protection)

最简单的情况——数据可能被"写一半读一半"。

/* 无保护:可能出现数据不一致 */
/* Sender 正在更新结构体 */
data.field1 = newValue1;  // ← Receiver 此时读取,只看到部分更新
data.field2 = newValue2;

/* Receiver 可能读到不一致的数据 */

2. 互斥保护(Mutual Exclusion / Semaphore)

使用信号量保护数据访问。

/* 使用信号量保护 */
Rte_Enter_ExclusiveArea();
data.field1 = newValue1;
data.field2 = newValue2;
Rte_Exit_ExclusiveArea();

3. 隐式通信(Implicit Communication via Variable Copies)

这是 AUTOSAR 最精妙的设计之一。RTE 为每个数据创建多个副本,Sender 和 Receiver 操作不同的副本,从而避免竞争。

              RTE 内部
Sender ──写──> [副本A] ──交换──> [副本B] ──读──> Receiver
                     ↑              ↑
                  Sender写的新值   Receiver读到的是上次交换后的完整值

这种机制的关键属性:

  • initValue:初始值,在系统启动时使用
  • dataInvalidPolicy:当数据从未被写入时,Receiver 的行为策略
    • Zero:返回零值
    • Replace:替换为初始值
    • Invalidate:标记为无效

4.1.3 Data Filter(数据过滤器)

Data Filter 允许 Receiver 只在数据满足特定条件时才接收:

Filter 类型:
├── NEVER:从不接收(用于禁用数据传递)
├── ALWAYS:总是接收(默认)
├── ONE_EVERY_N:每 N 次接收 1 次
└── MASKED_NEW_EQ_X:新值与掩码比较
/* 配置示例:每 5 次只接收 1 次 */
/* Receiver 每 10ms 执行,但实际只每 50ms 获得新数据 */
DataFilter: ONE_EVERY_N, factor = 5

4.1.4 Invalidation Policy

当 Sender 显式地使数据无效时,Receiver 如何处理?

/* Sender 使数据无效 */
Rte_Invalidate_VehicleData_EngineSpeed();

/* Receiver 侧的行为由 InvalidationPolicy 决定 */
/* Invalidate: Receiver 也会看到数据无效 */
/* Keep: Receiver 保留最后一次有效值 */

4.2 Client-Server 通信深度解析

4.2.1 调用模型

Client-Server 通信是同步的请求-响应模式:

Client                    RTE                    Server
  |                        |                       |
  |-- Call Operation() --> |                       |
  |   (阻塞等待)           |-- forward call -----> |
  |                        |                       |
  |                        |                       |-- 执行操作
  |                        |                       |
  |                        |<-- return result -----|
  |<-- return result -----|                       |
  |                        |                       |

4.2.2 错误处理

Client-Server 通信的错误处理是其关键特性:

Std_ReturnType ret;
uint8 result;

ret = Rte_Call_MathService_Divide(100, 0, &result);

switch (ret) {
    case RTE_E_OK:
        /* 调用成功,result 包含结果 */
        break;
    case RTE_E_UNKNOWN:
        /* 未知错误 */
        break;
    case RTE_E_NO_DATA:
        /* 无数据(数据从未被写入) */
        break;
    case RTE_E_NEVER_EXECUTED:
        /* Runnable 从未被执行过 */
        break;
    case RTE_E_LIMIT:
        /* 超出限制 */
        break;
    case RTE_E_LOST_DATA:
        /* 数据丢失 */
        break;
    case RTE_E_MAX_AGE_EXCEEDED:
        /* 超过最大有效期 */
        break;
    case RTE_E_SEVERE:
        /* 严重错误(如除零) */
        break;
}

4.2.3 Server 端的错误返回

Server 端的 Runnable 可以通过 ServerCallPoint 返回特定的错误码:

/* Server 侧 */
Std_ReturnType MathService_Divide(uint16 a, uint16 b, uint8* result) {
    if (b == 0) {
        return RTE_E_SEVERE;  /* 除零错误 */
    }
    *result = (uint8)(a / b);
    return RTE_E_OK;
}

4.3 Communication Specification(ComSpec)

ComSpec 用于在端口上配置通信的详细行为。

4.3.1 Receiver ComSpec

Receiver 端可以配置:

  • initValue:初始值
  • dataInvalidPolicy:数据无效时的策略
  • filter:数据过滤规则
  • timeout:超时时间(如果超时未收到新数据)
  • handleInvalid:超时后的处理方式
Receiver ComSpec 配置示例:
├── initValue: 0
├── dataInvalidPolicy: Replace (用初始值替代)
├── filter: ALWAYS
├── timeout: 100ms
└── handleInvalid: External (使用外部默认值)

4.3.2 Sender ComSpec

Sender 端可以配置:

  • initValue:初始值
  • queueLength:队列长度(用于排队多个发送值)
Sender ComSpec 配置示例:
├── initValue: 0
└── queueLength: 1 (不需要队列,只保留最新值)

4.4 通信模式对比总结

特性 Sender-Receiver Client-Server
通信方式 异步(解耦) 同步(阻塞)
数据方向 单向 请求 + 响应
错误处理 数据有效性标记 返回码
适用场景 传感器数据、信号传递 服务调用、诊断
性能 高(无阻塞) 较低(等待响应)
数据一致性 需要配置 天然保证

小结

  • Sender-Receiver 支持多种数据一致性和过滤机制
  • Client-Server 提供同步调用和完善的错误处理
  • ComSpec 精细控制通信行为的每个细节
  • 选择通信模式需要根据实时性、可靠性需求权衡

思考题

  1. 如果一个传感器数据需要每 10ms 更新,但控制算法每 50ms 才需要,你会如何配置 DataFilter?
  2. 在什么场景下,Client-Server 的同步阻塞特性会成为问题?如何解决?
  3. 数据一致性的三种策略各适用于什么场景?

第5课:内部行为与调度

学习目标

  • 理解 SwcInternalBehavior 的概念和组成
  • 掌握 RunnableEntity 的定义和使用
  • 深入理解各种事件类型(TimingEvent, DataReceivedEvent, ModeSwitchEvent 等)
  • 掌握 ExclusiveArea 和并发保护机制

5.1 SwcInternalBehavior 概述

SwcInternalBehavior 描述了一个 Atomic SWC 的内部行为——它有哪些可执行代码、什么条件下执行、如何保护共享资源。

用嵌入式的类比:如果你把 SWC 想象成一个 MCU,那么 SwcInternalBehavior 就是这个 MCU 的"中断向量表 + 任务列表"——它定义了哪些函数在什么条件下被调用。

SwcInternalBehavior
├── runnable: RunnableEntity 列表
│   ├── Runnable_A (由 TimingEvent 触发)
│   ├── Runnable_B (由 DataReceivedEvent 触发)
│   └── Runnable_C (由 ModeSwitchEvent 触发)
├── event: 事件列表
│   ├── TimingEvent_10ms → 触发 Runnable_A
│   ├── DataReceivedEvent → 触发 Runnable_B
│   └── ModeSwitchEvent → 触发 Runnable_C
├── exclusiveArea: 互斥区列表
│   └── DataProtectionArea
├── perInstanceMemory: 实例内存
└── dataTypeMapping: 数据类型映射

5.2 RunnableEntity 详解

RunnableEntity 是 SWC 内部的基本执行单元。每个 Runnable 对应一段可执行代码(通常是一个 C 函数)。

/* Runnable 就是一个普通的 C 函数 */
void MyRunnable(void) {
    /* 通过 RTE API 读写数据 */
    float input = Rte_Read_InputPort_Signal();
    float output = ProcessData(input);
    Rte_Write_OutputPort_Signal(output);
}

Runnable 的关键属性:

  • shortName:Runnable 的名称
  • canBeInvokedConcurrently:是否允许并发执行
  • symbol:对应的 C 函数名
  • activationReason:激活原因(哪个事件触发了它)
  • exclusiveAreaRef:需要进入的互斥区

Runnable 的入口点(Entry Points):

一个 Runnable 可以有多个入口点,对应不同的激活原因:

/* Runnable 根据激活原因执行不同逻辑 */
void FlexibleRunnable(void) {
    RunnableEntityActivationReason reason = Rte_Reason();

    switch (reason) {
        case RTE_AE_TimingEvent_10ms:
            /* 定时触发:执行常规控制 */
            RegularControl();
            break;
        case RTE_AE_DataReceivedEvent_InputPort:
            /* 数据接收触发:立即处理新数据 */
            ProcessNewData();
            break;
        default:
            break;
    }
}

5.3 事件类型详解

事件(Event)是触发 Runnable 执行的"触发器"。AUTOSAR 定义了多种事件类型:

5.3.1 TimingEvent(定时事件)

最常用、最重要的事件类型。按固定周期触发 Runnable。

TimingEvent 属性:
├── period: 触发周期(如 10ms, 50ms, 100ms)
└── offset: 首次触发的偏移时间(如 5ms)

period(周期) 决定了 Runnable 的执行频率。offset(偏移) 决定了首次触发的时间点。

时间线:
0ms    5ms    10ms   20ms   30ms   40ms
|       |       |       |       |       |
        ↑       ↑       ↑       ↑       ↑
      offset  第2次   第3次   第4次   第5次
             触发    触发    触发    触发

period = 10ms, offset = 5ms

offset 的工程意义:

  • 错开不同 Runnable 的执行时间,避免同时执行导致 CPU 过载
  • 确保数据在 Runnable 执行前已经准备好
/* TimingEvent 触发的 Runnable */
/* 每 10ms 执行一次,首次执行在 5ms 后 */
void ControlLoop_Run(void) {
    /* 这里的代码每 10ms 执行一次 */
    /* 类似于一个周期为 10ms 的定时器中断服务函数 */
}

5.3.2 DataReceivedEvent(数据接收事件)

当 Receiver 端口收到新数据时触发。

数据流:
Sender --写入数据--> RTE --通知--> DataReceivedEvent --触发--> Runnable
/* 当 InputPort 收到新数据时触发 */
void OnDataReceived_Run(void) {
    float newData = Rte_Read_InputPort_Signal();
    /* 立即处理新数据 */
    ProcessData(newData);
}

适用场景:

  • 事件驱动型处理(不需要固定周期,有数据就处理)
  • 需要快速响应外部输入的场景

5.3.3 ModeSwitchEvent(模式切换事件)

当模式切换发生时触发。

/* 当 ECU 模式切换到 Degraded 时触发 */
void OnModeDegraded_Run(void) {
    /* 进入降级模式的处理 */
    DisableNonCriticalFunctions();
    ActivateBackupSensors();
}

5.3.4 OperationInvokedEvent(操作调用事件)

当 Client 调用 Server 的 Operation 时触发 Server 端的 Runnable。

/* 当 Client 调用 DiagnosticService.ReadDTC 时触发 */
void Diagnostic_ReadDTC_Run(void) {
    /* 处理诊断请求 */
}

5.3.5 InitEvent 和 ResetEvent

  • InitEvent:SWC 初始化时触发(系统启动时执行一次)
  • ResetEvent:SWC 重置时触发
/* 初始化 Runnable - 系统启动时执行一次 */
void Init_Run(void) {
    /* 初始化变量 */
    counter = 0;
    /* 读取 NV 数据 */
    Rte_Read_NvData_Config(&config);
    /* 初始化硬件 */
    // ...
}

5.3.6 事件类型总结

事件类型 触发条件 典型用途
TimingEvent 固定周期 周期性控制算法
DataReceivedEvent 收到新数据 事件驱动处理
ModeSwitchEvent 模式切换 模式相关初始化/清理
OperationInvokedEvent Client 调用 Server 端服务处理
InitEvent SWC 初始化 系统启动初始化
ResetEvent SWC 重置 重置处理
BackgroundEvent 空闲时 低优先级后台任务
SwcModeSwitchEvent SWC 模式切换 SWC 内部模式响应

5.4 ExclusiveArea(互斥区)

当多个 Runnable 共享数据时,需要保护数据的一致性。ExclusiveArea 提供了互斥保护机制。

类比:就像嵌入式中的临界区保护(关中断 / 信号量)。

/* 使用 ExclusiveArea 保护共享数据 */
void HighPriorityRunnable_Run(void) {
    Rte_Enter_SharedDataArea();
    /* 临界区:其他使用同一 ExclusiveArea 的 Runnable 不能同时执行 */
    sharedCounter++;
    sharedData[sharedCounter % 10] = newValue;
    Rte_Exit_SharedDataArea();
}

ExclusiveArea 的实现方式取决于 RTE 配置:

  • 信号量(Semaphore)
  • 关中断(Interrupt Disabling)
  • 优先级天花板(Priority Ceiling)

5.5 InterRunnableVariable(Runnable 间变量)

当同一个 SWC 内的多个 Runnable 需要共享数据时,使用 InterRunnableVariable。

SWC 内部:
Runnable_A ──写──> InterRunnableVariable: sharedData ──读──> Runnable_B
/* Runnable_A 写入 */
void RunnableA_Run(void) {
    Rte_Enter_DataArea();
    sharedData = CalculateData();
    Rte_Exit_DataArea();
}

/* Runnable_B 读取 */
void RunnableB_Run(void) {
    Rte_Enter_DataArea();
    float data = sharedData;
    Rte_Exit_DataArea();
    UseData(data);
}

5.6 Runnable 的调度时序

多个 Runnable 的调度时序是系统设计的关键:

时间线(一个 1ms 基础周期内的调度):
0ms     1ms     2ms     5ms     10ms    20ms
|       |       |       |       |       |
↑       ↑       ↑       ↑       ↑       ↑
Init   10ms    10ms    50ms   10ms    100ms
       Task    Task    Task   Task    Task

10ms Task 内:
├── Runnable_A (传感器采集) - TimingEvent 10ms
├── Runnable_B (控制计算)   - TimingEvent 10ms, offset 2ms
└── Runnable_C (输出更新)   - TimingEvent 10ms, offset 5ms

小结

  • SwcInternalBehavior 定义 SWC 的全部内部行为
  • RunnableEntity 是基本执行单元,对应 C 函数
  • TimingEvent 是最常用的触发方式(period + offset)
  • DataReceivedEvent 实现事件驱动处理
  • ExclusiveArea 保护共享数据的并发访问

思考题

  1. 一个 PID 控制 Runnable 应该用 TimingEvent 还是 DataReceivedEvent 触发?为什么?
  2. 如果两个 Runnable 共享一个变量,一个 10ms 执行一次,一个 50ms 执行一次,需要怎样的保护?
  3. offset 在实际项目中如何设置?考虑 CPU 负载和数据就绪时间。

第6课:数据类型系统

学习目标

  • 理解 AUTOSAR 的两层数据类型体系
  • 掌握 ApplicationDataType 和 ImplementationDataType 的区别
  • 理解 CompuMethod(计算方法/数据缩放)
  • 掌握 RecordLayout 和标定数据的物理存储

6.1 为什么需要两层数据类型

在嵌入式开发中,同一个物理量在不同层面有不同的表示:

物理世界:温度 = 25.5 °C

应用层视角(Application):
  → float32 temperature = 25.5  (工程单位: °C)

通信层视角(Communication):
  → uint16 rawValue = 2550      (分辨率: 0.01°C/bit)

存储层视角(Implementation):
  → uint16 storedValue = 2550   (与通信层相同)

标定工具视角(Calibration):
  → float32 calValue = 25.5     (工程单位,可读可写)

AUTOSAR 用两层数据类型来解决这个问题:

  • ApplicationDataType:应用层使用的数据类型(工程单位,人类可读)
  • ImplementationDataType:实现层使用的数据类型(原始值,机器友好)

两者之间通过 CompuMethod 进行转换。

6.2 ApplicationDataType

ApplicationDataType 是应用层"看到"的数据类型。

ApplicationDataType
├── ApplicationPrimitiveDataType (基本类型)
│   ├── float32 (温度、电压等模拟量)
│   ├── uint8 (状态、计数等)
│   └── boolean (开关量)
├── ApplicationCompositeDataType (复合类型)
│   ├── ApplicationArrayDataType (数组)
│   └── ApplicationRecordDataType (结构体)
└── SwBaseType (底层基础类型)
    ├── uint8, uint16, uint32
    ├── sint8, sint16, sint32
    ├── float32, float64
    └── boolean

定义一个 Application 数据类型:

ApplicationPrimitiveDataType: EngineSpeed
├── category: VALUE
├── swDataDefProps:
│   ├── baseType: uint16
│   ├── unit: rpm
│   ├── compuMethod: LinearScaling (0.0, 0.25)  /* 分辨率 0.25 rpm */
│   └── dataConstraint: 0..8000 rpm
└── description: 发动机转速

6.3 ImplementationDataType

ImplementationDataType 是代码"使用"的数据类型——它决定了 C 代码中变量的实际类型。

ImplementationDataType: EngineSpeed_Impl
├── category: VALUE
├── swDataDefProps:
│   ├── baseType: uint16
│   └── implementationType: uint16
└── description: 发动机转速(实现类型)

在 C 代码中:

/* 生成的 RTE 类型 */
typedef uint16 EngineSpeed_ImplType;

/* RTE 变量 */
EngineSpeed_ImplType Rte_Variable_EngineSpeed = 0;

6.4 CompuMethod(数据缩放/转换方法)

CompuMethod 定义了 Application 值和 Implementation 值之间的转换关系。

6.4.1 线性缩放(Linear Scaling)

最常见的转换方式:physical = raw * factor + offset

CompuMethod: EngineSpeed_Scaling
├── category: LINEAR
├── compuRationalCoeffs:
│   ├── numerator: offset=0, factor=0.25
│   └── denominator: 1
└── 含义: physical_value = raw_value * 0.25 + 0

示例:
  raw = 4000 → physical = 4000 * 0.25 = 1000 rpm
  physical = 3000 → raw = (3000 - 0) / 0.25 = 12000

6.4.2 查表转换(Table Conversion)

使用查找表进行非线性转换:

CompuMethod: ThermistorScaling
├── category: TABULAR
├── compuScale:
│   ├── [0]   → -40 °C
│   ├── [100] → -20 °C
│   ├── [200] → 0 °C
│   ├── [400] → 40 °C
│   ├── [600] → 80 °C
│   └── [800] → 120 °C
└── 含义: 通过查表+插值将 ADC 原始值转换为温度

6.4.3 文本表(Text Table)

将数值映射为文本描述:

CompuMethod: GearPosition
├── category: TEXTTABLE
├── compuScale:
│   ├── [0] → "Park"
│   ├── [1] → "Reverse"
│   ├── [2] → "Neutral"
│   ├── [3] → "Drive"
│   └── [4] → "Low"

6.5 DataConstraint(数据约束)

DataConstraint 定义了数据的有效范围:

DataConstraint: EngineSpeed_Constraint
├── dataConstraintLevel:
│   ├── lowerLimit: 0 rpm
│   └── upperLimit: 8000 rpm
└── constraintType: NOT_YET_AVAILABLE (或 CONSTRAINT)

约束的作用:

  • 标定工具知道参数的可调范围
  • 通信层可以做合理性检查
  • 诊断可以检测超范围值

6.6 RecordLayout(标定数据布局)

RecordLayout 定义了标定数据在内存中的物理布局。

对于标定工程师来说,RecordLayout 决定了标定工具如何读写参数:

RecordLayout: PID_Params_Layout
├── Kp: float32, offset 0
├── Ki: float32, offset 4
├── Kd: float32, offset 8
└── 总大小: 12 bytes

在 C 代码中:

typedef struct {
    float32 Kp;  /* offset 0 */
    float32 Ki;  /* offset 4 */
    float32 Kd;  /* offset 8 */
} PID_Params_Type;

/* 标定参数 - 可以被标定工具在线修改 */
PID_Params_Type PID_Params __attribute__((section(".calibration"))) = {
    .Kp = 1.0f,
    .Ki = 0.1f,
    .Kd = 0.01f
};

6.7 数据类型转换流程

完整的数据流经过以下转换:

标定工具写入: 25.5 °C
       │
       ▼ (CompuMethod: LINEAR, factor=0.25, offset=0)
Implementation 值: 102 (uint8)
       │
       ▼ (存储在 RAM/Flash 中)
       │
       ▼ (RTE 读取)
Application 值: 25.5 °C
       │
       ▼ (SWC 使用)
控制算法计算
       │
       ▼ (SWC 输出)
Application 值: 75.0 %
       │
       ▼ (CompuMethod: LINEAR, factor=0.5, offset=0)
Implementation 值: 150 (uint8)
       │
       ▼ (通过 RTE 发送)
接收方 Application 值: 75.0 %

小结

  • AUTOSAR 用两层数据类型分离应用语义和实现细节
  • ApplicationDataType 面向工程师(工程单位)
  • ImplementationDataType 面向代码(原始值)
  • CompuMethod 定义两者之间的转换(线性、查表、文本表)
  • RecordLayout 定义标定数据的内存布局

思考题

  1. 一个温度传感器,ADC 范围 0-4095 对应 -40°C 到 125°C,你会用什么 CompuMethod?
  2. 为什么标定参数不能直接用 float64 存储?考虑 MCU 的资源限制。
  3. 如果一个数据需要在两个不同分辨率的 ECU 之间传递,如何处理缩放?

第7课:Composition 与连接

学习目标

  • 理解 Composition 的概念和用途
  • 掌握三种 Connector 类型
  • 理解端口映射和委托机制
  • 学会设计合理的 Composition 结构

7.1 Composition 的概念

Composition 是将多个 SWC 组合在一起的"容器"。

类比:如果把每个 SWC 比作一个电子元器件(电阻、电容、IC),那么 Composition 就是一个电路板——它定义了这些元器件如何连接在一起工作。

+-- Composition: EngineManagementSystem --+
|                                         |
|  +----------+    +----------+          |
|  | SensorSWC|───→|ControlSWC|───→ Out |
|  +----------+    +----------+          |
|       ↑              ↓                 |
|  +----------+    +----------+          |
|  | ParamSWC |───→| ActuatorSWC|        |
|  +----------+    +----------+          |
|                    ↓                    |
|  In ──────────────→                    |
+─────────────────────────────────────────+

Composition 的关键特征:

  • 它本身不包含可执行代码
  • 它定义子 SWC 之间的连接关系
  • 它对外暴露端口(通过端口映射)
  • 子 SWC 在 Composition 内被实例化

7.2 SwComponentPrototype(组件原型)

在 Composition 中,每个子 SWC 通过 SwComponentPrototype 来实例化:

Composition: ClimateControl
├── SwComponentPrototype: TempSensor (type: TemperatureSensorSWC)
├── SwComponentPrototype: PIDController (type: PIDControlSWC)
└── SwComponentPrototype: HeaterDriver (type: HeaterDriverSWC)

类比:SwComponentPrototype 就像电路图中的元器件位号(R1, C1, U1)——它指定了使用哪种元器件(type)以及给它一个实例名称。

7.3 三种 Connector 类型

AUTOSAR 定义了三种连接器来描述 SWC 之间的连接关系:

7.3.1 AssemblySwConnector(装配连接器)

连接同一 Composition 内两个子 SWC 的端口。

Composition 内部:
+-- Composition --+
|  SWC-A          |  SWC-B          |
|  PPort:Output ──┼──→ RPort:Input  |
|                 |                  |
+──────────────────────────────────+

AssemblySwConnector:
├── providerRef: SWC-A.PPort:Output
└── requesterRef: SWC-B.RPort:Input

类比:电路板上的走线——连接两个元器件的引脚。

7.3.2 DelegationSwConnector(委托连接器)

将 Composition 外部端口映射到内部子 SWC 的端口

Composition 对外:
         Composition 的外部 PPort
              │
              │ DelegationSwConnector
              ↓
+-- Composition --+
|  内部 SWC-A     |
|  PPort:Output   |
+─────────────────+

DelegationSwConnector:
├── outerPort: Composition.PPort:ExternalOutput
└── innerPort: SWC-A.PPort:Output

类比:电路板对外接插件——内部信号通过接插件引出到外部。

7.3.3 PassThroughSwConnector(直通连接器)

在同一 Composition 内,直接连接一个子 SWC 的 RPort 和另一个子 SWC 的 PPort,通过一个中间端口传递。

+-- Composition --+
|  SWC-A          |  SWC-B          |
|  RPort:Input ←──┼── PPort:Output  |
|       ↑         |       ↑         |
|       └──PassThrough──┘           |
+──────────────────────────────────+

PassThrough 比较少用,主要用于需要同时满足两种连接语义的场景。

7.4 Connector 的兼容性规则

两个端口要通过 Connector 连接,它们的 Interface 必须兼容:

  • 相同类型的 Interface(SenderReceiver 对 SenderReceiver)
  • 相同的 DataElement 名称和类型
  • 兼容的数据类型(考虑 CompuMethod 的转换)
兼容:
  PPort: SenderReceiverInterface { EngineSpeed: uint16 }
  RPort: SenderReceiverInterface { EngineSpeed: uint16 }
  ✓ 可以连接

不兼容:
  PPort: SenderReceiverInterface { EngineSpeed: uint16 }
  RPort: ClientServerInterface { GetSpeed: Operation }
  ✗ Interface 类型不同,不能连接

7.5 多层 Composition

Composition 可以嵌套——一个 Composition 内部可以包含子 Composition:

+-- Composition: VehicleSystem --+
|  +-- Composition: Engine --+   |
|  |  SensorSWC               |   |
|  |  ControlSWC              |   |
|  |  ActuatorSWC             |   |
|  +--------------------------+   |
|  +-- Composition: Body --+     |
|  |  LightSWC              |     |
|  |  WindowSWC             |     |
|  +--------------------------+   |
+---------------------------------+

嵌套的 Composition 通过多层 DelegationConnector 将内部端口映射到最外层。

7.6 设计实践:如何划分 Composition

好的 Composition 设计遵循以下原则:

  1. 功能内聚:同一 Composition 内的 SWC 应该实现同一个功能域
  2. 松耦合:不同 Composition 之间通过明确定义的接口通信
  3. 可复用:Composition 应该可以在不同的上下文中使用
  4. 层次清晰:避免过深的嵌套(通常不超过 3 层)
推荐的层次结构:
Level 0: Vehicle (整车)
├── Level 1: Powertrain (动力总成)
│   ├── Level 2: Engine Management
│   ├── Level 2: Transmission Control
│   └── Level 2: Fuel System
├── Level 1: Body (车身)
│   ├── Level 2: Lighting
│   ├── Level 2: HVAC
│   └── Level 2: Door Control
└── Level 1: Chassis (底盘)
    ├── Level 2: Brake System
    ├── Level 2: Steering
    └── Level 2: Suspension

小结

  • Composition 是多个 SWC 的组合容器
  • AssemblySwConnector 连接内部 SWC 之间的端口
  • DelegationSwConnector 映射内部端口到外部
  • PassThroughSwConnector 用于直通连接
  • 端口连接需要 Interface 兼容

思考题

  1. 一个车窗控制系统需要哪些 SWC?如何组织 Composition?
  2. AssemblySwConnector 和 DelegationSwConnector 的区别是什么?
  3. 为什么 Composition 嵌套不宜过深?

第8课:模式管理

学习目标

  • 理解 AUTOSAR 模式管理的核心概念
  • 掌握 ModeDeclaration、ModeDeclarationGroup、ModeTransition
  • 理解模式切换的触发和响应机制
  • 学会设计模式管理策略

8.1 为什么需要模式管理

在嵌入式系统中,ECU 通常需要在不同的工作模式之间切换:

ECU 工作模式示例:
├── Startup(启动中)
├── Normal(正常运行)
├── Degraded(降级运行 - 部分功能失效)
├── LimpHome(跛行回家 - 最小功能)
├── Sleep(休眠)
└── Shutdown(关机)

AUTOSAR 的模式管理提供了一套标准化的方式来定义和切换这些模式。

8.2 ModeDeclaration(模式声明)

ModeDeclaration 代表一个具体的模式值。

ModeDeclarationGroup: EcuMode
├── initialMode: Startup
├── ModeDeclaration: Startup
├── ModeDeclaration: Normal
├── ModeDeclaration: Degraded
├── ModeDeclaration: LimpHome
├── ModeDeclaration: Sleep
└── ModeDeclaration: Shutdown

类比:ModeDeclaration 就像状态机中的"状态"——每个状态代表系统的一种工作条件。

8.3 ModeTransition(模式转换)

ModeTransition 定义了允许的模式切换路径:

允许的模式转换:
Startup ──→ Normal
Normal ──→ Degraded
Normal ──→ Sleep
Degraded ──→ LimpHome
Degraded ──→ Normal
LimpHome ──→ Shutdown
Sleep ──→ Normal
Sleep ──→ Shutdown
ModeTransition: StartupToNormal
├── enteredMode: Normal
└── exitedMode: Startup

ModeTransition: NormalToDegraded
├── enteredMode: Degraded
└── exitedMode: Normal

8.4 ModeSwitchInterface 的使用

模式切换通过 ModeSwitchInterface 实现:

Mode Sender(模式发送方):通常是状态管理器 SWC

/* 状态管理器 - 决定 ECU 应该处于什么模式 */
void StateManager_Run(void) {
    EcuModeType currentMode;
    Rte_Mode_EcuMode_EcuModeGroup(&currentMode);

    if (currentMode == Normal && faultDetected) {
        /* 检测到故障,切换到降级模式 */
        Rte_Mode_EcuMode_EcuModeGroup(Degraded);
    }

    if (currentMode == Degraded && faultCleared) {
        /* 故障清除,恢复正常模式 */
        Rte_Mode_EcuMode_EcuModeGroup(Normal);
    }
}

Mode Receiver(模式接收方):需要响应模式变化的 SWC

/* 应用 SWC - 根据当前模式调整行为 */
void Application_Run(void) {
    EcuModeType mode;
    Rte_Mode_EcuMode_EcuModeGroup(&mode);

    switch (mode) {
        case Normal:
            /* 全功能运行 */
            EnableAllFeatures();
            break;
        case Degraded:
            /* 降级运行 */
            DisableNonCritical();
            break;
        case LimpHome:
            /* 最小功能 */
            MinimalOperation();
            break;
    }
}

8.5 SwcModeSwitchEvent

SwcModeSwitchEvent 是一种事件类型,当模式切换发生时触发特定的 Runnable:

/* 当切换到 Degraded 模式时触发 */
void OnEnterDegraded_Run(void) {
    /* 进入降级模式的特殊初始化 */
    SaveCriticalData();
    ActivateBackupSensors();
    SetDefaultParameters();
}

/* 当离开 Degraded 模式时触发 */
void OnExitDegraded_Run(void) {
    /* 离开降级模式的清理 */
    RestoreNormalConfig();
}

8.6 模式管理的层次

AUTOSAR 支持多层次的模式管理:

层次 1: ECU 全局模式
├── Startup, Normal, Sleep, Shutdown
│
层次 2: 子系统模式
├── CommunicationMode: Normal, Silent, ListenOnly
├── DiagnosticMode: Off, Extended, Production
│
层次 3: SWC 内部模式
├── ControlMode: Manual, Auto, Calibration

每个层次的模式可以独立切换,但也可以相互关联。

8.7 模式错误处理

当模式切换出现问题时(如切换超时),可以配置错误处理行为:

ModeErrorBehavior:
├── errorReactionPolicy:
│   ├── ReportToDefaultErrorHook (报告给默认错误钩子)
│   └── ReportToModeErrorEvent (触发模式错误事件)
└── modeErrorEvent: SwcModeManagerErrorEvent

小结

  • ModeDeclaration 定义具体的模式值
  • ModeDeclarationGroup 组织一组相关的模式
  • ModeTransition 定义允许的模式切换路径
  • ModeSwitchInterface 用于模式的发送和接收
  • SwcModeSwitchEvent 响应模式切换事件

思考题

  1. 设计一个空调系统的模式管理:需要哪些模式?允许哪些转换?
  2. 模式切换过程中,如果正在执行的 Runnable 还没完成怎么办?
  3. 多个 SWC 都需要响应同一个模式切换,如何保证它们同步?

第9课:服务依赖

学习目标

  • 理解 SwcServiceDependency 的概念
  • 掌握常见的服务需求类型(NvM, ComM, EcuM, Watchdog 等)
  • 理解 Role-based Port 的分配机制
  • 学会配置 SWC 对系统服务的依赖关系

9.1 为什么需要服务依赖

SWC 不仅与其他 SWC 通信,还需要使用系统级服务:

  • 读写 NV 数据 → 需要 NvM 服务
  • 控制通信模式 → 需要 ComM 服务
  • 管理 ECU 状态 → 需要 EcuM 服务
  • 喂狗 → 需要 Watchdog 服务
  • 加密通信 → 需要 Crypto 服务

SwcServiceDependency 描述了 SWC 对这些服务的需求。

9.2 SwcServiceDependency 的结构

SwcServiceDependency: NvDataService
├── roleBasedPortAssignment:
│   ├── NvM_Read → RPort:NvM_ReadPort
│   └── NvM_Write → RPort:NvM_WritePort
├── roleBasedDataAssignment:
│   └── NvBlock → DataElement:OdometerValue
├── serviceNeed:
│   └── NvMServiceNeeds
│       ├── NvBlockNeed: Odometer
│       │   ├── nvBlockDataStoragePriority: Medium
│       │   └── timingEvent: NvM_Write_Timer
│       └── dataTypeMapping: ...
└── assignment: RoleBasedDataAssignment

9.3 常见的服务需求

9.3.1 NvM(Non-Volatile Memory Manager)

管理 NV 数据的读写:

/* SWC 通过 RPort 请求 NvM 服务 */
/* 读取 NV 数据 */
void Init_Run(void) {
    NvM_RequestResultType result;
    Rte_Call_NvM_ReadBlock(NvM_BlockId_Odometer, &odomData, &result);
}

/* 写入 NV 数据 */
void Update_Run(void) {
    Rte_Call_NvM_WriteBlock(NvM_BlockId_Odometer, &odomData, &result);
}

NvM 服务的关键配置:

  • nvBlockDataStoragePriority:存储优先级(High/Medium/Low)
  • timingEvent:周期性写入的触发事件
  • immediateNvWrite:是否立即写入

9.3.2 ComM(Communication Manager)

控制通信行为(如控制 CAN 通信的静默/正常模式):

/* 请求通信模式 */
void StateManager_Run(void) {
    Rte_Call_ComM_RequestComMode(ComM_UserHandle, COMM_FULL_COMMUNICATION);
}

9.3.3 EcuM(ECU State Manager)

管理 ECU 的上电/下电状态:

/* 请求 ECU 关机 */
void Shutdown_Request(void) {
    Rte_Call_EcuM_ShutdownTarget(EcuM_State_SHUTDOWN);
}

9.3.4 Watchdog(看门狗)

提供看门狗喂狗服务:

/* 在 Runnable 中喂狗 */
void MainLoop_Run(void) {
    /* 正常执行 */
    ProcessData();
    /* 喂狗 */
    Rte_Call_WdgM_Trigger(WdgM_SupervisionId_MainLoop);
}

9.3.5 其他常见服务

服务 用途 典型使用场景
Dcm (Diagnostic Communication Manager) 诊断通信 UDS 服务处理
Dem (Diagnostic Event Manager) 诊断事件管理 故障码管理
BswM (BSW Mode Manager) BSW 模式管理 模式条件监控
StbM (Synchronized Time-base Manager) 时间同步 网络时间同步
SecOc (Secure Onboard Communication) 安全通信 消息认证
Crypto 加密服务 数据加密/解密
DLT (Diagnostic Log and Trace) 诊断日志 调试信息输出

9.4 Service Use Cases(服务用例)

AUTOSAR 定义了一些标准的服务用例,描述了典型的 SWC 如何与系统服务交互:

用例 1:周期性 NV 数据写入

SWC 每 100ms 更新里程数据
→ 通过 NvM 服务写入 NV 内存
→ NvM 根据优先级和 timingEvent 决定实际写入时机
→ 避免频繁写入 Flash 延长寿命

用例 2:通信控制

SWC 检测到 ECU 应该进入休眠
→ 通过 ComM 请求 COMM_NO_COMMUNICATION
→ ComM 协调所有通信通道关闭
→ 通过 EcuM 请求进入 Sleep 状态

小结

  • SwcServiceDependency 描述 SWC 对系统服务的需求
  • 常见服务:NvM, ComM, EcuM, Watchdog, Dcm, Dem
  • Role-based Port 将服务需求映射到具体的 RPort
  • 服务用例描述了典型的服务交互模式

思考题

  1. 一个故障诊断 SWC 需要依赖哪些系统服务?
  2. NV 数据写入为什么要通过 NvM 服务而不是直接操作 Flash?
  3. 如果两个 SWC 都请求不同的 ComM 模式,ComM 如何处理冲突?

第10课:实战演练 — 完整 SWC 设计案例

学习目标

  • 将前面所有知识综合运用
  • 完成一个完整的 SWC 设计流程
  • 理解从需求到 ARXML 配置的完整思路

10.1 项目需求

设计一个车窗防夹控制系统,功能需求如下:

  1. 实时监测车窗电机电流
  2. 当检测到电流异常增大(可能有障碍物)时,立即停止并反转车窗
  3. 支持正常升/降/自动升/自动降四种模式
  4. 支持来自车身控制器的远程遥控
  5. 记录故障码和运行次数(NV 数据)
  6. 响应 ECU 的休眠/唤醒管理

10.2 SWC 划分

根据功能需求,划分以下 SWC:

Composition: WindowAntiPinch
├── WindowControlSWC (主控制)
│   ├── 输入: 开关信号、远程指令、电机电流
│   ├── 输出: 电机控制信号
│   └── 功能: 防夹算法、状态机
├── CurrentMonitorSWC (电流监测)
│   ├── 输入: ADC 原始值
│   ├── 输出: 滤波后的电流值
│   └── 功能: 滤波、基线校准
├── FaultManagerSWC (故障管理)
│   ├── 输入: 防夹事件、堵转事件
│   ├── 输出: DTC 状态
│   └── 功能: 故障检测、DTC 管理
└── NvDataManagerSWC (NV 数据管理)
    ├── 功能: 运行次数、故障记录的 NV 存储

10.3 WindowControlSWC 详细设计

端口定义:

WindowControlSWC
├── RPort: SwitchInput (SenderReceiver)
│   └── DataElement: SwitchState (uint8: 0=Off, 1=Up, 2=Down, 3=AutoUp, 4=AutoDown)
├── RPort: RemoteCommand (SenderReceiver)
│   └── DataElement: RemoteCmd (uint8: 0=None, 1=Open, 2=Close)
├── RPort: MotorCurrent (SenderReceiver)
│   └── DataElement: CurrentValue (float32, A)
├── PPort: MotorControl (SenderReceiver)
│   └── DataElement: MotorCommand (uint8: 0=Stop, 1=Up, 2=Down)
├── PPort: FaultEvent (SenderReceiver)
│   └── DataElement: PinchDetected (boolean)
├── RPort: VehicleMode (ModeSwitch)
│   └── ModeDeclarationGroup: EcuMode
├── RPort: NvMService (ClientServer)
│   └── Operation: ReadBlock, WriteBlock
└── RPort: Parameters (Parameter)
    ├── Parameter: PinchCurrentThreshold (float32, A)
    ├── Parameter: PinchDebounceTime (uint16, ms)
    └── Parameter: MotorStallTimeout (uint16, ms)

内部行为:

SwcInternalBehavior:
├── Runnable: Init_Run
│   └── trigger: InitEvent
├── Runnable: Control_Run
│   └── trigger: TimingEvent (period=10ms, offset=3ms)
├── Runnable: OnDataReceived
│   └── trigger: DataReceivedEvent (MotorCurrent)
├── Runnable: OnModeChange
│   └── trigger: SwcModeSwitchEvent (EcuMode → Sleep)
├── ExclusiveArea: StateProtection
└── PerInstanceMemory: MotorPosition (float32)

C 代码实现:

/* WindowControlSWC.c */
#include "Rte_WindowControlSWC.h"

/* 内部状态 */
typedef enum {
    STATE_IDLE,
    STATE_MOVING_UP,
    STATE_MOVING_DOWN,
    STATE_AUTO_UP,
    STATE_AUTO_DOWN,
    STATE_PINCH_DETECTED,
    STATE_ERROR
} WindowState;

static WindowState currentState = STATE_IDLE;
static float32 baselineCurrent = 0.0f;
static uint16 pinchDebounceCounter = 0;

/* 初始化 */
void Init_Run(void) {
    currentState = STATE_IDLE;

    /* 读取 NV 数据 */
    NvM_WindowConfig config;
    Rte_Call_NvMService_ReadBlock(NVM_BLOCK_WINDOW_CONFIG, &config);

    /* 读取标定参数 */
    float32 threshold = Rte_Param_PinchCurrentThreshold;
    baselineCurrent = config.lastBaselineCurrent;

    Rte_Write_MotorControl_MotorCommand(MOTOR_STOP);
}

/* 主控制 - 每 10ms 执行 */
void Control_Run(void) {
    /* 读取输入 */
    uint8 switchState = Rte_Read_SwitchInput_SwitchState();
    float32 current = Rte_Read_MotorCurrent_CurrentValue();

    /* 防夹检测 */
    bool pinchDetected = false;
    float32 threshold = Rte_Param_PinchCurrentThreshold;

    if (currentState == STATE_MOVING_UP || currentState == STATE_AUTO_UP) {
        if (current > baselineCurrent + threshold) {
            pinchDebounceCounter++;
            uint16 debounceTime = Rte_Param_PinchDebounceTime;
            if (pinchDebounceCounter >= (debounceTime / 10)) {
                pinchDetected = true;
            }
        } else {
            pinchDebounceCounter = 0;
        }
    }

    /* 状态机处理 */
    if (pinchDetected) {
        /* 检测到防夹 */
        currentState = STATE_PINCH_DETECTED;
        Rte_Write_MotorControl_MotorCommand(MOTOR_DOWN); /* 反转 */
        Rte_Write_FaultEvent_PinchDetected(TRUE);
    } else {
        switch (switchState) {
            case 0: /* Off */
                if (currentState != STATE_IDLE) {
                    Rte_Write_MotorControl_MotorCommand(MOTOR_STOP);
                    currentState = STATE_IDLE;
                }
                break;
            case 1: /* Up */
                Rte_Write_MotorControl_MotorCommand(MOTOR_UP);
                currentState = STATE_MOVING_UP;
                break;
            case 2: /* Down */
                Rte_Write_MotorControl_MotorCommand(MOTOR_DOWN);
                currentState = STATE_MOVING_DOWN;
                break;
            case 3: /* AutoUp */
                Rte_Write_MotorControl_MotorCommand(MOTOR_UP);
                currentState = STATE_AUTO_UP;
                break;
            case 4: /* AutoDown */
                Rte_Write_MotorControl_MotorCommand(MOTOR_DOWN);
                currentState = STATE_AUTO_DOWN;
                break;
        }
    }

    /* 更新基线电流(简单移动平均) */
    if (currentState == STATE_IDLE) {
        baselineCurrent = current; /* 静止时更新基线 */
    }
}

/* 休眠处理 */
void OnSleepMode_Run(void) {
    /* 保存当前状态到 NV */
    Rte_Write_MotorControl_MotorCommand(MOTOR_STOP);

    NvM_WindowConfig config;
    config.lastBaselineCurrent = baselineCurrent;
    config.lastState = currentState;
    Rte_Call_NvMService_WriteBlock(NVM_BLOCK_WINDOW_CONFIG, &config);

    currentState = STATE_IDLE;
}

10.4 ARXML 配置思路

在实际项目中,以上设计会被建模为 ARXML 文件。以下是关键的配置项:

<!-- 简化的 ARXML 结构示意 -->
<AR-PACKAGE>
  <ELEMENTS>
    <!-- SWC 类型定义 -->
    <APPLICATION-SW-COMPONENT-TYPE>
      <SHORT-NAME>WindowControlSWC</SHORT-NAME>
      <PORTS>
        <R-PORT-PROTOTYPE>
          <SHORT-NAME>SwitchInput</SHORT-NAME>
          <REQUIRED-INTERFACE-TREF DEST="SENDER-RECEIVER-INTERFACE">
            /PortInterfaces/SwitchInput_IF
          </REQUIRED-INTERFACE-TREF>
        </R-PORT-PROTOTYPE>
        <!-- ... 更多端口 ... -->
      </PORTS>
      <INTERNAL-BEHAVIORS>
        <SWC-INTERNAL-BEHAVIOR>
          <RUNNABLES>
            <RUNNABLE-ENTITY>
              <SHORT-NAME>Control_Run</SHORT-NAME>
              <SYMBOL>Control_Run</SYMBOL>
            </RUNNABLE-ENTITY>
          </RUNNABLES>
          <EVENTS>
            <TIMING-EVENT>
              <SHORT-NAME>TimingEvent_10ms</SHORT-NAME>
              <PERIOD VALUE="10"/>  <!-- 10ms -->
              <OFFSET VALUE="3"/>   <!-- 3ms offset -->
              <STARTS-EVENTS-REF DEST="RUNNABLE-ENTITY">Control_Run</STARTS-EVENTS-REF>
            </TIMING-EVENT>
          </EVENTS>
        </SWC-INTERNAL-BEHAVIOR>
      </INTERNAL-BEHAVIORS>
    </APPLICATION-SW-COMPONENT-TYPE>
  </ELEMENTS>
</AR-PACKAGE>

10.5 设计检查清单

完成 SWC 设计后,使用以下检查清单验证:

小结

  • SWC 设计从功能需求出发,划分合理的模块
  • 端口定义决定了 SWC 与外界的交互
  • 内部行为定义了执行逻辑和调度
  • ARXML 将所有配置形式化
  • 设计检查清单确保完整性

附录

A. 常用术语表

术语 中文 说明
ARXML AUTOSAR XML AUTOSAR 配置描述文件格式
AtomicSwComponentType 原子软件组件类型 包含实际代码实现的最小组件
BSW Basic Software 基础软件层
CompuMethod 计算方法 数据缩放/转换规则
Composition 组合 多个 SWC 的集合容器
Connector 连接器 SWC 之间的连接关系
DataConstraint 数据约束 数据的有效范围
DataElement 数据元素 Interface 中的基本数据单元
DelegationSwConnector 委托连接器 内部端口到外部端口的映射
ExclusiveArea 互斥区 并发保护机制
ImplementationDataType 实现数据类型 代码中实际使用的数据类型
InitEvent 初始化事件 SWC 启动时触发
InterRunnableVariable Runnable间变量 同一 SWC 内 Runnable 共享的变量
ModeDeclaration 模式声明 一个具体的模式值
ModeDeclarationGroup 模式声明组 一组相关模式的集合
ModeSwitchInterface 模式切换接口 用于模式切换通信
NvBlock NV 块 非易失性数据块
Operation 操作 ClientServer 接口中的方法
PerInstanceMemory 实例内存 每个 SWC 实例独立的内存
PPort (Provided Port) 提供端口 SWC 提供数据/服务的端口
PRPort 提供-请求端口 双向通信端口
RecordLayout 记录布局 标定数据的内存布局
Required Port (RPort) 请求端口 SWC 请求数据/服务的端口
RTE Runtime Environment 运行时环境
RunnableEntity 可执行实体 SWC 内部的基本执行单元
SenderReceiverInterface 发送接收接口 周期性数据交换接口
ServiceNeeds 服务需求 SWC 对系统服务的需求
SwBaseType 软件基础类型 最底层的数据类型
SwcInternalBehavior SWC 内部行为 SWC 行为的完整描述
SwcServiceDependency SWC 服务依赖 SWC 与系统服务的关联
TimingEvent 定时事件 按固定周期触发的事件
VariableAccess 变量访问 Runnable 对数据的读写访问

B. RTE API 速查

API 用途 示例
Rte_Read_<Port>_<Data>() 读取 SenderReceiver 数据 Rte_Read_Sensor_Temp(&val)
Rte_Write_<Port>_<Data>() 写入 SenderReceiver 数据 Rte_Write_Output_Speed(val)
Rte_Invalidate_<Port>_<Data>() 标记数据无效 Rte_Invalidate_Sensor_Temp()
Rte_IsValid_<Port>_<Data>() 检查数据有效性 if (Rte_IsValid_Sensor_Temp())
Rte_Call_<Port>_<Op>() 调用 ClientServer 操作 Rte_Call_NvM_Read(id, &data)
Rte_Mode_<Port>_<Group>() 读取/设置模式 Rte_Mode_ECU_ModeGroup(&mode)
Rte_Enter_<Area>() 进入互斥区 Rte_Enter_DataProtect()
Rte_Exit_<Area>() 退出互斥区 Rte_Exit_DataProtect()
Rte_Reason() 获取激活原因 reason = Rte_Reason()
Rte_Param_<Name> 读取标定参数 kp = Rte_Param_PID_Kp

C. 学习资源推荐

官方文档:

  • AUTOSAR CP R25-11 Software Component Template(本文档)
  • AUTOSAR CP R25-11 RTE (Runtime Environment) 规范
  • AUTOSAR CP R25-11 BSW Module Description Template

入门书籍:
-《AUTOSAR 软件架构》— 系统介绍 AUTOSAR 整体架构
-《汽车电子软件设计》— 从汽车电子角度介绍

工具链:

  • EB tresos / EB studio — Elektrobit 的 AUTOSAR 配置工具
  • DaVinci Configurator / Developer — Vector 的 AUTOSAR 工具链
  • ISOLAR — ETAS 的 AUTOSAR 开发环境
  • MATLAB/Simulink + AUTOSAR Blockset — 基于模型的设计

实践建议:

  1. 先用本教程建立整体概念
  2. 阅读官方文档的第 1-4 章(概述和核心概念)
  3. 尝试用工具(如 DaVinci 或 EB)创建一个简单的 SWC 配置
  4. 生成 RTE 代码,观察生成的 API
  5. 编写 Runnable 实现,编译运行
  6. 逐步增加复杂度:添加更多端口、事件、模式

本教程覆盖了 AUTOSAR CP Software Component Template 的核心概念。
建议结合官方文档的完整中文翻译一起学习。
如有疑问,欢迎在实践中探索和验证。

posted @ 2026-07-16 14:18  无极至上  阅读(9)  评论(0)    收藏  举报