首先,请问大家几个小小的问题,你清楚:
你知道多核OS在什么场景下使用吗?
多核系统OS又是如何协同启动或者关闭的呢?
AUTOSAR OS存在哪些功能安全等方面的要求呢?
多核OS之间的启动关闭与单核相比又存在哪些异同呢?
。。。。。。
今天,我们来一起探索并回答这些问题。为了便于大家理解,以下是本文的主题大纲:
在上篇文章AUTOSAR基础篇之OS(上)中我们可以了解到AUTOSAR OS的基本特点,基本对象以及各个对象之间的彼此关联,本篇文章将承前启后,在此基础上来简单谈谈我对AUTOSAR 多核OS的理解与认识。鉴于本人水平能力有限,如存在错误之处,还请大家多多批评指正。
我们已知道AUTOSAR OS来源于OSEK OS,随着汽车电子信息安全,功能安全等需求的不断提出,传统的OSEK OS已无法满足当前的需求,因此AUTOSAR组织在OSEK OS的基础上为不同的用户提供四类不同功能安全的OS可裁剪类型,分别为SC1-SC4。
AUTOSAR OS 可裁剪类型
AUTOSAR OS的四种可裁剪类型分别为SC1-SC4,具体含义如下:
SC1: OSEK OS + Schedule Table;
SC2: OSEK OS + Schedule Table + Timing Protection;
SC3: OSEK OS + Schedule Table + Memory Protection;
SC4: OSEK OS + Schedule Table + Timing Protection + Memory Protection;
如下图1所示,较为清晰了描述了这四种不同可裁剪类型的区别与联系。
AUTOSAR OS 时间保护
从AUTOSAR OS四种可裁剪类型可以看出,时间保护(Timing Protection)是一项非常重要的功能保护机制。如之前文章所示,AUTOSAR OS作为一实时操作系统,那么就需要在预定的时间内完成特定的任务,但有时由于某些原因导致超时错误,OS必须采用有效的方式来预防超时任务的发生,而这类措施则可以称为时间保护。
一种较为常见的时间保护就是Deadline Monitoring。即当OS检测到某一任务的运行时间超过其截止时间时,则会调用相应的Hook函数向系统报错,但是AUTOSAR OS并不是通过监控截止时间方式来实现时间保护的,因为针对截止时间的保护并不能准确识别出当前错误的原因。具体解释如下:
现象:任务1的运行时间超过其截止时间时,任务A本身可能并没有出错;
过程:在执行任务1之前的任务2频繁的抢占或者过长的阻塞资源的访问;
原因:正由于任务2的上述行为,进而导致任务1执行超时,从而直观的认为任务1发生错误便停止任务1,反而让真正的罪魁祸首任务2继续逍遥法外,这就不合情理,也起不到对OS中各任务的时间保护。
下面为了进一步加强大家对上述简单的监控截止时间造成运行错误的理解,假设存在一个操作系统中存在下列任务A,B,C,并明确各自任务的优先级,执行时间,Deadline 如下表1中所示:
假设所有任务在0时刻均处于就绪状态,期望运行的任务执行时序如下图2所示。具体的任务执行时序如下所述:
由于任务A优先级最高,因此任务A先执行;
1个Tick之后任务B开始执行,3个Tick之后任务C执行;
当任务C执行1个Tick后被任务A打断,任务A执行完毕后,任务C继续运行;
到第10个Tick任务C执行完毕,周而复始,整个过程并未出现超时现象,并且仍有一个Tick的空闲状态;
接下来,如果发生如下图3所示的异常状况,那么我们看会发生什么呢?
任务A的第二个周期与任务B的第一个周期都出现运行时间过长的现象,但并没有超过其截止时间。
任务B在第二个周期提前进入运行状态,但也未超过其截止时间;
任务C按照正确的方式运行,但由于任务A与任务B的出错导致任务C运行超时,则发生超时错误;
若此时采用简单的超时监控机制只能监控到任务C超时,这时操作系统调用钩子函数,由于出错原因并未被检测到,从而操作系统采取的措施将无法有效解决错误。
因此,从上述例子分析可以得出任务或者中断能否满足其截止时间需取决于以下三大基本要素:
1.静态任务或者中断的执行时间上限;
2.被低优先级任务锁住共享资源或屏蔽中断所引起的阻塞时间;
3.任务或者中断之间的间隔执行时间;
针对上述三大基本要素,AUTOSAR OS采取了下列三种时间保护机制:
对于1:AUTOSAR OS为任务或者二类中断服务设定了运行时间上限;
对于2:AUTOSAR OS设定了共享资源被任务或者二类中断锁定的时间上限,设定了OS中断被任务或者二类中断中断挂起的时间上限,设定了所有中断被任务或者二类中断挂起或者屏蔽的时间上限;
对于3:AUTOSAR OS设定了任务或者二类中断执行间隔的时间下限;
特别的,需要注意的是AUTOSAR OS时间保护存在一些基本特性:
时间保护仅仅用于任务或者二类中断,对于一类中断不起作用;
在OS未开启之前,时间保护将不起作用;
对于Trusted OS Application, OS应当有能力提供一种基于任务或者二类中断的时间保护,而对于Non-Trusted OS Application,OS必须提供为这个非信任的OS Application中的每一个任务或者二类中断提供时间保护;
AUTOSAR OS内存保护
AUTOSAR OS的内存保护需要特定的硬件支持,即处理器应该存在MPU单元(Memory Protection Unit), 例如英飞凌AURIX单片机则具备这个特性。鉴于内存保护可以有效防止出错的应用模块影响到其他模块,降低系统完全瘫痪的风险,因此,AUTOSAR OS提供以下三种形式的保护:
栈保护
即每一个OS Application和其中的OS Object都有各自的私有栈,不同的OS Object无需存在共享栈。栈保护能够更为快速的检测出栈溢出,同时栈保护也是划分OS Application的一种方式和依据。
数据保护
每一个OS Application和其中的Objects都具备各自私有数据,同时OS Application的私有数据区就是从属于该OS Application的Objects的共享数据区;
代码保护
代码区既可以被私有,也可以被共享,在没有代码保护的前提下,错误代码的执行会导致内存,时间和服务上的出错。
OS通过MPU监控内存的访问权限,其中AUTOSAR的访问权限可分为受信任与非受信任的Object(Trusted and Non Trusted)两级,受信任的Object有读写大部分内存的权限,但没有读取其他非激活栈的权限。
而非受信任的Object仅有读写少数内存的权限,包括当前活跃的栈,当前OS Application的数据以及LMU的共享数据。
在AUTOSAR软件基本架构下,无论是单核操作系统还是多核操作系统,都与EcuM模块和BswM模块息息相关。因为这两类模块决定了OS启动,初始化,运行,关闭等状态及其过程。
从之前文章AUTOSAR基础篇之EcuM我们可以知道ECU工作过程可分为启动(STARTUP), 运行(UP), 睡眠(SLEEP)以及关闭(SHUTDOWN)四种状态。
ECU在上电前处于SHUTDOWN阶段,上电后便进入STARTUP阶段,主要包括StartPreOS与StartPostOS两个子阶段。
在StartPreOS子阶段主要完成一些OS启动之前的一些准备工作,如初始化MCU,IO,WatchDog等模块;
在StartPostOS子阶段则是启动OS之后的阶段,该阶段主要执行初始化BSW的调度器以及初始化BswM模块两个动作,如下图4所示。
由于ECU详细的启动过程在AUTOSAR基础篇之EcuM文章中已有大量篇幅介绍,本文就不再赘述,只是作为一个引子,大家如果有兴趣,可以阅读了解一下。
多核OS启动过程
当然无论是否存在OS,多核的启动过程相比单核与硬件关系则更为密切。
通常情况下,硬件会首先启动一个核作为主核(Master Core),而从核(Slave Core)则由软件启动,这种启动方式被称为主从模式。AUTOSAR规范定义了多核启动方式应该为主从模式。
值得注意的是:即使硬件支持多核同时启动,AUTOSAR规定也需要通过软件模拟的方式来实现主从模式来启动多核系统。
如下图5所示,非常生动形象的描述了主从模式的各个环节的启动时序及相互之间的交互关系。
在上图中,Core 0作为主核,其他核则作为从核。
主核Core 0完成前期的硬件初始化之后启动从核Core 1 并随后调用Start OS函数来启动OS,OS完成初始化之后在第一个同步点等待所有从核完成OS的启动。
从核Core 1被主核启动之后,首先完成硬件相关的初始化,然后激活从核Core2,Core3,并在第一个同步点等待其余从完成OS的启动;
从核Core2,Core3被Core 1激活之后,首先完成各自的硬件相关初始化,然后调用StartOS完成OS的初始化并在第一个同步点进行同步;
在完成第一个同步点之后,主从核便分别执行Startup Hook函数之后在第二个同步点进行同步,然后所有核的Kernel将一起运行,只有这样才能够更好的保证整个系统的稳定性与鲁棒性。
值得注意的是如果某从核运行的OS不是AUTOSAR OS时,此时则不能使用AUTOSAR OS API StartCore来启动该从核,而应当使用StartNonAutosarCore来实现该从核的启动。
多核OS关闭过程
与单核OS关闭过程类似,多核OS的关闭也是通过EcuM来完成,如果在关闭过程中出现唤醒事件,ECU则需要关闭之后立即重启。
在关闭过程中可以选择ShutDown Target分别为关闭(OFF), 睡眠(Sleep),和复位(Reset),
如上图的ECU关闭过程主要分为以下几个阶段:
反初始化BswM以及BSW调度器;
检查是否存在唤醒事件发生;
选择ShutDown Target;
关闭OS;
如下图7所示,则较为生动形象的描述了多核OS的关闭过程。
在多核系统中,关闭过程存在以下几个特点:
AUTOSAR4.x不支持仅仅关闭单个核,即若发送关闭指令或者致命错误时所有核必须全部关闭,具体的关闭过程如上图所示;
若某一任务拥有调用ShutDown All Cores的权限时,关闭信号将会同步发送至所有核;
当关闭过程启动后,所有的中断服务和任务都不能被激活,关闭前必须完成的程序由EcuM保证完成;
关闭完成前,各自的OS Application调用各自的Shutdown Hooks函数完成对应的回调程序,然后等待到同步点所有核执行关闭回调函数。
基本特点
多核OS调度相比单核OS调度而言并没有什么区别,都是根据任务或者中断的优先级作为首要因素来决定调度顺序。在同一处理器内核上,优先级越高的任务或者中断优先调度。如果优先级相同,那么就根据激活顺序进行调度。
需要明白一点的是对于单核系统,CPU每时每刻只能运行一个任务或者中断,采用时间片轮转法来实现看上去的并发执行。
对于多核系统而言则不同,由于存在多核所以可以同时运行多个任务或者中断,至于能够同时运行几个任务或者中断由CPU内核数量来决定,我们把这种执行方式称为并行执行。
同时对于AUTOSAR操作系统而言,任务及中断的优先级是提前静态分配的,在运行过程中不支持动态更改。
调度方式
如下图8所示,清晰的表现了 多核OS调度任务的过程。根据调度规则,若在同一核上多个任务被同时调度,即这些任务均处于就绪状态,那么高优先级任务会被率先执行,如图中的Core0上的任务T2,Core1上的任务T3以及Core2上的任务T5,三个任务同时进入运行状态,各个内核上的任务独立运行,互不干扰,其优先级并没有相互影响。
同时,对于AUTOSAR 多核OS支持任务选择调度模式,可分为全调度和拒绝调度模式。对于全调度模式,任务在运行过程中,可以被高优先级的任务或者中断抢占,而对于拒绝调度模式下,该任务不能够被任何其他任务或者中断抢占。
因此在任务分配优先级的过程中,应当将起到关键作用的重要任务分配较高的优先级,重要程度类似的任务周期越短,分配的优先级越高。
AUTOSAR规范定义了内部通信与外部通信两种方式,其中内部通信包括核内通信,核间通信。
每当不同内核中的用用程序需要进行数据交互时,操作系统就需要开辟单独的内存区域,通信双方可以实现该内存区域的读写,从而完成数据的传输。
但需要注意的是共享内存区域有可能在读取数据的过程中发生数据更新,这样就会发生数据一致性问题。
为解决上述数据不一致问题,AUTOSAR多核OS提供了应用于核间通信的IOC(Inter OS Application Communication)通信机制。
IOC不同于核内通信,核内通信则是通过RTE来实现。
在使用IOC的过程中如果应用程序对这一共享内存区域进行读写时,会申请占用一个自旋锁(SpinLock),以防止被其他内核的应用程序同时访问,这样便可以保证核间数据读写的一致性。
IOC仅提供Send-Recerver的通信方式,但是RTE可以将Client-Server的请求与应答可间接转换为Send-Recerver模型,因此IOC支持1:1,1:N,N:M的通信。
在每次传输过程中可以传输一个数据项,该数据项可以是基本类型的值或者复杂数据结构的参考,而如果是复杂数据结构,那么就必须被实现为单个内存块,这样IOC便无需得知内部的数据结构 ,仅需知道内存地址和长度便可以完成该结构体数据的传输。
Send-Receiver模型
如下图9所示为也不带通知的1:1的Sender-Recerver的通信模型。
如上图,Core0中SW-C将数据发送至Core1中的SW-C模块,以下是核间通信的具体步骤:
接收端实体被周期性调用通过Rte_Receive从RTE接收来自Core0的数据;
发送端调用函数Rte_Send函数发送数据,进而调用Ioc_Send函数写入数据到Buffer中;
接收端便会通过Ioc_Read函数读取共享内存中的Buffer数据,并传递给到Rte_Read函数中供Core1中的SW-C使用。
IOC生成器会生成所有的发送及接受函数,为了优化目的,这些函数被定义为宏指令,这种不带通知的通信方式适用于以下场景:
Send/Receiver通信;
队列或非队列通信;
1:1通信;
Client-Server模型
如下图10所示,为带通知的N:1的Client-Server模型。
如上图为Core 0 中的SW-C请求Core1中的服务操作。RTE通过将client-Server调用映射为send-Receiver来实现客户端的服务,因为需要跨核通信,所以RTE调用IOC将数据从Core0传输至Core1,具体传输过程如下所示:
发送端调用函数Rte_Call函数进而调用函数IocSend函数,将数据写入IOC内部队列缓存中;
Rte_Call函数使用OS调用激活接受从核的服务任务来通知接收端;
接收端被激活的该任务将负责调用IocReceive函数从IOC共享内存Buffer中读取数据并将数据传输至服务端的运行实体中;
Core1中服务函数的结果会被反向传输至Core0的客户端中。
这种带通知的通信方式适用于以下场景:
带通知的Send-Receiver通信;
Client-Server通信,在此类情况下,RTE需要将服务转换为1:1的Send-Receiver模型通信,同时将服务结果反向传输到客户端的过程转换为另外一组Send-Receiver通信;
队列或者非队列通信;
1:1通信,如果接受端没有被周期性的调用;
N:1通信;
核间元素交互与任务同步
我们知道多核OS由任务,中断,报警器和事件等元素组成,它们之间的相互作用使得操作系统能够有条不紊的运作。
从一般意义上来讲,AUTOSAR OS本质上就是基于事件驱动的操作系统。如下可简要描述核间各元素的交互关系:
报警器可以激活基本任务A或者设置某事件1;
扩展任务B等待事件1那边可以激活基本任务C;
基本任务C可以设置某事件2,中断可以设置某事件3;
扩展任务D等待事件2和事件3之后便可以开启执行;
基本任务E可以通过IOC机制实现与基本任务A之间的数据交互;
如上可知,在多核OS中事件是可以跨核传输的,这也就意味着核与核之间的同步可以通过事件触发的方式来实现。
如下图11所示,当Core0中的任务T1执行时,可以通过设置Event来激活位于Core1中的T2,这样便完成了T1与T2之间的任务同步,该方法适用于事件触发的任务或者定期执行的任务之间的同步,当然如果是定期执行的任务只需使用Alarm或者调度表定期触发Event即可。
除此以外,我们还可以通过调度表来实现任务同步,由于报警器只能一次触发一个任务,因此不能实现任务同步,而调度表则可以实现同时触发不同核的多个任务,而该方法仅用于定期执行的任务的同步。
推荐阅读
特斯拉最新中央计算模块(CCM)解析
关于对自动驾驶传感器的理解
特斯拉的电池管理系统 (BMS) 相比其他电动车有哪些优势?
2021款特斯拉Model Y ECU接口梳理
详解CANoe之CAPL编程
关于CAN时间同步的理解
dbc文件的格式以及创建详解
大众ID.4 X网络架构详解
学习笔记——NVM数据处理机制
学习笔记——AUTOSAR NVM基础知识
基于UDS的Bootloder详解
关于整车上下电流程的理解
一文详解CAN总线错误帧|附下载
DoIP协议介绍,资料分享!
详解车载网络 OTA系统的开发|文末附下载
一文了解汽车嵌入式AUTOSAR架构|附下载
特斯拉Autopilot系统安全研究|附dbc下载