|
|
Line 19: |
Line 19: |
|
| |
|
| ---+ Real-time system | | ---+ Real-time system |
| ---++ Xenomai
| | Click here for detail on the upgrade to the realtime system [[RT_System]] |
| ---+++ 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
| |
|
| |
|
|
| |
|