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
思考题
- 在你目前的项目中,应用层代码和底层驱动是如何划分的?有没有用到类似 RTE 的分层思想?
- 如果你的项目要移植到另一款 MCU 上,哪些代码需要修改?AUTOSAR 的方式能减少多少改动?
- 你认为 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 | 触发信号 | 中断信号 |
最常用的两种是 SenderReceiverInterface 和 ClientServerInterface,后续课程会详细展开。
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 与外界通信,不直接访问底层
思考题
- 在你熟悉的项目中,哪些功能模块可以被建模为独立的 SWC?
- 一个控制算法 SWC 应该有哪些 Port?分别是什么类型?
- 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 读到的数据是完整的。这通过 DataInvalidPolicy 和 InitValue 等属性配置。
数据有效性:
每个 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(¤tMode);
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 类型取决于通信模式和数据特性
思考题
- 一个发动机控制 SWC 需要与哪些外部模块通信?分别适合用什么 Interface?
- SenderReceiver 和 ClientServer 的核心区别是什么?什么场景下不能用 SenderReceiver 替代 ClientServer?
- 为什么标定参数要用专门的 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 精细控制通信行为的每个细节
- 选择通信模式需要根据实时性、可靠性需求权衡
思考题
- 如果一个传感器数据需要每 10ms 更新,但控制算法每 50ms 才需要,你会如何配置 DataFilter?
- 在什么场景下,Client-Server 的同步阻塞特性会成为问题?如何解决?
- 数据一致性的三种策略各适用于什么场景?
第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 保护共享数据的并发访问
思考题
- 一个 PID 控制 Runnable 应该用 TimingEvent 还是 DataReceivedEvent 触发?为什么?
- 如果两个 Runnable 共享一个变量,一个 10ms 执行一次,一个 50ms 执行一次,需要怎样的保护?
- 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 定义标定数据的内存布局
思考题
- 一个温度传感器,ADC 范围 0-4095 对应 -40°C 到 125°C,你会用什么 CompuMethod?
- 为什么标定参数不能直接用 float64 存储?考虑 MCU 的资源限制。
- 如果一个数据需要在两个不同分辨率的 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 设计遵循以下原则:
- 功能内聚:同一 Composition 内的 SWC 应该实现同一个功能域
- 松耦合:不同 Composition 之间通过明确定义的接口通信
- 可复用:Composition 应该可以在不同的上下文中使用
- 层次清晰:避免过深的嵌套(通常不超过 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 兼容
思考题
- 一个车窗控制系统需要哪些 SWC?如何组织 Composition?
- AssemblySwConnector 和 DelegationSwConnector 的区别是什么?
- 为什么 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(¤tMode);
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 响应模式切换事件
思考题
- 设计一个空调系统的模式管理:需要哪些模式?允许哪些转换?
- 模式切换过程中,如果正在执行的 Runnable 还没完成怎么办?
- 多个 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
- 服务用例描述了典型的服务交互模式
思考题
- 一个故障诊断 SWC 需要依赖哪些系统服务?
- NV 数据写入为什么要通过 NvM 服务而不是直接操作 Flash?
- 如果两个 SWC 都请求不同的 ComM 模式,ComM 如何处理冲突?
第10课:实战演练 — 完整 SWC 设计案例
学习目标
- 将前面所有知识综合运用
- 完成一个完整的 SWC 设计流程
- 理解从需求到 ARXML 配置的完整思路
10.1 项目需求
设计一个车窗防夹控制系统,功能需求如下:
- 实时监测车窗电机电流
- 当检测到电流异常增大(可能有障碍物)时,立即停止并反转车窗
- 支持正常升/降/自动升/自动降四种模式
- 支持来自车身控制器的远程遥控
- 记录故障码和运行次数(NV 数据)
- 响应 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-4 章(概述和核心概念)
- 尝试用工具(如 DaVinci 或 EB)创建一个简单的 SWC 配置
- 生成 RTE 代码,观察生成的 API
- 编写 Runnable 实现,编译运行
- 逐步增加复杂度:添加更多端口、事件、模式
本教程覆盖了 AUTOSAR CP Software Component Template 的核心概念。
建议结合官方文档的完整中文翻译一起学习。
如有疑问,欢迎在实践中探索和验证。

浙公网安备 33010602011771号