什么是OSEK/VDX?
OSEK,是指德国的汽车电子类开放系统和对应接口标准(Open Systems and their Interfaces for the Electronics in Motor Vehicles),而VDX则是汽车分布式执行标准(Vehicle Distributed Executive),后者最初是由法国独自发起的,后来加入了OSEK团体。 词条来源:百度百科
OSEK OS描述了一种应用于汽车的实时操作系统概念。不同的相似类(Conformance classes),不同的调度机制和配置功能使得OSEK OS适用于广泛的应用程序和硬件。
01
—
OSEK OS架构
OSEK OS为用户提供了一组定义好的接口,这些接口由占用CPU的实体(Entities)来使用。实体有两种类型:
1)ISR (Interrupt Service Routines)
2)Task(Basic Tasks and Extended Tasks)
OSEK OS定义了3个处理等级:
1)中断级(Interrupt level )
2)调度器的逻辑级别(Logical level for scheduler)
3)任务级(Task level,task根据分给其的优先级来进行调度)
OSEK OS处理等级
优先级规则:
相似类(Conformance classes):
Conformance classes的最低要求
注:
BT - Basic Task
ET - Extended Task
(Basic Task,Extended Task是什么?请接着往下看)
02
—
任务管理
OSEK OS提供了两种任务概念:
基本任务(Basic Tasks)状态模型:
状态跳转描述:
扩展任务(Extended Tasks)状态模型:
状态跳转描述:
注:
任务只能自我终止(self-termination),这种限制降低了操作系统的复杂性。
任务优先级:
0代表任务最低优先级,数字越大优先级越高。为了提高效率,在OSEK OS中动态优先级管理是不允许的(任务的优先级是静态定义的,用户在执行时不能更改它)。
在BCC2和ECC2中支持优先级相同的任务。具有相同优先级的任务会根据其激活顺序启动,处于等待状态的扩展任务(Extended Tasks)不会阻止相同优先级的其他后续任务的启动。
被抢占的任务(Preempted task)被放在其优先级就绪任务队列的第一个(最旧的),从等待状态释放的任务被放在其优先级就绪队任务列中的最后一个(最新的)。
示例:
如上图所示,不同优先级的一些任务都在就绪状态(Ready state),三个优先级为3的任务,一个优先级为2的任务,一个优先级为1的任务,两个优先级为0的任务。调度任务时,首先会找到优先级最高的就绪队列,然后再找到当前队列里最旧的任务(图中即为标注“next task to be processed”的任务)执行,然后再执行这个任务后面的任务,只有当优先级为3的队列中的任务都执行完成,才会执行优先级为2的队列中的任务,依此类推。
调度策略:
完全抢占示意(T1优先级高于T2)
非抢占示意(T1优先级高于T2)
03
—
中断处理
处理中断的功能(中断服务例程:ISR)分为两类:
OSEK提供了关闭所有中断的API:
DisableAllInterrupts和ResumeAllInterrupts
仅关闭2类中断的API:
ResumeOSInterrupts和SuspendOSInterrupts
这些API典型的用法是用于临界区(Critical Sections)的保护。
04
—
事件(Event)机制
事件机制:
事件是将扩展任务从等待状态转换(Waiting)为就绪状态(Ready)的标准。OS提供设置,清除,询问事件以及等待事件发生的服务。
任何任务和2类中断都可以为未挂起的扩展任务设置事件,但只有事件的所有者(Owner)才能清除事件。
示例1(完全抢占式,优先级T1>T2):
T1在等待事件到来,T2在执行,某一时刻T2把T1的事件给置起来了,这时候由于T1优先级高,调度器立即调度执行T1,某一时刻T1清除了事件,然后到某一时刻又开始等待事件,这时候会再次发生调度,执行T2。
示例2(非抢占式,优先级T1>T2):
与完全抢占式对比,调度不会在事件置起来后立刻执行。
05
—
资源管理
资源管理用于协调具有不同优先级的几个任务对共享资源的并发访问,例如管理实体(调度器)、程序序列、存储器或硬件区域。
资源管理对所有相似类(Conformance classes)都是强制性的。
资源管理主要是为了防止一些非预期情况的发生,例如优先级反转(Priority inversion)和死锁(Deadlocks)等。
优先级反转(Priority inversion):
如上图所示,先设定T1有最高优先级,T4有最低优先级,T1和T4共享信号量1,某一时刻T4先运行并且占用信号量1,随后某一时刻T1进入就绪状态,调度发生,T1开始运行,在运行过程中的某一时刻需要请求信号量1,但此时信号量1被T4占用所以T1进入等待状态,但此时优先级比T4高的T2和T3都就绪,所以T4会先等待T2和T3运行完毕,等T2和T3运行完以后,由于T1需要的信号量1仍然被T4占用着,所以要等T4运行完以后T1才能运行。这种情况就是优先级反转,高优先级任务由于所需资源被低优先级任务占用,需要等待资源释放反而成了最后执行的任务。
死锁(Deadlocks):
如上图所示,设定T1优先级高于T2优先级,T1先运行并且占用了信号量1,在某一时刻等待事件,此时T2开始运行并且占用了信号量2,随后T1等待的事件被置起,T1又开始运行,某一时刻T1请求信号量2而此时信号量2被T2占用,所以T1进入等待状态T2开始运行,T2运行某一时刻请求信号量1,但此时信号量1被T1占用,于是出现两个任务同时占用对方所需资源而陷入一种两个任务都无法运行下去的情况,这种情况就是死锁。
OSEK优先级上限协议:
系统生成时,每个资源会被静态分配其上限优先级。
示例一(优先级:T0>T1>T2>T3>T4,可抢占式,T1和T4请求相同的资源):
如上图所示,T4先运行,在某一时刻T4请求了资源,此时T4的优先级会被提至上限优先级,即使T1准备就绪T4还是会接着运行而不会被抢占,由于中途T0准备就绪,而T0不使用资源,所以T4的执行会被T0打断,当T0运行完后T4继续运行,直到某一时刻释放了资源,这时候T4优先级降到原来,T1优先级最高,T1运行。这样就不会出现因为T4占用T1所需资源导致T1被阻塞,等T2,T3,T4运行完以后才能运行的优先级反转问题。
将资源管理扩展到中断级别是可选的。
示例二(任务优先级T3>T2>T1,中断优先级INT2>INT1,T1和INT1共享资源):
如上图所示,T1在运行中并且请求了资源,后面中断服务INT1发生了,由于优先级上限协议,T1继续运行,然后INT2发生了,由于INT2不使用资源,所以T1被打断,INT2开始运行,INT2运行完后T1继续,然后T1释放了资源,中断服务INT1在pending状态,此时由于资源释放INT1转入运行态,运行完后优先级较高的T3,T2先后运行完,最后T1才继续运行。
06
—
Alarms
以“Ticks”为单位,基于计数器,OSEK OS给应用软件提供了Alarm机制。
OSEK OS提供激活任务、设置事件或当Alarm到期时调用Alarm回调例程的服务。
当达到预定义的计数器值时,Alarm将到期。该计数器值可以相对于实际计数器值(Relative alarm)定义,也可以定义为绝对值(Absolute alarm)。例如,Alarm可能在接收到多个定时器中断时、到达特定角度位置时或接收到消息时到期。
Alarm可以定义为单个Alarm或者循环Alarm,OSEK OS还提供了取消Alarm和获取Alarm当前状态的服务。
Alarm在系统生成时静态分配给一个计数器(Counter),一个任务或者Alarm回调例程。
根据配置,当Alarm到期时,Alarm回调例程被调用,或者任务被激活,或者任务的一个事件被置起。
计数器和Alarm是静态定义的。Alarm到计数器的分配,以及Alarm到期时要执行的操作也是静态定义的。动态参数是Alarm到期时的计数器值,以及循环Alarm的周期。
Alarm回调例程的原型定义为:
ALARMCALLBACK(AlarmCallbackRoutineName);
示例:
/* Example */
ALARMCALLBACK(BrakePedalStroke)
{
/* do application processing */
}
参考文献:
OSEK/VDX Operating System Version 2.2.3