SEARCH
TOOLBOX
LANGUAGES
modified on 3 August 2011 at 14:51 ••• 45,292 views

Electrum Xenomai Notes

From Manuals

(Difference between revisions)
Jump to: navigation, search
(Real-Time (Xenomai) Debian Linux from Scratch for Electrum100)
(Real-Time (Xenomai) Debian Linux from Scratch for Electrum100)
Line 108: Line 108:
'''Avoid filesystem corruption'''
'''Avoid filesystem corruption'''
-
If you mount the root filesystem in read-write mode on a MicroSD card, it can happen that, over time, due to repeated  power cycles and unclean reboots, some sectors on the card will become unusable. In order to overcome this, mount the root filesystem as read only. Mount /var (if you need kernel logs) and /home on different partitions. In U-Boot, modify bootargs accordingly.
+
If you mount the root filesystem in read-write mode on a MicroSD card, it can happen that, over time, due to repeated  power cycles and unclean reboots, some sectors on the card will become unusable. In order to overcome this, mount the root filesystem as read only. Mount /var (if you need kernel logs) and /home on different partitions. In U-Boot, modify ''bootargs'' accordingly.
  U-Boot> setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait ro'
  U-Boot> setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait ro'

Revision as of 18:17, 20 July 2011

Real-Time (Xenomai) Debian Linux from Scratch for Electrum100

Contributed by: Razvan-Ionut Stoian - razvan@stoian.us


This tutorial is split into four sections: compilation of a kernel for Electrum100, installation of Debian Squeeze root filesystem and Xenomai user libraries onto the SBC, and a short Xenomai development example (user-land).

1. Preparing a kernel for Electrum100

The newest kernel supported by Xenomai for ARM systems was 2.6.35.9, so you need to apply the provided patch to the kernel sources downloaded from http://www.kernel.org.

First, you need to have a MicroSD card partitioned like this:

  • first partition: ext2 (max 10 MB) - for uImage
  • second partition: ext4 (at least 100 MB) - for the root filesystem
  • third partition: swap (128 MB) - for swap space (optional)

Patch the kernel tree, so that your machine can be supported.

$ cp *.patch linux-2.6.35.9
$ cd linux-2.6.35.9
$ patch -p1 < *.patch

Next, rename the provided configuration file as .config, configure (or leave it as it is) and compile your kernel and modules with the following commands:

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- 

Transfer uImage on the boot partition of your MicroSD and install the modules on the second partition.

$ sudo cp arch/arm/boot/uImage /media/disk1
$ sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- INSTALL_MOD_PATH=/media/disk2/ modules_install

2. Rolling a Debian Squeeze filesystem

On your i686 or any Pentium-based computer with Ubuntu on it, do the following:

$ mkdir squeeze_rootfs
$ cd squeeze_rootfs
$ sudo debootstrap --include=openssh-client,openssh-server --exclude=udev --arch=armel --foreign squeeze \
      ./ http://ftp.us.debian.org/debian
$ sudo tar cvjf ../squeeze_rootfs.tar.bz2 *

Untar the rootfs onto the MicroSD's second partition and boot your SBC to finish the second stage of your debootstrap installation.

$ sudo tar xvjf squeeze_rootfs.tar.bz2 -C /media/disk2/ ; sync

Issue the following commands in the U-Boot interface.

U-Boot> setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait init=/bin/sh'
U-Boot> setenv bootcmd 'mmcinfo; ext2load mmc 0:1 0x20100000 uImage; bootm 0x20100000'
U-Boot> boot

After you will get terminal access, the following sequence of commands will complete the installation of the root filesystem.

$ mount /proc /proc -t proc
$ export PATH=/usr/loca/sbin:/usr/local/bin/:/usr/bin:/usr/sbin:/sbin:/bin
$ /debootstrap/debootstrap –second-stage
$ echo "T2:23:respawn:/sbin/getty -L ttyS0 115200 vt100" >> /etc/inittab 
$ echo ttyS0 > /etc/securetty
$ passwd root

Also, in order to make the boot process faster, one should get rid of all services and utilities that are not needed at boot time (after all, this is a light weight embedded system). Just start them later, on a need to use basis (networking, cron jobs, etc.).

$ mkdir ~root/backup_services
$ mv /etc/sysctl* ~root/backup_services
$ cd /etc/init.d
$ mv cron hwclock* ifupdown* networking rsyslog stop-bootlogd* bootmisc* mountall-* ~root/backup_services
$ mv /sbin/startpar ~root/backup_services
$ mv /sbin/sysctl ~root/backup_services

Now it is a good time to create entries for serial ports, MMC and onboard flash memory partitions in /dev/.

$ mknod -m 660 /dev/tty1 c 4 1
$ mknod -m 660 /dev/ttyS0 c 4 64
$ mknod -m 660 /dev/mmcblk0 b 179 0
$ mknod -m 660 /dev/mmcblk0p1 b 179 1
$ mknod -m 660 /dev/mtdblock0 b 31 0
$ mknod -m 660 /dev/mtdblock0p1 b 31 1

Finally, in order to get a clean login terminal in runlevel 2, the following lines must be commented in /etc/inittab.

1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4

Final touches

Set-up your network interface in /etc/network/interfaces and start your network interfaces

$ /backup_services/networking restart

Update Debian repositories in /etc/apt/sources.list

$ echo “deb http://security.debian.org/ squeeze/updates main contrib non-free” >> /etc/apt/sources.list
$ echo “deb http://ftp.debian.org/debian/ squeeze main contrib non-free” >> /etc/apt/sources.list
$ apt-get update
$ apt-upgrade

Create a user account with (temporary) root privileges (sudo) and lock the root user

$ apt-get install sudo
$ adduser user
$ echo "user ALL=(ALL) ALL" >> /etc/sudoers
$ sudo passwd -l root

Avoid filesystem corruption

If you mount the root filesystem in read-write mode on a MicroSD card, it can happen that, over time, due to repeated power cycles and unclean reboots, some sectors on the card will become unusable. In order to overcome this, mount the root filesystem as read only. Mount /var (if you need kernel logs) and /home on different partitions. In U-Boot, modify bootargs accordingly.

U-Boot> setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait ro'

More on filesystem corruption on embedded systems here.

The command line passed to the kernel by U-Boot must contain the lpj parameter. Without it, the BogoMIPS calculation would add to the overall boot time.

U-Boot> setenv bootcmd 'mmcinfo; ext2load mmc 0:1 0x20100000 uImage; bootm 0x20100000'
U-Boot> setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait lpj=98304 noswap'
U-Boot> saveenv
U-Boot> boot 

If you followed the previous instructions closely, you will get a login terminal in 6 seconds including kernel decompression. Enjoy your fast booting Linux SBC!

3. Xenomai 2.5.6 on Electrum100

Disclaimer: This section was more or less copy-pasted from http://www.stoian.us/misc. I put it here for the sake of consistency.

On a i686 machine, patch the kernel with Adeos I-pipe and compile it. If you are unsure of a workable configuration file, you can use the one provided.

$ tar -xvjf xenomai-2.5.6.tar.bz2 
$ xenomai-2.5.6/scripts/prepare-kernel.sh –-linux=linux-2.6.35.9 --arch=arm 
$ cd linux-2.6.35.9
$ make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm menuconfig
$ make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm uImage
$ make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm

Xenomai-2.5.6 must be compiled from sources on the same machine.

$ mkdir /home/user/xeno_installation
$ cd xenomai-2.5.6
$ ./configure -–host=arm-linux-gnueabi --enable-arm-mach=at91sam9 --enable-arm-eabi
$ sudo make DESTDIR=/home/user/xeno_installation ARCH=arm install

Warning: I could not compile Xenomai using GCC-4.4 and GCC-4.5 on Ubuntu 10.10. If you want to use newer compilers to get the job done, you are on your own. If you can make it work, please shoot me an email.

If everything goes with no issues, all the libraries, benchmarks and character devices will be installed in /home/user/xeno_installation.

$ ls /home/user/xeno_installation/
dev usr 
$ ls /home/user/xeno_installation/usr/xenomai/
bin include lib sbin share 

Transfer usr/xenomai and dev/ to the MicroSD containing the root filesystem created in the previous steps, and you are almost done. In order to have a good approximation of your system's latency, you should launch intensive computational tasks. The following script ran alongside /usr/xenomai/bin/latency for more than 3 hours on the SBC.

#! /bin/bash
# running the script: chmod +x script; ./script > /dev/null
cd /home/user/xenomai-2.5.6
./configure --enable-arm-mach=at91sam9 --enable-arm-eabi
while[1]; do
  make; make clean
done

Worst case latency was 60.2 µs in userspace. If one gets negative latencies in kernel space (when running the benchmarks), /proc/xenomai/latency should be tweaked. The best value to start with is 0.

$ sudo chmod 766 /proc/xenomai/latency
$ sudo echo 0 > /proc/xenomai/latency

4. Simple Xenomai Code

A simple application featuring a real-time thread is shown. Once the thread is started, a GPIO on the Electrum100 (PIOB, bit 0) is toggled inside a “while” loop. This application's Makefile has an scp line included, so that on every successful compilation, a passwordless SSH connection is initiated and the binaries are transferred directly to the SBC.

[...]
LDFLAGS+=-Xlinker -rpath -Xlinker $(shell $(XENOCONFIG) --libdir)

LDFLAGS+= -lrtdk

all:: $(APPLICATIONS)
      scp $(APPLICATIONS) user@SBC_ip:

clean::
	$(RM) $(APPLICATIONS) *.o
[...]

To make this setup work, do the following: on the build machine, do in terminal

$ cp -rf xeno_installation/usr/xenomai /usr

the build and target machines should be on the same network the network interface on the target should be active

$ sudo /backup_services/networking restart

the SSH server must be started on the target machine

$ sudo /backup_services/ssh start

Unless you believe the G-Men are interested in your DIY home defense Xenomai-powered AegisTM system, generate an SSH key pair of short bit length on the build machine.

$ ssh-keygen -t dsa -b 1024
$ ssh-copy-id user@sbc_ip

If your source file is gpio.c, simply type make in terminal and you can find gpio ready for execution on your SBC.

[...]
#include <stdio,mman, ...>
[...]

#include <native/task.h>
#include <native/timer.h>

#include "definitions.h" // base addresses, offsets

RT_TASK spin_task;
int fd,i,j;
unsigned char *piob_base, *aic_base, *pmc_base; 

void open_controller(){

    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) 
   {
       printf("Couldn't open /dev/mem. error %s\n", strerror(errno));
       exit(1);
   }

   printf("/dev/mem opened.\n"); 

  aic_base=mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, AT91C_BASE_AIC);
  piob_base = aic_base + AT91C_BASE_PIOB - AT91C_BASE_AIC;
  pmc_base = aic_base + AT91C_BASE_PMC - AT91C_BASE_AIC;

  if( (aic_base == MAP_FAILED)) {
    printf("Couldn't get Map-Address.(errno: %d).\n", errno);		
    exit(1);
  }

// peripheral settings
*((unsigned int *) (piob_base + PIO_IDR))   = 1<<0;
*((unsigned int *) (piob_base + PIO_PER))   = 1<<0;
*((unsigned int *) (piob_base + PIO_CODR))  = 1<<0;
*((unsigned int *) (piob_base + PIO_PPUDR)) = 1<<0;
*((unsigned int *) (piob_base + PIO_OER))   = 1<<0;
*((unsigned int *) (piob_base + PIO_MDDR))  = 1<<0;
}

void spin(void){

rt_task_set_periodic(&spin_task,TM_NOW, 100000);

while(i<100000){

    *((unsigned int *) (piob_base + PIO_SODR)) = 1<<0;
    rt_task_wait_period(NULL);    
    *((unsigned int *) (piob_base + PIO_CODR)) = 1<<0;
    //rt_timer_spin(0);
    for(j=0;j<50;j++)
    asm("mov r0,r0"); // no-op for small delays
    i++;
 }
}

void catch_signal() {}

int main(void)
{  
    signal(SIGTERM, catch_signal);
    signal(SIGINT, catch_signal);
   /* Avoids memory swapping for this program */
    mlockall(MCL_CURRENT|MCL_FUTURE);	
    open_controller();
    rt_task_create(&spin_task, "spin", 0, 99, 0);
    rt_task_start(&spin_task, &spin, NULL);
    getchar();
    rt_task_delete(&spin_task);
    close(fd);
    return 0;
}

Supporting files:

[1] Electrum100 (200) patch for vanilla 2.6.35.9 and kernel configuration file
[2] sample code - real-time GPIO toggling (Xenomai)

Sources:

http://wiki.debian.org/Debootstrap
http://code.google.com/p/mini2440/wiki/MiniBringup
http://www.debianadmin.com/enable-and-disable-ubuntu-root-password.html
http://www.armadeus.com/wiki/index.php?title=Xenomai:Blinking_LEDs
http://www.embeddedarm.com
http://gna.org/mail/?group=xenomai