Document not found! Please try again

Trampoline an opensource implementation of the OSEK/VDX RTOS ...

12 downloads 187600 Views 224KB Size Report
days an inescapable reference for automotive embedded. software. ... cording to the conformance classes of OSEK/VDX OS (see. below) it is possible to ...
Trampoline An OpenSource Implementation of the OSEK/VDX RTOS Specification Jean-Luc B´echennec, Mika¨el Briday, S´ebastien Faucou and Yvon Trinquet IRCCyN, UMR CNRS 6597, 1, rue de la No¨e - BP92101 44321 Nantes Cedex 3 - France {Jean-Luc.Bechennec, Mikael.Briday, Sebastien.Faucou, Yvon.Trinquet}@irccyn.ec-nantes.fr

Abstract This paper introduces an OSEK/VDX1 Operating System implementation. OSEK/VDX is an industry standard for real-time operating system used in the field of automotive embedded software. This implementation is proposed in the context of the open source software, which interest needs not to be demonstrated any more. The paper explains the main implementation choices as well as the technique proposed for the generation of a real-time application. This implementation is nowadays available for three targets: Infineon C167, Darwin/PowerPC and Linux/x86.

1

Introduction

The implementation of a real-time application depends on the choice which was made for its execution scheme. Two approaches are possible: synchronous and asynchronous. Synchronous approach is based on the null time hypothesis for the execution of actions; it led to the development of synchronous languages [1, 2]. Application program is converted into a state machine and a very simple kernel insures the management of the state machine according to the event occurrences. This approach offers numerous interests mainly for the application verification using formal methods. On the contrary, asynchronous approach is based on the hypothesis that any action takes some time to be executed. This has many consequences, notably the interleaving execution of tasks due to preemption and the necessity to use a real-time operating system (RTOS). This approach comes in two variants. The first one is based on the use of a single external event: the interrupt from the real-time clock. 1 OSEK/VDX: Offene Systeme und deren Schnittstellen f¨ ur die Elektronik im Kraftfahrzeug / Vehicle Distributed eXecutive

It allows to put rhythm into the application execution. It is the ”Time-Triggered” variant, a good example being the MARS system [6]. The other variant does not make limitation regarding the use of external events. It is the ”EventTriggered” variant. It is the most wide-spread at present. It is in this frame that the work presented here is situated. In a recent paper J.A. Stankovic and R. Rajkumar [9] presented an historical survey on RTOS, notably the academic works which allowed to develop numerous concepts which are now implemented in commercial products. In this paper the European OSEK/VDX consortium works are mentioned. The result of these works is a proposition of a standard for RTOS dedicated to embedded real-time applications in the automotive domain. This standard is nowadays an inescapable reference for automotive embedded software. Our contribution in this domain is to propose an implementation of the standard with an open source approach. The complete control of the implementation allows us rather easily to generate implementation for multiple targets (at present Infineon C167, Darwin/PowerPC and Linux/x86, MPC565 in a near future) and to propose various algorithms, in the scheduling domain for instance. Moreover we use our implementation in real-time systems labs in the University of Nantes. The paper is organized as follows: First we present a very short survey of OSEK/VDX standard. Then some related works are presented in section 3. In section 4, we expose the constraints and objectives we impose to our implementation. In section 5, the implementation and the main choices which were made are highlighted. Section 6 is devoted to the technique used for the application generation. Finally, concluding section proposes some perspectives on this work.

2

A very short survey of OSEK/VDX

OSEK/VDX aims at being an industry standard for RTOS used in distributed control units in vehicles. The European consortium aims at standardizing the interfaces of the operating system to ease application software portability, interoperability, re-use and the supply of software packages independently of hardware units. Various parts are proposed for the standard: OS (the basic services of the real-time kernel), COM (the communication services), NM (the Network Management services) and OIL (OSEK Implementation Language). The presentation below - which is very brief - concerns only the kernel of the operating system (OS 2.2.3, Feb, 2005), although our implementation also includes the communication subsystem (COM 3.0.3, july, 2004). For more information refer to [7]. All the objects of an OSEK/VDX application are static: they are created before the start-up of the application and are never destroyed (no dynamic allocation). Task management. OSEK/VDX specification provides two different task types. On one side, a basic task is a sequential code without service call being able to block the task. Synchronisation points are only at the beginning and the end of the task. On the other side, an extended task is composed of one or several blocks separated by invocations of service calls which may result in a WAITING state. According to the conformance classes of OSEK/VDX OS (see below) it is possible to authorize the record of activation requests of a task while it is already active. Every request is then recorded (no multiple instances) and taken into account when the task ends. Scheduling policy. For scheduling, static priority are assigned to tasks. Several tasks can share the same priority level according to the used conformance class, but the scheduling is independent of the conformance classes and the task’s type. For an application, the scheduling can be: full non preemptive, full preemptive or mixed preemptive. In this last case, every task has its appropriate mode (preemptive or non pre-emptive). The notion of group exists for tasks that share a common internal resource. Usual preemption rules are used for the tasks which are not in the group, according to their priority level. Inside the group the tasks can’t preempte among themselves. Conformance classes. The conformance classes define several versions of the real-time executive in order to adapt it to different application requirements. Four conformance classes were defined. They are determined by three main attributes and some implementation requirements: the type of task (basic or extended), the possibility of recording multiple activation request for a basic task and finally the number of tasks per priority level. BCC1 and BCC2 classes only allow basic tasks while ECC1 and ECC2 classes allow basic

and extended tasks in a software architecture. For BCC1 and ECC1 classes all the tasks have different priority levels and it is not possible to record multiple activation requests for the tasks. For BCC2 and ECC2 classes several tasks can share the same priority level; furthermore it is possible to record activation requests for basic tasks. Task synchronization. Synchronization (extended tasks only) is based on the private event mechanism: only the owner task can explicitly wait for the occurrence of one or more of its events (logical OR). The setting of occurrences can be made by tasks (basic or extended) or ISRs (Interrupt Service Routine). There is no timeout associated to the WaitEvent service call, but using the alarm concept (see below) it is possible to build watchdogs to monitor the temporal behavior. Resources management. OSEK/VDX co-ordinates the concurrent access to shared resources with the OSEK-PCP protocol (Priority Ceiling Protocol). OSEK-PCP protocol is more simple than original PCP [8], it is also known as ”Highest Locker” protocol. The resource sharing is allowed between tasks and ISRs or between ISRs (see 5.4). For that purpose, a virtual priority is assigned to every interrupt. Two services allow to control access to resources: GetResource and ReleaseResource. A predefined system resource ”Res Scheduler” allows a task to lock the processor. This allows a task to execute some code in non preemptive scheduling mode. Alarms and counters. These objects allow mainly the processing of recurring phenomena: timer ticks, signals from mechanical organs of a car engine (camshaft, crankshaft). They constitute complements to the event mechanism. They allow the management of periodic tasks and watchdog timers for the monitoring of various situations (wait for an event occurrence, send/receive a message). A counter is an object intended for the counting of ”ticks” from a source. An alarm allows to link a counter and a task. An alarm will expire when a predefined counter value is reached. At the occurrence of the alarm an action is taken. It can be either the activation of the associated task, the setting of an event of the task or the execution of a routine. An alarm can be defined to be a single alarm or a cyclic alarm, the corresponding counter value being absolute or relative to the current counter value. Communication. The communication services of OSEK/VDX are built around the ”message” object. Two types of messages are offered: those using the blackboard model (Unqueued Message, single place buffer); those using a FIFO (Queued Message). The communication services are the same whatever the communication is local or distant. Communication implementation is not the topic of this paper even if we have implemented a part of the OSEK/VDX COM 3.0.3 specification. For more information refer to [7].

3

Related works

Despite the standard status of OSEK/VDX, and the fact that it has been designed and promoted by major actors of the european automotive industry, some engineers confess that homemade solutions are still widely used. However, one can bet that this situation will evolve in the next years. First, the reasons that led to the creation of OSEK/VDX still exists: the automotive industry needs to solve software and system engineering issues such as portability, interoperability and reusability. Second, through the ITEA EASTEEA2 project and the AUTOSAR consortium3 , this industry is about to define a standard software development process. Such a process supposes the existence of a standard platform, OSEK/VDX being one of its main components. Last, the development of new critical functionalities, for instance X-by-wire systems, will impose the certification of the different layers of the software systems. In order to control the cost of these systems, it will be mandatory to use certified COTS, the RTOS layer being one of them. Today, OSEK/VDX (especially its time-triggered variant OSEKtime) seems to be a good basis to answer this last problem. Since the publication of the first OSEK/VDX standards, many implementations have been designed by RTOS vendor or automotive engineering society (eg. 3Soft, Accelerated Technology, ETAS, Metrowerk, Vector, WindRiver, etc.). They usually target 8, 16 or 32 bits microcontrollers with limited memory, typically used in automotive embedded systems. Most of them are certified (in order to be certified, an OSEK/VDX implementation must pass the MODISTARC4 conformance test suite). Considering this wide offer, at first sight, Trampoline could be seen as ”another implementation of the OSEK/VDX standard”. However, considering the main requirements stated below, its purpose is not to compete with commercial products. Concerning open-source initiative, we can cite PICos185 , an OSEK/VDX 2.1r1 (partially) compliant implementation dedicated to the PIC18xxx family of microcontroller. Being dedicated to this family of microcontroller, PICos18 is highly optimized, especially concerning memory footprint. On the other hand, it is poorly customizable (for instance, the task list always has 8 entries) and its port to another family of microcontroller would require to rewrite a big part of the kernel. It is still an interesting project for systems with small computation require2 EAST-EEA was an ITEA project (2001-2004) aiming at enabling a proper electronic integration through the definition of an open architecture (http://www.east-eea.net). 3 AUTOSAR (for AUTomotive Open System ARchitecture) is a partnership aiming at defining an open standard for electronic embedded architecture (http://www.autosar.org). 4 MODISTARC was an ESPRIT project aiming at providing the relevant test methods and tools to assess the conformance of OSEK/VDX implementations (see OSEK/VDX website for more details). 5 PICos18 project website: http://www.picos18.com

ments. An other initiative is openOSEK6 . Unfortunately, the project website does not show many activities and no release have been published yet. Concerning academic initiative, we can cite EMERALDS-OSEK [11], an OSEK/VDX OS 2.0 compliant API developed on top of the EMERALDS microkernel by the Real-Time Computing Laboratory at the university of Michigan. We are not aware of its availability. The paper introduces different optimizations allowing to reduce the memory footprint of an OSEK/VDX system, for instance sharing a single stack between all the non-preemptive basic tasks of the system. As explained in section 5, similar optimization are used in Trampoline.

4

Aims of the RTOS

Trampoline[4] has been designed with different constraints in mind: portability to different targets, memory usage limitation, availability of the four conformance classes and use of a supervisor mode. It complies to the OS 2.2.3 specification. Portability. Whereas a target is generally referred on desktop computers as a couple of an operating system and a processor (Linux/x86, Darwin/PowerPC, etc.), a target on embedded computer is associated to a couple of an ABI (Application Binary Interface) and a processor on microcontrollers. The ABI, which is defined by one or more compilers, must be included in the definition of a target because it deeply impacts on the generated code. For instance, for Infineon C167, the generated code from Keil compiler 7 uses two stacks: a system stack for function calls and a user stack for local variables and parameters passing. This user stack is only managed by the compiler (there is no assembly instruction related to that stack). To be easily portable, operating systems use a Hardware Abstraction Layer (HAL). This way, all the code that resides above the HAL needs not to be adapted to a new target. In Trampoline code, functions that are specific for a target are clearly isolated. These functions are limited to the strict minimum as they concern only context switching, initialization and a few hardware specific functions (interrupt enabling, sleeping mode, etc). There are currently three targets: Darwin/PowerPC 8 , Linux/x86 and Keil/C167. All the other functions are implemented using strict ANSI C and have been successfully tested with different compilers (Keil C compiler for C167 and GCC for PowerPC and x86) with the most restrictive options. 6 openOSEK

project website: http://www.openosek.org. http://www.keil.com 8 In that case, the whole application (including tasks and real time kernel) runs directly in a Unix process. Trampoline is responsible for the context switches in the Unix process, and may be preempted by the hosting OS. See section 6.2 7 See

Memory usage limitation. The memory usage must be as low as possible, especially for RAM. On small microcontrollers typically used in in-vehicle embedded systems, the amount of RAM is very limited (from few hundreds bytes, to few kilobytes). The ROM usage is a little bit less problematic (tens of kilobytes). Upgrading to a more powerful micro-controller would imply a cost repercussion on each vehicle and may not be acceptable for high volumes. Supervisor mode. Most high efficient micro-controllers (the PowerPC architecture is a good example) have at least two levels of privilege: supervisor mode (typically used by the operating system) and user mode (used by the application software). This feature allows to implement some kind of memory protection to isolate data of the kernel from the application and to prevent OS data structures corruption (supervisor data space). Function registers related to the system configuration (including exception and interrupt mechanism) are restricted to the supervisor mode. This characteristic ensures that the processor remains in the appropriate configuration, with a correct OS behavior even if a task has crashed. The main drawback is that the other tasks may have been corrupted (there is no memory protection between tasks). Incorporating the supervisor access into Trampoline implies switching from supervisor mode to user mode for each system call, which is deeply dependent of underlying hardware. It has not been implemented yet, but this approach has been taken into account in the design and may be adapted with few efforts. Conformance classes. As explained in section 2, the OSEK/VDX OS standard supports four conformance classes. Trampoline has been designed to meet the requirements of all of the 4 classes. The more unrestricted class ECC2 has been the first target. Some parts of the OS source code are taken away to obtain the other 3 conformance classes, using conditional compilation.

5

Implementation

In this section, we will only focus on the implementation of some services to highlight some specific implementation choices we made according to the previously stated goals.

5.1

Startup

At startup, after hardware specific initializations and application intialization, autostarting tasks9 , if any, are activated. Then Trampoline calls the scheduler to give the CPU to the highest priority autostarting task. If there is no ready task available, tpl sleep is called. This function is hardware 9 When generating the application, some tasks can be set as AUTOSTART. Autostarting tasks are ready to run just after the startup of the operating system.

specific and should put the CPU in a sleep state or should go into an infinite loop. All these operations are done on the stack of the idle task. This special task runs when no other task is ready. As the other tasks, it has a task descriptor and a context but some fields are not used since this task cannot be activated and uses a very small subset of the services of the OS. The priority of the idle task is set to -1 while application tasks have priority greater or equal to zero (the higher the value, the higher the priority).

5.2

Scheduling

The scheduling policy of OSEK uses a static priority scheme. A priority level is assigned to each task at system generation time. Depending on the conformance class, the same priority can be assigned to several tasks. A task can be in 4 states : SUSPENDED, WAITING (ECCx only), READY and RUNNING. A suspended or waiting task is not stored in any special structure of the OS since it is explicitly identified when calling a service. The reference to the running task is kept in a pointer called tpl running task. A READY task set is managed by the scheduler of Trampoline. When the ready task with the highest priority gets the CPU, it is removed from the set and switches to the RUNNING state. It stays in the RUNNING state until it terminates or calls a blocking service or a higher priority task becomes READY. Additionally, a task may be nonpreemptable. In this case, it keeps the CPU even when a higher priority task becomes READY. Mixed scheduling is also possible by using task groups. A task belonging to a task group is not preemptable by other tasks of the same group although it is preemptable by higher priority tasks that do not belong to the same group. In ECC2 and BCC2 conformance classes, Trampoline uses a list to store the READY tasks. This structure differs from a linear list in the following way: the descriptors of the tasks that share the same priority level are linked together to build a task subset. Task subsets are linked from the highest to the lowest priority to build the ready tasks set (see figure 1). Using this structure, the highest priority task is always at the head of the list. On the one hand, the activation of a higher priority task is fast because the insertion of a task begins from the head of the list. On the other hand, the activation of a task with a priority equal to the lowest priority of the ready task is slow because we have to travel along the sets then to the end of the last set (see paragraph 5.7 for some performance measures). While a linear list needs a O(n) sequential search when a task is enqueued, [5] has shown that linear list is faster than more sophisticated algorithm for a number of items fewer than about 10 and has comparable performance for up to 30-40 items. The number of tasks in a typical OSEK

would be set to NULL, avoiding the waste of RAM. The context and stack structures are black boxes for the kernel. They are managed through architecture dependent function. This achieves the third goal. context stack *static_desc *entry *resources id *next_exec base_priority *next_set max_activate_count activate_count type priority tpl_exec_static state evt_set *static_isr_desc evt_wait tpl_exec_common

application is in this range. For ECC1 and BCC1 conformance classes, to reduce the task descriptor RAM usage, it is planned to use a simple list since a set contains exactly one task descriptor. A simple list could be also used for ECC2 conformance class too if RAM is scarce but task activation of lower priority tasks would be slower. tpl_task_list_head task set task descriptor

task descriptor

task descriptor

next_set

next_set

next_set

next_task

next_task

next_task

NULL

tpl_task task descriptor next_set next_task

NULL

NULL

NULL

… TerminateTask(); }

tpl_isr

task descriptor next_set next_task

NULL

NULL

Figure 1. Ready task set list structure used in Trampoline. Adding a ready task to the set requires traveling along the subset list to find the subset that matches the priority. If it does not exists, the ready task makes a new set of its own.

5.3

void f(void) {

Figure 2. Trampoline ECC2 task descriptor. The task descriptor is split in two parts: 1) tpl exec static contains data that do not change during the execution of the application. This part can be stored in ROM. The grayed fields are hardware dependent pointers to context(s) and stack(s). 2) tpl exec common is the dynamic part of the task descriptor and is used for basic tasks. It is extended with events specific fields for Extended Tasks or with interrupt handler informations pointers for ISR2.

Task Management 5.4

The task descriptor has been designed so as to meet three goals: 1) minimizing the RAM usage, 2) sharing of the stacks and the contexts among tasks that will not be running at the same time (this leads to a lower RAM usage too), 3) being independent of the target architecture (as much as possible) to ease portability. To achieve the first goal, the task descriptor has been split in two parts (see figure 2). The first one gathers the data that are updated while the system is running and must be stored in RAM. It is linked to the second one, the static descriptor. This one gathers the static data and can be stored in ROM. Two structures are architecture dependent in the static descriptor: the context structure and the stack field structure. These structures gather one or more pointers to the RAM zones which store the saved context and the execution stack. This achieves the second goal since tasks can share the same RAM zones when possible. Moreover the design of the context structures allows to reduce the RAM usage. For instance, if the target is a processor with a FPU, the context structure would have two pointers, the first one pointing to the integer context RAM zone and the second one pointing to the floating-point context RAM zone. Since the FP registers are not used by each task, the second pointer

Level 2 Interrupt Service Routine

ISR2 are interrupt routines that can call a large subset of the OSEK services. They can even share resources with tasks. This feature would lead to an unfortunate situation where an ISR2 is started and tries to get a resources which is already held by a task. A way to implement the resource sharing between tasks and ISR2 would be to allow the GetResource (resp. ReleaseResource) service, when invoked from task level, to disable (resp. enable) the interrupts that could access the resource. Having the interrupt disabled for a long time is the main drawback of this implementation. Another way is suggested by the OSEK specification [7]. This situation can be handled by giving a priority to the ISR2 and using OSEK PCP. This way, a task that gets a resource shared with an ISR2 will have its priority level arisen to a priority higher than the ISR2 priority level. With this feature, ISR2 are almost like task, but with a higher priority. For the sake of simplicity and to keep the kernel smaller, Trampoline takes the plunge and implements a kind of deferred ISR for ISR2. Both task and ISR2 descriptors inherit from a common object called a running object. A task adds data for event management and ISR2 a pointer to additional data that can be stored in ROM (see figure 2). An

ISR2 is hooked to an interrupt vector. When the interrupt is raised, Trampoline activates the corresponding ISR2 and returns. The ISR2 is then executed according to the standard scheduling policy at task level and handled by the scheduler that manages the tasks. Moreover, this implementation adds an abstraction level for ISR2. On one side, when a hardware interrupt is raised by a device, the instructions at the corresponding interrupt vector offset are executed. Several hardware interrupts can share the same interrupt vector offset. On the other side, attached to this interrupt vector offset, there is a set of ISRs: each of them corresponds to a hardware interrupt and is activated as a response to it. To find the ISR that matches a hardware interrupt, each of these ISRs must supply a function that tests the corresponding device interrupt flag. If the function returns TRUE, the ISR is activated. This work is done by the General Interrupt Handler (GIH), in charge of dispatching the ISRs in response to hardware interrupt requests. Two concerns are raised by the implementation we used in Trampoline. First, the execution of an ISR2 can be preempted by a lower priority hardware interrupt which activates the GIH in order to dispatch another (lower priority) ISR2. This is a big issue since traditionally a high priority ISR cannot be interrupted by a low priority interrupt. Anyway, the high priority ISR2 will be preempted by the GIH only (which has an execution time comparable with the one of ActivateTask service), not by the execution of the low priority ISR2. This newly activated low priority ISR2 will stay in the ready queue until the high priority ISR2 terminates. Second, according to the OSEK specification, no rescheduling takes place while ISRs are running. Instead, a rescheduling is done after the last ISR2 terminates. In Trampoline, the task scheduler is used to schedule the ISR2. Hence, a rescheduling is done when each of the ISR2 terminates. However the nature of this rescheduling is specific. In the OSEK specification, rescheduling means rescheduling of tasks. Here, while there is at least one ISR2 running, the rescheduling is done among the ISR2 since they have higher priorities than tasks. When the last running ISR2 terminates, the rescheduling gives the CPU to the highest priority task.

5.5

Alarm Management

Alarms are OSEK objects used to notify recurring events. An alarm has two states: SLEEP or ACTIVE and, when activated, can have a one shot or a cyclic behavior. Each alarm belongs to a counter which is often derived from a hardware timer. A counter counts hardware ticks (it can be prescaled) and updates a current date. When an alarm becomes ACTIVE (as a result of SetRelAlarm or SetAbsAlarm system calls) Trampoline computes its expiration

date and inserts it in its counter alarm queue. When the date of the counter equals the next alarm expiration date, the alarm expires and is removed from the queue. At expiration time, an alarm may have three behaviors: 1) a task activation, 2) a callback routine execution, 3) an event setting. A cyclic alarm is put back in the queue after date computation. Since counters have a maximum value, date computation is done modulus this maximum value and a date may be lower than the current date although it is in the future. The counter keeps a pointer to the next alarm. When the pointer reaches the end of the queue, it is reset to the beginning. Figure 3 shows the data structures involved in alarm management.

Time

Head Counter Next

Alarm 3

Alarm 4

current date Alarm 1

Alarm 2

Figure 3. Alarm management data structures. Each counter manages an alarm list. Head points to the first alarm of the list and Next to the nearest alarm. When the current date reaches the date of the alarm pointed by Next, the alarm expires, is removed from the queue and the code corresponding to its behavior is executed. In both cases Next and Head are updated if necessary.

5.6

Memory requirements

Trampoline has been designed to use a very small memory space. Compiled for the C167 (16 bits) target, it uses about 2.6 Kbytes of ROM. The internal variables of the kernel uses only 10 bytes of RAM and 4 bytes (on a 32 bits target) per object (task, alarm, resource). In addition each kind of object uses ROM and RAM. Table 1 gives the ROM and RAM used by object for PowerPC (32 bits) and C167 (16 bits) targets. The RAM used by the context of a task is not counted in this table because it is not saved on the stack. Instead, it has its own memory zone. This is useful because micro-controllers often have many RAM zones with different performances and sizes. This way, stacks can be put in internal RAM (for instance) and contexts in external RAM. Most of the RAM is used by contexts. For the PowerPC target, an integer context uses 144 bytes and a floating-point context uses 260 bytes, so the ability to share a context among non-preemptive tasks can have a huge impact on RAM usage.

Table 1. Memory used by some OS objects (sizes are in bytes)

Object Task Resource Alarm Counter

5.7

PowerPC (32 bits) ROM RAM 24 21 10 10 17 14

C167 (16 bits) ROM RAM 14 13 6 6 11 10

Timing performances

Timing performances are a key feature in the design of a RTOS. Good timing performances must be achieved using appropriate algorithms (finding the next running task in ready tasks in constant time for instance), and not with lowlevel programming (extensive assembly language). This would be in contradiction with the portability goal. Measures presented in this section have been realized on an Infineon C167 processor at 20MHz. The performances of the scheduler presented in section 5.2 depends on the number of ready tasks. To highlight this dependency, we have measured the execution time of the ActivateTask service when inserting the lowest priority task of the system, with a range of 0 to 20 ready tasks. As we have to travel along the whole list of ready tasks, this is the worst case scenario without context switch (see table 2). As can be seen, the execution time is composed of a constant part (about 50 µs) and a variable part equals to 2µs times the number of higher priority tasks in a ready state. When calling ActivateTask for the highest priority task of the system, the variable part is null. Nevertheless, in this case, a context switch is performed (iff the running task can be preempted). For this scenario, we have measured a 92.4 µs execution time. As ISR2 are managed by Trampoline like high priority tasks (see paragraph 5.4), the ISR2 latency is similar to the activation of a task. We have measured the time from the instant where the interrupt raised to the instant where the first instruction of the user code of the ISR2 is executed. We obtain 84 µs, which is less than the activation of a task.

6 6.1

How to use Trampoline Generation of the application

Three targets are currently available for Trampoline: Infineon C167 with Keil Compiler, Darwin/PowerPC and Linux/x86. The Freescale MPC565 (with Metrowerks Codewarrior) target is under development.

Table 2. Execution time of the ActivateTask service when inserting the lowest priority task of the system, with a range of 0 to 20 ready tasks. Time is in µs. number of tasks ActivateTask

0 49.6

5 60.4

10 70.8

15 81.2

20 91.6

As OSEK/VDX is a static operating system, a definition of the system objects is required before compiling. The OIL (Osek Implementation Language) is the standard language to write this definition. It allows to define all the parameters of the objects of the application (configuration of the tasks, ISRs, alarms, counters and resources). Using this language makes a standardized interface between all the OSEK implementations shipped with an OIL compiler and (graphical) development tools used for application design (such as osCAN from Vector or OSEKWorks OIL graphical configurator from WindRiver) which generates OIL files. There is currently no OIL implementation available for Trampoline. Instead, to allow a rapid design of an application, macros have been written using the M4 macro processor[3]. We choose M4 because it is present on almost all UNIX based systems and has been ported to MS Windows. The automatic generation of the C structures using the M4 preprocessors does not aim at replacing OIL, but rather at allowing rapid development until OIL is available.

6.2

First development stages on the host machine

In the first stages , the development of an application is made on a host machine, and (in most cases) debugged using a simulator of the target controller. These simulators are generally available with the development tools related to the target. To develop an application with Trampoline, another solution consists in testing preliminary versions of the application natively on the host machine. The development on the host machine has many advantages: the target may not be available, the development is independent of the target (evaluation of the computation requirements), and the application is run at a higher speed than using a simulator. To allow the first steps of the development on the host machine, Trampoline can run natively on PowerPC (with Mac OS X) or an Intel compatible x86 (with Linux 2.6.x) with GCC. In that case, the whole application (including tasks and real time kernel) runs in a Unix process. Trampoline is responsible for the context switches in the Unix process, and may be preempted by the hosting OS. The main drawback of this method concerns the inter-

rupts that cannot be taken into account. This is a real problem for periodic tasks and alarms that are based on hardware timers. This handicap is resolved using another Unix process that sends fake interrupts requests to the former process (using POSIX signals). This other program is called Viper, which stands for VIrtual Processor EmulatoR (see figure 4). Host machine

Task1

...

Task 2 Trampoline OSEK kernel

Tn IT

VIPER VIrtual Processor EmulatoR

UNIX based Host Operating System (Mac OS X, Linux, ..) OSEK application tasks

Unix process POSIX signal

IT

Interrupt handler of Trampoline

Figure 4. First development stages on the host machine, using Viper to emulate interrupts.

The Trampoline application that runs on the host machine is the same as the one on the target, except the machine dependent code. Hence, timer configuration code, which is target specific, is replaced by Viper specific code, to accept signals raised by Viper. The Viper process can be configured to emit one or more POSIX signals. The Trampoline application accepts the signals and serves it as an interrupt. With such a mechanism, periodic tasks can be executed. Unfortunately, timings can’t be taken into account as the host operating system can preempt the two running processes related to Trampoline and Viper. This mechanism is still very useful for a functional validation in the first stages of the development process.

7

Conclusion

We have developed Trampoline , an open source implementation of the OSEK/VDX RTOS standard designed to be portable. Three targets are available: Unix process with GCC (PowerPC or x86) compiler and C16x with Keil compiler. The Unix process implementation is a special HAL that allows application functional test in a comfortable environment. Trampoline is also designed to be memory efficient (especially RAM). In this regard, great attention has been paid to object descriptors (task, resource, alarm and counter) to minimize the RAM usage. Trampoline is an academic initiative, still in early development stage. For this first release, as stated in section 4 we have chosen to focus on portability. As a consequence, many hardware-dependent optimizations have not

been considered, which would have led to smaller memory footprint and latency time. As a beneficial counterpart, the source code of Trampoline is easily understandable (we used it with success this year for a master level course on real-time scheduling). Now that we have a running prototype, together with the on-going validation process, the next developments will certainly focus on the implementation of state-of-the-art solutions for the kernel data structures and algorithms, together with the research of new solutions that conciliate portability and efficiency. We also hope that the choice of an open source license will encourage the RTOS research community to use Trampoline as a basis for some of its works and that results of these works will help to improve Trampoline. Concerning port to other platforms, we will add in a near future the MPC565 with Metrowerks Codewarrior compiler target. Performance comparison with other implementations is also planned. Other planned works around Trampoline include power aware scheduling algorithms study, online execution time measurement for feedback scheduling techniques, and an OIL compiler. Trampoline is distributed under the LGPL license (http://trampoline.rts-software.org/).

References [1] G. Berry and G. Gonthier. the ESTEREL synchronous programming language: design, semantics, implementation. Science of Computer Programming, 19(2):87–152, 1992. [2] Esterel Technologies. Esterel Technologies website. http: //www.esterel-technologies.com. [3] F. S. Foundation. Gnu m4 - gnu macro processor. http://www.gnu.org/software/m4/manual/ index.html, 1989-2005. [4] R.-T. S. group IRCCyN. Trampoline. http:// trampoline.rts-software.org/, 2005. [5] D. W. Jones. An empirical comparison of priority-queue and event-set implementations. Commun. ACM, 29(4):300–311, 1986. [6] H. Kopetz et al. The MARS Approach. IEEE Micro, 9(1):25–40, 1989. [7] OSEK Group. OSEK/VDX Operating System Specification. http://www.osek-vdx.org. [8] R. Rajkumar and J. Lehocsky. Priority Inheritance Protocols: an Approach to Real-Time Synchronisation. IEEE Transaction on Computer, 39(9):1175–1185, 1990. [9] J. Stankovic and R. Rajkumar. Real-Time Operating Systems. The Journal of Real-Time Systems, 28(2/3):237–253, 2004. [10] S. Suzuki et al. A Distributed Control System Framework for Automotive Powertrain Control with OSEK Standard and CAN Network. In Society of Automotive Engineers Congress and Exposition, 1999. [11] K. Zuberi et al. EMERALDS-OSEK: A Small Real-Time Operating System for Automotive Control and Monitoring. In Society of Automotive Engineers Congress and Exposition, 1999.