Module: xenomai-forge
Branch: next
Commit: 3e52ecb465f5e3e25fb42d600da50e66b5b0f17b
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=3e52ecb465f5e3e25fb42d600da50e66b5b0f17b

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Jun 13 10:21:52 2014 +0200

demo/posix: add CAN round-trip time measurement program

---

 demo/posix/Makefile.am            |   24 +++
 demo/posix/Makefile.in            |  192 +++++++++++++++--
 demo/posix/can-rtt.c              |  427 +++++++++++++++++++++++++++++++++++++
 doc/doxygen/manual-common.conf.in |    7 +-
 include/rtdm/can.h                |    2 +-
 5 files changed, 633 insertions(+), 19 deletions(-)

diff --git a/demo/posix/Makefile.am b/demo/posix/Makefile.am
index 7af79ba..dca7e90 100644
--- a/demo/posix/Makefile.am
+++ b/demo/posix/Makefile.am
@@ -1,4 +1,28 @@
+demodir = @XENO_DEMO_DIR@
+
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
+core_libs =
 
 if XENO_COBALT
 SUBDIRS = cobalt
+core_libs += ../../lib/cobalt/libcobalt.la
 endif
+
+demo_PROGRAMS =        \
+       can-rtt
+
+cppflags =                     \
+       $(XENO_USER_CFLAGS)     \
+       -I$(top_srcdir)/include
+
+ldflags = $(XENO_POSIX_WRAPPERS)
+
+ldadd =                                        \
+       $(core_libs)                            \
+        @XENO_USER_LDADD@                      \
+       -lpthread -lrt
+
+can_rtt_SOURCES = can-rtt.c
+can_rtt_CPPFLAGS = $(cppflags)
+can_rtt_LDFLAGS = $(ldflags)
+can_rtt_LDADD = $(ldadd)
diff --git a/demo/posix/Makefile.in b/demo/posix/Makefile.in
index 801ccc2..722b750 100644
--- a/demo/posix/Makefile.in
+++ b/demo/posix/Makefile.in
@@ -13,6 +13,7 @@
 # PARTICULAR PURPOSE.
 
 @SET_MAKE@
+
 VPATH = @srcdir@
 am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
 am__make_running_with_option = \
@@ -78,8 +79,11 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
+@XENO_COBALT_TRUE@am__append_1 = ../../lib/cobalt/libcobalt.la
+demo_PROGRAMS = can-rtt$(EXEEXT)
 subdir = demo/posix
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+       $(top_srcdir)/config/depcomp
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/config/ac_prog_cc_for_build.m4 \
        $(top_srcdir)/config/libtool.m4 \
@@ -94,6 +98,19 @@ mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = $(top_builddir)/include/xeno_config.h
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(demodir)"
+PROGRAMS = $(demo_PROGRAMS)
+am_can_rtt_OBJECTS = can_rtt-can-rtt.$(OBJEXT)
+can_rtt_OBJECTS = $(am_can_rtt_OBJECTS)
+am__DEPENDENCIES_1 = $(core_libs)
+can_rtt_DEPENDENCIES = $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+can_rtt_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(can_rtt_LDFLAGS) $(LDFLAGS) -o $@
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -106,8 +123,29 @@ AM_V_at = $(am__v_at_@AM_V@)
 am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
 am__v_at_0 = @
 am__v_at_1 = 
-SOURCES =
-DIST_SOURCES =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(can_rtt_SOURCES)
+DIST_SOURCES = $(can_rtt_SOURCES)
 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
        ctags-recursive dvi-recursive html-recursive info-recursive \
        install-data-recursive install-dvi-recursive \
@@ -338,10 +376,28 @@ target_vendor = @target_vendor@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
+demodir = @XENO_DEMO_DIR@
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
+core_libs = $(am__append_1)
 @XENO_COBALT_TRUE@SUBDIRS = cobalt
+cppflags = \
+       $(XENO_USER_CFLAGS)     \
+       -I$(top_srcdir)/include
+
+ldflags = $(XENO_POSIX_WRAPPERS)
+ldadd = \
+       $(core_libs)                            \
+        @XENO_USER_LDADD@                      \
+       -lpthread -lrt
+
+can_rtt_SOURCES = can-rtt.c
+can_rtt_CPPFLAGS = $(cppflags)
+can_rtt_LDFLAGS = $(ldflags)
+can_rtt_LDADD = $(ldadd)
 all: all-recursive
 
 .SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
 $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  
$(am__configure_deps)
        @for dep in $?; do \
          case '$(am__configure_deps)' in \
@@ -372,6 +428,102 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ 
$(am__configure_deps)
 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 $(am__aclocal_m4_deps):
+install-demoPROGRAMS: $(demo_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       @list='$(demo_PROGRAMS)'; test -n "$(demodir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(demodir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(demodir)" || exit 1; \
+       fi; \
+       for p in $$list; do echo "$$p $$p"; done | \
+       sed 's/$(EXEEXT)$$//' | \
+       while read p p1; do if test -f $$p \
+        || test -f $$p1 \
+         ; then echo "$$p"; echo "$$p"; else :; fi; \
+       done | \
+       sed -e 'p;s,.*/,,;n;h' \
+           -e 's|.*|.|' \
+           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+       sed 'N;N;N;s,\n, ,g' | \
+       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+           if ($$2 == $$4) files[d] = files[d] " " $$1; \
+           else { print "f", $$3 "/" $$4, $$1; } } \
+         END { for (d in files) print "f", d, files[d] }' | \
+       while read type dir files; do \
+           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+           test -z "$$files" || { \
+           echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) 
$(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files 
'$(DESTDIR)$(demodir)$$dir'"; \
+           $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) 
$(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files 
"$(DESTDIR)$(demodir)$$dir" || exit $$?; \
+           } \
+       ; done
+
+uninstall-demoPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(demo_PROGRAMS)'; test -n "$(demodir)" || list=; \
+       files=`for p in $$list; do echo "$$p"; done | \
+         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+             -e 's/$$/$(EXEEXT)/' \
+       `; \
+       test -n "$$list" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(demodir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(demodir)" && rm -f $$files
+
+clean-demoPROGRAMS:
+       @list='$(demo_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+
+can-rtt$(EXEEXT): $(can_rtt_OBJECTS) $(can_rtt_DEPENDENCIES) 
$(EXTRA_can_rtt_DEPENDENCIES) 
+       @rm -f can-rtt$(EXEEXT)
+       $(AM_V_CCLD)$(can_rtt_LINK) $(can_rtt_OBJECTS) $(can_rtt_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/can_rtt-can-rtt.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF 
$(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' 
libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF 
$(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' 
libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF 
$(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' 
libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+can_rtt-can-rtt.o: can-rtt.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(can_rtt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT can_rtt-can-rtt.o 
-MD -MP -MF $(DEPDIR)/can_rtt-can-rtt.Tpo -c -o can_rtt-can-rtt.o `test -f 
'can-rtt.c' || echo '$(srcdir)/'`can-rtt.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/can_rtt-can-rtt.Tpo 
$(DEPDIR)/can_rtt-can-rtt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='can-rtt.c' 
object='can_rtt-can-rtt.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(can_rtt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
can_rtt-can-rtt.o `test -f 'can-rtt.c' || echo '$(srcdir)/'`can-rtt.c
+
+can_rtt-can-rtt.obj: can-rtt.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(can_rtt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT can_rtt-can-rtt.obj 
-MD -MP -MF $(DEPDIR)/can_rtt-can-rtt.Tpo -c -o can_rtt-can-rtt.obj `if test -f 
'can-rtt.c'; then $(CYGPATH_W) 'can-rtt.c'; else $(CYGPATH_W) 
'$(srcdir)/can-rtt.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/can_rtt-can-rtt.Tpo 
$(DEPDIR)/can_rtt-can-rtt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='can-rtt.c' 
object='can_rtt-can-rtt.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(can_rtt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
can_rtt-can-rtt.obj `if test -f 'can-rtt.c'; then $(CYGPATH_W) 'can-rtt.c'; 
else $(CYGPATH_W) '$(srcdir)/can-rtt.c'; fi`
 
 mostlyclean-libtool:
        -rm -f *.lo
@@ -535,9 +687,12 @@ distdir: $(DISTFILES)
        done
 check-am: all-am
 check: check-recursive
-all-am: Makefile
+all-am: Makefile $(PROGRAMS)
 installdirs: installdirs-recursive
 installdirs-am:
+       for dir in "$(DESTDIR)$(demodir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
 install: install-recursive
 install-exec: install-exec-recursive
 install-data: install-data-recursive
@@ -570,11 +725,14 @@ maintainer-clean-generic:
        @echo "it deletes files that may require special tools to rebuild."
 clean: clean-recursive
 
-clean-am: clean-generic clean-libtool mostlyclean-am
+clean-am: clean-demoPROGRAMS clean-generic clean-libtool \
+       mostlyclean-am
 
 distclean: distclean-recursive
+       -rm -rf ./$(DEPDIR)
        -rm -f Makefile
-distclean-am: clean-am distclean-generic distclean-tags
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
 
 dvi: dvi-recursive
 
@@ -588,7 +746,7 @@ info: info-recursive
 
 info-am:
 
-install-data-am:
+install-data-am: install-demoPROGRAMS
 
 install-dvi: install-dvi-recursive
 
@@ -617,12 +775,14 @@ install-ps-am:
 installcheck-am:
 
 maintainer-clean: maintainer-clean-recursive
+       -rm -rf ./$(DEPDIR)
        -rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
 mostlyclean: mostlyclean-recursive
 
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
 
 pdf: pdf-recursive
 
@@ -632,22 +792,24 @@ ps: ps-recursive
 
 ps-am:
 
-uninstall-am:
+uninstall-am: uninstall-demoPROGRAMS
 
 .MAKE: $(am__recursive_targets) install-am install-strip
 
 .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
-       check-am clean clean-generic clean-libtool cscopelist-am ctags \
-       ctags-am distclean distclean-generic distclean-libtool \
-       distclean-tags distdir dvi dvi-am html html-am info info-am \
-       install install-am install-data install-data-am install-dvi \
+       check-am clean clean-demoPROGRAMS clean-generic clean-libtool \
+       cscopelist-am ctags ctags-am distclean distclean-compile \
+       distclean-generic distclean-libtool distclean-tags distdir dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-data install-data-am install-demoPROGRAMS install-dvi \
        install-dvi-am install-exec install-exec-am install-html \
        install-html-am install-info install-info-am install-man \
        install-pdf install-pdf-am install-ps install-ps-am \
        install-strip installcheck installcheck-am installdirs \
        installdirs-am maintainer-clean maintainer-clean-generic \
-       mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
-       ps ps-am tags tags-am uninstall uninstall-am
+       mostlyclean mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am uninstall-demoPROGRAMS
 
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/demo/posix/can-rtt.c b/demo/posix/can-rtt.c
new file mode 100644
index 0000000..d1e49f0
--- /dev/null
+++ b/demo/posix/can-rtt.c
@@ -0,0 +1,427 @@
+/*
+ * Round-Trip-Time Test - sends and receives messages and measures the
+ *                        time in between.
+ *
+ * Copyright (C) 2006 Wolfgang Grandegger <w...@grandegger.com>
+ *
+ * Based on RTnet's examples/xenomai/posix/rtt-sender.c.
+ *
+ * Copyright (C) 2002 Ulrich Marx <m...@kammer.uni-hannover.de>
+ *               2002 Marc Kleine-Budde <kleine-bu...@gmx.de>
+ *               2006 Jan Kiszka <jan.kis...@web.de>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * The program sends out CAN messages periodically and copies the current
+ * time-stamp to the payload. At reception, that time-stamp is compared
+ * with the current time to determine the round-trip time. The jitter
+ * values are printer out regularly. Concurrent tests can be carried out
+ * by starting the program with different message identifiers. It is also
+ * possible to use this program on a remote system as simple repeater to
+ * loopback messages.
+ */
+
+#include <errno.h>
+#include <mqueue.h>
+#include <signal.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#ifdef __XENO__
+#include <rtdm/can.h>
+#else
+#include <linux/can.h>
+#include <linux/can/raw.h>
+#endif
+
+#define NSEC_PER_SEC 1000000000
+
+static unsigned int cycle = 10000; /* 10 ms */
+static canid_t can_id = 0x1;
+
+static pthread_t txthread, rxthread;
+static int txsock, rxsock;
+static mqd_t mq;
+static int txcount, rxcount;
+static int overruns;
+static int repeater;
+
+struct rtt_stat {
+    long long rtt;
+    long long rtt_min;
+    long long rtt_max;
+    long long rtt_sum;
+    long long rtt_sum_last;
+    int counts_per_sec;
+};
+
+static void print_usage(char *prg)
+{
+    fprintf(stderr,
+           "Usage: %s  [Options] <tx-can-interface> <rx-can-interface>\n"
+           "Options:\n"
+           " -h, --help     This help\n"
+           " -r, --repeater Repeater, send back received messages\n"
+           " -i, --id=ID    CAN Identifier (default = 0x1)\n"
+           " -c, --cycle    Cycle time in us (default = 10000us)\n",
+           prg);
+}
+
+static void *transmitter(void *arg)
+{
+    struct sched_param  param = { .sched_priority = 80 };
+    struct timespec next_period;
+    struct timespec time;
+    struct can_frame frame;
+    long long *rtt_time = (long long *)&frame.data;
+
+    /* Pre-fill CAN frame */
+    frame.can_id = can_id;
+    frame.can_dlc = sizeof(*rtt_time);
+
+#ifdef __XENO__
+    pthread_set_name_np(pthread_self(), "rtcan_rtt_transmitter");
+#endif
+    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+
+    clock_gettime(CLOCK_MONOTONIC, &next_period);
+
+    while(1) {
+       next_period.tv_nsec += cycle * 1000;
+       while (next_period.tv_nsec >= NSEC_PER_SEC) {
+               next_period.tv_nsec -= NSEC_PER_SEC;
+               next_period.tv_sec++;
+       }
+
+       clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_period, NULL);
+
+       if (rxcount != txcount) {
+           overruns++;
+           continue;
+       }
+
+       clock_gettime(CLOCK_MONOTONIC, &time);
+       *rtt_time = (long long)time.tv_sec * NSEC_PER_SEC + time.tv_nsec;
+
+       /* Transmit the message containing the local time */
+       if (send(txsock, (void *)&frame, sizeof(struct can_frame), 0) < 0) {
+           if (errno == EBADF)
+               printf("terminating transmitter thread\n");
+           else
+               perror("send failed");
+           return NULL;
+       }
+       txcount++;
+    }
+}
+
+
+static void *receiver(void *arg)
+{
+    struct sched_param param = { .sched_priority = 82 };
+    struct timespec time;
+    struct can_frame frame;
+    long long *rtt_time = (long long *)frame.data;
+    struct rtt_stat rtt_stat = {0, 1000000000000000000LL, 
-1000000000000000000LL,
+                               0, 0, 0};
+
+#ifdef __XENO__
+    pthread_set_name_np(pthread_self(), "rtcan_rtt_receiver");
+#endif
+    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+
+    rtt_stat.counts_per_sec = 1000000 / cycle;
+
+    while (1) {
+       if (recv(rxsock, (void *)&frame, sizeof(struct can_frame), 0) < 0) {
+           if (errno == EBADF)
+               printf("terminating receiver thread\n");
+           else
+               perror("recv failed");
+           return NULL;
+       }
+       if (repeater) {
+           /* Transmit the message back as is */
+           if (send(txsock, (void *)&frame, sizeof(struct can_frame), 0) < 0) {
+               if (errno == EBADF)
+                   printf("terminating transmitter thread\n");
+               else
+                   perror("send failed");
+               return NULL;
+           }
+           txcount++;
+       } else {
+           clock_gettime(CLOCK_MONOTONIC, &time);
+           if (rxcount > 0) {
+               rtt_stat.rtt = ((long long)time.tv_sec * 1000000000LL +
+                               time.tv_nsec - *rtt_time);
+               rtt_stat.rtt_sum += rtt_stat.rtt;
+               if (rtt_stat.rtt <  rtt_stat.rtt_min)
+                   rtt_stat.rtt_min = rtt_stat.rtt;
+               if (rtt_stat.rtt > rtt_stat.rtt_max)
+                   rtt_stat.rtt_max = rtt_stat.rtt;
+           }
+       }
+       rxcount++;
+
+       if ((rxcount % rtt_stat.counts_per_sec) == 0) {
+           mq_send(mq, (char *)&rtt_stat, sizeof(rtt_stat), 0);
+           rtt_stat.rtt_sum_last = rtt_stat.rtt_sum;
+       }
+    }
+}
+
+static void catch_signal(int sig)
+{
+    mq_close(mq);
+}
+
+
+int main(int argc, char *argv[])
+{
+    struct sched_param param = { .sched_priority = 1 };
+    pthread_attr_t thattr;
+    struct mq_attr mqattr;
+    struct sockaddr_can rxaddr, txaddr;
+    struct can_filter rxfilter[1];
+    struct rtt_stat rtt_stat;
+    char mqname[32];
+    char *txdev, *rxdev;
+    struct ifreq ifr;
+    int ret, opt;
+
+    struct option long_options[] = {
+       { "id", required_argument, 0, 'i'},
+       { "cycle", required_argument, 0, 'c'},
+       { "repeater", no_argument, 0, 'r'},
+       { "help", no_argument, 0, 'h'},
+       { 0, 0, 0, 0},
+    };
+
+    while ((opt = getopt_long(argc, argv, "hri:c:",
+                             long_options, NULL)) != -1) {
+       switch (opt) {
+       case 'c':
+           cycle = atoi(optarg);
+           break;
+
+       case 'i':
+           can_id = strtoul(optarg, NULL, 0);
+           break;
+
+       case 'r':
+           repeater = 1;
+           break;
+
+       default:
+           fprintf(stderr, "Unknown option %c\n", opt);
+       case 'h':
+           print_usage(argv[0]);
+           exit(-1);
+       }
+    }
+
+    printf("%d %d\n", optind, argc);
+    if (optind + 2 != argc) {
+       print_usage(argv[0]);
+       exit(0);
+    }
+
+    txdev = argv[optind];
+    rxdev = argv[optind + 1];
+
+    /* Create and configure RX socket */
+    if ((rxsock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
+       perror("RX socket failed");
+       return -1;
+    }
+
+    strncpy(ifr.ifr_name, rxdev, IFNAMSIZ);
+    printf("RX rxsock=%d, ifr_name=%s\n", rxsock, ifr.ifr_name);
+
+    if (ioctl(rxsock, SIOCGIFINDEX, &ifr) < 0) {
+       perror("RX ioctl SIOCGIFINDEX failed");
+       goto failure1;
+    }
+
+    /* We only want to receive our own messages */
+    rxfilter[0].can_id = can_id;
+    rxfilter[0].can_mask = 0x3ff;
+    if (setsockopt(rxsock, SOL_CAN_RAW, CAN_RAW_FILTER,
+                  &rxfilter, sizeof(struct can_filter)) < 0) {
+       perror("RX setsockopt CAN_RAW_FILTER failed");
+       goto failure1;
+    }
+    memset(&rxaddr, 0, sizeof(rxaddr));
+    rxaddr.can_ifindex = ifr.ifr_ifindex;
+    rxaddr.can_family = AF_CAN;
+    if (bind(rxsock, (struct sockaddr *)&rxaddr, sizeof(rxaddr)) < 0) {
+       perror("RX bind failed\n");
+       goto failure1;
+    }
+
+    /* Create and configure TX socket */
+
+    if (strcmp(rxdev, txdev) == 0) {
+       txsock = rxsock;
+    } else {
+       if ((txsock = socket(PF_CAN, SOCK_RAW, 0)) < 0) {
+           perror("TX socket failed");
+           goto failure1;
+       }
+
+       strncpy(ifr.ifr_name, txdev, IFNAMSIZ);
+       printf("TX txsock=%d, ifr_name=%s\n", txsock, ifr.ifr_name);
+
+       if (ioctl(txsock, SIOCGIFINDEX, &ifr) < 0) {
+           perror("TX ioctl SIOCGIFINDEX failed");
+           goto failure2;
+       }
+
+       /* Suppress definiton of a default receive filter list */
+       if (setsockopt(txsock, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0) < 0) {
+           perror("TX setsockopt CAN_RAW_FILTER failed");
+           goto failure2;
+       }
+
+       memset(&txaddr, 0, sizeof(txaddr));
+       txaddr.can_ifindex = ifr.ifr_ifindex;
+       txaddr.can_family = AF_CAN;
+
+       if (bind(txsock, (struct sockaddr *)&txaddr, sizeof(txaddr)) < 0) {
+               perror("TX bind failed\n");
+               goto failure2;
+       }
+    }
+
+    signal(SIGTERM, catch_signal);
+    signal(SIGINT, catch_signal);
+    signal(SIGHUP, catch_signal);
+    mlockall(MCL_CURRENT|MCL_FUTURE);
+
+    printf("Round-Trip-Time test %s -> %s with CAN ID 0x%x\n",
+          argv[optind], argv[optind + 1], can_id);
+    printf("Cycle time: %d us\n", cycle);
+    printf("All RTT timing figures are in us.\n");
+
+    /* Create statistics message queue */
+    snprintf(mqname, sizeof(mqname), "/rtcan_rtt-%d", getpid());
+    mqattr.mq_flags   = 0;
+    mqattr.mq_maxmsg  = 100;
+    mqattr.mq_msgsize = sizeof(struct rtt_stat);
+    mq = mq_open(mqname, O_RDWR | O_CREAT | O_EXCL, 0600, &mqattr);
+    if (mq == (mqd_t)-1) {
+       perror("opening mqueue failed");
+       goto failure2;
+    }
+
+    /* Create receiver RT-thread */
+    pthread_attr_init(&thattr);
+    pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
+    pthread_attr_setstacksize(&thattr, PTHREAD_STACK_MIN);
+    ret = pthread_create(&rxthread, &thattr, &receiver, NULL);
+    if (ret) {
+       fprintf(stderr, "%s: pthread_create(receiver) failed\n",
+               strerror(-ret));
+       goto failure3;
+    }
+
+    if (!repeater) {
+       /* Create transitter RT-thread */
+       ret = pthread_create(&txthread, &thattr, &transmitter, NULL);
+       if (ret) {
+           fprintf(stderr, "%s: pthread_create(transmitter) failed\n",
+                   strerror(-ret));
+           goto failure4;
+       }
+    }
+
+    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
+
+    if (repeater)
+       printf("Messages\n");
+    else
+       printf("Messages RTTlast RTT_avg RTT_min RTT_max Overruns\n");
+
+    while (1) {
+       long long rtt_avg;
+
+       ret = mq_receive(mq, (char *)&rtt_stat, sizeof(rtt_stat), NULL);
+       if (ret != sizeof(rtt_stat)) {
+           if (ret < 0) {
+               if (errno == EBADF)
+                   printf("terminating mq_receive\n");
+               else
+                   perror("mq_receive failed");
+           } else
+               fprintf(stderr,
+                       "mq_receive returned invalid length %d\n", ret);
+           break;
+       }
+
+       if (repeater) {
+           printf("%8d\n", rxcount);
+       } else {
+           rtt_avg = ((rtt_stat.rtt_sum - rtt_stat.rtt_sum_last) /
+                      rtt_stat.counts_per_sec);
+           printf("%8d %7ld %7ld %7ld %7ld %8d\n", rxcount,
+                  (long)(rtt_stat.rtt / 1000), (long)(rtt_avg / 1000),
+                  (long)(rtt_stat.rtt_min / 1000),
+                  (long)(rtt_stat.rtt_max / 1000),
+                  overruns);
+       }
+    }
+
+    /* This call also leaves primary mode, required for socket cleanup. */
+    printf("shutting down\n");
+
+    /* Important: First close the sockets! */
+    while ((close(rxsock) < 0) && (errno == EAGAIN)) {
+       printf("RX socket busy - waiting...\n");
+       sleep(1);
+    }
+    while ((close(txsock) < 0) && (errno == EAGAIN)) {
+       printf("TX socket busy - waiting...\n");
+       sleep(1);
+    }
+
+    pthread_join(txthread, NULL);
+    pthread_kill(rxthread, SIGHUP);
+    pthread_join(rxthread, NULL);
+
+    return 0;
+
+ failure4:
+    pthread_kill(rxthread, SIGHUP);
+    pthread_join(rxthread, NULL);
+ failure3:
+    mq_close(mq);
+ failure2:
+    close(txsock);
+ failure1:
+    close(rxsock);
+
+    return 1;
+}
diff --git a/doc/doxygen/manual-common.conf.in 
b/doc/doxygen/manual-common.conf.in
index 7cbb1d1..370d867 100644
--- a/doc/doxygen/manual-common.conf.in
+++ b/doc/doxygen/manual-common.conf.in
@@ -869,9 +869,10 @@ INPUT                  =                                   
        \
 # directories that contain example code fragments that are included (see
 # the \include command).
 
-EXAMPLE_PATH           =                       \
-                      @top_srcdir@/demo/posix  \
-                      @top_srcdir@/demo/alchemy
+EXAMPLE_PATH           =                               \
+                      @top_srcdir@/demo/posix          \
+                      @top_srcdir@/demo/alchemy        \
+                      @top_srcdir@/utils
 
 # The INCLUDE_PATH tag can be used to specify one or more directories that
 # contain include files that are not input files but should be processed by
diff --git a/include/rtdm/can.h b/include/rtdm/can.h
index a597be8..d70b89e 100644
--- a/include/rtdm/can.h
+++ b/include/rtdm/can.h
@@ -231,7 +231,7 @@
  * @example rtcanconfig.c
  * @example rtcansend.c
  * @example rtcanrecv.c
- * @example rtcan_rtt.c
+ * @example can-rtt.c
  * @}
  *
  * @}


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to