基于AUTOSAR的ECU启动阶段哪些事儿

AUTOSAR实战篇:EcuM启动时序大总结

前言

小T出品,必是精品!
EcuM启动时序大总结,你值得拥有!

在这里插入图片描述


正文

正如小T前文中《AUTOSAR基础篇之EcuM》中讲到的那样,AUTOSAR架构中将ECU的上下电过程统一由单一的模块来进行统一管理,即EcuM模块。

虽然不同硬件的初始化过程不一样,但是只要使用AUTOSAR架构,整个上下电过程时序确是稳定不变的,与硬件完全解耦,也就意味着该EcuM模块能够快速移植适配不同的硬件平台。

本人将基于RH850芯片的启动流程来讲解,采用ETAS的ISOLAR-AB工具进行配置实现整个ECU的上电启动过程,在这个过程中会重点描述几个关键的步骤与要点,让大家掌握基本的方法论。

S1: 硬件复位

启动的第一步就是从控制器的复位向量表处开始执行,该复位向量表不同的控制器均会有所差异,主要涉及到初始化栈指针以及内存的初始化,该硬件初始化代码会最终跳入到Main函数入口,在Main函数中一般执行的第一个函数就是EcuM_Init函数

S2: OS初始化

在调用EcuM_Init函数的第一步就是调用函数接口EcuM_AL_SetProgrammableInterrupts,该函数接口可以通过如下ISOLAR工具进行配置。

这一步非常关键,因为Os_InitializeVectorTable() 函数将会在该函数内部调用,这是OS提供的标准化API用于实现中断向量表初始化,从而保证后续OS开启后中断均可以正常工作。

值得注意的是此时中断并没有开始运行,该步骤只是为了确保后续进来的中断能够正常工作,中断仅在调用StartOS函数接口后才正式工作起来。

在这里插入图片描述

图1 中断向量表配置

在这里插入图片描述

图2 在EcuM_Init函数中位置
S3: 硬件驱动初始化时序

在EcuM_Init函数中的第二阶段就是硬件底层驱动程序的初始化,该初始化动作通过Block 0与Block 1两部分来完成。我们将Block 0的初始化称为EcuM模块Init Zero,将Block 1初始化称为EcuM模块Init One。

这两个Block 0 与Block 1两个初始化列表就可以完成MCAL初始化以及其他CDD复杂驱动的初始化工作,从而完成整个硬件底层驱动初始化环境。如下图3为AUTOSAR官方文档推荐的EcuM初始化时序,当然大家也可以根据实际的硬件设计进行调整,比如将block 0中的初始化放入到block 1中。

其中Block 0的底层驱动初始化通过调用函数接口EcuM_AL_DriverInitZero()来完成,Block 1的底层驱动初始化通过调用函数接口EcuM_AL_DriverInitOne来完成。

一般推荐的原则是:如果跟EcuM配置参数无关,则可以直接放入到Block 0中进行初始化,如果跟EcuM配置参数有关,则需要放入到Block 1中。

在这里插入图片描述

图3 AUTOSAR推荐底层驱动初始化时序

如下图4所示,配置了相关底层驱动的初始化函数,统一放入到了Block 1中,

在这里插入图片描述

图4 ISOLAR工具Block 1初始化配置

生成的对应代码如下图5所示:

在这里插入图片描述

图5 EcuM模块Block 1初始化生成代码

在Block 1中如果存在其他的CDD复杂驱动初始化,也可以通过在EcuM模块中进行统一配置添加,EcuM模块会按照加入的先后顺序进行驱动初始化,相关的外部头文件也可以通过配置加入。

S4: EcuM 启动时间测量

如果需要使用EcuM_GetTicks()函数,你需要使能通过如下参数“EcuMRbStartupDuration”为TRUE进行测量,该函数就会自动计算block 0与block 1各个阶段的启动时间。

与此同时,你需要将EcuM_GetTicks()函数map到一个已经启动的定时器上,因为MCU初始化在调用EcuM_GetTicks()函数之后,所以使用MCU初始化的定时器是没有作用的,这点要尤其注意。
在这里插入图片描述

图6 EcuM模块启动时间测量使能
S5:OS启动

在EcuM_Init中的最后一步就是通过调用函数接口EcuM_Prv_StartOS()启动OS:

在这里插入图片描述

图7 EcuM模块StartOS调用

如下图所示为StartOS的实际代码,本质上就是一个while(1)大循环,然后通过定时器中断来驱动整个OS的运行。OS再此便是等待中断或者任务的激活。此时需要注意虽然此时OS已经被启动,但是使用的ScheduleTable并没有启动,也就意味着虽然OS已经启动,但是周期性任务并没有被调用。

在这里插入图片描述

图8 StartOS函数执行体

开启OS的操作将触发设置成AutoStart的OS模块或初始化任务运行,如下图仅InitTask配置成Auto-Start,由于设置成AutoStart的Task不属于Schedule Table,因此设置成Auto-Start的task仅运行一次。
在这里插入图片描述

图9 InitTask函数设置成Auto Start函数
S6: 多核OS启动

对于所有的多核应用系统,所有的非Master Core都应该在初始保持Halt状态,例如对于RH850,Os_AwaitStartup被其他非master core进行调用。

OS将会将其他非Master Core从Sleep状态切换成正常状态,当OS启动后,他们将依次跳入到各自的main入口函数执行EcuM_Init函数:

  • Master Core通过调用函数Os_Cbk_StartCore把其他Core从Os_AwaitStartup中启动起来;
  • 每个核启动也可以通过写入Boot寄存器来进行启动,你可以通过配置RH850 可选字节来自动化实现这一点;
S7:初始化Task(InitTask)

初始化任务InitTask是启动的下一阶段,其主要的任务就是初始化BswM 列表。

在这里插入图片描述

图10 InitTask列表

该Task的主要目标就是初始化BswM模块,然后触发相应的action list。除此以外就是初始化EcuM模块的第二阶段。

注:对于ISOLAR AB中子模块BSW小于等于6.1.2的版本存在一个问题:就是SchM初始化在BswM初始化之前,导致SchM初始化的动作无效,因此需要在EcuM_StartupTwo之后再次添加SchM_IModeInit函数来发送请求至BswM模块。

EcuM_StartupTwo函数中会调用BswM_Init函数,一旦BswM完成初始化,那么SchM_IModeInit函数将触发BswM初始化list One。

在这里插入图片描述

在这里插入图片描述

图11 老版本(<=6.1.2)InitTask列表

注意事项:

在调用EcuM_StartupTwo函数的内部,需调用SchM_Init()以及BswM_Init函数,不过由于AUTOSAR版本的变化因此,针对ETAS RTA工具生成的EcuM_StartupTwo函数代码也有所差异:

  • 对于RTA BSW版本小于等于6.1.2,是先初始化SchM_Init函数,然后初始化BswM_Init函数,代码如下:

在这里插入图片描述

  • 对于RTA BSW版本大于等于6.1.3,其顺序则是BswM_Init在前,SchM_Init初始化在后,代码如下;

在这里插入图片描述

S8:BswM Startup One阶段

如下图12所示,如下在OS启动初始化之后,BswM模块首次进入到Startup One阶段,在该阶段主要做用来初始化Mem Stack以及进行Nvm_ReadAll等操作,同时触发进入到Startup Two阶段

在这里插入图片描述

在这里插入图片描述

图12 BswM Startup One初始化列表
S9:BswM Startup Two阶段

对于进入到BswM Startup Two阶段,需要有如下两个条件满足:

  • BswM模式请求为ECUM_STATE_STARTUP_TWO;
  • 在Startup One阶段的Nvm_ReadAll确认已完成;

在这里插入图片描述

图13 BswM Startup One前置判断条件

成功进入到Startup Two阶段后,在该阶段需要进行剩余BSW模块的初始化工作,其中最为关键的是则是调用Rte_Start()函数来开启OS调度表调度。

在这里插入图片描述

在这里插入图片描述

图13 BswM Startup One前置判断条件
S10:RTE开启阶段

如上所示,调用RTE_Start函数是非常重要的一个步骤,因为该函数内部将会开启OS调度表,OS调度表的开启就意味着ECU已经接近于Full Operation的状态。

值得注意的是执行了RTE_Start函数,并不意味着OS调度表立马可以运行,而是需要OS Counter来进行驱动才行,此时仅表示调度表已处于激活Ready状态。

在这里插入图片描述

图14 RTE开启调度表条件

在正式启动过程中,Rte_TickCounter则是通过一个GPT Timer的回调中断函数来进行增加,前提是我们需要使能该Gpt 对应通道的中断通知函数,如果我们设定为1ms触发一次Gpt中断,那么Rte_TickCounter就每1ms增加一次,如下图15所示:

在这里插入图片描述

图15 Gpt定时中断回调函数
S11: OS调度表设置

通过上述的准备工作,我们便需要根据RTE生成的调度表来进行的OS中调度表配置,之所以RTE能够生成调度表,是因为RTE知道所有的Runnable 映射到task的关系以及各个Runnable的周期。

通过这些信息,RTE可以生成一个名为osNeeds.arxml文件,该文件可以用于作为RTA OS的输入文件。

一个调度表由一个或者多个Expiry Points来组成,每个Expiry Points包含一系列的task激活行为,如下图16所示为存在两个任务:

  • BSW任务:该任务需要每1ms调度一次;
  • ASW_Period任务:该ASW任务需要每10ms调度一次;

因此设置Expiry Points的数目则可以根据这些任务的调度周期最小公倍数来决定。

在这里插入图片描述

图16 OS调度表设置

如上图,在每个Expiry Point均会执行BSW函数,在Expiry Point 0以及Expiry Point 9两处需执行激活ASW_Period任务。

当Task被激活时,那么就会从Suspend状态切换至Ready状态,然后就由OS来查看优先级并调度高优先级任务,当一个任务被调度,它将从Ready状态切换成Running状态,一旦任务执行完,将会从Running状态切换成Suspend状态,然后OS将会调度其在Ready状态下的低优先级任务。

上述10个OS调度表的Expiry Point配置,需同步在如下选项中进行配置:

在这里插入图片描述

图17 OS调度表Expiry Point设置

正如前面提到的那样,该调度表由Rte_TickCounter来进行驱动,每当Rte_TickCounter增加1,那么OS将会移动一个Expiry Point,由于Rte_TickCounter每1ms增加一次,因此OS也是每1ms进行调度一次;

S12:OS问题调试技巧

在配置OS的过程中,可能多多少少会存在一些OS引起的系统崩溃错误,绝大多数错误是可以通过ETAS支持的ErrorHook函数接口来获得,当错误发生时,可以在Error_Hook函数中添加while(1)函数,这样便可以保留到现场调查问题,同时也可以获取到当前出问题的Task或者中断时哪个?

在这里插入图片描述

图18 OS ErrorHook函数捕捉问题现场

更多精彩内容,敬请关注公号:ADAS与ECU之吾见!

  • 3
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽车小T

感谢打赏,我会继续努力奉献精彩

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值