# HG changeset patch # User edouard # Date 1289597046 -3600 # Node ID b9274b595650763ed8fdfaa71c0184ee5b4e9651 # Parent 9e496a2aadca2e630931b0b24477e1104f58b19d CosateQ contribution. diff -r 9e496a2aadca -r b9274b595650 CanFestival-3.vc8.sln --- a/CanFestival-3.vc8.sln Fri Nov 12 22:02:32 2010 +0100 +++ b/CanFestival-3.vc8.sln Fri Nov 12 22:24:06 2010 +0100 @@ -1,18 +1,16 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual C++ Express 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CanFestival-3", "CanFestival-3.vc8.vcproj", "{50EF2507-9B87-4525-8B19-80EB42E67079}" +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CanFestival-3", "CanFestival-3.vc8.vcxproj", "{50EF2507-9B87-4525-8B19-80EB42E67079}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_uvccm_win32", "drivers\can_uvccm_win32\can_uvccm_win32.vcproj", "{39E3300A-29B4-4AA7-AF62-3B181FC26155}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_uvccm_win32", "drivers\can_uvccm_win32\can_uvccm_win32.vcxproj", "{782632D2-B467-DF90-C86E-D767972BAA59}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_peak_win32", "drivers\can_peak_win32\can_peak_win32.vcproj", "{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_peak_win32", "drivers\can_peak_win32\can_peak_win32.vcxproj", "{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestMasterSlave", "examples\TestMasterSlave\TestMasterSlave.vcproj", "{B51A176D-5320-4534-913B-3025CED5B27E}" - ProjectSection(ProjectDependencies) = postProject - {50EF2507-9B87-4525-8B19-80EB42E67079} = {50EF2507-9B87-4525-8B19-80EB42E67079} - EndProjectSection +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestMasterSlave", "examples\TestMasterSlave\TestMasterSlave.vcxproj", "{B51A176D-5320-4534-913B-3025CED5B27E}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_ixxat_win32", "drivers\can_ixxat_win32\can_ixxat_win32.vc8.vcproj", "{8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_ixxat_win32", "drivers\can_ixxat_win32\can_ixxat_win32.vc8.vcxproj", "{8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_copcican_win32", "drivers\can_copcican_win32\can_copcican_win32.vcxproj", "{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -30,22 +28,22 @@ {50EF2507-9B87-4525-8B19-80EB42E67079}.Release UNICODE|Win32.Build.0 = Release|Win32 {50EF2507-9B87-4525-8B19-80EB42E67079}.Release|Win32.ActiveCfg = Release|Win32 {50EF2507-9B87-4525-8B19-80EB42E67079}.Release|Win32.Build.0 = Release|Win32 - {39E3300A-29B4-4AA7-AF62-3B181FC26155}.Debug UNICODE|Win32.ActiveCfg = Debug UNICODE|Win32 - {39E3300A-29B4-4AA7-AF62-3B181FC26155}.Debug UNICODE|Win32.Build.0 = Debug UNICODE|Win32 - {39E3300A-29B4-4AA7-AF62-3B181FC26155}.Debug|Win32.ActiveCfg = Debug|Win32 - {39E3300A-29B4-4AA7-AF62-3B181FC26155}.Debug|Win32.Build.0 = Debug|Win32 - {39E3300A-29B4-4AA7-AF62-3B181FC26155}.Release UNICODE|Win32.ActiveCfg = Release UNICODE|Win32 - {39E3300A-29B4-4AA7-AF62-3B181FC26155}.Release UNICODE|Win32.Build.0 = Release UNICODE|Win32 - {39E3300A-29B4-4AA7-AF62-3B181FC26155}.Release|Win32.ActiveCfg = Release|Win32 - {39E3300A-29B4-4AA7-AF62-3B181FC26155}.Release|Win32.Build.0 = Release|Win32 - {732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Debug UNICODE|Win32.ActiveCfg = Debug UNICODE|Win32 - {732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Debug UNICODE|Win32.Build.0 = Debug UNICODE|Win32 - {732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Debug|Win32.Build.0 = Debug|Win32 - {732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Release UNICODE|Win32.ActiveCfg = Release UNICODE|Win32 - {732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Release UNICODE|Win32.Build.0 = Release UNICODE|Win32 - {732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Release|Win32.ActiveCfg = Release|Win32 - {732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Release|Win32.Build.0 = Release|Win32 + {782632D2-B467-DF90-C86E-D767972BAA59}.Debug UNICODE|Win32.ActiveCfg = Debug UNICODE|Win32 + {782632D2-B467-DF90-C86E-D767972BAA59}.Debug UNICODE|Win32.Build.0 = Debug UNICODE|Win32 + {782632D2-B467-DF90-C86E-D767972BAA59}.Debug|Win32.ActiveCfg = Debug|Win32 + {782632D2-B467-DF90-C86E-D767972BAA59}.Debug|Win32.Build.0 = Debug|Win32 + {782632D2-B467-DF90-C86E-D767972BAA59}.Release UNICODE|Win32.ActiveCfg = Release UNICODE|Win32 + {782632D2-B467-DF90-C86E-D767972BAA59}.Release UNICODE|Win32.Build.0 = Release UNICODE|Win32 + {782632D2-B467-DF90-C86E-D767972BAA59}.Release|Win32.ActiveCfg = Release|Win32 + {782632D2-B467-DF90-C86E-D767972BAA59}.Release|Win32.Build.0 = Release|Win32 + {C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Debug UNICODE|Win32.ActiveCfg = Debug UNICODE|Win32 + {C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Debug UNICODE|Win32.Build.0 = Debug UNICODE|Win32 + {C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Debug|Win32.ActiveCfg = Debug|Win32 + {C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Debug|Win32.Build.0 = Debug|Win32 + {C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Release UNICODE|Win32.ActiveCfg = Release UNICODE|Win32 + {C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Release UNICODE|Win32.Build.0 = Release UNICODE|Win32 + {C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Release|Win32.ActiveCfg = Release|Win32 + {C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Release|Win32.Build.0 = Release|Win32 {B51A176D-5320-4534-913B-3025CED5B27E}.Debug UNICODE|Win32.ActiveCfg = Debug|Win32 {B51A176D-5320-4534-913B-3025CED5B27E}.Debug UNICODE|Win32.Build.0 = Debug|Win32 {B51A176D-5320-4534-913B-3025CED5B27E}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -62,6 +60,14 @@ {8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}.Release UNICODE|Win32.Build.0 = Release|Win32 {8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}.Release|Win32.ActiveCfg = Release|Win32 {8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}.Release|Win32.Build.0 = Release|Win32 + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Debug UNICODE|Win32.ActiveCfg = Debug|Win32 + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Debug UNICODE|Win32.Build.0 = Debug|Win32 + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Debug|Win32.Build.0 = Debug|Win32 + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Release UNICODE|Win32.ActiveCfg = Release|Win32 + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Release UNICODE|Win32.Build.0 = Release|Win32 + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Release|Win32.ActiveCfg = Release|Win32 + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff -r 9e496a2aadca -r b9274b595650 configure --- a/configure Fri Nov 12 22:02:32 2010 +0100 +++ b/configure Fri Nov 12 22:24:06 2010 +0100 @@ -2,41 +2,41 @@ # # Copyright (C) 2004 Edouard TISSERRANT, Laurent BESSARD -# Based on Gabriel Gerhardsson's cacheprobe configure script. -# -# This file is part of CanFestival, a library implementing CanOpen Stack. -# +# Based on Gabriel Gerhardsson's cacheprobe configure script. +# +# This file is part of CanFestival, a library implementing CanOpen Stack. +# # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. -# +# # This library 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 # Lesser General Public License for more details. -# +# # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# +# ########################################################################### # DEFAULT CANFESTIVAL DEFINES # ########################################################################### -# Number of can bus to use +# Number of can bus to use MAX_CAN_BUS_ID=1 # max bytes to transmit by SDO Put 4 if you only support expedited transfert. #For a normal transfert, (usually for a string), put the maximum string size to transfer. SDO_MAX_LENGTH_TRANSFERT=32 -# Number of SDO from differents nodes that the node can manage concurrently. +# Number of SDO from differents nodes that the node can manage concurrently. #for a slave node, usually put 1. SDO_MAX_SIMULTANEOUS_TRANSFERTS=4 -# Used for NMTable[bus][nodeId] +# Used for NMTable[bus][nodeId] # You can put less of 128 if on the netwo # are connected only smaller nodeId node. NMT_MAX_NODE_ID=128 @@ -78,7 +78,7 @@ # Install prefix SUB_PREFIX= -# Used for C compiler test/detection +# Used for C compiler test/detection CFLAGS= test=conftest rm -f $test $test.c @@ -96,7 +96,7 @@ ########################################################################### while [ $# -ge 1 ]; do optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` - + case $1 in --cc=*) CC=$optarg;; --cxx=*) CXX=$optarg;; @@ -145,11 +145,11 @@ echo " \"win32\" for win32 systems (native, mingw or VC++)" echo " \"hcs12\" for HCS12 micro-controller" echo " --can=foo Use 'foo' as CAN driver" - echo " \"anagate_linux\" use AnaGate CAN(duo) driver for linux" - echo " \"anagate_win32\" use AnaGate CAN(duo) driver for win32" + echo " \"anagate_linux\" use AnaGate CAN(duo) driver for linux" + echo " \"anagate_win32\" use AnaGate CAN(duo) driver for win32" echo " \"peak_linux\" use Linux build host installed Peak driver and library" echo " see http://www.peak-system.com/linux/" - echo " \"peak_win32\" use win32 PcanLight Peak driver and library with Cygwin" + echo " \"peak_win32\" use win32 PcanLight Peak driver and library with Cygwin" echo " see http://www.peak-system.com/themen/download_gb.html" echo " \"virtual\" use unix pipe based virtual can driver" echo " \"virtual_kernel\" use kernel module virtual can driver" @@ -159,7 +159,11 @@ echo " see http://www.ocera.org/download/components/WP7/lincan-0.3.3.html" echo " \"can4linux\" can4linux driver" echo " see http://www.port.de/engl/canprod/hw_can4linux.html" - echo " --timers=foo Use 'foo' as TIMERS driver (can be 'unix', 'xeno', 'rtai' or 'kernel')" + echo " \"copcican_linux\" user space driver interface for CO-PCICAN card" + echo " see http://www.cosateq.com/" + echo " \"copcican_comedi\" COMEDI driver interface for CO-PCICAN card" + echo " see http://www.cosateq.com/" + echo " --timers=foo Use 'foo' as TIMERS driver (can be 'unix', 'xeno', 'rtai', 'kernel' or 'kernel_xeno')" echo " --wx=foo Force result of WxWidgets detection (0 or 1)" echo " --binutils=path Override binutils path detection (as regards \$CC content)" echo " --disable-dll Disable run-time dynamic linking of can, led and nvram drivers" @@ -273,18 +277,24 @@ # Try to guess can if [ "$SUB_CAN_DRIVER" = "" ]; then if [ "$SUB_TARGET" = "unix" ]; then - if [ -e /usr/lib/libpcan.so ]; then + if [ -e /usr/lib/libpcan.so ]; then echo "Choosing installed Peak driver as CAN driver." SUB_CAN_DRIVER=peak_linux elif [ "$SUB_OS_NAME" = "CYGWIN" -a "PCAN_LIB" != "" ]; then echo "Choosing installed Peak driver as CAN driver." - SUB_CAN_DRIVER=peak_win32 - elif [ -e /usr/lib/libcanlib.so ]; then + SUB_CAN_DRIVER=peak_win32 + elif [ -e /usr/lib/libcanlib.so ]; then echo "Choosing installed Kvaser driver as CAN driver. (unix)" SUB_CAN_DRIVER=kvaser - elif [ -e /usr/local/lib/libAnaGateAPIDLL.so ]; then + elif [ -e /usr/local/lib/libAnaGateAPIDLL.so ]; then echo "Choosing installed AnaGate driver as CAN driver. (unix)" SUB_CAN_DRIVER=anagate_linux + elif [ -e /usr/local/lib/libcanfestival_can_copcican_linux.so ]; then + echo "Choosing installed CO-PCICAN driver as CAN driver. (unix)" + SUB_CAN_DRIVER=copcican_linux + elif [ -e /usr/local/lib/libcanfestival_can_copcican_comedi.so ]; then + echo "Choosing installed CO-PCICAN driver as CAN driver. (unix)" + SUB_CAN_DRIVER=copcican_comedi elif [ "$SUB_OS_NAME" = "CYGWIN" -a "$KVASER_DLL_PATH" != "" ]; then echo "Choosing installed Kvaser driver as CAN driver. (cygwin)" SUB_CAN_DRIVER=kvaser @@ -309,7 +319,7 @@ # Warn for unstalled peak driver if choosen if [ "$SUB_CAN_DRIVER" = "peak" ]; then - if [ ! -e /usr/lib/libpcan.so ]; then + if [ ! -e /usr/lib/libpcan.so ]; then echo "Peak driver hasn't been installed !" exit -1 fi @@ -317,21 +327,29 @@ # Warn for unstalled peak driver if choosen if [ "$SUB_CAN_DRIVER" = "anagate_linux" ]; then - if [ ! -e /usr/local/lib/libAnaGateAPIDLL.so ]; then + if [ ! -e /usr/local/lib/libAnaGateAPIDLL.so ]; then echo "AnaGateCAN driver hasn't been installed !" exit -1 fi fi +# Warn for unstalled CO-PCICAN driver if choosen +if [ "$SUB_CAN_DRIVER" = "copcican_linux" ]; then + if [ ! -e /usr/local/lib/libcanfestival_can_copcican_linux.so ]; then + echo "CO-PCICAN driver hasn't been installed !" + exit -1 + fi +fi + # Warn for unstalled kvaser driver if choosen if [ "$SUB_CAN_DRIVER" = "kvaser" ]; then if [ "$SUB_OS_NAME" = "CYGWIN" ]; then - if [ ! -e "$KVASER_DLL_PATH/canlib32.dll" ]; then + if [ ! -e "$KVASER_DLL_PATH/canlib32.dll" ]; then echo "Kvaser driver hasn't been installed (cygwin)" exit -1 fi elif [ "$SUB_OS_NAME" = "LINUX" ]; then - if [ ! -e /usr/lib/libcanlib.so ]; then + if [ ! -e /usr/lib/libcanlib.so ]; then echo "Kvaser driver hasn't been installed (unix)" exit -1 fi @@ -348,20 +366,20 @@ # search for gcc hcs12 compiler m6811-elf-gcc or m68hc12-gcc ? if [ "$CC" = "" ]; then which m6811-elf-gcc >/dev/null 2>&1 - if (( $? )); then + if (( $? )); then which m68hc12-gcc >/dev/null 2>&1 - if (( $? )); then + if (( $? )); then echo "Please use --cc flag to specify compiler" exit 0 else - CC=m68hc12-gcc + CC=m68hc12-gcc fi else CC=m6811-elf-gcc SUB_PROG_CFLAGS=-m68hc12 fi fi -fi +fi #### CAN_DRIVER #### @@ -377,7 +395,7 @@ SUB_PROG_CFLAGS=$SUB_PROG_CFLAGS\ -I$KVASER_INCLUDE_PATH fi fi - fi + fi fi if [ "$SUB_CAN_DRIVER" = "peak_linux" ]; then @@ -469,6 +487,20 @@ fi fi +if [ "$SUB_TIMERS_DRIVER" = "kernel_xeno" ]; then + DISABLE_DLL=1 + if [ "$SUB_KERNELDIR" = "" ]; then + # use directory of current kernel + SUB_KERNELDIR=/lib/modules/$(uname -r)/build + fi + + # Also get the xenomai config + RT_LIB_DIR=`$XENO_CONFIG --library-dir`\ -Wl,-rpath\ `$XENO_CONFIG --library-dir` + SUB_EXE_CFLAGS=$SUB_EXE_CFLAGS\ `$XENO_CONFIG --xeno-ldflags`\ -L$RT_LIB_DIR\ -lnative\ -lrtdm + SUB_PROG_CFLAGS=$SUB_PROG_CFLAGS\ -DUSE_XENO\ `$XENO_CONFIG --xeno-cflags` + RTCAN_SOCKET=1 +fi + if [ "$SUB_TIMERS_DRIVER" = "none" ]; then SUB_TIMERS_DRIVER= fi @@ -489,7 +521,7 @@ echo "Checking for ${CC2}... No." fi rm -f $test.c $test.o - + # Check for first compiler, CC1 cat > $test.c <> include/config.h fi -done +done echo "" >> include/config.h for i in \ @@ -666,7 +698,7 @@ save_ifs="$IFS"; IFS=',' -for DEBUG_METHOD in $DEBUG; +for DEBUG_METHOD in $DEBUG; do IFS="$save_ifs" case $DEBUG_METHOD in @@ -679,7 +711,7 @@ echo "Possible Debug's methods are : \"ERR\", \"WAR\", \"MSG\", \"PDO\"" exit -1 ;; - esac + esac done if [ $WAR ]; then @@ -720,7 +752,7 @@ else SUB_EXE_CFLAGS=$SUB_EXE_CFLAGS\ -ldl fi - + fi @@ -767,7 +799,13 @@ if [ "$SUB_TARGET" = "unix" -a "$SUB_TIMERS_DRIVER" = "kernel" ]; then MAKEFILES=$MAKEFILES\ -\ examples/kerneltest/Makefile.in +\ examples/kerneltest/Makefile.in\ +\ examples/test_copcican_comedi/Makefile.in + +elif [ "$SUB_TARGET" = "unix" -a "$SUB_TIMERS_DRIVER" = "kernel_xeno" ]; then + MAKEFILES=$MAKEFILES\ +\ examples/kerneltest/Makefile.in\ +\ examples/test_copcican_comedi/Makefile.in elif [ "$SUB_TARGET" = "unix" ]; then MAKEFILES=$MAKEFILES\ @@ -775,7 +813,8 @@ \ examples/TestMasterSlave/Makefile.in\ \ examples/TestMasterSlaveLSS/Makefile.in\ \ examples/SillySlave/Makefile.in\ -\ examples/TestMasterMicroMod/Makefile.in +\ examples/TestMasterMicroMod/Makefile.in\ +\ examples/test_copcican_linux/Makefile.in fi if [ "$SUB_TARGET" = "win32" ]; then diff -r 9e496a2aadca -r b9274b595650 copcican_comedi_howto.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/copcican_comedi_howto.txt Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,55 @@ +HOW TO configure CanFestival for a CO-PCICAN card for COMEDI in the kernel (optionally with Xenomai): + + + +pre-actions: +- install the CO-PCICAN card +- install and load COMEDI and the corresponding driver co_pcican.ko + (COMEDI sources are expected in /usr/src/comedi) + +- optionally: install the Xenomai package + (Xenomai sources are expected in /usr/xenomai) + + + +- unpack the package to your target (if not already done) + +- perform package configuration: + sh ./configure --can=copcican_comedi --timers=kernel --kerneldir='/lib/modules/$(shell uname -r)/build' + + optionally: use --timers=kernel_xeno for the realtime Xenomai timer functions + +- patch the sed "s:-I:-I$(src)/:g" statement to + 's:-I../..:-I/canopeninstalldir:g' in drivers/unix/Makefile + 's:-I..:-I/canopeninstalldir:g' in src/Makefile + The original statement did not run on my computer ! + +- build the CanFestival Unix library: + cd drivers/unix + make + +- build the CanFestival library: + cd src + make + make install + +- build the CO-PCICAN driver interface: + cd drivers/can_copcican_comedi + make + make install + +- build the example application (not for Xenomai): + cd examples/test_copcican_comedi + make + make install + +Run test_copcican_comedi with the insert.sh script to see it works... + +For Xenomai please use the example /usr/src/scale-rt-canopendemo of the SCALE-RT distribution. + + + +Copyright (C) 2010 Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + diff -r 9e496a2aadca -r b9274b595650 copcican_linux_howto.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/copcican_linux_howto.txt Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,49 @@ +HOW TO configure CanFestival for a CO-PCICAN card for linux: + + + +pre-actions: +- install the CO-PCICAN card +- install and load the user space driver co_pcicanext.ko + + + +- unpack the package to your target (if not already done) + +- create empty file: + touch /usr/local/lib/libcanfestival_can_copcican_linux.so + +- perform package configuration: + sh ./configure --can=copcican_linux + +- build the CanFestival library: + cd src + make + make install + +- build the CanFestival Unix library: + cd drivers/unix + make + make install + +BUGFIX: + copy library into build directory back: + cp /usr/local/lib/libcanfestival_unix.a drivers/unix + +- build the CO-PCICAN driver interface: + cd drivers/can_copcican_linux + make + make install + +- build the example application: + cd examples/test_copcican_linux + make + +Run test_copcican_linux to see it works... + + + +Copyright (C) 2010 Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_comedi/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_comedi/Makefile.in Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,60 @@ +#! gmake + +# +# Copyright (C) 2010 Cosateq GmbH & Co.KG +# http://www.cosateq.com/ +# http://www.scale-rt.com/ +# +# This file is part of canfestival, a library implementing the canopen +# stack +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +#ifneq ($(KERNELRELEASE),) +# Kbuild part of Makefile +TARGET = SUB_TARGET +CAN_DRIVER = SUB_CAN_DRIVER +TIMERS_DRIVER = SUB_TIMERS_DRIVER + +EXTRA_CFLAGS := -I$(src)/../../include +EXTRA_CFLAGS += -I$(src)/../../include/$(TARGET) +EXTRA_CFLAGS += -I$(src)/../../include/$(CAN_DRIVER) +EXTRA_CFLAGS += -I/usr/src/comedi/include +EXTRA_CFLAGS += SUB_PROG_CFLAGS + +obj-m := can_copcican_comedi.o +can_copcican_comediko-objs = $(CAN_DRIVER).o + +#else +# Normal Makefile +PREFIX = SUB_PREFIX +KERNELDIR := SUB_KERNELDIR + +all: driver + +driver: + $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(shell pwd) clean + rm -f Module.symvers + +mrproper: clean + +install: + $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_install + +#endif diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_comedi/can_copcican_comedi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_comedi/can_copcican_comedi.c Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,490 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + COMEDI interface for CO-PCICAN card. +*/ + +#include +#include +#include + +#define NEED_PRINT_MESSAGE +#include "can_driver.h" +#include "def.h" +#include "co_pcicanops.h" + +MODULE_LICENSE("GPL"); + +/* at the moment not threadsafe :-( */ +static unsigned char selectedChannelRx = 0, selectedChannelTx = 0; + +static int rt_strcmp( const char *src, const char *dst ) +{ + int ret = 0; + + while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst) + { + src++; + dst++; + } + + if( ret < 0 ) + { + ret = -1 ; + } + else + { + if( ret > 0 ) + ret = 1 ; + } + + return ret; +} + +static int TranslateBaudRate( char* optarg ) +{ + /* values see documentation of CO-PCICAN */ + if( !rt_strcmp( optarg, "1M" ) ) return 0; + if( !rt_strcmp( optarg, "800K" ) ) return 1; + if( !rt_strcmp( optarg, "500K" ) ) return 2; + if( !rt_strcmp( optarg, "250K" ) ) return 3; + if( !rt_strcmp( optarg, "125K" ) ) return 4; + if( !rt_strcmp( optarg, "100K" ) ) return 5; + if( !rt_strcmp( optarg, "83.3K" ) ) return 6; + if( !rt_strcmp( optarg, "10K" ) ) return 7; + + return -1; +} + +/*********CO-PCICAN specific functions to communicate with the board**********/ +typedef struct +{ + char used; + CAN_HANDLE fd; + void* receiveTask; + void* d; +} CANPort; /* taken from drivers/unix.c */ + +comedi_t* get_dev_of_port( CAN_PORT port ) +{ + CANPort *thisPort = (CANPort*)port; + CAN_HANDLE thisHandle; + comedi_t *dev; + + if( thisPort == NULL ) + { + MSG("can_copcican_comedi: get_dev_of_port(): thisPort is NULL\n"); + return NULL; + } + + thisHandle = thisPort->fd; + + if( thisHandle == NULL ) + { + MSG("can_copcican_comedi: get_dev_of_port(): thisHandle is NULL\n"); + return NULL; + } + + dev = (comedi_t*)thisHandle; + + /*MSG("can_copcican_comedi: get_dev_of_port(): handle is 0x%08x\n", (unsigned int)dev);*/ + + return dev; +} + +int co_pcican_enter_run_mode( comedi_t *dev ) +{ + unsigned int opcmd[15]; + unsigned int opcode = CMDQ_OPC_ENTER_RUN_MODE; + comedi_insn insn; + + if( dev == NULL ) + { + MSG("can_copcican_comedi: co_pcican_enter_run_mode(): dev is NULL\n"); + return 1; + } + + memset( opcmd, 0x00, sizeof(opcmd) ); + opcmd[0] = 0; + + memset( &insn, 0x00, sizeof(insn) ); + insn.insn = INSN_CONFIG; + insn.n = 1; + insn.data = (void*)opcmd; + insn.subdev = 0; + insn.unused[0] = opcode; /* in use for CO-PCICAN */ + + comedi_do_insn( dev, &insn ); + + opcmd[0] = 2; + insn.subdev = 2; + insn.unused[0] = opcode; /* in use for CO-PCICAN */ + + return comedi_do_insn( dev, &insn ); +} + +int co_pcican_enter_config_mode( comedi_t *dev ) +{ + unsigned int opcmd[15]; + unsigned int opcode = CMDQ_OPC_ENTER_CONFIG_MODE; + comedi_insn insn; + + if( dev == NULL ) + { + MSG("can_copcican_comedi: co_pcican_enter_config_mode(): dev is NULL\n"); + return 1; + } + + memset( opcmd, 0x00, sizeof(opcmd) ); + opcmd[0] = 0; + + memset( &insn, 0x00, sizeof(insn) ); + insn.insn = INSN_CONFIG; + insn.n = 1; + insn.data = (void*)opcmd; + insn.subdev = 0; + insn.unused[0] = opcode; /* in use for CO-PCICAN */ + + comedi_do_insn( dev, &insn ); + + opcmd[0] = 2; + insn.subdev = 2; + insn.unused[0] = opcode; /* in use for CO-PCICAN */ + + return comedi_do_insn( dev, &insn ); +} + +int co_pcican_select_channel( const unsigned char channel, const unsigned int direction ) +{ + if( channel >= NUM_CAN_CHANNELS ) + { + MSG("can_copcican_comedi: co_pcican_select_channel(): invalid channel\n"); + return -1; + } + + /* at the moment not threadsafe :-( */ + switch( direction ) + { + case RX: selectedChannelRx = channel; + break; + case TX: selectedChannelTx = channel; + break; + default: return -1; + } + + return 0; +} + +int co_pcican_configure_selected_channel( comedi_t *dev, s_BOARD *board, const unsigned int direction ) +{ + unsigned int opcmd[15]; + unsigned int opcode = CMDQ_OPC_SET_CONFIG_CHANNEL; + unsigned int selectedChannel; + comedi_insn insn; + + if( dev == NULL ) + { + MSG("can_copcican_comedi: co_pcican_configure_selected_channel(): dev is NULL\n"); + return -1; + } + + if( board == NULL ) + { + MSG("can_copcican_comedi: co_pcican_configure_selected_channel(): board is NULL\n"); + return -1; + } + + if( board->baudrate == NULL ) + { + MSG("can_copcican_comedi: co_pcican_configure_selected_channel(): baudrate is NULL\n"); + return -1; + } + + switch( direction ) + { + case RX: selectedChannel = selectedChannelRx; + break; + case TX: selectedChannel = selectedChannelTx; + break; + default: selectedChannel = 0xff; + } + + if( selectedChannel >= NUM_CAN_CHANNELS ) + { + MSG("can_copcican_comedi: co_pcican_configure_selected_channel(): invalid channel selected\n"); + return -1; + } + + memset( opcmd, 0x00, sizeof(opcmd) ); + opcmd[0] = selectedChannel; + opcmd[1] = TranslateBaudRate( board->baudrate ); + + memset( &insn, 0x00, sizeof(insn) ); + insn.insn = INSN_CONFIG; + insn.n = 1; + insn.data = (void*)opcmd; + + if( selectedChannel < 2 ) + insn.subdev = 0; + else + insn.subdev = 2; + + insn.unused[0] = opcode; /* in use for CO-PCICAN */ + + return comedi_do_insn( dev, &insn ); +} + +/*********functions which permit to communicate with the board****************/ +UNS8 canReceive_driver( CAN_HANDLE fd0, Message *m ) +{ + MESSAGE_T canmsg; + comedi_insn insn; + UNS8 ret = 0; + comedi_t *dev = (comedi_t*)fd0; + + if( dev == NULL ) + { + MSG("can_copcican_comedi: canReceive_driver(): dev is NULL\n"); + return 1; + } + + if( selectedChannelRx >= NUM_CAN_CHANNELS ) + { + MSG("can_copcican_comedi: canReceive_driver(): invalid channel selected\n"); + return 1; + } + + if( m == NULL ) + { + MSG("can_copcican_comedi: canReceive_driver(): message is NULL\n"); + return 1; + } + + memset( &canmsg, 0x00, sizeof(MESSAGE_T) ); + + memset( &insn, 0x00, sizeof(insn) ); + insn.insn = INSN_READ; + insn.n = 1; + insn.data = (void*)&canmsg; + + if( selectedChannelRx < 2 ) + insn.subdev = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DI, 0); + else + insn.subdev = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DI, 2); + + insn.unused[1] = selectedChannelRx; /* in use for CO-PCICAN */ + insn.unused[2] = sizeof(MESSAGE_T); /* in use for CO-PCICAN */ + + comedi_do_insn( dev, &insn ); + + if( canmsg.timestamp_lo == 0 ) + { + memset( m, 0x00, sizeof(Message) ); + + m->cob_id = 0xffff; /* set to invalid so nothing happens */ + } + else + { + m->len = canmsg.size; + m->cob_id = canmsg.id; + m->rtr = canmsg.type & MSG_RTR; + + if( !m->rtr ) + { + /* this is for safety */ + if( m->len > 8 ) + m->len = 8; + + memcpy( m->data, canmsg.data, m->len); + } + } + + return ret; +} + +/***************************************************************************/ +UNS8 canSend_driver( CAN_HANDLE fd0, Message *m ) +{ + MESSAGE_T canmsg; + comedi_insn insn; + UNS8 ret = 0; + comedi_t *dev = (comedi_t*)fd0; + + if( dev == NULL ) + { + MSG("can_copcican_comedi: canSend_driver(): dev is NULL\n"); + return 1; + } + + if( selectedChannelTx >= NUM_CAN_CHANNELS ) + { + MSG("can_copcican_comedi: canSend_driver(): invalid channel selected\n"); + return 1; + } + + if( m == NULL ) + { + MSG("can_copcican_comedi: canSend_driver(): message is NULL\n"); + return 1; + } + + memset( &canmsg, 0x00, sizeof(MESSAGE_T) ); + canmsg.size = m->len; + canmsg.id = m->cob_id; + + if( canmsg.id >= 0x800 ) + canmsg.type |= MSG_EXT; + + if( m->rtr ) + { + canmsg.type |= MSG_RTR; + } + else + { + /* this is for safety */ + if( canmsg.size > 8 ) + canmsg.size = 8; + + memcpy( canmsg.data, m->data, canmsg.size); + } + + memset( &insn, 0x00, sizeof(insn) ); + insn.insn = INSN_WRITE; + insn.n = 1; + insn.data = (void*)&canmsg; + + if( selectedChannelTx < 2 ) + insn.subdev = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DO, 0); + else + insn.subdev = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DO, 2); + + insn.unused[1] = selectedChannelTx; /* in use for CO-PCICAN */ + insn.unused[2] = sizeof(MESSAGE_T) - sizeof(unsigned long); /* in use for CO-PCICAN, no timestamp for tx */ + + if( comedi_do_insn( dev, &insn ) < 0 ) + ret = 1; + + return ret; +} + +/***************************************************************************/ +CAN_HANDLE canOpen_driver( s_BOARD *board ) +{ + comedi_t *dev; + + if( board == NULL ) + { + MSG("can_copcican_comedi: canOpen_driver(): board is NULL\n"); + return NULL; + } + + if( board->busname == NULL ) + { + MSG("can_copcican_comedi: canOpen_driver(): busname is NULL\n"); + return NULL; + } + + dev = comedi_open( board->busname ); + + /*MSG("can_copcican_comedi: canOpen_driver(): handle is 0x%08x\n", (unsigned int)dev);*/ + + return dev; +} + +/***************************************************************************/ +int canClose_driver( CAN_HANDLE fd0 ) +{ + comedi_t *dev = (comedi_t*)fd0; + + if( dev == NULL ) + { + MSG("can_copcican_comedi: canClose_driver(): dev is NULL\n"); + return 1; + } + + comedi_close( dev ); + + selectedChannelRx = 0; + selectedChannelTx = 0; + + return 0; +} + +/***************************************************************************/ +UNS8 canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud ) +{ + s_BOARD board; + UNS8 ret = 0; + comedi_t *dev = (comedi_t*)fd0; + + if( dev == NULL ) + { + MSG("can_copcican_comedi: canChangeBaudRate_driver(): dev is NULL\n"); + return 1; + } + + if( baud == NULL ) + { + MSG("can_copcican_comedi: canChangeBaudRate_driver(): baud is NULL\n"); + return 1; + } + + memset( &board, 0x00, sizeof(s_BOARD) ); + board.baudrate = baud; + + if( co_pcican_configure_selected_channel( dev, &board, RX ) < 0 ) + ret = 1; + + if( co_pcican_configure_selected_channel( dev, &board, TX ) < 0 ) + ret = 1; + + return ret; +} + +static int init(void) +{ + printk("can_copcican_comedi for CanFestival loaded\n"); + + return 0; +} + +static void exit(void) +{ + printk("can_copcican_comedi unloaded\n"); +} + +module_init(init); +module_exit(exit); + +EXPORT_SYMBOL(get_dev_of_port); +EXPORT_SYMBOL(co_pcican_enter_run_mode); +EXPORT_SYMBOL(co_pcican_enter_config_mode); +EXPORT_SYMBOL(co_pcican_select_channel); +EXPORT_SYMBOL(co_pcican_configure_selected_channel); +EXPORT_SYMBOL(canOpen_driver); +EXPORT_SYMBOL(canClose_driver); +EXPORT_SYMBOL(canSend_driver); +EXPORT_SYMBOL(canReceive_driver); +EXPORT_SYMBOL(canChangeBaudRate_driver); diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_comedi/co_pcicanops.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_comedi/co_pcicanops.h Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,63 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + COMEDI interface for CO-PCICAN card. +*/ + +#ifndef _CO_PCICANOPS_ +#define _CO_PCICANOPS_ + +#define NUM_CAN_CHANNELS 4 + +#define CMDQ_OPC_ENTER_RUN_MODE 0x01 +#define CMDQ_OPC_ENTER_CONFIG_MODE 0x02 +#define CMDQ_OPC_SET_CONFIG_CHANNEL 0xA2 + +typedef struct message_t +{ + unsigned long type; + unsigned long size; + unsigned long id; + unsigned char data[8]; + unsigned long timestamp_lo; + unsigned long timestamp_hi; +} MESSAGE_T; + +/*============================================================================= + directions + ===========================================================================*/ +#define RX 0 +#define TX 1 + +/*============================================================================= + supported types + ===========================================================================*/ +#define MSG_EXT 0x00000001 +#define MSG_RTR 0x00000002 + + + +#endif + diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_linux/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_linux/Makefile.in Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,70 @@ +#! gmake + +# +# Copyright (C) 2010 Cosateq GmbH & Co.KG +# http://www.cosateq.com/ +# http://www.scale-rt.com/ +# +# This file is part of canfestival, a library implementing the canopen +# stack +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +CC = SUB_CC +OPT_CFLAGS = -O2 +CFLAGS = SUB_OPT_CFLAGS +PROG_CFLAGS = SUB_PROG_CFLAGS +PREFIX = SUB_PREFIX +TARGET = SUB_TARGET +CAN_DRIVER = SUB_CAN_DRIVER +TIMERS_DRIVER = SUB_TIMERS_DRIVER +ENABLE_DLL_DRIVERS=SUB_ENABLE_DLL_DRIVERS +CAN_DLL_CFLAGS=SUB_CAN_DLL_CFLAGS + +INCLUDES = -I../../include -I../../include/$(TARGET) -I../../include/$(CAN_DRIVER) + +OBJS = $(CAN_DRIVER).o + +ifeq ($(ENABLE_DLL_DRIVERS),1) +CFLAGS += -fPIC +DRIVER = libcanfestival_$(CAN_DRIVER).so +else +DRIVER = $(OBJS) +endif + +TARGET_SOFILES = $(PREFIX)/lib/$(DRIVER) + +all: driver + +driver: $(DRIVER) + +%o: %c + $(CC) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ -c $< + +libcanfestival_$(CAN_DRIVER).so: $(OBJS) + $(CC) -shared -Wl,-soname,libcanfestival_$(CAN_DRIVER).so $(CAN_DLL_CFLAGS) -o $@ $< + +install: libcanfestival_$(CAN_DRIVER).so + mkdir -p $(PREFIX)/lib/ + cp $< $(PREFIX)/lib/ + +uninstall: + rm -f $(TARGET_SOFILES) + +clean: + rm -f $(OBJS) + +mrproper: clean diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_linux/can_copcican_linux.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_linux/can_copcican_linux.c Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,415 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + CAN driver interface for CO-PCICAN card. +*/ + +#include +#include +#include + +#define NEED_PRINT_MESSAGE +#include "can_driver.h" +#include "def.h" +#include "co_pcicanops.h" + +/* at the moment not threadsafe :-( */ +static unsigned char selectedChannelRx = 0, selectedChannelTx = 0; + +static int TranslateBaudRate( char* optarg ) +{ + /* values see documentation of CO-PCICAN */ + if( !strcmp( optarg, "1M" ) ) return 0; + if( !strcmp( optarg, "800K" ) ) return 1; + if( !strcmp( optarg, "500K" ) ) return 2; + if( !strcmp( optarg, "250K" ) ) return 3; + if( !strcmp( optarg, "125K" ) ) return 4; + if( !strcmp( optarg, "100K" ) ) return 5; + if( !strcmp( optarg, "83.3K" ) ) return 6; + if( !strcmp( optarg, "10K" ) ) return 7; + + return -1; +} + +/*********CO-PCICAN specific functions to communicate with the board**********/ +typedef struct +{ + char used; + CAN_HANDLE fd; + void* receiveTask; + void* d; +} CANPort; /* taken from drivers/unix.c */ + +int get_fd_of_port( CAN_PORT port ) +{ + CANPort *thisPort = (CANPort*)port; + CAN_HANDLE thisHandle; + int *pfd; + + if( thisPort == NULL ) + { + MSG("can_copcican_linux: get_fd_of_port(): thisPort is NULL\n"); + return -1; + } + + thisHandle = thisPort->fd; + + if( thisHandle == NULL ) + { + MSG("can_copcican_linux: get_fd_of_port(): thisHandle is NULL\n"); + return -1; + } + + pfd = (int*)thisHandle; + + /*MSG("can_copcican_linux: get_fd_of_port(): handle is %d\n", *pfd);*/ + + return *pfd; +} + +int co_pcican_enter_run_mode( const int fd ) +{ + co_pcican_config_t board_config; + + if( fd < 0 ) + { + MSG("can_copcican_linux: co_pcican_enter_run_mode(): invalid file descriptor\n"); + return -1; + } + + memset( &board_config, 0x00, sizeof(co_pcican_config_t) ); + board_config.opcode = CMDQ_OPC_ENTER_RUN_MODE; + + return ioctl( fd, CAN_CONFIG, &board_config ); +} + +int co_pcican_enter_config_mode( const int fd ) +{ + co_pcican_config_t board_config; + + if( fd < 0 ) + { + MSG("can_copcican_linux: co_pcican_enter_config_mode(): invalid file descriptor\n"); + return -1; + } + + memset( &board_config, 0x00, sizeof(co_pcican_config_t) ); + board_config.opcode = CMDQ_OPC_ENTER_CONFIG_MODE; + + return ioctl( fd, CAN_CONFIG, &board_config ); +} + +int co_pcican_select_channel( const unsigned char channel, const unsigned int direction ) +{ + if( channel >= NUM_CAN_CHANNELS ) + { + MSG("can_copcican_linux: co_pcican_select_channel(): invalid channel\n"); + return -1; + } + + /* at the moment not threadsafe :-( */ + switch( direction ) + { + case RX: selectedChannelRx = channel; + break; + case TX: selectedChannelTx = channel; + break; + default: return -1; + } + + return 0; +} + +int co_pcican_configure_selected_channel( const int fd, s_BOARD *board, const unsigned int direction ) +{ + co_pcican_config_t board_config; + unsigned int selectedChannel; + + if( fd < 0 ) + { + MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid file descriptor\n"); + return -1; + } + + if( board == NULL ) + { + MSG("can_copcican_linux: co_pcican_configure_selected_channel(): board is NULL\n"); + return -1; + } + + if( board->baudrate == NULL ) + { + MSG("can_copcican_linux: co_pcican_configure_selected_channel(): baudrate is NULL\n"); + return -1; + } + + switch( direction ) + { + case RX: selectedChannel = selectedChannelRx; + break; + case TX: selectedChannel = selectedChannelTx; + break; + default: selectedChannel = 0xff; + } + + if( selectedChannel >= NUM_CAN_CHANNELS ) + { + MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid channel selected\n"); + return -1; + } + + memset( &board_config, 0x00, sizeof(co_pcican_config_t) ); + board_config.opcode = CMDQ_OPC_SET_CONFIG_CHANNEL; + board_config.param[0] = selectedChannel; + board_config.param[1] = TranslateBaudRate( board->baudrate ); + + return ioctl( fd, CAN_CONFIG, &board_config ); +} + +/*********functions which permit to communicate with the board****************/ +UNS8 canReceive_driver( CAN_HANDLE fd0, Message *m ) +{ + co_pcican_message_t canmsg; + UNS8 ret = 0; + int *pfd = (int*)fd0; + + if( pfd == NULL ) + { + MSG("can_copcican_linux: canReceive_driver(): file descriptor is NULL\n"); + return 1; + } + + if( *pfd < 0 ) + { + MSG("can_copcican_linux: canReceive_driver(): invalid file descriptor\n"); + return 1; + } + + if( selectedChannelRx >= NUM_CAN_CHANNELS ) + { + MSG("can_copcican_linux: canReceive_driver(): invalid channel selected\n"); + return 1; + } + + if( m == NULL ) + { + MSG("can_copcican_linux: canReceive_driver(): message is NULL\n"); + return 1; + } + + memset( &canmsg, 0x00, sizeof(co_pcican_message_t) ); + canmsg.channelnum = selectedChannelRx; + + ioctl( *pfd, CAN_READ, &canmsg ); + + if( canmsg.timestamp_lo == 0 ) + { + memset( m, 0x00, sizeof(Message) ); + + m->cob_id = 0xffff; /* set to invalid so nothing happens */ + } + else + { + m->len = canmsg.size; + m->cob_id = canmsg.id; + m->rtr = canmsg.type & MSG_RTR; + + if( !m->rtr ) + { + /* this is for safety */ + if( m->len > 8 ) + m->len = 8; + + memcpy( m->data, canmsg.data, m->len); + } + } + + return ret; +} + +/***************************************************************************/ +UNS8 canSend_driver( CAN_HANDLE fd0, Message *m ) +{ + co_pcican_message_t canmsg; + UNS8 ret = 0; + int *pfd = (int*)fd0; + + if( pfd == NULL ) + { + MSG("can_copcican_linux: canSend_driver(): file descriptor is NULL\n"); + return 1; + } + + if( *pfd < 0 ) + { + MSG("can_copcican_linux: canSend_driver(): invalid file descriptor\n"); + return 1; + } + + if( selectedChannelTx >= NUM_CAN_CHANNELS ) + { + MSG("can_copcican_linux: canSend_driver(): invalid channel selected\n"); + return 1; + } + + if( m == NULL ) + { + MSG("can_copcican_linux: canSend_driver(): message is NULL\n"); + return 1; + } + + memset( &canmsg, 0x00, sizeof(co_pcican_message_t) ); + canmsg.channelnum = selectedChannelTx; + canmsg.size = m->len; + canmsg.id = m->cob_id; + + if( canmsg.id >= 0x800 ) + canmsg.type |= MSG_EXT; + + if( m->rtr ) + { + canmsg.type |= MSG_RTR; + } + else + { + /* this is for safety */ + if( canmsg.size > 8 ) + canmsg.size = 8; + + memcpy( canmsg.data, m->data, canmsg.size); + } + + if( ioctl( *pfd, CAN_WRITE, &canmsg ) < 0 ) + ret = 1; + + return ret; +} + +/***************************************************************************/ +CAN_HANDLE canOpen_driver( s_BOARD *board ) +{ + int *pfd; + + if( board == NULL ) + { + MSG("can_copcican_linux: canOpen_driver(): board is NULL\n"); + return NULL; + } + + if( board->busname == NULL ) + { + MSG("can_copcican_linux: canOpen_driver(): busname is NULL\n"); + return NULL; + } + + /* create dynamically to avoid global variable */ + pfd = (int*)malloc( sizeof(int) ); + + if( pfd == NULL ) + { + MSG("can_copcican_linux: canOpen_driver(): file descriptor is NULL\n"); + return NULL; + } + + *pfd = open( board->busname, O_RDWR, 0 ); + + if( *pfd < 0 ) + { + MSG("can_copcican_linux: canOpen_driver(): invalid file descriptor\n"); + + /* clear resources if open failed */ + free( pfd ); + pfd = NULL; + } + + /*MSG("can_copcican_linux: canOpen_driver(): handle is %d\n", *pfd);*/ + + return (CAN_HANDLE)pfd; +} + +/***************************************************************************/ +int canClose_driver( CAN_HANDLE fd0 ) +{ + int *pfd = (int*)fd0; + + if( pfd == NULL ) + { + MSG("can_copcican_linux: canClose_driver(): file descriptor is NULL\n"); + return -1; + } + + if( *pfd < 0 ) + { + MSG("can_copcican_linux: canClose_driver(): invalid file descriptor\n"); + return -1; + } + + close( *pfd ); + free( pfd ); + pfd = NULL; + + selectedChannelRx = 0; + selectedChannelTx = 0; + + return 0; +} + +/***************************************************************************/ +UNS8 canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud ) +{ + s_BOARD board; + UNS8 ret = 0; + int *pfd = (int*)fd0; + + if( pfd == NULL ) + { + MSG("can_copcican_linux: canChangeBaudRate_driver(): file descriptor is NULL\n"); + return 1; + } + + if( *pfd < 0 ) + { + MSG("can_copcican_linux: canChangeBaudRate_driver(): invalid file descriptor\n"); + return 1; + } + + if( baud == NULL ) + { + MSG("can_copcican_linux: canChangeBaudRate_driver(): baud is NULL\n"); + return 1; + } + + memset( &board, 0x00, sizeof(s_BOARD) ); + board.baudrate = baud; + + if( co_pcican_configure_selected_channel( *pfd, &board, RX ) < 0 ) + ret = 1; + + if( co_pcican_configure_selected_channel( *pfd, &board, TX ) < 0 ) + ret = 1; + + return ret; +} + diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_linux/co_pcicanops.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_linux/co_pcicanops.h Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,77 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + CAN driver interface for CO-PCICAN card. +*/ + +#ifndef _CO_PCICANOPS_ +#define _CO_PCICANOPS_ + +#define NUM_CAN_CHANNELS 4 + +#define CMDQ_OPC_ENTER_RUN_MODE 0x01 +#define CMDQ_OPC_ENTER_CONFIG_MODE 0x02 +#define CMDQ_OPC_SET_CONFIG_CHANNEL 0xA2 + +typedef struct +{ + unsigned char opcode; + unsigned long param[15]; +} co_pcican_config_t; + +typedef struct +{ + unsigned char channelnum; + unsigned long type; + unsigned long size; + unsigned long id; + unsigned char data[8]; + unsigned long timestamp_lo; + unsigned long timestamp_hi; +} co_pcican_message_t; + +/*============================================================================= + supported operations + ===========================================================================*/ +#define CAN_CONFIG 2 +#define CAN_WRITE 3 +#define CAN_READ 4 + +/*============================================================================= + directions + ===========================================================================*/ +#define RX 0 +#define TX 1 + +/*============================================================================= + supported types + ===========================================================================*/ +#define MSG_EXT 0x00000001 +#define MSG_RTR 0x00000002 + + + +#endif + diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/ReadMe.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/ReadMe.txt Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,48 @@ +======================================================================== + DYNAMIC LINK LIBRARY : can_copcican_win32 Project Overview +======================================================================== + +AppWizard has created this can_copcican_win32 DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your can_copcican_win32 application. + + +can_copcican_win32.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +can_copcican_win32.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +can_copcican_win32.cpp + This is the main DLL source file. + + When created, this DLL does not export any symbols. As a result, it + will not produce a .lib file when it is built. If you wish this project + to be a project dependency of some other project, you will either need to + add code to export some symbols from the DLL so that an export library + will be produced, or you can set the Ignore Input Library property to Yes + on the General propert page of the Linker folder in the project's Property + Pages dialog box. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named can_copcican_win32.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/can_copcican_win32.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/can_copcican_win32.cpp Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,249 @@ +// can_copcican_win32.cpp : Defines the exported functions for the DLL application. +// + + +#include "stdafx.h" + +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + CAN driver interface for CO-PCICAN card. +*/ + +#include +//#include +#include + +//#define NEED_PRINT_MESSAGE +static int initdone = 0; + +inline void * maskDevID(int devId){ return ((void*)( (devId & 0x0000000F) | 0xC05A0000)); } +inline int unmaskDevID(void * Ptr){ return ((int)((int)Ptr & 0x0000000F)); } + +/* at the moment not threadsafe :-( */ +static unsigned char selectedChannelRx = 1, selectedChannelTx = 1; + +static cosateq::devices::can::co_baudrate_t TranslateBaudRate( char* optarg ) +{ + /* values see documentation of CO-PCICAN */ + if( !strcmp( optarg, "1M" ) ) return cosateq::devices::can::CO_BAUD_1M; + if( !strcmp( optarg, "800K" ) ) return cosateq::devices::can::CO_BAUD_800k; + if( !strcmp( optarg, "500K" ) ) return cosateq::devices::can::CO_BAUD_500k; + if( !strcmp( optarg, "250K" ) ) return cosateq::devices::can::CO_BAUD_250k; + if( !strcmp( optarg, "125K" ) ) return cosateq::devices::can::CO_BAUD_125k; + if( !strcmp( optarg, "100K" ) ) return cosateq::devices::can::CO_BAUD_100k; + if( !strcmp( optarg, "83.3K" ) ) return cosateq::devices::can::CO_BAUD_83k; + if( !strcmp( optarg, "10K" ) ) return cosateq::devices::can::CO_BAUD_10k; + + return (cosateq::devices::can::co_baudrate_t)-1; +} + +int co_pcican_select_channel( const unsigned char channel, const unsigned int direction ) +{ + if( channel >= CHANNELS ) + { + MSG("can_copcican_linux: co_pcican_select_channel(): invalid channel\n"); + return -1; + } + + /* at the moment not threadsafe :-( */ + switch( direction ) + { + case cosateq::devices::can::CO_CAN_RX: selectedChannelRx = channel; + break; + case cosateq::devices::can::CO_CAN_TX: selectedChannelTx = channel; + break; + default: return -1; + } + + return 0; +} + +int co_pcican_configure_selected_channel( const int fd, s_BOARD *board, const unsigned int direction ) +{ + unsigned int selectedChannel; + int ret = 0; + + if( fd < 0 ) + { + MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid file descriptor\n"); + return -1; + } + + if( board == NULL ) + { + MSG("can_copcican_linux: co_pcican_configure_selected_channel(): board is NULL\n"); + return -1; + } + + if( board->baudrate == NULL ) + { + MSG("can_copcican_linux: co_pcican_configure_selected_channel(): baudrate is NULL\n"); + return -1; + } + + switch( direction ) + { + case cosateq::devices::can::CO_CAN_RX: selectedChannel = selectedChannelRx; + break; + case cosateq::devices::can::CO_CAN_TX: selectedChannel = selectedChannelTx; + break; + default: selectedChannel = 0xff; + } + + if( selectedChannel >= CHANNELS ) + { + MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid channel selected\n"); + return -1; + } + + ret = can_setChannelConfig( TranslateBaudRate( board->baudrate ),0x0,unmaskDevID((void*)fd),selectedChannel); + if ( ret != 0 ) { + can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2); + return -ret; + }else{ + ret = can_setIrqMode(unmaskDevID((void*)fd),selectedChannel); + can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2); + } + return ret; +} + +/*********functions which permit to communicate with the board****************/ + +UNS8 __stdcall canReceive_driver( CAN_HANDLE fd0, Message *m ) +{ + cosateq::devices::can::co_can_packet_t p; + int ret = 0; + + if ( !m ) + return 0; + + memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t)); + ret = can_receive(&p,unmaskDevID(fd0),selectedChannelRx); + //printf("rec: %d\n",ret); + if ( ret != 0 ) + return 1; + + //printf("rec2: %d\n",ret); + if ( p.size > 8 ) + p.size = 8; + + if ( !(p.type & MSG_RTR ) ) + memcpy(m->data,p.data,p.size); + + m->cob_id = p.id; + m->len = p.size; + m->rtr = p.type & MSG_RTR; + + return 0; +} + +/***************************************************************************/ + +UNS8 __stdcall canSend_driver( CAN_HANDLE fd0, Message *m ) +{ + cosateq::devices::can::co_can_packet_t p; + + if ( !m ) + return 0; + memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t)); + p.id = m->cob_id; + p.size = (m->len > 8) ? 8 : m->len; + p.type = ( m->rtr ) ? 0x2:0x0; + if ( p.id > 0x800 ) + p.type |= MSG_EXT; + memcpy(p.data,m->data,p.size); + + return can_send(&p,unmaskDevID(fd0),selectedChannelTx); +} + + + +/***************************************************************************/ + +UNS8 __stdcall canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud ) +{ + UNS8 ret = 0; + + ret = can_enterCfgMode(unmaskDevID(fd0),0); + if ( ret != 0) + MSG("Enter config mode for Channelpair 0 failed in Function %s! Error: %d\n",__FUNCTION__,ret); + ret = can_enterCfgMode(unmaskDevID(fd0),1); + if ( ret != 0) + MSG("Enter config mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret); + + for ( int i = 0; i < 4; i++ ) { + ret = can_setChannelConfig(TranslateBaudRate(baud),0x0,unmaskDevID(fd0),i); + if ( ret != 0) + MSG("Set config for channel %d failed in Function %s! Error: %d\n",i,__FUNCTION__,ret); + can_setIrqMode(unmaskDevID(fd0),i); + } + ret = can_enterRunMode(unmaskDevID(fd0),0); + if ( ret != 0) + MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret); + + ret = can_enterRunMode(unmaskDevID(fd0),1); + if ( ret != 0) + MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret); + + return ret; +} + +CAN_HANDLE __stdcall canOpen_driver( s_BOARD *board ) +{ + int ret = 0; + int devId = 0; + if ( !board ) + return NULL; + if ( !board->busname ) + return NULL; + //TODO find out how boardname resolves + + //printf("BOARD: 0x%x %s\n",board,board->busname); + //sscanf_s(board->busname,"%d",&devId); + + if ( devId < 0 || devId > 15 ) + return NULL; + + //return (can_HANDLE)NULL; + if ( !initdone ) { + can_init(); + initdone = 1; + } + + ret = can_open(devId); + if ( ret < 0 ) + return (CAN_HANDLE)NULL; + + canChangeBaudRate_driver( maskDevID(devId),board->baudrate ); + + return maskDevID(devId); +} + +int __stdcall canClose_driver(CAN_HANDLE fd0 ) +{ + return can_close(unmaskDevID(fd0)); +} + diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/can_copcican_win32.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/can_copcican_win32.def Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,28 @@ +; This file is part of CanFestival, a library implementing CanOpen Stack. +; +; CanFestival Copyright (C): Edouard TISSERANT and Francis DUPIN +; CanFestival Win32 port Copyright (C) 2007 Leonid Tochinski, ChattenAssociates, Inc. +; +; See COPYING file for copyrights details. +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2.1 of the License, or (at your option) any later version. +; +; This library 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 +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this library; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +LIBRARY can_copcican_win32 + +EXPORTS + canReceive_driver + canSend_driver + canOpen_driver + canClose_driver \ No newline at end of file diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/can_copcican_win32.vcxproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/can_copcican_win32.vcxproj Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,104 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D} + Win32Proj + can_copcican_win32 + + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + + + + + + + + + + + true + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;CAN_COPCICAN_WIN32_EXPORTS;%(PreprocessorDefinitions) + $(SolutionDir)\include;$(SolutionDir)\include\win32;$(SolutionDir)\..\driver_windows\Cosateq_4Port_CAN_SDK\include;%(AdditionalIncludeDirectories) + + + Windows + true + $(SolutionDir)\..\driver_windows\Cosateq_4Port_CAN_SDK\lib\co_can_lib.lib;%(AdditionalDependencies) + can_copcican_win32.def + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;CAN_COPCICAN_WIN32_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + can_copcican_win32.def + + + + + + + + + + + + + + false + + + false + + + + + Create + Create + + + + + + \ No newline at end of file diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/can_copcican_win32.vcxproj.filters --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/can_copcican_win32.vcxproj.filters Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + Source Files + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/can_copcican_win32.vcxproj.user --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/can_copcican_win32.vcxproj.user Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/dllmain.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/dllmain.cpp Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,22 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include "stdafx.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + + break; + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + + break; + } + return TRUE; +} + diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/stdafx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/stdafx.cpp Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// can_copcican_win32.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/stdafx.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/stdafx.h Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,20 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include + + +//#include "co_can.h" +#include "public.h" +#include "can_driver.h" +#include "co_can_cinterface.h" + +// TODO: reference additional headers your program requires here diff -r 9e496a2aadca -r b9274b595650 drivers/can_copcican_win32/targetver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/can_copcican_win32/targetver.h Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff -r 9e496a2aadca -r b9274b595650 drivers/timers_kernel/timers_kernel.c --- a/drivers/timers_kernel/timers_kernel.c Fri Nov 12 22:02:32 2010 +0100 +++ b/drivers/timers_kernel/timers_kernel.c Fri Nov 12 22:24:06 2010 +0100 @@ -1,5 +1,5 @@ /* -This file is part of CanFestival, a library implementing CanOpen Stack. +This file is part of CanFestival, a library implementing CanOpen Stack. Copyright (C): Edouard TISSERANT and Francis DUPIN @@ -111,5 +111,9 @@ void WaitReceiveTaskEnd(TASK_HANDLE *Thread) { - force_sig (SIGTERM, *Thread); + /* join thread here because force_sig() does not work */ + while((*Thread)->state <= 0) + { + ; /* >0 means stopped */ + } } diff -r 9e496a2aadca -r b9274b595650 drivers/timers_kernel_xeno/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/timers_kernel_xeno/Makefile.in Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,59 @@ +#! gmake + +# +# Copyright (C) 2010 Cosateq GmbH & Co.KG +# http://www.cosateq.com/ +# http://www.scale-rt.com/ +# +# This file is part of canfestival, a library implementing the canopen +# stack +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +#ifneq ($(KERNELRELEASE),) +# Kbuild part of Makefile +TARGET = SUB_TARGET +CAN_DRIVER = SUB_CAN_DRIVER +TIMERS_DRIVER = SUB_TIMERS_DRIVER + +EXTRA_CFLAGS := -I$(src)/../../include +EXTRA_CFLAGS += -I$(src)/../../include/$(TARGET) +EXTRA_CFLAGS += -I$(src)/../../include/$(CAN_DRIVER) +EXTRA_CFLAGS += -I$(src)/../../include/$(TIMERS_DRIVER) +EXTRA_CFLAGS += SUB_PROG_CFLAGS + +obj-m := $(TIMERS_DRIVER).o + +#else +# Normal Makefile +PREFIX = SUB_PREFIX +KERNELDIR := SUB_KERNELDIR + +all: driver + +driver: + $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(shell pwd) clean + rm -f Module.symvers + +mrproper: clean + +install: + + +#endif diff -r 9e496a2aadca -r b9274b595650 drivers/timers_kernel_xeno/timers_kernel_xeno.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/timers_kernel_xeno/timers_kernel_xeno.c Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,288 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "applicfg.h" +#include "can_driver.h" +#include "timer.h" + +#define TIMERLOOP_TASK_CREATED 1 + +TimerCallback_t exitall; + +RT_MUTEX condition_mutex; +RT_SEM CanFestival_mutex; +RT_SEM control_task; +RT_COND timer_set; +RT_TASK timerloop_task; + +RTIME last_time_read; +RTIME last_occured_alarm; +RTIME last_timeout_set; + +int stop_timer = 0; + +/** + * Init Mutex, Semaphores and Condition variable + */ +void TimerInit(void) +{ + int ret = 0; + char taskname[32]; + + // lock process in to RAM + //mlockall(MCL_CURRENT | MCL_FUTURE); + + snprintf(taskname, sizeof(taskname), "S1-%d", current->pid); + rt_sem_create(&CanFestival_mutex, taskname, 1, S_FIFO); + + snprintf(taskname, sizeof(taskname), "S2-%d", current->pid); + rt_sem_create(&control_task, taskname, 0, S_FIFO); + + snprintf(taskname, sizeof(taskname), "M1-%d", current->pid); + rt_mutex_create(&condition_mutex, taskname); + + snprintf(taskname, sizeof(taskname), "C1-%d", current->pid); + rt_cond_create(&timer_set, taskname); +} + +/** + * Stop Timer Task + * @param exitfunction + */ +void StopTimerLoop(TimerCallback_t exitfunction) +{ + exitall = exitfunction; + stop_timer = 1; + rt_cond_signal(&timer_set); +} + +void cleanup_all(void) +{ + /* normally this will fail with a non-periodic task that has already ended at this time */ + if (rt_task_suspend(&timerloop_task) != 0){ + printk("Failed to join with Timerloop task\n"); + } + rt_task_delete(&timerloop_task); +} + +/** + * Clean all Semaphores, mutex, condition variable and main task + */ +void TimerCleanup(void) +{ + rt_sem_delete(&CanFestival_mutex); + rt_mutex_delete(&condition_mutex); + rt_cond_delete(&timer_set); + rt_sem_delete(&control_task); + + /* normally this will fail with a non-periodic task that has already ended at this time */ + if (rt_task_suspend(&timerloop_task) != 0){ + printk("Failed to join with Timerloop task\n"); + } + rt_task_delete(&timerloop_task); +} + +/** + * Take a semaphore + */ +void EnterMutex(void) +{ + rt_sem_p(&CanFestival_mutex, TM_INFINITE); +} + +/** + * Signaling a semaphore + */ +void LeaveMutex(void) +{ + rt_sem_v(&CanFestival_mutex); +} + +static TimerCallback_t init_callback; + +/** + * Timer Task + */ +void timerloop_task_proc(void *arg) +{ + int ret = 0; + + getElapsedTime(); + last_timeout_set = 0; + last_occured_alarm = last_time_read; + + /* trigger first alarm */ + SetAlarm(NULL, 0, init_callback, 0, 0); + RTIME current_time; + RTIME real_alarm; + do{ + + rt_mutex_acquire(&condition_mutex, TM_INFINITE); + if(last_timeout_set == TIMEVAL_MAX) + { + ret = rt_cond_wait( + &timer_set, + &condition_mutex, + TM_INFINITE + ); /* Then sleep until next message*/ + rt_mutex_release(&condition_mutex); + }else{ + current_time = rt_timer_read(); + real_alarm = last_time_read + last_timeout_set; + ret = rt_cond_wait( /* sleep until next deadline */ + &timer_set, + &condition_mutex, + (real_alarm - current_time)); /* else alarm consider expired */ + if(ret == -ETIMEDOUT){ + last_occured_alarm = real_alarm; + rt_mutex_release(&condition_mutex); + EnterMutex(); + TimeDispatch(); + LeaveMutex(); + }else{ + rt_mutex_release(&condition_mutex); + } + } + }while ((ret == 0 || ret == -EINTR || ret == -ETIMEDOUT) && !stop_timer); + + if(exitall){ + EnterMutex(); + exitall(NULL,0); + LeaveMutex(); + } +} + +/** + * Create the Timer Task + * @param _init_callback + */ +void StartTimerLoop(TimerCallback_t _init_callback) +{ + int ret = 0; + stop_timer = 0; + init_callback = _init_callback; + + char taskname[32]; + snprintf(taskname, sizeof(taskname), "timerloop-%d", current->pid); + + /* create timerloop_task */ + ret = rt_task_create(&timerloop_task, taskname, 0, 50, 0); /* T_JOINABLE only in user space */ + if (ret) { + printk("Failed to create timerloop_task, code %d\n",ret); + return; + } + + /* start timerloop_task */ + ret = rt_task_start(&timerloop_task,&timerloop_task_proc,NULL); + if (ret) { + printk("Failed to start timerloop_task, code %u\n",ret); + goto error; + } + + return; + +error: + cleanup_all(); +} + +/** + * Create the CAN Receiver Task + * @param fd0 CAN port + * @param *ReceiveLoop_task CAN receiver task + * @param *ReceiveLoop_task_proc CAN receiver function + */ +void CreateReceiveTask(CAN_PORT fd0, TASK_HANDLE *ReceiveLoop_task, void* ReceiveLoop_task_proc) +{ + int ret; + static int id = 0; + char taskname[32]; + snprintf(taskname, sizeof(taskname), "canloop%d-%d", id, current->pid); + id++; + + /* create ReceiveLoop_task */ + ret = rt_task_create(ReceiveLoop_task,taskname,0,50,0); /* T_JOINABLE only in user space */ + if (ret) { + printk("Failed to create ReceiveLoop_task number %d, code %d\n", id, ret); + return; + } + + /* periodic task for Xenomai kernel realtime */ + rt_task_set_periodic(ReceiveLoop_task, 0, 1 * 1000 * 1000); /* 1ms */ + + /* start ReceiveLoop_task */ + ret = rt_task_start(ReceiveLoop_task, ReceiveLoop_task_proc,(void*)fd0); + if (ret) { + printk("Failed to start ReceiveLoop_task number %d, code %d\n", id, ret); + return; + } + rt_sem_v(&control_task); +} + +/** + * Wait for the CAN Receiver Task end + * @param *ReceiveLoop_task CAN receiver thread + */ +void WaitReceiveTaskEnd(TASK_HANDLE *ReceiveLoop_task) +{ + /* normally this will fail with a non-periodic task that has already ended at this time */ + if (rt_task_suspend(ReceiveLoop_task) != 0){ + printk("Failed to join with Receive task\n"); + } + rt_task_delete(ReceiveLoop_task); +} + +/** + * Set timer for the next wakeup + * @param value + */ +void setTimer(TIMEVAL value) +{ + rt_mutex_acquire(&condition_mutex, TM_INFINITE); + last_timeout_set = value; + rt_mutex_release(&condition_mutex); + rt_cond_signal(&timer_set); +} + +/** + * Get the elapsed time since the last alarm + * @return a time in nanoseconds + */ +TIMEVAL getElapsedTime(void) +{ + RTIME res; + rt_mutex_acquire(&condition_mutex, TM_INFINITE); + last_time_read = rt_timer_read(); + res = last_time_read - last_occured_alarm; + rt_mutex_release(&condition_mutex); + return res; +} diff -r 9e496a2aadca -r b9274b595650 drivers/timers_win32/timers_win32.c --- a/drivers/timers_win32/timers_win32.c Fri Nov 12 22:02:32 2010 +0100 +++ b/drivers/timers_win32/timers_win32.c Fri Nov 12 22:24:06 2010 +0100 @@ -77,7 +77,11 @@ CloseHandle(*Thread); } +#if !defined(WIN32) || defined(__CYGWIN__) int TimerThreadLoop(void) +#else +DWORD TimerThreadLoop(LPVOID arg) +#endif { diff -r 9e496a2aadca -r b9274b595650 drivers/unix/Makefile.in --- a/drivers/unix/Makefile.in Fri Nov 12 22:02:32 2010 +0100 +++ b/drivers/unix/Makefile.in Fri Nov 12 22:24:06 2010 +0100 @@ -2,24 +2,24 @@ # # Copyright (C) 2006 Laurent Bessard -# +# # This file is part of canfestival, a library implementing the canopen # stack -# +# # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. -# +# # This library 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 # Lesser General Public License for more details. -# +# # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# +# #ifneq ($(KERNELRELEASE),) # Kbuild part of Makefile @@ -56,6 +56,13 @@ all: driver ifeq ($(TIMERS_DRIVER), timers_kernel) +USE_KERNEL_TIMER = true +endif +ifeq ($(TIMERS_DRIVER), timers_kernel_xeno) +USE_KERNEL_TIMER = true +endif + +ifeq ($(USE_KERNEL_TIMER), true) OBJS := $(shell echo $(OBJS) | sed "s:$(TARGET)_::g") EXTRA_CFLAGS := $(shell echo $(INCLUDES) | sed "s:-I:-I$(src)/:g") EXTRA_CFLAGS += $(PROG_CFLAGS) @@ -75,7 +82,7 @@ rm -f Module.symvers install: - + else CFLAGS = SUB_OPT_CFLAGS diff -r 9e496a2aadca -r b9274b595650 drivers/unix/unix.c --- a/drivers/unix/unix.c Fri Nov 12 22:02:32 2010 +0100 +++ b/drivers/unix/unix.c Fri Nov 12 22:24:06 2010 +0100 @@ -1,5 +1,5 @@ /* -This file is part of CanFestival, a library implementing CanOpen Stack. +This file is part of CanFestival, a library implementing CanOpen Stack. Copyright (C): Edouard TISSERANT and Francis DUPIN @@ -26,6 +26,7 @@ #else #include #endif +#include #ifndef NOT_USE_DYNAMIC_LOADING #define DLL_CALL(funcname) (* funcname##_driver) @@ -95,7 +96,7 @@ { LIB_HANDLE handle = NULL; char *error; - + if(handle==NULL) { @@ -106,7 +107,7 @@ fprintf (stderr, "%s\n", dlerror()); return NULL; } - + /*Get function ptr*/ DLSYM(canReceive) DLSYM(canSend) @@ -142,7 +143,7 @@ res = DLL_CALL(canSend)(((CANPort*)port)->fd, m); //EnterMutex(); return res; // OK - } + } return 1; // NOT OK } @@ -161,6 +162,13 @@ EnterMutex(); canDispatch(((CANPort*)port)->d, &m); LeaveMutex(); + +#ifdef __KERNEL__ +#ifdef USE_XENO + /* periodic task for Xenomai kernel realtime */ + rt_task_wait_period(NULL); +#endif +#endif } } @@ -178,19 +186,19 @@ if(!canports[i].used) break; } - + #ifndef NOT_USE_DYNAMIC_LOADING if (&DLL_CALL(canOpen)==NULL) { fprintf(stderr,"CanOpen : Can Driver dll not loaded\n"); return NULL; } -#endif +#endif CAN_HANDLE fd0 = DLL_CALL(canOpen)(board); if(fd0){ canports[i].used = 1; canports[i].fd = fd0; canports[i].d = d; - d->canHandle = (CAN_PORT)&canports[i]; + d->canHandle = (CAN_PORT)&canports[i]; CreateReceiveTask(&(canports[i]), &canports[i].receiveTask, &canReceiveLoop); return (CAN_PORT)&canports[i]; }else{ @@ -207,17 +215,18 @@ int canClose(CO_Data * d) { UNS8 res; - + ((CANPort*)d->canHandle)->used = 0; CANPort* tmp = (CANPort*)d->canHandle; - d->canHandle = NULL; - + + // kill receiver task before port is closed and handle set to NULL + WaitReceiveTaskEnd(&tmp->receiveTask); + // close CAN port res = DLL_CALL(canClose)(tmp->fd); - // kill receiver task - WaitReceiveTaskEnd(&tmp->receiveTask); - + d->canHandle = NULL; + return res; } @@ -236,7 +245,7 @@ res = DLL_CALL(canChangeBaudRate)(((CANPort*)port)->fd, baud); //EnterMutex(); return res; // OK - } + } return 1; // NOT OK } diff -r 9e496a2aadca -r b9274b595650 drivers/win32/win32.c --- a/drivers/win32/win32.c Fri Nov 12 22:02:32 2010 +0100 +++ b/drivers/win32/win32.c Fri Nov 12 22:24:06 2010 +0100 @@ -190,16 +190,18 @@ } tmp = (CANPort*)d->canHandle; - d->canHandle = NULL; if(tmp) { + // kill receiver task before port is closed and handle set to NULL + WaitReceiveTaskEnd(&tmp->receiveTask); + // close CAN port res = m_canClose(tmp->fd); - - // kill receiver task - WaitReceiveTaskEnd(&tmp->receiveTask); - } + } + + d->canHandle = NULL; + return res; } diff -r 9e496a2aadca -r b9274b595650 examples/TestMasterSlave/TestMasterSlave.c --- a/examples/TestMasterSlave/TestMasterSlave.c Fri Nov 12 22:02:32 2010 +0100 +++ b/examples/TestMasterSlave/TestMasterSlave.c Fri Nov 12 22:24:06 2010 +0100 @@ -189,8 +189,10 @@ /* install signal handler for manual break */ signal(SIGTERM, catch_signal); signal(SIGINT, catch_signal); +#endif + // Also Windows needs to initialize the Timer! + // Moving this line into the ifndef leads to a lethal crash! TimerInit(); -#endif #ifndef NOT_USE_DYNAMIC_LOADING if (LoadCanDriver(LibraryPath) == NULL) diff -r 9e496a2aadca -r b9274b595650 examples/test_copcican_comedi/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/test_copcican_comedi/Makefile.in Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,66 @@ +#! gmake + +# +# Copyright (C) 2010 Cosateq GmbH & Co.KG +# http://www.cosateq.com/ +# http://www.scale-rt.com/ +# +# This file is part of canfestival, a library implementing the canopen +# stack +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +#ifneq ($(KERNELRELEASE),) +# Kbuild part of Makefile +TARGET = SUB_TARGET +CAN_DRIVER = SUB_CAN_DRIVER +TIMERS_DRIVER = SUB_TIMERS_DRIVER + +EXTRA_CFLAGS := -I$(src)/../../include +EXTRA_CFLAGS += -I$(src)/../../include/$(TARGET) +EXTRA_CFLAGS += -I$(src)/../../include/$(CAN_DRIVER) +EXTRA_CFLAGS += -I$(src)/../../include/$(TIMERS_DRIVER) +EXTRA_CFLAGS += -I/usr/src/comedi/include +EXTRA_CFLAGS += SUB_PROG_CFLAGS + +OBJS := test_copcican_comedi.o + +obj-m := test_copcican_comedi.o +test_copcican_comediko-objs := $(OBJS) + +#else +# Normal Makefile +CC = SUB_CC +PREFIX = SUB_PREFIX +KERNELDIR := SUB_KERNELDIR + +all: test_copcican_comedi + +test_copcican_comedi: + cat ../../drivers/can_copcican_comedi/Module.symvers > Module.symvers + $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(shell pwd) clean + rm -f Module.symvers + +mrproper: clean + rm -f test_copcican_comedi.c + +install: + $(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_install + +#endif diff -r 9e496a2aadca -r b9274b595650 examples/test_copcican_comedi/insert.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/test_copcican_comedi/insert.sh Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,19 @@ +#!/bin/sh + +module="test_copcican_comedi" +device="test_copcican_comedi" +mode="664" + +# insert neccessary modules +/sbin/insmod ../../drivers/can_copcican_comedi/can_copcican_comedi.ko +/sbin/insmod ../../src/canfestival.ko + +# insert module with all arguments we got +# and use a pathname, as newer modutils don't look in . by default +/sbin/insmod ./$module.ko $* || exit 1 + +# stale nodes and device files are created by COMEDI + +rmmod $module +rmmod canfestival +rmmod can_copcican_comedi diff -r 9e496a2aadca -r b9274b595650 examples/test_copcican_comedi/test_copcican_comedi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/test_copcican_comedi/test_copcican_comedi.c Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,120 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + example for application with CO-PCICAN card. +*/ + +#include +#include +#include +#include "canfestival.h" + +/* only for mdelay() */ +#include + +MODULE_LICENSE("GPL"); + +#define CHTX 2 /* channel number of the CO-PCICAN */ +#define CHRX 0 /* channel number of the CO-PCICAN */ + +void mySyncHandler( CO_Data* d ) +{ + printk( "test_copcican_comedi: got a SYNC message...\n" ); +} + +static int main( void ) +{ + s_BOARD bd; + CO_Data myData; + CAN_PORT port; + Message myMessage; + const char busname[] = "/dev/comedi0"; + const char baudrate[] = "1M"; + comedi_t *dev; + + memset( &myData, 0x00, sizeof(CO_Data) ); + myData.CurrentCommunicationState.csSYNC = 1; + myData.post_sync = mySyncHandler; + bd.busname = (char*)busname; + bd.baudrate = (char*)baudrate; + + printk( "test_copcican_comedi: This example sends three SYNCs from port#%u to port#%u with a CO-PCICAN card\n", CHTX, CHRX ); + + /* direction: 0=RX, 1=TX */ + co_pcican_select_channel( CHRX, 0 ); + co_pcican_select_channel( CHTX, 1 ); + + port = canOpen( &bd, &myData ); + + if( port == NULL ) + { + /* something strange happenend */ + return 0; + } + + /* get device pointer to control the opened device */ + dev = get_dev_of_port( port ); + + co_pcican_enter_config_mode( dev ); + co_pcican_configure_selected_channel( dev, &bd, 0 ); + co_pcican_configure_selected_channel( dev, &bd, 1 ); + co_pcican_enter_run_mode( dev ); + + memset( &myMessage, 0x00, sizeof(Message) ); + myMessage.cob_id = 0x80; /* SYNC message */ + myMessage.len = 1; + myMessage.data[0] = 0xA5; + + /* SEND HERE */ + canSend( port, &myMessage ); + + myMessage.data[0] = 0x5A; + canSend( port, &myMessage ); + + myMessage.data[0] = 0xA5; + canSend( port, &myMessage ); + + /* mySyncHandler() is called by the receive thread and shows a received SYNC message in the kernel log */ + mdelay( 1*1000 ); /* 1s */ + + canClose( &myData ); + + return 0; +} + +static int init(void) +{ + printk("test_copcican_comedi for CanFestival loaded\n"); + + return main(); +} + +static void exit(void) +{ + printk("test_copcican_comedi unloaded\n"); +} + +module_init(init); +module_exit(exit); diff -r 9e496a2aadca -r b9274b595650 examples/test_copcican_linux/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/test_copcican_linux/Makefile.in Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,76 @@ +#! gmake + +# +# Copyright (C) 2010 Cosateq GmbH & Co.KG +# http://www.cosateq.com/ +# http://www.scale-rt.com/ +# +# This file is part of canfestival, a library implementing the canopen +# stack +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +CC = SUB_CC +CXX = SUB_CXX +LD = SUB_LD +OPT_CFLAGS = -O2 +CFLAGS = SUB_OPT_CFLAGS +PROG_CFLAGS = SUB_PROG_CFLAGS +EXE_CFLAGS = SUB_EXE_CFLAGS +OS_NAME = SUB_OS_NAME +ARCH_NAME = SUB_ARCH_NAME +PREFIX = SUB_PREFIX +TARGET = SUB_TARGET +CAN_DRIVER = SUB_CAN_DRIVER +TIMERS_DRIVER = SUB_TIMERS_DRIVER + +INCLUDES = -I../../include -I../../include/$(TARGET) -I../../include/$(CAN_DRIVER) -I../../include/$(TIMERS_DRIVER) + +TEST_COPCICAN_LINUX_OBJS = test_copcican_linux.o + +OBJS = $(TEST_COPCICAN_LINUX_OBJS) ../../drivers/$(TARGET)/libcanfestival_$(TARGET).a ../../src/libcanfestival.a + +all: test_copcican_linux + +../../src/libcanfestival.a: + $(MAKE) -C ../../src libcanfestival.a + + +../../drivers/$(TARGET)/libcanfestival_$(TARGET).a: + $(MAKE) -C ../../drivers/$(TARGET) libcanfestival_$(TARGET).a + + +test_copcican_linux: test_copcican_linux.c $(OBJS) + $(LD) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ $(OBJS) $(EXE_CFLAGS) + +%o: %c + $(CC) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ -c $< + +clean: + rm -f $(TEST_COPCICAN_LINUX_OBJS) + rm -f test_copcican_linux + +mrproper: clean + rm -f test_copcican_linux.c + +install: test_copcican_linux + mkdir -p $(PREFIX)/bin/ + cp $< $(PREFIX)/bin/ + +uninstall: + rm -f $(PREFIX)/bin/test_copcican_linux + + diff -r 9e496a2aadca -r b9274b595650 examples/test_copcican_linux/test_copcican_linux.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/test_copcican_linux/test_copcican_linux.c Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,130 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Cosateq GmbH & Co.KG + http://www.cosateq.com/ + http://www.scale-rt.com/ + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + example for application with CO-PCICAN card. +*/ + +#include +#include "canfestival.h" + +/* only for usleep() */ +#include + +#define CHTX 2 /* channel number of the CO-PCICAN */ +#define CHRX 0 /* channel number of the CO-PCICAN */ + +void mySyncHandler( CO_Data* d ) +{ + printf( " got a SYNC message...\n" ); +} + +int main() +{ + LIB_HANDLE driver; + + /* handles for additional CO-PCICAN functions */ + int (*get_fd_of_port)( CAN_PORT port ); + int (*co_pcican_enter_run_mode)( const int fd ); + int (*co_pcican_enter_config_mode)( const int fd ); + int (*co_pcican_select_channel)( const unsigned char channel, const unsigned int direction ); + int (*co_pcican_configure_selected_channel)( const int fd, s_BOARD *board, const unsigned int direction ); + + s_BOARD bd; + CO_Data myData; + CAN_PORT port; + Message myMessage; + const char busname[] = "/dev/co_pcican-0"; + const char baudrate[] = "1M"; + int fd; + + memset( &myData, 0x00, sizeof(CO_Data) ); + myData.CurrentCommunicationState.csSYNC = 1; + myData.post_sync = mySyncHandler; + bd.busname = (char*)busname; + bd.baudrate = (char*)baudrate; + + printf( "This example sends three SYNCs from port#%u to port#%u with a CO-PCICAN card\n", CHTX, CHRX ); + + driver = LoadCanDriver( "/usr/local/lib/libcanfestival_can_copcican_linux.so" ); + + if( driver == NULL ) + { + /* something strange happenend */ + return 0; + } + + /* dynamic load of additional library functions */ + get_fd_of_port = dlsym( driver, "get_fd_of_port" ); + co_pcican_enter_run_mode = dlsym( driver, "co_pcican_enter_run_mode" ); + co_pcican_enter_config_mode = dlsym( driver, "co_pcican_enter_config_mode" ); + co_pcican_select_channel = dlsym( driver, "co_pcican_select_channel" ); + co_pcican_configure_selected_channel = dlsym( driver, "co_pcican_configure_selected_channel" ); + + /* direction: 0=RX, 1=TX */ + co_pcican_select_channel( CHRX, 0 ); + co_pcican_select_channel( CHTX, 1 ); + + port = canOpen( &bd, &myData ); + + if( port == NULL ) + { + UnLoadCanDriver( driver ); + + /* something strange happenend */ + return 0; + } + + /* get file descriptor to control the opened device */ + fd = get_fd_of_port( port ); + + co_pcican_enter_config_mode( fd ); + co_pcican_configure_selected_channel( fd, &bd, 0 ); + co_pcican_configure_selected_channel( fd, &bd, 1 ); + co_pcican_enter_run_mode( fd ); + + memset( &myMessage, 0x00, sizeof(Message) ); + myMessage.cob_id = 0x80; /* SYNC message */ + myMessage.len = 1; + myMessage.data[0] = 0xA5; + + /* SEND HERE */ + canSend( port, &myMessage ); + + myMessage.data[0] = 0x5A; + canSend( port, &myMessage ); + + myMessage.data[0] = 0xA5; + canSend( port, &myMessage ); + + /* mySyncHandler() is called by the receive thread and shows a received SYNC message on console */ + usleep( 1*1000*1000 ); /* 1s */ + + canClose( &myData ); + + UnLoadCanDriver( driver ); + + return 0; +} + diff -r 9e496a2aadca -r b9274b595650 include/can_driver.h --- a/include/can_driver.h Fri Nov 12 22:02:32 2010 +0100 +++ b/include/can_driver.h Fri Nov 12 22:24:06 2010 +0100 @@ -46,7 +46,11 @@ }; #ifndef DLL_CALL +#if !defined(WIN32) || defined(__CYGWIN__) #define DLL_CALL(funcname) funcname##_driver +#else +//Windows was missing the definition of the calling convention +#define DLL_CALL(funcname) __stdcall funcname##_driver #endif #ifndef FCT_PTR_INIT diff -r 9e496a2aadca -r b9274b595650 include/objacces.h --- a/include/objacces.h Fri Nov 12 22:02:32 2010 +0100 +++ b/include/objacces.h Fri Nov 12 22:24:06 2010 +0100 @@ -1,287 +1,287 @@ -/* -This file is part of CanFestival, a library implementing CanOpen Stack. - -Copyright (C): Edouard TISSERANT and Francis DUPIN - -See COPYING file for copyrights details. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/** @file - * @brief Responsible for accessing the object dictionary. - * - * This file contains functions for accessing the object dictionary and - * variables that are contained by the object dictionary. - * Accessing the object dictionary contains setting local variables - * as PDOs and accessing (read/write) all entries of the object dictionary - * @warning Only the basic entries of an object dictionary are included - * at the moment. - */ - -/** @defgroup od Object Dictionary Management - * @brief The Object Dictionary is the heart of each CANopen device containing all communication and application objects. - * @ingroup userapi - */ - -#ifndef __objacces_h__ -#define __objacces_h__ - -#include - - +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Edouard TISSERANT and Francis DUPIN + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** @file + * @brief Responsible for accessing the object dictionary. + * + * This file contains functions for accessing the object dictionary and + * variables that are contained by the object dictionary. + * Accessing the object dictionary contains setting local variables + * as PDOs and accessing (read/write) all entries of the object dictionary + * @warning Only the basic entries of an object dictionary are included + * at the moment. + */ + +/** @defgroup od Object Dictionary Management + * @brief The Object Dictionary is the heart of each CANopen device containing all communication and application objects. + * @ingroup userapi + */ + +#ifndef __objacces_h__ +#define __objacces_h__ + +#include + + #ifdef __cplusplus extern "C" { -#endif - - -typedef UNS32 (*valueRangeTest_t)(UNS8 typeValue, void *Value); -typedef void (* storeODSubIndex_t)(CO_Data* d, UNS16 wIndex, UNS8 bSubindex); -void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex); - -/** - * @brief Print MSG_WAR (s) if error to the access to the object dictionary occurs. - * - * You must uncomment the lines in the file objaccess.c :\n - * //#define DEBUG_CAN\n - * //#define DEBUG_WAR_CONSOLE_ON\n - * //#define DEBUG_ERR_CONSOLE_ON\n\n - * Beware that sometimes, we force the sizeDataDict or sizeDataGiven to 0, when we wants to use - * this function but we do not have the access to the right value. One example is - * getSDOerror(). So do not take attention to these variables if they are null. - * @param index - * @param subIndex - * @param sizeDataDict Size of the data defined in the dictionary - * @param sizeDataGiven Size data given by the user. - * @param code error code to print. (SDO abort code. See file def.h) - * @return - */ -UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex, - UNS32 sizeDataDict, UNS32 sizeDataGiven, UNS32 code); - - -/* _getODentry() Reads an entry from the object dictionary.\n - * - * use getODentry() macro to read from object and endianize - * use readLocalDict() macro to read from object and not endianize - * - * @code - * // Example usage: - * UNS8 *pbData; - * UNS8 length; - * UNS32 returnValue; - * - * returnValue = getODentry( (UNS16)0x100B, (UNS8)1, - * (void * *)&pbData, (UNS8 *)&length ); - * if( returnValue != SUCCESSFUL ) - * { - * // error handling - * } - * @endcode - * @param *d Pointer to a CAN object data structure - * @param wIndex The index in the object dictionary where you want to read - * an entry - * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is - * used to tell you how many valid entries you can find - * in this index. Look at the canopen standard for further - * information - * @param *pDestData Pointer to the pointer which points to the variable where - * the value of this object dictionary entry should be copied - * @param pExpectedSize This function writes the size of the copied value (in Byte) - * into this variable. - * @param *pDataType Pointer to the type of the data. See objdictdef.h - * @param CheckAccess if other than 0, do not read if the data is Write Only - * [Not used today. Put always 0]. - * @param Endianize When not 0, data is endianized into network byte order - * when 0, data is not endianized and copied in machine native - * endianness - * @return - * - OD_SUCCESSFUL is returned upon success. - * - SDO abort code is returned if error occurs . (See file def.h) - */ -UNS32 _getODentry( CO_Data* d, - UNS16 wIndex, - UNS8 bSubindex, - void * pDestData, - UNS32 * pExpectedSize, - UNS8 * pDataType, - UNS8 checkAccess, - UNS8 endianize); - -/** - * @ingroup od - * @brief getODentry() to read from object and endianize - * @param OD Pointer to a CAN object data structure - * @param wIndex The index in the object dictionary where you want to read - * an entry - * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is - * used to tell you how many valid entries you can find - * in this index. Look at the canopen standard for further - * information - * @param *pDestData Pointer to the pointer which points to the variable where - * the value of this object dictionary entry should be copied - * @param pExpectedSize This function writes the size of the copied value (in Byte) - * into this variable. - * @param *pDataType Pointer to the type of the data. See objdictdef.h - * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes) - * @param endianize Set to 1 : endianized into network byte order - * @return - * - OD_SUCCESSFUL is returned upon success. - * - SDO abort code is returned if error occurs . (See file def.h) - */ -#define getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \ - pDataType, checkAccess) \ - _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \ - pDataType, checkAccess, 1) - -/** - * @ingroup od - * @brief readLocalDict() reads an entry from the object dictionary, but in - * contrast to getODentry(), readLocalDict() doesn't endianize entry and reads - * entry in machine native endianness. - * @param OD Pointer to a CAN object data structure - * @param wIndex The index in the object dictionary where you want to read - * an entry - * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is - * used to tell you how many valid entries you can find - * in this index. Look at the canopen standard for further - * information - * @param *pDestData Pointer to the pointer which points to the variable where - * the value of this object dictionary entry should be copied - * @param pExpectedSize This function writes the size of the copied value (in Byte) - * into this variable. - * @param *pDataType Pointer to the type of the data. See objdictdef.h - * @param checkAccess if other than 0, do not read if the data is Write Only - * [Not used today. Put always 0]. - * @param endianize Set to 0, data is not endianized and copied in machine native - * endianness - * @return - * - OD_SUCCESSFUL is returned upon success. - * - SDO abort code is returned if error occurs . (See file def.h) - */ -#define readLocalDict( OD, wIndex, bSubindex, pDestData, pExpectedSize, \ - pDataType, checkAccess) \ - _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \ - pDataType, checkAccess, 0) - -/* By this function you can write an entry into the object dictionary - * @param *d Pointer to a CAN object data structure - * @param wIndex The index in the object dictionary where you want to write - * an entry - * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is - * used to tell you how many valid entries you can find - * in this index. Look at the canopen standard for further - * information - * @param *pSourceData Pointer to the variable that holds the value that should - * be copied into the object dictionary - * @param *pExpectedSize The size of the value (in Byte). - * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes) - * @param endianize When not 0, data is endianized into network byte order - * when 0, data is not endianized and copied in machine native - * endianness - * @return - * - OD_SUCCESSFUL is returned upon success. - * - SDO abort code is returned if error occurs . (See file def.h) - */ -UNS32 _setODentry( CO_Data* d, - UNS16 wIndex, - UNS8 bSubindex, - void * pSourceData, - UNS32 * pExpectedSize, - UNS8 checkAccess, - UNS8 endianize); - -/** - * @ingroup od - * @brief setODentry converts SourceData from network byte order to machine native - * format, and writes that to OD. - * @code - * // Example usage: - * UNS8 B; - * B = 0xFF; // set transmission type - * - * retcode = setODentry( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 ); - * @endcode - * @param d Pointer to a CAN object data structure - * @param wIndex The index in the object dictionary where you want to write - * an entry - * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is - * used to tell you how many valid entries you can find - * in this index. Look at the canopen standard for further - * information - * @param *pSourceData Pointer to the variable that holds the value that should - * be copied into the object dictionary - * @param *pExpectedSize The size of the value (in Byte). - * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes) - * @param endianize Set to 1 : endianized into network byte order - * @return - * - OD_SUCCESSFUL is returned upon success. - * - SDO abort code is returned if error occurs . (See file def.h) - */ -#define setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \ - checkAccess) \ - _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \ - checkAccess, 1) - -/** @fn UNS32 writeLocalDict(d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess) - * @ingroup od - * @hideinitializer - * @brief Writes machine native SourceData to OD. - * @param d Pointer to a CAN object data structure - * @param wIndex The index in the object dictionary where you want to write - * an entry - * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is - * used to tell you how many valid entries you can find - * in this index. Look at the canopen standard for further - * information - * @param *pSourceData Pointer to the variable that holds the value that should - * be copied into the object dictionary - * @param *pExpectedSize The size of the value (in Byte). - * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes) - * @param endianize Data is not endianized and copied in machine native endianness - * @return - * - OD_SUCCESSFUL is returned upon success. - * - SDO abort code is returned if error occurs . (See file def.h) - * \n\n - * @code - * // Example usage: - * UNS8 B; - * B = 0xFF; // set transmission type - * - * retcode = writeLocalDict( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 ); - * @endcode - */ -#define writeLocalDict( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess) \ - _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess, 0) - - - -/** - * @brief Scan the index of object dictionary. Used only by setODentry and getODentry. - * @param *d Pointer to a CAN object data structure - * @param wIndex - * @param *errorCode : OD_SUCCESSFUL if index foundor SDO abort code. (See file def.h) - * @param **Callback - * @return NULL if index not found. Else : return the table part of the object dictionary. - */ - const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback); - -UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback); - +#endif + + +typedef UNS32 (*valueRangeTest_t)(UNS8 typeValue, void *Value); +typedef void (* storeODSubIndex_t)(CO_Data* d, UNS16 wIndex, UNS8 bSubindex); +void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex); + +/** + * @brief Print MSG_WAR (s) if error to the access to the object dictionary occurs. + * + * You must uncomment the lines in the file objaccess.c :\n + * //#define DEBUG_CAN\n + * //#define DEBUG_WAR_CONSOLE_ON\n + * //#define DEBUG_ERR_CONSOLE_ON\n\n + * Beware that sometimes, we force the sizeDataDict or sizeDataGiven to 0, when we wants to use + * this function but we do not have the access to the right value. One example is + * getSDOerror(). So do not take attention to these variables if they are null. + * @param index + * @param subIndex + * @param sizeDataDict Size of the data defined in the dictionary + * @param sizeDataGiven Size data given by the user. + * @param code error code to print. (SDO abort code. See file def.h) + * @return + */ +UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex, + UNS32 sizeDataDict, UNS32 sizeDataGiven, UNS32 code); + + +/* _getODentry() Reads an entry from the object dictionary.\n + * + * use getODentry() macro to read from object and endianize + * use readLocalDict() macro to read from object and not endianize + * + * @code + * // Example usage: + * UNS8 *pbData; + * UNS8 length; + * UNS32 returnValue; + * + * returnValue = getODentry( (UNS16)0x100B, (UNS8)1, + * (void * *)&pbData, (UNS8 *)&length ); + * if( returnValue != SUCCESSFUL ) + * { + * // error handling + * } + * @endcode + * @param *d Pointer to a CAN object data structure + * @param wIndex The index in the object dictionary where you want to read + * an entry + * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is + * used to tell you how many valid entries you can find + * in this index. Look at the canopen standard for further + * information + * @param *pDestData Pointer to the pointer which points to the variable where + * the value of this object dictionary entry should be copied + * @param pExpectedSize This function writes the size of the copied value (in Byte) + * into this variable. + * @param *pDataType Pointer to the type of the data. See objdictdef.h + * @param CheckAccess if other than 0, do not read if the data is Write Only + * [Not used today. Put always 0]. + * @param Endianize When not 0, data is endianized into network byte order + * when 0, data is not endianized and copied in machine native + * endianness + * @return + * - OD_SUCCESSFUL is returned upon success. + * - SDO abort code is returned if error occurs . (See file def.h) + */ +UNS32 _getODentry( CO_Data* d, + UNS16 wIndex, + UNS8 bSubindex, + void * pDestData, + UNS32 * pExpectedSize, + UNS8 * pDataType, + UNS8 checkAccess, + UNS8 endianize); + +/** + * @ingroup od + * @brief getODentry() to read from object and endianize + * @param OD Pointer to a CAN object data structure + * @param wIndex The index in the object dictionary where you want to read + * an entry + * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is + * used to tell you how many valid entries you can find + * in this index. Look at the canopen standard for further + * information + * @param *pDestData Pointer to the pointer which points to the variable where + * the value of this object dictionary entry should be copied + * @param pExpectedSize This function writes the size of the copied value (in Byte) + * into this variable. + * @param *pDataType Pointer to the type of the data. See objdictdef.h + * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes) + * @param endianize Set to 1 : endianized into network byte order + * @return + * - OD_SUCCESSFUL is returned upon success. + * - SDO abort code is returned if error occurs . (See file def.h) + */ +#define getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \ + pDataType, checkAccess) \ + _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \ + pDataType, checkAccess, 1) + +/** + * @ingroup od + * @brief readLocalDict() reads an entry from the object dictionary, but in + * contrast to getODentry(), readLocalDict() doesn't endianize entry and reads + * entry in machine native endianness. + * @param OD Pointer to a CAN object data structure + * @param wIndex The index in the object dictionary where you want to read + * an entry + * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is + * used to tell you how many valid entries you can find + * in this index. Look at the canopen standard for further + * information + * @param *pDestData Pointer to the pointer which points to the variable where + * the value of this object dictionary entry should be copied + * @param pExpectedSize This function writes the size of the copied value (in Byte) + * into this variable. + * @param *pDataType Pointer to the type of the data. See objdictdef.h + * @param checkAccess if other than 0, do not read if the data is Write Only + * [Not used today. Put always 0]. + * @param endianize Set to 0, data is not endianized and copied in machine native + * endianness + * @return + * - OD_SUCCESSFUL is returned upon success. + * - SDO abort code is returned if error occurs . (See file def.h) + */ +#define readLocalDict( OD, wIndex, bSubindex, pDestData, pExpectedSize, \ + pDataType, checkAccess) \ + _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \ + pDataType, checkAccess, 0) + +/* By this function you can write an entry into the object dictionary + * @param *d Pointer to a CAN object data structure + * @param wIndex The index in the object dictionary where you want to write + * an entry + * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is + * used to tell you how many valid entries you can find + * in this index. Look at the canopen standard for further + * information + * @param *pSourceData Pointer to the variable that holds the value that should + * be copied into the object dictionary + * @param *pExpectedSize The size of the value (in Byte). + * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes) + * @param endianize When not 0, data is endianized into network byte order + * when 0, data is not endianized and copied in machine native + * endianness + * @return + * - OD_SUCCESSFUL is returned upon success. + * - SDO abort code is returned if error occurs . (See file def.h) + */ +UNS32 _setODentry( CO_Data* d, + UNS16 wIndex, + UNS8 bSubindex, + void * pSourceData, + UNS32 * pExpectedSize, + UNS8 checkAccess, + UNS8 endianize); + +/** + * @ingroup od + * @brief setODentry converts SourceData from network byte order to machine native + * format, and writes that to OD. + * @code + * // Example usage: + * UNS8 B; + * B = 0xFF; // set transmission type + * + * retcode = setODentry( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 ); + * @endcode + * @param d Pointer to a CAN object data structure + * @param wIndex The index in the object dictionary where you want to write + * an entry + * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is + * used to tell you how many valid entries you can find + * in this index. Look at the canopen standard for further + * information + * @param *pSourceData Pointer to the variable that holds the value that should + * be copied into the object dictionary + * @param *pExpectedSize The size of the value (in Byte). + * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes) + * @param endianize Set to 1 : endianized into network byte order + * @return + * - OD_SUCCESSFUL is returned upon success. + * - SDO abort code is returned if error occurs . (See file def.h) + */ +#define setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \ + checkAccess) \ + _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \ + checkAccess, 1) + +/** @fn UNS32 writeLocalDict(d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess) + * @ingroup od + * @hideinitializer + * @brief Writes machine native SourceData to OD. + * @param d Pointer to a CAN object data structure + * @param wIndex The index in the object dictionary where you want to write + * an entry + * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is + * used to tell you how many valid entries you can find + * in this index. Look at the canopen standard for further + * information + * @param *pSourceData Pointer to the variable that holds the value that should + * be copied into the object dictionary + * @param *pExpectedSize The size of the value (in Byte). + * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes) + * @param endianize Data is not endianized and copied in machine native endianness + * @return + * - OD_SUCCESSFUL is returned upon success. + * - SDO abort code is returned if error occurs . (See file def.h) + * \n\n + * @code + * // Example usage: + * UNS8 B; + * B = 0xFF; // set transmission type + * + * retcode = writeLocalDict( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 ); + * @endcode + */ +#define writeLocalDict( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess) \ + _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess, 0) + + + +/** + * @brief Scan the index of object dictionary. Used only by setODentry and getODentry. + * @param *d Pointer to a CAN object data structure + * @param wIndex + * @param *errorCode : OD_SUCCESSFUL if index foundor SDO abort code. (See file def.h) + * @param **Callback + * @return NULL if index not found. Else : return the table part of the object dictionary. + */ + const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback); + +UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback); + #ifdef __cplusplus } -#endif - -#endif /* __objacces_h__ */ +#endif + +#endif /* __objacces_h__ */ diff -r 9e496a2aadca -r b9274b595650 include/timers_kernel_xeno/timerscfg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/timers_kernel_xeno/timerscfg.h Fri Nov 12 22:24:06 2010 +0100 @@ -0,0 +1,42 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Edouard TISSERANT and Francis DUPIN + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __TIMERSCFG_H__ +#define __TIMERSCFG_H__ + +#include +#include +#include +#include +#include +#include + +// Time unit : ns +// Time resolution : 64bit (~584 years) +#define TIMEVAL RTIME +#define TIMEVAL_MAX ~(RTIME)0 +#define MS_TO_TIMEVAL(ms) rt_timer_ns2ticks((RTIME)ms*1000000) +#define US_TO_TIMEVAL(us) rt_timer_ns2ticks((RTIME)us*1000) + +#define TASK_HANDLE RT_TASK + +#endif diff -r 9e496a2aadca -r b9274b595650 src/Makefile.in --- a/src/Makefile.in Fri Nov 12 22:02:32 2010 +0100 +++ b/src/Makefile.in Fri Nov 12 22:24:06 2010 +0100 @@ -2,24 +2,24 @@ # # Copyright (C) 2006 Laurent Bessard -# +# # This file is part of canfestival, a library implementing the canopen # stack -# +# # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. -# +# # This library 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 # Lesser General Public License for more details. -# +# # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# +# ifneq ($(KERNELRELEASE),) # Kbuild part of Makefile @@ -60,11 +60,18 @@ OPT_CFLAGS = -O2 endif -# # # # Options # # # # +# # # # Options # # # # all: canfestival ifeq ($(TIMERS_DRIVER), timers_kernel) +USE_KERNEL_TIMER = true +endif +ifeq ($(TIMERS_DRIVER), timers_kernel_xeno) +USE_KERNEL_TIMER = true +endif + +ifeq ($(USE_KERNEL_TIMER), true) OBJS := $(shell echo $(OBJS) | sed "s:$(TARGET)_::g") OBJS += symbols.o OBJS += ../drivers/unix/libcanfestival_$(TARGET).o diff -r 9e496a2aadca -r b9274b595650 src/objacces.c --- a/src/objacces.c Fri Nov 12 22:02:32 2010 +0100 +++ b/src/objacces.c Fri Nov 12 22:24:06 2010 +0100 @@ -40,10 +40,12 @@ #include "data.h" -#ifdef DEBUG_WAR_CONSOLE_ON +//We need the function implementation for linking +//Only a placeholder with a define isnt enough! UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex, UNS32 sizeDataDict, UNS32 sizeDataGiven, UNS32 code) { +#ifdef DEBUG_WAR_CONSOLE_ON MSG_WAR(0x2B09,"Dictionary index : ", index); MSG_WAR(0X2B10," subindex : ", subIndex); switch (code) { @@ -72,11 +74,10 @@ default : MSG_WAR(0x2B20, "Unknown error code : ", code); } + #endif + return 0; } -#else -#define accessDictionaryError(index, subIndex, sizeDataDict, sizeDataGiven, code) -#endif UNS32 _getODentry( CO_Data* d, UNS16 wIndex, diff -r 9e496a2aadca -r b9274b595650 src/pdo.c --- a/src/pdo.c Fri Nov 12 22:02:32 2010 +0100 +++ b/src/pdo.c Fri Nov 12 22:24:06 2010 +0100 @@ -487,8 +487,8 @@ { /*store_as_last_message */ d->PDO_status[pdoNum].last_message = *pdo; - MSG_WAR (0x396D, "sendPDO cobId :", UNS16_LE(pdo->cob_id)); - MSG_WAR (0x396E, " Nb octets : ", pdo->len); + MSG_WAR (0x396D, "sendPDO cobId :", UNS16_LE(pdo.cob_id)); + MSG_WAR (0x396E, " Nb octets : ", pdo.len); canSend (d->canHandle, pdo); } @@ -512,16 +512,18 @@ UNS8 sendOnePDOevent (CO_Data * d, UNS32 pdoNum) { + UNS16 offsetObjdict; + Message pdo; if (!d->CurrentCommunicationState.csPDO || - (d->PDO_status[pdoNum].transmit_type_parameter & PDO_INHIBITED)) + !(d->PDO_status[pdoNum].transmit_type_parameter & PDO_INHIBITED)) { return 0; } - UNS16 offsetObjdict = d->firstIndex->PDO_TRS + pdoNum; + offsetObjdict = d->firstIndex->PDO_TRS + pdoNum; MSG_WAR (0x3968, " PDO is on EVENT. Trans type : ", *pTransmissionType); - Message pdo; + memset(&pdo, 0, sizeof(pdo)); if (buildPDO (d, pdoNum, &pdo)) { diff -r 9e496a2aadca -r b9274b595650 src/symbols.c --- a/src/symbols.c Fri Nov 12 22:02:32 2010 +0100 +++ b/src/symbols.c Fri Nov 12 22:24:06 2010 +0100 @@ -50,10 +50,12 @@ // objacces.h EXPORT_SYMBOL (_storeODSubIndex); +#ifdef DEBUG_WAR_CONSOLE_ON EXPORT_SYMBOL (accessDictionaryError); -EXPORT_SYMBOL (getODentry); -EXPORT_SYMBOL (setODentry); -EXPORT_SYMBOL (writeLocalDict); +#endif +EXPORT_SYMBOL (_getODentry); +EXPORT_SYMBOL (_setODentry); +//EXPORT_SYMBOL (writeLocalDict); EXPORT_SYMBOL (scanIndexOD); EXPORT_SYMBOL (RegisterSetODentryCallBack); diff -r 9e496a2aadca -r b9274b595650 src/timer.c --- a/src/timer.c Fri Nov 12 22:02:32 2010 +0100 +++ b/src/timer.c Fri Nov 12 22:24:06 2010 +0100 @@ -124,7 +124,7 @@ TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */ /* First run : change timer state depending on time */ /* Get time since timer signal */ - TIMEVAL overrun = getElapsedTime(); + UNS32 overrun = (UNS32)getElapsedTime(); TIMEVAL real_total_sleep_time = total_sleep_time + overrun; @@ -142,8 +142,9 @@ } else /* or period have expired */ { - /* set val as interval, with overrun correction */ - row->val = row->interval - (overrun % row->interval); + /* set val as interval, with 32 bit overrun correction, */ + /* modulo for 64 bit not available on all platforms */ + row->val = row->interval - (overrun % (UNS32)row->interval); row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */ /* Check if this new timer value is the soonest */ if(row->val < next_wakeup)