RT System

From Monnier Group Research Wiki
Jump to navigationJump to search

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:

  1. This file describes the network interfaces available on your system
  2. and how to activate them. For more information, see interfaces(5).
  1. The loopback network interface

auto lo iface lo inet loopback

  1. 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:

  1. deb cdrom:[Debian GNU/Linux 5.0.2 _Lenny_ - Official i386 NETINST Binary-1 20090629-11:06]/ lenny main
  1. deb cdrom:[Debian GNU/Linux 5.0.2 _Lenny_ - Official i386 NETINST Binary-1 20090629-11:06]/ lenny main
  1. 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

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

  1. 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:

  1. apt-get install git-core git-buildpackage
  2. 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:

  1. 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:

  1. /etc/fstab: static file system information.
  2. <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:

  1. /etc/modules: kernel modules to load at boot time.
  2. This file contains the names of kernel modules that should be loaded
  3. at boot time, one per line. Lines beginning with "#" are ignored.
  4. 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"

  1. 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.
*/
  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <sys/mman.h>
  4. include <errno.h>
  5. include <getopt.h>
  6. include <string.h>
  1. include <native/task.h>
  1. include <analogy/analogy.h>

/* Default command's parameters */

/* For write operation, we consider

  the default subdevice index is 1 */
  1. define ID_SUBD 1

/* For simplicity sake, a maximum channel

  count is defined */
  1. define MAX_NB_CHAN 10

/* Four channels used by default */

  1. define NB_CHAN 4

/* One hundred triggered scans by default */

  1. define NB_SCAN 100
  1. define FILENAME "analogy0"
  1. 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