MT/content/osek.tex

504 lines
26 KiB
TeX

\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.