Sunteți pe pagina 1din 92

TRAINEESHIP – PROJECT

Installation and Implementation of Xenomai on an Industrial Component and Porting a Driver for an Industrial IO-Card to the Xenomai Infrastructure

by Ondrej Cevan

Submitted in partial satisfaction of the requirements for the degree of BACHELOR of COMPUTER ENGINEERING at the Vienna University of Technology

Advisors:

Professor Dr. Uwe Schmidtmann and Dipl.-Inf. Bodo Wenker (Institute I2AR, Emden University of Applied Sciences)

Univ.Ass. Dipl.-Ing. Dr.techn. Wilfried Elmenreich (Institute of Computer Engineering, Vienna University of Technology)

July-August 2006

Installation and Implementation of Xenomai on an Industrial Component and Porting a Driver for an Industrial IO-Card to the Xenomai Infrastructure

Xenomai is a new real-time operating system emulation framework based on GNU/Linux. It was designed with the goal to help application designers using traditional and proprietary real-time operating systems to move as smoothly as possible to a GNU/Linux based execution environment.

The aim of this work is to establish a Xenomai environment on an indus- trial computer from Siemens and write a simple device driver for the digital I/O card CPCI-EA221 using the Real-Time Driver Model (RTDM) which is integrated in Xenomai. To achieve this goal, first a simple real-time user- space task under Xenomai was created. As a second step a Linux device driver was written and later adapted to the Xenomai-RTDM features.

The Fachhochschule (The University of Applied Sciences) in Emden, Germany, initiated this work because of the increasing interest on Xenomai real-time environment in the industry. This work is supposed to be used for further research and working on Xenomai at the university mainly in the automation sphere.

i

Contents

1 Introduction

 

1

1.1 Xenomai .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

2

1.2 Workplace

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

2

1.3 Source Code

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

4

1.4 Structure of the Project Report

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

5

2 Xenomai – an Installation Guide

 

6

2.1 System Requirements

 

.

.

.

.

.

.

.

.

.

.

.

6

 

2.1.1

Preinstallation Steps

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

6

2.2 Downloading and Unpacking the Sources

 

8

2.3 Compiling

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

9

2.4 Setting up Bootloader and Testing

 

12

 

2.4.1 Configuring LILO .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

12

2.4.2 Configuring GRUB

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

13

2.4.3 Testing .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

14

2.4.4 Error Handling

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

15

3 Xenomai- First Application

 

19

4 Linux Driver

 

21

4.1

Programming the Driver

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

21

4.2

API

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

23

4.2.1 IOCTL Code and Argument Structure:

 

24

4.2.2 Examples:

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

24

4.3

Test Application

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

25

5 Xenomai – RTDM Driver

 

26

5.1

Programming the RTDM Driver

 

26

5.2

API

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

28

5.2.1

Examples:

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

28

5.3

Test Application

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

28

6 Conclusion

 

30

6.1 Problems .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

30

6.2 Outlook

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

31

 

ii

7 Listings

32

7.1 Xenomai – First Application

 

.

.

.

.

.

.

.

.

.

.

.

33

7.1.1 timer 1.c .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

33

7.1.2 timer 2.c .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

36

7.1.3 Makefile

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

39

7.2 Linux Driver .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

40

7.2.1 cpci ea221 driver.c

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

40

7.2.2 cpci ea221 driver.h

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

51

7.2.3 test led.c .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

54

7.2.4 test led.h

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

57

Makefile

7.2.5 .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

58

7.2.6 cpci ea221 load.sh

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

60

7.2.7 cpci ea221 unload.sh

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

62

7.3 Xenomai- RTDM Driver

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

63

7.3.1 xen cpciea221 driver.c

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

63

7.3.2 xen cpciea221 driver.h

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

75

7.3.3 xen led timer.c

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

77

7.3.4 xen led timer.h

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

83

7.3.5 Makefile

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

85

References

87

 

iii

1 Introduction

This project report is intended to be used as a manual for establishing Xeno- mai environment which runs together with Linux distribution and for writing first Linux device driver and Xenomai device driver for CPCI 1 cards. We chose the way of writing this report as a manual because this project should explain installing the Xenomai environment and make the step-in phase for program- ming device drivers mainly in Xenomai smoother. The following sections will briefly introduce the major facts on our working environment and then the next chapters will show you the way to the Xenomai driver for a CPCI card.

1 a standard based on PCI, see section 1.2

the way to the Xenomai driver for a CPCI card. 1 a standard based on PCI,

Figure 1.1: the workplace

1

1 Introduction

1.1 Xenomai

1.1 Xenomai

There are different real-time operating systems (RTOS) these days using dif- ferent APIs, but one can find common features and behaviors among many of them. Major embedded RTOS, such as VRTX, VxWorks, pSOS+ and a few others, have implemented a real-time kernel behavior which has become a de facto standard. Xenomai uses these similarities to build a nucleus offering set of generic services. These services build an architecture-neutral abstrac- tion layer, that provides the foundation for developing emulation modules of real-time application programming interfaces, which mimic the corresponding real-time kernel APIs. One can set the Xenomai’s emulators or APIs for real- time operating systems at configuring the kernel in the kernel menu [Real-time sub-system- >Interfaces ]. We will come to it in the next chapter. Of course there is also the possibility to use the Xenomai’s native API, which was used at programming the applications for this project. For a detailed report on im- plementing a RTOS emulation framework on GNU/Linux see the paper [Ger04]. The aim which Xenomai wants to achieve with this approach, using the simi- larities among traditional RTOS, is to offer the application designers a smooth and comfortable way for migrating the real-time applications from traditional RTOS to GNU/Linux.

To make Xenomai’s tasks hard real-time in GNU/Linux a Real-Time Appli- cation Interface (RTAI) [rta] co-kernel is used. It allows to run real-time tasks seamlessly aside of the hosting GNU/Linux system while the tasks of the ’reg- ular’ Linux kernel can be seen as running in a low-priority mode. The RTAI co-kernel shares hardware interrupts and system-originated events like traps and faults with the Linux kernel using the Adaptive Domain Environment for Operating Systems (Adeos) 2 [ade, Ger05] virtualization layer, which in turn ensures RTAI low interrupt latencies.

You can find a lot of useful information on Xenomai on the webpages [xenb, xena, Unib] and in the Xenomai source directory 3 .

1.2 Workplace

This traineeship project was done at The University of Applied Sciences in Emden, Germany, in July- August 2006. At our disposal we had a Siemens industrial computer Sicomp SMP16, figure 1.2, and a Siemens digital I/O card CPCI-EA221, figure 1.3.

2 Adeos can be loaded as a Linux module to allow another OS to run along with it. 3 it depends where you installed the sources, we had it in /usr/src/xenomai-2.2.0/doc

2

1 Introduction

1.2 Workplace

1 Introduction 1.2 Workplace Figure 1.2: SICOMP-SMP16 c Siemens Figure 1.3: CPCI-EA221 c Siemens The industrial

Figure 1.2: SICOMP-SMP16 c Siemens

1.2 Workplace Figure 1.2: SICOMP-SMP16 c Siemens Figure 1.3: CPCI-EA221 c Siemens The industrial

Figure 1.3: CPCI-EA221 c Siemens

The industrial microcomputer SICOMP [Sieb] is a high performance modu- lar, open board architecture system that allows hardware systems to be tailored individually to a task and combined with customer developments. Our Sicomp had a SMP16 CPCI central processing unit (CPU) with the 1266MHz power and a CPCI bus interface. The hardware is PC compatible and has been ex- panded with additional safety functions.

Compact PCI (CPCI) is a high-performace standard based upon peripheral component interconnect (PCI) technology and is a norm of the PICMG (PCI

3

1 Introduction

1.3 Source Code

1 Introduction 1.3 Source Code Figure 1.4: input/output control box Industrial Computer Manufactures Group). Because it

Figure 1.4: input/output control box

Industrial Computer Manufactures Group). Because it is based on PCI, device drivers for CPCI can use the same design approach as normally used for PCI device drivers.

The CPCI-EA221 card is a plug-in computer card. It has 16 input and 16 output pins and 4 control LEDs on the front panel. The control LEDs signal the state of the input/output pins, depending on the configuration setting. The possible configurations and other technical information on the device can be found in [Siea]. To test the inputs and outputs of the card we used a device connected to the port of the card, picture 1.4. It was also connected to a 24V source as the input voltage of the card is that high. On the leds of this test device we could observe the states of all of the 16 output pins and set the state of every of the input pin with the devices’ buttons.

On our Sicomp computer a Linux distribution, Debian GNU/Linux, release 3.1 (sarge ), with Linux kernel 2.6.17.6 was installed and run together with Xenomai. The way how to establish the Linux environment together with the Xenomai is described in the next chapter 2.

1.3 Source Code

Care has been taken to comment the source code to make reading the code more comfortable, however, for better and deeper understanding of the used

4

1 Introduction

1.4 Structure of the Project Report

functions one should read the relevant APIs. It would make no sense to write detailed description of the used operations into the source code nor into this project report.

One can see some free places in the code that should be filled before the driver can be said to be complete. When we found such places we wrote there TODO and noted what we think there should be done. It is important to remark that the code listed at the end of this project report does not have the ambition to be complete and ready for distribution. The basic aim was to get the understanding of how to write simple device drivers for Xenomai and to document that way, so that this document can be used as a starting point for further developing of a driver for Xenomai. We wrote the Linux device driver to obtain basic knowledge needed for writing drivers also under Xenomai. We didn’t get into its precise code writing. Nevertheless, the code is functional and we think and hope that it, together with the documentation, will be helpfull source for future developers who want to start programming device drivers under Xenomai.

1.4 Structure of the Project Report

The project report is structured as follows: The Xenomai environment will be established in the chapter 2 and afterwards the chapter 3 shows two simple applications using the environment. On the base of these two codes the basic programming approach used in Xenomai is explained. The following chapter 4 concerns with the programming of Linux device driver for the CPCI-EA221 card to get the basic knowledge on programming PCI/CPCI driver modules. With that knowledge we can start programming Xenomai driver module in the chapter 5. The following chapter 6 summarizes the key results of the presented work and gives an outlook on what can be expected from future development and research in this area. Finally, the project report ends with the chapter 7 in which one can find the source code written and used in the scope of this project. All the documents, manuals, papers etc applied in this project are listed at the end of this project report.

5

2 Xenomai – an Installation Guide

This section describes the step-by-step approach we needed to go through to install Xenomai. To make the installation guide more schematic some Linux-Debian commands are present since Debian Linux was used as an en- vironment to prepare the with Xenomai extended Linux kernel. We used Linux kernel 2.6.17.6 and Xenomai version 2.2.0. To see other installation guides visit [Unib, Xenomai 2.1, 2.2 Installation Guide], [Len] and look at the readme.txt file in the Xenomai installation package.

2.1 System Requirements

This installation guide assumes that the user is running a functional GNU/Linux environment, best with a Debian or a Debian-like (e.g. Ubuntu) distribution. The user should be also familiar with the basic Linux commands and working in shell, because the whole installation process explained is real- ized in a terminal using CLI 1 . Since we will need the existing kernel config file of the Linux OS we are working in, it is necessary to ensure that the recent kernel version is 2.6.xx.yy. The best when the version is as close as possible to the kernel we are going to compile and to merge with the Xenomai extension.

2.1.1 Preinstallation Steps

Check the Linux kernel version you are currently using:

$ uname -r

2.6.12-10-386

To search for the latest available kernel image for your distribution using apt:

$ su

Password:

# apt-cache search ^kernel-image-2.6

#change to root, super-user mode

1 Command Line Interface

6

2 Xenomai – an Installation Guide

2.1 System Requirements

It is worth to checkup if /etc/apt/sources.list has a good source where these images can be found, e.g. add a line deb ftp://ftp.de.debian.org/debian/ stable main contrib to get the source to the stable packages of a Debian distri- bution. To get more help on configuring apt and its sources.list see man-pages or help on internet.

If the list you will get contains a kernel image with a newer version number than your current kernel, we recommend to install it. Take care to check that the kernel image is suitable for your CPU architecture. If you are not sure about the CPU of your computer, you can get the info with the command cat /proc/cpuinfo.

To install new kernel image:

#

apt-get install kernel-image-(version-number)

OR

#

apt-get upgrade ## your old recent kernel will be updated with the ## new available kernel, also if you have some older ## programs in your distribution they will be updated, ## see man pages of apt-get for more info.

The bootloader GRUB or LILO should be configured automatically by the program apt-get and offer you the possibility at boot-up to return back to the previous kernel version in case the new one will not work. We recommend that you check up that your bootloader is configured properly. See GRUB or LILO documentation for more info.

It is also important before starting with the compilation to check out if you have the correct version of the compiler . Make sure you have gcc-3.2 or newer. Older versions can have problems compiling newer versions of Linux kernel. First find the path to it and then check the symbolic link gcc if it is showing on the right compiler. If not, download the new one, and make a link to it.

# whereis gcc

gcc: /usr/bin/gcc /usr/lib/gcc

# cd /usr/bin/

# ls -l | grep gcc

gcc gcc-4.0 gcc-3.0

# ls -l gcc

lrwxrwxrwx 1 root root 7 Jan 23 17:23 gcc -> gcc-4.0

In this case is the compiler right. If your compiler is old:

7

2 Xenomai – an Installation Guide2.2 Downloading and Unpacking the Sources

# apt-cache search ^gcc

# apt-get install gcc-4.0

# cd /usr/bin/

# ls -l | grep gcc

lrwxrwxrwx 1 root root 7 Jan 23 17:23 gcc -> gcc-3.0

-rwxr-xr-x 1 root

root

89208 Oct

1 2005 gcc-4.0

-rwxr-xr-x 1 root

root

89208 Oct

1 2005 gcc-3.0

# ln -s gcc-4.0 gcc

# ls -l gcc

lrwxrwxrwx 1 root root 7 Jan 23 17:25 gcc -> gcc-4.0

One more sentence to the compiler: Do not compile Linux kernel and Xeno- mai with different compilers or different compiler’s versions, it could make Linux kernel and Xenomai incompatible.

2.2 Downloading and Unpacking the Sources

For establishing an Xenomai environment we need three files to download:

the Linux kernel source code

the Xenomai source code

and the Adeos ipipe patch, since Xenomai relies on the Adeos microkernel which is implemented as a patch.

Download the latest stable version of Linux kernel source, linux-

2.6.xx.yy.tar.gz, from http://kernel.org/ and save it to /usr/src. The main page [kerb] informs on the latest stable version. Next we will need the latest stable version of Xenomai. Download it from http://download.gna.org/xenomai/ and save it to /usr/src. Finally, the Adeos ipipe patch must be downloaded from http://download. gna.org/adeos/ and also saved to /usr/src/. Normally in Debian GNU/Linux was the Adeos patch provided in the package kernel-patch-adeos, but this package has not been updated for kernel versions more recent than

2.6.11.

# lftp

lftp :~> lftp http://www.kernel.org/pub/linux/kernel/v2.6/

lftp :~> get linux-2.6.17.6.tar.bz2 -o /usr/src/

8

2 Xenomai – an Installation Guide

2.3 Compiling

lftp :~> lftp http://download.gna.org/xenomai/stable lftp :~> get xenomai-2.2.0.tar.bz2 -o /usr/src/ lftp :~> lftp http://download.gna.org/adeos/patches/v2.6/i386

lftp :~> get adeos-ipipe-2.6.17-i386-1.3-08.patch -o /usr/src/ lftp :~> exit

#

Note that the version numbers can differ, but take care that the first three version numbers of the patch do match with the first three version numbers of the kernel. We recommend to use the latest stable versions.

To unpack the sources:

# cd /usr/src/

# tar -xjf linux-2.6.17.6.tar.bz2

# tar -xjf xenomai-2.2.0.tar.bz2

2.3 Compiling

Before you start compiling you will need to run a Xenomai script which informs the Linux kernel about Xenomai and the Adeos ipipe patch. The script will install Adeos and link Xenomai with Linux kernel.

# cd /usr/src/xenomai-2.2.0/scripts

# ./prepare-kernel.sh

The script will ask you for a path to the Linux kernel source and Adeos patch. Make sure you specify the right ones. In our case:

Linux path: /usr/src/linux-2.6.17.6 Adeos path: /usr/src/adeos-ipipe-2.6.17-i386-1.3-08.patch

Now we will need the existing config file of the recently running kernel. You should find it in /boot/ and copy it to /usr/src/linux-2.6.17.6/

There are more possibilities how to configure the kernel before compiling, one of them is with the command make menuconfig or you can also edit directly the file, e.g. vi .config which can be practical if you are searching for some specific attributes. With make menuconfig you will jump into a text-based menu-style configurator, where you can descend into the menus

9

2 Xenomai – an Installation Guide

2.3 Compiling

and change the configuration options which interest you.

IMPORTANT: if you are a newcomer in the kernel configuration and you don’t want to spend lot of time with recompiling the kernel it is wise not to change anything in the configuration. The result will be that the kernel will have many modules you will maybe never need and therefore it will be bigger and need more time to compile, also higher latencies in the real-time environment of Xenomai could occur. The good thing is that it should run just after one compilation without freezing and kernel panic at boot-up.

As a newcomer do just this in the configuration:

In the menuconfig main-menu you should see a sub-menu Real-time sub- system , enter it and make sure Xenomai is marked for installing as a build-in, meaning that it will be build directly into the kernel.

In Real-time sub-system > Interfaces make sure Native API is chosen for installing.

Make sure you don’t have SMP enabled if you are on a UP (uni-processor) machine [Unia].

If you decide to optimize your kernel the following hints will help you, but be sure, that you know that it will not make your kernel unable to run on your hardware. It is recommended to exclude all modules and build-ins, that you will not need later while working with the system, e.g. you could exclude Joystick interface, Touchscreens or ISDN support. Also set the file systems you will want to use and the system will need as build-ins. The web page [Len] recommends “to activate I-pipe and to deactivate some kernel features (essen- tially some power management features) that would ruin the latencies in the real-time kernel ”:

In Processor type and features :

Check that Interrupt pipeline is enabled (this is to enable the Adeos implementation - I-pipe). 2

Check that Local APIC support on uniprocessors and IO-APIC sup- port on uniprocessors are enabled.

In Power management options (ACPI, APM) :

2 In newer versions of Xenomai is this option not configurable.

10

2 Xenomai – an Installation Guide

2.3 Compiling

In ACPI (Advanced Configuration and Power Interface) Support:

Disable Processor.

In APM (Advanced Power Management) BIOS Support:

Disable APM (Advanced Power Management) BIOS support.

In CPU Frequency scaling:

Disable CPU Frequency scaling.

In Real-time sub-system

Optionally, if needed by your applications , enable Interrupt shield support.

Enable Watchdog support (this is sometimes useful).

In Scalability:

Optionally, if your applications create many RT threads, enable O(1) scheduler.

In Machine (x86):

Only if your system has FPU 3 , enable FPU support to improve latency.

In SMI workaround:

· Only if your system uses SMI 4 , AND you encouter high maximum latencies , enable Enable SMI workaround and Globally disable SMI 5 .

In APIs, enable all options.

In Drivers, enable all options.

Finally save changes and type make to let the kernel compile. Note: if you are compiling the kernel for the first time, it may be appropriate to inform you, that it takes, dependend from the computing power of your computer, one to three hours.

Shell commands to configure and compile the kernel:

3 Look for FPU in /proc/cpuinfo file 4 SMI- System Maintenance Interrupt 5 If some devices do not work anymore when loading Xenomai modules with the SMI workaround enabled, it probably means that those devices rely on SMI. You should try to re-enable some SMI interrupts in Xenomai’s SMI workaround configuration, one by one. Try to enable an SMI interrupt, compile and then disable it again if it has no effect. See also [Unib, High latencies with SMI not disabled].

11

2 Xenomai – an Installation Guide

2.4 Setting up Bootloader and Testing

# cp /boot/config-2.6.12-10-386 /usr/src/linux-2.6.17.6/.config

# cd /usr/src/linux-2.6.17.6

# make menuconfig

# make

# make modules_install install

We spent a lot of time recompiling the kernel searching for the right configu- ration. It is wise to get help from somebody who has already some experiences in it if you want to optimize the kernel. For more info or getting help with configuring, compiling and hacking the kernel, visit also webpages that are con- cerned with Linux kernel compilation, editing and hacking. As a starting point we recommend [lxc, kera]. Next go to the Xenomai directory and compile Xenomai:

# cd /usr/src/xenomai-2.2.0

# ./configure

# make

# make install

2.4 Setting up Bootloader and Testing

After the sources were successfully compiled you will need to add the new kernel to LILO or GRUB, dependend on what is your system using.

2.4.1 Configuring LILO

Keep in mind that you are adding new kernel, not changing the settings of the

old one. When there will be problem booting-up the new kernel you can still return to the old one. Say your lilo.conf 6 has something like this:

image=/boot/vmlinuz-2.6.8-2-686

label=linux-2.6.8

read-only

After adding the new kernel it should look like this:

6 You should find lilo.conf in directory /etc/ and open it in you favorite editor.

12

2 Xenomai – an Installation Guide

2.4 Setting up Bootloader and Testing

image=/boot/vmlinuz-2.6.8-2-686

label=linux-2.6.8

read-only

image=/boot/vmlinuz-2.6.17.6-xenomai

label=linux-xenomai

read-only

Save changes and inform LILO about the changed lilo.conf file with running the command lilo. Afterwards you can reboot into your new kernel. If you observe any problems at boot-up please read the sub-section 2.4.4.

2.4.2 Configuring GRUB

Keep in mind that you are adding new kernel, not changing the settings of the

old one. When there will be problem booting-up the new kernel you can still return to the old one. Say your menu.lst 7 has something like this at the end of the file:

title

Debian, kernel 2.6.15-1-486

root

(hd0,0)

kernel

/boot/vmlinuz-2.6.15-1-486 root=/dev/hda1 ro

initrd

/boot/initrd.img-2.6.15-1-486

savedefault

boot

After adding the new kernel it should look like this:

title

Debian, kernel 2.6.15-1-486

root

(hd0,0)

kernel

/boot/vmlinuz-2.6.15-1-486 root=/dev/hda1 ro

initrd

/boot/initrd.img-2.6.15-1-486

savedefault

boot

7 You should find menu.lst in directory /boot/grub/ and open it in your favorite editor.

13

2 Xenomai – an Installation Guide

2.4 Setting up Bootloader and Testing

title

Xenomai, kernel 2.6.17.6

root

(hd0,0)

kernel

/boot/vmlinuz-2.6.17.6-xenomai root=/dev/hda1 ro

savedefault

boot

Save changes and reboot. If you observe any problems at boot-up please read the sub-section 2.4.4.

2.4.3 Testing

After successfully logged into the system with the new kernel first check if Adeos is working with the command “dmesg | grep I-pipe ”. You should get this output:

I-pipe 1.3-06: pipeline enabled I-pipe: Domain Xenomai registered

also check if the directory /proc/ipipe/ exists. Next, the command “dmesg | grep Xenomai ” should return:

Xenomai: hal/x86 started Xenomai: real-time nucleus v2.2.0 (Seven String) loaded Xenomai: starting POSIX services. Xenomai: starting RTDM services.

if Xenomai was loaded properly. Also execute /usr/xenomai/bin/xeno-test. If no error occurs, any Xenomai application should execute fine also. The test measures real-time interrupt latencies of your Linux/Adeos and Xenomai setup. See the man pages for options:

# man /usr/xenomai/man/man1/xeno-test.1

To cancel the test you should press “Ctrl-C ”. That test uses program dd to execute high load on the system, therefore it is wise to checkout if the program was cancelled together with the test. Type “ps ” to see if dd is still running, if yes type “killall dd ” to kill that process.

Also it is recommended to look on the other programs delivered with Xenomai in the /usr/xenomai/bin/ directory. Man pages can be found in /usr/xenomai/man/ . Further you can run as a root the testsuite tests in /usr/xenomai/testsuite .

14

2 Xenomai – an Installation Guide

2.4 Setting up Bootloader and Testing

# cd /usr/xenomai/testsuite/latency

# ./run

If you will get an error message please read the sub-section 2.4.4.

2.4.4 Error Handling

In what follows this installation guide will give solutions to the problems we observed while installing the Xenomai.

Kernel Panic at Boot-up

It is possible that you will get this error message at boot-up: VFS:Cannot open root device or “Kernel panic- not syncinc: VFS: Unable to mount root fs on unknows-blocks(3,3) ”. In that case, you may need to make the initial RAM- disk. To do so, reboot into your old kernel and go to the directory /boot/.

# cd /boot/

# mkinitrd -o /boot/initrd.img-2.6.17.6-xenomai 2.6.17.6-xenomai

The -o option specifies the file to be generated and the second argument 2.6.17.6-xenomai specifies directory to grab modules from (/lib/modules/ x.x.x-x) Then, if you are using LILO, add initrd.img-2.6.17.6-xenomai into the /etc/lilo.conf file.

image=/boot/vmlinuz-2.6.17.6-xenomai

label=linux-xenomai initrd=/boot/initrd.img-2.6.17.6-xenomai ## new line read-only

Run lilo again and reboot.

If you are using GRUB , add initrd.img-2.6.17.6-xenomai into the /boot/ grub/menu.lst file.

title

Xenomai, kernel 2.6.17.6

root

(hd0,0)

15

2 Xenomai – an Installation Guide

2.4 Setting up Bootloader and Testing

kernel

/boot/vmlinuz-2.6.17.6-xenomai root=/dev/hda1 ro

initrd

/boot/initrd.img-2.6.17.6-xenomai ## new line

savedefault

boot

And reboot.

Testprograms not Working

native skin or CON-

FIG XENO OPT PERVASIVE disabled. ” check the kernel log with the com-

mand “dmesg | grep Xenomai ” and if you get similar output then here:

If you get an error message like “Xenomai:

Xenomai: Local APIC absent or disabled! Disable APIC support or pass "lapic=1" as bootparam. Xenomai: system init failed, code -19. Xenomai: starting POSIX services. Xenomai: POSIX skin init failed, code -19. Xenomai: RTDM skin init failed, code -19.

You will have to pass lapic=1 as a bootparameter. Having LILO you can do it in lilo.conf file as follows:

image=/boot/vmlinuz-2.6.17.6-xenomai

label=linux-xenomai

append="lapic=1"

initrd=/boot/initrd.img-2.6.17.6-xenomai

read-only

Run lilo and reboot 8 . If you are using GRUB modify the kernel line in /boot/ grub/menu.lst:

title

Xenomai, kernel 2.6.17.6

8 you can also reboot from the command line writing simply reboot and pressing enter

16

2 Xenomai – an Installation Guide

2.4 Setting up Bootloader and Testing

root

(hd0,0)

kernel

/boot/vmlinuz-2.6.17.6-xenomai root=/dev/hda1 ro lapic

initrd

/boot/initrd.img-2.6.17.6-xenomai

savedefault

boot

and reboot.

NOTE: The reason why we didn’t tell you to write all these options to the bootloaders in subsections 2.4.1, 2.4.2 is that with some architectures and kernel configurations it may be working also without them. The initrd option- initial RAM-disk contains modules that need to be loaded by the kernel at boot-up. If no modules are needed to be loaded in the boot-up phase, the system should be able to boot-up also without it. See man pages of mkinitrd and lilo.conf for more help. The cause of the need to pass lapic as a bootparameter seems to be a bug in Xenomai. As we found in the mailing-list 9 it should have been fixed, but as of 07.07.2006, we still had to add that parameter in spite of the fact that we have enabled it while configuring the linux kernel. On the web page [Len], that is of an older date, is the explanation: “Xenomai requires to have local APIC enabled for the CPUs by the kernel, which is always the case for SMP systems, but is not always the case by default for single-CPU systems. ” You can find more information concerning LILO on the man pages of lilo or viewing the webpage [lxc, lesson4] or [Sko]. For GRUB manual see [Fou].

Failed to Start Menuconfig

During our installation process we also observed a problem with starting the menuconfig because the ncurses lib’s were not installed. So if you will get error messages saying that some ncurses files are missing, just type:

# apt-get install ncurses-dev

to install them.

If you still will have problems starting make menuconfig , you can edit directly /usr/src/linux-2.6.17.6/.config file or as a last possibility try make config, which is pure line by line text mode and will ask you lot of questions.

9 https://mail.gna.org/public/xenomai-help/2006-04/msg00178.html

17

2 Xenomai – an Installation Guide

2.4 Setting up Bootloader and Testing

Error Loading Shared Libraries

If you will get an error message saying: “error while loading shared libraries:

libnative.so.0: cannot open shared object file: No such file or directory ”, add “/usr/xenomai/lib ” to /etc/ld.so.conf and run /sbin/ldconfig .

If you have some other problems installing Xenomai you should visit the official Xenomai webpages [xenb, xena] and use an internet search engine.

18

3 Xenomai- First Application

After the Xenomai environment was successfully established we can start to write our first application. The best way is to look at an existing noncomplex code and analyze its Xenomai operations. One can find some examples of simple Xenomai codes on the webpage [Unib] and Xenomai actual API on [xenc] or in the Xenomai source directory /usr/src/xenomai-2.2.0/doc/generated/ html/api/main.html.

In this work we used the code from the webpage [Unib] which can be found in the section 7.1 of this paper. As one can see, the main() function prepares the environment for the real-time task execution, starts the task and waits for a signal that cancels that task. In Xenomai versions before 2.2.0 also the timer had to be started explicitly in the main function, now it is done by the operating system itself when a real-time task begins its execution. The real- time task is stand-alone and self-contained. It defines its variables, configures itself and executes the real-time functions. It is important to note that these two examples of codes use function printf which is not real-time and though can disturb the hard real-time feature. Therefore the use of printf is not recommended in the real hard real-time tasks.

In the real-time task of “timer 1.c ” we used in the while-loop the rt task set mode function. At this point we want to note that the tasks cre- ated in Xenomai can run either in the primary or in the secondary execution mode . The former means that the threads can run in the context of the highest priority domain in the pipeline, like kernel-based Xenomai threads. The latter means that the tasks can run in the regular Linux space but still are considered as real-time by Xenomai. More on these modes can be found in [Ger05, section

2.1.].

The basic difference between the two example codes is that they use different timing modes. The first one “timer 1.c ” uses the aperiodic (one-shot) and the second one “ timer 2.c ” the periodic timing mode. The first one is enabled by default when configuring the kernel before kernel compilation and the second one must be set explicitly in the kernel configuration menu following these steps in the kernel configuration menu:

Real-time sub-system -->

19

3 Xenomai- First Application

Timing --> [ ] Use periodic timer hardware

In periodic mode, clock ticks are interpreted as periodic jiffies. In oneshot mode, clock ticks are interpreted as nanoseconds. The, by default, aperiodic mode has much better accuracy for different time scales that cannot be easily expressed as multiples of a single base tick. The periodic mode makes the hard- ware timer tick at constant frequency and rounds the timeouts to a constant time slice. Therefore it is recommended to use aperiodic (oneshot) mode for precise timing.

Before compiling one of the codes with Makefile you have to add <xeno- install>/bin to your PATH variable. That’s easily done this way:

$ PATH=$PATH:/usr/xenomai/bin #use your <xeno-install>/bin path!

$ echo $PATH

/sbin:/usr/sbin:/bin:/usr/bin:/usr/bin/X11:/usr/xenomai/bin

You can set the name of the code you want to compile in the Makefile when you add the name to the TASK variable. Compile it and run in the super-user mode. Both programs will print out periodically (every second) a message on the stdout.

20

4 Linux Driver

Before we begin to write a hard real-time driver for our CPCI-EA221 card under Xenomai we first focus on writing a simple driver under Linux system without Xenomai extension. The reason not to go directly to program real-time driver is that we could not find any good reference, any tutorial for programming our CPCI driver under Xenomai. Luckily this was not the case with Linux and we soon have found an excellent source of the needed information. The book Linux Device Drivers, Third Edition [CRKH05], which is also freely available for download. In the next sections will be described what you need to know to create the CPCI driver and at the end of the chapter also a short description of the functions our driver offers to the user space (API) will be defined. It is also important to note that our driver was build to serve only to one CPCI-EA221 device, to extend its functionality for more devices is one of the more points that should be done in the future development.

The complete code is in the section 7.2.

4.1 Programming the Driver

You can extend the functionality of your Linux kernel by adding modules to it even at run time, so you don’t have to restart the system to get your module working with the kernel. That’s a very nice feature since the development process can progress faster. Our driver is also a module and therefore the first thing we need to know is how to define and initialize kernel modules. To obtain that knowledge we recommend to read [CRKH05, chapter 2, Building and Running Modules]. To get the background knowledge on Linux kernel, Linux drivers, Linux licensing, etc it is also wise to read [CRKH05, chapter 1, An Introduction to Device Drivers].

Afterwards we need to find the device the driver is supposed to work on. The recommended way is to inform the kernel in what hardware device we are interested. We export the structure defining our device to the module loading system so that the system knows which driver to call when it finds the specified device. As it was already mentioned in the chapter 1, CPCI is a high-performance standard based upon peripheral component interconnect

21

4 Linux Driver

4.1 Programming the Driver

(PCI) technology and therefore we can initialize any CPCI device like described in [CRKH05, chapter 12, PCI Drivers]. Also, there is a helpful pci skeleton code pci skel.c provided in the programs package of the book.

The first three needed steps to do in the device initialization function .probe() are to wake up the device with pci enable device() , allocate a memory region with request mem region() and to map the allocated memory to the kernel space virtual memory with ioremap(). Afterwards you can already write to the device registers using functions iowrite8(), iowrite16() or iowrite32(). To study how to allocate and map the memory read [CRKH05, chapter 9, Communicating with Hardware, section: Using I/O Memory] and [CRKH05, chapter 8, Allocating Memory, section: vmalloc and Friends]. In [CRKH05, chapter 12, PCI Drivers] you will find how to find the physical location (memory address) of the device. Do not forget to deallocate, to free always the memory you allocated in case of an error and in the exit() function of the driver.

So far we have initialized the driver module to be able to read from and to write to the registers of the device. What we need now is to define and make available some functions the driver will offer to the kernel and that way also to the (user-space) applications. Our device falls into the category of char devices and such devices are accessed through names in the filesystem. To learn how to create a name in the filesystem for a device read [CRKH05, chapter 3, Char Drivers, section: Major and Minor Numbers]. Basically, by creating of such an entry point, the device will get its major and minor number and also its name. Afterwards you can check the successful allocation viewing the file /proc/devices. You should see the major number and the device name there. After creating the numbers, the driver needs on one side a node in the filesystem that serves as an entry point for the applications that want to use the device and on the other side the device numbers must be connected to the driver’s internal functions that implement the operations on the device.

Creation of the device node with the allocated major number is best done by the loading script. In our CPCI-EA221 driver we use the script cpci ea221 load.sh to insert the module to the kernel and to create the de- vice node. The script cpci ea221 unload.sh is used to remove the device nodes and the driver module from the kernel. Note that the minor number is hard- coded, because the driver is build to work just with one CPCI-EA221 device. In our code, if you prefere to give your own major number to the device you can do it at compile time when you change the appropriate macro in the header file of the driver or you can also specify the number at module loading time with the command ./cpci ea221 load.sh cpci ea221 major=xx

To know how to connect the device numbers to the internal functions of the device which implements the device’s operations read [CRKH05, chapter 3, Char Drivers, sections: Some Important Data Structures and Char Device

22

4 Linux Driver

4.2 API

Registration]. It is needed to define the file operations structure with the functions the driver will implement. A pointer to such structure is called fops . In our module we just use open(), close() and ioctl() . The important method is ioctl() in which we define specific hardware control operations [CRKH05, chapter 6, Advanced Char Driver Operations, section: ioctl]. In this case we just wanted to enable to read from and to write to the registers of the device. Because with these two functions the device can be configured also from the user-space we don’t need to think about all possible configurations of the device and write those configurations as separate ioctl() operations. The functions are described in 4.2 and to be able to configure the device you will need the CPCI-EA221 technical manual [Siea]. In our ioctl() operations we could not use the recommended fast functions put user(), get user() because our parameter structure didn’t fit in one of the specific sizes needed when using these functions, that’s why we had to use copy to user() and copy from user() instead.

The last step is to registry our char device [CRKH05, chapter 3, Char Drivers, section: Char Device Registration]. In the .probe() we call setup cdev() as a last operation, in which we set up the important cdev structure and add that struc- ture to the other cdev structures that are available to the kernel. Immediately afterwards the kernel can handle operations on the device, that’s why it is im- portant to call the function cdev add() first when the driver is completely ready to process the operations on the device.

4.2 API

The applications can use the ioctl function:

int ioctl(int fd, unsigned long cmd, struct ioc_param* arg);

Parameters:

[in] fd : File descriptor as returned by open() 1 . [in] cmd : IOCTL code (see 4.2.1). [in|out] arg : Pointer on an argument structure (see 4.2.1).

Return value:

In case of an error -1 and sets errno to indicate the error.

1 A good source of many detailed function descriptions can be found on the webpage [Gro04].

23

4 Linux Driver

4.2 API

4.2.1 IOCTL Code and Argument Structure:

You should include into your code the file cpci_ea221_driver.h or add the following code into your header file:

#include <linux/ioctl.h> //needed for creating the ioctl cmnd numbers

struct ioc_param{ uint32_t bv; uint8_t offset;

}; typedef struct ioc_param ioc_param_struct;

#define EA221_IOCRESET #define EA221_IOCWRITE #define EA221_IOCREAD

_IO(0xEE, 0) _IOW(0xEE, 1, ioc_param_struct) _IOWR(0xEE, 2, ioc_param_struct)

The bv member of the ioc param struct is a place where to store the 32-bits long vector you want to write into a register in the CPCI-EA221 card. Also the driver will store into the bv variable the value from a register you wanted to read. The offset is for storing the value that must be added to the base address (BA) of the device to obtain the full address of the register. You will find these offset values in the address column of the register tables in [Siea, chapter 4, Overview of the Registers].

The meaning of the IOCTL commands is following:

EA221 IOCRESET stands for software reset. If you want to know how exactly the board reacts to the reset see [Siea, chapter 5, Reset Reaction].

EA221 IOCWRITE stands for writing into the device registers.

EA221 IOCREAD stands for reading from device registers.

4.2.2 Examples:

To reset the board: ioctl(fd, EA221 IOCRESET) . Next, for instance, we want to write the vector 0x0000FFFF in the register with the address BA +0x28 . We simply declare and initialize one variable in the driver.c file as an ioc param struct with the given values and use an ioctl function, i.e.:

ioc_param_struct data = {0x0000FFFF, 0x28); ioctl(fd, EA221_IOCWRITE, &data);

24

4 Linux Driver

4.3 Test Application

When we want to read from an register on the address BA +0x28 :

ioc_param_struct data = {0x00, 0x28); ioctl(fd, EA221_IOCWRITE, &data);

Afterwards will be the value read from the register stored in data.bv variable.

value_from_register = data.bv;

4.3 Test Application

For test reasons we wrote a simple test application that should prove if our ioctl() functions are working properly also from the user-space. Everything important is in the main() task. First we need to open the character device with the open() function. After opening the device file, or, in other words, after opening the entry point to the device, we have the file descriptor on which we can apply the ioctl() functions. In the while loop the process will change the output of the device after every pressing enter button on the keyboard. So one time there will be HIGH on the output pins and another time will be LOW, the state of the output pins will be signalized with the LED #1, if outputs will be HIGH the LED #1 will be also HIGH (switched on), if the outputs will be LOW, the LED #1 will be off.

25

5 Xenomai – RTDM Driver

Now we know some basic functions of Xenomai and know also how to write a simple driver module under Linux kernel. This chapter will explain how to use the Xenomai features in the driver module, so that in the end we will have a driver module which runs in hard real-time. It will be shown that some things that are important in Linux drivers are not used in Xenomai drivers. At this point we would like to note, that drivers under Xenomai are using the Real- Time Driver Model (RTDM) skin that can be loaded together with the main interface, so make sure you enabled the installation of RTDM in the kernel con- figuration menu. In this chapter we will use instead of the name Xenomai driver the name “RTDM driver ” as it represents the used API better. As a starting point we recommend to read an article on RTDM by Jan Kiszka [Kis05] from which we cite the goal of the RTDM “The Real-Time Driver Model (RTDM) is an approach to unify the interfaces for developing device drivers and associated applications under real-time Linux.”. Because there is no such book for RTDM as for Linux drivers [CRKH05], we helped us with reading the source code of the real-time serial port mod- ule xeno 16550A.ko 1 , further with reading the code on the Captain’s web- page [Unib, mostly the section: Hard Real Time Driver Example Tutorial with MMAP using the RTDM (Real Time Driver Model)] and studying the Xenomai and RTDM API on [xenc]. With these three sources of information and the background we gained by programming the Linux driver in the previous chap- ter we could achieve our next goal, to write our own CPCI-EA driver module with Xenomai(RTDM) features. As for the Linux driver, in the chapter 4, as well for this driver holds that it was build to serve only to one CPCI-EA221 device, to extend its functionality for more devices is one of the more points that should be done in the future development. For the complete source code of the driver see the section 7.3.

5.1 Programming the RTDM Driver

The definition and initialization of the driver module is made the same way as in the Linux driver. Alike is it with defining the device, we are interested in, to

1 the source code is in the file /usr/src/xenomai-2.2.0/ksrc/drivers/16550A/16550A.c

26

5 Xenomai – RTDM Driver

5.1 Programming the RTDM Driver

the module loading system. You can even use the same PCI skeleton code as introduced in the chapter 4 and you should also read the first two paragraphs of the section “Programming the driver ” from the same chapter.

Next we need to define the RTDM device description that will be passed lately to rtdm dev register() function. The description is specified within the structure rtdm device . An overview of central parameters that have to be spec- ified can be found in [Kis05, section 2.2, Device Registration and Invocation] otherwise see the API [xenc]. In our device module we left out or left blank the device name and proc name because it will be defined in the .probe() func- tion. This approach will be usefull later when the module will be adapted to support more devices. Another important structure used in our code is the xen cpciea221 context structure. It is used as an internal source of information on our device, we simply store there what we think will be needed in further work with the device.

When the RTDM device structure is defined we can continue with working on the .probe() function. After enabling the pci device with pci enable device() and obtaining the physical location and size of the physical memory of the CPCI- EA221 card, the memory for the RTDM structure will be allocated and sub- sequently the structure will be copied into that new memory space. Then the name of the RTDM device is specified, given to the RTDM structure and used for allocating the memory region for CPCI card with request mem region(). The memory region is afterwards mapped to the virtual kernel space with ioremap(). The name of the RTDM device given to the device structure is important because it is the only one access point to our RTDM device, thus it should be different for every device using this driver. The approach used in the Linux driver, that each driver has a node in the file system that serves as an access point to the device, is not followed in RTDM drivers. For this reason we don’t need to allocate major and minor numbers of the device nor to write an extra loading script for the driver’s module. From that follows also that we will not find the RTDM device name in the /dev/ directory, but you can find it listed in the /proc/iomem file. In the section 5.3 will be shown how to access the RTDM device. After the memory was successfully mapped to the kernel space, the last thing needed to be done is to register the RTDM structure with rtdm dev register() . Immediately afterwards the kernel can call the functions defined in the RTDM structure, so make sure that the function is called first when everything is prepared for the proper device operation.

The functions rt open() and rt close() are not doing anything necessary at this state of the development of the driver. Their bodies have now rather a demonstrative character. To every open device instance is a device context structure associated. In the rt open() is its use depicted. One can see how to access data from the rtdm device struct or from the context structure of the

27

5 Xenomai – RTDM Driver

5.2 API

device we defined ourselves as a place where to store the data that could be needed by other functions handling on the device. In further development this functions should be used to allocate or deallocate additional memory for the driver, or to start the interrupt handlers and so on. The bodies of the ioctl() function are quite the same as in the Linux driver module, just most of the used operations were replaced by the RTDM operations. Otherwise all what was said on ioctl() in the chapter 4 holds also in this module. See 5.2 for API of the RTDM ioctl().

5.2 API

The applications can use the rt dev ioctl function:

int rt_dev_ioctl(int fd, unsigned long cmd, struct ioc_param* arg);

Parameters:

[in] fd : File descriptor as returned by rt dev open(). [in] cmd : IOCTL code (see 4.2.1). [in|out] arg : Pointer on an argument structure (see 4.2.1).

Return value:

Positive value on success, otherwise negative error code.

5.2.1 Examples:

The same as in the subsection 4.2.2 with an small exception, ioctl() is replaced by rt dev ioctl() function.

5.3 Test Application

To test our driver module with the Xenomai-RTDM features we build up a simple application. As you can see from the source code, the structure of the application is similar to the applications in the chapter 3. There is the main() task that initializes everything needed, like opening the character de- vice, starting the real-time task and waiting for cancel of the real-time task

28

5 Xenomai – RTDM Driver

5.3 Test Application

and also there is the real-time task which embodies the most important part of the application. The real-time task supports different modes, which can be set up in the header file with uncommenting or commenting the two macros #define PRINTF and #define SIMPLE . With PRINTF enabled a message will be printed on stdout, but because printf function brings high latencies and corrupts the precise timing it is not recommended to use it. If SIMPLE is enabled, just a simple real-time task will be executed in which no care on input register is taken, all output pins will change their common state periodically. Otherwise, if SIMPLE is not enabled, the little bit more complex task will be executed that takes care on the input register. That means that the state of the output register will change periodically considering the the state of the input. This application proves that it is possible to write to and to read from the registers of the device under timing constraints and from the user-space.

One more note to opening the device in the Xenomai environment. The device is opened with the rt dev open(dev name, flags) function in which the dev name stands for the name we defined and used in the .probe() function of the RTDM driver when calling request mem region(). As already mentioned before, this is the access point to the driver and subsequently to the device. This seems to be the biggest difference to the approach used in common Linux drivers.

29

6 Conclusion

This project showed that solutions for real-time execution of tasks under Linux that can run together with ’regular’ Linux kernel already exists. We showed how to establish such real-time environment, how to write the first tasks using

it and concerned on the development of a device driver. The first steps needed

for designing a driver under ’regular’ Linux and under Xenomai were explained. When comparing these device drivers one can see that they have some main differences, like that the Xenomai device is not accessed per a node in the filesystem, and they have also many similarities, and in some cases what one needs to do is just to rename the function, like it was the case with access ok()

in ’regular’ Linux and rtdm read user ok() in Xenomai.

In the folllowing sections we will discuss briefly what problems we found at programming of our driver and what could be the next steps or possible extensions of our project.

6.1 Problems

We observed only two problems for that we didn’t have time to solve. First is that while loading the device driver module into the kernel space, the im- portant function .probe() is executed two times, except of being just one time. We observed the same also with unloading the module from the kernel. The problem is with allocating and mapping the memory in this function that is done in that case also two times. The first allocation and mapping is the right one and we get wrong values in the second loop. We solved this problem with assuring that the mapping and allocation is executed only one time by giving

a if condition at the beginning of the .probe() function. The same for unload-

ing function of the module, because otherwise we would deallocate the same memory two times, what is not desired. We are sure this is not the right way to go, but it seems to be the easiest one at the time. This problem should be solved another way.

The second problem we have is with the test application xen_led_timer.c.

The catch signal() function should reset the board when the exit signal occurs. The board should put all of its outputs low and take no care on inputs, which

is not the case. We didn’t come on the solution till deadline.

30

6 Conclusion

6.2 Outlook

6.2 Outlook

There are quite many things still to do. What we did is only that one can write a simple user-space application that can configure the device, per device registers, how it wants and then use the card’s services. The most important work what we did not come to is setting up and using the interrupts. We think that the next step in extending the functionality of the device driver under Xenomai should be the interrupt support. Therefore, it is necessary to establish hard real-time interrupt handlers and write some applications using them. Other extensions could be for example the support for multiple CPCI devices, some more sophisticated ioctl functions, establishing communication with external devices using the CPCI-EA221 card, etc. It would be also important to make tests on hard real-time, to measure the tasks execution and latencies to get to know and approve hard-real time features of the Xenomai system.

31

7 Listings

7 Listings

7.1 Xenomai – First Application

7.1 Xenomai – First Application

7.1.1 timer 1.c

/*======================================================================*/

*/

/* Traineeship-Project:

Implementation of Xenomai

/* Title:

timer task #1, based on code on website: www.captain.at */

/* Purpose:

- to get first experience with the Xenomai environment */

/*

*/

/* File:

timer_1.c

*/

/* Version:

0.1

*/

/* Date:

08/2006

*/

/*

*/

/* Description: - hard real-time user-space task that prints out

*/

/*

periodically a simple text on stdout

*/

/* Software:

Linux Debian kernel 2.6.17.6 with Xenomai-2.2.0 extension*/

/* Hardware:

Sicomp SMP16 (Siemens industrial computer)

*/

/*

*/

/* Authors:

www.captain.at, Ondrej Cevan (TU Vienna)

*/

/* Licence:

GPL

*/

/* Note:

- set aperiodic timing mode (in kernel config menu) to get*/

/*

precise timing

*/

/*

- No warranty is attached, we cannot take responsibility */

/*

for errors or fitness for use.

*/

/*======================================================================*/

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <sys/time.h> #include <sys/io.h> #include <sys/mman.h>

#include <native/task.h> #include <native/queue.h> #include <native/intr.h>

#define STACK_SIZE 0 // a pre-defined size will be substituted #define STD_PRIO 99 // the highest one

33

7 Listings

7.1 Xenomai – First Application

RT_TASK test_task_ptr; const char* cmnd = "<not yet set>"; int int_count = 0; int end = 0;

// RTIME task_period_ns =

--s-ms-us-ns

1000000000llu;

/* cookie --> A user-defined opaque cookie the real-time kernel will pass to the emerging task as the sole argument of its entry point.*/ void testtask(void *cookie){ int count = 0; int ret; unsigned long overrun;

/* Make a task periodic by programing its first release point and its period in the processor time line.

*/ ret = rt_task_set_periodic(NULL, TM_NOW,

rt_timer_ns2ticks(task_period_ns));

if (ret) { printf("%s: error while set periodic, code %d\n",cmnd, ret); return;

}

while(!end){ //switch to primary mode ret = rt_task_set_mode(0, T_PRIMARY, NULL); if (ret) { printf("%s: error while rt_task_set_mode, code %d\n",cmnd, ret); return;

}

// Wait for the next periodic release point // and write the number of overruns to &overrun. ret = rt_task_wait_period(&overrun); if (ret) { printf("%s: error while rt_task_wait_period, code %d\n",cmnd, ret); return;

}

count++; printf("%s: message from testtask: count=%d\n", cmnd, count); fflush(NULL);

34

7 Listings

7.1 Xenomai – First Application

}

}

// signal-handler, to ensure clean exit on Ctrl-C void clean_exit(int dummy) { printf("%s: cleanup\n",cmnd); end = 1; rt_task_delete(&test_task_ptr); printf("%s: end\n", cmnd);

}

int main(int argc, char *argv[]) { int err; cmnd = argv[0];

printf("%s started\n", cmnd); printf("press ctrl-c to exit\n");

// install signal handler signal(SIGTERM, clean_exit); signal(SIGINT, clean_exit);

//disable paging for this program’s memory mlockall(MCL_CURRENT | MCL_FUTURE);

//create and start a task err = rt_task_spawn(&test_task_ptr, "Timer", STACK_SIZE, STD_PRIO, 0, &testtask, NULL);

if (err) { printf("%s: error rt_task_spawn\n", cmnd); return 0;

}

// wait for a signal & return of signal handler pause(); fflush(NULL); return 0;

}

35

7 Listings

7.1 Xenomai – First Application

7.1.2 timer 2.c

/*======================================================================*/

*/

/* Traineeship-Project:

Implementation of Xenomai

/* Title:

timer task #2, based on code on website: www.captain.at */

/* Purpose:

- to get first experience with the Xenomai environment */

/*

*/

/* File:

timer_2.c

*/

/* Version:

0.1

*/

/* Date:

08/2006

*/

/*

*/

/* Description: - hard real-time user-space task that prints out

*/

/*

periodically a simple text on stdout

*/

/* Software:

Linux Debian kernel 2.6.17.6 with Xenomai-2.2.0 extension*/

/* Hardware:

Sicomp SMP16 (Siemens industrial computer)

*/

/*

*/

/* Authors:

www.captain.at, Ondrej Cevan (TU Vienna)

*/

/* Licence:

GPL

*/

/* Note:

- periodic timer support must be enabled

*/

/*

(in kernel config menu)

*/

/*

- No warranty is attached, we cannot take responsibility */

/*

for errors or fitness for use.

*/

/*======================================================================*/

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <sys/time.h> #include <sys/io.h> #include <sys/mman.h> #include <native/task.h> #include <native/queue.h> #include <native/intr.h>

#define STACK_SIZE 0 // a pre-defined size will be substituted #define STD_PRIO 99 // the highest priority

RT_TASK test_task_ptr; int int_count = 0; int end = 0;

36

7 Listings

7.1 Xenomai – First Application

void testtask(void *cookie){ int count = 0; while(!end){ //delay the execution of the calling task //if we have periodic timer support

rt_task_sleep(1000000000);

//if we don’t have periodic timer support:

//rt_task_sleep(rt_timer_ns2ticks(1000000000));

count++; printf("message from testtask: count=%d\n", count); fflush(NULL);

}

}

// signal-handler, to ensure clean exit on Ctrl-C void clean_exit(int dummy) { printf("cleanup\n"); end = 1; rt_task_delete(&test_task_ptr); printf("end\n");

}

int main(int argc, char *argv[]) { int err; printf("start\n"); printf("press ctrl-c to exit\n");

// install signal handler signal(SIGTERM, clean_exit); signal(SIGINT, clean_exit);

//disable paging for this program’s memory mlockall(MCL_CURRENT | MCL_FUTURE);

//create and start an RT task err = rt_task_spawn(&test_task_ptr, "Timer", STACK_SIZE, STD_PRIO, 0, &testtask, NULL);

if (err) { printf("error rt_task_spawn\n"); return 0;

}

37

7 Listings

7.1 Xenomai – First Application

// wait for signal & return of signal handler pause(); fflush(NULL); return 0;

}

38

7 Listings

7.1 Xenomai – First Application

7.1.3 Makefile

##########################################################################

##

Traineeship-Project:

Implementation of Xenomai

##

##

Title:

Makefile for timer task #1 and #2

##

##

based on website: www.captain.at

##

##

Purpose:

- to build the timer applications

##

##

##

##

File:

Makefile

##

##

Version:

0.1

##

##

Date:

08/2006

##

##

##

##

Software: Linux Debian kernel 2.6.17.6 with Xenomai-2.2.0 extension ##

##

Hardware: Sicomp SMP16 (Siemens industrial computer)

##

##

##

##