前言:在上篇中,我们主要描述了OSEK OS的相关内容以及AUTOSAR OS的OS Application对象的一些内容,包括Counter,Alarm,Enent,ISR,Task,Schudule Table等,本篇文章中,主要讲一下AUTOSAR OS的资源管理,分区,OS裁剪,OS保护,分区间通信,多核启动和下电,OS Error和Hook函数。
1、资源Resource
在AUTOSAR OS中,资源是一种为保护关键共享区域的数据结构,标识了该事物是否被占用,利用API函数GetResource(x)和ReleaseResource(x)来占用和释放资源。资源可以在Task和ISR中使用,在释放前不能被二次占用。
在上篇中讲过,在OSEK OS中天花板模式防止了资源死锁及优先级反转,AUTOSAR OS继承了天花板模式,即将访问共享资源的任务的优先级在占用资源的过程中提升至共享资源任务的最高优先级之上。
共享资源的申请者发现共享资源正在被占用时,会返回等待状态。
#include "0s.h"
TASK(Task1)
{
...
GetResource(Resourcel);
/* Critical section. */
ReleaseResource(Resourcel);
...
TerminateTask();
}
2、分区OS-Application
如下图所示,OS-Application是一系列对象(Tasks, ISRs, Alarms, ScheduleTables, Counters)的集合,每个Core可以有1-N个OS-Application,每个OS-Application包含0-M个对象,同一OS-Application内的对象可以相互访问,不同OS-Application的对象需要授权才能访问。
通常将一些基础软件层的模块的模式管理主函数映射到 Non-Trusted OSApplication中的任务,如: EcuM_MainFuction (), BswM-MainFuction (), CanMainFuction_Mode()等周期性查询函数,前提是这些模块的安全级别为QM。
OS-Application又分为Trusted OS-Application和Non-Trusted OS-Application。
Trusted OS-Application有以下特征:
- 运行在特权模式即supervisor mode
- 不需要监控和保护
- 无限制的访问内存资源和无限制访问OS API
Non-Trusted OS-Application有以下特征:
- 运行在用户模式即user mode
- 运行时需要监控和保护
- 只能访问部分内存资源
- 有限制的访问OS API(需要先陷入内核态)
3、OS裁剪及保护
3.1 OS裁剪
AUTOSAR OS在OSEK OS的基础上为不同的用户提供四类不同功能安全等级的OS可裁剪类型,分别为SC1-SC4。一般来讲SC1-SC4依次对应QM,ASIL B,ASIL C,ASIL D等级。
3.2 时间保护
实时操作系统需要在预定的时间内完成一些任务,但是在某些情况下会出现超时错误,因此,操作系统须采用一定的措施来预防超时错误的产生。这种措施称为时间保护。一个时间保护的方法是时间监控,即:当检测到某一任务运行时间超出其截止时间时,操作系统报错并调用相应的钩子(Hook)函数。AUTOSAR OS并不是采用监控截止时间的方式来进行时间保护的,因为对截止时间的监控并不能识别出引起错误的原因。当任务的执行超过截止时间时,任务本身的执行可能没有出错,而是由于受到其他任务或中断过于频繁的抢占或者过长的阻塞资源的访问而衍生出来的错误。这种情况下,如果采用监控截止时间的方式,则有可能结束正确的任务,而错误的任务仍被允许运行。
假设所有任务在0时刻就绪,则期望时序如下表和下图所示。由于任务A的优先级最高,故任务 A 先执行,1 个Tick之后任务B 执行,3个Ticks之后任务C执行,当任务C执行 1 个 Tick 后任务 A将其打断,任务A执行完毕后,任务C继续运行,到第 10 个Tick任务C执行完毕,周而复始,整个过程并未出现超时现象,并且有1个Tick的空闲状态。
下图给出了任务错误运行的状态。任务 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调用相应的HOOK函数,作出相应的错误处理。
3.3 内存保护
内存保护需要特定的硬件支持,即处理器上应该有MPU(Memory Protection Unit),英飞凌AURIX单片机具备该特性。内存保护可防止某些出错的应用程序影响到其他模块。内存保护分为以下三种形式:
1、栈保护(Stack Protection):每一个 OS Application 和其中的 OS Object 都有各自的私有栈,不同的 OS Object之间没有共享栈的存在。栈保护可以更快速地检测出栈上溢和栈下溢,同时,栈保护是划分OS Application的一种方式和依据。
2、数据保护(Data Protection):OS Application 和其中的 Objects 都具有各自的私有数据,OS Application 的私有数据区是从属于该OS Application 的Objects 的共享数据区。
3、代码保护(Code Protection):代码区既可以为 OS Application 所私有,也可以被共享。在没有代码保护的情况下,错误的代码执行会导致内存、时间和服务上的出错。
OS 通过 MPU 监控内存的访问权限,AUTOSAR 中的访问权限分为:受信任 Object 的和非受信任的Object(Trusted and Non Trusted)两级。受信任的Object 有读写大部分内存的权限,但是没有读取其他非激活栈的权限。非受信任的Object 仅有读写少数内存的权限,包括当前活跃的栈、当前OS Application的数据以及LMU中的共享数据。
3.4 服务保护
由于OS-Application可以通过服务与操作系统模块交互,因此服务调用不会破坏操作系统模块本身是至关重要的。服务保护在运行时防止此类损坏。有许多情况需要考虑服务保护,如当OS-Application进行以下API调用时:
- 句柄无效或值超出范围;
- 在错误的上下文中,例如在StartupHook中调用ActivateTask;
- 或者调用API失败,导致OSEK操作系统处于未定义状态,例如,没有调用ReleaserResource就终止了;
- 影响系统中所有其他OS-Application的行为,如操纵属于另一个OS-Application(没有权限)的操作系统对象。
OSEK操作系统已经通过从服务调用返回的状态码提供了一些服务保护,这将为服务保护提供基础。这意味着服务保护只适用于OSEK操作系统的扩展状态。但是,OSEK OS并没有涵盖上面列出的所有情况。
4、分区间通信IOC
IOC是Inter OS-Application Communicator的简称,IOC有以下特征:
- 当不同核的或者同核有内存保护等权限隔离的OS-Application进行数据交互时,需要使用IOC通信机制来完成
- IOC属于OS内核的一部分,当进行IOC通信时会先陷入内核态绕过内存保护,再在OS内核中开辟一片空间用于缓存交互的数据,然后不同OS-Application访问内核中的缓存进而完成数据读写
- 同一OS-Application中数据交互不建议用IOC,IOC效率较低
- 非Queue形式使用API:IocWrite/IocRead。Queue形式使用API:IocSend/IocReceive
- 支持1:1,1:N,N:M的通信方式
- 锁机制保证数据一致性。通信时内部可以使用自旋锁Spinlock(GetSpinlock/ReleaseSpinlock)和挂起II类中断保护临界区
- IOC发送完成可以触发回调函数
- Cache机制可能导致核对变量的读写只保存在Cache中,并未同步到内存,其他核访问该变量时可能会出现数据不一致问题,因此多核访问共享数据时必须要关闭Cache机制
关于自旋锁,对执行时间较长的任务,不宜申请占用自旋锁,以防止对其他内核的资源浪费。如果低优先级的任务在占用自旋锁的情况下被高优先级任务抢占,如果高优先级任务也需要申请占用同一个自旋锁,根据自旋锁的设定,其必须等待低优先级任务将其释放,而根据AUTOSAR OS任务调度机制,高优先级不可能被低优先级打断,故此时内核会陷入死锁状态。AUTOSAR OS为了上述情况发生,在任务或中断占用自旋锁时,操作系统会自动挂起(屏蔽)所有中断,即某任务成功申请占用自旋锁后,不会被同一内核上的任何任务(任务也是来自中断触发)或中断抢占。
Send-Receiver通信

如上图,Core0中SWC将数据发送至Core1中的SWC模块,分区间通信的具体步骤如下:
- 接收端实体被周期性调用通过Rte_Receive从RTE接收来自Core0的数据;
- 发送端调用函数Rte_Send函数发送数据,进而调用Ioc_Send函数写入数据到Buffer中;
- 接收端便会通过Ioc_Read函数读取共享内存中的Buffer数据,并传递给到Rte_Read函数中供Core1中的SW-C使用。
Client-Server通信

上图为Core 0 中的SWC请求Core1中的服务操作。RTE通过将Client-Server调用映射为send-Receiver来实现客户端的服务(事实上IOC不支持Client-Server),RTE调用IOC将数据从Core0传输至Core1,传输过程如下:
- 发送端调用函数Rte_Call函数进而调用函数IocSend函数,将数据写入IOC内部队列缓存中;
- Rte_Call函数使用OS调用激活接受核的服务任务来通知接收端;
- 接收端被激活的该任务将负责调用IocReceive函数从IOC共享内存Buffer中读取数据并将数据传输至服务端的运行实体中;
- Core1中服务函数的结果会被反向传输至Core0的客户端中。
带通知的适用二类中断ISR来通知Receivers数据已经到达共享buffer,能保证Receiver及时的取得数据。
5、多核系统
在AUTOSAR多核系统中,所有核共享一套OS代码和数据结构,但每个核有自己的OS数据对象,如Tasks、ISRs、Alarms、 Resource等等,且每个核的数据对象相互独立唯一。
主核和从核
- 主核:芯片复位/上电时自动启动的核
- 从核:芯片复位/上电时核处于非运行状态,需要主核激活后才能运行
- 主核只有1个,从核可以有很多个,每个核的OS调度是独立的、并行的
5.1 多核启动
芯片复位/上电后,硬件会启动主核,然后激活从核。
如上图所示,Core 0作为主核,其他核作为从核。启动过程如下:
- 主核Core 0完成前期的硬件初始化之后启动从核Core 1 ,然后调用StartOS来启动OS,OS完成初始化之后在第一个同步点等待所有从核完成OS的启动;
- 从核Core 1被主核启动之后,首先完成硬件相关的初始化,然后激活从核Core 2,Core 3,并在第一个同步点等待其余从完成OS的启动;
- 从核Core 2,Core 3被Core 1激活之后,首先完成各自的硬件相关初始化,然后调用StartOS完成OS的初始化并在第一个同步点进行同步;
- 在完成第一个同步点之后,主从核便分别执行Startup Hook函数之后在第二个同步点进行同步,然后所有核的Kernel将一起运行,开始任务调度。
5.2 多核关闭
如上图所示,下电流程如下:
- 主核调用ShutdownAllCores触发所有核开始下电
- 下电过程会经历一次同步,即等待所有核关闭OS后同步进入ShutdownHooks
- 主核在ShutdownHook中调用SBC接口控制ECU下电
6、Hook函数和OS Error
6.1 Hook函数
Hook函数是OS中定义的且被OS调用的一种钩子函数,用户可以在Hook函数中实现具体的逻辑。Hook函数提供了获取OS内核运行时关键信息的一种方法。
OS所有的Hook函数及访问权限:
StartupHook
系统StartupHook在多核启动时第一次同步后调用
StartupHook_<App>
分区StartupHook_<App>在系统StartupHook执行后调用(如果配置了)
ShutdownHook
系统ShutdownHook在OS下电同步后执行
ShutdownHook_<App>
分区ShutdownHook_<App>在OS下电同步后顺序执行在系统ShutdownHook后面
6.2 OS Error
可以OS Error分为三种类型:Application Error,Kenel Error,Protection Error。了解OS Error类型,有助于我们调试分析OS问题。
Error类型 | 描述 | 发生场景 | OS内核数据是否损坏 | 调用Hook函数 | 采取措施 |
Application Error | 调用OS API条件不满足时触发 | 调用OS API时传入的参数有误;调用OS API的上下文不对;服务保护权限不通过... | 否 | 先调用ErrorHook,再调用ErrorHook_App(如果已配置) | 在Hook函数中根据错误类型具体对待 |
Kenel Error | OS内部代码或数据被破坏不能正常运行 | OS内核代码执行非法指令.. | 是 | Os_PanicHook | 停止系统运行 |
Protection Error | 程序进入到异常状态不能继续运行 | 发生Trap;发生内存保护;发生时间保护;发生栈溢出... | 否 | ProtectionHook | 可选措施:1.不处理,返回继续运行;2.强制发生的任务或II类中断;3.强制终止发生错误分区内的所有任务和II类中断;4.强制终止分区内的所有任务和II类中断,然后重启分区 |
7、总结
本篇主要对AUTOSAR OS的资源,分区,保护以及多核的启动与关闭进行了介绍。不同裁剪类型具备不同种类的保护功能,用IOC机制完成分区间的通信。利用GetResource(x)和ReleaseResource(x)来保证核内数据的一致性,可以用自旋锁Spinlock(GetSpinlock/ReleaseSpinlock)和中断锁来保证核间数据的一致性(若是原子操作则不需要这些手段)。
参考文档:《AUTOSAR_CP_SWS_OS》《RTA-OS User Guide》《ATOSAR多核操作系统及其应用》