
第02篇AUTOSAR BSW模块家族——谁是“通信担当”谁是“管家担当” 核心内容目录BSW的三层“夹心”结构回顾——Services / ECU Abstraction / MCAL通信栈Communication Stack——从COM到CAN Driver的数据流路径诊断栈Diagnostic Stack——DCM与DEM的职责分工存储栈Memory Stack——NvM / Fee / Ea / MemIf 的存储层次图解一个CAN报文从应用层发到总线上的“旅行路线”1. 从办公室场景出发认识BSW的“部门架构”想象你入职了一家大公司第一天走进办公区看到几十个工位上坐满了人每个人都忙忙碌碌。你问HR“他们分别负责什么”HR回答“左边那一排是通信部负责对外联络中间那一排是诊断部负责处理投诉和故障报修右边那一排是存储部负责档案管理角落里的老张是OS部负责整个办公室的排班调度。”这就是AUTOSAR BSW模块的构成逻辑——BSW不是一个单独的模块而是一组模块的集合按职能划分成若干个“部门”模块组。AUTOSAR CP中的BSW包含了几十个功能模块。如果逐个学习会非常零散且效率低下。好的方法是先按职能把它们分成“几大家族”再深入每个家族的具体成员。2. BSW三层结构快速回顾在第01篇中我们已经建立了BSW的基础认知。先花1分钟快速回顾RTE 通信转接标准化接口基础软件层BSW微控制器抽象层MCALCAN Driver / SPI Driver / GPT Driver服务层ServicesCOM / DCM / DEM / NvM / OS / WdgECU抽象层ECU AbstractionCAN IF / LIN IF / Fee / MemIfRTE通信转接运行时环境应用层ASW老板只关心做什么今天我们把这几十个BSW模块按照职能重新分组建立一张清晰的“部门组织架构图”。3. BSW模块的四大家族家族名称核心模块角色类比主要职责 通信家族COM / PduR / CanIf / CanDrv / LinIf / EthIf“外交部”负责所有进出ECU的数据收发 诊断家族DCM / DEM / FIM“医院保险公司”负责故障检测、存储、上报和诊断请求处理️ 存储家族NvM / Fee / Ea / MemIf“档案馆”负责非易失性数据的读写和管理⏰ 系统服务家族OS / Wdg / EcuM / BswM“总务处”负责任务调度、看门狗监控、ECU状态管理在实际开发中通信家族和诊断家族是你接触频率最高的两个模块组也是本篇的重点。下面我们逐一深入每个家族。4. 通信家族Communication Stack——ECU的“外交部”通信家族是BSW中规模最大、调用最频繁的模块组。它的核心任务很简单让数据从一个地方走到另一个地方。但这个“简单任务”涉及的数据流方向很多发送方向ASW产生数据 → 交给通信家族 → 打包成CAN/LIN/以太网帧 → 发送到总线接收方向从总线收到CAN/LIN帧 → 通信家族解析 → 提取Signal → 交给ASW4.1 通信家族的核心成员我们从底层到顶层逐一认识层级模块全称职责MCALCanDrvCAN Driver直接操作CAN控制器寄存器发送/接收CAN帧硬件级MCALLinDrvLIN Driver直接操作LIN控制器发送/接收LIN帧ECU抽象CanIfCAN Interface统一CAN通信接口管理多个CAN控制器对上层屏蔽硬件差异ECU抽象LinIfLIN Interface统一LIN通信接口管理多个LIN通道ECU抽象EthIfEthernet Interface统一以太网通信接口用于车载以太网座舱域常见服务层PduRPDU Router核心枢纽根据路由表把PDU协议数据单元转发到目标模块服务层ComCommunication Service最核心Signal打包/解包、信号网关、通信状态管理服务层CanTpCAN Transport ProtocolCAN传输层协议用于长报文分段传输如UDS on CAN重点理解当你说“我要发一个CAN报文”时数据实际经过了Com → PduR → CanIf → CanDrv这条链路。4.2 核心模块深度解析 Com通信服务模块Com是通信家族中工作量最大的模块它直接与RTE对接。它的职责包括Signal打包把多个Signal例如车速、水温、转速按照DBC定义的布局打包到一个PDU的Data Field中。Signal解包从收到的PDU中提取出各个Signal。信号网关把从CAN收到的Signal转发到LIN或以太网跨网络转发。通信模式管理控制通信状态开启/关闭/待机。信号监测监控Signal的超时、有效性等。Com模块的配置信息通常来自系统设计阶段定义的通信矩阵例如DBC文件。 PduRPDU路由器PduR是通信家族里的交通警察。它不负责“制造”数据只负责“路由”数据。PduR根据配置的路由表决定一个PDU的去向来源 → PduR → 目标 ───────────────────────────── Com发送 → PduR → CanIf发送到CAN总线 CanIf接收 → PduR → Com交给上层 CanIf接收 → PduR → Dcm诊断报文直接走诊断通道 CanIf接收 → PduR → CanTp长报文需要分段重组PduR的路由策略是实现“诊断报文直接走诊断栈、普通报文走COM”的关键机制。 CanIfCAN接口模块CanIf是ECU抽象层的代表模块它的核心价值在于屏蔽多CAN控制器差异一个ECU可能有多个CAN控制器比如CAN0、CAN1每个控制器的硬件访问方式不同。CanIf向上层提供统一的接口。管理CAN控制器状态启动、停止、休眠、唤醒。 CanDrvCAN驱动模块CanDrv是最底层的MCAL模块直接操作芯片的CAN控制器寄存器。它的典型函数包括// 伪代码示例CanDrv_Init(canConfig);// 初始化CAN控制器CanDrv_Write(canCtrlId,pdu);// 发送一个CAN帧CanDrv_Read(canCtrlId,pdu);// 接收一个CAN帧CanDrv_IrqHandler();// CAN中断处理函数CanDrv通常由芯片厂商提供底层驱动代码如英飞凌的iLLD、NXP的MCAL SDK。5. 诊断家族Diagnostic Stack——ECU的“医院”诊断家族负责的是让ECU具备“感知疾病、记录病情、接受治疗”的能力。在智能汽车上诊断功能是法规强制要求如OBD法规也是售后维修的基础工具。5.1 诊断家族的核心成员模块全称职责DCMDiagnostic Communication Manager“急诊科”接收诊断仪请求解析UDS服务分发到其他模块DEMDiagnostic Event Manager“病历科”管理诊断事件DTC记录故障发生时的快照数据FIMFunction Inhibition Manager“康复科”根据故障状态禁止或恢复某些功能如检测到刹车故障→禁用巡航功能三个模块的协作关系DCM负责“接诊”DEM负责“建档”FIM负责“下医嘱”。5.2 核心模块深度解析 DCM诊断通信管理器DCM是诊断家族里最繁忙的模块。每一条UDS诊断请求都由DCM处理。它的典型工作流程是收到诊断请求例如$22 读取DTC状态。解析服务ID和子功能。检查安全访问状态如果服务需要安全级别。执行对应的诊断操作如读取DTC、写入数据、执行例程。组装正响应或负响应NRC发送回去。DCM需要支持的UDS服务示例服务ID名称用途$10Diagnostic Session Control切换诊断会话默认/编程/扩展$22Read Data By Identifier通过DID读取数据如软件版本号$27Security Access安全访问验证密钥校验$2EWrite Data By Identifier通过DID写入数据$31Routine Control执行/停止/查询例程$34Request Download请求下载OTA/Bootloader$36Transfer Data传输数据OTA/Bootloader$37Request Transfer Exit退出传输OTA/Bootloader在座舱MCU开发中DCM是你打交道最多的模块之一。 DEM诊断事件管理器DEM的职责是管理ECU内部发生的“事件”事件监控应用层或BSW模块报告“某温度传感器值超阈值”。事件存储将事件记录为DTC诊断故障码存储到非易失性存储器。快照数据在事件发生时刻冻结关键数据如当时的速度、温度、电压。事件状态管理维护DTC的状态位如“当前故障”、“历史故障”、“已确认”等。DEM与DCM的协作关系DEM负责“制造病历”监控故障、存储DTC。DCM负责“查看病历”响应$22读取DTC请求。6. 存储家族Memory Stack——ECU的“档案馆”存储家族负责把需要“永久记住”的数据写入非易失性存储器Flash/EEPROM。6.1 存储家族的核心成员模块全称职责NvMNVRAM Manager“档案管理员”统一管理所有需要持久化的数据块FeeFlash EEPROM Emulation“Flash模拟EEPROM”把MCU内部的Flash模拟成EEPROM使用EaEEPROM Abstraction“EEPROM抽象”直接访问外接的EEPROM芯片MemIfMemory Interface“存储接口”为上层NvM提供统一的存储访问接口6.2 核心模块深度解析️ NvM非易失性内存管理NvM是存储家族里唯一与上层直接交互的模块。ASW通过RTE调用NvM接口来读写数据。NvM的功能包括管理多个数据块Block每个Block有唯一的ID。支持即时写入写穿或周期写入写回。支持数据校验CRC和数据冗余防止写入过程中断电损坏。支持数据初始化新ECU首次上电时写入默认值。 FeeFlash EEPROM仿真Fee模块的目的是大多数MCU自带的数据FlashDFlash可擦写次数有限约10万次直接用于频繁写入数据会快速老化。Fee通过在Flash上实现磨损均衡Wear Leveling算法延长存储寿命。Fee的内部机制比较复杂但作为使用者你只需要知道Fee是NvM和Flash硬件之间的“中间层”。NvM的读写请求通过MemIf → Fee → Flash Driver 完成。7. 系统服务家族System Services——ECU的“总务处”模块职责OS实时操作系统任务调度、中断处理、时间管理Wdg看门狗监控软件运行状态超时则复位ECUEcuMECU状态管理器控制ECU的启动、运行、休眠、关机BswMBSW模式管理器协调BSW各模块的模式切换如通信模式、诊断模式SchM调度管理器管理BSW模块内部的调度点OS是系统服务家族的核心我们在后续第9篇功能安全中会重点展开。8. 图解开篇一个CAN报文从应用到总线的“旅行路线”现在我们把通信家族的所有模块串联起来走一遍完整的CAN报文发送流程。场景设定应用层ASW需要发送一个“当前车速”信号车速值80km/h到CAN总线上。完整的数据流路径第1步ASW产生数据 ───────────────────────────────────── ASW中的某个Runnable函数调用 Rte_Write_VehicleSpeed(80); // 车速80km/h ↓ 数据交给RTE 第2步RTE转交数据给COM ───────────────────────────────────── RTE根据ARXML配置调用Com模块接口 Com_SendSignal(VehicleSpeed_Signal, 80); ↓ 数据交给COM 第3步COM打包Signal到PDU ───────────────────────────────────── COM根据DBC定义的布局起始位、长度、字节序 - 将80km/h转换为原始值乘以Factor、加上Offset - 将原始值填入PDU Data Field的对应位位置 - 填充其他Signal如果有 Com_SendPdus(); → 调用PduR接口 ↓ PDU含Signal数据交给PduR 第4步PduR路由PDU ───────────────────────────────────── PduR根据路由表查找 - 该PDU的目标通信协议是CAN - 目标CAN控制器是CAN0 - 调用CanIf接口 CanIf_Transmit(canCtrlId0, pdu); ↓ PDU交给CanIf 第5步CanIf添加CAN帧头 ───────────────────────────────────── CanIf将PDU打包成CAN帧格式 - 添加CAN ID从配置中获取 - 设置DLC数据长度通常为8字节 - 调用CanDrv_Write(canCtrlId, canFrame); ↓ CAN帧交给CanDrv 第6步CanDrv发送CAN帧 ───────────────────────────────────── CanDrv直接操作CAN控制器寄存器 - 将CAN帧写入CAN控制器的发送邮箱Tx Mailbox - 设置发送请求标志 - CAN控制器自动将帧发送到CAN总线 ↓ 最终物理层将差分信号发送到CAN总线上 完成对应的模块调用关系链ASW → RTE → COM → PduR → CanIf → CanDrv → CAN总线这个过程是AUTOSAR CP通信栈的标准数据流你需要像背乘法口诀一样熟悉它。9. 本篇重点回顾家族核心模块一句话职责通信家族Com / PduR / CanIf / CanDrv负责所有数据收发诊断家族DCM / DEM / FIM负责故障监控和诊断请求处理存储家族NvM / Fee / MemIf负责数据持久化系统服务家族OS / Wdg / EcuM / BswM负责调度、监控、状态管理发送数据流路径ASW→RTE→COM→PduR→CanIf→CanDrv→总线标准通信流程 第二篇交付物清单请完成以下实践任务巩固本篇所学画出BSW模块家族分类图用draw.io或手绘画出一张包含四大模块家族通信、诊断、存储、系统服务的组织架构图标注每个家族的核心模块名称。追踪一条接收路径思考并写出当一个CAN帧从CAN总线上到达MCU时数据依次经过哪些模块顺序是什么提示与发送路径相反模块匹配练习把以下功能匹配到对应的模块名称选填Com / PduR / CanIf / DCM / DEM / NvM / Fee把车速信号打包成PDU的Data Field → ______决定一个PDU发到CAN还是LIN → ______响应诊断仪发送的$22服务请求 → ______存储故障发生时快照数据 → ______在Flash上实现磨损均衡 → ______ 参考代码片段以下是一个简化的COM发送伪代码帮助理解// Com模块的发送信号函数简化版voidCom_SendSignal(SignalIdType signalId,uint32_tvalue){uint8_tpduData[MAX_PDU_LENGTH];uint16_tpduIdCom_GetPduId(signalId);// 1. 将物理值转换为原始值Factor Offsetint32_trawValue(value/Com_GetSignalFactor(signalId))Com_GetSignalOffset(signalId);// 2. 将原始值按位布局写入PDU数据缓存Com_PackSignal(pduData,signalId,rawValue);// 3. 调用PduR发送PDUPduR_ComTransmit(pduId,pduData);}你已经完成了第二篇的学习。第三篇我们将进入CAN协议的“物理课”——从差分信号、帧格式到DBC解析彻底搞懂CAN通信的每个细节。