diff options
Diffstat (limited to 'ecos/packages/devs/can/loop')
-rw-r--r-- | ecos/packages/devs/can/loop/current/ChangeLog | 73 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/cdl/can_loop.cdl | 140 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/doc/README | 2 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/doc/synth_test.ecm | 66 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/src/loop_can.c | 408 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/tests/can_callback.c | 240 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/tests/can_nonblock.c | 199 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/tests/can_overrun1.c | 275 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/tests/can_overrun2.c | 354 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/tests/can_rdwr.c | 307 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/tests/can_test_aux.inl | 147 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/tests/can_timeout.c | 247 | ||||
-rw-r--r-- | ecos/packages/devs/can/loop/current/tests/can_txevent.c | 271 |
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 |