-
简介
ECU Manager(EcuM)的主要任务包括:
- 初始化(initializes)/反初始化(de-initializes)OS、SchM及BSW模块;
- 执行ECU的关闭(SHUTDOWN)和睡眠(SLEEP)动作;
- 处理唤醒(wakeup)事件并对唤醒源进行校验(wakeup validation)。
最初ECU的整个状态管理都由EcuM模块内部实现,称为EcuM Fixed。后来又引入了EcuM Flexible,这种方式下,除了启动(STARTUP)的早期阶段、关闭(SHUTDOWN)的晚期阶段以及睡眠(SLEEP)阶段外,其它时候的状态管理都由BswM实现。从AUTOSAR 4.4版本开始,EcuM Fixed已被移除,因此,本文讨论的重点是EcuM Flexible。
-
状态管理
EcuM整个管理周期可以划分为STARTUP、UP、SLEEP、SHUTDOWN及OFF五个阶段。
STARTUP阶段主要负责BSW模块的初始化,以OS启动为界又细分为两部分StartPreOs和StartPostOs。
UP阶段任务调度开启,此阶段的状态管理、动作执行主要靠BswM模块实现,例如,通过设置规则,可以建立RUN和POST RUN状态以及他们之间的切换逻辑。
SHUTDOWN阶段主要负责下电流程处理,下电完成后根据设置可以选择进入OFF还是RESET重启,该阶段以OS关闭为界细分为两部分OffPreOs和OffPostOs。
SLEEP阶段ECU(MCU)处于低功耗模式,MCU不断电,通常处于Halt或Poll模式,当有唤醒源发生时会返回正常工作状态。相对于让ECU(MCU)直接SHUTDOWN,进入SLEEP可以换取更快的唤醒重启时间,当然SLEEP下的功耗是要比SHUTDOWN下高的。
OFF阶段MCU处于断电状态,如果ECU支持唤醒,唤醒源一般通过LDO/SBC唤醒MCU。
-
STARTUP
STARTUP执行流程如下图所示:
StartPreOs Sequence由EcuM_Init()调用,而StartPostOs Sequence(EcuM_StartupTwo)则是由Os启动后的首个激活Task(StartupTask)进行调用。
-
StartPreOs
StartPreOs又称ECUM_STATE_STARTUP_ONE,StartPreOs Sequence是为启动OS做准备的,要尽可能保持短小精悍,该阶段通常不使用中断,如果一定要用中断的话只能使用一类(category I)中断。
上图展示了StartPreOs Sequence会做的一些事情,其中有一些步骤是可选的[Optional],简单来看一下:
1. EcuM_AL_SetProgrammableInterrupts设置在OS启动前必须要配置好的可编程中断,例如一些异常Trap;
2. EcuM_AL_DriverInitZero初始化不带post-build配置参数的BSW模块,有些模块的初始化函数需要传递配置参数,例如Can_Init(&CanPbConfig),像这种就不能放在该接口中;
3. EcuM_DeterminePbConfiguration返回所有BSW模块post-build配置参数的一个引用,通过此引用能获取各个模块的参数信息;
4. Check consistency of configuration data对上一步结果的一致性检查;
5. EcuM_AL_DriverInitOne初始化BSW模块,通常是OS启动前必须要初始化的一些模块;
6. Get reset reason获取MCU复位源,并根据映射关系设置唤醒源。唤醒源通常是从功能角度定义的,比如CAN唤醒,KL15唤醒等,而复位源则和MCU相关,比如所有MCU都支持的Power on reset,这两者之间通过EcuM可以配置映射关系;
7. Select default shutdown target设置SHUTDOWN目标,可以是SLEEP、OFF或RESET;
8. EcuM_LoopDetection该接口每次startup时都会被调用,例如可以用来记录启动次数;
9. Start OS。
-
StartPostOs
StartPostOs又称ECUM_STATE_STARTUP_TWO,如上面所言StartPreOs阶段只会初始化一部分模块,那么剩余模块的初始化工作则在StartPostOs阶段进行。
下面简单看下StartPostOs阶段做的事情:
1. Init BSW Scheduler初始化SchM;
2. Init BSW Mode Manager初始化BswM,初始化完成后就会由BswM接手来进行后续操作,包括读取NvM数据,初始化其它的BSW模块等,也正因为如此整个STARTUP阶段StartPostOs的时间消耗比较大。
3. Start Scheduler Timing启动任务调度。
通常来讲,我们会将BSW模块的Mainfunction和SWC的Runnable放在一起调度,使用同一张任务调度表,为了确保在任务运行时各模块及要用的NvM数据都已就绪,需要在开启任务调度前做完NvM的数据读取及所有模块的初始化工作,因此在执行步骤3前需要等待BswM将相关事情做完,为了BswM能够正常运作,我们需要手动调用它的Mainfunction。
当然,如果有其它方式可以保证在任务运行时模块及数据均已就绪的话,这里也不必死等,可以正常启动任务调度,然后EcuM进入UP阶段,相应的数据读取和模块初始化也下放到此阶段来进行。
-
UP
UP阶段各模块的Mainfunction/runnable正常运行,由BswM处理模式请求,控制状态切换,比如,停在RUN/POST_RUN、切换到SLEEP或者直接进入SHUTDOWN。此外,EcuM也会处理唤醒源的验证事宜。
-
唤醒源验证
当系统检测到唤醒事件时,由于不能知道这是一个真正的、有效的唤醒事件还是一个偶然的电磁信号波动,因此需对唤醒源进行二次验证:在一定的时限内查询唤醒源状态,若确有此事便认为是有效的唤醒请求,否则不予理会。
为了实现这种验证机制,唤醒源分为四种状态:
NONE —— 无唤醒事件或唤醒事件被清除;
PENDING —— 唤醒事件等待验证;
VALIDATED —— 唤醒事件验证通过;
EXPIRED —— 唤醒事件验证失败。
各状态之间的转换关系如下图:
如果唤醒源不需要验证,通过EcuM_SetWakeupEvent可以直接设置为已验证状态,而对于需要验证的唤醒源,则要经过PENDING阶段确认是否有效,当然,如果迟迟确认不了,时限到了也会验证失败。
EcuM模块除了标准的五个唤醒源(POWER、RESET、INTERNAL RESET、INTERNAL WDG和EXTERNAL WDG)外,其它用户配置的唤醒源均可以开启验证功能。
-
SLEEP
ECU能否进入SLEEP有两个条件,一是硬件上MCU自身支持低功耗休眠模式,二是STARTUP阶段shutdown target选择SLEEP,满足这两个条件,当在UP阶段请求休眠时便会进入SLEEP。
进入SLEEP阶段,首先要执行预休眠动作,包括设置模块(软件/硬件)的工作状态,设置唤醒支持等,然后控制MCU进入Poll或者Halt模式,在Poll模式下会周期查询有无唤醒事件,一旦检测到唤醒事件便会进入WakeUpRestart,而Halt模式下不会执行代码,只能通过中断方式触发状态切换。WakeUpRestart下会对唤醒进行验证,如果验证失败就继续sleep,如果验证通过,则回到UP阶段。
如果在WakeUpRestart下,不做唤醒源的验证工作,而是直接进行一些恢复操作,如将MCU恢复到正常模式、恢复任务调度等,然后切换回UP阶段,这样,假如唤醒源是个无效唤醒源的话,最终还是会从UP跳回SLEEP,只是这个过程时间相对来说要很长。
-
SHUTDOWN
SHUTDOWN阶段执行流程如下图所示:
ECU能否进入SHUTDOWN依赖于初始化阶段ShutdownTarget的选择,只要ShutdownTarget选择OFF或RESET,在ECU休眠时就会进入SHUTDOWN。在AUTOSAR 4.4中通过接口EcuM_GoDownHaltPoll启动SHUTDOWN流程,而在4.2中则是EcuM_GoDown。
-
OffPreOs
OffPreOs又叫ECUM_STATE_GO_OFF_ONE,如果在此阶段检测到唤醒源,EcuM并不会立刻返回UP,而是将shutdowntarget设置为RESET,等待整个SHUTDOWN阶段完成后复位ECU。
在执行ShutdownOS的最后OS会调用shutdown hook,通过该hook函数调用EcuM_Shutdown从而启动OffPostOs。
-
OffPostOs
OffPostOs也叫ECUM_STATE_GO_OFF_TWO,在该阶段主要会做一些收尾处理工作,比如NvM数据的WriteAll操作,然后便会根据shutdowntarget的选择进行OFF或RESET动作。