RT System
Real-time System ---++ Xenomai ---+++ Install Debian network install using debian-503-i386-businesscard.iso
I used linux.csua.berkrley.edu as a mirror for Debian archive. The install is pretty straightforward. I used guided partitioning using entire disc.
After install and reboot edit /etc/network/interfaces to look like this:
- This file describes the network interfaces available on your system
- and how to activate them. For more information, see interfaces(5).
- The loopback network interface
auto lo iface lo inet loopback
- The primary network interface
allow-hotplug eth0 iface eth0 inet static
address 192.168.3.136 netmask 255.255.255.0 network 192.168.3.0 broadcast 192.168.3.255 gateway 192.168.3.1 # dns-* options are implemented by the resolvconf package, if installed dns-nameservers 192.153.157.142 dns-search chara-array.org
if you want to work remotely install ssh server aptitude install openssh-server
aptitude search package will search a package in the debian archive.
Once installation finished create a file called preference in /etc/apt
Package: * Pin: release a=stable Pin-Priority: 700
Package: * Pin: release a=testing Pin-Priority: 650
Package: * Pin: release a=unstable Pin-Priority: 600
Then modify /etc/apt/sources.list to look like this:
- deb cdrom:[Debian GNU/Linux 5.0.2 _Lenny_ - Official i386 NETINST Binary-1 20090629-11:06]/ lenny main
- deb cdrom:[Debian GNU/Linux 5.0.2 _Lenny_ - Official i386 NETINST Binary-1 20090629-11:06]/ lenny main
- stable
deb http://linux.csua.berkeley.edu/debian/ lenny main non-free contrib deb-src http://linux.csua.berkeley.edu/debian/ lenny main non-free contrib deb http://security.debian.org/ lenny/updates main non-free contrib deb-src http://security.debian.org/ lenny/updates main non-free contrib deb http://volatile.debian.org/debian-volatile lenny/volatile main non-free contrib deb-src http://volatile.debian.org/debian-volatile lenny/volatile main non-free contrib
- testing
deb http://ftp.us.debian.org/debian testing main non-free contrib deb-src http://ftp.us.debian.org/debian testing main non-free contrib
- unstable
deb http://ftp.us.debian.org/debian unstable main non-free contrib deb-src http://ftp.us.debian.org/debian unstable main non-free contrib
aptitude update aptitude safe-upgrade aptitude full-upgrade
if you get this: E: Dynamic MMap ran out of room
Add the following line to /etc/apt/apt.conf
APT::Cache-Limit "8388608";
You will be on debian STABLE. you can install packages from testing or unstable by typing:
aptitude install <package> /unstable (or /testing)
Install screen (useful when compiling remotely if ssh connection dies)
aptitude install screen
run screen
Now install the latest xenomai
cd /usr/src
Install the packages necessary to compile the kernel. aptitude install kernel-package ncurses-dev fakeroot bzip2
Install package to retrieve latest stable xenomai from the git repository aptitude install git-buildpackage aptitude install pbuilder
Using new howto on: http://www.xenomai.org/index.php/Building_Debian_packages
aptitude install devscripts debhelper dh-kpatches findutils
rom a Git repository
To build from a git Repository install these additional packages and clone the Git repository:
- apt-get install git-core git-buildpackage
- cd /usr/src
$ git clone git://xenomai.org/xenomai-2.5.git
Change to the Xenomai Git working tree and update the repository:
$ cd xenomai-2.5 && git fetch origin
Create and checkout a new branch based on a git treeish object. In this example, we create a branch v2.5.3-deb based on git tag v2.5.3:
xenomai-2.5$ git checkout -b v2.5.3-deb v2.5.3
Create a new debian changelog entry:
xenomai-2.5$ DEBEMAIL="your@email" DEBFULLNAME="Your Name" debchange -v 2.5.3-0.1 Release 2.5.3
Commit the changelog to the v2.5.3-deb branch:
xenomai-2.5$ git commit -a --author="Your Name <your@email>" -m 2.5.3-0.1
Build the packages in the parent directory:
xenomai-2.5$ git-buildpackage \
--git-upstream-branch=v2.5.3 \ --git-debian-branch=v2.5.3-deb \ --git-export-dir=.. \ -uc -us
Switch back to the master branch and delete the branch v2.5.3-deb:
xenomai-2.5$ git checkout master && git branch -D v2.5.3-deb
use dpkg to install the packages:
- dpkg -i *.deb
dpkg-query -W -f'${Description}\n' linux-patch-xenomai | grep Patch-file
Apply the Xenomai adeos-ipipe patch and compile kernel:
tar -jxf linux-2.6.32.11.tar.bz2 && cd linux-2.6.32.11
remember to copy to this directory the .config file used in the previous kernel cp /boot/config-2.6.32.11-xenomai-2.5.3 .config (note: this file could be called differently).
since we copied the old .config file we can use --config oldconfig if you want to edit the kernel configuration use --config menuconfig (NEVER edit .config manually).
Compile and patch the kernel:
CONCURRENCY_LEVEL=2 fakeroot make-kpkg --initrd --added-patches xenomai --append-to-version -xenomai-2.5.3 --revision 1.0 --config oldconfig binary-arch
If you need to recompile the kernel additional times, avoid reapplying the xenomai patch:
CONCURRENCY_LEVEL=2 fakeroot make-kpkg --initrd --revision=ipipe.2.0.05 binary-arch
install the kernel
dpkg -i linux-image-2.6.31.1_ipipe.2.0.05_i386.deb
modify /boot/grub/menu.lst root= should not use the device (/dev/sda1) since that may change. Use the UUID (obtained typing blkid) or the label of the disc
Also append "noht mem=2048M memmap=1024M" to the real time kernel using the asgtropci board.
install kernel and headers dpkg -i linux-image*.deb
emacs /boot/grub/menu.lst
title Debian GNU/Linux, kernel 2.6.32.11-xenomai-2.5.3 root (hd0,0) kernel /boot/vmlinuz-2.6.32.11-xenomai-2.5.3 root=LABEL=ROOTFS_TEST ro noht mem=2048M memmap=1024M pci=routeirq initrd /boot/initrd.img-2.6.32.11-xenomai-2.5.3
title Debian GNU/Linux, kernel 2.6.32.11-xenomai-2.5.3 (single-user mode) root (hd0,0) kernel /boot/vmlinuz-2.6.32.11-xenomai-2.5.3 root=LABEL=ROOTFS_TEST ro single initrd /boot/initrd.img-2.6.32.11-xenomai-2.5.3
title Debian GNU/Linux, kernel 2.6.26-2-686 root (hd0,0) kernel /boot/vmlinuz-2.6.26-2-686 root=LABEL=ROOTFS_TEST ro quiet initrd /boot/initrd.img-2.6.26-2-686
Also modify /etc/fstab to use UUID or LABEL instead of devices. Label names have to be unique:
- /etc/fstab: static file system information.
- <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0 LABEL=ROOTFS-XENO / ext3 errors=remount-ro 0 1 LABEL=SWAP-XENO none swap sw 0 0 /dev/scd0 /media/cdrom0 udf,iso9660 user,noauto 0 0 /dev/fd0 /media/floppy0 auto rw,user,noauto 0 0
Modify /etc/modules to look like this:
- /etc/modules: kernel modules to load at boot time.
- This file contains the names of kernel modules that should be loaded
- at boot time, one per line. Lines beginning with "#" are ignored.
- Parameters can be specified after the module name.
loop xeno_native xeno_rtdm
In this way the xenomai modules are loaded at boot time.
and reboot
Type lsmod to see the kernel modules loaded. It should show:
Module Size Used by xeno_native 105088 0 analogy_ni_pcimio 15644 0 analogy_ni_mio 44860 1 analogy_ni_pcimio analogy_ni_tio 24956 1 analogy_ni_mio analogy_8255 3900 1 analogy_ni_mio analogy_ni_mite 10140 3 analogy_ni_pcimio,analogy_ni_mio,analogy_ni_tio xeno_analogy 40220 5 analogy_ni_pcimio,analogy_ni_mio,analogy_ni_tio,analogy_8255,analogy_ni_mite xeno_rtdm 28436 2 analogy_ni_mio,xeno_analogy ext3 109636 1 jbd 43920 1 ext3 mbcache 6272 1 ext3 ide_pci_generic 3712 0 ide_core 74204 1 ide_pci_generic ata_piix 15748 2 sata_mv 26448 0 e1000 114208 0 libata 142156 2 ata_piix,sata_mv unix 22992 10
all the analogy drives are the real-time comedi drivers (not present in mirkwood).
Obtain the astropci driver from the Bob Leach site. For kernel 2.6.30 is astropciFC11.tar.bz2.
tar xjf astropciFC11.tar.bz2 cd /usr/src/astropci/FC11/ make default make install
reboot
Now with lsmod you should see an extra module: astropci 10944 0
I have not figured out how to create the node /dev/astropci automatically.
execute this command to create the node:
astropci_make_node
you can test the RTOS with xeno-test
xeno-test was broken but I fixed it doing the following links:
ln -s /usr/lib/xenomai/clocktest /usr/bin/clocktest ln -s /usr/lib/xenomai/cyclictest /usr/bin/cyclictest ln -s /usr/lib/xenomai/irqloop /usr/bin/irqloop ln -s /usr/lib/xenomai/klatency /usr/bin/klatency ln -s /usr/lib/xenomai/latency /usr/bin/latency ln -s /usr/lib/xenomai/sigtest /usr/bin/sigtest ln -s /usr/lib/xenomai/switchtest /usr/bin/switchtest ln -s /usr/lib/xenomai/unit /usr/bin/unit
Install CVS and SVN to retrieve MIRC anc CHAMP trees.
aptitude install cvs subversion
Now test compile of old mirkwood code
install dependencies
aptitude install fftw3 aptitude install fftw3-dev aptitude install fftw3-doc
---+++ RTNET
Building RTNET
Download git tree in /usr/src/
git clone git://rtnet.git.sourceforge.net/gitroot/rtnet/rtnet
Change name of directory to a tag name (otherwise dhmake refuses to write debian info to dir)
mv rtnet rtnet-0.9.11
Install the package dh_make
aptitude install dh-make
cd rtnet-0.9.11/
dh_make --createorig
Type of package: single binary, multiple binary, library, kernel module or cdbs?
[s/m/l/k/b] b
Maintainer name : root Email-Address : root@fangorn.chara-array.org Date : Fri, 27 Nov 2009 03:15:25 -0800 Package Name : rtnet Version : 0.9.11 License : blank Using dpatch : no Type of Package : cdbs Hit <enter> to confirm: Done. Please edit the files in the debian/ subdirectory now. rtnet uses a configure script, so you probably don't have to edit the Makefiles. fangorn:/usr/src/rtnet-0.9.11# git clone git://rtnet.git.sourceforge.net/gitroot/rtnet/rtnet Initialized empty Git repository in /usr/src/rtnet-0.9.11/rtnet/.git/
'b' option worked when I compiled the package.
Need to run this script for building dependencies: /usr/lib/pbuilder/pbuilder-satisfydepends
Then run:
git-buildpackage -us -uc -rfakeroot --git-debian-branch=master --git-upstream-branch=origin/master --git-ignore-new
The following packages are created:
rtnet_0.9.11-1.diff.gz rtnet_0.9.11-1.dsc rtnet_0.9.11-1_i386.build rtnet_0.9.11-1_i386.changes rtnet_0.9.11-1_i386.deb rtnet_0.9.11.orig.tar.gz
install debian package:
dpkg -i rtnet_0.9.11-1_i386.deb
edit /etc/rtnet.conf
need to change:
RT_DRIVER="rt_e1000" #driver for our intel chipset RT_DRIVER_OPTIONS="cards=0,1" #This loads RT driver for eth1
IPADDR="10.0.0.10"
- Simple setup: List of TDMA slaves
TDMA_SLAVES="10.0.0.9" # this is the VME address (could add mirkwood too as 10.0.0.8)
To test RTNET do the following
Shutdown network interface/s
ifdown eth0
remove standard network driver for ethernet cards: modprobe -r e1000
start rtnet:
rtnet start
add a route to the VME CPU
rtroute add 10.0.0.9 00:01:af:17:a4:53 dev rteth0
reinsert non-RT ethernet driver
modprobe e1000
Test connection:
rtping 10.0.0.9
---+++ Analogy (comedi)
Example programme:
/**
* @file * Analogy for Linux, output command test program * * @note Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> * @note Copyright (C) 2008 Alexis Berlemont <alexis.berlemont@free.fr> * * Xenomai is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Xenomai is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Xenomai; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
- include <stdio.h>
- include <stdlib.h>
- include <sys/mman.h>
- include <errno.h>
- include <getopt.h>
- include <string.h>
- include <native/task.h>
- include <analogy/analogy.h>
/* Default command's parameters */
/* For write operation, we consider
the default subdevice index is 1 */
- define ID_SUBD 1
/* For simplicity sake, a maximum channel
count is defined */
- define MAX_NB_CHAN 10
/* Four channels used by default */
- define NB_CHAN 4
/* One hundred triggered scans by default */
- define NB_SCAN 100
- define FILENAME "analogy0"
- define BUF_SIZE 10000
static unsigned char buf[BUF_SIZE]; static char *filename = FILENAME; static char *str_chans = "0,1"; static unsigned int chans[MAX_NB_CHAN]; static int verbose = 0; static int real_time = 0; static int use_mmap = 0;
static RT_TASK rt_task_desc;
/* The command to send by default */ a4l_cmd_t cmd = {
.idx_subd = ID_SUBD, .flags = 0, .start_src = TRIG_INT, .start_arg = 0, .scan_begin_src = TRIG_TIMER, .scan_begin_arg = 2000000, /* in ns */ .convert_src = TRIG_NOW, .convert_arg = 0, /* in ns */ .scan_end_src = TRIG_COUNT, .scan_end_arg = 0, .stop_src = TRIG_COUNT, .stop_arg = NB_SCAN, .nb_chan = 0, .chan_descs = chans,
};
a4l_insn_t insn = {
.type = A4L_INSN_INTTRIG, .idx_subd = ID_SUBD, .data_size = 0,
};
struct option cmd_write_opts[] = {
{"verbose", no_argument, NULL, 'v'}, {"real-time", no_argument, NULL, 'r'}, {"device", required_argument, NULL, 'd'}, {"subdevice", required_argument, NULL, 's'}, {"scan-count", required_argument, NULL, 'S'}, {"channels", required_argument, NULL, 'c'}, {"mmap", no_argument, NULL, 'm'}, {"help", no_argument, NULL, 'h'}, {0},
};
void do_print_usage(void) {
fprintf(stdout, "usage:\tcmd_write [OPTS]\n"); fprintf(stdout, "\tOPTS:\t -v, --verbose: verbose output\n"); fprintf(stdout,
"\t\t -d, --device: " "device filename (analogy0, analogy1, ...)\n");
fprintf(stdout, "\t\t -s, --subdevice: subdevice index\n"); fprintf(stdout, "\t\t -S, --scan-count: count of scan to perform\n"); fprintf(stdout, "\t\t -c, --channels: channels to use (ex.: -c 0,1)\n"); fprintf(stdout, "\t\t -m, --mmap: mmap the buffer\n"); fprintf(stdout, "\t\t -h, --help: print this help\n");
}
int main(int argc, char *argv[]) {
int ret = 0, len, ofs; unsigned int i, scan_size = 0, cnt = 0; unsigned long buf_size; void *map = NULL; a4l_desc_t dsc = { .sbdata = NULL };
/* Compute arguments */ while ((ret = getopt_long(argc,
argv, "vrd:s:S:c:mh", cmd_write_opts, NULL)) >= 0) {
switch (ret) { case 'v': verbose = 1; break; case 'r': real_time = 1; break; case 'd': filename = optarg; break; case 's': cmd.idx_subd = insn.idx_subd = strtoul(optarg, NULL, 0); break; case 'S': cmd.stop_arg = strtoul(optarg, NULL, 0); break; case 'c': str_chans = optarg; break; case 'm': use_mmap = 1; break; case 'h': default: do_print_usage(); return 0; } }
/* Recover the channels to compute */ do { cmd.nb_chan++; len = strlen(str_chans); ofs = strcspn(str_chans, ","); if (sscanf(str_chans, "%u", &chans[cmd.nb_chan - 1]) == 0) { fprintf(stderr, "cmd_write: bad channels argument\n"); return -EINVAL; } str_chans += ofs + 1; } while (len != ofs);
/* Update the command structure */ cmd.scan_end_arg = cmd.nb_chan;
if (real_time != 0) {
if (verbose != 0) printf("cmd_write: switching to real-time mode\n");
/* Prevent any memory-swapping for this program */ ret = mlockall(MCL_CURRENT | MCL_FUTURE); if (ret < 0) { ret = errno; fprintf(stderr, "cmd_write: mlockall failed (ret=%d)\n",
ret);
goto out_main; }
/* Turn the current process into an RT task */ ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0); if (ret < 0) { fprintf(stderr,
"cmd_write: rt_task_shadow failed (ret=%d)\n", ret);
goto out_main; } }
/* Open the device */ ret = a4l_open(&dsc, filename); if (ret < 0) { fprintf(stderr,
"cmd_write: a4l_open %s failed (ret=%d)\n", FILENAME, ret);
return ret; }
if (verbose != 0) { printf("cmd_write: device %s opened (fd=%d)\n",
filename, dsc.fd);
printf("cmd_write: basic descriptor retrieved\n"); printf("\t subdevices count = %d\n", dsc.nb_subd); printf("\t read subdevice index = %d\n", dsc.idx_read_subd); printf("\t write subdevice index = %d\n", dsc.idx_write_subd); }
/* Allocate a buffer so as to get more info (subd, chan, rng) */ dsc.sbdata = malloc(dsc.sbsize); if (dsc.sbdata == NULL) { fprintf(stderr, "cmd_write: malloc failed \n"); return -ENOMEM; }
/* Get this data */ ret = a4l_fill_desc(&dsc); if (ret < 0) { fprintf(stderr,
"cmd_write: a4l_get_desc failed (ret=%d)\n", ret);
goto out_main; }
if (verbose != 0) printf("cmd_write: complex descriptor retrieved\n");
/* Get the size of a single acquisition */ for (i = 0; i < cmd.nb_chan; i++) { a4l_chinfo_t *info;
ret = a4l_get_chinfo(&dsc,
cmd.idx_subd, cmd.chan_descs[i], &info);
if (ret < 0) { fprintf(stderr,
"cmd_write: a4l_get_chinfo failed (ret=%d)\n", ret);
goto out_main; }
if (verbose != 0) { printf("cmd_write: channel %x\n", cmd.chan_descs[i]); printf("\t ranges count = %d\n", info->nb_rng); printf("\t range's size = %d (bits)\n", info->nb_bits); }
scan_size += (info->nb_bits % 8 == 0) ? info->nb_bits / 8 : (info->nb_bits / 8) + 1; }
if (verbose != 0) { printf("cmd_write: scan size = %u\n", scan_size); printf("cmd_write: size to write = %u\n",
scan_size * cmd.stop_arg);
}
/* Cancel any former command which might be in progress */ a4l_snd_cancel(&dsc, cmd.idx_subd);
if (use_mmap != 0) {
/* Get the buffer size to map */ ret = a4l_get_bufsize(&dsc, cmd.idx_subd, &buf_size); if (ret < 0) { fprintf(stderr,
"cmd_write: a4l_get_bufsize() failed " "(ret=%d)\n", ret);
goto out_main; }
if (verbose != 0) printf("cmd_write: buffer size = %lu bytes\n",
buf_size);
/* Map the analog input subdevice buffer */ ret = a4l_mmap(&dsc, cmd.idx_subd, buf_size, &map); if (ret < 0) { fprintf(stderr,
"cmd_write: a4l_mmap() failed (ret=%d)\n", ret);
goto out_main; }
if (verbose != 0) printf("cmd_write: mmap performed successfully "
"(map=0x%p)\n", map);
}
/* Send the command to the output device */ ret = a4l_snd_command(&dsc, &cmd); if (ret < 0) { fprintf(stderr,
"cmd_write: a4l_snd_command failed (ret=%d)\n", ret);
goto out_main; }
if (verbose != 0) printf("cmd_write: command successfully sent\n");
/* Set up the buffer to be written */ for (i = 0; i < BUF_SIZE; i++) buf[i] = i;
if (use_mmap == 0) {
/* Send data */ while (cnt < scan_size * cmd.stop_arg) { unsigned int tmp =
(scan_size * cmd.stop_arg - cnt) > BUF_SIZE ? BUF_SIZE : (scan_size * cmd.stop_arg - cnt);
ret = a4l_async_write(&dsc, buf, tmp, A4L_INFINITE); if (ret < 0) {
fprintf(stderr, "cmd_write: a4l_write failed (ret=%d)\n", ret); goto out_main;
} cnt += ret;
if (cnt == ret && cnt != 0) {
ret = a4l_snd_insn(&dsc, &insn); if (ret < 0) { fprintf(stderr, "cmd_write: triggering failed (ret=%d)\n", ret); goto out_main; }
} } } else { unsigned long front = 0;
/* Send data through the shared buffer */ while (cnt < cmd.stop_arg * scan_size) {
/* If the buffer is full, wait for an event
(Note that a4l_poll() also retrieves the data amount to read; in our case it is useless as we have to update the data read counter) */
if (front == 0) {
ret = a4l_poll(&dsc, cmd.idx_subd, A4L_INFINITE); if (ret < 0) { fprintf(stderr, "cmd_write: a4l_mark_bufrw() failed (ret=%d)\n", ret); goto out_main; } else front = (unsigned long)ret;
}
/* Update the variable front according to the data amount
we still have to send */
if (front > (scan_size * cmd.stop_arg - cnt))
front = scan_size * cmd.stop_arg - cnt;
/* Perform the copy
(Usually, such an operation should be avoided: the shared buffer should be used without any intermediate buffer, the "mmaped" buffer is interesting for saving data copy) */
memcpy(map + (cnt % buf_size),
buf + (cnt % BUF_SIZE), front);
/* Update the counter */ cnt += front;
/* Retrieve and update the buffer's state
(In output case, we recover how many bytes can be written into the shared buffer) */
ret = a4l_mark_bufrw(&dsc, cmd.idx_subd, front, &front); if (ret < 0) {
fprintf(stderr, "cmd_write: a4l_mark_bufrw() failed (ret=%d)\n", ret); goto out_main;
}
if (cnt == front && cnt != 0) {
ret = a4l_snd_insn(&dsc, &insn); if (ret < 0) { fprintf(stderr, "cmd_write: triggering failed (ret=%d)\n", ret); goto out_main; }
} } }
if (verbose != 0) printf("cmd_write: %d bytes successfully written\n", cnt);
ret = 0;
out_main:
/* Free the buffer used as device descriptor */ if (dsc.sbdata != NULL) free(dsc.sbdata);
/* Release the file descriptor */ a4l_close(&dsc);
return ret;
}
Makefile for programme:
CC = $(shell /usr/bin/xeno-config --cc) LXRT_CFLAGS = $(shell /usr/bin/xeno-config --skin=native --cflags) LXRT_LDFLAGS = $(shell /usr/bin/xeno-config --skin=native --ldflags) EXTRA_LDFLAGS = -lanalogy -lrtdm OBJ = cmd_write SRC := $(OBJ).c
all: $(OBJ)
$(OBJ): $(SRC) $(CC) $(SRC) $(LXRT_CFLAGS) $(LXRT_LDFLAGS) $(EXTRA_LDFLAGS) -o $(OBJ)
clean: rm -fr *.mod.c *.o *.ko $(OBJ) *~ .$(OBJ) .tmp_versions
install: install -m 0755 $(OBJ) /usr/local/bin
.PHONY: clean