summaryrefslogtreecommitdiff
path: root/ecos/packages/devs/can/loop
diff options
context:
space:
mode:
Diffstat (limited to 'ecos/packages/devs/can/loop')
-rw-r--r--ecos/packages/devs/can/loop/current/ChangeLog73
-rw-r--r--ecos/packages/devs/can/loop/current/cdl/can_loop.cdl140
-rw-r--r--ecos/packages/devs/can/loop/current/doc/README2
-rw-r--r--ecos/packages/devs/can/loop/current/doc/synth_test.ecm66
-rw-r--r--ecos/packages/devs/can/loop/current/src/loop_can.c408
-rw-r--r--ecos/packages/devs/can/loop/current/tests/can_callback.c240
-rw-r--r--ecos/packages/devs/can/loop/current/tests/can_nonblock.c199
-rw-r--r--ecos/packages/devs/can/loop/current/tests/can_overrun1.c275
-rw-r--r--ecos/packages/devs/can/loop/current/tests/can_overrun2.c354
-rw-r--r--ecos/packages/devs/can/loop/current/tests/can_rdwr.c307
-rw-r--r--ecos/packages/devs/can/loop/current/tests/can_test_aux.inl147
-rw-r--r--ecos/packages/devs/can/loop/current/tests/can_timeout.c247
-rw-r--r--ecos/packages/devs/can/loop/current/tests/can_txevent.c271
13 files changed, 2729 insertions, 0 deletions
diff --git a/ecos/packages/devs/can/loop/current/ChangeLog b/ecos/packages/devs/can/loop/current/ChangeLog
new file mode 100644
index 0000000..da8347e
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/ChangeLog
@@ -0,0 +1,73 @@
+2007-08-28 Andrew Lunn <andrew.lunn@ascom.ch>
+
+ * tests/can_overrun1.c (can0_thread): Fix the length of the data
+ in the message. Add a delay to allow the CAN device to process
+ the packets.
+ * test/can_txcevent.c: (can0_thread): Add a delay to allow the CAN device
+ to process the packet.s
+ * src/loop_can.c (FIFO_SIZE): Changed to one more than the TX
+ queue size. If it is less, the loopback tests don't pass because
+ packets don't get transmitted.
+
+2007-08-24 Andrew Lunn <andrew.lunn>
+
+ * doc/synth_test.ecm: Import file for running the tests on synth.
+
+2007-08-24 Alexey Shusharin <mrfinch@mail.ru>
+
+ * tests/can_callback.c: Added test of CAN callback on event
+ * cdl/can_loop.cdl: Added can_callback.c into tests list
+
+2007-08-09 Andrew Lunn <andrew.lunn@ascom.ch>
+
+ * src/loop_can.c: Change all CYGPKG_IO_CAN_* to CYGPKG_DEVS_CAN_*
+ so that the loopback driver gets compiled. It looks like
+ at some point in its life it used to live in io/can instead
+ of its current location in dev/can/loop.
+
+2007-03-23 Uwe Kindler <uwe_kindler@web.de>
+
+ * cdl/can_loop.cd: Changed naming of various options from
+ xxx_IO_CAN_LOOP into xxx_DEVS_CAN_LOOP
+
+2007-03-23 Uwe Kindler <uwe_kindler@web.de>
+
+ * cdl/can_loop.cdl: Driver now implements the interfaces
+ CYGINT_IO_CAN_TX_EVENTS, CYGINT_IO_CAN_STD_CAN_ID,
+ CYGINT_IO_CAN_EXT_CAN_ID.
+ Removed CYGPKG_IO_CAN_LOOP_CFLAGS_ADD and
+ CYGPKG_IO_CAN_LOOP_CFLAGS_REMOVE because they had no function.
+
+ * src/loop_can.c: Added missing function loop_can_get_config
+ to make the driver build properly.
+
+ * tests: Did some fixes and cleanups for all test cases to make them
+ work properly with the changes in the CAN I/O layer.
+
+2005-08-15 Uwe Kindler <uwe_kindler@web.de>
+
+ * Loopback CAN driver created
+
+//===========================================================================
+// ####GPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin Street,
+// Fifth Floor, Boston, MA 02110-1301, USA.
+// -------------------------------------------
+// ####GPLCOPYRIGHTEND####
+//===========================================================================
diff --git a/ecos/packages/devs/can/loop/current/cdl/can_loop.cdl b/ecos/packages/devs/can/loop/current/cdl/can_loop.cdl
new file mode 100644
index 0000000..14cfad5
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/cdl/can_loop.cdl
@@ -0,0 +1,140 @@
+# ====================================================================
+#
+# can_loop.cdl
+#
+# eCos CAN LOOP configuration data
+#
+# ====================================================================
+## ####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later
+## version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT
+## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with eCos; if not, write to the Free Software Foundation, Inc.,
+## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##
+## As a special exception, if other files instantiate templates or use
+## macros or inline functions from this file, or you compile this file
+## and link it with other works to produce a work based on this file,
+## this file does not by itself cause the resulting work to be covered by
+## the GNU General Public License. However the source code for this file
+## must still be made available in accordance with section (3) of the GNU
+## General Public License v2.
+##
+## This exception does not invalidate any other reasons why a work based
+## on this file might be covered by the GNU General Public License.
+## -------------------------------------------
+## ####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Uwe Kindler
+# Original data: gthomas
+# Contributors:
+# Date: 2005-07-11
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_CAN_LOOP {
+ display "Loop CAN device drivers"
+
+ parent CYGPKG_IO_CAN_DEVICES
+ active_if CYGPKG_IO_CAN
+ requires CYGPKG_ERROR
+ include_dir cyg/io
+ include_files ; # none _exported_ whatsoever
+
+ description "
+ This package contains the loop CAN device driver."
+
+ compile -library=libextras.a loop_can.c
+
+ # Support up to two CAN loop device.
+ for { set ::loopcan 0 } { $::loopcan < 2 } { incr ::loopcan } {
+
+ cdl_component CYGPKG_DEVS_CAN_LOOP_CAN[set ::loopcan] {
+ display "LOOP CAN channel [set ::loopcan] driver"
+ flavor bool
+ default_value 0
+ implements CYGINT_IO_CAN_TIMESTAMP
+ implements CYGINT_IO_CAN_TX_EVENTS
+ implements CYGINT_IO_CAN_STD_CAN_ID
+ implements CYGINT_IO_CAN_EXT_CAN_ID
+ description "
+ This option includes the CAN loop device driver for channel [set ::loopcan]."
+
+ cdl_option CYGDAT_DEVS_CAN_LOOP_CAN[set ::loopcan]_NAME {
+ display "Device name for LOOP CAN channel [set ::loopcan]"
+ flavor data
+ default_value [format {"\"/dev/can%d\""} $::loopcan]
+ description "
+ This option specifies the device name for loop CAN channel [set ::loopcan]."
+ }
+
+ cdl_option CYGNUM_DEVS_CAN_LOOP_CAN[set ::loopcan]_KBAUD {
+ display "Baud rate for the LOOP CAN channel [set ::loopcan] driver"
+ flavor data
+ default_value 100
+ legal_values { 10 20 50 100 125 250 500 800 1000 }
+ description "This option determines the initial baud rate in KBaud for
+ loop CAN channel [set ::loopcan]."
+ }
+
+ cdl_option CYGNUM_DEVS_CAN_LOOP_CAN[set ::loopcan]_QUEUESIZE_TX {
+ display "Size of TX Queue for loop CAN channel [set ::loopcan]"
+ flavor data
+ default_value 32
+ legal_values 16 to 512
+ description "
+ The CAN device driver will run in interrupt mode and will
+ perform buffering of outgoing data. This option controls the number
+ of CAN messages the TX queue can store."
+ }
+
+ cdl_option CYGNUM_DEVS_CAN_LOOP_CAN[set ::loopcan]_QUEUESIZE_RX {
+ display "Size of RX Queue for the loop CAN channel [set ::loopcan]"
+ flavor data
+ default_value 32
+ legal_values 16 to 512
+ description "
+ The CAN device driver will run in interrupt mode and will
+ perform buffering of incoming data. This option controls the number
+ of CAN events the RX queue can store."
+ }
+ }
+ }
+
+
+ cdl_component CYGPKG_DEVS_CAN_LOOP_OPTIONS {
+ display "CAN device driver build options"
+ flavor none
+ description "
+ Package specific build options including control over
+ compiler flags used only in building this package,
+ and details of which tests are built."
+
+
+ cdl_option CYGPKG_DEVS_CAN_LOOP_TESTS {
+ display "CAN loop device driver tests"
+ flavor data
+ calculated { "tests/can_rdwr tests/can_timeout tests/can_txevent tests/can_overrun1 tests/can_overrun2 tests/can_nonblock tests/can_callback" }
+ description "
+ This option specifies the set of tests for the CAN loop device drivers."
+ }
+ }
+}
+
+# EOF can_loop.cdl
diff --git a/ecos/packages/devs/can/loop/current/doc/README b/ecos/packages/devs/can/loop/current/doc/README
new file mode 100644
index 0000000..78195b6
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/doc/README
@@ -0,0 +1,2 @@
+The file synth_test.ecm can be used to configure a synthetic target
+work tree to enable the various options to allow the tests to be run. \ No newline at end of file
diff --git a/ecos/packages/devs/can/loop/current/doc/synth_test.ecm b/ecos/packages/devs/can/loop/current/doc/synth_test.ecm
new file mode 100644
index 0000000..634924a
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/doc/synth_test.ecm
@@ -0,0 +1,66 @@
+cdl_savefile_version 1;
+cdl_savefile_command cdl_savefile_version {};
+cdl_savefile_command cdl_savefile_command {};
+cdl_savefile_command cdl_configuration { description hardware template package };
+cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value };
+cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value };
+
+cdl_configuration eCos {
+ description "" ;
+ hardware linux ;
+ template default ;
+ package -hardware CYGPKG_HAL_SYNTH current ;
+ package -hardware CYGPKG_HAL_SYNTH_I386 current ;
+ package -hardware CYGPKG_DEVS_FLASH_SYNTH current ;
+ package -hardware CYGPKG_DEVS_ETH_ECOSYNTH current ;
+ package -hardware CYGPKG_DEVS_WATCHDOG_SYNTH current ;
+ package -hardware CYGPKG_DEVS_WALLCLOCK_SYNTH current ;
+ package -template CYGPKG_HAL current ;
+ package -template CYGPKG_IO current ;
+ package -template CYGPKG_IO_SERIAL current ;
+ package -template CYGPKG_INFRA current ;
+ package -template CYGPKG_KERNEL current ;
+ package -template CYGPKG_MEMALLOC current ;
+ package -template CYGPKG_ISOINFRA current ;
+ package -template CYGPKG_LIBC current ;
+ package -template CYGPKG_LIBC_I18N current ;
+ package -template CYGPKG_LIBC_SETJMP current ;
+ package -template CYGPKG_LIBC_SIGNALS current ;
+ package -template CYGPKG_LIBC_STARTUP current ;
+ package -template CYGPKG_LIBC_STDIO current ;
+ package -template CYGPKG_LIBC_STDLIB current ;
+ package -template CYGPKG_LIBC_STRING current ;
+ package -template CYGPKG_LIBC_TIME current ;
+ package -template CYGPKG_LIBM current ;
+ package -template CYGPKG_IO_WALLCLOCK current ;
+ package -template CYGPKG_ERROR current ;
+ package CYGPKG_IO_CAN current ;
+ package CYGPKG_DEVS_CAN_LOOP current ;
+};
+
+cdl_component CYGPKG_DEVS_CAN_LOOP_CAN0 {
+ user_value 1
+};
+
+cdl_component CYGPKG_DEVS_CAN_LOOP_CAN1 {
+ user_value 1
+};
+
+cdl_option CYGOPT_IO_CAN_TX_EVENT_SUPPORT {
+ user_value 1
+};
+
+cdl_option CYGOPT_IO_CAN_SUPPORT_NONBLOCKING {
+ user_value 1
+};
+
+cdl_option CYGOPT_IO_CAN_SUPPORT_CALLBACK {
+ user_value 1
+};
+
+cdl_component CYGOPT_IO_CAN_SUPPORT_TIMEOUTS {
+ user_value 1
+};
+
diff --git a/ecos/packages/devs/can/loop/current/src/loop_can.c b/ecos/packages/devs/can/loop/current/src/loop_can.c
new file mode 100644
index 0000000..85e4a57
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/src/loop_can.c
@@ -0,0 +1,408 @@
+//==========================================================================
+//
+// loop_can.c
+//
+// Loopback CAN device driver
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler
+// Contributors: Uwe Kindler
+// Date: 2005-07-10
+// Purpose: Loopback CAN device driver
+// Description: This device driver implements a pair of CAN lines that are
+// connected back-to-back. Data output to one will appear as
+// input on the other. This process in part driven by an alarm
+// object which provides a degree of separation between the two
+// channels.
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/io_can.h>
+#include <pkgconf/devs_can_loop.h>
+#include <cyg/hal/hal_io.h>
+
+#include <cyg/io/io.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/can.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/kernel/kapi.h>
+
+#ifdef CYGPKG_DEVS_CAN_LOOP
+
+//-------------------------------------------------------------------------
+
+extern void diag_printf(const char *fmt, ...);
+
+//-------------------------------------------------------------------------
+// Forward definitions
+
+static bool loop_can_init(struct cyg_devtab_entry *devtab_entry);
+static bool loop_can_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
+static Cyg_ErrNo loop_can_lookup(struct cyg_devtab_entry **tab,
+ struct cyg_devtab_entry *sub_tab,
+ const char *name);
+static bool loop_can_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
+static Cyg_ErrNo loop_can_set_config(can_channel *chan, cyg_uint32 key,
+ const void *xbuf, cyg_uint32 *len);
+static Cyg_ErrNo loop_can_get_config(can_channel *chan, cyg_uint32 key,
+ const void* buf, cyg_uint32* len);
+static void loop_can_start_xmit(can_channel *chan);
+static void loop_can_stop_xmit(can_channel *chan);
+
+static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data);
+
+
+//-------------------------------------------------------------------------
+// Alarm object for feeding data back into CAN channels
+
+static cyg_alarm alarm_obj;
+
+static cyg_handle_t alarm_handle;
+
+//-------------------------------------------------------------------------
+// Transfer FIFOs
+
+#define FIFO_SIZE 33
+
+struct fifo
+{
+ cyg_bool tx_enable;
+ volatile int head;
+ volatile int tail;
+ volatile int num;
+ volatile cyg_can_event buf[FIFO_SIZE+1];
+};
+
+static struct fifo fifo0 = { false, 0, 0, 0 }; // from CAN0 to CAN1
+static struct fifo fifo1 = { false, 0, 0, 0 }; // from CAN1 to CAN0
+
+//-------------------------------------------------------------------------
+
+#define BUFSIZE 128
+
+//-------------------------------------------------------------------------
+// Info for each serial device controlled
+
+typedef struct loop_can_info {
+ struct fifo *write_fifo;
+ struct fifo *read_fifo;
+} loop_can_info;
+
+//-------------------------------------------------------------------------
+// Callback functions exported by this driver
+CAN_LOWLEVEL_FUNS(loop_can_lowlevel_funs,
+ loop_can_putmsg,
+ loop_can_getevent,
+ loop_can_get_config,
+ loop_can_set_config,
+ loop_can_start_xmit,
+ loop_can_stop_xmit
+ );
+
+//-------------------------------------------------------------------------
+// Hardware info for each serial line
+
+#ifdef CYGPKG_DEVS_CAN_LOOP_CAN0
+static loop_can_info loop_can_info0 = {
+ &fifo0,
+ &fifo1
+};
+
+static cyg_can_message loop_can_txbuf0[CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_TX];
+static cyg_can_event loop_can_rxbuf0[CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_RX];
+#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL0
+
+#ifdef CYGPKG_DEVS_CAN_LOOP_CAN1
+static loop_can_info loop_can_info1 = {
+ &fifo1,
+ &fifo0
+};
+
+static cyg_can_message loop_can_txbuf1[CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_TX];
+static cyg_can_event loop_can_rxbuf1[CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_RX];
+#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL1
+
+
+
+//-------------------------------------------------------------------------
+// Channel descriptions:
+//
+#ifdef CYGPKG_DEVS_CAN_LOOP_CAN0
+CAN_CHANNEL_USING_INTERRUPTS(loop_can0_chan,
+ loop_can_lowlevel_funs,
+ loop_can_info0,
+ CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LOOP_CAN0_KBAUD),
+ loop_can_txbuf0, CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_TX,
+ loop_can_rxbuf0, CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_RX
+ );
+#endif // CYGPKG_DEVS_CAN_LOOP_CAN1
+
+#ifdef CYGPKG_DEVS_CAN_LOOP_CAN1
+CAN_CHANNEL_USING_INTERRUPTS(loop_can1_chan,
+ loop_can_lowlevel_funs,
+ loop_can_info1,
+ CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LOOP_CAN1_KBAUD),
+ loop_can_txbuf1, CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_TX,
+ loop_can_rxbuf1, CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_RX
+ );
+#endif // CYGPKG_DEVS_CAN_LOOP_CAN1
+
+
+
+//-------------------------------------------------------------------------
+// And finally, the device table entries:
+//
+#ifdef CYGPKG_DEVS_CAN_LOOP_CAN0
+DEVTAB_ENTRY(loop_can_io0,
+ CYGDAT_DEVS_CAN_LOOP_CAN0_NAME,
+ 0, // Does not depend on a lower level interface
+ &cyg_io_can_devio,
+ loop_can_init,
+ loop_can_lookup, // CAN driver may need initializing
+ &loop_can0_chan
+ );
+#endif // CYGPKG_DEVS_CAN_LOOP_CAN0
+
+#ifdef CYGPKG_DEVS_CAN_LOOP_CAN1
+DEVTAB_ENTRY(loop_can_io1,
+ CYGDAT_DEVS_CAN_LOOP_CAN1_NAME,
+ 0, // Does not depend on a lower level interface
+ &cyg_io_can_devio,
+ loop_can_init,
+ loop_can_lookup, // CAN driver may need initializing
+ &loop_can1_chan
+ );
+#endif // CYGPKG_DEVS_CAN_LOOP_CAN1
+
+//-------------------------------------------------------------------------
+
+static bool
+loop_can_config_channel(can_channel *chan, cyg_can_info_t *new_config, bool init)
+{
+ if (new_config != &chan->config) {
+ chan->config = *new_config;
+ }
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// Function to initialize the device. Called at bootstrap time.
+
+bool loop_can_init(struct cyg_devtab_entry *tab)
+{
+ can_channel *chan = (can_channel *)tab->priv;
+
+ (chan->callbacks->can_init)(chan);
+
+ // Set up alarm for feeding data back into channels
+
+ cyg_alarm_create( cyg_real_time_clock(),
+ alarm_handler,
+ 0,
+ &alarm_handle,
+ &alarm_obj);
+
+ cyg_alarm_initialize( alarm_handle, 1, 1 );
+
+ loop_can_config_channel(chan, &chan->config, true);
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// This routine is called when the device is "looked" up (i.e. attached)
+
+static Cyg_ErrNo
+loop_can_lookup(struct cyg_devtab_entry **tab,
+ struct cyg_devtab_entry *sub_tab,
+ const char *name)
+{
+ can_channel *chan = (can_channel *)(*tab)->priv;
+ (chan->callbacks->can_init)(chan);
+ return ENOERR;
+}
+
+//-------------------------------------------------------------------------
+// Return 'true' if message is sent to device
+
+bool
+loop_can_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
+{
+ loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
+
+ struct fifo *fwr = loop_chan->write_fifo;
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+ struct fifo *frd = loop_chan->read_fifo;
+#endif
+
+ if( fwr->num == FIFO_SIZE )
+ {
+ return false;
+ }
+
+ fwr->buf[fwr->tail].msg = *pmsg;
+ fwr->buf[fwr->tail].flags = CYGNUM_CAN_EVENT_RX;
+ fwr->num++;
+ fwr->tail = (fwr->tail + 1) % FIFO_SIZE;
+
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+ //
+ // if TX events are supported we insert a TX event into read fifo
+ //
+ if( frd->num < FIFO_SIZE )
+ {
+ frd->buf[frd->tail].msg = *pmsg;
+ frd->buf[frd->tail].flags = CYGNUM_CAN_EVENT_TX;
+ frd->num++;
+ frd->tail = (frd->tail + 1) % FIFO_SIZE;
+ }
+#endif
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+
+bool loop_can_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
+{
+ loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
+
+ struct fifo *frd = loop_chan->read_fifo;
+
+ while( frd->num == 0 )
+ {
+ continue;
+ }
+
+ *pevent = frd->buf[frd->head];
+
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP
+ //
+ // if timestamps are supported then we store a actual timestamp into
+ // CAN event
+ //
+ pevent->timestamp = cyg_current_time();
+#endif // CYGOPT_IO_CAN_SUPPORT_TIMESTAMP
+
+ frd->num--;
+ frd->head = (frd->head + 1) % FIFO_SIZE;
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+
+static Cyg_ErrNo
+loop_can_set_config(can_channel *chan, cyg_uint32 key,
+ const void *xbuf, cyg_uint32 *len)
+{
+ return ENOERR;
+}
+
+//-------------------------------------------------------------------------
+// Query device configuration
+
+static Cyg_ErrNo
+loop_can_get_config(can_channel *chan, cyg_uint32 key,
+ const void* buf, cyg_uint32* len)
+{
+ return ENOERR;
+}
+
+
+//-------------------------------------------------------------------------
+// Enable the transmitter on the device
+
+static void
+loop_can_start_xmit(can_channel *chan)
+{
+ loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
+
+ loop_chan->write_fifo->tx_enable = true;
+
+ (chan->callbacks->xmt_msg)(chan, 0);
+}
+
+//-------------------------------------------------------------------------
+// Disable the transmitter on the device
+
+static void
+loop_can_stop_xmit(can_channel *chan)
+{
+ loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
+
+ loop_chan->write_fifo->tx_enable = false;
+}
+
+//-------------------------------------------------------------------------
+
+static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data)
+{
+ can_channel *chan0 = &loop_can0_chan;
+ can_channel *chan1 = &loop_can1_chan;
+
+
+ while(fifo0.num )
+ {
+ (chan1->callbacks->rcv_event)(chan1, 0);
+
+ if(fifo0.tx_enable )
+ {
+ (chan0->callbacks->xmt_msg)(chan0, 0);
+ }
+ }
+
+ while(fifo1.num )
+ {
+ (chan0->callbacks->rcv_event)(chan0, 0);
+
+ if(fifo1.tx_enable )
+ {
+ (chan1->callbacks->xmt_msg)(chan1, 0);
+ }
+ } // while( fifo1.num )
+}
+
+
+#endif // CYGPKG_IO_CAN_LOOP
+
+//-------------------------------------------------------------------------
+// EOF loop_can.c
diff --git a/ecos/packages/devs/can/loop/current/tests/can_callback.c b/ecos/packages/devs/can/loop/current/tests/can_callback.c
new file mode 100644
index 0000000..528199b
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/tests/can_callback.c
@@ -0,0 +1,240 @@
+//==========================================================================
+//
+// can_callback.c
+//
+// CAN driver test of callback on event
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler, Alexey Shusharin
+// Contributors: Uwe Kindler, Alexey Shusharin
+// Date: 2007-08-23
+// Description: CAN driver test of callback on event
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// Package option requirements
+#if defined(CYGOPT_IO_CAN_SUPPORT_CALLBACK)
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can_thread;
+thread_data_t can_thread_data;
+
+cyg_mutex_t can_lock;
+cyg_cond_t can_wait;
+
+cyg_io_handle_t hCAN0;
+cyg_io_handle_t hCAN1;
+
+//===========================================================================
+// LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+// CALLBACK FUNCTION
+//===========================================================================
+
+static void callback_func(cyg_uint16 flags, CYG_ADDRWORD data)
+{
+ if (data == ((CYG_ADDRWORD) hCAN0) && (flags & CYGNUM_CAN_EVENT_RX))
+ {
+ // Wake up thread
+ cyg_cond_signal(&can_wait);
+ }
+}
+
+//===========================================================================
+// READER THREAD
+//===========================================================================
+void can_thread(cyg_addrword_t data)
+{
+ cyg_uint32 len;
+ cyg_can_callback_cfg callback_cfg;
+ cyg_can_message tx_msg;
+ cyg_bool_t wait_res;
+
+ //
+ // open CAN0 device driver
+ //
+ if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+ }
+
+ //
+ // open CAN1 device driver
+ //
+ if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can1");
+ }
+
+ //
+ // configure CAN0 callback
+ //
+ len = sizeof(callback_cfg);
+ callback_cfg.flag_mask = 0xFFFF;
+ callback_cfg.data = (CYG_ADDRWORD) hCAN0;
+ callback_cfg.callback_func = callback_func;
+
+ if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_CALLBACK,
+ &callback_cfg, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+ }
+
+ //
+ // transmit message from CAN1 to CAN0
+ //
+ tx_msg.id = 0x001;
+ tx_msg.ext = CYGNUM_CAN_ID_STD;
+ tx_msg.rtr = CYGNUM_CAN_FRAME_DATA;
+ tx_msg.dlc = 0;
+ len = sizeof(tx_msg);
+
+ if (ENOERR != cyg_io_write(hCAN1, &tx_msg, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing message to /dev/can1");
+ }
+
+ //
+ // Wait CAN0 callback
+ //
+ cyg_mutex_lock(&can_lock);
+
+ wait_res = cyg_cond_timed_wait(&can_wait, 100);
+
+ cyg_mutex_unlock(&can_lock);
+
+ //
+ // If result of wait is a signal operation, test is successed
+ // If timeout - test is failed, because callback_func() hasn't been
+ // called with correct parameters
+ //
+ if(wait_res)
+ {
+ CYG_TEST_PASS_FINISH("can_callback test OK");
+ }
+ else
+ {
+ CYG_TEST_FAIL_FINISH("can_callback test FAILED");
+ }
+}
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ cyg_mutex_init(&can_lock);
+ cyg_cond_init(&can_wait, &can_lock);
+
+ //
+ // create the main thread
+ //
+ cyg_thread_create(4, can_thread,
+ (cyg_addrword_t) 0,
+ "can_thread",
+ (void *) can_thread_data.stack,
+ 1024 * sizeof(long),
+ &can_thread_data.hdl,
+ &can_thread_data.obj);
+
+ cyg_thread_resume(can_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+
+#else // #if defined(CYGOPT_IO_CAN_SUPPORT_CALLBACK)
+#define N_A_MSG "Needs callback support"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF can_callback.c
diff --git a/ecos/packages/devs/can/loop/current/tests/can_nonblock.c b/ecos/packages/devs/can/loop/current/tests/can_nonblock.c
new file mode 100644
index 0000000..73d953a
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/tests/can_nonblock.c
@@ -0,0 +1,199 @@
+//==========================================================================
+//
+// can_nonblock.c
+//
+// CAN driver test of nonblocking calls
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler
+// Contributors: Uwe Kindler
+// Date: 2005-08-14
+// Description: CAN driver test of nonblocking callst
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// Package option requirements
+#if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t can0_thread_data;
+
+
+cyg_io_handle_t hDrvFlexCAN;
+
+
+//===========================================================================
+// LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+// READER THREAD
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+ cyg_uint32 len;
+ cyg_uint32 blocking;
+ cyg_can_event rx_event;
+ Cyg_ErrNo res;
+
+ blocking = 0;
+ len = sizeof(blocking);
+ if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_READ_BLOCKING ,&blocking, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+ }
+
+ len = sizeof(rx_event);
+ res = cyg_io_read(hDrvFlexCAN, &rx_event, &len);
+
+ if (-EAGAIN == res)
+ {
+ CYG_TEST_PASS_FINISH("can_test1 test OK");
+ }
+ else if (-EINTR == res)
+ {
+ CYG_TEST_PASS_FINISH("can_test1 test OK");
+ }
+ else
+ {
+ CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+ }
+}
+
+
+void
+cyg_start(void)
+{
+ cyg_uint32 len;
+ cyg_can_info_t can_cfg;
+
+ CYG_TEST_INIT();
+
+ //
+ // open flexcan device driver
+ //
+ if (ENOERR != cyg_io_lookup("/dev/can0", &hDrvFlexCAN))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+ }
+
+ //
+ // setup CAN baudrate 250 KBaud
+ //
+ can_cfg.baud = CYGNUM_CAN_KBAUD_250;
+ len = sizeof(can_cfg);
+ if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+ }
+
+ //
+ // create the main thread
+ //
+ cyg_thread_create(4, can0_thread,
+ (cyg_addrword_t) 0,
+ "can0_thread",
+ (void *) can0_thread_data.stack,
+ 1024 * sizeof(long),
+ &can0_thread_data.hdl,
+ &can0_thread_data.obj);
+
+ cyg_thread_resume(can0_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+
+#else // #if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING)
+#define N_A_MSG "Needs nonblocking calls"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF can_nonblock.c
diff --git a/ecos/packages/devs/can/loop/current/tests/can_overrun1.c b/ecos/packages/devs/can/loop/current/tests/can_overrun1.c
new file mode 100644
index 0000000..8e57a74
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/tests/can_overrun1.c
@@ -0,0 +1,275 @@
+//==========================================================================
+//
+// can_overrun1.c
+//
+// Test CAN device drivers
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler
+// Contributors: Uwe Kindler
+// Date: 2005-08-07
+// Description: Simple read/write test of CAN driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// tx event support required
+#if defined(CYGOPT_IO_CAN_TX_EVENT_SUPPORT)
+
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t can0_thread_data;
+
+
+//===========================================================================
+// LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+// WRITER THREAD
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+ cyg_io_handle_t hCAN0;
+ cyg_uint8 i;
+ cyg_uint32 len;
+ cyg_can_buf_info_t buf_info;
+ cyg_can_event rx_event;
+ cyg_can_message tx_msg =
+ {
+ 0x000, // CAN identifier
+ data :
+ {
+ {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }// 8 data bytes
+ },
+ CYGNUM_CAN_ID_STD, // standard frame
+ CYGNUM_CAN_FRAME_DATA, // data frame
+ 1, // data length code
+ };
+
+ if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+ }
+
+ len = sizeof(buf_info);
+ if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+ }
+
+ if (buf_info.rx_count > 0)
+ {
+ CYG_TEST_FAIL_FINISH("Empty RX buffer expected for /dev/can0");
+ }
+
+ //
+ // now we send exactly one CAN message more than it is space in left in buffer
+ // Because each TX message will cause a TX event in receive queue we should
+ // get a RX queue overrun
+ //
+ diag_printf("Sending %d CAN messages to /dev/can0\n", buf_info.rx_bufsize + 1);
+ for (i = 0; i <= buf_info.rx_bufsize; ++i)
+ {
+ CYG_CAN_MSG_SET_STD_ID(tx_msg, 0x000 + i);
+ CYG_CAN_MSG_SET_DATA(tx_msg, 0, i);
+ len = sizeof(tx_msg);
+
+ if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+ }
+ else
+ {
+ print_can_msg(&tx_msg, "");
+ }
+ }
+
+ //
+ // Give the loop back driver time to process all those messages.
+ //
+ cyg_thread_delay(10);
+
+ //
+ // now check if receive queue is completely filled - that means number of rx events should
+ // be equal to RX queue size
+ //
+ if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+ }
+
+ if (buf_info.rx_bufsize != buf_info.rx_count)
+ {
+ CYG_TEST_FAIL_FINISH("Number of events in /dev/can0 RX queue differs from queue size");
+ }
+
+ //
+ // Now read all events from receive queue - if everything is o.k. than the oldest
+ // event should be overwritten by the latest sent message and the last event in
+ // queue should indicate a RX overrun
+ //
+ diag_printf("\nReceiving %d CAN messages from /dev/can0\n", buf_info.rx_bufsize);
+ for (i = 0; i < buf_info.rx_bufsize; ++i)
+ {
+ len = sizeof(rx_event);
+
+ if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading from /dev/can1");
+ }
+ else
+ {
+ //
+ // if we received a valid TX event then we can print the message
+ //
+ if (rx_event.flags & CYGNUM_CAN_EVENT_TX)
+ {
+ print_can_msg(&rx_event.msg, "");
+ if (rx_event.msg.data.bytes[0] != (i + 1))
+ {
+ CYG_TEST_FAIL_FINISH("Received /dev/can0 TX event contains invalid data");
+ }
+ }
+ else
+ {
+ CYG_TEST_FAIL_FINISH("Unexpected CAN event for /dev/can0");
+ }
+
+ //
+ // now check if any other flag is set
+ //
+ if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX)
+ {
+ diag_printf("RX queue overrun successfully indicated for /dev/can0\n");
+ if (i < (buf_info.rx_bufsize - 1))
+ {
+ CYG_TEST_FAIL_FINISH("RX queue overrun occured too early /dev/can0");
+ }
+ else
+ {
+ CYG_TEST_PASS_FINISH("can_overrun1 test OK");
+ }
+ } // if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX)
+ }
+ } // for (i = 0; i < buf_info.rx_bufsize; ++i)
+
+ CYG_TEST_FAIL_FINISH("RX overrun expected but not received for /dev/can0");
+}
+
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ //
+ // create the two threads which access the CAN device driver
+ //
+ cyg_thread_create(4, can0_thread,
+ (cyg_addrword_t) 0,
+ "can0_thread",
+ (void *) can0_thread_data.stack,
+ 1024 * sizeof(long),
+ &can0_thread_data.hdl,
+ &can0_thread_data.obj);
+
+ cyg_thread_resume(can0_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+
+#else // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+#define N_A_MSG "TX event support required for IO/CAN"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF serial4.c
diff --git a/ecos/packages/devs/can/loop/current/tests/can_overrun2.c b/ecos/packages/devs/can/loop/current/tests/can_overrun2.c
new file mode 100644
index 0000000..2318e9b
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/tests/can_overrun2.c
@@ -0,0 +1,354 @@
+//==========================================================================
+//
+// can_overrun2.c
+//
+// Test CAN device RX overrun events
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler
+// Contributors: Uwe Kindler
+// Date: 2005-08-07
+// Description: Simple read/write test of CAN driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t can0_thread_data;
+
+cyg_thread_entry_t can1_thread;
+thread_data_t can1_thread_data;
+
+
+//===========================================================================
+// LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+// WRITER THREAD
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+ cyg_io_handle_t hCAN0;
+ cyg_uint8 i;
+ cyg_uint32 len;
+ cyg_uint32 rx_bufsize;
+ cyg_can_buf_info_t tx_buf_info;
+ cyg_can_event rx_event;
+ cyg_can_message tx_msg =
+ {
+ 0x000, // CAN identifier
+ data :
+ {
+ {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }// 8 data bytes
+ },
+ CYGNUM_CAN_ID_STD, // standard frame
+ CYGNUM_CAN_FRAME_DATA, // data frame
+ 2, // data length code
+ };
+
+ if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+ }
+
+ len = sizeof(tx_buf_info);
+ if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&tx_buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+ }
+
+ //
+ // Before we can write the CAN messages, we need to know the buffer size of the
+ // receiver. The receiver will tell us this buffer size with one single CAN
+ // message
+ //
+ len = sizeof(rx_event);
+
+ if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+ }
+
+ //
+ // we expect a RX event here - we treat any other flag as an error
+ //
+ if (!(rx_event.flags & CYGNUM_CAN_EVENT_RX) || (rx_event.flags & !CYGNUM_CAN_EVENT_RX))
+ {
+ CYG_TEST_FAIL_FINISH("Unexpected RX event for /dev/can0");
+ }
+
+ rx_bufsize = *((cyg_uint32 *)rx_event.msg.data.bytes);
+
+ //
+ // now we send exactly one CAN message more than there is space in the receive buffer
+ // this should cause an RX ovverun in receive buffer
+ //
+ diag_printf("/dev/can0: Sending %d CAN messages\n", rx_bufsize);
+ for (i = 0; i <= rx_bufsize; ++i)
+ {
+ //
+ // we store the message number as CAN id and in first data byte so
+ // a receiver can check this later
+ //
+ CYG_CAN_MSG_SET_STD_ID(tx_msg, 0x000 + i);
+ CYG_CAN_MSG_SET_DATA(tx_msg, 0, i);
+ len = sizeof(tx_msg);
+
+ if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+ }
+ else
+ {
+ print_can_msg(&tx_msg, "");
+ }
+ } // for (i = 0; i <= rx_bufsize; ++i)
+
+ cyg_thread_suspend(cyg_thread_self());
+}
+
+
+//===========================================================================
+// READER THREAD
+//===========================================================================
+void can1_thread(cyg_addrword_t data)
+{
+ cyg_io_handle_t hCAN1;
+ cyg_uint8 i;
+ cyg_uint32 len;
+ cyg_can_buf_info_t rx_buf_info;
+ cyg_can_event rx_event;
+ cyg_can_message tx_msg;
+
+ if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can1");
+ }
+
+ len = sizeof(rx_buf_info);
+ if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1");
+ }
+
+ //
+ // first we send the size of our receive buffer to the writer
+ // we setup tx message now
+ //
+ tx_msg.id = 0x000;
+ tx_msg.ext = CYGNUM_CAN_ID_STD;
+ tx_msg.rtr = CYGNUM_CAN_FRAME_DATA;
+ tx_msg.dlc = sizeof(rx_buf_info.rx_bufsize);
+
+ //
+ // we store size of rx buffer in CAN message. We do not need to care about
+ // endianess here because this is a loopback driver test and we will receive
+ // our own messages
+ //
+ *((cyg_uint32 *)tx_msg.data.bytes) = rx_buf_info.rx_bufsize;
+ len = sizeof(tx_msg);
+
+ //
+ // as soon as we send a CAN message, thread 0 will resume because it is waiting
+ // for a message
+ //
+ diag_printf("/dev/can1: Sending size of RX buffer %d\n", rx_buf_info.rx_bufsize);
+ if (ENOERR != cyg_io_write(hCAN1, &tx_msg, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing to /dev/can1");
+ }
+ cyg_thread_delay(10); // let thread 0 run
+
+ //
+ // now we check if we received CAN messages - if receive buffer is not full
+ // the we have an error here because we expect a full receive buffer
+ //
+ len = sizeof(rx_buf_info);
+ if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1");
+ }
+
+ if (rx_buf_info.rx_bufsize != rx_buf_info.rx_count)
+ {
+ CYG_TEST_FAIL_FINISH("RX buffer of /dev/can1 does not contain number of expected messages");
+ }
+
+ //
+ // now we wait for messages from /dev/can0
+ //
+ diag_printf("/dev/can1: Receiving %d CAN messages\n", rx_buf_info.rx_count);
+ for (i = 0; i < rx_buf_info.rx_count; ++i)
+ {
+ len = sizeof(rx_event);
+ if (ENOERR != cyg_io_read(hCAN1, &rx_event, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+ }
+ else
+ {
+ if (rx_event.flags & CYGNUM_CAN_EVENT_RX)
+ {
+ print_can_msg(&rx_event.msg, "");
+ if (rx_event.msg.data.bytes[0] != (i + 1))
+ {
+ CYG_TEST_FAIL_FINISH("Received /dev/can1 RX event contains invalid data");
+ }
+ }
+ else
+ {
+ CYG_TEST_FAIL_FINISH("Unexpected CAN event for /dev/can1");
+ }
+
+ //
+ // now check if any other flag is set
+ //
+ if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX)
+ {
+ diag_printf("RX queue overrun successfully indicated for /dev/can1\n");
+
+//
+// if TX events are supported then we have already a TX event in receive queue because
+// we sent a message and the RX queue overrun will occur one message earlier
+//
+#if defined(CYGOPT_IO_CAN_TX_EVENT_SUPPORT)
+ if (i < (rx_buf_info.rx_bufsize - 2))
+#else
+ if (i < (rx_buf_info.rx_bufsize - 1))
+#endif
+ {
+ CYG_TEST_FAIL_FINISH("RX queue overrun occured too early for /dev/can1");
+ }
+ else
+ {
+ CYG_TEST_PASS_FINISH("can_overrun2 test OK");
+ }
+ } // if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX)
+ }
+
+ }
+}
+
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ //
+ // create the two threads which access the CAN device driver
+ //
+ cyg_thread_create(4, can0_thread,
+ (cyg_addrword_t) 0,
+ "can0_thread",
+ (void *) can0_thread_data.stack,
+ 1024 * sizeof(long),
+ &can0_thread_data.hdl,
+ &can0_thread_data.obj);
+
+ cyg_thread_create(5, can1_thread,
+ (cyg_addrword_t) can0_thread_data.hdl,
+ "can1_thread",
+ (void *) can1_thread_data.stack,
+ 1024 * sizeof(long),
+ &can1_thread_data.hdl,
+ &can1_thread_data.obj);
+
+ cyg_thread_resume(can0_thread_data.hdl);
+ cyg_thread_resume(can1_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF serial4.c
diff --git a/ecos/packages/devs/can/loop/current/tests/can_rdwr.c b/ecos/packages/devs/can/loop/current/tests/can_rdwr.c
new file mode 100644
index 0000000..f9e3789
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/tests/can_rdwr.c
@@ -0,0 +1,307 @@
+//==========================================================================
+//
+// can_rdwr.c
+//
+// Test CAN device drivers
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler
+// Contributors: Uwe Kindler
+// Date: 2005-08-07
+// Description: Simple read/write test of CAN driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t can0_thread_data;
+
+cyg_thread_entry_t can1_thread;
+thread_data_t can1_thread_data;
+
+cyg_sem_t sem_wait;
+
+
+//===========================================================================
+// LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+// WRITER THREAD
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+ cyg_io_handle_t hCAN0;
+ cyg_uint8 i;
+ cyg_uint32 len;
+ cyg_can_buf_info_t tx_buf_info;
+ cyg_can_message tx_msg =
+ {
+ 0x000, // CAN identifier
+ data :
+ {
+ {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes
+ },
+ CYGNUM_CAN_ID_STD, // standard frame
+ CYGNUM_CAN_FRAME_DATA, // data frame
+ 8, // data length code
+ };
+
+ if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+ }
+
+ len = sizeof(tx_buf_info);
+ if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&tx_buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+ }
+
+ if (tx_buf_info.tx_bufsize < 10)
+ {
+ CYG_TEST_FAIL_FINISH("TX quesize of /dev/can0 too small for 10 CAN messages");
+ }
+
+ while (1)
+ {
+ //
+ // now we simply send 10 CAN messages and then suspend the thread
+ //
+ CYG_TEST_INFO("Thread0: Writing 10 CAN messages");
+ for (i = 0; i < 10; ++i)
+ {
+ //
+ // we store the message number as CAN id and in first data byte so
+ // a receiver can check this later
+ //
+ CYG_CAN_MSG_SET_STD_ID(tx_msg, 0x000 + i);
+ CYG_CAN_MSG_SET_DATA(tx_msg, 0, i);
+ len = sizeof(tx_msg);
+
+ if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+ }
+ else
+ {
+ print_can_msg(&tx_msg, "");
+ }
+ } // for (i = 0; i < 10; ++i)
+
+ //
+ // Give reader thread 200 ticks time for readung all messages. The reader thread
+ // signals the semaphore if it received all transmitted messages
+ //
+ if (!cyg_semaphore_timed_wait( &sem_wait, cyg_current_time( ) + 200 ))
+ {
+ CYG_TEST_FAIL_FINISH("Waiting for reader thread timed out.");
+ }
+ else
+ {
+ CYG_TEST_PASS_FINISH("can_rdwr test OK");
+ }
+ } // while (1)
+}
+
+
+//===========================================================================
+// READER THREAD
+//===========================================================================
+void can1_thread(cyg_addrword_t data)
+{
+ cyg_io_handle_t hCAN1;
+ cyg_uint8 i;
+ cyg_uint32 len;
+ cyg_can_buf_info_t rx_buf_info;
+ cyg_can_event rx_event;
+
+ if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can1");
+ }
+
+ len = sizeof(rx_buf_info);
+ if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1");
+ }
+
+ if (rx_buf_info.rx_bufsize < 10)
+ {
+ CYG_TEST_FAIL_FINISH("RX quesize of /dev/can1 too small for 10 CAN events");
+ }
+
+ while (1)
+ {
+ //
+ // now we try to read the 10 CAN messages that was sent by writer
+ // thread previously
+ //
+ CYG_TEST_INFO("Thread1: Reading 10 CAN messages");
+ for (i = 0; i < 10; ++i)
+ {
+ len = sizeof(rx_event);
+
+ if (ENOERR != cyg_io_read(hCAN1, &rx_event, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading from /dev/can1");
+ }
+
+ //
+ // we expect only RX events in this test case - so all other events
+ // cause a test fail
+ //
+ if (!(rx_event.flags & CYGNUM_CAN_EVENT_RX))
+ {
+ CYG_TEST_FAIL_FINISH("Received wrong CAN event type");
+ }
+
+ //
+ // The writer thread stored the message number in CAN id and first
+ // data byte so we can check now if we received valid data
+ //
+ if ((rx_event.msg.id != i) || (rx_event.msg.data.bytes[0] != i))
+ {
+ CYG_TEST_FAIL_FINISH("Received CAN message contains unexpected data");
+ }
+ else
+ {
+ print_can_msg(&rx_event.msg, "");
+ }
+ } //for (i = 0; i < 10; ++i)
+
+ //
+ // signal successfull reception of all messages
+ //
+ cyg_semaphore_post(&sem_wait);
+ } // while (1)
+}
+
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ //
+ // Initialize the wait semaphore to 0
+ //
+ cyg_semaphore_init( &sem_wait, 0 );
+
+ //
+ // create the two threads which access the CAN device driver
+ //
+ cyg_thread_create(4, can0_thread,
+ (cyg_addrword_t) 0,
+ "can0_thread",
+ (void *) can0_thread_data.stack,
+ 1024 * sizeof(long),
+ &can0_thread_data.hdl,
+ &can0_thread_data.obj);
+
+ cyg_thread_create(5, can1_thread,
+ (cyg_addrword_t) can0_thread_data.hdl,
+ "can1_thread",
+ (void *) can1_thread_data.stack,
+ 1024 * sizeof(long),
+ &can1_thread_data.hdl,
+ &can1_thread_data.obj);
+
+ cyg_thread_resume(can0_thread_data.hdl);
+ cyg_thread_resume(can1_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF serial4.c
diff --git a/ecos/packages/devs/can/loop/current/tests/can_test_aux.inl b/ecos/packages/devs/can/loop/current/tests/can_test_aux.inl
new file mode 100644
index 0000000..2bb2e07
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/tests/can_test_aux.inl
@@ -0,0 +1,147 @@
+//==========================================================================
+//
+// can_test_aux.inl
+//
+// CAN test auxiliary functions
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler
+// Contributors: Uwe Kindler
+// Date: 2005-08-07
+// Description: Auxiliary functions for CAN driver tests
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// PRINT CAN EVENT
+//===========================================================================
+void print_can_msg(cyg_can_message *pmsg, char *pMsg)
+{
+ char *pmsg_str;
+ static char* msg_tbl[] =
+ {
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:]\n",
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X]\n",
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X]\n",
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X]\n",
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X]\n",
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X]\n",
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X]\n",
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X %02X]\n",
+ "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X %02X %02X]\n"
+ };
+
+ if (pmsg->rtr)
+ {
+ diag_printf("%s [ID:%03X] [RTR:%d] [EXT:%d] [DLC:%d]\n",
+ pMsg,
+ pmsg->id,
+ pmsg->rtr,
+ pmsg->ext,
+ pmsg->dlc);
+
+ return;
+ }
+
+ if (pmsg->dlc > 8)
+ {
+ pmsg_str = msg_tbl[8];
+ }
+ else
+ {
+ pmsg_str = msg_tbl[pmsg->dlc];
+ }
+
+ diag_printf(pmsg_str,
+ pMsg,
+ pmsg->id,
+ pmsg->rtr,
+ pmsg->ext,
+ pmsg->data.bytes[0],
+ pmsg->data.bytes[1],
+ pmsg->data.bytes[2],
+ pmsg->data.bytes[3],
+ pmsg->data.bytes[4],
+ pmsg->data.bytes[5],
+ pmsg->data.bytes[6],
+ pmsg->data.bytes[7]);
+}
+
+
+//===========================================================================
+// PRINT CAN EVENT FLAGS
+//===========================================================================
+void print_can_flags(cyg_uint16 flags, char *pMsg)
+{
+ char *pmsg_str;
+ cyg_uint8 i ;
+ static char* msg_tbl[] =
+ {
+ "RX ",
+ "TX ",
+ "WRX ",
+ "WTX ",
+ "ERRP ",
+ "BOFF ",
+ "OVRX ",
+ "OVTX ",
+ "CERR ",
+ "LSTY ",
+ "ESTY ",
+ "ALOS ",
+ "DEVC ",
+ "PHYF ",
+ "PHYH ",
+ "PHYL "
+ };
+ i = 0;
+ while (flags && (i < 16))
+ {
+ if (flags & 0x0001)
+ {
+ pmsg_str = msg_tbl[i];
+ diag_printf(pmsg_str);
+ }
+ flags >>=1;
+ i++;
+ }
+
+ diag_printf("\n");
+}
+
+//---------------------------------------------------------------------------
+// end of can_test_aux.inl
diff --git a/ecos/packages/devs/can/loop/current/tests/can_timeout.c b/ecos/packages/devs/can/loop/current/tests/can_timeout.c
new file mode 100644
index 0000000..7feba87
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/tests/can_timeout.c
@@ -0,0 +1,247 @@
+//==========================================================================
+//
+// can_timeout.c
+//
+// Test CAN device driver timeouts
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler
+// Contributors: Uwe Kindler
+// Date: 2005-08-07
+// Description: Timeout test of CAN device driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// timeout support required
+#if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS)
+
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t can0_thread_data;
+
+
+//===========================================================================
+// LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+// Measure timeout time and compare it with RX timeout value
+//===========================================================================
+void check_timeout(cyg_io_handle_t hCAN, cyg_uint32 timeout)
+{
+ cyg_can_event rx_event;
+ cyg_can_timeout_info_t timeout_info;
+ cyg_uint32 len;
+ cyg_uint32 current_time_old;
+ cyg_uint32 current_time_new;
+ cyg_int32 diff_time;
+
+
+
+ timeout_info.tx_timeout = timeout;
+ timeout_info.rx_timeout = timeout;
+ len = sizeof(timeout_info);
+ if (ENOERR != cyg_io_set_config(hCAN, CYG_IO_SET_CONFIG_CAN_TIMEOUT ,&timeout_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+ }
+
+ diag_printf("read timeout: %d\n", timeout);
+
+ //
+ // if the return code is -EINTR then we know that a timout occured. Normally the
+ // receive queue should be empty so we can expect a timeout here
+ //
+ current_time_old = (cyg_uint32)cyg_current_time();
+ len = sizeof(rx_event);
+ if (-EINTR == cyg_io_read(hCAN, &rx_event, &len))
+ {
+ current_time_new = (cyg_uint32)cyg_current_time();
+ diff_time = current_time_new - current_time_old;
+ diag_printf("measured time: %d\n\n", diff_time);
+ diff_time = diff_time - timeout;
+
+ //
+ // If the measured value is smaller then the timeout value or if
+ // the difference is > 2 the we treat this as an error
+ //
+ if ((diff_time < 0) || (diff_time > 2))
+ {
+ CYG_TEST_FAIL_FINISH("Measured timeout time differs from /dev/can0 RX timeout value.");
+ }
+ }
+ else
+ {
+ CYG_TEST_FAIL_FINISH("Timeout expected for /dev/can0");
+ }
+}
+
+//===========================================================================
+// WRITER THREAD
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+ cyg_io_handle_t hCAN0;
+ cyg_uint32 len;
+ cyg_uint32 blocking;
+ cyg_can_timeout_info_t timeout_info;
+
+
+ if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+ }
+
+ //
+ // the first thing we need to do is to switch to nonblocking calls because
+ // function calls with timeout require nonblocking calls
+ //
+ blocking = 0;
+ len = sizeof(blocking);
+ if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_READ_BLOCKING ,&blocking, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error changing config of /dev/can0");
+ }
+
+ //
+ // first we read the timeout configuration
+ //
+ len = sizeof(timeout_info);
+ if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_TIMEOUT ,&timeout_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+ }
+
+ //
+ // now we check the default timeout and a number of different timeout values
+ //
+ check_timeout(hCAN0, timeout_info.rx_timeout);
+ check_timeout(hCAN0, 10);
+ check_timeout(hCAN0, 20);
+ check_timeout(hCAN0, 50);
+ check_timeout(hCAN0, 100);
+ check_timeout(hCAN0, 200);
+ check_timeout(hCAN0, 500);
+
+
+ CYG_TEST_PASS_FINISH("can_timeout test OK");
+}
+
+
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ //
+ // create the thread which access the CAN device driver
+ //
+ cyg_thread_create(4, can0_thread,
+ (cyg_addrword_t) 0,
+ "can0_thread",
+ (void *) can0_thread_data.stack,
+ 1024 * sizeof(long),
+ &can0_thread_data.hdl,
+ &can0_thread_data.obj);
+
+ cyg_thread_resume(can0_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+
+#else // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+#define N_A_MSG "Timeout support required for IO/CAN"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF can_timeout.c
diff --git a/ecos/packages/devs/can/loop/current/tests/can_txevent.c b/ecos/packages/devs/can/loop/current/tests/can_txevent.c
new file mode 100644
index 0000000..e2e521d
--- /dev/null
+++ b/ecos/packages/devs/can/loop/current/tests/can_txevent.c
@@ -0,0 +1,271 @@
+//==========================================================================
+//
+// can_txevent.c
+//
+// Test CAN device driver timeouts
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Uwe Kindler
+// Contributors: Uwe Kindler
+// Date: 2005-08-07
+// Description: Timeout test of CAN device driver
+//####DESCRIPTIONEND####
+
+
+//===========================================================================
+// INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+
+#include <cyg/infra/testcase.h> // test macros
+#include <cyg/infra/cyg_ass.h> // assertion macros
+#include <cyg/infra/diag.h>
+
+// Package requirements
+#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL)
+
+#include <pkgconf/kernel.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+
+// Package option requirements
+#if defined(CYGFUN_KERNEL_API_C)
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/kernel/kapi.h>
+
+// tx event support required
+#if defined(CYGOPT_IO_CAN_TX_EVENT_SUPPORT)
+
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+typedef struct st_thread_data
+{
+ cyg_thread obj;
+ long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+ cyg_handle_t hdl;
+} thread_data_t;
+
+
+//===========================================================================
+// LOCAL DATA
+//===========================================================================
+cyg_thread_entry_t can0_thread;
+thread_data_t can0_thread_data;
+
+
+//===========================================================================
+// LOCAL FUNCTIONS
+//===========================================================================
+#include "can_test_aux.inl" // include CAN test auxiliary functions
+
+
+//===========================================================================
+// WRITER THREAD
+//===========================================================================
+void can0_thread(cyg_addrword_t data)
+{
+ cyg_io_handle_t hCAN0;
+ cyg_uint32 len;
+ cyg_can_buf_info_t buf_info;
+ cyg_uint16 i;
+ cyg_can_event rx_event;
+ cyg_can_message tx_msg =
+ {
+ 0x000, // CAN identifier
+ data :
+ {
+ {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }// 8 data bytes
+ },
+ CYGNUM_CAN_ID_STD, // standard frame
+ CYGNUM_CAN_FRAME_DATA, // data frame
+ 4, // data length code
+ };
+
+
+ if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0))
+ {
+ CYG_TEST_FAIL_FINISH("Error opening /dev/can0");
+ }
+
+ //
+ // first we read the buffer info
+ //
+ len = sizeof(buf_info);
+ if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+ }
+
+ //
+ // check if buffer is really empty
+ //
+ if (buf_info.rx_count != 0)
+ {
+ CYG_TEST_FAIL_FINISH("Receive buffer of /dev/can0 is not empty.");
+ }
+
+ //
+ // now send messages - because TX events are supported each transmitted CAN message
+ // will cause a TX event that is filled into receive queue
+ //
+ diag_printf("Sending %d CAN messages to /dev/can0 \n", buf_info.rx_bufsize);
+ for (i = 0; i < buf_info.rx_bufsize; ++i)
+ {
+ CYG_CAN_MSG_SET_STD_ID(tx_msg, 0x000 + i);
+ CYG_CAN_MSG_SET_DATA(tx_msg, 0, i);
+ len = sizeof(tx_msg);
+
+ if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error writing to /dev/can0");
+ }
+ else
+ {
+ print_can_msg(&tx_msg, "");
+ }
+ }
+
+ //
+ // Give the loop back driver time to process all those messages.
+ //
+ cyg_thread_delay(10);
+
+ //
+ // now we read the buffer info - we expect a completely filled recieve queue
+ //
+ len = sizeof(buf_info);
+ if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0");
+ }
+
+ //
+ // if receive queue is not completely filled, then we have an error here
+ //
+ if (buf_info.rx_bufsize != buf_info.rx_count)
+ {
+ diag_printf("RX bufsize: %d events in RX buffer: %d\n", buf_info.rx_bufsize, buf_info.rx_count);
+ CYG_TEST_FAIL_FINISH("Receive queue of /dev/can0 not completely filled.");
+ }
+
+ //
+ // now we read the receive queue
+ //
+ diag_printf("Receiving %d TX events from /dev/can0 \n", buf_info.rx_count);
+ for (i = 0; i < buf_info.rx_count; ++i)
+ {
+ len = sizeof(rx_event);
+
+ if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len))
+ {
+ CYG_TEST_FAIL_FINISH("Error reading from /dev/can0");
+ }
+
+ //
+ // we expect only a set TX flag because no other events may arrive for the
+ // loopback driver
+ //
+ if (!(rx_event.flags & CYGNUM_CAN_EVENT_TX) || (rx_event.flags & !CYGNUM_CAN_EVENT_TX))
+ {
+ CYG_TEST_FAIL_FINISH("Unexpected receive event flags.");
+ }
+
+ //
+ // Now check if TX events contain valid data - we know that the ID and the first
+ // data byte contain the message number
+ //
+ if ((rx_event.msg.id != i) || (rx_event.msg.data.bytes[0] != i))
+ {
+ CYG_TEST_FAIL_FINISH("Received invalid data in TX event");
+ }
+ else
+ {
+ print_can_msg(&rx_event.msg, "");
+ }
+ } // for (i = 0; i < buf_info.rx_count; ++i)
+
+ CYG_TEST_PASS_FINISH("can_txevent test OK");
+}
+
+
+
+void
+cyg_start(void)
+{
+ CYG_TEST_INIT();
+
+ //
+ // create the thread which access the CAN device driver
+ //
+ cyg_thread_create(4, can0_thread,
+ (cyg_addrword_t) 0,
+ "can0_thread",
+ (void *) can0_thread_data.stack,
+ 1024 * sizeof(long),
+ &can0_thread_data.hdl,
+ &can0_thread_data.obj);
+
+ cyg_thread_resume(can0_thread_data.hdl);
+
+ cyg_scheduler_start();
+}
+
+#else // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+#define N_A_MSG "TX event support required for IO/CAN"
+#endif
+
+#else // CYGFUN_KERNEL_API_C
+#define N_A_MSG "Needs kernel C API"
+#endif
+
+#else // CYGPKG_IO_CAN && CYGPKG_KERNEL
+#define N_A_MSG "Needs IO/CAN and Kernel"
+#endif
+
+#ifdef N_A_MSG
+void
+cyg_start( void )
+{
+ CYG_TEST_INIT();
+ CYG_TEST_NA( N_A_MSG);
+}
+#endif // N_A_MSG
+
+// EOF serial4.c