ISO 17356-3-2005

第 3 部分:OSEK/VDX 操作系统 (OS)

道路车辆 — 面向嵌入式汽车应用的开放式接口

1 范围


OSEK/VDX 是汽车行业的联合项目,旨在为车辆中的分布式控制单元制定开放式架构的行业标准。

ISO 17356 的这一部分描述了可被用于机动车辆的、能够进行多任务处理的实时操作系统的概念。它不是针对特定实现的产品的描述。它规定了操作系统(OS)的应用程序接口 (API)。

ISO 17356-1 描述了通用约定、术语的解释及缩写。ISO 17356-6 描述了实施和系统生成方面的内容。

此操作系统规范提供了一个统一的环境,以支持汽车的控制单元的应用软件高效地利用资源。此操作系统(OS)是一个单核处理器操作系统,专为分布式嵌入式控制单元而设计。

2 规范性引用


下列文件在本文中被引用,其部分或全部内容构成本文件的要求。凡是注日期的引用文件,仅其版本适用。凡是不注日期的引用文件,其最新版本(包括所有的修改)适用于本文件。

ISO 17356-1, Road vehicles — Open interface for embedded automotive applications
  • Part 1: General structure and terms, definitions and abbreviations terms

ISO 17356-2, Road vehicles — Open interface for embedded automotive applications
  • Part 2: OSEK/VDX specifications for binding OS, COM and NM

ISO 17356-6, Road vehicles — Open interface for embedded electronic equipment
  • Part 6: OSEK/VDX Implementation Language (OIL)

3 操作系统“OS”的架构


3.1 处理级别

操作系统(OS)为彼此间独立的应用程序的实现提供了基础,并在处理器上为它们提供了运行环境。操作系统(OS)能够以受控的方式实时地执行多个看似并行运行的进程。

操作系统(OS)为用户提供了一组被预定义的接口。这些接口被相互间争夺 CPU 运行资源的实体使用。实体分为两种类型:
  • 由操作系统(OS)管理的中断服务例程(ISR)
  • 任务(基本任务和扩展任务)

控制单元的硬件资源可以由操作系统(OS)的服务进行管理。应通过一个唯一的接口对这些服务进行调用,此接口既可以在应用程序(上下文)中被调用,也可以在操作系统(OS)的内部被调用。

操作系统(OS)定义了三种处理级别:
  • 中断级别
  • 逻辑级别(调度器)
  • 任务级别

任务级别中,任务将根据其被分配的任务优先级被调度(非抢占式、完全抢占式或混合抢占式调度)。运行时(Runtime)上下文在对任务的执行开始时被占用,并在对任务的执行结束时被释放。


已制定以下优先级规则:
  • 中断优先级高于任务优先级
  • 中断级别(处理级别)由一个或多个中断优先级组成
  • 中断服务例程(ISR)具有被静态地分配的中断优先级
  • 对中断服务例程(ISR)的中断优先级的分配取决于具体实现和硬件架构
  • 对于任务优先级和资源上限优先级,数字越大表示优先级越高
  • 任务优先级由用户静态地指定(任务优先级的具体含义见 4.5 节)

处理级别应被定义为一系列连续的值,被用于对任务和中断例程(ISR)的处理。操作系统优先级硬件中断级别的映射取决于具体实现。

注意

为调度器分配的优先级只是一个逻辑概念,不会实际地对此优先级进行使用。此外,此规范没有规定在特定的微处理器架构中任务优先级硬件中断级别之间的关系。

3.2 一致性等级

“应用软件对系统的各种需求”及“特定系统(例如,处理器、内存)的各种功能”对操作系统(OS)提出了不同的功能需求。在以下描述中,这些功能被称为“一致性等级(CC)”。

一致性等级(CC)旨在对以下目标进行支持:
  • 提供便于对操作系统(OS)进行理解和讨论的对操作系统(OS)的功能的分组
  • 允许按照预定义的路线进行部分的实施(并可被认证为合规)
  • 利用相关的功能,在不对应用程序进行更改的情况下,创建从较低的功能级别到较高的功能级别的升级路径

为了获得认证,必须实现完整的一致性等级(CC)。实际上,系统生成只需对特定应用软件所需的系统服务进行链接即可。在运行过程中,不允许对一致性等级(CC)进行更改。

一致性等级(CC)由以下属性确定:
  • 多个对任务进行激活的请求(如 4.3 节所述)
  • 任务类型(如 4.2.4 节所述)
  • 每个优先级对应的任务的数量

除非另行说明,否则所有其他功能均为强制项。


定义了如下一致性等级(CC):
  • BCC1(仅限基本任务,对于每个任务仅允许一个激活请求存在,每个优先级对应的任务仅被允许存在一个,所有任务的优先级各不相同)
  • BCC2(与 BCC1 类似,但每个优先级对应的任务被允许存在多个,并且对于每个任务允许多个激活请求存在)
  • ECC1(与 BCC1 类似,包括扩展任务)
  • ECC2(与 ECC1 类似,但每个优先级对应的任务被允许存在多个,并且对于每个基本任务允许多个激活请求存在)

只有在功能需求未超过最低功能需求的范围的情况下,才能假定应用软件具有可移植性。一致性等级(CC)的最低功能需求的范围如表 1 所示。


3.3 OS 与 OSEKtime OS 的关系

OSEKtime OS(www.osek-vdx.org)是一款专为时间触发型架构的功能需求量身定制的操作系统(OS)。它允许 ISO 17356-3 与 OSEKtime OS 共存。从概念上讲,OSEKtime OS 会将其空闲时间分配给 ISO 17356-3。与 OSEKtime OS 中的类似实体相比,OS 的中断优先级任务优先级较低。

如果操作系统(OS)与 OSEKtime OS 共存,操作系统(OS)的接口及对系统调用的定义不会改变。由于 OSEKtime OS 负责整个系统,而操作系统(OS)仅负责本地系统,因此在系统启动和关闭层面存在一些细微的差异。在 ISO 17356-3 中对这些差异有详细的说明。

此外,OSEKtime OS 还定义了一些功能,如果其他操作系统(OS)与 OSEKtime OS 共存,则在对操作系统(OS)的具体实现中需添加一些限制以实现这些功能。更多信息,请参阅 OSEKtime OS 的规范。

4 任务管理


4.1 任务概念

4.1.1 概述

根据其实时性要求,复杂的控制软件可被方便地细分为多个部分执行。应通过任务对这些部分进行实现。任务为对函数的执行提供了框架。操作系统(OS)支持对任务进行并发地及异步地执行。调度器负责管理对任务的执行的顺序。

操作系统(OS)提供了一种任务切换机制(参见第 4.4 节),其中包括一种在系统或应用程序的功能均未被执行时生效的机制。这种机制被称为空闲机制。操作系统(OS)提供了两种不同的任务概念:
  • 基本任务
  • 扩展任务

4.1.2 基本任务

基本任务仅在以下情况下释放处理器:
  • 其自身终止执行
  • 操作系统(OS)将当前被处理的任务切换为优先级更高的任务
  • 中断发生并导致处理器将当前被处理的任务切换为中断服务例程(ISR)

4.1.3 扩展任务

扩展任务与基本任务的区别在于,扩展任务可以使用操作系统(OS)的等待事件(WaitEvent),这可能会导致任务进入等待状态(参见第 7 节和 13.6.3.4 节)。在等待状态下允许任务释放处理器,并允许处理器被重新分配给优先级较低的任务,而无需终止正在被执行的扩展任务。

从操作系统(OS)的角度来看,管理扩展任务(原则上)比管理基本任务更复杂,且需要更多的系统资源。

4.2 任务状态模型

4.2.1 概述

以下描述了两种任务类型的任务状态及状态之间的切换。

任务状态应能够在多种状态之间被切换,因为处理器在同一时刻只能执行一个任务中的一条指令,而在同一时刻可能存在多个争夺处理器的任务。操作系统(OS)负责在必要时通过切换任务状态保存或恢复任务的上下文。

4.2.2 扩展任务

扩展任务有四种任务状态:
  • Running 状态:在 Running 状态下,处理器被分配给该任务,以便执行其指令。同一时刻只能有一个任务处于该状态,而所有其他任务状态都可被多个任务同时采用。
  • Ready 状态:所有进入 Running 状态所需的功能性前提条件均被满足,任务仅等待处理器被分配给其自身。调度器将决定接下来执行哪个处于 Ready 状态的任务。
  • Waiting 状态:任务不能被继续执行,因为它必须等待直到至少一个事件到来(见第 7 条)。
  • Suspended 状态:在 Suspended 状态下,任务处于被动状态,且可被激活。



仅当任务终止其自身(自我终止)时才能终止该任务。这一限制降低了操作系统(OS)的复杂性。系统允许任务状态直接从 Suspended 状态被切换至 Waiting 状态。这种切换是多余的,且会增加调度器的复杂性。

4.2.3 基本任务

基本任务的状态模型与扩展任务的状态模型几乎完全相同。唯一的区别在于基本任务没有 Waiting 状态。基本任务包含以下任务状态:
  • Running 状态:在 Running 状态下,处理器被分配给该任务,以便执行其指令。同一时刻只能有一个任务处于该状态,而所有其他任务状态都可被多个任务同时采用。
  • Ready 状态:所有进入 Running 状态所需的功能性前提条件均被满足,任务仅等待处理器被分配给其自身。调度器将决定接下来执行哪个处于 Ready 状态的任务。
  • Suspended 状态:在 Suspended 状态下,任务处于被动状态,且可被激活。



4.2.4 任务类型比较

基本任务没有 Waiting 状态,因此仅包含任务开始和结束时的同步点。具有内部同步点的应用部分应由多个基本任务实现。

基本任务的优势在于其对运行时上下文(RAM)的需求适中。扩展任务的优势在于无论当前存在哪些处于活动状态的同步请求(同步类型,事件、数据、标志位),它们都能对单个任务中的一个完整的作业(Job)进行处理。当缺少被用于后续的处理的信息时,扩展任务会被切换至 Waiting 状态。一旦收到相应的事件(表明已收到或更新了所需的数据或事件),扩展任务就会退出 Waiting 状态。此外,扩展任务包含的同步点也比基本任务多。

4.3 激活任务

4.3.1 概述

对任务的激活是通过操作系统(OS)提供的 ActivateTask 或 ChainTask 服务被完成的。被激活后,任务即可从其第一条语句开始被执行。

操作系统(OS)不支持在任务被启动时以类似 C 语言的方式传递参数。应通过消息通信(参见第 10 节)或全局变量传递这些参数。

4.3.2 多个对任务的激活请求

根据一致性等级(CC)的不同,一个基本任务可被激活一次或多次。“多个对任务的激活请求”是指操作系统(OS)接收并记录对已被激活的基本任务的并行激活。

在系统生成过程中,并行请求的(最大)数量由基本任务的特定属性定义。如果当前已被发起的请求的数量未达到并行请求的最大数量,则请求将被入队。对同一优先级基本任务的激活请求将按被发起的顺序被入队(队列与优先级对应)。

4.4 任务切换机制

与传统的顺序编程不同,多任务处理的原则允许操作系统(OS)同时执行各种任务。因此,必须明确地对调度策略(参见 4.6 节)进行定义。

决定将执行哪个任务并触发所有必要的操作系统(OS)的内部活动的实体被称为“调度器”。根据已被实现的调度策略,只要存在进行任务切换的可能性,调度器就会被激活。调度器可被视为一种资源,可被任务占用或释放。因此,任务可通过占用调度器阻止调度器进行任务切换,直到调度器被释放(参见 8.4 节)。

4.5 任务优先级

调度器根据任务优先级(优先顺序)决定下一个其任务状态将从 Ready 状态被切换为 Running 状态的任务。

数值 0 表示任务优先级最低。相应地,数值越大,表示任务优先级越高。

为了提高效率,不对动态优先级管理进行支持。因此,任务优先级是被静态地定义的,也就是说,用户无法在执行过程中对任务优先级进行更改。但是,在特定情况下,操作系统(OS)可以将任务作为任务优先级更高的任务进行处理(参见 8.6 节)。

BCC2 和 ECC2 的一致性等级(CC)支持每个优先级对应的任务存在多个(见 3.2 节)。

同一任务优先级的任务会按照其激活请求被发起的顺序被执行,因此处于 Waiting 状态的扩展任务不会阻止后续具有相同任务优先级的任务被执行。

被抢占的任务将被视为与其当前任务优先级对应的(任务状态为 Ready 状态)队列中的第一个(最早被入队的)任务。

处于 Waiting 状态的被释放的任务将被视为与其当前任务优先级对应的(任务状态为 Ready 状态)队列中的最后一个(最晚被入队的)任务。

图 6 展示了一个对调度器的实现的示例,其中对于每个任务优先级都存在一个与其对应的队列。存在多个不同任务优先级的任务处于 Ready 状态,例如:三个任务优先级为 3 的任务、一个任务优先级为 2 的任务、一个任务优先级为 1 的任务,以及两个任务优先级为 0 的任务。已等待的时间最长的任务位于每个队列的底部(取决于对任务的激活请求被发起的顺序)。处理器刚刚已执行并终止了一个任务。调度器将选择下一个要执行的任务(任务优先级为 3 的任务,位于队列的底部)。在执行任务优先级为 2 的任务之前,所有更高任务优先级的任务都必须不处于 Running 或 Ready 状态(即在被执行后由于被终止或进入 Waiting 状态而从与任务优先级 3 对应的队列中被移除)。


确定下一个要执行的任务需要进行以下基本步骤:
  • 调度器会搜索所有处于 Ready Running 状态的任务
  • 调度器从处于 Ready Running 状态的任务的集合中,确定任务优先级最高的任务的集合
  • 在处于 Ready Running 状态且任务优先级最高的任务的集合中,调度器会找到已等待的时间最长的任务

4.6 调度策略

4.6.1 完全抢占式调度

完全抢占式调度意味着当前处于 Running 状态的任务可能会在任何指令处因操作系统(OS)预先设置的触发条件的出现而被重新调度。一旦出现更高任务优先级的任务处于 Ready 状态,完全抢占式调度就会将当前处于 Running 状态的任务的任务状态切换为 Ready 状态。任务状态被切换(被抢占)的任务的上下文将会被保存,以便该任务之后可以在任务状态被切换(被抢占)时的指令处继续执行。

在完全抢占式调度中,延迟时间与低任务优先级的任务的运行时间无关。某些限制与因保存上下文而增加的对内存空间(RAM)的需求,以及因任务间同步而增加的功能的复杂性有关。由于理论上每个任务都可在任何位置被重新调度,因此当发生对与其他任务共同使用的数据进行访问时必须进行同步。

在图 7 中,较低任务优先级的任务 T2 不会延迟对较高任务优先级的任务 T1 的调度。


在完全抢占式调度的系统中,应始终预期处于 Ready 状态的任务将会被抢占。如果在某个任务的上下文片段中不应发生抢占,则应通过系统服务 GetResource 临时阻塞调度器。

在以下情况中将会发生重新调度: 
  • 任务被成功地终止(系统服务 TerminateTask,见 13.3.3.2
  • 任务被成功地终止,并显式地对后续任务进行激活(系统服务 ChainTask,见 13.3.3.3
  • 对特定任务优先级的任务进行激活(例如,系统服务 ActivateTask,见 13.3.3.1,消息通知机制,闹钟过期,如果定义了任务激活,见 9.3
  • 显式地进入 Waiting 状态(仅适用于扩展任务,系统服务 WaitEvent,见 13.6.3.4
  • 为处于 Waiting 状态的任务设置事件(例如,系统服务 SetEvent,见 13.6.3.1,消息通知机制,闹钟过期,如果定义了事件设置,见 9.3
  • 释放资源(系统服务 ReleaseResource,见 13.5.3.2
  • 从中断级别返回任务级别

在执行中断服务例程(ISR)期间,不会发生重新调度(见图 2)。

使用调度策略“完全抢占式调度”的应用程序无需系统服务 Schedule,但其他调度策略将使用该系统服务。为了使被移植的应用程序在不同的调度策略下正常运行,可在上下文中需要进行重新调度的位置通过系统服务 Schedule 强制进行调度。

4.6.2 非抢占式调度

如果仅通过一组被显示地定义的系统服务(显示的重新调度点)执行任务切换,则该调度策略被称为非抢占式调度。

非抢占式调度对可能出现的任务的时序要求施加了特定的约束。具体而言,对处于 Running 状态的较低任务优先级的任务的非抢占式调度将会使对较高任务优先级的任务的执行被延迟到下一个重新调度点。

在图 8 中,较低任务优先级的任务 T2 会使较高任务优先级的任务 T1 被延迟到下一个重新调度点(在这种情况下,即任务 T2 被终止时)。


4.6.3 重新调度的要点

对于不可被抢占的任务,在下列情况中必须进行重新调度
  • 任务被成功地终止(系统服务 TerminateTask,见 13.3.3.2
  • 任务被成功地终止,并显式地对后续任务进行激活(系统服务 ChainTask,见 13.3.3.3
  • 显式地调用调度程序(系统服务 Schedule,参见 13.3.3.4
  • 进入 Waiting 状态(系统服务 WaitEvent,见 13.6.3.4

注意 1:

如果被传递给 WaitEvent 的事件掩码所代表的事件中的某个事件已经被设置(发生),则调用 WaitEvent 不会使任务状态被切换为 Waiting 状态。在这种情况下,WaitEvent 不会导致重新调度

对非抢占式调度的系统的实现可能会规定,导致重新调度的操作系统(OS)的服务只能在任务的最外层上下文中(而不是在任务的子函数中)被调用。

注意 2:

在这些调度点进行任务切换所需保存的任务的上下文信息通常较少。

4.6.4 任务组

通过定义任务组,操作系统(OS)允许多个任务与抢占式调度或非抢占式调度的特性相结合。对于任务优先级等于或低于组内最高任务优先级的任务的任务,组内任务的行为类似于不可被抢占的任务:重新调度只能在 4.6.2 节所述的重新调度点进行。对于任务优先级高于组内最高任务优先级的任务的任务,组内任务的行为类似于可被抢占的任务(参见 4.6.1 节)。

8.8 节描述了利用内部资源定义任务组的机制。对于内部资源的概念,不可被抢占的任务是最常见的应用场景。这类任务将被分配一个具有最高任务优先级的特殊内部资源。

4.6.5 混合抢占式调度

如果在同一系统中同时存在可被抢占的任务和不可被抢占的任务,则由此产生的调度策略被称为混合抢占式调度。在这种情况下,调度策略取决于正在被执行的任务的抢占特性。如果正在被执行的任务是不可被抢占的,则执行非抢占式调度。如果正在被执行的任务是可被抢占的,则执行抢占式调度。

在完全抢占式调度的操作系统(OS)中,对不可被抢占的任务的定义才有意义: 
  • 如果执行任务的时间与进行任务切换的时间处于同一数量级
  • 如果要经济高效地利用 RAM(为保存任务的上下文提供空间)
  • 如果该任务不可被抢占

许多应用程序仅包含少量的并行任务,这些任务的执行时间较长,此时完全抢占式调度的操作系统(OS)较为合适。而另一些应用程序则包含许多执行时间(被明确地定义)较短的任务,此时非抢占式调度的操作系统(OS)更为高效。针对这种配置,开发了一种混合抢占式调度策略作为折衷方案(另见 14.3.5 节中的设计提示)。

4.6.6 选择调度策略

软件开发人员或系统集成商通过配置任务优先级并将可被抢占性作为任务属性来确定任务的执行顺序。

任务类型(基本任务或扩展任务)与任务被调度的方式(可被抢占或不可被抢占)无关。因此,完全抢占式调度的系统可以包含基本任务,而非抢占式调度的系统可以包含扩展任务。

如果操作系统(OS)的服务正在运行,则对抢占和上下文切换的执行可能会被延迟到服务结束后。

4.7 任务终止

在操作系统(OS)中,仅当任务终止其自身(自我终止)时才能终止该任务。操作系统(OS)提供 ChainTask 服务,以确保在当前执行的任务被终止后,立即对另一个专门的任务进行激活。此调用会将被激活的任务置于与其任务优先级对应的队列的末尾。

每个任务在其指令被全部执行完毕后都应进行自我终止。任务进行自我终止时,必须调用 TerminateTask 或 ChainTask 函数。否则会导致未被定义的行为。

5 应用程序模式


5.1 概述

应用程序模式旨在允许操作系统(OS)以不同的运行模式启动。应最少支持一种应用程序模式。它仅适用于完全互斥的运行模式。例如,行尾编程模式和正常运行模式就是两种互斥的运行模式。操作系统(OS)启动后,不允许更改其应用程序模式。

5.2 应用程序模式的范围

许多 ECU 可以执行完全独立的应用程序,例如,工厂测试、闪存编程或正常运行。应用程序模式是一种根据不同条件组织在 ECU 中运行的软件的方式,也是一种开发完全独立的系统的简洁机制。通常,每种应用程序模式只使用属于其自身的子集(任务、中断服务例程(ISR)、闹钟和时序条件),同一任务或中断服务例程 (ISR) 可以在不同的应用程序模式下被执行。如果需要使用相同的功能,建议在不同的应用程序模式之间共享任务、中断服务例程 (ISR)、闹钟。如果所使用的功能不完全相同,则需要在运行时(runtime)和资源之间进行权衡:要么(在任务被执行时)动态地对应用程序模式进行检查,要么单独地定义不同的任务。

考虑到系统生成和优化,应用程序模式有助于减少需要考虑的操作系统(OS)的对象的数量。

5.3 启动性能

对于汽车应用中的 ECU 而言,启动性能是一个至关重要的安全问题,因为在正常运行期间可能会出现复位的情况。因此,被用于对应用程序模式进行确定的代码必须是非常简洁的。启动时,不应对任何系统服务进行使用的用户代码(参见图 19)应对应用程序模式进行确定,并应将应用程序模式作为参数传递给系统服务 StartOS

注意:

如果操作系统(OS)与 OSEKtime OS 共存,则应使用传递给 OSEKtime OS 的应用程序模式。

建议仅使用引脚状态或类似的易于被评估的条件来对应用程序模式进行确定。应用程序模式应在操作系统(OS)被启动前被确定,由此产生的代码不具备可移植性。应避免冗长或复杂的启动过程。

被传递给系统服务 StartOS 的应用程序模式允许操作系统(OS)自动地执行正确的子集(任务、中断服务例程(ISR)、闹钟和时序条件)。被自动地执行的子集(任务、中断服务例程(ISR)、闹钟和时序条件)与对应用程序模式的分配应在 ISO 17356-6 中被静态地定义。

5.4 对应用程序模式的支持

应用程序模式不限于特定的致性等级(CC),所有致性等级(CC)都应支持。这不会影响关机功能。不支持在运行时(runtime)中对应用程序模式进行切换。

6 中断处理


6.1 概述

中断(中断服务例程(ISR))被分为两种类别:
  • ISR 类别 1:中断服务例程 (ISR) 不使用操作系统(OS)的服务(系统服务)。(例外情况,某些被用于对中断进行启用和禁用的系统服务,参见表 4。)中断服务例程 (ISR) 被执行完毕后,任务会从中断发生时所处的指令处被继续执行,也就是说,中断不会对任务管理造成影响。此类中断服务例程 (ISR) 的开销最小。
  • ISR 类别 2:操作系统(OS)将提供中断服务例程 (ISR) 帧,被用于为专门的用户例程准备运行时(runtime)。在系统生成过程中,该用户例程将被分配给中断。

在中断服务例程 (ISR) 中,对操作系统(OS)的服务(系统服务)的使用将受到表 4 中的限制。


在中断服务例程 (ISR) 中,不会发生重新调度。如果在执行可被抢占的任务的过程中发生中断且没有其他中断处于被激活的状态,则在 ISR 类别 2 的中断服务例程 (ISR) 被终止时将发生重新调度

该实现确保任务按照调度点被执行(参见 4.6.1)。为此,该实现可以对所有类别的中断服务例程 (ISR) 的中断优先级进行限制,及在配置时进行检查(参见 14.3.4.1)。

中断优先级的最大数量取决于所使用的控制器及具体实现。对中断的调度依赖于硬件,ISO 17356 并未对此进行规定。对中断的调度由硬件完成,而对任务的调度由调度器完成。对于中断优先级,可能存在一些限制(如 14.3.4.1 节所述)。中断可以中断任务(包括可被抢占的任务和不可被抢占的任务)。如果任务是在中断服务例程 (ISR) 中被激活的,则对该任务的调度会在所有被激活的中断服务例程 (ISR) 被终止后进行。

在中断服务例程 (ISR) 中,可以使用在表 4 中被列出的系统服务。

快速禁用/启用 API 函数
ISO 17356 提供了快速禁用所有中断(参见 13.4.2.1 节 EnableAllInterrupts、13.4.2.2 节 DisableAllInterrupts、13.4.2.3 节 ResumeAllInterrupts 和 13.4.2.4 节 SuspendAllInterrupts)的函数及快速禁用所有 ISR 类别 2 的中断(参见 13.4.2.5 节 ResumeOSInterrupts 和 13.4.2.6 节 SuspendOSInterrupts)的函数。典型的用途是保护较短的临界区。中断服务例程 (ISR) 不得在此类受保护的临界区内被调用,“挂起/禁用”操作必须与相应的“恢复/启用”操作配套被使用。在“挂起/禁用”函数和“恢复/启用”函数之间,仅允许对 SuspendOSInterrupts / ResumeOSInterrupts(函数对)或 SuspendAllInterrupts / ResumeAllInterrupts(函数对)进行调用。

7 事件机制


事件机制:
  • 是一种同步方式
  • 仅适用于扩展任务
  • 使任务进入/退出 Waiting 状态

事件是由操作系统(OS)管理的对象。它们并非独立的对象,而是被分配给扩展任务的对象。每个扩展任务都拥有一定数量的事件。该扩展任务被称为这些事件的所有者。每个事件都由其所有者及其名称(或掩码)标识。对扩展任务进行激活时,操作系统(OS)会清除这些事件。事件可被用于向其所属的扩展任务传递二进制信息。事件的含义由应用程序定义(例如,定时器即将到期、资源可用、收到消息等)。

根据特定任务是否为事件或非扩展任务的任务的所有者,存在多种对事件进行操作的方式。所有任务都可以对属于未被挂起的扩展任务的事件进行设置。只有事件的所有者才能对事件进行清除或等待。

事件是扩展任务的任务状态从 Waiting 状态过渡到 Ready 状态的判定依据。操作系统(OS)提供被用于对事件进行设置、清除、查询及等待的系统服务。

任何 ISR 类别 2 的任务或中断服务例程 (ISR) 都可以为未被挂起的扩展任务设置事件,从而改变扩展任务的任务状态。

事件的接收者必须为扩展任务。因此,中断服务例程 (ISR) 或基本任务无法对事件进行等待。事件只能由其所有者清除。扩展任务只能清除其拥有的事件,而基本任务不得使用操作系统(OS)提供的事件清除服务。

对于处于 Waiting 状态的扩展任务,如果存在至少一个其正在等待的事件已发生,则该扩展任务将被释放且其任务状态将被切换为 Ready 状态。如果一个处于 Running 状态的扩展任务尝试对某个事件进行等待,且该事件已经发生,则该任务将仍处于 Running 状态。

10 解释了在完全抢占式调度的情况下,如何通过设置事件对扩展任务进行同步,其中扩展任务 T1 具有更高的任务优先级

10 展示了在设置事件后受影响的流程:任务 T1 对一个事件进行等待。任务 T2 为任务 T1 设置此事件。调度器被激活。随后,任务 T1 的任务状态从 Waiting 状态被切换为 Ready 状态。由于任务 T1 具有更高的任务优先级,将发生任务切换,任务 T2 将被任务 T1 抢占。任务 T1 将对该事件进行清除。随后,任务 T1 再次对该事件进行等待,调度器将继续对任务 T2 进行执行。


如果在非抢占式调度的情况下,在设置事件后不会立即发生重新调度(参见图 11,其中扩展任务 T1 具有更高的任务优先级)。


8 资源管理


8.1 概述

资源管理被用于协调多个不同任务优先级的任务对共享资源(例如,管理实体(调度器)、程序序列、内存或硬件)的并发访问。

资源管理对于所有致性等级(CC)都是强制性的。

可以选择性地对资源管理进行扩展,以协调任务和中断服务例程 (ISR) 的并发访问。

资源管理将确保:
  • 两个任务不会同时对同一资源进行占用
  • 不会发生优先级反转
  • 对资源进行使用不会导致死锁
  • 对资源进行访问永远不会导致任务状态被切换为 Waiting 状态

如果将资源管理扩展到中断级别,则可以进一步地确保两个任务或中断服务例程 (ISR) 不会同时对同一资源进行占用。

在以下情况下,资源管理将变得非常有用:
  • 可被抢占的任务
  • 如果希望按照其他调度策略执行应用程序,则应使用不可被抢占的任务
  • 任务和中断服务例程 (ISR) 间的资源共享
  • 中断服务例程 (ISR) 间的资源共享

如果不仅需要禁用由任务引起的中断,还需要禁用由中断引起的中断,则可以使用操作系统(OS)的服务来启用/禁用中断以避免发生重新调度(参见第 6 节和第 13.4 节)。

8.2 在对被占用的资源进行访问期间的行为

操作系统(OS)规定了优先级上限协议(见 8.6 节)。因此,在任务或中断尝试对已被占用的资源进行访问的情况下不会出现问题。

如果使用资源的概念对任务和中断进行协调,操作系统(OS)还会确保只有当所有在中断服务例程 (ISR) 被执行期间可能会被占用的资源都已被释放时,才会对中断服务例程 (ISR) 进行执行。

ISO 17356 禁止对同一资源进行嵌套式访问。在极少数需要进行嵌套式访问的情况下,建议使用其行为与第一个资源的行为相同的第二个资源。ISO 17356-6 支持对行为相同的资源(即所谓的“链接资源”)进行定义。

8.3 资源的使用限制

当资源被占用时,不得对 TerminateTaskChainTaskScheduleWaitEvent 进行使用。当其所需的资源被占用时,不得对中断服务例程 (ISR) 进行执行。

如果同一个任务占用了多个资源,应遵循 LIFO(后进先出)的原则(类似堆栈)对资源进行请求和释放。

8.4 作为资源的调度器

如果一个任务需要防止其自身被其他任务抢占,可以对调度器进行锁定。调度器被视为一种所有任务都可以对其进行访问的资源。因此,系统会生成一个预定义名称为 RES_SCHEDULER 的资源。

对中断的接收和处理独立于资源 RES_SCHEDULER 的状态。资源 RES_SCHEDULER 可以阻止对任务的重新调度

8.5 同步机制的一般问题

8.5.1 对优先级反转的解释

常见的同步机制(例如,信号量)的一个典型问题是优先级反转。这意味着低任务优先级的任务会阻塞对高任务优先级的任务的执行。ISO 17356 规定了优先级上限协议(参见 8.6 节)来避免优先级反转

12 展示了两个任务对同一信号量进行访问的顺序(在完全抢占式调度的系统中,任务 T1 的任务优先级最高)。较低任务优先级的任务 T4 占用了信号量 S1。任务 T1 抢占了任务 T4 并对相同的信号量进行请求。由于信号量 S1 已被占用,任务 T1 的任务状态被切换为 Waiting 状态。此时,较低任务优先级的任务 T4 被任务优先级介于任务 T1 和任务 T4 之间的任务中断及抢占。只有在所有低任务优先级的任务被终止且信号量 S1 被释放后,任务 T1 才能被执行。虽然任务 T2 和 T3 不使用信号量 S1,但对它们的执行会阻塞对任务 T1 的执行。


8.5.2 死锁

另一个常见的同步机制(例如,信号量)的典型问题是死锁。在这种情况下,死锁意味着由于对被相互锁定的资源的无限等待而导致任务无法被执行。

以下场景会导致死锁(参见图 13):

任务 T1 对信号量 S1 进行占用,随后它的任务状态被切换为 Waiting 状态(例如,它正在对某个事件进行等待)。因此,较低任务优先级的任务 T2 的任务状态被切换为 Running 状态。它对信号量 S2 进行占用。如果任务 T1 在其任务状态被切换为 Ready 状态时尝试对信号量 S2 进行占用,则它的任务状态将再次被切换为 Waiting 状态。如果随后任务 T2 尝试对信号量 S1 进行占用,则会导致死锁。


8.6 优先级上限协议

为了避免出现优先级反转和死锁的问题,操作系统(OS)要求如下行为:
  • 在系统生成时,每个资源都应被静态地分配一个优先级上限。该优先级上限应至少等于所有对该资源或与该资源关联的其他资源进行访问的任务中任务优先级最高的任务的任务优先级。该优先级上限应低于所有不对该资源进行访问的任务中任务优先级最低的任务的任务优先级,但前提是这些任务的任务优先级必须高于所有对该资源进行访问的任务中任务优先级最高的任务的任务优先级
  • 如果一个任务对资源进行请求,并且其当前任务优先级低于该资源的优先级上限,则该任务的任务优先级应被提升至该资源的优先级上限。
  • 如果一个任务对资源进行了释放,则该任务的任务优先级应被重置为在对资源进行请求之前被动态地分配的任务优先级

优先级上限协议将可能导致任务优先级等于或低于资源的优先级上限的任务被延迟。此延迟取决于任何低任务优先级的任务对资源进行占用的最大时间。

由于其任务优先级低于或等于正在被执行的任务,将对正在被执行的任务占用的资源进行占用的任务的任务状态将不会被切换为 Running 状态。如果某个任务占用的资源被释放,则另一个将对该资源进行占用的任务的任务状态将被切换为 Running 状态。对于可被抢占的任务,这是一个进行重新调度的节点。

14 中的示例对优先级上限协议进行了说明。任务 T0 的任务优先级最高,任务 T4 的任务优先级最低。任务 T1 和任务 T4 都想对同一资源进行访问。系统清楚地表明,不会出现无限制的优先级反转。高任务优先级的任务 T1 的等待时间将短于任务 T4 对资源进行占用的最大时间。


8.7 带有中断优先级扩展的优先级上限协议

资源管理的中断优先级扩展是可选的。

为了确定在中断中被使用的资源的优先级上限,应为中断分配高于所有任务的任务优先级的虚拟中断优先级。对软件优先级和硬件中断级别的操作由具体实现决定。
  • 在系统生成时,每个资源都应被静态地分配一个优先级上限。该优先级上限应至少等于所有对该资源或与该资源关联的其他资源进行访问的任务和中断服务例程 (ISR) 中任务优先级/中断优先级最高的任务/中断的任务优先级/中断优先级。该优先级上限应低于所有不对该资源进行访问的任务和中断服务例程 (ISR) 中任务优先级/中断优先级最低的任务/中断的任务优先级/中断优先级,但前提是这些任务和中断服务例程 (ISR) 的任务优先级/中断优先级必须高于所有对该资源进行访问的任务和中断服务例程 (ISR) 中任务优先级/中断优先级最高的任务/中断的任务优先级/中断优先级
  • 如果一个任务或中断服务例程 (ISR) 对资源进行请求,并且其当前任务优先级/中断优先级低于该资源的优先级上限,则该任务或中断服务例程 (ISR) 的任务优先级/中断优先级应被提升至该资源的优先级上限。
  • 如果一个任务或中断服务例程 (ISR) 对资源进行了释放,则该任务或中断服务例程 (ISR) 的任务优先级/中断优先级应被重置为在对资源进行请求之前被动态地分配的任务优先级/中断优先级

由于其任务优先级/中断优先级低于或等于正在被执行的任务或中断服务例程 (ISR),将对正在被执行的任务或中断服务例程 (ISR) 占用的资源进行占用的任务或中断服务例程 (ISR) 的任务状态将不会被切换为 Running 状态(对于中断服务例程 (ISR),其将不会被执行)。如果某个任务占用的资源被释放,则另一个将对该资源进行占用的任务或中断服务例程 (ISR) 的任务状态将被切换为 Running 状态(对于中断服务例程 (ISR),其将被执行)。对于可被抢占的任务(如果为该任务分配的新的任务优先级不是为中断分配的虚拟中断优先级),这是一个进行重新调度的节点。

图 15 中的示例对带有中断优先级扩展的优先级上限协议进行了说明。可被抢占的任务 T1 正在被执行,并对与中断服务例程 (ISR) INT1 共享的资源进行请求。任务 T1 对更高任务优先级的任务 T2 和 T3 进行激活。由于优先级上限协议,任务 T1 将仍处于 Running 状态。中断 INT1 发生。由于优先级上限协议,任务 T1 将仍处于 Running 状态,中断 INT1 将被挂起。中断 INT2 发生,中断服务例程 (ISR) INT2 将中断任务 T1 并被执行。中断服务例程 (ISR) INT2 被终止后,任务 T1 将继续被执行。任务 T1 对资源进行释放。中断服务例程 (ISR) INT1 将中断任务 T1 并被执行。中断服务例程 (ISR) INT1 被终止后,任务 T3 将被执行。任务 T3 被终止后,任务 T2 将被执行。任务 T2 被终止后,任务 T1 将继续被执行。


图 16 中的示例对带有中断优先级扩展的优先级上限协议进行了说明。可被抢占的任务 T1 正在被执行。中断 INT1 发生。任务 T1 被中断,中断服务例程 (ISR) INT1 被执行。中断服务例程 (ISR) INT1 对与中断服务例程 (ISR) INT2 共享的资源进行请求。更高中断优先级的中断 INT2 发生。由于优先级上限协议,中断服务例程 (ISR) INT1 仍将被执行,中断 INT2 将被挂起。中断 INT3 发生。由于中断 INT3 的中断优先级高于中断 INT1,它将中断中断服务例程 (ISR) INT1 并被执行。中断服务例程 (ISR) INT3 对任务 T2 进行激活。中断服务例程 (ISR) INT3 被终止后,中断服务例程 (ISR) INT1 将继续被执行。中断服务例程 (ISR) INT1 对资源进行释放,由于中断 INT2 的中断优先级高于中断 INT1,中断服务例程 (ISR) INT2 被执行。中断服务例程 (ISR) INT2 被终止后,中断服务例程 (ISR) INT1 将继续被执行。中断服务例程 (ISR) INT1 被终止后,由于任务 T2 的任务优先级高于任务 T1,任务 T2 将被执行,而任务 T1 的任务状态将被切换为 Ready 状态。任务 T2 被终止后,任务 T1 将继续被执行。


8.8 内部资源

内部资源是指对于用户为不可见的资源,因此无法通过系统服务 GetResourceReleaseResource 对其进行访问。应通过一组被明确地定义的系统服务对其进行严格地内部管理。此外,内部资源的行为与标准资源的行为完全相同(例如,优先级上限协议等)。

内部资源仅限于任务。系统生成过程中,每个任务最多只能被分配一个内部资源。如果某个任务被分配了内部资源,则对该内部资源的管理方式如下:
  • 当任务的任务状态被切换为 Running 状态时(而非被激活时),其内部资源将被自动地占用,除非该任务已对该资源进行了占用。因此,该任务的任务优先级将被自动地更新为其内部资源的优先级上限。
  • 根据 4.6.2 节的定义,在需要进行重新调度时,内部资源应被自动地释放。可对具体实现进行优化,例如,仅在需要进行重新调度时才在系统服务 Schedule 中对内部资源进行获取或释放。

注意:

当任务被抢占时,内部资源将不会被释放。

4.6.4 节描述了被分配了相同的内部资源的任务的行为。不可被抢占的任务是一类特殊的任务,它们被分配了任务优先级与 RES_SCHEDULER 的任务优先级相同的内部资源(参见 4.6.2 节)。当需要避免在任务组内发生不必要的重新调度时,可以对内部资源进行使用。在一个系统中可以对多个任务组(多个内部资源)进行定义。14.3.6 节中提供了一个典型示例。

某些系统服务必须在资源被占用时才能被调用(参见 8.3 节),而这个限制不适用于内部资源,因为内部资源将在这些系统服务中被处理。但是,所有标准资源都必须在内部资源被释放之前被释放(参见 8.3 节)。

被分配了相同的内部资源的任务将涵盖一定的任务优先级范围。同一任务优先级范围内也可能存在未对此内部资源进行使用的任务。应用程序应判断这种情况是否合理。

9 闹钟


9.1 概述

操作系统(OS)提供对周期性事件进行处理的服务。此类事件可以是定时器定期发出的中断,也可以是轴上的编码器在凸轮轴或曲轴的角度持续发生变化时产生的中断,或其他特定于应用程序的常规触发源。

操作系统(OS)采用两阶段机制对此类事件进行处理。周期性事件(触发源)由特定于实现的计数器进行注册。操作系统(OS)基于这些计数器,为应用程序提供闹钟机制。

9.2 计数器

计数器由一个计数器值(以“滴答”为单位)及一些计数器特定的常量表示。

操作系统(OS)不提供直接地对计数器进行操作的标准化 API。

操作系统(OS)负责处理对计数器递增时的闹钟的管理及计数器的递增方式等必要操作。

操作系统(OS)应至少提供一个由(硬件或软件)定时器派生的计数器。

9.3 闹钟管理

操作系统(OS)提供被用于激活任务、设置事件或在闹钟到期时对闹钟回调例程进行调用的服务。闹钟回调例程是由应用程序提供的函数。

当达到被预定义的计数器值时,闹钟将到期。该计数器值可以被定义为(相对于上一次到期时的计数器值)相对值(相对闹钟),也可以被定义为绝对值(绝对闹钟)。例如,闹钟可以在收到一定数量的定时器中断、达到特定的角度位置或收到消息时到期。

闹钟可以被定义为单次闹钟或循环闹钟。此外,操作系统(OS)还提供被用于取消闹钟或获取闹钟的当前状态的服务。

一个计数器可以关联多个闹钟。

闹钟在系统生成时将被静态地分配给:
  • 一个计数器
  • 一个任务或一个闹钟回调例程

根据配置,当闹钟到期时,将调用闹钟回调例程、激活任务或为任务设置一个事件。闹钟回调例程可在禁用 ISR 类别 2 的中断的情况下被执行。闹钟回调例程中允许对在表 4 中被列出的系统服务进行使用。在闹钟到期时激活任务和设置事件与普通情况下激活任务和设置事件没有区别。

计数器和闹钟是被静态地定义的。闹钟到计数器的映射关系及闹钟到期时要执行的操作也是被静态地定义的。

动态参数包括闹钟到期时的计数器值和循环闹钟的周期。


9.4 闹钟回调例程

闹钟回调例程不能带有参数或返回值。

闹钟回调例程的原型应遵循以下格式:

ALARMCALLBACK(AlarmCallbackRoutineName);

闹钟回调例程示例:

ALARMCALLBACK(BrakePedalStroke)
{
    /* do application processing */
}

闹钟回调例程的中断优先级取决于具体实现。

10 消息


为了符合 ISO 17356-4,具体实现必须具备消息处理功能(处理器内部通信)。最低的功能要求应符合 ISO 17356-4CCCACCCB 是唯一可被接受的其他标准,因为它是 CCCA 的超集。

如果具体实现提供了 ISO 17356-4 中被描述的其他一致性等级(CC)所规定的更多功能,则该实现必须遵循 ISO 17356-4 中相应功能的语法和语义。

请注意,ISO 17356-4 中被规定的关于消息的规则同样适用于本文档。例如,ISO 17356-4 中系统接口不会对 ErrorHook 进行调用。但是,如果 ISO 17356-4 的功能在内部使用了系统服务(例如,ActivateTask),则 ActivateTask 应在必要时调用 ErrorHook。更多详情,请参阅 ISO 17356-4

11 错误处理、跟踪和调试


11.1 Hook 例程

操作系统(OS)提供系统特定的 Hook 例程,允许在操作系统(OS)的内部处理过程中执行用户自定义的操作。这些 Hook 例程:
  • 由操作系统(OS)调用,存在于特定的上下文中(取决于操作系统(OS)的具体实现)
  • 优先级高于所有任务
  • 不会被 ISR 类别 2 的中断服务例程 (ISR) 中断
  • 为操作系统(OS)的一部分
  • 由用户实现(由用户定义的功能)
  • 为标准化接口,但其功能(Hook 例程的运行时环境和行为)未被标准化,因此 Hook 例程通常不具备可移植性
  • 仅允许对部分 API 函数(见表 4)进行使用
  • 为强制性的,但可通过 ISO 17356-6 对其进行配置

在操作系统(OS)中,Hook 例程可被用于: 
  • 系统启动(参见 11.3 节):相应的 Hook 例程(StartupHook)在操作系统(OS)启动后、调度程序运行前被调用
  • 系统关闭(参见 11.4 节):当应用程序或操作系统(OS)出现严重错误并请求系统关闭时,将调用相应的 Hook 例程(ShutdownHook
  • 被用于跟踪或与应用程序相关的调试,以及由用户定义的上下文切换的扩展(参见 11.5 节)
  • 错误处理

每个操作系统(OS)的具体实现都应描述 Hook 例程的约定。

如果应用程序在 Hook 例程中调用了未经允许的 API 服务,则其行为为未被定义的。如果发生错误,具体实现应返回特定于实现的错误代码。

大多数操作系统(OS)的服务不被允许在 Hook 例程中被使用。此限制是为了降低系统复杂性。

11.2 错误处理

11.2.1 一般性说明

操作系统(OS)提供错误服务以对临时性错误永久性错误进行处理。其基本框架已被预定义,用户需自行完善。这使得用户可以选择高效的集中式错误处理或分散式错误处理。

错误被分为两种类型:
  • 应用程序错误:操作系统(OS)无法正确地执行被请求的服务,但会保证其内部数据的正确性。在这种情况下,将调用集中式错误处理。此外,操作系统(OS)还会返回状态信息以进行分散式错误处理。用户需根据发生的错误类型决定采取何种措施。
  • 致命错误:操作系统(OS)无法保证其内部数据的正确性。在这种情况下,操作系统(OS)将集中地调用系统关闭。

所有这些错误服务都将被分配一个参数来指定其错误类型。

操作系统(OS)应提供两种级别的错误检查:标准状态和扩展状态。如果任务以标准状态被激活,则可能的返回结果为“E_OK”或“任务被激活的次数过多”。如果任务以扩展状态被激活,则可能的返回结果还可以为“任务无效”或“任务仍对资源进行占用”等附加的返回值。在目标应用程序被执行时,这些附加的返回值不再被需要,也就是说,相应的错误不会被操作系统(OS)的运行时环境拦截。

API 服务的返回值的优先级应高于输出参数。如果 API 服务返回错误,则输出参数的值为未被定义的。

11.2.2 错误 Hook 例程

如果系统服务返回的 StatusType 类型的值不等于 E_OK,则会对错误 Hook 例程 (ErrorHook) 进行调用。如果在 ErrorHook 中对系统服务进行使用,则不会对 ErrorHook(即不会出现对 ErrorHook 的递归调用)进行调用。只能通过系统服务的返回值来检测在 ErrorHook 中使用系统服务而导致的错误。

如果在内部对任务进行激活或对事件进行设置的期间检测到错误,例如,在闹钟到期或消息到达时,也会对 ErrorHook 进行调用。

11.2.3 错误管理

为了在 ErrorHook 中实现有效的错误管理,用户可以对附加信息进行访问。图 18 总结了错误管理的逻辑架构。

宏 OSErrorGetServiceId 提供了引发错误的服务标识符。服务标识符的类型为 OSServiceIdType。可能的值为 OSServiceId_xxxx,其中 xxxx 为系统服务的名称。必须对 OSErrorGetServiceId 进行实现。如果提供了对 ErrorHook 进行调用的系统服务的参数,则应使用以下访问宏名称来构建方案:OSError_Name1_Name2,其中:
  • Name1:系统服务的名称
  • Name2:ISO 17356-3 中该参数的正式名称

例如,对 SetRelAlarm 的参数进行访问的宏如下:
  • OSError_SetRelAlarm_AlarmID
  • OSError_SetRelAlarm_increment
  • OSError_SetRelAlarm_cycle

如果系统服务的第一个参数是对象标识符,则对该参数进行访问的宏是必需的。为了优化性能,可以在 ISO 17356-6 中禁用访问宏。


11.3 系统启动

处理器被复位后的初始化取决于具体实现,但操作系统(OS)支持标准化的初始化方式。

硬件、操作系统(OS)和应用程序的初始化接口应由具体实现明确地定义。

ISO 17356 的这一部分并未强制应用程序去定义在操作系统(OS)被初始化后被执行的特殊任务,但允许用户在系统生成期间指定被自动地执行的任务和被自动地启动的闹钟。

处理器被复位后,将执行特定于硬件(非可移植)的应用程序软件(无操作系统(OS)上下文)。该应用程序软件最后将对应用程序模式进行检测。出于安全考虑,此检测不应依赖于系统历史记录。

如果操作系统(OS)与 OSEKtime OS 共存(图 19 中未反映),则应始终先执行对 OSEKtime OS 的初始化,对 ISO 17356 其余部分的初始化应在 OSEKtime OS 执行空闲(idle)任务后被执行,这将导致 OSEKtime OS 自动地对 StartOS 进行调用,并应将应用程序模式作为参数传递给 OSEKtime OS。

否则,应用程序的可移植部分将以对启动操作系统(OS)的函数进行调用开始,即对 StartOS 进行调用,并将应用程序模式作为参数传递。操作系统(OS)被初始化完成后(此时调度器尚未运行),StartOS 会对 Hook 例程 StartupHook 进行调用,可以在其中放置所有与操作系统(OS)相关的初始化代码。为了根据启动时的应用程序模式来组织 StartupHook 中的初始化代码,系统提供了系统服务 GetActiveApplicationMode。从该 Hook 例程返回后,操作系统(OS)将启用中断并启动调度器。之后,系统即可运行并执行用户的任务。


系统启动包含以下步骤(参见图 19):
  • a) 复位后,用户可以执行特定于硬件(非可移植)的代码。在第 5 阶段之前,不允许执行 ISR 类别 2 的中断服务例程 (ISR) 或系统服务。非可移植部分将以对应用程序模式进行检测结束
  • b) 对 StartOS 进行调用,并将应用程序模式作为参数传递。此调用将启动操作系统(OS)(如果存在 OSEKtime OS,则此操作将被自动地完成)
  • c) 操作系统(OS)执行内部启动函数
  • d) 操作系统(OS)调用 Hook 例程 StartupHook,可以在其中放置初始化代码。在执行此 Hook 例程期间,所有中断均被禁用
  • e) 操作系统(OS)启用中断并启动调度程序。操作系统(OS)将启动与当前应用程序模式对应的应被自动地启动的任务和闹钟。对任务优先级相同且应被自动地执行的任务的激活顺序未被定义。(自动地)对任务的激活应先于(自动地)对闹钟的启动

注意

如果可能,在系统初始化时会在(自动地)对闹钟进行启动之前将计数器清零(日历定时器等除外)。对于被自动地启动的闹钟,所有值均为相对值。

11.4 系统关闭

ISO 17356-3 定义了一个名为 ShutdownOS 的系统服务,被用于关闭操作系统(OS)。

当应用程序或操作系统(OS)发生致命错误时都可以请求此服务。

调用 ShutdownOS 时,操作系统(OS)应调用 Hook 例程 ShutdownHook,然后关闭。

通常用户可以自由地在 ShutdownHook 中定义任何系统行为,例如,不从该 Hook 例程返回(参见 13.8.2.3)。但是,如果操作系统(OS)与 OSEKtime OS 共存,则在 ShutdownHook 中可被执行的功能会受到限制。可能只有操作系统(OS)被关闭,而 OSEKtime OS 不受影响。因此,在 ShutdownHook 中不应对在 OSEKtime OS 中被处理的 I/O 设备进行重置,并且 ShutdownHook 应返回。

11.5 调试

在切换任务上下文时会对两个 Hook 例程(PreTaskHook 和 PostTaskHook)进行调用。

这两个 Hook 例程可被用于调试或时间测量(包括上下文切换时间)。因此,每次在上一个任务的任务状态被切换为 Suspended 状态之前都会对 PostTaskHook 进行调用。每次在新的任务的任务状态被切换为 Running 状态之后都会对 PreTaskHook 进行调用。由于任务仍/已处于 Running 状态,(在这两个 Hook 例程中)对 GetTaskId 进行调用不会返回 INVALID_TASK。

在任务被执行时调用 ShutdownOSShutdownOS 可能会对 PostTaskHook 进行调用,也可能不会。如果对 PostTaskHook 进行了调用,则对其进行调用的具体时间(在 ShutdownHook 之前或之后)未被定义。


12 Description of system services 


12.1 Definition of system objects 

Within the OS, all system objects shall be determined statically by the user. The OS supplier shall provide the definition of the OS objects. The actual creation of the objects (unique names and specific characteristics) is done during the system generation phase. The declarations done in the application source are external references to those OS objects. There are no system services available to dynamically create system objects. Declarations provide information that a system object is being used which has been created at another location. The names are used as identifiers within the system services. 

Usually the scope of those names is like an external variable in C-language. 

Internal representation of system objects is implementation-specific. There are various alternatives for implementation of system objects. For example, a TaskType could be implemented either as a pointer to the data structure of the task or as an index to the corresponding list element. Application programmers shall not assume a specific representation. 

The creation of system objects may require additional tools that enable the user to add or to modify values which have been specified in definitions. Consequently, the system generation and the tools used to this effect are also implementation-specific. 

12.2 Conventions 

12.2.1 Type of calls 

The system service interface is ISO/ANSI-C. Its implementation is normally a function call, but may also be solved differently, as required by the implementation, by macros of the C pre-processor, for example. A specific type of implementation shall not be assumed. 

12.2.2 Legitimacy of calls 

System services are called from tasks, interrupt service routines, hook routines, and alarm-callbacks. Depending on the system service, there may be restrictions regarding their availability. Further restrictions are imposed by the conformance classes. 

Table 4 lists all system services and shows in which situation they are allowed to be called (9).


12.2.3 Error characteristics 

To keep the system efficient and fast, the OS does not test all errors. If the application uses OS services incorrectly, undefined system behaviour may result. 

Most system services return a status to the user. The return status is E_OK if it was possible to execute the system service without any restrictions. If the system recognizes an exceptional condition which restricts execution of the system service, a different status is returned. 

A status other than E_OK may be information which is not considered to be an error ("warning"). An example is the return status of the system service CancelAlarm, which informs that the alarm to be cancelled has already expired. A user program is thus informed that e.g. a task activation has taken place which was not wanted. The detection of "warnings" is part of the system services.

If it is possible to exclude errors before run time, the run time version may omit checking of these errors. If the only possible return status is E_OK, the implementation is free not to return a status. 

All return values of a system service are listed under the individual descriptions. The return status distinguishes between the "standard" and "extended" status. The "standard" version fulfils the requirements of a debugged application system as described before. With respect to the description above, a status other than E_OK which is returned in standard mode is a "warning". The "extended" version is considered to support testing of not yet fully debugged applications. It comprises extended error checking compared to the standard version. 

The sequence of error checking within the OS is not specified. Whenever multiple errors occur, it is implementation-dependent which status is returned to the application. 

In case of application errors, the OS shall call the hook routine ErrorHook if defined. The purpose of ErrorHook is to treat status information as centralized. 

The ErrorHook routine is only called if a return value other than E_OK is generated. 

The ErrorHook routine is configured within the ISO 17356-6 file. 

For ErrorHook routine management, the standard mode corresponding to standard status management is distinguished from the extended mode corresponding to extended status management. 

The system passes additional information to the ErrorHook routine. For performance reasons and stack consumption, a global structure including complementary information about the last error is used. This global structure is filled at execution time depending on given services and given implementation constraints. To allow efficient and adaptive implementation, the format of this error management structure is not prescribed. However, in order to achieve source code portability in the ErrorHook routine, standardized macros to access to the different parameters are defined. 

In case of fatal errors, the system service does not return to the application, but activates ShutdownOS. An example is a non-detected incorrect parameter of a system service which generates an inconsistency in the system. The parameter passed to ShutdownOS is an implementation dependent system error code. System error codes occupy a range of numbers of their own and do not conflict with the states of the OS services. 

The functionality of ShutdownOS is implementation-specific. Possible implementations are to stop the application or to issue an assertion. The application itself can access ShutdownOS to shut down the OS in a controlled fashion. 

Calling of ShutdownOS is also recommended when processing non-assignable errors, for example "illegal instruction code". This is not mandatory because hardware support is necessary, which cannot be taken for granted.

13 Specification of OS services 


13.1 Basics 

13.1.1 Structure of the description 

OS services are arranged in logical groups. A coherent description is provided for all services of the task management, the interrupt management, etc. 

The description of each logical group starts with data type definitions. A description of the group-specific constructional elements and system services follows. The last items are a description of constants, and of any additional conventions.

13.1.2 Constructional elements 

The description of constructional elements contains the following fields:  
  • Syntax: Interface in C-like syntax;  
  • Parameter (In): List of all input parameters;  
  • Description: Explanation of the constructional element;  
  • Particularities: Explanation of restrictions relating to the utilization;  
  • Conformance: Specifies the conformance classes where the constructional element is provided. 

13.1.3 Service description 

A service description contains the following fields:  
  • Syntax: Interface in C-like syntax;  
  • Parameter (In): List of all input parameters;  
  • Parameter (Out): List of all output parameters;  
  • Description: Explanation of the functionality of the OS service;  
  • Particularities: Explanation of restrictions relating to the utilization of the OS service;  
  • Status: List of possible return values:  
    • Standard: List of return values provided in the OS's standard version. Special case: Service does not return;  
    • Extended: List of additional return values in the OS's extended version;  
  • Conformance: Specifies the conformance classes where the operating system service is provided. 

The specification of OS services uses the following naming conventions for data types:  
  • ...Type: Describes the values of individual data (including pointers);  
  • ...RefType: Describes a pointer to the ...Type (for call by reference).

13.2 Common data types 

13.2.1 StatusType 

This data type is used for all status information the API services offer. Naming convention: all errors for API services shall start with E_. Those reserved for the OS shall begin with E_OS_. 

The normal return value is E_OK which is associated with the value 0. 

The following error values are defined.

13.2.2 All errors of API services

  • E_OS_ACCESS = 1,  
  • E_OS_CALLEVEL = 2,  
  • E_OS_ID = 3,  
  • E_OS_LIMIT = 4,  
  • E_OS_NOFUNC = 5,  
  • E_OS_RESOURCE = 6,  
  • E_OS_STATE = 7, 
  • E_OS_VALUE = 8. 

If the only possible return status is E_OK, the implementation is free not to return a status; this is not separately stated in the description of the individual services.

13.2.3 Internal errors of the OS 

These errors are implementation-specific and not part of the portable section. The error names reside in the same name-space as the errors for API services mentioned above, i.e. the range of numbers shall not overlap. 

To show the difference in use, the names internal errors shall start with E_OS_SYS_ 

Examples:
  • E_OS_SYS_STACK, 
  • E_OS_SYS_PARITY, 
  • ... and other implementation-specific errors, which shall be described in the vendor-specific documentation. 

The names and range of numbers of the internal errors of the OS do not overlap the names and range of numbers of other services (i.e. communication and network management) or the range of numbers of the API error values. For details please refer to the ISO 17356-2. 

13.3 Task management 

13.3.1 Data types 

  • TaskType: This data type identifies a task. 
  • TaskRefType: This data type points to a variable of TaskType. 
  • TaskStateType: This data type identifies the state of a task. 
  • TaskStateRefType: This data type points to a variable of the data type TaskStateType.

13.3.2 Constructional elements 

13.3.2.1 DeclareTask  

  • Syntax: DeclareTask ( <TaskIdentifier> );  
  • Parameter (In):  
    • TaskIdentifier: Task identifier (C-identifier);  
  • Description: DeclareTask serves as an external declaration of a task. The function and use of this service are similar to that of the external declaration of variables.  
  • Particularities: -  
  • Conformance: BCC1, BCC2, ECC1, ECC2. 

13.3.3 System services 

13.3.3.1 ActivateTask  

  • Syntax: StatusType ActivateTask ( TaskType <TaskID> );  
  • Parameter (In):  
    • TaskID: Task reference;  
  • Parameter (Out): none;  
  • Description: The task <TaskID> is transferred from the suspended state into the ready state. (ActivateTask will not immediately change the state of the task in case of multiple activation requests. If the task is not suspended, the activation will only be recorded and performed later.) The OS ensures that the task code is being executed from the first statement.  
  • Particularities: The service may be called from interrupt level and from task level (see Table 4). Rescheduling after the call to ActivateTask depends on the place it is called from (ISR, non-preemptable task, preemptable task). If E_OS_LIMIT is returned the activation is ignored. When an extended task is transferred from suspended state into ready state all its events are cleared.  
  • Status:  
    • Standard:
      • No error, E_OK;  
      • Too many task activations of <TaskID>, E_OS_LIMIT;  
    • Extended: Task <TaskID> is invalid, E_OS_ID;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.3.3.2 TerminateTask  

  • Syntax: StatusType TerminateTask (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: This service causes the termination of the calling task. The calling task is transferred from the running state into the suspended state. (In case of tasks with multiple activation requests, terminating the current instance of the task automatically puts the next instance of the same task into the ready state.)  
  • Particularities: An internal resource assigned to the calling task is automatically released. Other resources occupied by the task shall be released before the call to TerminateTask. If a resource is still occupied in standard status, the behaviour is undefined. If the call was successful, TerminateTask does not return to the call level and the status cannot be evaluated. If the version with extended status is used, the service returns in case of error, and provides a status which can be evaluated in the application. If the service TerminateTask is called successfully, it enforces a rescheduling. A task function shall not be ended without a call to TerminateTask or ChainTask, as this may leave the system in an undefined state.  
  • Status:  
    • Standard: No return to call level;  
    • Extended:  
      • Task still occupies resources, E_OS_RESOURCE;  
      • Call at interrupt level, E_OS_CALLEVEL;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.3.3.3 ChainTask  

  • Syntax: StatusType ChainTask (TaskType <TaskID>);  
  • Parameter (In):  
    • TaskID: Reference to the sequential succeeding task to be activated;  
  • Parameter (Out): none;  
  • Description: This service causes the termination of the calling task. After termination of the calling task, a succeeding task <TaskID> is activated. Using this service, it ensures that the succeeding task starts to run at the earliest after the calling task has been terminated.  
  • Particularities: If the succeeding task is identical with the current task, this does not result in multiple requests. The task is not transferred to the suspended state. An internal resource assigned to the calling task is automatically released, even if the succeeding task is identical with the current task. Other resources occupied by the calling task shall be released before ChainTask is called. If a resource is still occupied in standard status the behaviour is undefined. If called successfully, ChainTask does not return to the call level and the status cannot be evaluated. In case of error, the service returns to the calling task and provides a status which can then be evaluated in the application. If the service ChainTask is called successfully, this enforces a rescheduling. Ending a task function without call to TerminateTask or ChainTask is strictly forbidden and may leave the system in an undefined state. If E_OS_LIMIT is returned the activation is ignored. When an extended task is transferred from suspended state into ready state, all its events are cleared.
  • Status:  
    • Standard:  
      • No return to call level;  
      • Too many task activations of <TaskID>, E_OS_LIMIT;  
    • Extended:  
      • Task <TaskID> is invalid, E_OS_ID;  
      • Calling task still occupies resources, E_OS_RESOURCE;  
      • Call at interrupt level, E_OS_CALLEVEL;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.3.3.4 Schedule  

  • Syntax: StatusType Schedule (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: If a higher-priority task is ready, the internal resource of the task is released, the current task is put into the ready state, its context is saved and the higher-priority task is executed. Otherwise the calling task is continued.  
  • Particularities: Rescheduling can only take place if an internal resource is assigned to the calling task during system generation. For these tasks, Schedule enables a processor assignment to other tasks with lower or equal priority than the ceiling priority of the internal resource and higher priority than the priority of the calling task in application-specific locations. When returning from Schedule, the internal resource has been taken again. This service has no influence on tasks with no internal resource assigned (preemptable tasks).  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended:  
      • Call at interrupt level, E_OS_CALLEVEL;  
      • Calling task occupies resources, E_OS_RESOURCE;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.3.3.5 GetTaskID  

  • Syntax: StatusType GetTaskID (TaskRefType <TaskID>);  
  • Parameter (In): none;
  • Parameter (Out):  
    • TaskID: Reference to the task which is currently running;  
  • Description: GetTaskID returns the information about the TaskID of the task which is currently running.  
  • Particularities: Allowed on task level, ISR level and in several hook routines (see Table 4). This service is intended to be used by library functions and hook routines. If <TaskID> can't be evaluated (no task currently running), the service returns INVALID_TASK as TaskType.  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended: No error, E_OK; 
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.3.3.6 GetTaskState  

  • Syntax: StatusType GetTaskState (TaskType <TaskID>, TaskStateRefType <State>);  
  • Parameter (In):  
    • TaskID: Task reference;  
  • Parameter (Out):  
    • State: Reference to the state of the task <TaskID>;  
  • Description: Returns the state of a task (running, ready, waiting, suspended) at the time of calling GetTaskState.  
  • Particularities: The service may be called from interrupt service routines, task level, and some hook routines (see Table 4). When a call is made from a task in a full preemptive system, the result may already be incorrect at the time of evaluation. When the service is called for a task, which is multiply activated, the state is set to running if any instance of the task is running.  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended: Task <TaskID> is invalid, E_OS_ID;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.3.4 Constants 

The following are constants:  
  • RUNNING: Constant of data type TaskStateType for task state running;  
  • WAITING: Constant of data type TaskStateType for task state waiting;  
  • READY: Constant of data type TaskStateType for task state ready;  
  • SUSPENDED: Constant of data type TaskStateType for task state suspended;  
  • INVALID_TASK: Constant of data type TaskType for an undefined task.

13.3.5 Naming convention 

The OS shall be able to assign the entry address of the task function to the name of the corresponding task for identification. With the entry address, the OS is able to call the task. 

Within the application, a task is defined according to the following pattern:

TASK (TaskName)
{
}

With the macro TASK, the user may use the same name for "task identification" and "name of task function". 

The task identification shall be generated from the TaskName during system generation time. 

NOTE 

The pre-processor could, for example, generate the name of the task function by using the pre-processor symbol sequence ## to add a string "Func" to the task name:

#define TASK(TaskName) StatusType Func ## TaskName(void).

With this macro, TASK(MyTask) has the entry function FuncMyTask.

13.4 Interrupt handling 

13.4.1 Data types 

No special data types are defined for the interrupt handling functionality. 

13.4.2 System services 

13.4.2.1 EnableAllInterrupts  

  • Syntax: void EnableAllInterrupts (void);  
  • Parameter (In): none;  
  • Parameter (Out): none.  
  • Description: This service restores the state saved by DisableAllInterrupts.  
  • Particularities: The service may be called from an ISR category 1 and category 2 and from the task level, but not from hook routines. This service is a counterpart of DisableAllInterrupts service, which shall be called before, and its aim is the completion of the critical section of code. No API service calls shall be made within this critical section. The implementation should adapt this service to the target hardware, providing a minimum overhead. Usually, this service enables recognition of interrupts by the central processing unit.  
  • Status:  
    • Standard: none;  
    • Extended: none;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.4.2.2 DisableAllInterrupts  

  • Syntax: void DisableAllInterrupts (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: This service disables all interrupts for which the hardware supports disabling. The state before is saved for the EnableAllInterrupts call.  
  • Particularities: The service may be called from an ISR category 1 and category 2 and from the task level, but not from hook routines. This service is intended to start a critical section of the code. This section shall be finished by calling the EnableAllInterrupts service. No API service calls shall be made within this critical section. The implementation should adapt this service to the target hardware providing a minimum overhead. Usually, this service disables recognition of interrupts by the central processing unit. Note that this service does not support nesting. If nesting is needed for critical sections e.g. for libraries SuspendOSInterrupts/ResumeOSInterrupts or SuspendAllInterrupt/ResumeAllInterrupts should be used.  
  • Status:  
    • Standard: none;  
    • Extended: none;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.4.2.3 ResumeAllInterrupts  

  • Syntax: void ResumeAllInterrupts (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: This service restores the recognition status of all interrupts saved by the SuspendAllInterrupts service.  
  • Particularities: The service may be called from an ISR category 1 and category 2, from alarm-callbacks and from the task level, but not from some hook routines. This service is the counterpart of SuspendAllInterrupts service, which shall be called before, and its aim is the completion of the critical section of code. No API service calls besides SuspendAllInterrupts/ResumeAllInterrupts pairs and SuspendOSInterrupts/ResumeOSInterrupts pairs shall be made within this critical section. The implementation should adapt this service to the target hardware providing a minimum overhead. SuspendAllInterrupts/ResumeAllInterrupts can be nested. In case of nesting pairs of the calls SuspendAllInterrupts and ResumeAllInterrupts, the interrupt recognition status saved by the first call of SuspendAllInterrupts is restored by the last call of the ResumeAllInterrupts service.  
  • Status:  
    • Standard: none;  
    • Extended: none;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.4.2.4 SuspendAllInterrupts  

  • Syntax: void SuspendAllInterrupts (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: This service saves the recognition status of all interrupts and disables all interrupts for which the hardware supports disabling.  
  • Particularities: The service may be called from an ISR category 1 and category 2, from alarm-callbacks and from the task level, but not from some hook routines. This service is intended to protect a critical section of code from interruptions of any kind. This section shall be finished by calling the ResumeAllInterrupts service. No API service calls beside SuspendAllInterrupts/ResumeAllInterrupts pairs and SuspendOSInterrupts/ResumeOSInterrupts pairs shall be made within this critical section. The implementation should adapt this service to the target hardware providing a minimum overhead.  
  • Status:  
    • Standard: none;  
    • Extended: none;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.4.2.5 ResumeOSInterrupts  

  • Syntax: void ResumeOSInterrupts (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: This service restores the recognition status of interrupts saved by the SuspendOSInterrupts service.  
  • Particularities: The service may be called from an ISR category 1 and category 2 and from the task level, but not from hook routines. This service is the counterpart of SuspendOSInterrupts service, which shall be called before, and its aim is the completion of the critical section of code. No API service calls beside SuspendAllInterrupts/ResumeAllInterrupts pairs and SuspendOSInterrupts/ResumeOSInterrupts pairs shall be made within this critical section. The implementation should adapt this service to the target hardware providing a minimum overhead. SuspendOSInterrupts/ResumeOSInterrupts can be nested. In case of nesting pairs of the calls SuspendOSInterrupts and ResumeOSInterrupts, the interrupt recognition status saved by the first call of SuspendOSInterrupts is restored by the last call of the ResumeOSInterrupts service.  
  • Status:  
    • Standard: none;  
    • Extended: none;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.4.2.6 SuspendOSInterrupts 

  • Syntax: void SuspendOSInterrupts (void); 
  • Parameter (In): none; 
  • Parameter (Out): none; 
  • Description: This service saves the recognition status of interrupts of category 2 and disables the recognition of these interrupts. 
  • Particularities: The service may be called from an ISR and from the task level, but not from hook routines. This service is intended to protect a critical section of code. This section shall be finished by calling the ResumeOSInterrupts service. No API service calls beside SuspendAllInterrupts/ResumeAllInterrupts pairs and SuspendOSInterrupts/ResumeOSInterrupts pairs shall be made within this critical section. The implementation should adapt this service to the target hardware providing a minimum overhead. It is intended only to disable interrupts of category 2. However, if this is not possible in an efficient way, more interrupts may be disabled. 
  • Status: 
    • Standard: none; 
    • Extended: none; 
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.4.3 Naming convention

Within the application, an interrupt service routine of category 2 is defined according to the following pattern:

ISR(FuncName)
{
}

The keyword ISR is evaluated by the system generation to clearly distinguish between functions and interrupt service routines in the source code. 

For category 1 interrupt service routines, no naming convention is prescribed; their definition is implementation-specific.

13.5 Resource management 

13.5.1 Data types 

ResourceType: Data type for a resource. 

13.5.2 Constructional elements 

13.5.2.1 DeclareResource 

  • Syntax: DeclareResource (<ResourceIdentifier>); 
  • Parameter (In): 
    • ResourceIdentifier: Resource identifier (C-identifier);
  • Description: DeclareResource serves as an external declaration of a resource. The function and use of this service are similar to that of the external declaration of variables.  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.5.3 System services 

13.5.3.1 GetResource  

  • Syntax: StatusType GetResource (ResourceType <ResID>);  
  • Parameter (In):  
    • ResID: Reference to resource;  
  • Parameter (Out): none;  
  • Description: This call serves to enter critical sections in the code that are assigned to the resource referenced by <ResID>. A critical section shall always be left using ReleaseResource.  
  • Particularities: The priority ceiling protocol for resource management is described in 8.6. Nested resource occupation is only allowed if the inner critical sections are completely executed within the surrounding critical section (strictly stacked, see 8.3). There shall be no nested occupation of one and the same resource. Corresponding calls to GetResource and ReleaseResource should appear within the same function on the same function level. Services which are points of rescheduling for non-preemptable tasks (TerminateTask, ChainTask, Schedule and WaitEvent, see 4.6.5) shall not be used in critical sections. Additionally, critical sections shall be left before completion of an interrupt service routine. Generally speaking, critical sections should be short. The service may be called from an ISR and from task level (see Table 4).  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended:  
      • Resource <ResID> is invalid, E_OS_ID;  
      • Attempt to get resource which is already occupied by any task or ISR, or the statically assigned priority of the calling task or interrupt routine is higher than the calculated ceiling priority, E_OS_ACCESS;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.5.3.2 ReleaseResource  

  • Syntax: StatusType ReleaseResource (ResourceType <ResID>);  
  • Parameter (In):  
    • ResID: Reference to resource;  
  • Parameter (Out): none;
  • Description: ReleaseResource is the counterpart of GetResource and serves to leave critical sections in the code that are assigned to the resource referenced by <ResID>.  
  • Particularities: For information on nesting conditions, see particularities of GetResource. The service may be called from an ISR and from task level (see Table 4).  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended: 
      • Resource <ResID> is invalid, E_OS_ID;  
      • Attempt to release a resource which is not occupied by any task or ISR, or another resource shall be released before, E_OS_NOFUNC;  
      • Attempt to release a resource which has a lower ceiling priority than the statically assigned priority of the calling task or interrupt routine, E_OS_ACCESS;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.5.4 Constants 

RES_SCHEDULER: Constant of data type ResourceType (see Clause 8). 

13.6 Event control 

13.6.1 Data types 

Data types include:  
  • EventMaskType: Data type of the event mask; and  
  • EventMaskRefType: Reference to an event mask. 

13.6.2 Constructional elements 

13.6.2.1 DeclareEvent  

  • Syntax: DeclareEvent (<EventIdentifier>);  
  • Parameter (In):  
    • EventIdentifier: Event identifier (C-identifier);  
  • Description: DeclareEvent serves as an external declaration of an event. The function and use of this service are similar to that of the external declaration of variables.  
  • Particularities: -  
  • Conformance: ECC1, ECC2.

13.6.3 System services 

13.6.3.1 SetEvent  

  • Syntax: StatusType SetEvent (TaskType <TaskID> EventMaskType <Mask>);  
  • Parameter (In):  
    • TaskID: Reference to the task for which one or several events are to be set;  
    • Mask: Mask of the events to be set;  
  • Parameter (Out): none;  
  • Description: The service may be called from an interrupt service routine and from the task level, but not from hook routines. The events of task <TaskID> are set according to the event mask <Mask>. Calling SetEvent causes the task <TaskID> to be transferred to the ready state, if it was waiting for at least one of the events specified in <Mask>.  
  • Particularities: Any events not set in the event mask remain unchanged.  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended:  
      • Task <TaskID> is invalid, E_OS_ID;  
      • Referenced task is no extended task, E_OS_ACCESS;  
      • Events shall not be set as the referenced task is in the suspended state, E_OS_STATE.  
  • Conformance: ECC1, ECC2.

13.6.3.2 ClearEvent  

  • Syntax: StatusType ClearEvent (EventMaskType <Mask>);  
  • Parameter (In):  
    • Mask: Mask of the events to be cleared;  
  • Parameter (Out): none;  
  • Description: The events of the extended task calling ClearEvent are cleared according to the event mask <Mask>.  
  • Particularities: The system service ClearEvent is restricted to extended tasks which own the event.  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended:  
      • Call not from extended task, E_OS_ACCESS;
      • Call at interrupt level, E_OS_CALLEVEL;  
  • Conformance: ECC1, ECC2.

13.6.3.3 GetEvent  

  • Syntax: StatusType GetEvent (TaskType <TaskID> EventMaskRefType <Event>);  
  • Parameter (In):  
    • TaskID: Task whose event mask is to be returned;  
  • Parameter (Out):  
    • Event: Reference to the memory of the return data;  
  • Description: This service returns the current state of all event bits of the task <TaskID>, not the events that the task is waiting for. The service may be called from interrupt service routines, task level and some hook routines (see Table 4). The current status of the event mask of task <TaskID> is copied to <Event>.  
  • Particularities: The referenced task shall be an extended task.  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended:  
      • Task <TaskID> is invalid, E_OS_ID;  
      • Referenced task <TaskID> is not an extended task, E_OS_ACCESS;  
      • Referenced task <TaskID> is in the suspended state, E_OS_STATE.  
  • Conformance: ECC1, ECC2.

13.6.3.4 WaitEvent  

  • Syntax: StatusType WaitEvent (EventMaskType <Mask>);  
  • Parameter (In):  
    • Mask: Mask of the events waited for;  
  • Parameter (Out): none;  
  • Description: The state of the calling task is set to waiting, unless at least one of the events specified in <Mask> has already been set.  
  • Particularities: This call enforces rescheduling, if the wait condition occurs. If rescheduling takes place, the internal resource of the task is released while the task is in the waiting state. This service shall only be called from the extended task owning the event.  
  • Status:  
    • Standard: No error, E_OK;
    • Extended:  
      • Calling task is not an extended task, E_OS_ACCESS;  
      • Calling task occupies resources, E_OS_RESOURCE;  
      • Call at interrupt level, E_OS_CALLEVEL;  
  • Conformance: ECC1, ECC2.

13.7 Alarms 

13.7.1 Data types 

Data types include:  
  • TickType: This data type represents count values in ticks; 

NOTE 

All elements of the structure are of data type TickType.  

  • TickRefType: This data type points to the data type TickType;  
  • AlarmBaseType: This data type represents a structure for storage of counter characteristics. The individual elements of the structure are:  
    • maxallowedvalue: Maximum possible allowed count value in ticks;  
    • ticksperbase: Number of ticks required to reach a counter-specific (significant) unit;  
    • mincycle: Smallest allowed value for the cycle-parameter of SetRelAlarm/SetAbsAlarm) (only for systems with extended status).  
  • AlarmBaseRefType: This data type points to the data type 
  • AlarmBaseType;  AlarmType: This data type represents an alarm object.

13.7.2 Constructional elements 

13.7.2.1 DeclareAlarm  

  • Syntax: DeclareAlarm (<AlarmIdentifier>);  
  • Parameter (In):  
    • AlarmIdentifier: Alarm identifier (C-identifier)  
  • Description: DeclareAlarm serves as external declaration of an alarm element.  
  • Particularities: -  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.7.3 System services 

13.7.3.1 GetAlarmBase  

  • Syntax: StatusType GetAlarmBase (AlarmType <AlarmID>, AlarmBaseRefType <Info>);  
  • Parameter (In):  
    • AlarmID Reference to alarm;  
  • Parameter (Out):  
    • Info: Reference to structure with constants of the alarm base;  
  • Description: The system service GetAlarmBase reads the alarm base characteristics. The return value <Info> is a structure in which the information of data type AlarmBaseType is stored.  
  • Particularities: Allowed on task level, ISR, and in several hook routines (see Table 4).  
  • Status:  
    • Standard: No error, E_OK;  
    • Extended: Alarm <AlarmID> is invalid, E_OS_ID;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.7.3.2 GetAlarm  

  • Syntax: StatusType GetAlarm (AlarmType <AlarmID> TickRefType <Tick>)  
  • Parameter (In):  
    • AlarmID Reference to an alarm;  
  • Parameter (Out):  
    • Tick Relative value in ticks before the alarm <AlarmID> expires;  
  • Description: The system service GetAlarm returns the relative value in ticks before the alarm <AlarmID> expires.  
  • Particularities: It is up to the application to decide whether for example a CancelAlarm may still be useful. If <AlarmID> is not in use, <Tick> is not defined. It is allowed on task level, ISR, and in several hook routines (see Table 4).  
  • Status:  
    • Standard:  
      • No error, E_OK;  
      • Alarm <AlarmID> is not used, E_OS_NOFUNC;  
    • Extended: Alarm <AlarmID> is invalid, E_OS_ID;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.7.3.3 SetRelAlarm  

  • Syntax: StatusType SetRelAlarm (AlarmType <AlarmID>, TickType <increment>, TickType <cycle>);  
  • Parameter (In):  
    • AlarmID: Reference to the alarm element;  
    • increment: Relative value in ticks;  
    • cycle: Cycle value in case of cyclic alarm. In case of single alarms, cycle shall be zero;  
  • Parameter (Out): none;  
  • Description: The system service occupies the alarm <AlarmID> element. After <increment> ticks have elapsed, the task assigned to the alarm <AlarmID> is activated or the assigned event (only for extended tasks) is set or the alarm-callback routine is called.  
  • Particularities: The behaviour of <increment> equal to 0 is up to the implementation. If the relative value <increment> is very small, the alarm may expire, and the task may become ready or the alarm-callback may be called before the system service returns to the user. If <cycle> is unequal zero, the alarm element is logged on again immediately after expiry with the relative value <cycle>. The alarm <AlarmID> should not already be in use. To change values of alarms already in use, the alarm shall be cancelled first. If the alarm is already in use, this call shall be ignored and the error E_OS_STATE shall be returned. This is allowed on task level and in ISR, but not in hook routines.  
  • Status:  
    • Standard:  
      • No error, E_OK;  
      • Alarm <AlarmID> is already in use, E_OS_STATE;  
    • Extended:  
      • Alarm <AlarmID> is invalid, E_OS_ID;  
      • Value of <increment> outside of the admissible limits (lower than zero or greater than maxallowedvalue), E_OS_VALUE;  
      • Value of <cycle> unequal to 0 and outside of the admissible counter limits (less than mincycle or greater than maxallowedvalue), E_OS_VALUE;  
  • Conformance: BCC1, BCC2, ECC1, ECC2; Events only ECC1, ECC2.

13.7.3.4 SetAbsAlarm  

  • Syntax: StatusType SetAbsAlarm (AlarmType <AlarmID>, TickType <start>, TickType <cycle>);  
  • Parameter (In):  
    • AlarmID: Reference to the alarm element;  
    • start: Absolute value in ticks;  
    • cycle: Cycle value in case of cyclic alarm. In case of single alarms, cycle shall be zero.
  • Parameter (Out): none;  
  • Description: The system service occupies the alarm <AlarmID> element. When <start> ticks are reached, the task assigned to the alarm <AlarmID> is activated or the assigned event (only for extended tasks) is set or the alarm-callback routine is called.  
  • Particularities: If the absolute value <start> is very close to the current counter value, the alarm may expire, and the task may become ready or the alarm-callback may be called before the system service returns to the user. If the absolute value <start> already was reached before the system call, the alarm shall only expire when the absolute value <start> is reached again, i.e. after the next overrun of the counter. If <cycle> is unequal zero, the alarm element is logged on again immediately after expiry with the relative value <cycle>. The alarm <AlarmID> should not already be in use. To change values of alarms already in use, the alarm shall be cancelled first. If the alarm is already in use, this call shall be ignored and the error E_OS_STATE shall be returned. This is allowed on task level and in ISR, but not in hook routines.  
  • Status:  
    • Standard:  
      • No error, E_OK;  
      • Alarm <AlarmID> is already in use, E_OS_STATE;  
    • Extended:  
      • Alarm <AlarmID> is invalid, E_OS_ID;  
      • Value of <start> outside of the admissible counter limit (less than zero or greater than maxallowedvalue), E_OS_VALUE;  
      • Value of <cycle> unequal to 0 and outside of the admissible counter limits (less than mincycle or greater than maxallowedvalue), E_OS_VALUE;  
  • Conformance: BCC1, BCC2, ECC1, ECC2; Events only ECC1, ECC2.

13.7.3.5 CancelAlarm  

  • Syntax: StatusType CancelAlarm (AlarmType <AlarmID>);  
  • Parameter (In):  
    • AlarmID: Reference to an alarm;  
  • Parameter (Out): none;  
  • Description: The system service cancels the alarm <AlarmID>.  
  • Particularities: Allowed on task level and in ISR, but not in hook routines.  
  • Status:  
    • Standard:  
      • No error, E_OK;  
      • Alarm <AlarmID> not in use, E_OS_NOFUNC;  
    • Extended: Alarm <AlarmID> is invalid, E_OS_ID;  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.7.4 Constants 

For all counters, the return values of GetAlarmbase are also available as constants:  
  • OSMAXALLOWEDVALUE_x: Maximum possible allowed value of counter x in ticks;  
  • OSTICKSPERBASE_x: Number of ticks required to reach a specific unit of counter x;  
  • OSMINCYCLE_x: Minimum allowed number of ticks for a cyclic alarm of counter x. 

Thus, if the counter name is known, it is not necessary to call GetAlarmBase. 

There always exists at least one counter which is a time counter (system counter). The constants of this counter are additionally accessible via the following constants:  
  • OSMAXALLOWEDVALUE: Maximum possible allowed value of the system counter in ticks;  
  • OSTICKSPERBASE: Number of ticks required to reach a specific unit of the system counter;  
  • OSMINCYCLE: Minimum allowed number of ticks for a cyclic alarm of the system counter. 

Additionally the following constant is supplied:  
  • OSTICKDURATION: Duration of a tick of the system counter in nanoseconds.

13.7.5 Naming convention 

Within the application, an alarm-callback is defined according to the following pattern:

ALARMCALLBACK (AlarmCallBackName)
{
}

13.8 OS execution control 

13.8.1 Data types 

Data types include:  
  • AppModeType: This data type represents the application mode. 

13.8.2 System services 

13.8.2.1 GetActiveApplicationMode  

  • Syntax: AppModeType GetActiveApplicationMode (void);  
  • Description: This service returns the current application mode. It may be used to write mode dependent code.  
  • Particularities: See Clause 5 for a general description of application modes. It is allowed for task, ISR and all hook routines.  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.8.2.2 StartOS  

  • Syntax: void StartOS (AppModeType <Mode>);  
  • Parameter (In):  
    • Mode: application mode;  
  • Parameter (Out): none;  
  • Description: The user can call this system service to start the operating system in a specific mode, see Clause 5.  
  • Particularities: Only allowed outside of the OS; therefore implementation-specific restrictions may apply. See also 11.3, especially with respect to systems where ISO 17356-3 and OSEKtime coexist. This call does not need a return.  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.8.2.3 ShutdownOS 

  • Syntax: void ShutdownOS (StatusType <Error>); 
  • Parameter (In): 
    • Error: error occurred; 
  • Parameter (Out): none; 
  • Description: The user can call this system service to abort the overall system (e.g. emergency off). The OS also calls this function internally, if it has reached an undefined internal state and is no longer ready to run. If a ShutdownHook is configured, the hook routine ShutdownHook is always called (with <Error> as argument) before shutting down the OS. If ShutdownHook returns, further behaviour of ShutdownOS is implementation-specific. In case of a system where OS and OSEKtime OS coexist, ShutdownHook shall return. <Error> shall be a valid error code supported by the OS. In case of a system where OS and OSEKtime OS coexist, <Error> might also be a value accepted by OSEKtime OS. In this case, if enabled by an OSEKtime configuration parameter, OSEKtime OS is shut down after OS shutdown. 
  • Particularities: After this service, the OS is shut down. It is allowed at task level, ISR level, in ErrorHook and StartupHook, and also called internally by the operating system. If the OS calls ShutdownOS, it never uses E_OK as the passed parameter value. 
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.8.3 Constants 

Constants include:  
  • OSDEFAULTAPPMODE: Default application mode, always a valid parameter to StartOS. 

13.9 Hook routines 

13.9.1 Data types 

Data types include:  
  • OSServiceIdType: This data type represents the identification of system services.

13.9.2 System services 

13.9.2.1 ErrorHook  

  • Syntax: void ErrorHook (StatusType <Error>);  
  • Parameter (In):  
    • Error error occurred  
  • Parameter (Out): none;  
  • Description: This hook routine is called by the OS at the end of a system service which returns StatusType not equal E_OK. It is called before returning to the task level. This hook routine is called when an alarm expires and an error is detected during task activation or event setting. The ErrorHook is not called if a system service called from ErrorHook does not return E_OK as status value. Any error by calling of system services from the ErrorHook can only be detected by evaluating the status value.  
  • Particularities: See 11.1 for general description of hook routines.  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.9.2.2 PreTaskHook  

  • Syntax: void PreTaskHook (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: This hook routine is called by the OS before executing a new task, but after the transition of the task to the running state (to allow evaluation of the TaskID by GetTaskID).  
  • Particularities: See 11.1 for general description of hook routines.  
  • Conformance: BCC1, BCC2, ECC1, ECC2

13.9.2.3 PostTaskHook  

  • Syntax: void PostTaskHook (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: This hook routine is called by the OS after executing the current task, but before leaving the task's running state (to allow evaluation of the TaskID by GetTaskID).  
  • Particularities: See 11.1 for general description of hook routines.  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.9.2.4 StartupHook  

  • Syntax: void StartupHook (void);  
  • Parameter (In): none;  
  • Parameter (Out): none;  
  • Description: This hook routine is called by the OS at the end of the OS initialization and before the scheduler is running. At this time, the application can initialize device drivers, etc.  
  • Particularities: See 11.1 for general description of hook routines.  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.9.2.5 ShutdownHook  

  • Syntax: void ShutdownHook (StatusType <Error>);  
  • Parameter (In):  
    • Error: error occurred;  
  • Parameter (Out): none;  
  • Description: This hook routine is called by the OS when the OS service ShutdownOS has been called. This routine is called during the OS shut down.  
  • Particularities: ShutdownHook is a hook routine for user defined shutdown functionality (see 11.4).  
  • Conformance: BCC1, BCC2, ECC1, ECC2.

13.9.3 Constants 

Constants include:  
  • OSServiceId_xx: Unique identifier of system service xx. 

EXAMPLE 

OSServiceId_ActivateTask. OSServiceId_xx is of type OSServiceIdType. 

13.9.4 Macros 

Macros include:  
  • OSErrorGetServiceId: Provides the service identifier where the error has been raised. The service identifier is of type OsServiceIdType. Possible values are OSServiceId_xx, where xx is the name of the system service.  
  • OSError_x1_x2: Names of macros to access (within ErrorHook) parameters of the system service which is called ErrorHook, where x1 is the name of the system service and x2 is the parameter name.

14 Implementation- and application-specific topics 


14.1 General 

This clause is neither normative nor mandatory. It provides information for implementers and application programmers. 

14.2 Implementation hints 

ISO 17356 specifies an OS interface and its functionality. Implementation aspects are not prescribed. There is no restriction on the implementation of the OS, as long as the implementation corresponds to any of the defined conformance classes. 

14.2.1 Aspects of implementation 

The range of automotive applications varies greatly such that no performance characteristics of the OS implementation can be specified, i.e. as to the execution time and memory space required. 

As a result:  
  • The OS can be implemented with various degrees of efficiency.  
  • The linker needs only to link those objects and services of the OS which are actually used.  
  • The OS used in a product (e.g. in a control unit's EPROM) cannot be described as an operating system, but as an operating system which conforms to an operating system conformance class.  
  • The tool environment of the OS configuration and initialization is not part of this part of ISO 17356, and therefore implementation-specific.  
  • Commercial systems which provide the user with all OS-specific services and their functionality via an adaptation layer are also compliant. They are compliant irrespective of their actual suitability for control units as regards the memory space they require and their processing speed.

The conformance class selected for application software should be determined by the needs on functionality and flexibility. 

The real-time behaviour of the application software used with a specific hardware is also defined by the quality of implementation. 

14.2.2 Parameters of implementation 

The OS vendor should provide a list of parameters specifying the implementation. Detailed information is required concerning the functionality, performance and memory demand. Furthermore, the basic conditions to reproduce the measurement of those parameters should be mentioned, e.g. functionality, target CPU, clock speed, bus configuration, wait states, etc. 

14.2.2.1 Functionality 

Functionality includes:  
  • Maximum number of tasks;  
  • Maximum number of non-suspended tasks;  
  • Maximum number of priorities;
  • Number of tasks per priority (for BCC2 and ECC2);
  • Upper limit for number of task activation (shall be “1” for BCC1 and extended tasks);
  • Maximum number of events per task;
  • Limits for the number of alarm objects (per system/per task);
  • Limits for the number of nested resources (per system/per task);
  • Lowest priority level used internally by the OS. 

14.2.2.2 Hardware resources 

Hardware resources include: 
  • RAM and ROM requirement for each of the OS components;
  • Size for each linkable module;
  • Application-dependent RAM and ROM requirements for OS data (e.g. bytes RAM per task, RAM required per alarm, etc.);
  • Execution context of the OS (e.g. size of OS internal tables);
  • Timer units reserved for the OS;
  • Interrupts, traps and other hardware resources occupied by the OS. 

14.2.2.3 Performance 

Performance includes:  
  • Total execution time for each service; 

NOTE 1 

The time of execution may depend on the current state of the system, e.g. there are different execution times of "SetEvent" depending on the state of the task (waiting or ready). Therefore comparable results shall be extracted from a common benchmark procedure.  

  • OS start-up time (beginning of StartOS until execution of first task in standard mode) without invoking hook routines;  
  • Interrupt latency for ISRs of category 1 and 2; 

NOTE 2 

Interrupt latency is the time between interrupt request and execution of the first instruction of user code inside the ISR. A comparison of interrupt latencies of ISRs from category 1 to ISRs from category 2 specifies the OS overhead.  

  • Task switching times for all types of switching; 

NOTE 3 

This should be measured from the last user instruction of the preceding task to the first user instruction of the following task so that all overhead is covered. Task switching types are different for: normal termination of a task, termination forced by ChainTask(), preemptive task switch, task activation when OS idle task is running, alarm triggered task activation and task activation from ISRs of type 2.  

  • Base load of system without applications running. 

All performance figures should be stated as minimum and maximum (worst case) values.

14.2.2.4 Configuration of run time context 

A run time context is assigned to each task. This refers to all memory resources of the task which are occupied at the beginning of the execution time, and which are released again once the task is terminated. Typically, the run time context consists of some registers, a task control block and a certain amount of stack to operate. 

Depending on the design of tasks (e.g. type and preemptability) and depending on the scheduling mechanism (non-, mixed- or full preemptive) the run time context may have different sizes. Tasks which can never preempt each other may be executed in the same run time context in order to achieve an efficient utilization of the available RAM space. 

The OS vendor should provide information about the implemented handling of the run time context (e.g. one context per task or one context per priority level). Considering this information, the user may optimize the design of his application regarding RAM requirements versus run time efficiency. 

14.3 Application design hints 

14.3.1 General 

The purpose of this clause is to provide additional information about possible problems which might arise when designing applications for the OS. Not all of the consequences for the system design can be mentioned in this part of ISO 17356. Other design hints result from the experience of current ECU applications. 

14.3.2 Resource management 

Some aspects are mentioned in this clause in order to guarantee a proper handling of all resources. 

14.3.2.1 Occupation in LIFO order 

Each access to a resource should be encapsulated with calls to the services GetResource and ReleaseResource. Resources shall be released in reversed order of their occupation. The following code sequence is incorrect because function foo is not allowed to release resource res_1.

TASK(incorrect)
{
    GetResource( res_1 );

    /* some code accessing resource res_1 */
    ...

    foo();
    ...

    ReleaseResource( res_2 );
}

void foo()
{
    GetResource( res_2 );

    /* code accessing resource res_2 */
    ...

    ReleaseResource( res_1 );
}

Nested resource occupations are allowed. The occupation of resources shall be performed in strict LIFO order (stack principle). If the code accessing the resource as shown above is preempted by a task with higher priority (higher than the ceiling priority of the resource), another resource might be requested in that task leading to a nested resource occupation which conforms to the LIFO order.

14.3.2.2 Call level of API services 

The API services GetResource and ReleaseResource should be called from the same functional call level. If function foo is corrected concerning the LIFO order of resource occupation like:

void foo( void )
{
    ReleaseResource( res_1 );
    GetResource( res_2 );

    /* some code accessing resource res_2 */
    ...

    ReleaseResource( res_2 );
}

there still may be a problem because ReleaseResource(res_1) is called on a different level than GetResource(res_1). Calling the API services from different call levels might cause problems in some implementations. 

14.3.2.3 Resources still occupied at task termination or interrupt completion 

The access to a resource should be encapsulated directly by the calls of GetResource and ReleaseResource. Otherwise the release of the resource might be missed and possibly terminate the task.

GetResource( res_1 );
...
switch ( condition )
{
    case CASE_1 :
        do_something1();
        ReleaseResource( res_1 );
        break;

    /* !!! WRONG: no release of */
    case CASE_2 :
        /* resource here !!! */
        do_something2();
        break;

    default:
        do_something3();
        ReleaseResource( res_1 );
}
...

If in standard status of the OS a task terminates, or in standard or extended status an interrupt completes without releasing all of the occupied resources, the resulting behaviour is not defined by this part of ISO 17356. Depending on the implementation of the OS, the resource may be locked forever since further accesses are rejected by the operating system. 

14.3.3 Placement of API calls 

For the same reasons as mentioned above, the placement of API services TerminateTask and ChainTask is crucial for the OS. Both services are used to terminate the running task. Calling these services from a subroutine level of the task, the OS is responsible for a correct treatment of the stack when terminating the task. One solution could be to store the position of the stack pointer at the entry point of the running task and restore that value after terminating the task. 

14.3.4 Interrupt service routines 

The user shall be aware of some possible error cases when using ISRs of category 1 and 2 as described in Clause 6.

14.3.4.1 Nested interrupts of different categories 

Since all interrupts are of higher priority than the task levels, the processing of interrupts shall be terminated before the system returns to task level. If an ISR of category 2 interrupts an ISR of category 1, the system will continue processing of ISR1 after ISR2 terminates. Having tasks activated or events set from interrupt level in ISR2, the OS is not invoked after termination of ISR1 in order to perform a rescheduling.


Because ISRs of category 1 do not run under control of the OS, the OS has no possibility to perform a rescheduling when the ISR terminates. Thus, any activities corresponding to the calls of the OS in the interrupting ISR2 are unbounded delayed until the next rescheduling point. 

As a result of the problems discussed above, each system should set up rules to avoid these problems. There may be specific implementations which can avoid these problems, or the application might have specific properties such that these problems cannot occur (e.g. in non-preemptive systems). The rules shall therefore take into account both the specific implementations and the applications. 

However, for maximal application portability, an easy rule of thumb which always works is the following: All interrupts of category 1 shall have a higher or equal hardware priority compared with interrupts of category 2. 

14.3.4.2 Direct manipulation of interrupt levels 

Direct manipulation of interrupt levels is not portable and restricted by the implementation. 

14.3.5 Priority and preemption 

Tasks are scheduled by the OS according to their priority. A task is declared as being preemptable/non-preemptable (see 4.6.2). The application shall treat these two task attributes in a consistent manner to avoid conflicts in the run-time behaviour of the system. Care shall be taken because non-preemptable tasks of lower priority delay tasks of higher priority. 

Typically, the preemption of a task is assigned when designing, whereas priority is configured during system integration. Because many people are involved in larger software projects, the development process shall be coordinated precisely. To achieve a well-defined run-time behaviour of the system, this coordination is crucial.

14.3.6 Examples of usage of internal resources 

Besides for non-preemptable tasks, internal resources can be used in a number of situations. 

In general, they protect a group of tasks against being preempted by another task of the same group, except if the running task within the group explicitly allows rescheduling by calling Schedule, WaitEvent or TerminateTask/ChainTask. If, for example, all tasks of a group call those functions only on first procedure level, a stack of those tasks can be highly optimized. 

An example, besides non-preemptable tasks, is a concept sometimes referred to as "cooperative tasks", where the lowest priority tasks share the same internal resource and can freely be preempted by higher priority tasks, but not among themselves. 

This example can be extended by excluding the lowest priority of the system for usage as a background task. This task would again be preemptable by all tasks. 

The concept of non-preemptable tasks and cooperative tasks can be easily combined within one system by using two different internal resources within one configuration. 

Tasks which do not have an internal resource assigned are preemptable and act as described in 4.6.1. 

14.3.7 Parameter to pass to ShutdownOS 

The parameter passed to ShutdownOS is also passed to the ShutdownHook. If the OS calls ShutdownHook, the passed parameter is an implementation-dependent error value. If the user calls ShutdownOS he/she shall use one of the existing OS error numbers. If OSEKtime and ISO 17356-3 coexist, an OSEKtime OS error number can also be passed. 

It is strongly recommended to use the error number described in the implementation documentation. If no specific error number for ShutdownOS is defined, it is possible to use E_OK and to distinguish this way between OS calls of ShutdownOS and application calls.

14.3.8 Error handling 

Errors in the application software are typically caused by:
  • Errors on handling the OS, i.e. incorrect configuration/initialization/dimensioning of the OS or violations of restrictions regarding the operating system service;
  • Error in software design, e.g. inappropriate choice of task priorities, unprotected critical sections, incorrect scaling of time, inefficient conceptual design of task organization. 

Test of implementation 
Breakpoints, traces and time stamps can be integrated individually into the application software. 

As an example, users can set time stamps enabling them to trace the program execution at the following locations before calling OS services:
  • when activating or terminating tasks;
  • when setting or clearing events in the case of extended tasks;
  • at explicit points of the schedule;
  • at the beginning or the end of ISRs; and
  • when occupying and releasing resources or at critical locations. 

Time monitoring 
The OS need not include a time monitoring feature which ensures that each or only, e.g. the lowest-priority task, has been activated in any case after a defined maximum time period. 

The user can optionally use hook routines or establish a watchdog task that takes "one-shot displays" of the OS status. 

Constructional elements 
Constructional elements (e.g. DeclareTask) were introduced in the OS as means to create references to system objects used in the application. Like external declarations, constructors would be placed at the beginning of source files. With respect to the implementation, they can be implemented as macros. With the definition of OIL in ISO 17356-6, most implementations do not need them any more. However, they are still kept for compatibility. 

14.3.9 Errors and warnings 

Most of the error values of system services point to application errors. However, in some special cases, error values indicate warnings which might come up during normal operation. These cases are:
  • ActivateTask, ChainTask: E_OS_LIMIT (standard);
  • GetAlarm: E_OS_NOFUNC (standard);
  • SetAbsAlarm, SetRelAlarm: E_OS_STATE (standard);
  • CancelAlarm: E_OS_NOFUNC (standard). 

Especially when implementing a central error handling using ErrorHook, this shall be taken into account. 

14.4 Implementation-specific tools 

When buying or writing portable code, one shall be aware of the different implementation tools on the market. This has an impact on what kind of documentation shall go in parallel with the code. 

The example here shows two possible implementations of a tool chain:
  • Version A, with all declarations related to task properties etc. within the code; and
  • Version B, using a separate generation tool for these task properties, etc. 

For definitions which should be supplied with portable code, please consult ISO 17356-6.


评论

此博客中的热门博文

AUTOSAR_SWS_CANDriver

Linux Driver Char Device 笔记

AUTOSAR_SWS_PWMDriver

AUTOSAR_SWS_PortDriver

AUTOSAR_SWS_ECUStateManager

EB - MCAL - MCU

AUTOSAR_SWS_ICUDriver

EB - MCAL - PWM