目录
1 简介
EcuM(ECU State Manager)模块管理Ecu状态特指Ecu的上下电状态(包含STARTUP, OFF, UP, SLEEP阶段),每个Ecu状态包含很多内容,举个栗子:在进入STARTUP阶段时,需要初始化BswM,OS,Rte等模块,而在UP阶段,需对唤醒事件进行验证。因为在汽车电子中对ECU的上下电时序要求非常严格,AUTOSAR则特地为此整了一个EcuM模块来系列化这个过程。EcuM 模块位于 AUTOSAR 的系统服务层,透过 RTE 与用户直接交互,在基础软件中与 BswM、ComM 及驱动模块等交互。
2 缩略语
2.1 缩写表
缩写 | 描述 | 解释 |
---|---|---|
BswM | Basic Software Mode Manager | Bsw模式管理模块 |
Gpt | General Purpose Timer | 通用定时器模块 |
Icu | Input Capture Unit | 输入捕获单元 |
ISR | Interrupt Service Routine | 中断服务例程 |
Rte | Runtime Environment | 运行时环境 |
VFB | Virtual Function Bus | 虚拟功能总线 |
3 对其他模块的依赖
Module | dependencies |
---|---|
Mcu | Mcu驱动程序是EucM初始化的第一个基本软件模块, see Mcu_Init(), 在使用BSW模块之前需要提前对各个相互依赖的驱动程序进行初始化,甚至有些驱动程序也依赖其他驱动程序,举个栗子:外部wdg使用之前需要SPI的初始化 |
唤醒驱动(e.g : Trcv) | 在指定的驱动程序检测到唤醒源时,须调用EcuM_SetWakeupEvent通知EcuM,驱动须在以下几种情况下上报唤醒事件: 1. Ecu处于睡眠阶段等待唤醒事件时,2 . 驱动程序初始化时,3. EcuM_MainFunction运行时的正常操作期间调用。一般地,远程唤醒事件需要进行验证 |
OS | EcuM启动和关闭OS,并定义了在OS启动前如何处理控制以及在OS关闭后如何处理控制的协议 |
ComM | 在唤醒源通过验证之后,EcuM须通过ComM_EcuM_ WakeUpIndication或ComM_EcuM_ PNCWakeUpIndication通知ComM |
BswM | BswM仅在SchM运行期间才管理ECU电源状态,也就是BswM的管理仅在调度函数可用期间,那么在ECU刚刚上电,进入休眠,关闭OS期间还是EcuM控制电源状态;在唤醒源状态改变时,EcuM也会通知BswM |
这里需要特别说一下EcuM和BswM的关系,避免混淆:这两者并非上下级关系,而是合作关系;往往BswM能够从各个管理模块(e.g : CanSM, ComM,EcuM)收到状态变更的通知,以方便BswM进行仲裁并实施具体的Action; 为了让EcuM将当前Ecu状态(e.g : RUN,POST_RUN)通知BswM,需要配置EcuMModeHanding, 当然,如果EcuM不把当前Ecu状态通知BswM,BswM也可以通过Rte获得(参见RteBswRequiredModeGroupConnection)。
4 EcuM功能概述
EcuM有两种EcuMFixed( AUTOSAR3.x)和EcuMFlex( AUTOSAR4.x),EcuMFlex主要是为了适应不同应用场景的各种不同需求,实现更加灵活的处理。所以在AUTOSAR官方文档中,《AUTOSAR_SWS_ECUStateManager.pdf》则对应的是EcuMFlex,《AUTOSAR_SWS_ECUStateManagerFixed.pdf》则对应的是EcuMFixed。
两者主要区别在于 EcuMFixed 中的模式和状态是固定的,而 EcuMFlex 中删除了许多模式和状态,这些模式和状态的定义根据不同需求由 BswM 模块加以定义。因此EcuMFlex 也必须与 BswM 配合使用才能实现完整的模式和状态处理。
注: 本文主要介绍最常被使用的EcuMFlex,至于EcuMFixed ,感兴趣的小伙伴可自行查阅资料研究。
4.1 ECU状态处理
如上图所示,可以将Ecu状态分为四个阶段:STARTUP、UP、SLEEP、SHUTDOWN。下面我们把各个阶段中的内容拆分开来看:
4.1.1 STARTUP阶段
STARTUP阶段主要分为4个步骤:
- PowerOn : 上电或者Reset后,首先是从cstart.c这样的引导代码,引导ECU程序进入core_mian()函数;
- StartPreOS :进入EcuM_Init(), 在这做如下表中的动作,最后才启动OS;
- StartPostOS :启动OS之后会进入一个init task中,在该任务内须调用EcuM_StartupTwo(),StartPostOs 存在于该函数执行过程中。该函数主要执行两个操作,调用 SchM_Init()和调用 BswM_Init()。当 BswM 模块成功初始化后,后续的初始化任务由 BswM 模块完成。EcuM 的启动流程也就此结束。
- BswM启动:BswM启动之后,即STARTUP阶段完成,会在BswM中进行Rte_Start(),之后进入UP阶段。
No. | StartPreOS阶段具体实施动作 |
---|---|
1 | 调用 EcuM_AL_SetProgrammableInterrupts(),主要负责关闭芯片的可编程中断,为初始化其他模块和启动操作系统做准备。如果系统启动代码已将中断关闭,则可通过配置参数将该步骤省略,否则需要在该函数中关闭中断。 |
2 | 调用 EcuM_AL_DriverInitZero(),初始化Init List 0容器里面的驱动 |
3 | 调用EcuM_DeterminePbConfiguration(),根据相关系统设计读取 Post-build 配置参数数据指针 |
4 | 检查配置数据一致性,检查在上一步得到得Post-build配置数据的有效性 |
5 | 执行 EcuM_AL_DriverInitOne(),初始化Init List 1容器里面的驱动 |
6 | 获取上次复位原因,通过读取MCU的特殊复位原因寄存器,获取此次ECU复位的复位源,根据复位源来进行不同处理。例如复位原因是唤醒复位时,则需要执行唤醒源确认等步骤;如果复位原因是电源上电,则需要对 EcuM RAM 的一些关键变量进行初始化 |
7 | 设置默认 Shutdown target,系统关闭有三种情况,称为三种 ShutdownTarget,分别为 SLEEP、RESET 和 OFF。SLEEP 是指系统进入低功耗状态,RESET 是指复位重新运行,OFF 是完全断电 |
9 | 调用 EcuM_LoopDetection(),这是一个 Callout 函数 |
9 | 调用 StartOS(),启动操作系统 |
注: StartPreOS 和StartPostOS之间以 OS 的启动为分界线。
在上述上电流程中,提到了Init Block。现在很多MCU对初始化外设的时序都有严格要求,所以EcuM 设计了几个驱动初始化列表以满足不同需求:
- EcuMDriverInitListZero 由 EcuM_AL_DriverInitZero()实现,在获取 Post-build参数前调用。用于初始化一些公共基础模块,以及获取 PB 参数所需要的硬件模块的驱动。
- EcuMDriverInitListOne 由 EcuM_AL_DriverInitOne()实现,在获取 Post-build参数后调用。用于初始化一些具有多套配置,且不依赖于操作系统的模块。
- EcuMDriverRestartList 由 EcuM_AL_DriverRestart()实现,在唤醒后用于重启一些驱动模块。
注 : 在配置 EcuM 模块时指定每个列表中包含的驱动模块,其中InitListZero和InitListOne中的模块不能重复,而重启列表一般来讲是前两个列表的子集的组合,其中模块的相对顺序必须与前两个列表一致。
4.1.2 SHUTDOWN阶段
SHUTDOWN阶段主要分为4个步骤:
- BswM通知EcuM下电:在BswM准备好下电时会调用EcuM_GoDown()这个函数之后,EcuM开始下电流程。
- **OffPreOs ** : EcuM会在EcuM_MainFunction进行下电处理。
- 调用 EcuM_OnGoOffOne(),这是一个集成代码,主要负责处理一些关闭前的特殊操作。需要根据芯片特性填充功能。
- 调用 BswM_Deinit(),SchM_DeInit()。
- 检查唤醒事件,如果在关闭过程中发生PENGING或确认的唤醒事件,则系统需要响应唤醒。所以若当前 Shutdown Target 为 OFF,EcuM 会将其更改为 RESET,即在执行完后续的关闭动作后将处理器复位,从而再次启动。若没有发生唤醒事件,则正常执行关闭流程。
- 执行 ShutdownOS(),关闭操作系统。该函数会清理操作系统中的一些资源,最终调用ShutdownHook()。
- OffPostOs : 函数ShutdownHook()中会调用EcuM_Shutdown(),OffPostOS 流程则是在 EcuM_Shutdown()中实现。OffPostOS 流程分为两个步骤:
- 调用EcuM_OnGoOffTwo()。用户可以在其中调用不依赖于操作系统的模块的反初始化或清理工作。
- 根据前面设置的 Shutdown Target , 分别调用EcuM_AL_Reset() 或EcuM_AL_SwitchOff()。用户需要在这两个函数中分别调用驱动来实现系统复位或关闭电源等工作,自此ECU完成Shutdown流程。
注: OffPreOS 和OffPostOS之间以 OS 的关闭为分界线。STARTUP阶段和SHUTDOWN阶段的过程刚好相反。
4.1.3 SLEEP阶段
为了实现低功耗模式,在UP阶段,当应用软件不再执行操作,且在总线上满足休眠条件时(如CAN 网络的远程休眠条件满足),系统将进入SLEEP阶段。这个休眠由BswM发起,而EcuM执行休眠的具体操作。
在休眠前,需调用 EcuM_SelectShutdownTarget()将Target设置为 SLEEP,且需要设置具体的休眠模式。根据硬件芯片的不同,有些芯片可以处于不执行代码的状态,有些芯片会处于仍然执行代码的低频模式。需要根据这些硬件差异选择调用EcuM_GoHalt()或 EcuM_GoSleep()函数使 MCU 处于低功耗状态。进入休眠状态有三个步骤:GoSleep(预休眠),休眠和唤醒重启。
4.1.3.1 GoSleep(预休眠)
在预休眠步骤中,EcuM 首先会调用 BswM_EcuM_CurrentWakeup报告唤醒源状态。之后EcuM 调用 EcuM_EnableWakeupSources()使能唤醒源以备将来的休眠。该函数处于集成代码中,用户需要判断入参中每个bit,调用相应驱动的相应函数来将每个唤醒源使能。之后 EcuM 会调用 OS 的接口函数 GetResource()锁定调度功能,以备在将来唤醒中断处理完后仍然能返回当前进入休眠的任务中执行唤醒操作。
注: SLEEP阶段和SHUTDOWN阶段不同的是,OS并未关闭。
4.1.3.2 休眠
Sleep分为两种模式,分别是Halt模式和Poll模式。
-
Poll 模式休眠步骤
Poll 模式下 CPU 仍然执行代码,但以较低主频运行。这时 EcuM 将不停执行两个动作:调用 EcuM_SleepActivity()和调用 EcuM_CheckWakeup()。
其中EcuM_SleepActivity()为集成代码,用户可以在其中执行低功耗状态下运行的工作。
EcuM_CheckWakeup()也是集成代码,用户在其中根据入参遍历唤醒源,调用唤醒源驱动接口检查是否发生唤醒事件。如果发生唤醒事件,唤醒源应当调用EcuM_SetWakeupEvent()通知 EcuM。EcuM 会在检查完成后发现唤醒事件,触发唤醒重启。 -
Halt 模式休眠步骤
Halt 模式下 CPU 不再执行任何代码。在此模式下,会禁用所有二类中断,为了防止可能出现的 RAM 内容破坏,EcuM 会调用 EcuM_GenerateRamHash()计算 RAM 的校验值。在EcuM_GenerateRamHash()中用户需要自行对关键内容计算检验并保存。之后 EcuM 会调用 MCU 驱动进入休眠模式,CPU 会停止处于打盹模式,只有唤醒中断会将 CPU 重新置于运行状态。并且EcuM需要调用 EcuM_CheckRamHash()校验之后才能退出HALT,并且触发唤醒重启。
4.1.3.3 唤醒重启
在EcuM离开Poll或者Halt状态后,会执行WakeupRestart一系列步骤。首先,恢复 MCU 为正常模式,然后获取唤醒源,并将Validated和Pending的唤醒源禁止(让该唤醒源不能唤醒ECU),保留其他唤醒源以备稍后唤醒。最后调用 EcuM_AL_DriverRestart()执行重启驱动列表,解锁操作系统的调度器。
在驱动重新初始化过程中,驱动应当检测是否自己是触发本次唤醒的唤醒源,如果是,则最终会调用 EcuM_SetWakeupEvent()通知 EcuM。执行完唤醒重启步骤后,系统进入 UP 状态,有些唤醒源仍需要验证。
4.1.4 UP阶段
在UP阶段,EcuM主要在EcuM_MainFunction中干三件事:
- 唤醒源管理(唤醒源的识别和唤醒源的验证);
- Alarm clock的更新;
- 仲裁RUN 和POST_RUN的释放和请求;
注:RUN 和POST_RUN的状态仲裁和切换也可以在BswM内执行,而在BswM中也会有其他的状态。
4.1.4.1 唤醒源管理
直接上图把,具体还是要区分主动主动唤醒和被动唤醒源~~~
4.1.4.2 Alarm clock
EcuM 模块可以定义一个系统时间,基于 GPT 从上电复位开始以秒为单位运行。用户可以调用 EcuM_GetCurrentTime()获取系统自上电以来的运行时间。该时钟在休眠状态下仍然能正常运行,因为它依赖EcuM_MainFunction增加时间,因此用户还可以用以作定时唤醒源来唤醒系统。
Alarm clock能够配置指定User(e.g : bsw module 或 SW-C),User能够设置对应clock的时间。
4.1.4.3 Mode handing
Mode handing需要设置配置参数EcuMModehanding为True。
RUN和POST_RUN是用户(SW-C)对EcuM模块的两种模式请求。其中RUN 表示用户希望ECU处于正常运行状态,POST_RUN表示用户需要做休眠或关闭前的清理工作。用户需要通过 EcuM 模块接口来单独请求或释放 RUN 或 POST_RUN,而且请求和释放必须成对调用。因为EcuM内部没有这个mode迁移的状态机,所以EcuM只负责处理这些请求并转发给BswM,由BswM来管理状态机,并在mode迁移之后通过EcuM和Rte通知SW-Cs。
EcuM 模块整合所有 SW-C 的请求进行仲裁,向 BswM 模块发起模式请求。基本规则为:
- 当至少有一个 SW-C请求 RUN 时,EcuM 向 BswM 请求系统进入RUN状态(by BswM_EcuM_Request-edState());
- 当所有 SW-C 均释放 RUN,但仍有至少一个 SW-C 请求 POST_RUN 时,EcuM 向 BswM 请求进入POST_RUN 状态(by BswM_EcuM_RequestedState());
- 当所有SW-C 的 RUN 和 POST_RUN 均释放时(by BswM_EcuM_RequestedState());,EcuM 向 BswM 告知当前状态并等待BswM发起系统关闭(EcuM_GoDown())(根据shutdownTarget进入Sleep或者Shutdown)。
- 当BswMmode状态机迁移后,BswM会通过EcuM_SetMode())设定EcuM的状态,而EcuM也会通过BswM_EcuM_CurrentState())告知BswM当前状态。
注: 一般使用情况为:当用户希望正常运行时,向 EcuM 请求 RUN。当应用停止运行且希望进行一些后处理时,应该先请求 POST_RUN,再释放 RUN。EcuM 和 BswM 会根据系统整体状态在适当时机切换到 POST_RUN 状态,且通知应用可执行清理工作。当执行完清理工作后,应用调用 EcuM 接口释放 POST_RUN,则系统会进入Sleep或者Shutdown过程(由BswM决定何时进入)。
4.2 设置 Bootloader 启动目标
在 ECU 需要flash时,诊断仪与 Dcm 模块交互,设置 Bootloader 重编程有效标志后Reset,在这个过程中,EcuM提供了一个激活Bootloader的入口 。
在AUTOSAR中实现该流程 ,需要由应用层调用 EcuM 模块的EcuM_SelectBootTarget()函数来确定下次启动的引导目标是应用、OEM Bootloader 还是System Bootloader。具体流程为:
- 诊断仪发送请求切换编程会话;
- Dcm 模块先通过Rte向应用请求复位 ,应用调用 EcuM 模块EcuM_SelectBootTarget()函数设置复位启动目标;
- Dcm 向诊断仪发送 0x78 响应;
- Dcm 调用集成代码的接口,用户在集成代码中设置 Bootloader 的重编程有效标志;
- Dcm 通知 App 可以执行复位;
- 当 App 完成复位前的清理工作后,请求 EcuM 复位。在 Shutdown阶段中最后调用 EcuM_AL_Reset() 时 , 应当调用EcuM_GetBootTarget()来获取当前引导目标(也可以根据配置好的ResetMode进行判断)。并根据与 Bootloader 的交互协议设置相应标志,最后触发复位操作Mcu_PerformReset() 。
5 参考资料
- 【小猫爪】AUTOSAR学习笔记14-EcuM模块
- AUTOSAR_SWS_ECUStateManager.pdf