文章目录


前言

本文介绍CP AUTOSAR 架构下的EcuM组件,基于S32K312芯片、Vector提供的SIP包,使用DaVinci_Configurator、DaVinci_Developer工具进行配置的经验,不具体介绍芯片外设等功能。
EcuM组件实现ECU的状态管理。
EcuM组件位于System Services层里。
在这里插入图片描述


一、EcuM功能概述

(一)、功能概述

EcuM是一个基础软件模块,它负责管理ECU状态。具体而言,EcuM的功能如下:
初始化和反初始化Os、SchM、BswM以及一些BSW模块。
在收到请求时,将ECU配置为SLEEP和SHUTDOWN状态。
管理ECU上的所有唤醒事件。

EcuM提供唤醒验证协议,用于区分“真实”唤醒事件和“异常”唤醒事件。

此外,该模块还具备以下功能:
部分启动或快速启动,即ECU以有限的功能启动,之后根据应用程序的要求逐步完成启动过程。
交错启动,即ECU先进行最小化启动,然后尽快启动RTE以执行SW-Cs中的功能。随后继续启动更多的BSW和软件组件,从而实现BSW软件和应用程序功能的交错启动。
多种运行状态,即ECU不止有一种RUN状态。这在一定程度上细化了从SLEEP状态到RUN状态的一系列状态概念。如今,存在一系列连续的操作状态,从传统的RUN状态(完全运行)到最深的SLEEP状态(处理器停止工作)。
多核ECU:在ECU的所有内核上协调STARTUP、SHUTDOWN、SLEEP和WAKEUP操作。

灵活的EcuM利用以下模块提供的通用模式管理功能:
RTE和SchM现已合并为一个模块:该模块支持可自由配置的基础软件和应用程序模式及其模式切换功能。
BswM模块:该模块执行可配置的规则和操作列表,以评估切换ECU模式的条件,并执行切换模式所需的必要操作。

因此,借助灵活的EcuM,大多数ECU状态不再在EcuM模块内部实现。通常,在以下通用模式管理功能不可用的情况下,由EcuM模块接管控制权:
STARTUP的早期阶段
SHUTDOWN的后期阶段
调度器锁定相关功能的SLEEP阶段

在EcuM模块的UP阶段,由BswM负责后续操作。而EcuM模块会仲裁来自SW - Cs的RUN和POST_RUN请求,并将模式状态通知给BswM。

上文介绍了一种全新的、更灵活的ECU状态管理方法。然而,这种灵活性是有代价的,即需要承担相应的责任。不存在标准的ECU模式或状态,ECU的集成者必须确定所需的状态并对其进行配置。
当使用ECU模式处理时,标准状态RUN和 POST_RUN由运行请求协议进行仲裁,并传递给BswM。系统设计人员必须确保,在通过BswM操作设置ECU模式时,相应状态的前置条件得到满足。
需要注意的是,BSW和SW-Cs都无法依赖特定的ECU模式或状态,尽管早期版本的基础软件在很大程度上也并未依赖这些模式或状态。
EcuM R23-11仅规定了EcuM模块中保留的功能。要全面了解ECU状态管理,需要参考其他相关模块的规范,即RTE与 BSW Scheduler模块以及BswM的规范。
有关ECU状态的一些示例用例以及相关基础软件模块之间的交互,需要参考ModeManagementGuide。
EcuM模块对唤醒源状态的管理方式与以往相同。用于设置、清除和验证唤醒事件的APIs保持不变,但值得注意的是,这些接口如今是回调函数。
一直以来,唤醒源处理不仅要在唤醒期间进行,还应与所有其他ECU管理器活动并行地持续进行。如今,该功能通过模式请求与ECU管理的其他部分完全解耦。

(二)、模块依赖性

MCU Driver:
Mcu是由EcuM模块初始化的第一个基础软件模块。然而,当MCU_Init函数返回时,Mcu模块未必已完全初始化,可能还需要执行额外的Mcu模块特定步骤才能完成初始化。EcuM模块提供了两个回调函数,这些额外的代码可放置在其中。

Driver Dependencies and Initialization Order:
BSW驱动程序之间可能存在依赖关系。一个典型的例子是看门狗驱动程序,它需要通过SPI驱动程序来访问外部看门狗。这意味着,一方面,驱动程序可能会形成层级结构(这与EcuM模块无关);另一方面,被调用的模块必须在调用模块初始化之前完成初始化。
系统设计人员有责任在配置阶段,通过以下列表来明确初始化顺序:
EcuMDriverInitListZero
EcuMDriverInitListOne
EcuMDriverRestartList
EcuMDriverInitListBswM

Peripherals with Wakeup Capability:
唤醒源必须由驱动程序进行处理和封装。
这些驱动程序必须遵循EcuM文档中提出的协议和要求,以确保能够无缝集成到AUTOSAR BSW中。从根本上来说,该协议如下:
驱动程序必须调用EcuM_SetWakeupEvent(),以通知EcuM模块检测到了待处理的唤醒事件。无论ECU处于休眠阶段等待唤醒事件时,还是在驱动程序初始化阶段以及EcuM_MainFunction()运行的正常操作期间,驱动程序都必须调用EcuM_SetWakeupEvent()。
驱动程序必须提供一个明确的函数,用于使唤醒源进入休眠状态。该函数应将唤醒源置于节能且低功耗的运行模式,并重新启动唤醒通知机制。
如果唤醒源可能产生虚假事件,则以下任一组件:
驱动程序,或使用该驱动程序的软件栈,或其他合适的BSW模块,
必须提供唤醒事件的验证回调函数,或者调用EcuM模块的验证函数。如果无需验证,则此要求不适用于相应的唤醒源。

Os:
EcuM模块负责启动和关闭AUTOSAR OS。该模块定义了操作系统启动前和关闭后的控制流处理协议,

BSW Scheduler:
EcuM模块会初始化BSW调度器,同时该模块还包含EcuM_MainFunction()函数。此函数会按调度周期运行,用于评估唤醒请求并更新Alarm Clock。

BswM:
ECU状态通常以AUTOSAR模式的形式实现,BSW Mode Manager负责监控ECU中的状态变化,并根据情况对ECU状态机进行相应的调整。
BswM仅能在模式管理功能正常运行后即SchM初始化完成后,直至调度管理器被反初始化或停止前对ECU状态机进行管理。当BswM无法正常运行时,由EcuM接管ECU的控制权。
因此,EcuM在ECU启动后立即接管控制权,在初始化好SchM和BswM后,再将控制权移交至BswM。
BswM会将ECU的控制权交还给EcuM模块,以锁定操作系统并处理唤醒事件。
在关闭过程中,在操作系统即将停止前,BswM也会立即将控制权交还给EcuM。
在对唤醒源进行验证时,EcuM通过模式切换请求向BswM指示唤醒源的状态变化。

(三)、mode和state和phase

按EXP_ModeManagementGuide里的描述,EcuM里有mode、state、phase概念。
phase是EcuM的动作和时间在逻辑上或时间上的组合,例如STARTUP,SHUTDOWN,SLEEP等。
mode是运行在车辆上不同的状态机(不只是EcuM)的一组状态的集合,和一个实体,一个应用,或者整车都有关,如ECU进入sleep或reset模式等。
state是各自BSW组件内部定义的内容,对应用不可见;因此状态只会被BSW内部状态机所使用。EcuM定义的状态构建了phase,并处理模式。
EcuM代码里定义了如下状态:
在这里插入图片描述
按vector参考手册里描述的每个状态说明如下:
在这里插入图片描述

二、EcuM的各个Phases

EcuM的早期版本对ECU states和ECU modes进行了区分。

ECU模式指ECU运行活动的持续时间段,应用程序可感知这些模式并以此为参考,例如启动、关闭、进入休眠和唤醒。

EcuM状态通常是EcuM模块操作的连续序列,以等待外部条件满足为终止标志。例如,“Startup1” 包含操作系统启动前的所有BSW初始化操作,当操作系统将控制权交还给EcuM模块时,该状态终止。

对于当前的灵活EcuM,存在状态(States)、模式(Modes)和阶段(Phases)。

此处,ECU状态机以通用模式的形式实现,由BswM模块控制。这引发了术语上的混淆:旧版本中的ECU States如今成为可通过RTE模式端口接口感知的Modes,而旧版本中的ECU Modes如今则称为Phases。

由于VFB所定义的、RTE中使用的模式仅在UP阶段可用(此时EcuM处于被动状态),因此有必要将术语从Modes改为Phases。

下图概述了灵活EcuM模块的各个阶段。
在这里插入图片描述

STARTUP阶段持续至模式管理功能运行时结束。从根本上来说,STARTUP阶段包含启动模式管理所需的最少操作:初始化底层驱动程序、启动Os、初始化 BSW Scheduler和BswM模块。同样,SHUTDOWN阶段是STARTUP阶段的逆过程,在此阶段中,模式管理功能被反初始化。

未突出显示的所有状态均属于UP阶段。在该阶段,ECU会按照集成者定义的状态机,在不同状态和模式之间切换。

若使用ECU模式处理功能,UP阶段包含默认模式。这些模式之间的转换通过EcuM模块与BswM模块的协作完成。

需要注意的是,UP阶段包含一些以往的sleep状态。从为防止其他任务在休眠时运行而锁定操作系统调度器开始,到退出使ECU进入休眠状态的MCU模式为止,模式管理功能在此期间不运行。EcuM模块在此期间提供唤醒处理支持。

(一)、STARTUP Phase

STARTUP phase的目的是初始化基础软件模块,直至Generic Mode Management功能可正常运行。

(二)、UP Phase

UP phase本质上始于BSW Scheduler启动且BswM_Init()被调用之时。此时,内存管理尚未初始化,没有通信协议栈,不支持软件组件,且软件组件也未启动。
处理以某种模式(启动后配置的下一个模式)开始,带有相应的runnables,即BSW主函数,并继续以模式变化的任意组合形式进行,这会导致 BswM执行操作以及触发和禁用相应的runnables。

不过,从EcuM模块的角度来看,此时ECU处于up状态。随后,BswM模块启动模式仲裁,所有后续的BSW初始化、RTE启动以及(隐式的)软件组件启动,都将作为BswM动作列表中的代码执行,或由模式相关的调度驱动,实际上处于集成者的控制之下。

因此,初始化NvM并调用NvM_ReadAll()也属于集成代码的范畴。这意味着,集成者需负责在NvM_ReadAll()完成时触发Com、DEM和FIM的初始化。当NvM_ReadAll()执行完毕后,Nvm会通知BswM。

需要注意的是,RTE可在NvM和Com初始化后启动。此外,还需注意,在初始化Com之前,通信栈无需完全初始化。

这些更改会将BSW模块初始化,并以任意顺序启动SW-C,直至ECU达到最大容量,此后这些更改还将继续确定ECU的各项能力。

最终,模式切换会停止软件组件并反初始化BSW,当ECU进入可断电状态时,UP阶段结束。

因此,就EcuM模块而言,BSW和SW-Cs会持续运行,直至它们准备好让ECU进入shut down或进入sleep。

(三)、SHUTDOWN Phase

SHUTDOWN阶段负责对基本软件模块进行有控制的关机操作,并最终实现选定的关机目标(OFF或RESET)。

(四)、SLEEP Phase

SLEEP phase中,ECU会节省能源。通常情况下,此阶段不会执行任何代码,但仍会供电;并且如果配置得当,ECU在此状态下可被唤醒。EcuM模块提供一组可配置的(硬件)休眠模式,这些模式通常是在功耗和ECU重启时间之间进行权衡的结果。
EcuM模块会响应预期或非预期的唤醒事件,将ECU从休眠中唤醒。由于非预期的唤醒事件应被忽略,因此EcuM模块提供了一套唤醒事件验证协议。该协议规定了处理唤醒源的驱动程序与EcuM之间的协作流程。

(五)、OFF Phase

当ECU断电时,它会进入OFF状态。在此状态下,ECU可能仍可被唤醒,但仅支持具备集成电源控制功能的唤醒源。无论如何,ECU必须能够被启动(例如通过复位事件)。

三、EcuM的结构描述

在这里插入图片描述
上图展示了EcuM与其他BSW模块接口之间的关系。在大多数情况下,EcuM模块仅负责初始化工作。
然而,有一些模块与EcuM模块存在功能上的关联。比如:
一些基本的软件驱动模块会在启动时由EcuM模块进行初始化、关闭以及重新初始化操作。
Os由EcuM进行初始化和关闭操作。
在Os初始化完成后,EcuM会先执行一些额外的初始化步骤,然后再将控制权传递给BswM。在Os关闭之前,BswM会立即将执行控制权交还给EcuM。
SW-Components包含了AUTOSAR ECU的应用程序代码。一个SW-C通过AUTOSAR端口与EcuM模块进行交互。

四、STARTUP Phase

在这里插入图片描述
上图展示了ECU的启动行为。当EcuM_Init()被调用时,EcuM将掌控ECU的启动流程。通过调用StartOS,EcuM会暂时放弃控制权。要重新获得控制权,集成者必须实现一个会自动启动的操作系统任务,并首要操作调用EcuM_StartupTwo()。

(一)、EcuM_Init()之前的动作

EcuM模块假定,在调用EcuM_Init()之前,已经对MCU进行了最小化初始化,以便建立堆栈并能够执行代码,同时还会完成变量的C语言初始化。

(二)、StartPreOS序列中的动作

在这里插入图片描述
StartPreOS序列旨在为ECU初始化操作系统做好准备,且应尽可能精简。驱动程序应尽可能在UP阶段进行初始化,相关标注也需保持简洁。此序列期间不应使用中断;若必须使用,仅允许类别 I 中断。
EcuM并未严格规定驱动程序和硬件抽象模块的初始化方式,而是通过两个标注来定义初始化块0和I,如EcuM_AL_DriverInitZero()和EcuM_AL_DriverInitOne()。
StartPreOS序列必须初始化启动AUTOSAR操作系统所需的所有基础软件模块,最终完成操作系统的启动。

下面是StartPreOS中的执行动作,在EcuM_Init()中执行:

1、调用Callout函数EcuM_AL_SetProgrammableInterrupts(),对于具有可编程中断优先级的ECU而言,这些优先级必须在操作系统启动之前进行设置。用户可以在这里面对中断进行配置和操作,比如配置各个中断的优先级或者将中断关闭,因为初始化过程中不允许开中断,如果系统已经将中断关闭则不需要添加。

2、调用Callout函数EcuM_AL_DriverInitZero(),初始化第一次,此调用仅可初始化那些不使用构建后配置参数的BSW模块。该调用不仅可以包含驱动程序初始化代码,还可以包含任何类型的预操作系统或底层初始化代码。用户可以在这里面进行预初始化操作,比如各个BSW模块的变量和内存初始化,Det模块也在这里初始化,保证在后续的过程中,如果发生初始化的错误,开发集成人员可以确认。

3、调用Callout函数EcuM_DeterminePbConfiguration(),此调用将返回一个指向完全初始化的EcuM_ConfigType结构体的指针,该结构体包含
了EcuM模块以及所有其他BSW模块的构建后配置数据。

4、检查配置数据的一致性,如果检查失败,将调用EcuM_ErrorHook()。

5、调用Callout函数EcuM_AL_DriverInitOne(),初始化第二次,不仅可以包含驱动程序初始化,还可以包含任何类型的操作系统启动前的底层初始化代码并且不依赖于操作系统的模块。用户可以在这里面进行初始化各个底层驱动代码,比如Mcu、Port、Gpt、Wdg、Adc等,都是初始化MCU用的模块,MCU软件的初始化一般第一个要先初始化Wdg,然后是Port,再是Mcu,接着是一系列的其他外设初始化。

6、获取复位源
调用Mcu_GetResetReason()获取复位原因,同时调用EcuM_SetWakeupEvent()设置唤醒事件。

7、设置默认的Shutdown目标。

8、调用Callout函数EcuM_LoopDetection(),如果EcuMResetLoopDetection配置为TRUE,每次启动时都会调用该Callout。

9、启动OS。

(三)、StartPostOS序列中的动作

在这里插入图片描述
Os启动后,会执行初始化Task,然后调用EcuM_StartupTwo(),StartPostOS序列就在该函数里执行,执行完后该Task终止。

下面是StartPostOS中的执行动作,在EcuM_StartupTwo()中执行:

1、调用SchM_Start(),启动BSW调度表。

2、调用BswM_Init()初始化BswM模块。

3、调用SchM_Init()初始化调度表,即Rte里激活Bsw的Task,该序列结束之后EcuM控制权转交给BswM。

4、调用SchM_StartTiming()开始给调度表设置计时器,即各个任务的报警器,这样各个任务才有定时事件。

该序列结束时调用Rte_Start(),初始化Rte层的Task。

(四)、配置一致性检查

在AUTOSAR架构中,ECU的稳定运行依赖于各阶段配置参数的一致性。EcuM作为核心模块,承担着在运行时高效校验配置一致性的关键职责,其核心通过哈希值比对实现,既保障了检查的准确性,又避免了启动延迟。

ECU的配置参数在不同阶段被设置和写入:预编译参数(生成源码时设置,编译为目标代码)、链接时参数(编译后链接阶段设置,形成镜像)、post-build参数(后续单独配置、编译并写入ECU)。这些参数必须匹配才能确保ECU稳定,而post-build参数的一致性检查存在特殊挑战:
预编译和链接时参数在运行时不可直接访问,无法通过直接读取比对,
分散在各BSW模块中检查会导致冗余,拖慢启动流程。
因此,EcuM需在初始化第一个BSW模块前,集中完成所有post-build可配置BSW模块的一致性检查,避免分散检查的弊端。
直接比对成百上千个参数会严重延迟ECU启动,因此引入哈希值作为参数快照,通过配置时计算、运行时比对实现高效检查。

(五)、驱动初始化

在AUTOSAR架构中,驱动的初始化时机和流程与其实现方式及目标硬件设计密切相关。EcuM是驱动初始化的核心协调者,负责在特定阶段触发初始化或重新初始化操作,同时需遵循严格的配置规范以确保一致性。

驱动的初始化或重新初始化可在以下阶段由不同模块触发:
STARTUP phase:由EcuM在Init Block 0或Init Block 1中初始化;
WakeupRestart Sequence:由EcuM在EcuM_AL_DriverRestart()回调中重新初始化;
UP phase:由BswM初始化或重新初始化。

下图展示了推荐的初始化顺序:
在这里插入图片描述

(六)、BSW初始化

其余的BSW模块由BswM进行初始化,其使用的是EcuM的已配置功能,该功能是从已配置的初始化列表EcuMDriverInitListBswM中创建的。

五、SHUTDOWN Phase

在这里插入图片描述
当调用EcuM_GoDownHaltPoll()且关机目标为RESET或OFF时,将启动SHUTDOWN阶段。
当在SHUTDOWN阶段发生唤醒事件时,EcuM将立即完成关闭操作,并随后立即重新启动。
通常BswM会周期性的检测配置的Rule,如果所有的唤醒事件处于NONE和EXPIRED状态,BswM将调用EcuM_GoDownHaltPoll()接口。

当ECU下电时,需要检查每一个唤醒源,当所有唤醒源没请求通信时,ECU可执行下电流程,常见的唤醒源有ACC是否上电、是否有诊断请求、是否有NM报文、是否有SWC请求通信等。

(一)、OffPreOS序列中的动作

在这里插入图片描述
进入SHUTDOWN阶段时执行该序列,下面是OffPreOS中的执行动作:

1、调用Callout函数EcuM_OnGoOffOne(),用户可以在这里面处理关闭前的自定义操作。

2、调用BswM_Deinit(),反初始化BswM模块。

3、调用SchM_DeInit(),反初始化调度器,即在Rte里停止各个任务的报警定时器。

4、检查唤醒事件。根据EcuMlgnoreWakeupEvValOffPreOs的配置情况,会考虑所有待处理的唤醒事件,或者仅考虑在SHUTDOWN过程中验证过的唤醒事件。目的是检测在SHUTDOWN过程中发生的唤醒事件。
如果有唤醒事件,则系统需要唤醒,将Shutdown Target设为RESET,即在执行完后续的SHUTDOWN动作后将处理器复位,从而再次启动。若没有发生唤醒事件,则正常执行关闭流程。
EcuMIgnoreWakeupEvValOffPreOS为TRUE时,仅考虑无需验证的唤醒事件,忽略所有需要验证的唤醒事件。
EcuMIgnoreWakeupEvValOffPreOS为FALSE时,同时考虑无需验证的唤醒事件与处于待验证状态的唤醒事件(即已触发但尚未完成验证的事件)。

5、调用EcuM_ShutdownOS(),里面再调用ShutdownOS(),关闭操作系统。

(二)、OffPostOS序列中的动作

在这里插入图片描述
在调用ShutdownOS()后OS被关闭,然后OS会调用钩子函数ShutdownHook(),ShutdownHook()再调用EcuM_Shutdown()执行该序列,OffPostOS序列是在OS关闭后执行的最终步骤,以达到Shutdown Target,Shutdown Target可以是ECUM_SHUTDOWN_TARGET_RESET或ECUM_SHUTDOWN_TARGET_OFF。下面是OffPostOS中的执行动作:

1、调用EcuM_OnGoOffTwo()。用户可以在其中调用不依赖于操作系统的模块的反初始化或清理工作。

2、根据前面设置的Shutdown Target,RESET或OFF分别调用EcuM_AL_Reset()或EcuM_AL_SwitchOff()。用户需要在这两个函数中分别实现系统复位或ECU断电等工作,自此ECU完成SHUTDOWN流程。

六、SLEEP Phase

在这里插入图片描述
当BswM或SWC调用EcuM_GoDownHaltPoll()并且Shutdown Target为Sleep时进入SLEEP阶段。

(一)、GoSleep序列中的动作

在这里插入图片描述
在GoSleep序列中,EcuM会为即将进入的SLEEP阶段配置硬件,并为下一次唤醒事件做好准备。
为设置下一个睡眠模式的唤醒源,EcuM应针对目标睡眠模式下在EcuMWakeupSourceMask中配置的每个唤醒源,执行 EcuM_EnableWakeupSources()。
与SHUTDOWN阶段不同,EcuM在进入SLEEP阶段时不应关闭OS。睡眠式,即EcuM SLEEP阶段与Mcu模式的组合,对OS而言应是透明的。
在对多核ECU进行操作时,EcuM应为每个核心预留一个专用资源(RES_
AUTOSAR_ECUM),该资源在GoSleep期间进行分配。

(二)、Halt序列中的动作

在这里插入图片描述
EcuM将在睡眠模式下执行Halt序列,以使MCU停止运行。在这些睡眠模
式下,EcuM模块不会执行任何代码。

EcuM模块应在暂停微控制器之前调用Callout函数EcuM_GenerateRamHash(),该函数由用户自己设计RAM完整性检查,在处理器从暂停状态恢复后调用Callout函数EcuM_CheckRamHash()。在采用多核且存在从EcuM的情况下,此检查应仅在主EcuM上执行。主EcuM根据其可访问的所有数据生成哈希值,从EcuM的私有数据不在此范围内。
当ECU长时间处于睡眠模式时,RAM存储器可能会损坏。因此,应检查RAM存储器的完整性,以防止出现意外行为。系统设计人员可以选择适当的校验和算法来执行此检查。

(三)、Poll序列中的动作

在这里插入图片描述
在睡眠模式下设置的Poll序列可用于检测唤醒源。
在Poll序列中,EcuM应在阻塞循环中调用EcuM_SleepActivity()和
EcuM_CheckWakeupHook()这两个Callout(如果 EcuMWakeupSourcePolling设置为TRUE)直至报告一个待处理/已验证的唤醒事件。

(四)、离开Halt或Poll

当ECU处于Halt或Poll状态时,若发生唤醒事件(例如:唤醒线电平翻转、CAN 总线上的通信等),EcuM应重新获得控制权,并通过执行WakeupRestart序列退出SLEEP阶段。
可能会调用中断ISR来处理该唤醒事件,但其依赖于硬件和驱动程序的实现。

(五)、WakeupRestart序列中的动作

在这里插入图片描述
当EcuM被其他模块调用EcuM_SetWakeupEvent()后即ECU有事件唤醒,被唤醒后执行WakeupRestart序列,执行以下动作:

1、调用Mcu_SetMode()将MCU恢复为NORMAL模式。

2、调用EcuM_GetPendingWakeupEvents()获取已被设置为待处理状态但尚未被确认的事件。

3、调用Callout函数EcuM_DisableWakeupSources(),里面用户可以禁用当前等待状态的唤醒源,但保留其他唤醒源处于激活状态,以便日后仍能进行唤醒操作。

4、调用Callout函数EcuM_AL_DriverRestart(),用户可以添加初始化驱动程序的代码,如果在睡眠前反初始化了驱动程序,那么在唤醒后需要重新初始化。

5、解锁调度表,其他Task就都可以运行了。

七、UP Phase

在UP阶段,EcuM_MainFunction()会周期运行,它具有三项主要功能:
检查唤醒源是否已触发唤醒,必要时启动唤醒验证;
更新Alarm Clock定时器;
对RUN和POST_RUN的请求与释放进行仲裁。

(一)、Alarm Clock处理

如果Alarm Clock功能存在,则EcuM_MainFunction()应该更新Alarm Clock定时器。

(二)、Wakeup Source状态处理

在这里插入图片描述
唤醒源不仅在唤醒过程中被处理,而且会持续不断地进行处理,与所有其他EcuM活动并行进行。此功能在EcuM_MainFunction()中运行,完全独立于其余的EcuM功能,通过模式请求来实现。

Wakeup Source状态有如下:
NONE:未检测到任何唤醒事件,也未清除任何唤醒事件。
PENDING:检测到了一个唤醒事件,但该事件尚未得到验证。
VALIDATED:检测到一个唤醒事件,并且该事件已成功验证。
EXPIRED:检测到了唤醒事件,但验证失败。

当EcuM的某项操作导致唤醒源的状态发生变化时,EcuM应向BswM发出模式请求,以将该唤醒源的模式更改为新的唤醒源状态。

当EcuM处于UP阶段时,唤醒事件通常不会触发状态变更。不过,它们会触发Halt Sub Phase和Poll Sub Phase的结束。随后,EcuM会自动执行WakeupRestart序列,之后返回至UP阶段。

由集成者负责在BswM中配置规则,使ECU能对唤醒事件做出正确反应,因为这种反应完全取决于ECU当前的状态。

若唤醒源有效,BswM会使ECU返回至RUN状态。若所有唤醒事件均已恢复为NONE或EXPIRED状态,BswM会再次为BSW进入SLEEP或OFF状态做准备,并调用EcuM_GoDownHaltPoll()函数。

总而言之:每个未处理的事件都会被独立验证(若已配置),且EcuM会将验证结果作为模式请求发布至BswM,而BswM进而可触发EcuM中的状态变更。

(三)、Wakeup状态的内部表示

EcuM提供以下接口用于确定唤醒源的状态:
EcuM_GetPendingWakeupEvents
EcuM_GetValidatedWakeupEvents
EcuM_GetExpiredWakeupEvents

并通过以下接口操作唤醒源的状态:
EcuM_ClearWakeupEvent
EcuM_SetWakeupEvent
EcuM_ValidateWakeupEvent
EcuM_CheckWakeup
EcuM_DisableWakeupSources
EcuM_EnableWakeupSources
EcuM_StartWakeupSources
EcuM_StopWakeupSources

EcuM最多可管理32个唤醒源。在上述EcuM接口中,唤醒源的状态通常通过EcuM_WakeupSourceType位掩码来表示,其中各个唤醒源对应固定的位位置。存在5个预定义的位位置,其余位位置可通过配置进行分配。

(四)、WakeupValidation序列中的动作

在这里插入图片描述
由于唤醒事件可能是非故意产生的(例如CAN 总线上的EVM尖峰信号),因此在ECU恢复全面运行之前,有必要对唤醒进行验证。

所有唤醒源的验证机制都是相同的。当唤醒事件发生时,ECU会从睡眠SLEEP状态被唤醒,并在MCU驱动程序的MCU_SetMode()服务中恢复运行。当WakeupRestart序列完成后,EcuM会得到一份待验证的唤醒事件列表。然后,EcuM会释放BSW调度器和BSW的MainFunctions,在这种情况下,最值得注意的是,EcuM_MainFunction()可以恢复工作。

需要注意的是:由于在StartPostOS和WakeupRestart序列结束时,SchM将处于运行状态,因此可能会出现EcuM_MainFunction()对某个其协议栈尚未初始化的源启动验证的情况。集成者应配置适当的模式来指示协议栈不可用,并相应地禁用EcuM_MainFunction()。

EcuM仅应在那些通过配置要求进行唤醒验证的唤醒源上执行唤醒验证。如果未配置验证协议,那么调用EcuM_SetWakeupEvent()时,也应意味着调用EcuM_ValidateWakeupEvent()。

EcuM应为每个需要验证的待验证唤醒事件启动一个验证超时器。
一种足够可行的实现方式是仅提供一个计时器,当有新的唤醒事件上报时,将该计时器延长至最大的超时时间。

当某个待验证唤醒事件的验证超时时间到期时,EcuM_MainFunction()会设置(进行或运算)内部已超时唤醒事件变量中的相应位。
当一个待唤醒事件的验证超时时间到期时,EcuM_MainFunction()应调用
BswM_EcuM_CurrentWakeup()函数,并将带有对应于唤醒事件的位设置为1的EcuM_WakeupSourceType位掩码参数以及将状态值参数设置为ECUM_WKSTATUS_EXPIRED的值传递给该函数。
BswM将通过配置来监控唤醒验证,其依据是随着唤醒源被验证或计时器到期,从EcuM传来的模式切换请求。如果最后一个验证超时器在未经过验证的情况下到期,那么BswM应认为唤醒验证失败。如果至少有一个待验证事件通过了验证,那么整个验证应视为通过。
待验证事件通过调用EcuM_ValidateWakeupEvent()来进行验证。该调用必须放在驱动程序中,或放在驱动程序之上的应用程序中。具体放在何处,取决于硬件和软件设计。

1、通信通道的唤醒

如果在通信通道上发生唤醒事件,相应的总线收发器驱动程序必须通过调用EcuM_SetWakeupEvent()来通知EcuM。

2、Wakeup Sources和EcuM的交互

在EcuM_SetWakeupEvent()被调用后说明有唤醒事件,EcuM应以相同方式处理所有唤醒源。当唤醒事件发生时,相应的驱动程序应将该唤醒情况通知EcuM模块。这种通知最可能的方式有:
(1)、退出Halt或Poll序列之后。在此场景中,EcuM模块调用EcuM_AL_DriverRestart()来重新初始化相关驱动程序,而这些驱动程序进而有机会扫描其硬件查找是否有待验证的唤醒中断。
(2)、如果唤醒源实际上处于睡眠模式,驱动程序必须自主扫描唤醒事件,可通过轮询或等待中断的方式。

如果某个唤醒事件需要验证,那么EcuM模块应启动验证协议。

如果某个唤醒面事件不需要验证,EcuM模块应发出模式切换请求,将该事件的模式设置为ECUM_WKSTATUS_VALIDATED。

如果唤醒事件得到验证(无论是立即验证还是通过唤醒验证协议进行验证),EcuM模块将通过EcuM_GetValidatedWakeupEvents()函数告知其是当前ECU的唤醒源。

3、Wakeup验证超时

EcuM模块应提供单个唤醒验证超时计时器,或者为每个唤醒源各提供一个计时器。
当调用EcuM_SetWakeupEvent()时,EcuM模块应启动唤醒验证超时计时器。
EcuM_ValidateWakeupEvent()应停止唤醒验证超时计时器。
如果随后针对同一唤醒源调用EcuM_SetWakeupEvent(),EcuM模块不得重启唤醒验证超时计时器。
如果仅使用一个计时器,可以采用以下方法:
如果在同一唤醒周期内,针对某个尚未触发的唤醒源调用EcuM_SetWakeupEvent(),则EcuM模块应延长该唤醒源的验证超时时间。

4、带有唤醒源的驱动程序要求

当检测到唤醒事件时,驱动程序必须调用一次EcuM_SetWakeupEvent(),并提供一个EcuM_WakeupSourceType参数,该参数需根据配置来标识唤醒源。
EcuM模块应能检测到在驱动程序初始化之前发生的唤醒,无论是来自Halt/Poll状态还是OFF状态的唤醒。
驱动程序必须提供一个API,用于配置SLEEP状态下的唤醒源、启用或禁用唤醒源,以及使相关外设进入睡眠状态。此要求仅在硬件具备这些功能时适用。

(五)、Wakeup Validation的需求

如果唤醒源需要验证,可由BSW软件中任何一个(但只能是一个)合适的模块来执行此操作。该模块可以是驱动程序、接口、处理器或管理器。

验证通过调用EcuM_ValidateWakeupEvent()完成。

如果EcuM无法确定由Mcu驱动程序返回的复位原因,那么EcuM将
设置一个唤醒事件,以默认的唤醒源ECUM_WKSOURCE_RESET作为唤醒源。

(六)、Wakeup Sources和Reset Reason

EcuM的API仅提供一种类型EcuM_WakeupSourceType,该类型可描述ECU启动或唤醒的所有原因。

EcuM不得对以下唤醒源执行验证:
ECUM_WKSOURCE_POWER
ECUM_WKSOURCE_RESET
ECUM_WKSOURCE_INTERNAL_RESET
ECUM_WKSOURCE_INTERNAL_WDG
ECUM_WKSOURCE_EXTERNAL_WDG

(七)、电源芯片控制的Wakeup Sources

SLEEP状态可通过控制MCU电源的系统芯片来实现。典型示例包括集成电源的CAN收发器,这类收发器可根据应用请求关闭电源,并在检测到CAN活动时开启电源。

其结果是,在这类硬件上,SLEEP状态对EcuM而言就像OFF状态一样。这种区别更多是理论层面的,而非实际应用层面的。

实际影响在于,CAN总线上的被动唤醒对ECU而言就像一次上电复位。因此,ECU会在唤醒事件后继续执行STARTUP序列。尽管如此,唤醒验证仍是必需的,系统设计人员必须考虑以下事项:
CAN收发器在某个驱动程序初始化模块中进行初始化(默认情况下由BswM控制)。这属于配置代码或生成代码,即处于系统设计人员控制范围内的代码。
CAN收发器驱动程序的API提供了相关函数,用于确定是否是CAN收发器因被动唤醒而启动了ECU。系统设计人员有责任检查CAN收发器的唤醒原因,并通过调用EcuM_SetWakeupEvent()和EcuM_ClearWakeupEvent(),将该信息传递给EcuM。

这些原则适用于所有具有集成电源控制的唤醒源。CAN收发器仅作为示例。

八、Shutdown Targets

Shutdown Targets是对ECU所有不执行代码状态的描述性术语。它们被称为关闭目标,是因为当退出UP阶段时,状态机会切换到这些目标状态。以下状态属于关闭目标:
Off、Sleep、Reset。

需要注意的是,确定关闭目标的时间或可确定关闭目标的时间不一定是关闭过程的开始时间。由于BswM现在控制着大多数ECU资源,它会决定设置关闭目标的时间,并直接或间接地进行设置。因此,BswM必须确保,例如,在调用EcuM_GoDownHaltPoll()之前,将关闭目标从默认值更改为ECUM_STATE_SLEEP。
在EcuM模块的早期版本中,睡眠目标被特殊处理,因为ECU中实现的睡眠模式取决于ECU的能力。这些睡眠模式依赖于硬件,通常在时钟设置或硬件提供的其他低功耗功能方面有所不同。这些不同的功能可通过MCU驱动程序以所谓的MCU模式进行访问。

复位的执行也有多种方式,由不同的模块控制或触发:
Mcu_PerformReset()、WdgM_PerformReset()、通过IO引脚触发MCU的复位。

(一)、Sleep

在SLEEP阶段,不得遗漏任何唤醒事件。若在进入GoSleep序列中已发生唤醒事件,则不得进入Halt或Poll序列。
EcuM可以定义一组可配置的睡眠模式,其中每个模式本身都可作为关机目标。
EcuM模块应能够将MCU的睡眠模式与ECU的睡眠模式进行映射,从而能够将它们视为关机目标。
Sleep关机目标会将所有MCU的Core置于睡眠模式。

(二)、Reset

EcuM应定义一组可配置的复位模式,其中每种模式本身都是一个关机目标。该集合至少应包含以下目标对应的模式:
Mcu_PerformReset
WdgM_PerformReset
通过IO引脚触发MCU的复位。

复位类型如下:
在这里插入图片描述

EcuM模块应定义一组可配置的复位原因。该集合至少应包含以下目标对应的原因:
ECU状态机进入关机状态
WdgM检测到故障
Dcm请求关闭

原因类型如下:
在这里插入图片描述
在这里插入图片描述

九、Alarm Clock

EcuM提供了一项可选的持续时钟服务,该服务即使在睡眠期间也保持活跃状态。因此,它能保证ECU在未来的特定时间被唤醒(假设硬件无故障),并为长期活动(即按小时、天甚至年衡量的活动)提供时钟服务。

通常,这项服务通过ECU中可引发唤醒的定时器来实现。不过,在某些情况下,外部设备也可使用常规中断线路定期唤醒ECU。无论采用何种机制,该服务都会私下占用一个唤醒源。

EcuM模块维护一个主alarm时钟,其值决定ECU被唤醒的时间。此外,EcuM还管理一个内部时钟,即EcuM时钟,用于与主闹钟进行比较。

需要注意的是,闹钟唤醒机制仅与SLEEP阶段相关。然而,SW-Cs和BSW模块可在UP阶段(且仅在UP阶段)设置和获取闹钟值,这些值在SLEEP阶段会被遵循。

与其他可利用EcuM模块通用功能实现的定时/唤醒机制相比,alarm时钟服务在定时器到期前不会启动WakeupRestart序列。当ECU模块检测到其定时器引发了唤醒事件时,会递增其定时器,除非时钟时间已超过alarm时间,否则会立即返回SLEEP状态。

当alarm时钟服务存在时,EcuM模块应维护一个EcuM时钟,其时间应为从电池连接开始计算的秒数。

EcuM时钟应在UP阶段和SLEEP阶段跟踪时间。

在硬件允许的情况下,EcuM时钟时间不应因ECU复位而重置。

应恰好有一个唤醒源分配给EcuM时钟。

(一)、Alarm Clocks和Users

SW-Cs和BSW模块各自都能设置一个alarm clock。每个用户alarm clock都与一个EcuMUser相关联,该EcuMUser用于标识相应的SW-C或BSW模块。

每个EcuM用户最多只能设置一个用户alarm。

任何EcuM用户均不得更改其他用户alarm的设定时间。

EcuM模块应始终将主alarm时钟值设置为最早用户alarm时钟值的数值。
这意味着,当EcuM用户对其alarm发出取消指令,并且该用户alarm确定了当前的主alarm值时,EcuM模块应将主alarm值设置为下一个最早的用户alarm值。

只有获得授权的EcuM用户才能设置EcuM时钟时间。
通常情况下,EcuM用户无法设置EcuM时钟时间。EcuM时钟时间可以设置为任意时间,以便能够测试那些需要数天才会过期的alarm。

(二)、EcuM Clock Time

1、EcuM Clock Time
如果底层硬件机制是基于时钟滴答的,EcuM应相应地校正时间。

2、在UP阶段的EcuM Clock Time
在UP阶段, EcuM_MainFunction()会递增EcuM时钟。它使用标准的OS机制(alarms / counters)来获取时间。注意,counters与以秒为单位的EcuM时间在颗粒度上存在差异。

3、在Sleep阶段的EcuM Clock Time
根据所选的睡眠模式(EcuMSleepModeSuspend 参数),在睡眠期间递增EcuM时钟有两种方案:
在Halt序列中,GPT驱动程序必须被设置为GPT_MODE_SLEEP模式,仅配置用于时间基准所需的那些定时器通道。此外,还需要使用Gpt_EnableWakeup()使GPT启用基于定时器的唤醒通道。最好将Gpt_StartTimer()设置为1秒,但如果这个值无法达到,EcuM将需要更频繁地唤醒以累积多个定时器唤醒事件,直到累计达到1秒,从而增加时钟值。
在Poll序列中,假设时间概念仍然具备,EcuM时钟可在EcuM_SleepActivity()函数中通过EcuM_SetClock()函数定期更新。时钟必须仅在累积满1秒时才递增。
在这两种情况下,睡眠期间时钟递增后,EcuM模块必须评估主alarm是否已过期。如果已过期,BswM将启动完整的启动过程,或者让ECU再次进入Sleep。

当退出Sleep状态时,EcuM模块将中止所有活跃的用户alarm和主alarm。这意味着无论是时钟引发的唤醒,还是因其他事件导致的唤醒,都会清除所有alarm。
在StartPreOS序列、WakeupRestart序列和OffPreOS序列中,用户alarm和主alarm都应被取消。

十、多核

在这里插入图片描述
分区可以被视为映射在单个Core上的一个独立区域。因此,在单核和多核架构中,每个Core至少包含一个分区,而且还可以包含任意数量的分区。但任何分区都不能跨越多个Core。

BSW模块可以分布在不同的分区中,从而也可以分布在不同的Core上。有些BSW模块(如BswM)必须包含在每个分区中。而其他模块(如Os或EcuM)则需要每个核对应一个分区进行包含。

在多核架构中,EcuM必须以某种方式进行分布,使得每个Core都能运行一个独立的实例。

在其中一个指定的核中, bootloader会通过EcuM_Init()启动主EcuM。主EcuM会启动一些驱动程序,确定后期构建配置,并启动所有其余的核以及它们各自的附属EcuM。

每个EcuM现在都会启动本核的Os以及所有本核的BswM(每个分区内恰好只有一个BswM)。

如果将相同的EcuM镜像在ECU的每个核上执行,那么EcuM在不同核上的行为就必须有所差异。这可以通过EcuM来实现,它可以通过首先检测自身是否处于主核还是从核来确定并采取相应的行动。
EcuM模块在多核ECU上支持与单核ECU相同的几个阶段(即STARTUP、UP、SHUTDOWN和SLEEP)。

如果使用了安全机制,那么EcuM就必须以最高信任级别运行。

(一)、主核

存在一个明确的主核。主核具体是哪个核,由 bootloader确定。主核的EcuM作为第一个BSW模块启动,并执行初始化操作。

随后,它会启动所有其他核及其对应的所有EcuM。

当这些(其他核和EcuM)启动后,主核的EcuM会与每个附属EcuM一同初始化本核的Os和BswM。

(二)、从核

在每个从核,必须运行一个附属EcuM。如果一个核包含多个分区,那么每个核仅需存在一个EcuM即可。

(三)、主核-从核信号传输

同步关闭实例:
在调用ShutdownAllCores()之前,主EcuM模块必须启动所有从EcuM模块的关闭流程,并且必须等待所有模块完成其负责的BSW模块的反初始化并成功关闭。

为此,主EcuM模块会设置一个所有从模块都能读取的关闭标志。之后,EcuM会为每个已配置的从核激活任务。从模块会在主程序中读取该标志,若收到关闭请求则执行关闭操作。任务名称为EcuM_SlaveCore_Task,其中X为数字。这些任务需要由集成者进行配置。需要激活的任务数量可通过计算EcuMPartitionRef(EcuM分区引用)的实例数减一来确定,因为其中一个EcuMFlexPartitionRef(EcuM灵活分区引用)用于主核。

示例:若配置了3个EcuMPartitionRef实例,那么在调用EcuM_GoDownHaltPoll()时,EcuM_SlaveCore1_Task和EcuM_SlaveCore2_Task将被启动。从模块会在主程序中读取标志,若收到请求则执行关闭。

在这里插入图片描述
Os将OSEK的SetEvent()函数扩展到跨核场景。一个核上的任务可以等待另一个核上设置的事件。上图展示了这一点在调用ShutdownAllCores()之前实现核同步时的应用(其中省略了去初始化的细节)。SetEvent()/WaitEvent()函数接收一个位掩码,该位掩码可用于指示各个从核的关闭就绪状态。每个从EcuM的SetEvent()调用都会终止主EcuM模块的等待。因此,主EcuM模块必须跟踪各个从核的状态,并设置等待状态,直至所有核都已表示准备好为止。

如果调用者已获取资源或自旋锁,WaitEvent()可替换为GetEvent()循环。

(四)、UP Phase

从硬件角度来看,所有核都有可能发生唤醒中断。此时,整 ECU会被唤醒,运行在该核上的EcuM将处理唤醒事件。

EcuM_MainFunction()应在所有EcuM实例中运行。

每个EcuM模块实例都应处理其所在核的唤醒事件。

与单核情况一样,BswM负责控制ECU资源,确定本地核是否可以断电或暂停,并在将控制权交给其所在核的EcuM之前,对相应的应用程序和BSW进行反初始化。

(五)、STARTUP Phase

EcuM模块在所有核上的功能几乎相同。也就是说,与单核情况一样,EcuM模块会执行STARTUP阶段规定的步骤;其中最重要的是启动OS、初始化SchM以及启动本核的BswM。

主EcuM在调用InitBlock 1并完成reset/wakeup相关的内务处理后,会激活所有从核。从核被激活后,会执行其启动程序,在各自的核上调用EcuM_Init()。

每个EcuM在其核上调用StartOs后,OS会先对各核进行同步,然后再执行核各自的启动钩子函数,之后在每个核上执行首个任务前会再次进行核同步。

StartPostOS在每个核上执行,SchM在每个核上初始化。每个EcuM会初始化所有本核的BswM。

每个分区中都必须有一个BswM负责启动该核的RTE。

EcuM模块应在每个核上启动SchM和OS。

EcuM模块应为主核和所有从核上的所有本核调用BswM_Init()。

主核的STARTUP:
在这里插入图片描述
在这里插入图片描述

从核的STARTUP:
在这里插入图片描述

在这里插入图片描述

(六)、SHUTDOWN Phase

目前不支持单个核关闭(即ECU其余部分继续运行的情况)。所有核会同时关闭。

当ECU需要关闭时,主EcuM模块会调用ShutdownAllCores(),而非以某种方式在各个核心上调用ShutdownOS()。ShutdownAllCores()会停止所有核上的OS,并同时停止所有核。

由于主核可能在所有从核完成处理之前就发出ShutdownAllCores(),因此在进入SHUTDOWN阶段前,必须对所有核进行同步。

分布在所有分区上的BswM会确定ECU是否应关闭,并与ECU中的每个BswM进行同步。所有BswM会促使所在分区的所有BSWs、SWCs和CDDs进行反初始化,并向其他BswM发送适当信号,表明自身已准备好关闭。

为实现ECU的关闭,位于主EcuM同一分区的BswM最终会在主核上调用GoOff,该请求会被分发至所有从核。主EcuM会对BswM和SchM进行反初始化。从核上的EcuM会对各自的SchM和BswM进行反初始化,然后发送信号表明该核已准备好执行ShutdownOS。

主EcuM会等待每个从核EcuM发出的信号,随后像往常一样在主核上启动关闭流程(主EcuM调用ShutdownAllCores,ECU通过全局关闭钩子完成关闭)。

主核的SHUTDOWN:
在这里插入图片描述

在这里插入图片描述

从核的SHUTDOWN:
在这里插入图片描述

在这里插入图片描述

(七)、SLEEP Phase

当请求的关闭目标为Sleep状态时,所有核会同时进入睡眠状态。MCU必须为每个核发出halt指令。由于操作系统中任务的时序和优先级是本核的,因此在halt后,调度器和RTE都无需同步。由于主核可能在所有从核完成处理之前就发出MCU halt 指令,因此在进入GoHalt之前,必须对所有核进行同步。

BswM确定应开始睡眠模式,并为每个核分配适当的ECU模式。从属核的BSWs、SWCs和CDDs都必须通过其分区内的BswM获取信息,进行适当的初始化操作,并向BswM发送适当的模式请求,以表明它们已准备好。

如果ECU被置于睡眠状态,那么halt操作必须保持同步,即所有从属核
在主核计算校验和之前都要先停止运行。主核上的EcuM模块使用与在GoOff中同步核时相同的信号机制。
同样,主核上的EcuM模块必须先验证校验和,然后才能将从核从halt状态中释放出来。

主核的SLEEP:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

从核的SLEEP:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十一、EcuM模式处理

在这里插入图片描述

EcuM提供接口,供SW-Cs可选地请求和释放RUN模式与POST_RUN模式。
EcuMFlex会对软件组件提出的请求和释放操作进行仲裁,并将结果传递给BswM。EcuM与BswM的协作是必要的,因为只有BswM能够决定何时可以切换到不同的模式。由于EcuM没有自己的状态机,它依赖于BswM所做的状态转换。因此,EcuM不会主动请求某个状态。此外,它会将所有请求的当前仲裁情况通知给BswM,并且当RTE执行完属于某一模式的所有可运行实体时,也会通知BswM。

当BswM通过EcuM_SetState()设置EcuM的状态时,EcuM应向RTE指示相应的模式。

当最后一个RUN请求被释放后,EcuM模块应使用BswM_EcuM_RequestedState(POST_RUN,ECUM_RUNSTATUS_RELEASED)接口向BswM请求POST_RUN状态。
如果一个SW-C在POST_RUN阶段需要执行后续操作(例如关闭准备工作),那么它必须在释放RUN请求之前先请求POST_RUN操作。否则,不能保证该SW-C能够有机会运行其POST_RUN阶段的代码。

当EcuM未处于SW-C所请求的状态时,它应使用BswM_EcuM_RequestedState()接口将请求的状态通知给BswM。
POST_RUN状态为SW-Cs提供了一个运行后阶段,允许它们保存重要数据或关闭外设。

当最后一个POST_RUN请求被释放后,EcuM模块应使用BswM_EcuM_RequestedState(SHUTDOWN,ECUM_RUNSTATUS_RELEASED)接口向BswM请求关闭SHUTDOWN状态。
为防止ECU模式的模式机实例滞后,以及EcuM与RTE的状态不同步,EcuM可对模式切换通知使用确认反馈。
EcuM仅请求RUN模式与POST_RUN模式之间的切换,SLEEP模式必须由BswM设置,因为EcuM并不知晓何时可以进入该模式。

以下是EcuM模式的状态:
STARTUP:
初始值。当调用Rte_Start()时由Rte设置。
RUN:
一旦所有必要的BSW模块完成初始化,BswM就会切换到该模式。
POST_RUN:
当没有RUN请求时,EcuM会请求POST_RUN模式。
SLEEP:
当没有RUN和POST_RUN请求,且关闭目标设置为SLEEP时,EcuM会请求SLEEP模式。
SHUTDOWN:
当没有RUN和POST_RUN请求,且关闭目标设置为SHUTDOWN时,EcuM会请求SHUTDOWN模式。

EcuM的状态是可以被SWC和BswM去请求切换的,切换到相关状态后可以由EcuM或BswM去执行相关动作,如允许通信、保存NVM、关闭DEM等。
通常EcuM Fixed版本在状态切换时会自己调用相关接口去作处理,而Flex版本通过指示状态让BswM去处理,这样更有灵活性。

十二、其他

(一)、Bootloader相关
在这里插入图片描述
Bootloader并非AUTOSAR的一部分。但应用程序需要一个接口来激活Bootloader。为此,提供了两个函数:EcuM_SelectBootTarget()和EcuM_GetBootTarget()。
Bootloader、系统供应商Bootloader和应用程序是相互独立的程序镜像,在很多情况下甚至可以分别进行烧录。从一个镜像切换到另一个镜像的唯一方式是通过复位。引导菜单会根据所选的引导目标,分支进入相应的镜像。

(二)、EcuM flex和 EcuM fixed
Fixed模式在AUTOSAR 4.4中已被移除,现在用的都是Flex的,但是还是兼容Fixed的,两者区别可参考vector技术文档里:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

fixed版的状态机如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十三、唤醒序列图

(一)、GPT唤醒序列图

Gpt是可能的唤醒源之一。通常,ECU进入sleep之前,会先启动Gpt,并且硬件定时器在到期时会引发中断。该中断会唤醒MCU,并在Gpt模块中执行中断处理程序。它会通知EcuM模块,已发生Gpt引发的唤醒事件。为了区分导致唤醒的不同Gpt通道,集成者可以为每个Gpt通道分配不同的唤醒源标识符。

下图是通过Gpt中断唤醒
在这里插入图片描述
在这里插入图片描述

如果Gpt硬件能够记录定时器超时情况,那么也可以通过监测Gpt来实现唤醒功能,如下图是通过Gpt轮询唤醒:
在这里插入图片描述
在这里插入图片描述

(二)、ICU唤醒序列图

Icu是另一个唤醒源。与Gpt不同,Icu驱动程序本身并非唤醒源,它只是处理唤醒中断的模块。因此,只有唤醒源的驱动程序才能判断自身是否是此次唤醒的原因。这就要求EcuM_CheckWakeup()必须询问作为实际唤醒源的模块。而为了明确需要询问哪个模块,Icu必须将唤醒源的标识符传递给EcuM_CheckWakeup()。

对于共享中断,集成代码可能需要在EcuM_CheckWakeup()中检查多个唤醒源。为此,Icu必须将所有可能导致此次中断的唤醒源的标识符传递给EcuM_CheckWakeup()。需要注意的是,EcuM_WakeupSourceType为每个唤醒源分配了一个位,因此可以在一次调用中传递多个唤醒源。

由于Icu仅负责处理唤醒中断,因此对Icu进行轮询是不合理的。下图是通过Gpt中断唤醒:
在这里插入图片描述
在这里插入图片描述

(三)、CAN唤醒序列图

在CAN总线上,唤醒可以由收发器或通信控制器通过中断或轮询的方式检测到。唤醒源标识符应在收发器和控制器之间共享,因为EcuM只需知道哪个网络触发了唤醒,并将该信息传递给ComM。

在中断场景或共享中断场景中,无法明确具体是哪个唤醒源(CAN控制器、CAN收发器、LIN控制器等)检测到了唤醒。因此,集成人员必须将 EcuM_CheckWakeup(wakeupSource)中衍生的wakeupSource(它可能代表一个共享中断,也可能仅代表一个中断通道)分配给特定的唤醒源,再将这些特定唤醒源传递给CanIf_CheckWakeup(WakeupSource)。因此,此处EcuM_CheckWakeup()的参数wakeupSource与CanIf_CheckWakeup()的参数wakeupSource可能不同,也可能相同,这取决于硬件拓扑结构以及EcuM_CheckWakeup()集成代码中的实现方式。

在CanIf_CheckWakeup(WakeupSource)过程中,CanIf会检查是否有设备(CAN通信控制器或收发器)配置了与wakeupSource值匹配的参数。如果存在这样的设备,将通过相应的设备驱动模块检查该设备是否触发了唤醒。若设备检测到唤醒,设备驱动会通过EcuM_SetWakeupEvent(sources) 通知EcuM。其中,sources参数被设置为该设备的配置值,也就是调用CanIf_CheckWakeup()时所使用的值。

多个设备可能被配置为相同的唤醒源值。但如果设备连接到不同的总线介质且具备唤醒能力,将它们配置为不同的唤醒源会更为合理。

以下的CAN唤醒序列部分是可选的,因为集成代码没有明确的规范。因此,例如在EcuM_CheckWakeup()过程中是否调用CanIf来检查唤醒源,取决于具体的实现。

下图是通过CAN收发器中断唤醒,通过CAN收发器的IO引脚实现外部中断唤醒。该中断通常由Icu驱动程序处理:
在这里插入图片描述
在这里插入图片描述

通过CAN控制器的中断唤醒与Gpt唤醒的工作原理类似。此处的中断处理程序和CheckWakeup功能均封装在CanDrv模块中,如下图:
在这里插入图片描述
在这里插入图片描述

CAN收发器和控制器都可以通过轮询的方式实现唤醒。EcuM模块会定期检查CanIf模块,而CanIf模块则会根据传递给它的唤醒源参数,相应地询问CanDrv模块或CanTrcv模块,如下图是EcuM通过轮询的方式检测有没有CAN控制器和CAN收发器唤醒:
在这里插入图片描述
在这里插入图片描述

在通过中断或轮询方式检测到来自CAN 收发器或控制器的唤醒事件后,可以对该唤醒事件进行验证。验证过程通过在EcuM_StartWakeupSource()中开启相应CAN收发器和控制器来完成。集成代码EcuM_StartWakeupSource()中需要哪些函数调用,取决于所使用的CAN收发器和控制器。例如,下图提及了从CanSM模块启动和停止唤醒源所需的函数调用。
需要注意的是,尽管控制器和收发器已开启,但CanIf不会将任何CAN消息转发给上层模块。只有当CanIf相应的PDU通道模式设置为Online时它才会转发CAN消息。
CanIf会识别至少一条消息的成功接收,并将其记录为一次成功的验证。在验证过程中,EcuM模块会在集成代码EcuM_CheckValidation()中定期检查CanIf。
验证成功后,EcuM模块会通过ComM模块继续启动CAN网络的正常运行流程。否则,它会在EcuM_StopWakeupSources()中关闭CAN控制器和收发器,然后进入睡眠状态。
如下图所示是CAN唤醒验证流程:
在这里插入图片描述

(四)、LIN唤醒序列图

下图展示了接收LIN收发器的外部中断的唤醒,通常也是用Icu模块来实现该唤醒:
在这里插入图片描述
在这里插入图片描述

LIN控制器通过中断方式唤醒与CAN控制器通过中断方式唤醒的方式类似,由Lin驱动模块进行封装如下图是通过LIN控制器中断唤醒的序列图:
在这里插入图片描述
在这里插入图片描述

对于LIN收发器和控制器而言,通过轮询方式实现唤醒是可行的。EcuM会定期检查LinIf模块,而该模块又会向Lin模块或LinTrcv模块发出请求,如下图是通过轮询方式检测有没有LIN唤醒源:
在这里插入图片描述

LIN不需要唤醒验证,所以没有唤醒验证流程。

(五)、FlexRay唤醒序列图

对于FlexRay来说,唤醒操作只能通过FlexRay收发器来实现。在 FlexRay集群中,有两个收发器分别对应两个不同的通道。它们被视为属于同一个网络,因此,对于两个通道,应该只配置一个唤醒源标识符。
下图展示了通过中断实现的FlexRay收发器唤醒过程。
该中断是通常Icu程序来处理,如下图是通过FlexRay收发器触发的唤醒,在EcuM_CheckWakeup(),需要对Frlf_WakeupByTransceiver()进行两次独立调用,分别针对每个FlexRay通道:
在这里插入图片描述
在这里插入图片描述

下图是通过轮询方式检测有没有FlexRay收发器唤醒源:
在这里插入图片描述
在这里插入图片描述

(六)、Ethernet唤醒序列图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十四、主要代码和参数描述

(一)、主要函数

1、Initialization and Shutdown Sequences

(1)、Std_ReturnType EcuM_GoDownHaltPoll(uint16 caller)
在UP Phase时调用,用EcuM_SelectShutdownTarget()设置好关机目标后,调用EcuM_GoDownHaltPoll()可以进入SLEEP或OFF或RESET状态。

(2)、void EcuM_Init(void)
EcuM初始化。

(3)、void EcuM_StartupTwo(void)
在STARTUP Phase时调用,在Os启动后被调用,执行StartPostOS序列,执行完后启动调度表。

(4)、void EcuM_Shutdown(void)
在SHUTDOWN Phase时调用,在Os的ShutdownHook()钩子函数中被调用,接管控制权,执行OffPostOS序列,执行完后根据关机目标选择进入RESET还是OFF。

2、State Management

(1)、void EcuM_SetState(EcuM_ShutdownTargetType state)
Bsw调用的函数,用于通知EcuM进行状态切换。

(2)、Std_ReturnType EcuM_RequestRUN(EcuM_UserType user)
SW-C或其他模块向EcuM发出请求,要求将ECU切换到‌RUN状态。

(3)、Std_ReturnType EcuM_ReleaseRUN(EcuM_UserType user)
SW-C或其他模块释放对ECU RUN的请求。

(4)、Std_ReturnType EcuM_RequestPOST_RUN(EcuM_UserType user)
SW-C或其他模块向EcuM发出请求,要求将ECU切换到‌POST_RUN状态。POST_RUN状态通常用于ECU在关闭或休眠前的准备工作,例如保存关键数据或关闭外设。

(5)、Std_ReturnType EcuM_ReleasePOST_RUN(EcuM_UserType user)
SW-C或其他模块释放对ECU POST_RUN的请求。

3、Shutdown Management

(1)、Std_ReturnType EcuM_SelectShutdownTarget(EcuM_ShutdownTargetType shutdownTarget,EcuM_ShutdownModeType shutdownMode)
允许User去指定ECU的关机目标,SLEEP、RESET、OFF之一。

(2)、Std_ReturnType EcuM_GetShutdownTarget(EcuM_ShutdownTargetType* shutdownTarget,EcuM_ShutdownModeType* shutdownMode)
获取设置的关机目标。

(3)、Std_ReturnType EcuM_GetLastShutdownTarget(EcuM_ShutdownTargetType* shutdownTarget,EcuM_ShutdownModeType* shutdownMode)
返回最近一次通过EcuM_SelectShutdownTarget()配置的关机目标,而非当前待执行的关机目标。

(4)、Std_ReturnType EcuM_SelectShutdownCause(EcuM_ShutdownCauseType target)
用于设置ECU关机原因,如因为WDGM、DCM原因等,与EcuM_SelectShutdownTarget()配合使用,关机时可设置关机原因然后写入NVM供分析使用。

(5)、Std_ReturnType EcuM_GetShutdownCause(EcuM_ShutdownCauseType* shutdownCause)
会返回通过EcuM_Select_ShutdownCause()所设定的选定关机原因。

4、Wakeup Handling

(1)、void EcuM_CheckWakeup(EcuM_WakeupSourceType wakeupSource)
由唤醒源代码调用,比如Icu、Gpt等,用于检查配置的唤醒源是否有有效唤醒事件发生同时会调用EcuM_CheckWakeupHook()钩子函数。

(2)、EcuM_WakeupSourceType EcuM_GetPendingWakeupEvents(void)
返回待处理但未经过验证的唤醒事件。

(3)、void EcuM_ClearWakeupEvent(EcuM_WakeupSourceType sources)
用于‌清除已记录的唤醒事件。
唤醒源的清除操作应在ECU关机之前进行,即在调用Dem Shutdown()和NVM_WriteAll()之前完成。

(4)、EcuM_WakeupSourceType EcuM_GetValidatedWakeupEvents(void)
用于‌获取当前已通过验证的有效唤醒事件。

(5)、EcuM_WakeupSourceType EcuM_GetExpiredWakeupEvents(void)
获取已过期的唤醒事件。

5、Alarm Clock

(1)、Std_ReturnType EcuM_SetRelWakeupAlarm(EcuM_UserType user,EcuM_TimeType time)
用于‌设置基于相对时间的唤醒闹钟‌,通常用于ECU在SLEEP状态下按预定时间主动唤醒的场景。

(2)、Std_ReturnType EcuM_SetAbsWakeupAlarm(EcuM_UserType user,EcuM_TimeType time)
用于‌设置基于绝对时间的唤醒闹钟。

(3)、Std_ReturnType EcuM_AbortWakeupAlarm(EcuM_UserType user)
用于‌中止已设置的唤醒闹钟。

(4)、Std_ReturnType EcuM_GetCurrentTime(EcuM_TimeType* time)
返回EcuM时钟的当前值。

(5)、Std_ReturnType EcuM_GetWakeupTime(EcuM_TimeType* time)
用于‌获取已设置的唤醒时间。

(6)、Std_ReturnType EcuM_SetClock(EcuM_UserType user,EcuM_TimeType time)
用于设置EcuM时钟。

6、Miscellaneous

(1)、Std_ReturnType EcuM_SelectBootTarget(EcuM_BootTargetType target)
设置启动目标,一般是要进入编程会话时,SWC调用该函数设置要进入哪个Bootloader,做好复位前的工作后,EcuM执行复位流程,在复位流程里可以根据启动目标进入相应的Bootloader。

(2)、Std_ReturnType EcuM_GetBootTarget(EcuM_BootTargetType * target)
获取启动目标。

7、Scheduled Functions

(1)、void EcuM_MainFunction(void)
EcuM运行主函数。

8、Callbacks from Wakeup Sources

(1)、void EcuM_SetWakeupEvent(EcuM_WakeupSourceType sources)
设置待验证的唤醒事件通常是Icu、Gpt、CanTrcv等模块调用。

(2)、void EcuM_ValidateWakeupEvent(EcuM_WakeupSourceType sources)
用于‌确认唤醒事件的有效性,如果PENDING类型的唤醒事件经确认有效则变为VALIDATED。

9、Generic Callouts

(1)、void EcuM_ErrorHook(uint16 reason)
该函数是AUTOSAR EcuM模块的关键错误处理接口,用于‌在ECU初始化或状态切换过程中捕获并响应致命错误‌,支持自定义错误恢复策略(如复位、降级运行等)。

10、Callouts from the STARTUP Phase

(1)、void EcuM_AL_SetProgrammableInterrupts(void)
EcuM在‌StartPreOS序列的Callout,用于‌控制MCU可编程中断的全局开关状态‌。

(2)、void EcuM_AL_DriverInitZero(void)
EcuM在‌StartPreOS序列的Callout,此调用仅可初始化那些不使用构建后配置参数的BSW模块。该调用不仅可以包含驱动程序初始化代码,还可以包含任何类型的预操作系统或底层初始化代码。

(3)、const EcuM_ConfigType* EcuM_DeterminePbConfiguration(void)
EcuM在‌StartPreOS序列的Callout,此调用应评估某些条件(例如端口引脚或 NVRAM 值),以确定在启动过程的剩余阶段应使用哪种构建后的配置。

(4)、void EcuM_AL_DriverInitOne(void)
EcuM在‌StartPreOS序列的Callout,不仅可以包含驱动程序初始化,还可以包含任何类型的操作系统启动前的底层初始化代码并且不依赖于操作系统的模块。

(5)、void EcuM_LoopDetection(void)
EcuM在‌StartPreOS序列的Callout,可在里面添加一些安全机制,若检测到循环被调用,触发EcuM_ErrorHook并记录错误码,强制终止启动流程。

11、Callouts from the SHUTDOWN Phase

(1)、void EcuM_OnGoOffOne(void)
EcuM在‌OffPreOS序列的Callout,即进入关机流程时会进入,用户可以在这里面添加关机前的自定义代码比如保存关键数据到NVRAM、关闭外设等。

(2)、void EcuM_OnGoOffTwo(void)
EcuM在‌OffPostOS序列的Callout,该函数在EcuM完成OS关闭后调用,此时,ECU已停止软件调度,准备进入RESET或OFF状态。

(3)、void EcuM_AL_SwitchOff(void)
如果关机目标设为OFF,则在OffPostOS序列的最后一步去调用,用户可以在里面添加ECU断电操作。

(4)、void EcuM_AL_Reset(EcuM_ResetType reset)
如果关机目标设为RESET,则在OffPostOS序列的最后一步去调用,用户可以在里面添加ECU复位操作。

12、Callouts from the SLEEP Phase

(1)、void EcuM_EnableWakeupSources(EcuM_WakeupSourceType wakeupSource)
EcuM在‌GoSleep序列的Callout,即在睡眠前用户可以在该函数里添加使能唤醒源的动作,如调用Icu_EnableWakeup()、Gpt_EnableWakeup()使能Icu、Gpt的唤醒源。

(2)、void EcuM_GenerateRamHash(void)
EcuM在‌Halt序列的Callout,在MCU进入睡眠状态前用户可以在这里面添加对当前RAM进行哈希计算的操作,当MCU唤醒时,可以进行检查唤醒后的RAM哈希计算值,然后进行比对,防止MCU在睡眠期间RAM有损坏导致唤醒后功能不正常。

(3)、void EcuM_SleepActivity(void)
EcuM在‌Poll序列的Callout,在该序列下MCU进入睡眠状态后会不断周期唤醒然后低速运行,用户可以在这里添加轮询唤醒源操作。

(4)、void EcuM_StartCheckWakeup(EcuM_WakeupSourceType WakeupSource)
当有唤醒源时可调用,该函数用于‌启动唤醒源验证定时器,用于限定唤醒源的有效性验证时间窗口,若超时未完成验证,则判定为无效唤醒事件,通常在EcuM_CheckWakeup()检测到唤醒事件后调用。

(5)、void EcuM_CheckWakeupHook(EcuM_WakeupSourceType wakeupSource)
检查唤醒源钩子函数,当ECU唤醒时会调用,用户可以在这里面添加唤醒源检测函数_CheckWakeup()。

(6)、uint8 EcuM_CheckRamHash(void)
EcuM在‌Halt序列的Callout,从睡眠状态唤醒后会调用,用户可在里面添加RAM检测代码,与EcuM_GenerateRamHash()配合使用。

(7)、void EcuM_DisableWakeupSources(EcuM_WakeupSourceType wakeupSource)
EcuM会在WakeupRestart序列里调用,用户可在该Callout里添加禁用唤醒源操作,避免误触发休眠唤醒流程,比如调用Icu_DisableWakeup()去禁用ICU唤醒。

(8)、void EcuM_AL_DriverRestart(void)
EcuM在‌WakeupRestart序列的Callout,用户可在里面重新初始化驱动程序。

13、Callouts from the UP Phase

(1)、void EcuM_StartWakeupSources(EcuM_WakeupSourceType wakeupSource)
EcuM在WakeupValidation序列的Callout,启动指定的唤醒源,用以准备好唤醒验证,使其具备检测或响应唤醒信号的能力。
通常里面调用的是CanSM_StartWakeupSources(),调用后CanSM会调用CanIf将控制器和收发器设置NORMAL模式。

(2)、void EcuM_CheckValidation(EcuM_WakeupSourceType wakeupSource)
EcuM在WakeupValidation序列的Callout,验证唤醒源是否有效,通常调用CanIf_CheckValidation()。

(3)、void EcuM_StopWakeupSources(EcuM_WakeupSourceType wakeupSource)
EcuM在WakeupValidation序列的Callout,关闭已启动的唤醒源,通常在唤醒验证失败后被调用,通常里面调用CanSM_StopWakeupSources()关闭收发器和控制器。

(二)、主要类型

1、EcuM_WakeupSourceType
在这里插入图片描述

2、EcuM_WakeupStatusType
在这里插入图片描述

3、EcuM_BootTargetType
在这里插入图片描述

4、EcuM_ResetType
在这里插入图片描述

5、EcuM_ShutdownCauseType
在这里插入图片描述

6、EcuM_ShutdownTargetType
在这里插入图片描述

十五、DaVinci Configurator主要配置

(一)、EcuMGeneral

在这里插入图片描述

(二)、EcuMFlexGeneral

在这里插入图片描述
Alarm Clock Present:
定义是否使能Alarm功能。

Alarm Wakeup Source:
当Alarm被用作唤醒源时需要指定是哪个唤醒源。

Mode Handling:
Run Request Protocol是否使能。

Reset Loop Detections:
表示在StartPreOS中EcuM_Loop_Detection是否被调用。

(三)、EcuMCommonConfiguration

在这里插入图片描述

1、EcuMSleepModes
在这里插入图片描述
Sleep Mode Suspend:
当勾上时,进入halt-sleep模式,没勾上时进入poll-sleep模式。

Sleep Mode Mcu Mode Ref:
Mcu组件里对应的参考源。

Wakeup Source Mask:
在Sleep模式下只有该项列出的唤醒源才是有效的唤醒源。

2、EcuMWakeupSources
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
此处定义唤醒源,定义的唤醒源可供其他组件通过调用EcuM_SetWakeupEvent()去设置。
如CanTrcv这里的唤醒源参考为自定义的一个唤醒源,当CanTrcv认为有唤醒时便调用EcuM_SetWakeupEvent()去设置EcuM里的自定义唤醒源。
在这里插入图片描述

Check Wakeup Timeout[s]:
从EcuM_CheckWakeup()开始到检测到唤醒源即EcuM_SetWakeupEvent()被调用的超时时间,如果超时时间结束进入Sleep模式。

Reset Reason Ref:
Mcu组件检测到复位原因到唤醒源的映射,即EcuM每次初始化时会调用Mcu_GetResetReason()去检测复位原因并且获取到复位原因,如果唤醒源有配置对应的复位原因,则EcuM将该唤醒源设置为VALIDATED。

Validation Timeout[s]:
每个唤醒源的验证时间。如果未定义或0则该唤醒源验证被禁用。当调用EcuM_SetWakeupEvent()设置唤醒源时,该唤醒源状态为VALIDATED否则为PENDING。

Wakeup Source Id:
唤醒源ID,0-4为默认唤醒源。

Wakeup Source Polling:
如果此项为TRUE,并且Sleep Mode Suspend为FALSE即在睡眠模式下使能poll,并且Wakeup Source Mask里有配置了唤醒源,则在poll下会调用EcuM_CheckWakeup()检测配置了的唤醒源。

ComM Channel Reference:
ComM PNC Reference:
当该唤醒源被检测到并且验证有效,如果有配置引用的ComM通道或PNC通道,则会调用ComM_EcuM_WakeUpIndication()或ComM_EcuM_PNCWakeUpIndication()到ComM对相应的网络通道进行请求通信。

3、EcuMDefaultShutdownTarget
在这里插入图片描述
该配置项是EcuM初始化后没调用EcuM_SelectShutdownTarget()启用的默认项。

Default Reset Mode Ref:
当Default State配置为EcuMStateReset时有效,默认的复位模式。

Default Sleep Mode Ref:
当Default State配置为EcuMStateSleep时有效,默认的睡眠模式。

Default State:
默认的关机目标,EcuMStateSleep或EcuMStateReset或EcuMStateOff。

4、EcuMDemEventParameterRefs
在这里插入图片描述
此处定义当EcuM出现错误时用于记录的DTC。

5、EcuMDriverInitListOne
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
此处定义STARTUP阶段StartPreOS序列中的驱动初始化。即EcuM_AL_DriverInitOne()里的初始化动作。
Additional Init Code:
此处添加额外的代码段,比如.h里没有的接口。

Module Header:
要调用初始化该模块的头文件。

Module ID:
Module Service:
Module Service可以选择添加Init、PreInit、Start等,Module ID则为驱动名称,如需要调用Adc初始化则ID填Adc,Service可以填Adc_Init。
如果是额外代码则ID填Code。
在这里插入图片描述

6、EcuMDriverInitListZero
在这里插入图片描述
此处定义STARTUP阶段StartPreOS序列中的驱动内存初始化。即EcuM_AL_DriverInitZero()里的初始化动作。
配置项与上面一样。

7、EcuMDriverRestartList
此处定义从睡眠模式唤醒后要初始化的列表,即EcuM_AL_DriverRestart()里的初始化动作。

(四)、EcuMFlexConfiguration

在这里插入图片描述
此处配置Gpt的通道参考、从睡眠模式唤醒后要设置的MCU正常模式参考、EcuM要跑哪个分区(多核下用)。

1、EcuMAlarmClock
在这里插入图片描述
Alarm Clock Time Out:
当EcuM内部alarm计时到达此TimeOut值后,内部会产生一个alarm唤醒。

Alarm Clock User:
将该Alarm分配给哪一个user。

2、EcuMDriverInitListBswMs
此处定义用于初始化BSW模块的列表,如果定义了会生成EcuM_AL_DriverInitBswM()函数,可以被BswM调用,通常BSW模块初始化会在BswM里进行配置初始化,此项也可以不配置。

3、EcuMFlexUserConfigs
此处定义EcuM的User并且分配分区。

4、EcuMResetModes
在这里插入图片描述
此处配置复位模式,这些都是默认生成的。复位模式会在执行EcuM_AL_Reset()时输入,用户可根据输入的复位模式进行相应的复位动作。复位模式由EcuM_SelectShutdownTarget()设置。

5、EcuMShutdownCause
在这里插入图片描述
此处配置关机原因,这些都是默认生成的。

6、EcuMShutdownTargets
在这里插入图片描述

7、EcuMGoDownAllowedUsers
在这里插入图片描述
表示允许调用EcuM_GoDownHaltPoll()的User。

8、EcuMSetClockAllowedUsers
在这里插入图片描述
允许调用EcuM_SetClock()的user

(五)、唤醒源配置

首先需要在此处定义唤醒源:
在这里插入图片描述
每个唤醒源的设置可在相应的组件里去引用,如可在CanTrcv引用CAN唤醒源:
在这里插入图片描述
当唤醒源的Vaildation Timeout不设置为1时就启用了校验机制:
在这里插入图片描述
一般只有总线唤醒才有校验机制,因为考虑到总线上的波动总会使收发器给ECU上电,所以比如要在CanIf里使能校验:
在这里插入图片描述
在这里插入图片描述

上图的CanIf可以选择只有NM报文才为有效唤醒源或者所有CanIf接收的报文都为有效唤醒源。

CAN唤醒源检测可通过收发器和控制器去检测,需要在CanIf使能对应的检测,在CanIf_CheckWakeup()被调用时会选择调用CanTrcv_CheckWakeup()或Can_CheckWakeup():
在这里插入图片描述
在这里插入图片描述

通过代码发现休眠时EcuM会周期调用EcuM_CheckWakeup()或其他组件去调用EcuM_CheckWakeup(),EcuM_CheckWakeup()里再根据传入的唤醒源去调用对应的XX_CheckWakeup(),XX_CheckWakeup()里认为有唤醒源后(比如Gpt定时唤醒或CanTrcv收到报文都会唤醒ECU)调用EcuM_SetWakeupEvent()去设置配好的参考唤醒源,如果该唤醒源需要校验比如CAN唤醒源,则EcuM会在周期函数里调用EcuM_StartWakeupSources(),EcuM_StartWakeupSources()会再调用CanSM_StartWakeupSources()暂时开启CAN控制器和CAN收发器,但接收的报文只会传到CanIf层并且不会发送,因为这时候CanIf设置的PDU模式为OFFLINE,然后EcuM再调用EcuM_CheckValidation(),EcuM_CheckValidation()里再调用CanIf_CheckValidation(),CanIf会根据是控制器还是收发器去验证该唤醒源是否有效(是否为NM报文或允许接收的报文),有效的话调用EcuM_ValidateWakeupEvent()将该唤醒源设置为有效,然后EcuM再调用EcuM_StopWakeupSources()关闭CAN控制器和CAN收发器,如果该唤醒源有引用对应的网络通道则再调用ComM_EcuM_WakeUpIndication()或ComM_EcuM_PNCWakeUpIndication(),然后里面会调用Nm_PassiveStartUp()和CanSM_RequestComMode()请求COMM_FULL_COMMUNICATION使某路通道唤醒开启CAN控制器和CAN收发器。

某些项目要求第一帧NM报文就能请求某路网络,按上述的配置ECU需要收到第二帧NM报文才能请求网络,那么可以给收发器配置NM报文的过滤器并且可以给Trcv的唤醒源引用ECUM_WKSOURCE_POWER唤醒源,并且该唤醒源引用某路网络通道,并且复位原因引用上电复位,则可以实现第一帧NM报文过来激活网络。
在这里插入图片描述

(六)、不通过上电唤醒使能CAN网络被动唤醒

当ECU上电后除非SWC里调用ComM_RequestComMode(COMM_FULL_COMMUNICATION)唤醒CAN网络和使能收发器控制器,否则需要收到外部NM报文或ECU上电激活网络,如下图片:
在这里插入图片描述
但是当ECU上电后,CanSM的状态为NOCOM,即CAN控制器和CAN收发器都处于不通信状态,如果CAN唤醒源类型设置了PENDING类型,那么有CAN的唤醒源后会调用CanSM_StartWakeupSources()暂时开启CAN控制器和CAN收发器去判断是不是预期的CAN报文,但是CanIf里的PDU通道模式还是为OFFLINE,收到的报文不会传到上层,就不能实现是因为收到NM报文引起被动唤醒了。

如果要实现是因为收到NM报文引起被动唤醒,第一个方法是给CAN收发器设置滤波器,只有当收到NM报文的ID,收发器才拉高INH脚唤醒ECU,然后EcuM里的上电唤醒源可以直接引用相关的CAN通道,当唤醒事件有效时调用ComM_EcuM_WakeUpIndication(),然后CAN网络通道被动唤醒。第二个方法是CAN收发器不需要设置滤波器,给CAN唤醒源设置为PENDING类型即需要校验,在CanIf里使能NM校验即只有NM报文才会将唤醒源设置为VALIDATED,如下:
在这里插入图片描述
校验通过后调用ComM_EcuM_WakeUpIndication(),然后CAN网络通道被动唤醒。
第三个方法是所有唤醒源取消引用网络通道,取消不会再调用ComM_EcuM_WakeUpIndication(),给CAN唤醒源设置为需要校验,当需要校验时Callout函数EcuM_StartWakeupSources()被调用,里面添加CanSM_RequestComMode(0,COMM FULL COMMUNICATION)即开启CAN控制器和收发器并且PDU通道设置为ONLINE,如下:
在这里插入图片描述
这样第二帧NM报文就能被CanNm收到,最终ComM_Nm_NetworkStartIndication()被调用实现被动唤醒,但要注意调用CanSM_RequestComMode()调用后,Com层的IPDU组还不能开启,只有当ComM状态进入COMM_FULL_COM_NETWORK_REQUESTED后才能开启,该方法也可适用只有收到诊断请求才唤醒的场景。

十六、唤醒事件处理和唤醒事件校验以及Callout示例

Wake-up Source的处理及Wake-up Validation的配置与实现必须针对每个ECU单独进行。以下列表简要概述了涉及的相关callout:
EcuM_EnableWakeupSources(),
EcuM_DisableWakeupSources(),
EcuM_CheckWakeup(),
EcuM_StartWakeupSources(),
EcuM_StopWakeupSources()

集成工程师需要为这些callout填写代码,以满足特定ECU的需求。以下将通过两个示例用例进行说明:
休眠模式后的唤醒
网络通道的唤醒验证(EcuM处于Run state)

(一)、休眠模式后的唤醒

用例描述:
当Icu通道出现上升沿时,应使EcuM进入RUN状态。因此,配置了唤醒源ECUM_WKSOURCE_ICU_CH0,配置的Icu通道名称为Icu_Channel0。
对于该唤醒事件,无需执行唤醒验证。在目标休眠模式下,此唤醒事件是唯一有效的唤醒事件。

执行流程:
1、EcuM处于ECUM_STATE_RUN状态。
2、BswM调用EcuM_GoHalt()。
(1)、执行Callout函数EcuM_EnableWakeupSources()。
(2)、EcuM进入sleep模式,Mcu_SetMode()被调用。
3、ICU通道出现上升沿,触发Icu中断。
4、中断里调用EcuM_CheckWakeup()。
5、EcuM_SetWakeupEvent()被调用。
6、EcuM执行EcuM_ValidateWakeupEvent()因为唤醒事件有效。
7、EcuM从ECUM_STATE_SLEEP切换为ECUM_STATE_WAKEUP_ONE。
8、ECUM_STATE_WAKEUP_TWO切换为ECUM_STATE_ RUN,并且 EcuM_DisableWakeupSources()被调用。

以下Callout函数的实现:
在这里插入图片描述

(二)、网络通道的唤醒验证(EcuM处于Run state)

用例描述:
假设所使用的CAN通道具备唤醒功能。当CAN通道上出现一条报文时,该报文应被识别,且需将此CAN通道切换至正常工作模式(此操作将由ComM触发)。为此,配置了唤醒源ECUM_WKSOURCE_CAN0。对于该通道,需执行唤醒验证。

执行流程:
1、EcuM处于RUN状态,CAN通道处于sleep状态并且能够检测唤醒事件。
2、有报文后在中断里调用EcuM_CheckWakeup()。
3、EcuM_SetWakeupEvent()执行后,EcuM开始启用唤醒校验计时。
4、EcuM_MainFunction()周期运行:
(1)、EcuM检测到有PENDING型唤醒事件,并且调用EcuM_StartWakeupSources()。
(2)、EcuM调用EcuM_CheckValidation()。(可能多次被调用)
5、如果唤醒事件校验成功:
(1)、调用EcuM_ValidateWakeupEvent()将唤醒事件设置为VALIDATED同时调用ComM_WakeUpIndication()。
(2)、停止唤醒校验功能。
6、如果唤醒事件校验失败:
(1)、EcuM调用EcuM_StopWakeupSources()。
(2)、PENDING型事件改变为EXPIRED型事件。

以下Callout函数的实现:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十七、参考资料

AUTOSAR_CP_EXP_VFB
AUTOSAR_CP_SWS_RTE
AUTOSAR_CP_SRS_ModeManagement
AUTOSAR_CP_EXP_ModeManagementGuide
AUTOSAR_CP_RS_ModeManagement
AUTOSAR_CP_SWS_BSWModeManager
AUTOSAR_CP_SWS_BSWGeneral
AUTOSAR_FO_TR_Glossary
AUTOSAR_CP_RS_BSWGeneral
AUTOSAR_CP_SWS_MCUDriver
AUTOSAR_CP_SWS_CANTransceiverDriver
TechnicalReference_EcuM


总结

本文文字描述多点,更像是本人的使用笔记,仅供参考,如有不对地方欢迎指教。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐