OSEK-V:硬件定制RTOS
本文提出OSEK-V,一种将实时操作系统语义硬件化的方法。通过系统级分析提取应用特定的有限状态机,并将其集成到RISC-V处理器流水线中,实现低延迟、高可预测性的实时控制。该方法显著降低中断锁时间与系统调用开销,适用于汽车等安全关键嵌入式系统。
OSEK‐V:应用特定的实时操作系统硬件实例化
1. 引言
本文探讨了嵌入式控制系统中硬件与操作系统之间的边界。我们的现代生活由大量这类专用系统[30]驱动:仅在汽车中就已能找到超过一百个这样的系统[5],,家用电器中也有数十个,而物联网(IoT)等趋势将进一步提升它们在日常生活中的作用。
嵌入式控制系统通常需要在信息物理上下文中完成特定的预定任务,且经常需满足严格的 安全性 和时序要求。由于这些系统被用于大规模生产的产品(如汽车)中,因此单个单元的成本压力较高。因此,即使使用系统软件,也通常采用编译时可定制的实时操作系统(RTOS),但在许多情况下,开发人员会尽量避免使用即使是小型RTOS内核带来的开销。与RTOS相比,使用裸机软件或分立硬件的解决方案通常更难以分析/预测,并导致更高的事件延迟和内存开销。另一方面,RTOS提供的抽象(例如,优先级已实例化的线程、报警、资源等)显著简化了更复杂且可组合的控制应用的开发。然而,即使在软硬件协同设计的情况下,我们仍经常看到一种全有或全无的方法:工程师要么避免使用实时操作系统抽象(这会使软件开发复杂化),要么将完整的实时操作系统作为(昂贵的)标准软件组件进行实例化。
在本文中,我们通过结合两者的优势来解决软硬件协同设计中的全有或全无差距:其思想是保留RTOS接口以实现简单且可组合的应用开发,同时积极地将其实现根据具体应用的独特使用模式直接定制到硬件中。
将操作系统(或其部分)推进(定制)硬件以改善事件延迟的想法,是一个长期存在的研究领域(例如,[6, 3, 21, 24, 15, 11])。与以往的工作相比,我们基于全系统方法对操作系统和硬件进行了更紧密的定制:不是在中央处理器之外将专用组件(如调度器)实例化为额外的硬件设备,而是将实时操作系统语义直接集成到CPU流水线中。实际上,具体的实时操作系统交互模型(实际使用的系统调用及其调用点上下文)成为处理器指令集和寄存器文件的高效且面向应用程序的扩展。这种直接的处理器集成避免了完整RTOS的成本,同时展现出在现代架构上纯软件难以实现的特性:所有RTOS交互均可实现完全可预测的时序(仅需几个处理器周期),无内核引起的缓存逐出,显著减少的中断锁定时间。从安全性的角度来看,对RTOS的严格定制减少了其“滥用能力”,而硬件中的实例化则有效消除了向内核域注入代码的可能性。结合内存保护机制(本文未涉及),可在不执行内核代码的情况下实现完全隔离。
在之前的研究中,迪特里希等人[9]提出了一种静态跨内核和全系统分析方法,以及一种基于应用程序特定有限状态机(FSM)的内核实现[8]。
通过本文,我们提升了系统分析的效率,将基于有限状态机的表示集成到实际的处理器流水线中,并在硬件级别对系统组件进行了进一步的定制优化。具体而言,我们提出以下贡献:
- 我们提出了一种方法,将具体RTOS实例的语义捕获为有限状态机,以实现高效的硬件实现。
- 通过将标准RTOS接口应用特定化地实例化到处理器流水线中,我们实现了较低的系统调用和中断延迟。
- 整个定制过程完全自动化;根据需求生成硬件和软件变体。
- 我们的开源实现OSEK‐V涵盖了汽车领域的OSEK/AUTOSAR实时操作系统标准,并将其面向应用程序的语义集成到Rocket RISC‐V核心中。
本文的其余部分组织如下:第2节描述了系统模型,并概述了我们的方法:从应用程序开始,在第3节中推导出系统状态机,并在第4节中将其集成到中央处理器流水线中。我们在第5节以一个实际的飞行控制应用为例对所提出的方法进行评估,在第6节讨论结果,在第7节概述更多相关工作,最后在第8节进行总结。
2. 系统模型与思路
我们假设一个采用固定优先级调度的静态实时控制系统:一个应用程序与一个静态配置的实时操作系统(所有线程和中断处理程序在编译时均已知或可推导)结合,并以系统镜像的形式交付。此外,我们假设应用程序结构是静态的(无动态代码加载,不通过复杂的函数指针调用系统调用)。需要注意的是,这些要求虽然从通用计算的角度来看显得严格,但在大多数实时控制系统中却是常见的实践,并且本质上已基本满足。这是因为主流的安全性(例如MISRA‐C [10], ISO 26262[13])和实时操作系统行业标准本身就要求如此。例如,ARINC 653分区[1](航空电子)、µITRON [28]以及 OSEK/AUTOSAR [23, 2](汽车领域),甚至POSIX.4实时扩展(使用SCHED_FIFO)都规定对一组已知的任务进行固定优先级调度。
2.1 我们的方法概述
图1展示了我们将RTOS按使用情况进行硬件级定制的概念:首先,我们对具体应用及其描述的系统配置进行分析,以提取应用程序与RTOS之间所有可能的交互,并将其表示为一个有限状态机。该系统状态机(SSM)模拟了RTOS在具体应用中的语义;它接收输入信号(同步系统调用和中断),更新其内部状态,并将当前运行的线程作为输出信号暴露出来。其次,我们将此SSM集成到一个面向特定应用的CPU设计中:应用程序通过新引入的指令触发SSM,流水线则响应并调度到另一个硬件线程。最终,我们得到一个针对具体实时应用自动定制的计算系统。
当然,在一般情况下,由于状态爆炸问题,这样的RTOS‐FSM将变得不可处理:事件触发型RTOS的内核内部状态包括就绪列表、线程上下文、运行中的线程等。每个系统调用都可能是重新调度的潜在触发点,根据所选的调度策略和就绪列表的动态状态,可能会继续执行其他线程,进而可能触发更多的系统调用。
然而,由于以下两个原因,我们的方法是可处理的:首先,我们依赖于一个具有内在有限数量可能系统状态的系统模型。其次,我们在编译时向系统分析提供应用程序特定的信息,以尽可能减少不确定性:我们利用关于RTOS配置及其语义的静态知识,并结合对应用程序所有控制流的全系统分析,来确定RTOS的实际使用方式。
通过这种方式,我们可以大幅减少可能的状态数量,因为许多调度决策的结果可以在运行前被推导出来(或至少被限制)[9]。这进而为硬件中的高效实现提供了支持,在该实现中,我们将RTOS及其定制化硬件组件(例如线程上下文或定时器)直接集成到处理器流水线中。
在不失一般性的前提下,我们在下文中以OSEK规定的系统模型为例来描述我们的方法。我们名为OSEK‐V的实际实现涵盖了符合性类别ECC1及以下的OSEK/AUTOSAR系统[23, 2]。
2.2 OSEK‐OS 概述
OSEK标准定义了一类广泛使用的固定优先级RTOS,并且在过去二十年中一直是汽车应用的主流行业标准。在不失一般性的前提下,我们的方法基于OSEK‐OS标准规定的RTOS接口[23]。接下来,我们简要介绍其API提供的抽象。
基本上,OSEK提供了两种主要的控制流抽象:中断服务例程(ISRs)和任务(传统上称为线程)。ISRs由硬件异步激活,并对系统服务具有受限访问;而线程具有静态分配的优先级,由软件同步激活。线程可以使用所有系统服务,并按照固定优先级抢占式调度策略执行。每次新的激活时,线程都从开头开始执行,直到其(自行)终止。
临界区可以通过粗粒度全局中断锁或更细粒度的资源对象进行同步。基于栈的优先级上限协议,OSEK资源确保互斥的同时防止死锁和无界优先级倒置。此外,线程可以等待事件,可以被设置并保持在等待状态,直到另一个控制流发出事件到达的信号。
通过静态声明的报警可以触发周期性或非周期性的线程激活或事件。每个报警都关联一个计数器,该计数器通常由硬件定时器驱动。报警可以在系统启动时以相位/周期自动开始,或在运行时动态启动。
对于特定应用程序,开发人员在领域特定配置文件中声明所有系统对象及其参数。通常,系统生成器在编译时静态地生成具体的实时操作系统实例,并将应用程序和操作系统库链接成一个单一的系统镜像。
描述了一个线程T及其每70个节拍的周期性激活,该激活在系统启动时自动开始。应用代码(app.c)包含线程T的实现,生成器将系统描述实例化为 generated.c)
在图2中,展示了一个包含一个任务和一个周期性报警的示例 OSEK系统。应用程序代码(app.c)包含任务T,该任务执行一次计算后自行终止。系统配置(app.oil)表明,任务T具有10的静态优先级,并且是完全可抢占的(SCHEDULE= FULL)。此外,声明了一个计数器C并将其连接到报警A,报警A在初始相位偏移35个时钟节拍后,每隔70个时钟节拍触发一次。当报警A超时时,会激活任务T。在编译期间,系统生成器生成一个系统框架(generated.c):一个空闲任务以最低优先级运行;当中断发生时,报警_tick中断服务例程(ISR)处理计数器和报警。
为了明确地锚定系统行为,我们在代码中添加了人工系统调用(idle, isr, iret, kickoff)。
在本研究中,我们专注于OSEK扩展符合性类别1(ECC1),该类别包含等待状态和资源,但不包含每个优先级多个任务以及每个任务多次激活。随后,我们将所描述的实时操作系统(RTOS)原语视为用于表达实时系统(RTS)行为的标记语言,并使用线程(表示OSEK任务)和ISRs来区分不同类型的控制流。
3. 系统状态机器
由于我们的方法是应用特定的,因此我们从对一个特定实时系统(RTS)的系统分析开始,以提取应用程序、外部环境和实时操作系统(RTOS)之间的交互模型。系统状态机(SSM)在已分析的应用程序和环境模型存在的情况下,捕获期望的内核行为(即重新调度序列)。迪特里希等人[9] 描述了一种应用特定的状态转移图(STG),该图枚举并连接了所有可能的系统状态。在本研究中,我们改进了STG计算的效率,并由此推导出应用特定的SSM。
在事件触发的实时系统中,实时操作系统从两个方面接收信号:控制应用发出同步系统调用,外部组件提供异步硬件中断。在这两种情况下,实时操作系统都会被激活,操作其内部状态,并通过调度实现调度结果。系统调用的内部发出顺序受应用逻辑限制;外部事件的可能序列由周围环境决定。
3.1 应用状态机
对于系统分析,我们将内部应用结构表示为一组应用特定的有限状态机;每个线程和每个中断服务例程(ISR)都成为一个应用状态机(ASM)。这些状态机作为信号生成器向操作系统模型发送信号,后者则协调多个ASM的执行。在之前的研究中,迪特里希等人[9] 使用(压缩的)控制流图(CFG)来表达系统调用顺序。相比之下,ASM表示更加紧凑,由于状态数量减少,我们实现了更短的分析时间。
对于每个控制流,我们根据局部控制流图计算抽象状态机。首先,我们将代码划分为基本块,这些基本块不是最大化的,但每个基本块要么包含一个系统调用,要么仅包含计算代码;后者无法同步地影响系统状态。为了实现这种影响的分离,我们要求在系统生成时已知应用程序结构(控制流图和系统调用位置)。图3a 显示了图2中 alarm_isr处理程序的基本块划分(系统调用以深红色表示)。
为了生成一个针对每个执行的基本块都产生信号的状态机,我们从控制流图(CFG)计算出线图。每个CFG边变为一个顶点,而每个基本块变为一条带有该块内容标签的边。然而,由于操作系统状态只能通过系统调用影响,我们将所有计算替换为 ε转换。值得注意的是,转移标签对应的是系统调用点而非系统调用类型。图3b展示了 alarm_tick中断服务例程(ISR)的线图。
我们通过对每个ASM应用标准的 ε消除来移除 ε‐转换。此外,我们将可通过 ε‐转换到达的线程状态标记为可被中断服务例程中断(E)。对于每个ASM状态,其出边集合表示应用程序中某一点可能执行的系统调用。图3c展示了运行示例中的三个ASM:当报警处理程序处于状态A2时,ActivateTask下一个可执行的系统调用站点是 iret,并可将其发送到SSM。
目前,我们使用一种非常简单的模型来包含其他分析结果,以限制外部事件模型。当某个线程(或一组线程)具有隐式截止时间时,触发事件将被阻塞,直到事件处理完成[9]。然而,还可以推导并利用应用程序层面上的其他动作逻辑来限制事件模型。例如,可以定义 “发送缓冲区为空”中断仅在调用相关SendMessage()函数后才会发生。
应用程序模型和外部事件模型与一个抽象操作系统模型相连接。该操作系统模型通过系统配置实例化,并遵循OSEK语义[23]。我们使用系统状态枚举(SSE)[9]方法将这三个部分组合在一起,并在STG中显式枚举所有可能的系统状态。
STG是一个由抽象系统状态(AbSSs)构成的有向图,每个 AbSS捕获某一时刻的可能系统状态,并包含能够影响调度决策的信息。特别是,每个AbSS包含一个ASM状态向量,用于指示每个控制流的当前抢占点。在每个状态中,恰好有一个流被标记为当前运行的线程。有关STG构建的更多细节,请参考迪特里希等人[9]。
由于ASM中的每个转移标签对应一次内核激活,且SSE仅根据系统语义组合多个ASM,因此状态转移图(STG)可直接用作SSM。在图4中给出了运行示例的STG/SSM:系统从空闲循环开始。当中断发生时(E),报警处理程序可以激活线程T或直接返回空闲状态。如果被激活,线程T将被调度、执行计算并自行终止。尽管在计算过程中报警可能再次到期,但线程只能被激活一次。
3.2 系统状态机最小化
生成的SSM已经表现出正确的行为,但状态数和转换边数尚未达到最小化。然而,由于状态机最小化是一个已有广泛研究且长期存在的课题[22, 12],,我们将仅关注SSM的具体特性。
对于SSM的最小化,我们将表现出相同可观测行为的所有状态合并为单个状态。在本例中,可观测行为是指可能的重新调度事件序列。例如,如果两个状态总是以相同的顺序出现,但调度仅在第二个状态之后发生,则第一个状态可以合并到后一个状态中。在我们的运行示例(图4)中,A1和A2状态就是此类状态对的一个实例。
从系统视角来看,所有由硬件事件(E)激活的A1状态,其后续的重新调度序列与A2状态相同。因此,A1状态被对应的A2状态所包含。
我们通过使用摩尔算法[22]来识别这些等价状态,并将它们合并为一个状态。如果在合并后某个转移标签仅出现在自环上,则可以安全地将该信号从系统中完全移除。
3.3 静态报警
我们面向应用的硬件定制的一个优势是能够实现与静态系统配置相匹配的优化组件。除了SSM之外,我们还在应用程序中检测静态报警,这在嵌入式控制系统中非常常见:静态报警在启动时自动开始,从不重新配置,并以恒定速率触发。我们通过对接口配置和应用程序代码的静态分析来检查这些特性。所有非静态的报警均为动态报警,可根据配置由具有较低基本速率的定时器中断请求驱动,从而降低中断请求负载。
运行示例中的报警(图2)是静态的:它在启动时自动开始(AUTOSTART= TRUE ),相位为35个时钟节拍,周期为70个时钟节拍,并且从不重新配置。
4. 衍生OSEK‐V处理器
在系统分析中,我们收集了信息,以根据应用需求定制可参数化的处理器流水线。我们将每个操作系统线程映射到一个硬件线程(harts),并引入专用指令,这些指令与控制硬件线程调度的SSM组件进行交互。此外,静态报警组件生成周期性信号,并异步地激活 SSM。
4.1 状态分配和逻辑最小化
为了在硬件中实例化SSM,我们必须提供状态转移函数的高效实现:除了当前SSM状态外,它接收一个系统事件,并返回一个新的系统状态以及(下一个)核心。
SSM: ⟨系统事件⟩ × ⟨状态⟩ → ⟨状态⟩ × ⟨核心⟩
系统分析生成一个带有符号信号(例如“TerminateTask”、“ActivateTask(T)”)和状态的SSM。对于硬件实现,我们必须为这些符号值选择位向量(例如,⟨ActivateTask(T)⟩= 101₂)。这一选择被称为状态分配问题,它在很大程度上影响硬件实现所需的最小复杂度。幸运的是,已有多种方法被提出用于解决不同硬件设计下的该问题[33, 7, 32]。
我们使用NOVA程序[33]来解决我们的状态分配问题。NOVA针对两级逻辑实现的目标是最优编码,并根据给定的“线程ID”编码(我们任意选择)相应地为系统调用和SSM状态选择位向量。由于NOVA在内部使用了逻辑最小化器,因此我们得到转换函数的最小化真值表作为结果。结合该真值表和静态报警信息,我们继续实例化 OSEK‐V处理器。
4.2 OSEK‐V处理器
我们在Rocket核心[17],(一种64位、6级、顺序流水线)的基础上构建了OSEK‐V。尽管该软核最初并非主要面向嵌入式系统,但目前正开发一个兼容的精简版32位变体。Rocket实现了RISC‐V接口[34],,这是一种旨在支持计算机体系结构研究的指令集架构。Rocket类似于一个硬件产品系列,并提供了大量配置开关,以使实现能够适应应用需求。
我们将OSEK‐V集成到了Rocket芯片生成器中,该生成器能够在寄存器传输级生成周期精确的C++仿真器。通过我们的适配,它会根据系统分析的结果实例化所有组件,并将其连接到流水线中(见图5)。
为了实现快速控制流切换,我们扩展了流水线以支持硬件多线程。该处理器已启用
用于同时跟踪不同的执行流(硬件线程)及其上下文:每个流水线阶段都有一个标签,用于保存当前正在执行的硬件线程的信息;寄存器文件和程序计数器生成器(NPC生成)被扩展以保存多个硬件线程(harts)的执行上下文。来自不同硬件线程的指令发射由 SSM控制。
在我们的当前实现中,每个OSEK任务和空闲线程都被映射为独立的硬件线程,而ISRs仍在当前核心的上下文中执行。这是ISR激活时间与硬件资源消耗之间的权衡,但可以通过使用一个专用硬件线程来执行所有ISRs从而缓解这一问题。
4.3 特殊指令和静态报警
此外,OSEK‐V流水线提供了两条新指令以与SSM交互:ssm.ld和 ssm.tx。ssm.tx指令用于启动代码中,为所有硬件线程设置指令指针。ssm.tx指令将其立即数操作数作为系统事件(参见第4.1节)传递给SSM,SSM随后在其上执行状态转移函数。
当一条 ssm.tx指令进入流水线并到达执行阶段时,前面的流水线级将被暂停,直到内存和提交阶段清空。这种暂停确保了在该 ssm.tx指令之前的所有异常保持精确。执行阶段将系统事件发送给 SSM。在SSM应用转换函数并更新“当前hart”信号期间,流水线处于暂停状态。如果发生重新调度,则会重用分支预测错误逻辑来清空流水线,并为新hart的程序计数器发起指令取指。
除了 ssm.tx指令外,静态报警组件还会发出系统事件。在内部,它从实时时钟节拍中派生出具有不同相位和周期的时钟信号,并与 SSM通信。当一个或多个报警超时时,静态报警组件将暂停流水线并等待当前指令执行完毕。随后,多个系统事件将以原子方式传输,以确保报警可以同时触发。该传输以一个⟨isr()⟩开始,多个报警动作(例如,⟨ActivateTask(…)⟩)构成主体部分,而⟨iret()⟩则触发可能的重新调度。
静态报警事件的处理方式与其他外部事件类似;只有在处理器当前未锁定中断时才会被接受。因此,所有中断被锁定的区域仍然具有运行至完成的语义。
OSEK‐V功能已集成到Rocket芯片生成器中;配置参数以 JSON格式编码,并由硬件设计直接读取和解释。这些参数包括 SSM逻辑的最小化真值表、硬件线程数量以及静态报警设置。虽然配置仅描述预期行为,但生成器决定如何实现这些需求。例如,静态报警组件使用根据报警激活的相位和周期,采用不同的策略来生成时钟信号。
4.4 系统生成和开始
定制硬件还要求系统软件进行相应的定制。通过将操作系统逻辑推向硬件,内核的软件部分仅需保留少量功能。在启动时,内核使用 ssm.ld指令配置程序计数器。栈指针由线程自身作为前几条指令之一进行初始化。当一个已终止的线程被重新激活时,它将从栈初始化代码处开始执行。剩余的动态报警以及常规中断由软件内核处理。在应用程序中,系统调用点被替换为携带系统事件标识符的 ssm.tx指令。为了确保ISRs和线程中的重调度点之间的对称性,系统调用点必须由一对中断禁用/启用命令包围。
我们实现了实时操作系统和硬件定制过程的完全自动化。系统分析与转换在dOSEK框架中实现,无需人工干预。Rocket生成器读取处理器配置,并生成OSEK‐V实例;该实例可作为周期精确模拟器,也可作为Verilog代码。
5. 实验结果
在我们的评估场景中,我们采用了与西门子中央研究院合作开发的 I4Copter[31],,这是一种安全关键型嵌入式控制系统(四旋翼直升机)。
我们分析了I4Copter控制应用程序的任务设置(图6):线程通过三个报警和一个中断服务例程(ISR)周期性地和偶发地被激活。线程间同步通过OSEK资源实现,且有一个看门狗线程监控遥控通信。该场景总共包含十一个线程、三个周期性事件(报警)、一个偶发中断和一个资源。其中一个控制看门狗线程且以低激活率运行的报警在运行时被重新配置,因此属于动态报警;其余两个为静态报警。
我们将应用逻辑替换为检查点标记,因为我们关注的是应用程序与内核之间的交互。这种替换不会影响分析,仅交换计算块的内容。整个系统包含52个系统调用点。
在SSM构建(第3节)期间,我们利用了关于隐式截止时间的应 用知识来限制外部事件模型。例如,“采样”、“信号处理”和“飞 行控制”任务总是在3毫秒的报警再次触发之前完成执行。正如迪特 里希等人[9],所述,这种对可用信息的结合有助于简化系统分析。
5.1 性能
作为初步评估,我们针对不同程度的定制运行了基准测试场景,并在周期精确模拟器中测量了不同系统操作所需的时钟周期。我们对三个超周期运行了该基准测试,结果如图7所示。
前两个变体不涉及底层处理器,仅用于为OSEK‐V的结果提供上下文:图7中的基线变体是标准的dOSEK实现,其中所有报警均为动态。专用变体利用系统分析结果,将系统调用点替换为专用代码片段[9]。如果结果可以静态推导,则专用系统调用可省略某些操作(例如,查找最高优先级的可运行线程)。在OSEK‐V–SSM变体中,流水线通过定制的SSM组件得到增强,而所有报警仍以动态方式管理。最后,SSM+Alarms变体包含SSM以及一个静态报警组件,该组件负责管理三个报警中的两个。
在周期精确跟踪中,我们识别出在内核状态上原子执行的操作。这些操作包括同步系统调用、管理动态报警的定时器中断服务例程,以及静态报警信号的传输。我们统计了这些操作所需的时钟周期,同时将实际在流水线中执行的周期(a, b)与额外的缓存停顿周期(c, d)区分开来。这种区分使我们能够将OSEK‐V的实际计算开销与处理器特定的缓存层次结构区分开来。
在整个基准测试中,通过专用化系统调用,以及进一步使用专用硬件组件(a),处理器非空闲状态下的有效时钟周期减少。这种减少源于更短的原子执行的内核激活,其与中断锁同步。对于实时系统而言,更短的中断锁区间尤为重要;当中断延迟降低时,系统的责任增加。如果不考虑缓存停顿,所有操作的中断锁平均长度从195个时钟周期减少到41个时钟周期(SSM+Alarms),降幅约为80%。这一减少主要由定时器中断服务例程驱动。然而,即使没有静态报警,平均操作也仅需138个时钟周期(SSM)。
我们将同步系统调用和ISR激活的实例区分为两类:不会导致重新调度的事件,以及实际分派到另一个控制流的事件。此外,由于我们关注实时能力,因此将处理时间最长的事件视为重要信息。因此,我们不仅提供每种操作的平均运行时间,还提供其最大运行时间(上界)。
首先,我们考虑应用程序代码发出的同步系统调用。当不发生重新调度时,没有静态报警的OSEK‐V的最坏情况时间减少了−79.29%,下降范围与具有专用系统调用的版本(减少−75.71%)相似。平均而言,定制硬件比专用软件快约50%。这种差异的原因在于,调度器和分派器通常已经被消除针对这些非调度系统调用的专用化。对于带分派的系统调用操作,OSEK‐V硬件相比基线至少有75%的提升,而平均优势甚至超过90%。
在纯基于软件的实现中,每个报警都通过定时器中断服务例程动态管理。我们将整个定时器中断服务例程的执行周期作为一个单一的系统操作进行测量,因为报警激活的效果在 iret处以原子方式体现。同样,我们区分了有无调度另一个线程的操作。无论是否实际发生重新调度,系统调用特化对周期计数的影响都很小。
当定时器中断未引起重新调度时,SSM变体仅表现出轻微的最坏情况下的改进(−12.77%)。然而,在发生调度的情况下,该操作在最坏情况下执行速度大约快了一倍(−47.16%),并且平均导致显著更少的缓存停顿(−72 stalls)。
使用静态报警组件(SSM+Alarms)会导致系统在报警处理方面的行为发生若干变化。一方面,由于剩余的动态看门狗报警的基本速率得以降低,定时器中断请求(IRQ)的数量从280次减少到28次。这主要是导致整个基准测试中中断阻塞时间下降的主要原因。除了中断率降低外,静态报警变体的中断服务例程(ISR)执行时间也有所下降:由于只需管理一个报警而非三个,因此无需调度的 ISRs(−29.43%)以及需要重新调度的ISRs(−59%)执行速度显著加快。此外,一次静态报警激活最多消耗10个时钟周期,并且直接影响SSM,而无需利用处理器。
缓存停顿周期的减少与特化程度成正比,最高可达−46.79 percent(c, SSM+Alarms)。对于两种OSEK‐V变体而言,同步系统调用和静态报警激活所剩余的缓存停顿源于应用程序代码的指令取指(d)。只有动态报警处理可能导致由执行的内核指令引起的缓存逐出。
5.2 OSEK‐V 核心的现场可编程门阵列 Synthesis成本
除了OSEK‐V方法在运行时间和延迟方面的优势外,我们还评估了在流水线旁边使用专用硬件组件的实际成本。我们首先概述I4Copter 基准测试和图2中运行示例的系统分析结果。这些数据为理解综合不同OSEK‐V核心时产生的实际实现成本奠定了基础。
在表1中,我们展示了系统分析的结果,该分析在单个英特尔酷睿 i7‐2600 核心上通过 Python 实现的 dOSEK 框架执行。图2中的运行示例是一个小型系统:其分析速度快,初始SSM已经很小,且 SSM最小化并未消除太多冗余。最终得到的最小化逻辑块实现了状态转换函数仅由四个与子句组成(四个与门,其输出在一个或门中组合)。
对于 I4Copter 基准测试,系统分析耗时超过一分钟,其中运行时主要由状态分配相位(96.95%)决定。然而,初始SSM的规模仍随着系统规模(中断数量、任务数量)呈指数级增长,并表现出庞大的状态机特征。与之前的工作[8], 相比,通过使用 ASM(抽象状态机)替代控制流图,初始STG的规模显著减少了−75.91%。尽管如此,状态机最小化仍可消除85.5%的状态。最终得到的状态转移函数接收一个15位的输入向量(状态:10位,系统事件:5位),并生成一个14位的输出信号(hart标识符:4位)。
我们使用 Xilinx Vivado2015.2 工具链为 Zynq‐7020 FPGA芯片综合不同的 OSEK‐V核心,这集成到ZedBoard平台中。火箭的流水线被限制为至少以25兆赫运行,而现场可编程门阵列的单个逻辑单元工作频率为Fmax 100兆赫。
如预期所示,与基准Rocketcore相比,图2示例仅导致现场可编程门阵列资源使用量小幅增加(+127存储器查找表),如表2所示。这一增长主要源于寄存器文件翻倍,因为综合工具使用分布式内存单元来实现额外核心(空闲线程、线程T)的第二个寄存器文件。
I4Copter 基准测试产生了一个相当大的核心。在没有静态报警的情况下,需要多出9%的查找表(LUT),这些查找表主要被 SSM 组件使用(76.09%)。额外需要的983个存储器查找表主要用于寄存器文件(96.24%),以保存额外的核心上下文。这些增加的现场可编程门阵列资源需求与系统镜像中内存消耗的减少直接相关(见表3);SSM 避免了大部分内核代码,而扩展的寄存器文件避免了线程上下文对内存的占用。
当我们添加静态报警组件(SSM+Alarms)时,与没有此附加硬件组件的变体相比,现场可编程门阵列资源消耗仅略有增加。系统镜像的静态内存消耗没有显著变化。对于所有变体,Xilinx综合工具至少需要10分钟,并且始终能够满足流水线的25 MHz时序约束。
| 示例 | I4Copter |
|---|---|
| 生成时间 (秒) | 0.06 |
| 初始SSM 状态 | 9 |
| 转换 | 13 |
| 最小化SSM 状态 | 6 |
| 转换 | 9 |
| 转换函数 子句 | 4 |
表1:基准的系统分析结果
| 火箭示例 | I4Copter |
|---|---|
| (基线) | (图3) |
| LUT | 29 460 |
| 内存查找表 | 1033 |
| 触发器 | 14 208 |
| F max[兆赫] | 26.37 |
表2:定制OSEK‐V核心的综合结果
| 字节 | 基线 | SSM | SSM+Al |
|---|---|---|---|
| 内核 | 14 368 | 8669 | 8393 |
| 数据段(不含栈) | 1908 | 410 | 354 |
表3:I4Copter所需的闪存和内存空间
6. 讨论
与其他软硬件协同设计方法相比,我们专注于单个应用程序而非一小类应用程序,以揭示涌现系统特性。我们缩小的关注范围揭示了独特的特性,但也将讨论由此带来的限制。
6.1 专用化与标准化
我们的目标是基于可定制硬件设计的实时控制系统,其中采用现场可编程门阵列(FPGA)或专用集成电路(ASIC)。这与当前行业领域通过将定制设计整合到高产量(因而成本更低)的商用现成平台(COTS)以降低硬件/软件开发成本的趋势形成鲜明对比。
然而,我们相信,定制流程各个层面自动化程度的不断提高将在一定程度上扭转这一趋势——从长远来看,“按需专用集成电路”产业将大幅降低定制硬件的开发成本和单位成本。这种情况已经出现,正如帕特森和尼科利´奇在最近发表于《电子工程时报》的一篇博客文章[25]中所指出的那样。OSEK‐V 与这一愿景高度契合,因为我们完全保持了软件端的兼容性:应用程序基于标准RTOS接口进行开发,但自动生成的优化实现可选择性地部署到硬件中。
6.2 应用程序领域与可扩展性
当静态定制的不灵活性达到可接受的应用特定芯片程度时,我们的方法是适用的。OSEK‐V 芯片以硅基形式体现内部解决方案结构;所采用的专用集成电路无法更新,只能替换。对于现场可编程门阵列系统情况则不同,其中 OSEK‐V 处理器将成为已部署系统更新的一部分。然而,仅当应用程序结构(系统配置和 ASM)发生变化时,才需要更新 OSEK‐V 核心;其他更新可照常进行。此外,通过分层调度方案可以实现部分硬件化:高优先级线程可直接映射到硬件线程,而低优先级线程可在单个核心中合并并通过软件管理。这将在关键情况下提供低延迟,并在其他情况下保持灵活性。
主要的可扩展性挑战是状态转移图的状态爆炸问题。理论上,系统的状态数量可能相较于线程和中断的数量呈指数级增长。即使可行,这种负担也会导致漫长的分析和构建时间。然而,我们证明了我们的原型实现处理实际场景的速度快于生成的硬件描述被综合所需的时间。
硬件可扩展性由两个成本因素决定:寄存器文件和SSM逻辑。由于寄存器文件必须存储 n个线程上下文,因此我们必须分配相应的存储容量。然而,它随着硬件线程数量线性增长,并且可以放置在FPGA的块状存储器中。SSM逻辑则随着应用程序的复杂性和系统必须面对的外部非确定性而扩展。对于那些对周围环境具有充分了解的小型系统而言,将实时操作系统语义实例化到硬件中将获益最大。
除了工业中使用的传统实时控制系统外,我们认为新兴的物联网领域是一个可能的应用程序领域。当小型控制系统变得无处不在时,专用化与灵活性之间的权衡将被重新评估。物联网系统销量巨大,面临较高的价格压力,并且与所用设备的任务和使用寿命紧密相关。我们相信,应用特定的高度定制化芯片能够很好地适应这些变化的设计因素。
6.3 语义和应用程序的限制
除了可扩展性问题之外,我们对(1)RTOS语义和(2)应用程序结构所施加的限制,对语义提取的普遍适用性构成了威胁。本质上,状态转移图(STG)包含了在编译时可获得的固有确定性符合RTOS语义及其被应用程序的使用情况,即使存在外部中断也是如此。虽然这对于固定优先级调度效果良好,但在确定性显著较差的系统上其用途受限,例如使用最早截止时间优先(EDF)调度器或执行在线接纳测试的任何其他调度器的实时操作系统。在应用程序侧,所有与RTOS的交互都必须在编译时可检测。这禁止任何形式的动态代码加载、通过函数指针调用系统调用,以及无法在编译时计算的系统调用参数。
然而,在许多领域中,这些限制在实践中影响甚微——它们本来就被相关的行业和实时安全标准所规定和要求:例如,最早截止时间优先调度(EDF)在嵌入式控制系统中几乎不被使用;相关行业标准(如 OSEK/AUTOSAR [23, 2], 653[1] µ [28], 4 ARINC、 ITRON 以及 POSIX.)均采用固定优先级调度;函数指针的使用以及任何形式的动态代码修改都被相关的编码和安全标准所禁止(例如,[10, 13])。总之,大多数我们的要求本来就是嵌入式控制系统为了通过认证所必须满足的。
6.4 可预测的实时操作系统实现
实时开发人员使用最坏执行时间(WCET)分析来为任务所需的执行预算提供上限。tighter bounds 将简化获得时间可预测系统所需的资源分配。我们可以通过改进分析本身,或首先使底层平台更具可预测性,来增强我们的预测能力。与 T‐CREST/Patmos 项目 [27], 类似,OSEK‐V 为实时应用提供了更具可预测性的处理器平台。
通过OSEK‐V,实时操作系统对时序行为的影响被降至最低。SSM激活仅需消耗少量周期,主要由重新调度的硬件线程的取指延迟决定。SSM本身的执行不会逐出任何缓存行;只有必要的流水线冲刷会对应用程序产生影响。此外,静态报警组件承担了周期性系统协调任务,从而降低了中断负载。
尽管及时性是可预测性的一个重要方面,但安全性问题正变得越来越突出,尤其是当控制系统连接到(公共)网络时。OSEK‐V 核心仅继承所需的实时操作系统语义,减少了可信代码基,并将控制组件推向更可信的硬件实现领域。结合定制的内存保护机制,其中核心切换意味着保护域切换,可以在不执行任何内核指令的情况下实现完全隔离。然而,这属于进一步研究的课题。
7. 相关工作
将操作系统接口解释为对实际处理器接口的扩展,从而定义一个分层机器[29],这在系统领域中是一种公认的观点。因此,通过将操作系统(或其部分)移入(定制)硬件以提升不同的非功能性属性,来解决系统调用的部分解释问题,是一种顺理成章的做法。
HybridThreads[3]通过将操作系统组件置于实际处理器旁边,实现了低运行时开销和快速中断处理。调度决策通过中断服务例程(ISR)在软件中进行调度。Sloth[11]通过将所有调度和调度决策委托给中断硬件,在标准硬件上为 OSEK 实现了类似的优势。
FlexPRET 处理器[35],同样暴露了 RISC‐V 指令集架构,通过细粒度的硬件多线程实现了混合关键性系统的可预测执行,同时处理线程间依赖且未考虑同步问题。相比之下,ReconOS 项目[18],为线程和硬件组件提供统一的操作系统接口,类似于 POSIX;协调与同步仍通过软件实现。莫尼和布洛夫[21] 将操作系统组件在硬件中实例化,以提供应用特定的平台;开发者可手动选择预构建的、与核心服务正交的组件。与上述所有方法不同,OSEK‐V 对实时操作系统进行了深度定制:我们从特定应用程序的角度捕捉实时操作系统的语义,而不是在硬件中复制(通用的)软件实现。此外,我们将组件直接集成到处理器流水线中,以实现细粒度且应用特定的定制。
本质上,OSEK‐V 通过对每个调用点上的每个系统调用来进行完全特化,从而获得其定制的 RTOS 语义。这在某种程度上类似于 Synthesis[26, 19] 中 known的路径特定系统调用优化,或 Tempo [20] 框架提供的部分特化。然而,这两者都是在运行时进行特化的,这(a)需要昂贵的运行时支持,且(b)支持可逆的概率性优化。相比之下,OSEK‐V 是在编译时进行定制的,因此所有特化都必须是可靠的和完整的,即所生成的 RTOS 实例可以表示为一个有限状态机。
将有限状态机作为整个系统模型的使用也已被提出,用于深度嵌入式传感器节点,以增强简单性和能效:SenOS[14]是一种软件事件分派器和执行器,用于多个手动编码的有限状态机。科塔里等人[16]通过符号执行从TinyOS程序中推导出紧凑的状态机(< 16 状态),以促进对现有应用程序的理解。
8. 结论
借助 OSEK‐V,我们在硬件与操作系统边界处探索事件触发、固定优先级实时系统的软硬件设计空间。从单一应用程序和标准化的 OSEK‐OS API 出发,我们将实际使用的 RTOS 行为提取为一个有限状态机。该系统状态机由系统调用和中断触发,并控制线程调度。OSEK‐V 核心将每个 RTOS 线程映射到一个硬件线程,并辅以实现所提取 RTOS 语义的应用专用硬件组件。由此,我们展现出理想的非功能性属性,例如低事件延迟(平均中断请求锁时间减少 −79%)、干扰减少的 RTOS 执行(内核中缓存停顿减少 −47%)以及快速的线程重新调度(调度系统调用仅需 −81% 个周期)。这些改进的代价是适度的现场可编程门阵列资源开销,即每映射一个 RTOS 线程需要额外 10% 的查找表和 86 个分布式存储单元。
致谢
作者感谢匿名评审人提供的反馈意见。本工作得到了德国研究基金会(DFG)的资助,资助编号为 LO 1719/1‐3、SFB/Transregio 89 “Invasive Computing”(项目 C1)以及 LO 1719/4‐1。
OSEK‐V 的源代码可在以下地址获取:
https://gitlab.cs.fau.de/osek-v
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐



所有评论(0)