\section{OSEK/VDX OS} \label{section:osekvdxos} \Gls{osek} (\glsdesc*{osek}) \cite{osek} is an effort of the German and French automotive industry to establish common standards for the software architecture of distributed control units in vehicles. Defining a common architecture for communication, operating systems, and network management avoids problems that arise otherwise by using different interfaces and protocols. An abstraction layer between hardware and software allows \Gls{osek} compliant applications to be reused on different hardware platforms with minor modifications. \gls{osekos} specifies the architecture of a real-time operating system for single processors. Based on the services offered by the \gls{os}, integration of modules from different manufactures is possible. The \gls{os} meets the hard real-time requirements demanded by automotive applications. \gls{osekos} can also be used in multi-core environments. In such cases a separate kernel is executed on each core. Service routines can be used to interact between multiple \gls{os} instances. A high level of flexibility is required for an \gls{os} to support real-time systems on various target platforms. In order to support low-end and high-end microcontrollers alike \gls{osek} conformance classes (\glspl{osekcc}) are specified. Depending on the \gls{osekcc} certain features, e.g.\ multiple task activations, multiple tasks per priority, and extended tasks are available or not. Dynamic creation of system objects like tasks, alarms or events is not supported by \gls{osekos}. All objects are defined statically and created during the system generation phase \cite{osekos}. Consequently, all \gls{os} entities are known before the system execution. \autoref{fig:os_module_abstraction} illustrates the abstraction of application modules from hardware resources. Standardized system services offer functionality that can be used by all application modules. Well-defined service calls, type definitions, and constants are specified and ensure the portability of an application to different architectures. An \glsdesc{io} (\gls{io}) module parallel to the \gls{os} gives access to microcontroller specific functionality like serial interfaces or analog-to-digital converters. \gls{io} interfaces are not specified by \gls{osekos} which is opposing to the idea of easy portability. \gls{osek}'s follow-up standard \gls{autosar} (\glsdesc{autosar}) \cite{autosar} solves this problem by adding a \gls{mcal} (\glsdesc{mcal}) to the \gls{autosaros} specification \cite{autosarbsw}. In 2003 \gls{autosar} was established by automobile \glspl{oem}, suppliers, and tool developers pursuing the same goals like \gls{osek}. Different parts of the \gls{autosar} standard are based on \gls{osek} and \gls{autosaros} constitutes a superset of \gls{osekos}. Consequently, all features discussed here are also relevant for \gls{autosaros}. Differences that are important in the context of this thesis are mentioned explicitly. \begin{figure}[] \centering \includegraphics[width=\textwidth]{./media/osek/os_module_abstraction.pdf} \caption[\gls{osekos} architecture]{\gls{osek} compliant \glspl{os} abstract application modules and hardware via an \gls{os} layer. A non standardized \gls{io} module still results in hardware dependencies.} \label{fig:os_module_abstraction} \end{figure} \subsection{OSEK Architecture} \label{subsection:osek_architecture} \gls{osek} provides a specification for the architecture of an embedded real-time \gls{os}. One of the main purposes of the \gls{os} is to manage the available computational resources of the CPU\@. Based on different factors such as priority, task group and scheduling policy, executable entities, so-called processes are given access to the processor core. The procedure of deciding which entity is executed next is called scheduling. There are two types of process entities available: tasks and Interrupt Service Routines (\glspl{isr}). Former are scheduled on task level while for latter the interrupt level is used. Entities on interrupt level always have precedence over entities on task level. Scheduling on interrupt level depends solely on the priority of an entity and is done by hardware. For task entities scheduling is done by the \gls{os} and depends on priority, scheduling policy, and task group. \textbf{Tasks} are categorized into two types by \gls{osekos}. A basic task has three states: ready, running, and suspended. An extended task is a basic task with the additional waiting state. Suspended tasks are passive and can be activated. A task in the ready state can be allocated to the CPU for execution which is then indicated by the running state. Only one task per core can be in the running state at a given point in time. Extended tasks can wait passively for an event. In that case they reside in waiting state. Waiting tasks are not allocated to the CPU. \begin{figure}[] \centering \includegraphics[width=0.7\textwidth]{./media/osek/extended_task_state_model.pdf} \caption[\gls{osekos} task state model]{Task state model of an extended \gls{osekos} task. A basic task cannot enter the waiting state.} \label{fig:extended_task_state_model} \end{figure} Different task state transitions are possible as shown in \autoref{fig:extended_task_state_model}. At system initialization all tasks are suspended. If a task has to be executed it must be activated by a system service. A task can be started by the \gls{os} in order to be executed. A task is preempted if a task of higher priority is scheduled. Once a task has finished execution it terminates and switches to the suspended state. Extended tasks can wait for system events and are released and switched to ready once the expected event is set. The previous state of a ready task is not implicitly known. \begin{figure}[] \centering \includegraphics[width=0.9\textwidth]{./media/osek/isr_example.pdf} \caption[\gls{isr} scheduling behavior]{\gls{isr} scheduling is done by hardware and is solely depended on the interrupt priority. \glspl{isr} do not have a ready state because they are started by hardware.} \label{fig:isr_example} \end{figure} Priorities are assigned to tasks and \glspl{isr} statically. The lowest priority is zero and greater integers mean a higher priority. If an \gls{isr} of priority zero is running and another \gls{isr} of priority one is activated, the first \gls{isr} is preempted and restarts once the second \gls{isr} is terminated as shown in \autoref{fig:isr_example}. For tasks the same scenario is dependent on scheduling policy and task group. \begin{figure}[] \centering \includegraphics[width=\textwidth]{./media/osek/non_vs_full_preemptive_scheduling.pdf} \caption[Non vs full preemptive scheduling]{Scheduling behavior of a non (top) vs a full (bottom) preemptive task. A non preemptive task finishes execution even though a task with higher priority is in ready state. Only for certain system services, for example, an inter-process activation, the other task may be scheduled. A full preemptive task is preempted if a task with higher priority is activated. Once this task has terminated, the task with lower priority can continue running.} \label{fig:non_vs_full_preemptive_scheduling} \end{figure} \gls{osekos} specifies three \textbf{scheduling policies}: non, full, and mixed preemptive scheduling. For a non preemptive tasks, rescheduling is only possible if a system routine that causes rescheduling, e.g.\ an inter-process activation or an explicit scheduler call is executed. A full preemptive task can be rescheduled at any point in time during its execution if another task of higher precedence is activated as shown in \autoref{fig:non_vs_full_preemptive_scheduling}. A mixed preemptive system contains tasks with both, non, and full preemptive scheduling policies. Otherwise the system is either non or full preemptive. \begin{figure}[] \centering \includegraphics[width=\textwidth]{./media/osek/task_group_example.pdf} \caption[Scheduling of tasks in task groups]{Scheduling of task entities is not only dependent on priority and scheduling priority. \gls{osek} specifies task groups, which change the priority of tasks inside in relation to tasks outside a specific group. In this example Task 3 has a greater priority than Task 2. However, because they are in the same group, Task 2 inherits the priority of Task 1. Thus, Task 2 is not preempted by Task 3.} \label{fig:task_group_example} \end{figure} The precedence of a task is not necessarily due to its priority. \gls{osekos} introduces the concept of task groups which allows it to group multiple tasks into a group. A task which is not within a group has precedence over a task within a group only, if its priority is higher than the priority of the task with the highest priority within this group. This means a task acts non preemptive towards another task if the task with the highest priority within the group has a greater priority than the other task as shown in \autoref{fig:task_group_example}. \textbf{\gls{osek} Conformance Classes} are used to adapt applications to different hardware capacities such as available memory and CPU speed. Only one \gls{osekcc} can be active at a time and cannot be changed during runtime. Basic \glspl{osekcc} (BCC1 and BCC2) allow basic tasks only, while extended \glspl{osekcc} (ECC1 and ECC2) allow basic and extended tasks. Level one \glspl{osekcc} (BCC1 and ECC1) allow multiple tasks per priority and multiple activation requests per task. For level two \glspl{osekcc} (BCC2 and ECC2) multiple tasks can share the same priority and the same task can be activated multiple times as shown in \autoref{tab:conformance_class}. This means BCC2 and ECC2 allow \glsdesc{mta} (\glspl{mta}). An active task with pending activations becomes ready again immediately after termination. \begin{table}[] \centering \begin{tabular}{r|c c c c} & BCC1 & BCC2 & ECC1 & ECC 2 \\ \hline \gls{mta} & no & yes & no & yes \\ Multiple tasks per priority & no & yes & no & yes \\ Extended tasks & no & no & yes & yes \\ \end{tabular} \caption[\gls{osek} conformance classes]{\gls{osekos} specifies multiple \glspl{osekcc} to respect the computational capacities of different platforms. Depending on the \gls{osekcc} different features are supported or not.} \label{tab:conformance_class} \end{table} Task scheduling is done by the \gls{os} while \gls{isr} scheduling is done by hardware. \glspl{isr} can be divided into category one and category two. Category one \glspl{isr} do not run under \gls{os} control and are thus not allowed to call \gls{os} services. Category two \glspl{isr} are monitored by the \gls{os} and are allowed to execute a subset of the available \gls{os} services. Tasks are always preempted by \glspl{isr} and can only continue running when all \glspl{isr} have terminated. Tasks and \glspl{isr} serve as containers for application specific functions. These functions are not managed by the \gls{os} and must be added to the process code by the user. \gls{autosar} invented the concept of runnables to solve problems related to the \gls{vfb} (\glsdesc{vfb}) introduced by the \gls{autosar} architecture \cite{naumann2009autosar}. A runnable is essentially the same as a function. \textbf{Events} are system objects that can be set or not. Each event is owned by at least one extended task. Only a task that owns an event is allowed to clear and to wait for it. When waiting for an event a task switches into the waiting state. It is switched back to ready when the corresponding event is set. All tasks and category two \glspl{isr} are allowed to set an event. Events are used as a binary communication technique. One task can signal another one for example, if a certain resource has been released. Events are defined and assigned to tasks before runtime. All events assigned to a task are cleared when this task is activated. \textbf{Resource} management is used to manage access to shared objects. An \gls{osek} resource is basically a mutex. Each resource gets a ceiling priority that is at least as high as the highest priority of all tasks that access this resource. When a task accesses a resource and its priority is lower than the ceiling priority of this resource its priority is raised to the ceiling priority. The priority is reset to the original value once the task releases the resource. This technique ensures that a task that potentially accesses a shared resource cannot switch into the running state. This prevents priority inversion and deadlocks. On the downside, tasks with a priority lower than the ceiling priority may be delayed by a lower priority task. \textbf{Alarms} are used to activate a task, set an event or execute an alarm-callback routine. Each alarm has an alarmtime and a cycletime that is statically defined and measured in ticks. An alarm expires the first time after alarmtime ticks and afterwards every cycletime ticks. Thus, an alarm can be used to activate a task or set an event periodically. Each alarm is assigned to a counter object but each counter can be used by multiple alarms. Counters are responsible for triggering an alarm after the specified number of ticks have passed. Each \gls{osekos} offers at least one counter that is based on a hard- or software timer. \textbf{Hook routines} can be used to allow user-defined code within OS internal processing. They cannot be preempted by tasks and \glspl{isr} and only a subset of the available \gls{os} services is available from their context. The StartupHook and ShutdownHook can be used to execute user specified code at system start and shutdown. \gls{os} errors result in a call to the ErrorHook. It can be used to execute application specific error handling. Finally, PreTaskHook and PostTaskHook are called at task start and termination. \subsection{OSEK OS Services} \gls{osekos} specifies system services that can be used to interact with internal \gls{os} mechanisms and objects like tasks or resources. The internal presentation of system objects is implementation specific. Only specified system services allow well-defined interaction with \gls{os} objects. A system service may take zero or more input parameters and may return zero or more output parameters via call by reference. The return value of an \gls{os} service is of type \lstinline{StatusType}. \autoref{tab:status_types} shows defined status types. \begin{table}[] \centering \begin{tabular}{r|l} Define & Meaning\\ \hline \lstinline!E_OK! & Service finished correctly. \\ \lstinline!E_OS_ACCESS! & Calling task is not an extended task. \\ \lstinline!E_OS_CALLLEVEL! & Service called from invalid level. \\ \lstinline!E_OS_ID! & Invalid \gls{os} \gls{id}. \\ \lstinline!E_OS_LIMIT! & Number of activations is exceeded. \\ \lstinline!E_OS_NOFUNC! & Alarm or resource is not in use. \\ \lstinline!E_OS_RESOURCE! & A resource is still occupied. \\ \lstinline!E_OS_STATE! & Object is in invalid state. \\ \lstinline!E_OS_VALUE! & Value is not allowed. \\ \end{tabular} \caption[\gls{osekos} error codes]{\gls{osekos} defines a \lstinline{StatusType} type that can be used to return an error code from service routines. This table shows the status types that are defined by \gls{osek} and their meaning. Users are free to define additional codes.} \label{tab:status_types} \end{table} A task can be activated via alarm or \lstinline{ActivateTask} service routine. Latter is callable from interrupt and task level. The task to be activated must be provided as an input parameter. If this task is suspended its state will be changed to ready. If it is not suspended the pending activations counter is incremented or \lstinline{E_OS_LIMIT} is returned if the \gls{mta} limit is exceeded. \lstinline{TerminateTask} is used to switch a task from running to suspended. All internal task resources are released and the service will not return if the call was successful. \lstinline{TerminateTask} will fail with \lstinline{E_OS_RESOURCE} if resources are still occupied by a task. \lstinline{ChainTask} is a combination of \lstinline{ActivateTask} and \lstinline{TerminateTask}. It terminates the current task and activates another task which is provided via input parameter. \begin{figure}[] \centering \includegraphics[width=\textwidth]{./media/osek/non_vs_full_schedule.pdf} \caption[Explicit \gls{osekos} schedule call]{An explicit call to the scheduler can solve the problem of a delayed higher priority task.} \label{fig:non_vs_full_schedule} \end{figure} \lstinline{Schedule} can be called to explicitly trigger a scheduling decision. This makes sense for non preemptive tasks if a task with higher priority is ready. Normally the task with higher priority is delayed until the task with low priority has finished execution as shown in \autoref{fig:non_vs_full_preemptive_scheduling}. By calling \lstinline{Schedule} the non preemptive task is preempted and the task with higher priority is executed as illustrated in \autoref{fig:non_vs_full_schedule}. The routines \lstinline{GetResource} and \lstinline{ReleaseResource} can be used to request and release resources. Nested resource requests are only allowed in last-in-first-out order, i.e.\ the resource that has been requested first must be released last. Within a critical section that is protected via a resource no calls to services that cause rescheduling are allowed. Both methods can be called from task and \gls{isr} level. If a requested resource is already occupied \lstinline{E_OS_ACCESS} is returned. Interaction with event objects is done via \lstinline{SetEvent}, \lstinline{ClearEvent}, \lstinline{GetEvent}, and \lstinline{WaitEvent} service routines. \lstinline{SetEvent} takes a mask of events that should be set for a specific task. Events can be deleted from the context of a process owning this event via \lstinline{ClearEvent}. \lstinline{GetEvent} returns the current status of all events related to a specified task. A task can wait for one ore more events using the \lstinline{WaitEvent} service routine. Waiting lasts until at least on of the specified events is set. The service routine \lstinline{GetAlarmBase} returns the basic configuration of an alarm. The remaining ticks until an alarm expires can be retrieved with \lstinline{GetAlarm}. \lstinline{SetRelAlarm} increases the remaining ticks by the submitted value while \lstinline{SetAbsAlarm} sets them to an absolute value. An alarm can be deactivated with \lstinline{CancelAlarm}. \subsection{OSEK OIL and ORTI} \label{subsection:osek_oil_and_orti} \begin{figure}[] \centering \includegraphics[width=\textwidth]{./media/osek/osek_code_generation.pdf} \caption[\gls{osekos} build process]{An \gls{osek} application is compiled from three sources. The \gls{os} kernel, user created code and \gls{osekos} object definition files which are created via code generation based on one or more \gls{oil} files.} \label{fig:osek_code_generation} \end{figure} The implementation of system objects is not specified by \gls{osek}. Therefore, users cannot know how to create system objects because correct definition is depending on the \gls{os}. \glsdesc{oil} (\gls{oil}) solves this problem by providing a meta language for defining system objects \cite{osekoil}. Based on \gls{oil} configuration files code generators provided by the \gls{os} vendor can produce \gls{os} specific source code. In combination with kernel and user code an application can be built as shown in \autoref{fig:osek_code_generation}. \gls{osek} specifies data types for all system object types. However, the implementation of the data types is \gls{os} specific. For example, a task is identified by \lstinline{TaskType}. \lstinline{TaskType} could be implemented as an integer indexing a global list of task objects or as a pointer to the task object itself. Only a minimum amount of data types necessary to interact with service routines are specified. Consequently, a lot of information is kept internally by the \gls{os} and is not available for the user. For example, there is no common interface to get data of the pending activations of a task, the current state of a resource, or the state of an event. Application code that needs this information would need to access the \gls{os} internals directly which results in portability and security issues. Moreover, external tools like debuggers that want to provide \gls{os} aware debug information have no standardized interface to relevant internal data. \glsdesc{orti} (\gls{orti}) was specified to solve this problem. Via \gls{orti} tool vendors have a standardized interface to \gls{os} internal data and properties of relevant system objects. The \glsdesc{koil} (\gls{koil}) format is used to exchange relevant information via the \gls{orti} file. This file contains mappings from \gls{os} object properties to variables that hold the respective information. \gls{orti} specifies a set of system properties that must be available for every \gls{osek} compliant \gls{os}. Operating system vendors are free to add additional information. Each \gls{os} object is described in a separate section of the \gls{orti} file. The specified sections that are relevant for this thesis are \emph{os}, \emph{task}, \emph{alarm}, and \emph{resource}. Information about the currently running process, the system error state, and the active service routine can be found in the \gls{os} section shown in \autoref{tab:os_attributes}. The \emph{servicetrace} attribute is written whenever a service routine is started or finished along with the \gls{id} of the corresponding routine. Task and \gls{isr} processes that are currently running in a system can be retrieved via \emph{runningtask} and \emph{runningisr2}. The attribute \emph{lasterror} provides information about the last failure condition. As shown in \autoref{tab:os_task} the \gls{orti} task section makes the current \emph{priority}, \emph{state}, and number of open activations (\emph{currentactivations}) for each task available. \autoref{listing:os_task} shows the textual representation of the \gls{orti} attributes for a single task. \begin{code} \begin{lstlisting}[caption={[\gls{orti} task example]Textual representation of the \gls{orti} attributes for a task entity.}, label={listing:os_task}] TASK T_CylinderResponser { priority = "osTcbActualPrio[30]"; state = "osTcbTaskState[30]"; currentactivations = "osTcbActivationCount[30]"; }; \end{lstlisting} \end{code} \autoref{tab:os_alarm} shows that alarms have an \emph{alarmtime} attribute that contains the ticks to the next expiry time. A \emph{cycletime} is used for periodic alarms. If a cyclic alarm expires, \emph{alarmtime} is reset to this value. An alarm can be running or stopped which is indicated by the \emph{state} attribute and executes a certain \emph{action} if \emph{alarmtime} becomes zero. A resource can be locked or free which is indicated by the \emph{state} attribute. In the former case the \emph{locker} attribute indicates the corresponding process as shown in \autoref{tab:os_resource}. The resource \emph{priority} is also accessible. \begin{table}[] \centering \begin{tabular}{r|l} Attribute & Content \\ \hline runningtask & currently running task \\ runningisr2 & currently running category 2 \gls{isr} \\ servictrace & indicates entry and exit to service routines \\ lasterror & contains the last error code set by the system \\ \end{tabular} \caption[\gls{orti} \gls{os} section]{The \gls{orti} \gls{os} section provides information about the running task and category 2 \gls{isr}, entry and exit to service routines and the last system error.} \label{tab:os_attributes} \end{table} \begin{table}[] \centering \begin{tabular}{r|l} Attribute & Content \\ \hline priority & task priority \\ state & task state (\autoref{fig:extended_task_state_model})\\ currentactivations & number of task activations \\ \end{tabular} \caption[\gls{orti} task section]{The \gls{orti} task section provides information about the current task priority, task state and number of activations. The task priority can be different to the statically defined value because of the priority ceiling protocol.} \label{tab:os_task} \end{table} \begin{table}[] \centering \begin{tabular}{r|l} Attribute & Content \\ \hline alarmtime & time till alarm expires \\ cycletime & alarm cycle time of periodic alarms \\ state & alarm state (running or stopped) \\ action & action at alarm expiry time \\ \end{tabular} \caption[\gls{orti} alarm section]{The \gls{orti} alarm section provides information about the time that is left until an alarm expires, its cycle time, the current state and the action that is executed once the alarm expires.} \label{tab:os_alarm} \end{table} \begin{table}[] \centering \begin{tabular}{r|l} Attribute & Content \\ \hline state & resource state (locked or unlocked) \\ locker & the task that has locked a resource \\ priority & resource priority \\ \end{tabular} \caption[\gls{orti} resource section]{The \gls{orti} resource section provides information about the state of a resource. A resource can be locked or not. For a locked resource the corresponding task is made available.} \label{tab:os_resource} \end{table} Additional sections and attributes can be found in the \gls{osek} \gls{orti} specification \cite{osekortib}. Even via \gls{orti} not all \gls{os} internals become available. Via \emph{servicetrace} it can be detected that a certain event is set or cleared but no information about the event itself is available. Consequently, for certain use cases it may still be necessary to access \gls{os} specific data structures manually.