This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

I/O CAN driver and MCF52xx FlexCAN device driver


Hello,

the following patch adds generic I/O CAN driver and MCF52xx FlexCAN device driver to eCos.

The MCF52xx FlexCAN driver was developed for the SSV/DNP5280 board, which is not part of the public repository but the driver should also work with public MCF52xx boards if they provide the necessary defines.

Uwe Kindler



uwe_kindler@web.de
uwe.kindler@cetoni.de
http://www.cetoni.de
diff -urN ecos_web_cvs/ecos/packages/io/can/current/ChangeLog ecos/ecos/packages/io/can/current/ChangeLog
--- ecos_web_cvs/ecos/packages/io/can/current/ChangeLog	1970-01-01 01:00:00.000000000 +0100
+++ ecos/ecos/packages/io/can/current/ChangeLog	2005-05-24 20:06:56.000000000 +0200
@@ -0,0 +1,35 @@
+2005-05-24  Uwe Kindler  <uwe_kindler@web.de>
+
+	* Generic CAN driver package created
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2003, 2004 eCosCentric Limited
+//
+// 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.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+//
+// 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####
+//===========================================================================
diff -urN ecos_web_cvs/ecos/packages/io/can/current/cdl/io_can.cdl ecos/ecos/packages/io/can/current/cdl/io_can.cdl
--- ecos_web_cvs/ecos/packages/io/can/current/cdl/io_can.cdl	1970-01-01 01:00:00.000000000 +0100
+++ ecos/ecos/packages/io/can/current/cdl/io_can.cdl	2005-05-26 21:55:13.000000000 +0200
@@ -0,0 +1,169 @@
+# ====================================================================
+#
+#      io_can.cdl
+#
+#      eCos IO configuration data
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Uwe Kindler
+# Original data:  gthomas
+# Contributors:
+# Date:           2005-05-17
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_IO_CAN {
+    display       "CAN device drivers"
+    active_if     CYGPKG_IO
+    requires      CYGPKG_ERROR
+    include_dir   cyg/io
+    description   "
+        This option enables drivers for basic I/O services on
+        CAN devices."
+    doc           ref/io.html
+
+    compile       -library=libextras.a can.c
+ 
+    define_proc {
+	puts $::cdl_header "/***** proc output start *****/"
+	puts $::cdl_header "#include <pkgconf/system.h>"
+	puts $::cdl_header "#ifdef CYGDAT_IO_CAN_DEVICE_HEADER"
+	puts $::cdl_header "# include CYGDAT_IO_CAN_DEVICE_HEADER"
+	puts $::cdl_header "#endif "
+	puts $::cdl_header "/****** proc output end ******/"
+    }
+
+    cdl_interface CYGINT_IO_CAN_TIMESTAMP {
+        display "CAN driver supports timestamps"
+    }
+    
+    cdl_option CYGOPT_IO_CAN_SUPPORT_TIMESTAMP {
+        display       "Support CAN event timestamps"
+        requires      { CYGINT_IO_CAN_TIMESTAMP > 0 }
+        default_value 0
+        description "
+            If the CAN hardware driver supports some kind of timestamps
+            then this option enables propagation of timestamps to higher layers. 
+            This may add some extra code to hardware drivers."
+    }
+    
+    cdl_option CYGOPT_IO_CAN_TX_EVENT_SUPPORT {
+        display       "Support TX events"
+        default_value 0
+        description "
+            This option enables support for TX events. If a CAN message is
+            transmitted successfully a TX event will be inserted into the
+            receive event queue and propagated to higher layers. If this
+            option is enabled the RX event queue will be filled faster."
+    }
+    
+    cdl_component CYGPKG_IO_CAN_DEVICES {
+        display       "Hardware CAN device drivers"
+        flavor        bool
+        default_value 1
+        description   "
+            This option enables the hardware device drivers
+	        for the current platform."
+    }
+    
+    cdl_component CYGOPT_IO_CAN_SUPPORT_TIMEOUTS {
+        display       "Support read/write timeouts"
+        flavor        bool
+        default_value 0
+        active_if     CYGPKG_KERNEL
+        requires      CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT
+        description   "
+             Read and write operations are blocking calls. If no CAN message
+             arrives for a long time the calling thread remains blocked. If the
+             thread should return after a certain amount of time then this
+             option should be enabled."
+             
+        cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_READ {
+            display "Default read timeout."
+            flavor  data
+            default_value 100
+            description   "
+                The initial timeout value in clock ticks for cyg_io_read() calls."
+        }
+        
+        cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_WRITE {
+            display "Default write timeout."
+            flavor  data
+            default_value 100
+            description   "
+                The initial timeout value in clock ticks for cyg_io_write() calls."
+        }
+    }
+
+   cdl_component CYGPKG_IO_CAN_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_IO_CAN_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building the CAN device drivers. These flags are used in addition
+                to the set of global flags."
+        }
+
+        cdl_option CYGPKG_IO_CAN_CFLAGS_REMOVE {
+            display "Suppressed compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building the CAN device drivers. These flags are removed from
+                the set of global flags if present."
+        }
+
+    }
+}
+
+# EOF io_can.cdl
diff -urN ecos_web_cvs/ecos/packages/io/can/current/include/can.h ecos/ecos/packages/io/can/current/include/can.h
--- ecos_web_cvs/ecos/packages/io/can/current/include/can.h	1970-01-01 01:00:00.000000000 +0100
+++ ecos/ecos/packages/io/can/current/include/can.h	2005-05-25 15:18:16.000000000 +0200
@@ -0,0 +1,196 @@
+#ifndef CYGONCE_CAN_H
+#define CYGONCE_CAN_H
+// ====================================================================
+//
+//      can.h
+//
+//      Device I/O 
+//
+// ====================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler
+// Contributors: gthomas
+// Date:         2005-12-05
+// Purpose:      Internal interfaces for CAN I/O drivers
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+
+//==========================================================================
+//                                INCLUDES
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/io_can.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/io.h>
+#include <cyg/io/canio.h>
+#include <cyg/io/devtab.h>
+#include <cyg/hal/drv_api.h>
+
+
+//===========================================================================
+//                            FORWARD DECLARATIONS
+//===========================================================================
+typedef struct can_channel       can_channel;
+typedef struct can_lowlevel_funs can_lowlevel_funs;
+
+
+//===========================================================================
+//                                DATA TYPES
+//===========================================================================
+
+//---------------------------------------------------------------------------
+// Pointers into uper-level driver which ISRs and DSRs need
+//
+typedef struct 
+{
+    void (*can_init)(can_channel *chan);              // Initialize the can channel
+    void (*xmt_msg)(can_channel *chan, void *pdata);  // transmit one single message
+    void (*rcv_event)(can_channel *chan, void *pdata);// indicate can event occurance
+} can_callbacks_t;
+
+
+#define CAN_CALLBACKS(_l,_init,_xmt_msg,_rcv_event)  \
+can_callbacks_t _l = {                               \
+    _init,                                           \
+    _xmt_msg,                                        \
+    _rcv_event                                       \
+};
+
+extern can_callbacks_t cyg_io_can_callbacks;
+
+
+//---------------------------------------------------------------------------
+// Data buffer for receive and transmit FIFOs
+//
+typedef struct can_cbuf_st
+{
+    void                    *pdata;      // points to data buffer
+    volatile int             put;
+    volatile int             get;
+    int                      len;
+    volatile int             data_cnt;   // count of events or messages currently in buffer
+    cyg_drv_cond_t           wait;
+    cyg_drv_mutex_t          lock;
+    bool                     waiting;
+    volatile bool            abort;      // Set by an outsider to kill processing
+    volatile cyg_int32       pending;    // This many bytes waiting to be sent
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+    cyg_uint32               timeout;    // timeout value for reading data from buffer
+#endif
+} can_cbuf_t;
+
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+#define _TX_TIMEOUT CYGNUM_IO_CAN_DEFAULT_TIMEOUT_WRITE
+#define _RX_TIMEOUT CYGNUM_IO_CAN_DEFAULT_TIMEOUT_READ
+#define CBUF_INIT(_data, _len, _timeout)   \
+   {_data, 0, 0, _len, timeout : _timeout}
+#else
+#define _TX_TIMEOUT 0
+#define _RX_TIMEOUT 0
+#define CBUF_INIT(_data, _len, _timeout)   \
+   {_data, 0, 0, _len, }
+#endif // #ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+ 
+   
+//---------------------------------------------------------------------------
+// Private data which describes this channel + initialisation macro
+//
+struct can_channel 
+{
+    can_lowlevel_funs  *funs;
+    can_callbacks_t    *callbacks;
+    void               *dev_priv;  // Whatever is needed by actual device routines
+    cyg_can_info_t      config;    // Current configuration
+    bool                init;      // true if driver is already initialized
+    can_cbuf_t          out_cbuf;  // buffer for transmit can messages
+    can_cbuf_t          in_cbuf;   // buffer with received can events
+};
+
+
+
+#define CAN_CHANNEL_USING_INTERRUPTS(_l,                                \
+                       _funs,                                           \
+                       _dev_priv,                                       \
+                       _baud,                                           \
+                       _out_buf, _out_buflen,                           \
+                       _in_buf, _in_buflen)                             \
+can_channel _l = {                                                      \
+    &_funs,                                                             \
+    &cyg_io_can_callbacks,                                              \
+    &(_dev_priv),                                                       \
+    CYG_CAN_INFO_INIT(_baud),                                           \
+    false,                                                              \
+    CBUF_INIT(_out_buf, _out_buflen, _TX_TIMEOUT),                      \
+    CBUF_INIT(_in_buf, _in_buflen, _RX_TIMEOUT)                         \
+};
+
+
+
+//---------------------------------------------------------------------------
+// Low level interface functions - these functions are required by the generic 
+// CAN driver in order to access the low level hardware
+//
+struct can_lowlevel_funs 
+{
+    bool (*putmsg)(can_channel *priv, cyg_can_message *pmsg, void *pdata);   // send one can message - return true if consumed
+    bool (*getevent)(can_channel *priv, cyg_can_event *pevent, void *pdata); // fetch one CAN event from device
+    Cyg_ErrNo (*set_config)(can_channel    *priv,                        // Change hardware configuration (baud rate, etc)
+                            cyg_uint32      key, 
+                            const void     *xbuf,
+                            cyg_uint32     *len);
+    void (*start_xmit)(can_channel *priv);                               // Enable the transmit channel and turn on transmit interrupts
+    void (*stop_xmit)(can_channel *priv);                                // Disable the transmit channel and turn transmit interrupts off
+};
+
+#define CAN_LOWLEVEL_FUNS(_l,_putmsg,_getevent,_set_config,_start_xmit,_stop_xmit)  \
+can_lowlevel_funs _l = {                                                            \
+  _putmsg,                                                                          \
+  _getevent,                                                                        \
+  _set_config,                                                                      \
+  _start_xmit,                                                                      \
+  _stop_xmit                                                                        \
+};
+
+extern cyg_devio_table_t cyg_io_can_devio;
+//-------------------------------------------------------------------------
+#endif // CYGONCE_SERIAL_H
diff -urN ecos_web_cvs/ecos/packages/io/can/current/include/canio.h ecos/ecos/packages/io/can/current/include/canio.h
--- ecos_web_cvs/ecos/packages/io/can/current/include/canio.h	1970-01-01 01:00:00.000000000 +0100
+++ ecos/ecos/packages/io/can/current/include/canio.h	2005-05-25 15:17:27.000000000 +0200
@@ -0,0 +1,182 @@
+#ifndef CYGONCE_CANIO_H
+#define CYGONCE_CANIO_H
+// ====================================================================
+//
+//      canio.h
+//
+//      Device I/O 
+//
+// ====================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler
+// Contributors: gthomas
+// Date:         2005-05-12
+// Purpose:      Special support for CAN I/O devices
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+
+//===========================================================================
+//                               INCLUDES
+//===========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/io_can.h>
+#include <pkgconf/hal.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/config_keys.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//===========================================================================
+//                                DATA TYPES
+//===========================================================================
+
+//
+// Supported baud rates
+//
+typedef enum {
+    CYGNUM_CAN_KBAUD_10 = 1,
+    CYGNUM_CAN_KBAUD_20,
+    CYGNUM_CAN_KBAUD_50,
+    CYGNUM_CAN_KBAUD_100,
+    CYGNUM_CAN_KBAUD_125,
+    CYGNUM_CAN_KBAUD_250,
+    CYGNUM_CAN_KBAUD_500,
+    CYGNUM_CAN_KBAUD_800,
+    CYGNUM_CAN_KBAUD_1000,
+} cyg_can_baud_rate_t;
+#define CYGNUM_CAN_KBAUD_MIN CYGNUM_CAN_KBAUD_10 
+#define CYGNUM_CAN_KBAUD_MAX CYGNUM_CAN_KBAUD_1000
+
+
+// Note: two levels of macro are required to get proper expansion.
+#define _CYG_CAN_BAUD_RATE(n) CYGNUM_CAN_KBAUD_##n
+#define CYG_CAN_BAUD_RATE(n) _CYG_CAN_BAUD_RATE(n)
+
+//
+// Event types for received events. Not all event types are supported by each CAN
+// hardware but normally these events should cover the most common CAN events
+// that may occur. A combination of the event type values is allowed.
+//
+typedef enum 
+{
+    CYGNUM_CAN_EVENT_RX                  = 0x0001, // message received
+    CYGNUM_CAN_EVENT_TX                  = 0x0002, // mesage transmitted
+    CYGNUM_CAN_EVENT_WARNING_RX          = 0x0004, // tx error counter (TEC) reached warning level (>96)
+    CYGNUM_CAN_EVENT_WARNING_TX          = 0x0008, // rx error counter (REC) reached warning level (>96)
+    CYGNUM_CAN_EVENT_ERR_PASSIVE         = 0x0010, // CAN "error passive" occured
+    CYGNUM_CAN_EVENT_BUS_OFF             = 0x0020, // CAN "bus off" error occured
+    CYGNUM_CAN_EVENT_OVERRUN_RX          = 0x0040, // overrun in RX queue or hardware occured
+    CYGNUM_CAN_EVENT_OVERRUN_TX          = 0x0080, // overrun in TX queue occured
+    CYGNUM_CAN_EVENT_CAN_ERR             = 0x0100, // a CAN bit or frame error occured
+    CYGNUM_CAN_EVENT_LEAVING_STANDBY     = 0x0200, // CAN hardware leaves standby / power don mode or is waked up
+    CYGNUM_CAN_EVENT_ENTERING_STANDBY    = 0x0400, // CAN hardware enters standby / power down mode
+    CYGNUM_CAN_EVENT_ARBITRATION_LOST    = 0x0800, // arbitration lost
+    CYGNUM_CAN_EVENT_DEVICE_CHANGED      = 0x1000, // device changed event
+} cyg_can_event_type;
+
+
+//
+// CAN message type for transport or transmit of CAN messages 
+//
+typedef struct can_message
+{
+    cyg_uint32 id;
+    cyg_uint8  data[8];
+    cyg_uint8  ext;
+    cyg_uint8  rtr;
+    cyg_uint8  dlc;
+} cyg_can_message;
+
+//
+// CAN event type for reception of CAN events from driver. CAN events may be
+// a received CAN message or any other status information like tx msg or
+// arbitration lost
+//
+typedef struct cyg_can_event_st
+{
+    cyg_uint32      timestamp;
+    cyg_can_message msg;
+    cyg_uint16      type;
+} cyg_can_event;
+
+//
+// CAN configuration - at the moment there is only one data member but we are
+// prepared for future enhancements
+//
+typedef struct cyg_can_info_st {
+    cyg_can_baud_rate_t   baud;
+} cyg_can_info_t;
+
+//
+// buffer configuration - bufsize and count for tx are the number of messages
+// and for rx the number of events
+//
+typedef struct cyg_can_buf_info_st
+{  
+    cyg_int32 rx_bufsize;
+    cyg_int32 rx_count;
+    cyg_int32 tx_bufsize;
+    cyg_int32 tx_count;
+} cyg_can_buf_info_t;
+
+//
+// Timeout configuration
+//
+typedef struct cyg_can_timeout_info_st
+{
+    cyg_uint32 rx_timeout;
+    cyg_uint32 tx_timeout;
+} cyg_can_timeout_info_t;
+
+
+#define CYG_CAN_INFO_INIT(_baud) \
+  { _baud}
+
+#ifdef __cplusplus
+}
+#endif
+
+//---------------------------------------------------------------------------
+#endif // CYGONCE_CANIO_H
diff -urN ecos_web_cvs/ecos/packages/io/can/current/src/can.c ecos/ecos/packages/io/can/current/src/can.c
--- ecos_web_cvs/ecos/packages/io/can/current/src/can.c	1970-01-01 01:00:00.000000000 +0100
+++ ecos/ecos/packages/io/can/current/src/can.c	2005-05-26 21:58:02.000000000 +0200
@@ -0,0 +1,532 @@
+//==========================================================================
+//
+//      io/can/common/can.c
+//
+//      High level CAN driver
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Gary Thomas
+//
+// 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.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler
+// Contributors: Uwe Kindler
+// Date:         2005-05-12
+// Purpose:      Top level CAN driver
+// Description: 
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//==========================================================================
+//                              INCLUDES
+//==========================================================================
+#include <pkgconf/io.h>
+#include <pkgconf/io_can.h>
+
+#include <cyg/io/io.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/can.h>
+#include <cyg/infra/cyg_ass.h>      // assertion support
+#include <cyg/infra/diag.h>         // diagnostic output
+
+
+//==========================================================================
+//                                MACROS
+//==========================================================================
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+#define CYG_DRV_COND_WAIT(_cond, _time) cyg_cond_timed_wait(_cond, cyg_current_time() + (_time))
+#else
+#define CYG_DRV_COND_WAIT(_cond, _time) cyg_drv_cond_wait(_cond)
+#endif
+
+
+//==========================================================================
+//                            LOCAL FUNCTIONS
+//==========================================================================
+//
+// Device I/O functions
+//
+static Cyg_ErrNo can_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len);
+static Cyg_ErrNo can_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len);
+static cyg_bool  can_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);
+static Cyg_ErrNo can_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf, cyg_uint32 *len);
+static Cyg_ErrNo can_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *xbuf, cyg_uint32 *len);
+
+//
+// Callback functions into upper layer driver
+//
+static void can_init(can_channel *chan);    
+static void can_rcv_event(can_channel *chan, void *pdata);
+static void can_xmt_msg(can_channel *chan, void *pdata);
+
+//
+// Device I/O table
+//
+DEVIO_TABLE(cyg_io_can_devio,
+            can_write,
+            can_read,
+            can_select,
+            can_get_config,
+            can_set_config
+    );
+
+
+//
+// Callbacks into upper layer driver
+//
+CAN_CALLBACKS(cyg_io_can_callbacks, 
+              can_init, 
+              can_xmt_msg,
+              can_rcv_event);
+
+
+//===========================================================================
+// Initialize CAN driver
+//===========================================================================
+static void can_init(can_channel *chan)
+{
+    can_cbuf_t *cbuf;
+    
+    if (chan->init) 
+    {
+        return;
+    }
+    
+    cbuf = &chan->in_cbuf;
+    cyg_drv_mutex_init(&cbuf->lock);
+    cyg_drv_cond_init(&cbuf->wait, &cbuf->lock);
+    
+    cbuf = &chan->out_cbuf;
+    cyg_drv_mutex_init(&cbuf->lock);
+    cyg_drv_cond_init(&cbuf->wait, &cbuf->lock);
+    
+    chan->init = true;
+}
+
+
+//===========================================================================
+// Write exactly one CAN message to CAN bus
+//===========================================================================
+static Cyg_ErrNo can_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len)
+{
+    cyg_devtab_entry_t *t      = (cyg_devtab_entry_t *)handle;
+    can_channel        *chan   = (can_channel *)t->priv;
+    can_lowlevel_funs  *funs   = chan->funs;
+    Cyg_ErrNo           res    = ENOERR;
+    can_cbuf_t         *cbuf   = &chan->out_cbuf;
+    cyg_uint32          size   = *len;
+    
+    //
+    // the user need to provide a can message buffer
+    //
+    if (*len != sizeof(cyg_can_message))
+    {
+        return -EINVAL;
+    }
+    
+    cyg_drv_mutex_lock(&cbuf->lock);
+    cbuf->abort = false;
+    cyg_drv_dsr_lock(); // avoid race condition while testing pointers
+    
+    while (size > 0)
+    {
+        if (cbuf->data_cnt == cbuf->len) 
+        {
+            cbuf->waiting = true;      // Buffer full - wait for space
+            funs->start_xmit(chan);    // Make sure xmit is running
+            //
+            // Check flag: 'start_xmit' may have obviated the need
+            // to wait
+            //
+            if (cbuf->waiting) 
+            {
+                cbuf->pending += size;  // Have this much more to send [eventually]
+                if(!CYG_DRV_COND_WAIT(&cbuf->wait, cbuf->timeout))
+                {
+                    cbuf->abort = true;
+                }
+                cbuf->pending -= size;
+                if (cbuf->abort) 
+                {
+                    // Give up!
+                    *len -= size;   // number of characters actually sent
+                     cbuf->abort = false;
+                     cbuf->waiting = false;
+                     res = -EINTR;
+                     break;
+                } // if (cbuf->abort) 
+            } // if (cbuf->waiting)
+        } // if (cbuf->data_cnt == cbuf->len) 
+        else
+        {           
+            //
+            // there is enougth space left so we can store additional data
+            //
+            cyg_can_message *ptxbuf       = (cyg_can_message *)cbuf->pdata;
+            cyg_can_message *pbuf_message = &ptxbuf[cbuf->put];
+            cyg_can_message *pmessage     = (cyg_can_message *)_buf;
+            
+            *pbuf_message = *pmessage; // copy message
+   
+            cbuf->put = (cbuf->put + 1) % cbuf->len;
+            cbuf->data_cnt++;   
+            size -= sizeof(cyg_can_message);   
+        }
+    } // while (size > 0)
+    
+    (funs->start_xmit)(chan);  // Start output as necessary
+    cyg_drv_dsr_unlock();            
+    cyg_drv_mutex_unlock(&cbuf->lock);
+    return res;
+}
+
+
+//===========================================================================
+// Read one single CAN event from hw
+//===========================================================================
+static Cyg_ErrNo can_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len)
+{
+    cyg_devtab_entry_t *t      = (cyg_devtab_entry_t *)handle;
+    can_channel        *chan   = (can_channel *)t->priv;
+    can_cbuf_t         *cbuf   = &chan->in_cbuf;
+    cyg_uint32          size   = 0;
+    Cyg_ErrNo           res    = ENOERR;
+    
+    //
+    // the user need to provide a can event buffer
+    //
+    if (*len != sizeof(cyg_can_event))
+    {
+        return -EINVAL;
+    }
+    
+    cyg_drv_mutex_lock(&cbuf->lock);
+    cbuf->abort = false;
+    
+    cyg_drv_dsr_lock();  // avoid race conditions
+    while (size < *len)
+    {
+        //
+        // if message buffer contains at least one message then read the
+        // oldest message from buffer and return
+        //
+        if (cbuf->data_cnt > 0)
+        {
+            cyg_can_event *prxbuf     = (cyg_can_event *)cbuf->pdata;   
+            cyg_can_event *pbuf_event = &prxbuf[cbuf->get];
+            cyg_can_event *pevent     = (cyg_can_event *)_buf;
+
+            *pevent = *pbuf_event; // copy event
+            
+            cbuf->get = (cbuf->get + 1) % cbuf->len;
+            cbuf->data_cnt--; 
+            size += sizeof(cyg_can_event);
+        }
+        else
+        {
+            //
+            // if messaeg buffer does not contain any message, then wait until
+            // a message arrives
+            //
+            cbuf->waiting = true;
+            if(!CYG_DRV_COND_WAIT(&cbuf->wait, cbuf->timeout))
+            {
+                cbuf->abort = true;
+            }
+            
+            if (cbuf->abort)
+            {
+                *len = size;
+                cbuf->abort = false;
+                cbuf->waiting = false;
+                res = -EINTR;
+                break;
+            }
+        }
+    } // while (size < *len)
+    cyg_drv_dsr_unlock();
+    
+    cyg_drv_mutex_unlock(&cbuf->lock);
+    
+    return res;
+}
+
+
+//===========================================================================
+// Query CAN channel configuration data
+//===========================================================================
+static Cyg_ErrNo can_get_config(cyg_io_handle_t handle, 
+               cyg_uint32      key, 
+               void           *xbuf,
+               cyg_uint32     *len)
+{
+    cyg_devtab_entry_t *t         = (cyg_devtab_entry_t *)handle;
+    can_channel        *chan      = (can_channel *)t->priv;
+    Cyg_ErrNo           res       = ENOERR;
+    cyg_can_info_t     *pcan_info = (cyg_can_info_t *)xbuf;
+    can_cbuf_t         *out_cbuf  = &chan->out_cbuf;
+    can_cbuf_t         *in_cbuf   = &chan->in_cbuf;
+    
+    switch (key)
+    {
+        case CYG_IO_GET_CONFIG_CAN_INFO :
+             if (*len < sizeof(cyg_can_info_t)) 
+             {
+                 return -EINVAL;
+             }
+             *pcan_info = chan->config;
+             *len       = sizeof(chan->config);
+             break;
+        //
+        // return rx/tx buffer sizes and counts 
+        //    
+        case CYG_IO_GET_CONFIG_CAN_BUFFER_INFO :
+             {
+                 cyg_can_buf_info_t *pbuf_info;
+                 if (*len < sizeof(cyg_can_buf_info_t))
+                 {
+                     return -EINVAL; 
+                 } 
+          
+                *len = sizeof(cyg_can_buf_info_t);
+                pbuf_info = (cyg_can_buf_info_t *)xbuf;
+                pbuf_info->rx_bufsize = in_cbuf->len;
+                if (pbuf_info->rx_bufsize)
+                {
+                    pbuf_info->rx_count = in_cbuf->data_cnt ;
+                }
+                else
+                {
+                    pbuf_info->rx_count = 0;
+                }            
+                pbuf_info->tx_bufsize = out_cbuf->len;
+                if (pbuf_info->tx_bufsize)
+                {
+                    pbuf_info->tx_count = out_cbuf->data_cnt;
+                }
+                else
+                {
+                    pbuf_info->tx_count = 0;
+                }
+            }
+            break; // case CYG_IO_GET_CONFIG_CAN_BUFFER_INFO
+
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS            
+            //
+            // return current timeouts
+            //
+            case CYG_IO_GET_CONFIG_CAN_TIMEOUT :
+                 {
+                     cyg_can_timeout_info_t *ptimeout_info;
+                     if (*len < sizeof(cyg_can_timeout_info_t))
+                     {
+                         return -EINVAL; 
+                     } 
+                     
+                     *len = sizeof(cyg_can_timeout_info_t);
+                      ptimeout_info = (cyg_can_timeout_info_t *)xbuf;
+                      
+                      ptimeout_info->rx_timeout = in_cbuf->timeout;
+                      ptimeout_info->tx_timeout = out_cbuf->timeout;
+                 }
+                 break; // case CYG_IO_GET_CONFIG_CAN_TIMEOUT_INFO
+#endif // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+        
+        default:
+            res = -EINVAL;   
+    } // switch (key)
+    
+    return res;
+}
+
+
+//===========================================================================
+// Set CAN channel configuration
+//===========================================================================
+static Cyg_ErrNo can_set_config(cyg_io_handle_t handle, 
+               cyg_uint32      key,
+               const void     *xbuf, 
+               cyg_uint32     *len)
+{
+    cyg_devtab_entry_t *t         = (cyg_devtab_entry_t *)handle;
+    can_channel        *chan      = (can_channel *)t->priv;
+    Cyg_ErrNo           res       = ENOERR;
+    can_lowlevel_funs  *funs      = chan->funs;
+    can_cbuf_t         *out_cbuf  = &chan->out_cbuf;
+    can_cbuf_t         *in_cbuf   = &chan->in_cbuf;
+    
+    switch (key)
+    {
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS            
+        //
+        // return current timeouts
+        //
+        case CYG_IO_SET_CONFIG_CAN_TIMEOUT :
+             {
+                 cyg_can_timeout_info_t *ptimeout_info;
+                 if (*len < sizeof(cyg_can_timeout_info_t))
+                 {
+                     return -EINVAL; 
+                 } 
+                   
+                 *len = sizeof(cyg_can_timeout_info_t);
+                  ptimeout_info = (cyg_can_timeout_info_t *)xbuf;
+                   
+                  in_cbuf->timeout = ptimeout_info->rx_timeout;
+                  out_cbuf->timeout = ptimeout_info->tx_timeout;
+             }
+             break; // case CYG_IO_GET_CONFIG_CAN_TIMEOUT_INFO
+#endif // CYGOPT_IO_CAN_SUPPORT_TIMEOUTS
+        
+        default:
+            //
+            // pass down to lower layers
+            //
+            res = (funs->set_config)(chan, key, xbuf, len);
+    } // switch (key)
+    
+    return res;
+}
+
+
+//===========================================================================
+// Select support for CAN channel
+//===========================================================================
+static cyg_bool can_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
+{
+    //
+    // do nothing here because we currently do not support select
+    //
+    return true;
+}
+
+
+//===========================================================================
+// Callback for received events
+//===========================================================================
+static void can_rcv_event(can_channel *chan, void *pdata)
+{
+    can_cbuf_t     *cbuf   = &chan->in_cbuf;
+    cyg_can_event  *prxbuf = (cyg_can_event *)cbuf->pdata;
+    
+    //
+    // cbuf is a ring buffer - if the buffer is full, then we overwrite the
+    // oldest message in buffer so the user will always get the actual and
+    // last state of the external hardware that is connected to the
+    // CAN bus. 
+    //
+    if (chan->funs->getevent(chan, &prxbuf[cbuf->put], pdata))
+    {
+        if (cbuf->data_cnt < cbuf->len)
+        {
+            cbuf->data_cnt++;
+        }
+        else
+        {
+            //
+            // the buffer is full but a new message arrived. We store this new
+            // message and overwrite the oldest one, but at least we tell the user
+            // that there is an overrun in RX queue
+            //
+            prxbuf[cbuf->put].type |= CYGNUM_CAN_EVENT_OVERRUN_RX;
+            cbuf->get = (cbuf->get + 1) % cbuf->len;
+        }
+        
+        cbuf->put = (cbuf->put + 1) % cbuf->len;
+        
+        if (cbuf->waiting) 
+        {
+            cbuf->waiting = false;
+            cyg_drv_cond_broadcast(&cbuf->wait);
+        }
+    }
+}
+
+
+//===========================================================================
+// Callback function for transmit events
+//===========================================================================
+static void can_xmt_msg(can_channel *chan, void *pdata)
+{
+    can_cbuf_t        *cbuf    = &chan->out_cbuf;
+    can_lowlevel_funs *funs    = chan->funs;  
+    cyg_can_message   *ptxbuf  = (cyg_can_message *)cbuf->pdata;
+    cyg_can_message   *pbuf_txmsg;
+
+    //
+    // transmit messages as long as there are messages in the buffer 
+    //
+    while (cbuf->data_cnt > 0)
+    {
+        pbuf_txmsg = &ptxbuf[cbuf->get];
+        
+        if (funs->putmsg(chan, pbuf_txmsg, pdata))
+        {
+            cbuf->get = (cbuf->get + 1) % cbuf->len;
+            cbuf->data_cnt--;
+        }
+        else
+        {
+            //
+            // we are here because the hardware is busy at the moment and
+            // we can't send another message - now we check if there is already
+            // some space in buffer so we can wakeup the writer
+            //
+            if ((cbuf->len - cbuf->data_cnt) > 0)
+            {
+                if (cbuf->waiting)
+                {
+                    cbuf->waiting = false;
+                    cyg_drv_cond_broadcast(&cbuf->wait);
+                }
+            }
+            return;
+        }
+    } // while (cbuf->data_cnt > 0)
+    funs->stop_xmit(chan);  // Done with transmit
+    
+    if (cbuf->waiting)
+    {
+        cbuf->waiting = false;
+        cyg_drv_cond_broadcast(&cbuf->wait);
+    }            
+}
+
+
+//---------------------------------------------------------------------------
+// end of can.c
diff -urN ecos_web_cvs/ecos/packages/devs/can/m68k/mcf52xx/current/ChangeLog ecos/ecos/packages/devs/can/m68k/mcf52xx/current/ChangeLog
--- ecos_web_cvs/ecos/packages/devs/can/m68k/mcf52xx/current/ChangeLog	1970-01-01 01:00:00.000000000 +0100
+++ ecos/ecos/packages/devs/can/m68k/mcf52xx/current/ChangeLog	2005-05-24 20:08:57.000000000 +0200
@@ -0,0 +1,38 @@
+2005-05-24  Uwe Kindler  <uwe_kindler@web.de>
+
+	* mcf52xx FlexCAN driver package created
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
diff -urN ecos_web_cvs/ecos/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl ecos/ecos/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl
--- ecos_web_cvs/ecos/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl	1970-01-01 01:00:00.000000000 +0100
+++ ecos/ecos/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl	2005-05-24 00:26:15.000000000 +0200
@@ -0,0 +1,331 @@
+# ====================================================================
+#
+#      can_mcf52xx.cdl
+#
+#      eCos MCF52xx FlexCAN configuration data
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2003, 2004 eCosCentric Limited
+##
+## 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.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+##
+## 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:
+# Date:           2005-05-17
+#
+#####DESCRIPTIONEND####
+# ====================================================================
+
+
+cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN {
+    display       "CAN driver for FlexCAN module of coldfire mcf52xx family"
+
+    parent        CYGPKG_IO_CAN_DEVICES
+    active_if     CYGPKG_IO_CAN
+    active_if     CYGPKG_HAL_M68K_MCF52xx
+
+    requires      CYGPKG_ERROR
+
+    description   "
+           This package provides a generic CAN device driver for the on-chip
+           FlexCAN modules in MCF52xx ColdFire processors."
+    compile       -library=libextras.a   can_mcf52xx.c
+    define_proc {
+        puts $::cdl_system_header "/***** CAN driver proc output start *****/"
+        puts $::cdl_system_header "#define CYGDAT_IO_CAN_DEVICE_HEADER <pkgconf/devs_can_mcf52xx_flexcan.h>"
+        puts $::cdl_system_header "/*****  CAN driver proc output end  *****/"
+    }
+    
+    # Support up to two on-chip FlexCAN modules. The number varies between
+    # processor variants
+    for { set ::flexcan 0 } { $::flexcan < 2 } { incr ::flexcan } {
+    
+        cdl_interface CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan] {
+            display     "Platform provides FlexCAN [set ::flexcan]"
+            flavor      bool
+            description "
+                This interface will be implemented if the specific coldfire
+                processor being used has an on-chip FlexCAN[set ::flexcan], and if
+                that FlexCAN is accessible on the target hardware."
+        }
+    
+        cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan] {
+            display     "Allow access to the on-chip FlexCAN[set ::flexcan] via a CAN driver"
+            flavor      bool
+            active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+            default_value   1
+            implements      CYGINT_IO_CAN_TIMESTAMP
+            
+            description "
+                If the application needs to access the on-chip FlexCAN[set ::flexcan]
+                via an eCos CAN driver then this option should be enabled."
+
+            cdl_option CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_NAME {
+                display     "Device name for FlexCAN [set ::flexcan]"
+                flavor      data
+                default_value   [format {"\"/dev/can%d\""} $::flexcan]
+                description "
+                    This option controls the name that an eCos application
+                    should use to access this device via cyg_io_lookup(),
+                    open(), or similar calls."
+            }
+
+        
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_KBAUD {
+                display     "Default baud rate for FlexCAN [set ::flexcan]"
+                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 FlexCAN [set ::flexcan]"
+            }
+
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_QUEUESIZE_TX {
+                display     "Size of TX Queue for the FlexCAN [set ::flexcan] driver"
+                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_MCF52xx_FLEXCAN[set ::flexcan]_QUEUESIZE_RX {
+                display     "Size of RX Queue for the FlexCAN [set ::flexcan] driver"
+                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_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_GLOBAL {
+                display     "Receive mask for message buffers 0 - 13"
+                flavor      data
+                default_value   0x1FFFFFFF
+                description "
+                    The global RX-mask is composed of 4 bytes. The mask bits are
+                    applied to all Rx-Identifiers excluding Rx-buffers 14-15, that 
+                    have their specific Rx-mask. (0 corresponding incoming ID bit is 
+                    \"don?t care\". 1 corresponding ID bit is checked against the incoming 
+                    ID bit, to see if a match exists). By default the message buffers
+                    should only receive messages that exactly match the configured
+                    message buffer CAN identifier - that means alle bits are 1."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_14 {
+                display     "Receive mask for message buffer 14"
+                flavor      data
+                default_value   0x0
+                description "
+                    The RX-mask for message buffer 14 is composed of 4 bytes. The mask
+                    bits are applied to message buffer 14. (0 corresponding incoming ID 
+                    bit is \"don?t care\". 1 corresponding ID bit is checked against the 
+                    incoming ID bit, to see if a match exists). Message buffer 14 is
+                    the receive message buffer and should receive all available CAN
+                    messages - all bits are 0."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_15 {
+                display     "Receive mask for message buffer 15"
+                flavor      data
+                default_value   0x1FFFFFFF
+                description "
+                    The RX-mask for message buffer 15 is composed of 4 bytes. The mask
+                    bits are applied to message buffer 15. (0 corresponding incoming ID 
+                    bit is \"don?t care\". 1 corresponding ID bit is checked against the 
+                    incoming ID bit, to see if a match exists)."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_WAKEINT {
+                display     "Wake interrupt priority"
+                flavor      data
+                default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_WAKEINT) ? \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_WAKEINT : \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                description "
+                    Interrupt priority for wake interrupt."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_ERRINT {
+                display     "Error interrupt priority"
+                flavor      data
+                default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_ERRINT) ? \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_ERRINT : \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                description "
+                    Interrupt priority for error interrupt."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_BOFFINT {
+                display     "Bus off interrupt priority"
+                flavor      data
+                default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_BOFFINT) ? \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_BOFFINT : \
+                                CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                description "
+                    Interrupt priority for bus off interrupt."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_RX_MBOX {
+                display "Default receive message buffer"
+                flavor  data
+                calculated    14
+                legal_values  0 to 15
+                description "
+                    By default one message buffer will be used for message transmission.
+                    This option selects one of the 16 FlexCAN message buffers for
+                    transmission."
+            }
+            
+            cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_TX_MBOX {
+                display "Default transmit message buffer"
+                flavor  data
+                calculated    15
+                legal_values  0 to 15
+                description "
+                    By default one message buffer will be used for reception of
+                    all CAN messages. This option selects one of the 16 message
+                    buffers for reception."
+            }
+            
+            cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOXCFG {
+                display     "Message buffer configuration"
+                flavor       none
+                active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                description "
+                    The FlexCAN module contains 16 flexible message buffers of 0-8 bytes 
+                    data length, each configurable as Rx or Tx, all supporting standard and 
+                    extended messages. At the moment a fixed configuration is used for
+                    TX and RX message buffers but in future this may be configurable."
+                
+                cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOX14_CFG {
+                    display "Message buffer 14 configuration"
+                    flavor  none
+                    active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                    description "
+                       Configuration of FlexCAN message buffer 14."
+                   
+                    cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_MBOX14 {
+                        display     "Interrupt priority."
+                        flavor      data
+                        default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_MBOX14) ? \
+                                    CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_MBOX14 : \
+                                    CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                        legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                        description "
+                            Interrupt priority for message buffer 14"
+                    }
+                    
+                    cdl_option CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOX14_IS_TX {
+                        display "Use for transmit"
+                        flavor  bool
+                        active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                        calculated      0
+                        description "
+                            This option controls if this message buffer is used for sending
+                            or receiving messages. Currently this option is not configurable
+                            and message box 14 is used for reception of CAN messages."
+                        
+                    }
+                }
+                
+                cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOX15_CFG {
+                    display "Message buffer 15 configuration"
+                    flavor  none
+                    active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                    description "
+                       Configuration of FlexCAN message buffer 15."
+                   
+                    cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_MBOX15 {
+                        display     "Interrupt priority."
+                        flavor      data
+                        default_value   is_loaded(CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_MBOX15) ? \
+                                    CYGNUM_HAL_M68K_MCF52xx_ISR_DEFAULT_PRIORITY_FLEXCAN[set ::flexcan]_MBOX15 : \
+                                    CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN
+                        legal_values   CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MIN to CYGNUM_HAL_M68K_MCF52xx_ISR_PRIORITY_MAX
+                        description "
+                            Interrupt priority for message buffer 15"
+                    }
+                    
+                    cdl_option CYGOPT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOX15_IS_TX {
+                        display "Use for transmit"
+                        flavor  bool
+                        active_if       CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
+                        calculated      1
+                        description "
+                            This option controls if this message buffer is used for sending
+                            or receiving messages. Currently this option is not configurable
+                            and message box 15 is used for transmission of CAN messages."
+                        
+                    }
+                }
+            } 
+        }    
+    }
+
+
+    cdl_component CYGPKG_IO_CAN_MCF52xx_FLEXCAN_OPTIONS {
+        display "FlexCAN 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_IO_CAN_MCF52xx_FLEXCAN_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building these CAN device drivers. These flags are
+                used in addition to the set of global flags."
+        }
+
+        cdl_option CYGPKG_IO_CAN_MCF52xx_FLEXCAN_CFLAGS_REMOVE {
+            display "Suppressed compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building these CAN device drivers. These flags are
+                removed from the set of global flags if present."
+        }
+    }
+}
diff -urN ecos_web_cvs/ecos/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c ecos/ecos/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c
--- ecos_web_cvs/ecos/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c	1970-01-01 01:00:00.000000000 +0100
+++ ecos/ecos/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c	2005-05-23 22:51:02.000000000 +0200
@@ -0,0 +1,1398 @@
+//==========================================================================
+//
+//      devs/serial/m68k/flexcan/current/src/can_mcf_flexcan.c
+//
+//      CAN driver for Motorola coldfire processors
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Gary Thomas
+//
+// 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.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Uwe Kindler
+// Contributors: Uwe Kindler
+// Date:         2005-05-12
+// Purpose:      support coldfire on-chip flexcan moduls
+// Description: 
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//==========================================================================
+//                              INCLUDES
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/io_can.h>
+#include <pkgconf/devs_can_mcf52xx_flexcan.h>
+
+#include <cyg/infra/diag.h>
+
+#include <cyg/io/io.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/can.h>
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_io.h>
+
+
+//===========================================================================
+//                                DEFINES  
+//===========================================================================
+
+//
+// we define our own ste of register bits in order to be independent from
+// platform specific names
+//
+
+//---------------------------------------------------------------------------
+// MCR regsiter bits
+//
+#define FLEXCAN_MCR_STOP                    (0x01 << 15)
+#define FLEXCAN_MCR_FRZ                     (0x01 << 14)
+#define FLEXCAN_MCR_HALT                    (0x01 << 12)
+#define FLEXCAN_MCR_NOTRDY                  (0x01 << 11)
+#define FLEXCAN_MCR_WAKEMSK                 (0x01 << 10)
+#define FLEXCAN_MCR_SOFTRST                 (0x01 << 9)
+#define FLEXCAN_MCR_FRZACK                  (0x01 << 8)
+#define FLEXCAN_MCR_SUPV                    (0x01 << 7)
+#define FLEXCAN_MCR_SELFWAKE                (0x01 << 6)
+#define FLEXCAN_MCR_APS                     (0x01 << 5)
+#define FLEXCAN_MCR_STOPACK                 (0x01 << 4)
+
+
+//---------------------------------------------------------------------------
+// CTRL0 register bits
+//
+#define FLEXCAN_CTRL0_BOFFMSK                   (0x01 << 7)
+#define FLEXCAN_CTRL0_ERRMASK                   (0x01 << 6)
+#define FLEXCAN_CTRL0_RXMODE                    (0x01 << 2)
+#define FLEXCAN_CTRL0_RXMODE_0_DOMINANT         (0x00 << 2)
+#define FLEXCAN_CTRL0_RXMODE_1_DOMINANT         (0x01 << 2)
+#define FLEXCAN_CTRL0_TXMODE_MASK               (0x03 << 0)
+#define FLEXCAN_CTRL0_TXMODE_SHIFT              0
+#define FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT    (0x00 << 0)
+#define FLEXCAN_CTRL0_TXMODE_FULL_1_DOMINANT    (0x01 << 0)
+#define FLEXCAN_CTRL0_TXMODE_OPEN_0_DOMINANT    (0x02 << 0)
+
+
+//---------------------------------------------------------------------------
+// CTRL1 register bits
+//
+#define FLEXCAN_CTRL1_SAMP                      (0x01 << 7)
+#define FLEXCAN_CTRL1_TSYNC                     (0x01 << 5)
+#define FLEXCAN_CTRL1_LBUF                      (0x01 << 4)
+#define FLEXCAN_CTRL1_LOM                       (0x01 << 3)
+#define FLEXCAN_CTRL1_PROPSEG_MASK              (0x07 << 0)
+#define FLEXCAN_CTRL1_PROPSEG_SHIFT             0
+
+
+//---------------------------------------------------------------------------
+// CTRL2 register bits
+//
+#define FLEXCAN_CTRL2_RJW_MASK                  (0x03 << 6)
+#define FLEXCAN_CTRL2_RJW_SHIFT                 6
+#define FLEXCAN_CTRL2_PSEG1_MASK                (0x07 << 3)
+#define FLEXCAN_CTRL2_PSEG1_SHIFT               3
+#define FLEXCAN_CTRL2_PSEG2_MASK                (0x07 << 0)
+#define FLEXCAN_CTRL2_PSEG2_SHIFT               0
+
+//---------------------------------------------------------------------------
+// ESTAT register bits
+//
+#define FLEXCAN_ESTAT_BITERR_MASK               (0x03 << 14)
+#define FLEXCAN_ESTAT_BITERR_SHIFT              14
+#define FLEXCAN_ESTAT_BITERR_NONE               (0x00 << 14)
+#define FLEXCAN_ESTAT_BITERR_DOMINANT_RECESSIVE (0x01 << 14)
+#define FLEXCAN_ESTAT_BITERR_RECESSIVE_DOMINANT (0x02 << 14)
+#define FLEXCAN_ESTAT_ACKERR                    (0x01 << 13)
+#define FLEXCAN_ESTAT_CRCERR                    (0x01 << 12)
+#define FLEXCAN_ESTAT_FORMERR                   (0x01 << 11)
+#define FLEXCAN_ESTAT_STUFFERR                  (0x01 << 10)
+#define FLEXCAN_ESTAT_TXWARN                    (0x01 << 9)
+#define FLEXCAN_ESTAT_RXWARN                    (0x01 << 8)
+#define FLEXCAN_ESTAT_IDLE                      (0x01 << 7)
+#define FLEXCAN_ESTAT_TX_RX                     (0x01 << 6)
+#define FLEXCAN_ESTAT_FCS_MASK                  (0x03 << 4)
+#define FLEXCAN_ESTAT_FCS_SHIFT                 4
+#define FLEXCAN_ESTAT_FCS_ERROR_ACTIVE          (0x00 << 4)
+#define FLEXCAN_ESTAT_FCS_ERROR_PASSIVE         (0x01 << 4)
+#define FLEXCAN_ESTAT_BOFFINT                   (0x01 << 2)
+#define FLEXCAN_ESTAT_ERRINT                    (0x01 << 1)
+#define FLEXCAN_ESTAT_WAKEINT                   (0x01 << 0)
+
+//
+// For receive event calls we use these two identifiers for
+// err and bus off events - message boxes use 0 - 15
+//
+#define FLEXCAN_ERR_EVENT                       16
+#define FLEXCAN_BUSOFF_EVENT                    17
+
+
+//---------------------------------------------------------------------------
+// message buffer cfg bits
+//
+#define MBOX_RXCODE_NOT_ACTIVE 0x00
+#define MBOX_RXCODE_BUSY       0x10
+#define MBOX_RXCODE_EMPTY      0x40
+#define MBOX_RXCODE_FULL       0x20
+#define MBOX_RXCODE_OVERRUN    0x60
+
+#define MBOX_TXCODE_NOT_READY  0x80
+#define MBOX_TXCODE_TRANSMIT   0xC0
+#define MBOX_TXCODE_RESPONSE   0xA0
+
+#define MBOX_DATA_FRAME        0x00 // data frame
+#define MBOX_REMOTE_FRAME      0x01 // remote frame
+#define MBOX_STD_ID            0x00 // standard identifier
+#define MBOX_EXT_ID            0x01 // remote identifier
+#define MBOX_TX                0x08 // tx message box
+#define MBOX_RX                0x00 // rx messge box
+
+#define MBOX_CFG_IDE           0x08
+#define MBOX_CFG_RTR_EXT       0x01
+#define MBOX_CFG_RTR_STD       0x10
+#define MBOX_CFG_SSR           0x10
+#define MBOX_CFG_DLC_MASK      0x0F
+#define MBOX_CFG_STAT_MASK     0xF0
+
+
+//===========================================================================
+//                                 DATA TYPES
+//===========================================================================
+//
+// configuration info for flexcan message buffer
+//
+typedef struct flexcan_mbox_info_st
+{
+    cyg_vector_t  isr_vec;
+    int           isr_priority;
+    cyg_interrupt interrupt;
+    cyg_handle_t  interrupt_handle;   
+    cyg_uint8     num;  
+} flexcan_mbox_info; 
+
+//
+// flexcan interrupt (busoff, err, wake) data
+//
+typedef struct flexcan_int_st
+{
+    cyg_vector_t        isr_vec;  
+    int                 isr_priority;
+    cyg_interrupt       interrupt;
+    cyg_handle_t        interrupt_handle;
+} flexcan_int;
+
+//
+// flexcan message box initialisation
+//
+#define FLEXCAN_MBOX_INIT(_mbox0_vec, _prio, _mbox_no) { \
+    isr_vec      : (_mbox0_vec) + (_mbox_no),            \
+    isr_priority : (_prio),                              \
+    num          : (_mbox_no)                            \
+}
+
+//
+// Interrupt initialisation
+//
+#define FLEXCAN_INT_INIT(_vec, _prio) \
+{                                     \
+    isr_vec      : (_vec),            \
+    isr_priority : (_prio)            \
+}
+
+//
+// flexcan configuration 
+//
+typedef struct flexcan_info 
+{
+    cyg_uint8          *base;          // base address of flexcan modul
+    cyg_vector_t        isr_vec_mbox0; // vector number of ISR vector of first message box
+    flexcan_mbox_info   rx_mbox;       // rx message box interrupt
+    flexcan_mbox_info   tx_mbox;       // tx message box interrupt
+    cyg_uint32          last_tx_id;    // last transmitted message
+    bool                tx_busy;       // indicates if transmit process ic currently running
+    
+    cyg_uint32          rxgmask;       // acceptance filter for message box 0 - 13
+    cyg_uint32          rx14mask;      // acceptance filter for message box 14
+    cyg_uint32          rx15mask;      // acceptance filter for message box 15
+    
+    flexcan_int         boff_int;      // bus off interrupt data
+    flexcan_int         err_int;       // error interrupt data
+ 
+    cyg_uint32          timeout_rd;
+    cyg_uint32          timeout_wr;
+#ifdef FLEXCAN_CAN_STATS
+    cyg_uint32          isr_count;
+    cyg_uint32          dsr_count;
+    cyg_uint32          rx_bytes;
+    cyg_uint32          tx_bytes;
+    cyg_uint32          rx_errors;
+#endif  
+} flexcan_info;
+
+
+//
+// flexcan info initialisation
+//
+#define FLEXCAN_INFO(_l,                                                \
+                     _baseaddr,                                         \
+                     _isr_vec_mbox0,                                    \
+                     _rx_mbox_no, _rx_isr_prio,                         \
+                     _tx_mbox_no, _tx_isr_prio,                         \
+                     _boff_isr_vec, _boff_isr_prio,                     \
+                     _err_isr_vec, _err_isr_prio)                       \
+flexcan_info _l = {                                                     \
+    (void *)( _baseaddr),                                               \
+    (_isr_vec_mbox0),                                                   \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_rx_isr_prio), (_rx_mbox_no)), \
+    FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_tx_isr_prio), (_tx_mbox_no)), \
+    0xFFFFFFFF,                                                         \
+    false,                                                              \
+    rxgmask       : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_GLOBAL,     \
+    rx14mask      : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_14,         \
+    rx15mask      : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_15,         \
+    boff_int      : FLEXCAN_INT_INIT(_boff_isr_vec, _boff_isr_prio),    \
+    err_int       : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio)       \
+};
+
+
+//===========================================================================
+//                          GLOBAL DATA
+//===========================================================================
+//
+// Note: two levels of macro are required to get proper expansion.
+//
+#define _FLEXCAN_MBOX_INTPRIO(n) CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX##n
+#define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n)
+
+//
+// FlexCAN channel initialisation
+//
+FLEXCAN_INFO(flexcan_can0_info, 
+             HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
+             HAL_MCF52xx_FLEXCAN0_MBOX0_ISRVEC,
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX, 
+             FLEXCAN_MBOX_INTPRIO(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX),
+             CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX, 
+             FLEXCAN_MBOX_INTPRIO(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX),
+             HAL_MCF52xx_FLEXCAN0_BOFF_ISRVEC,
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_BOFFINT,  
+             HAL_MCF52xx_FLEXCAN0_ERR_ISRVEC,          
+             CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_ERRINT);
+
+//
+// message box structure
+//
+typedef struct flexcan_mbox
+{
+    cyg_uint8  timestamp;
+    cyg_uint8  ctrlstat;
+    cyg_uint16 id_hi;
+    cyg_uint16 id_lo;
+    cyg_uint8  data[8];
+    cyg_uint16 reserved;
+} flexcan_mbox;
+
+//
+// flexcan register layout
+//
+typedef struct flexcan_regs
+{
+    cyg_uint16 CANMCR;       // 0x00
+    cyg_uint16 reserved0[2]; // 0x02
+    cyg_uint8  CANCTRL0;     // 0x06
+    cyg_uint8  CANCTRL1;     // 0x07
+    cyg_uint8  PRESDIV;      // 0x08
+    cyg_uint8  CANCTRL2;     // 0x09
+    cyg_uint16 TIMER;        // 0x0A
+    cyg_uint16 reserved1[2]; // 0x0C
+    cyg_uint16 RXGMASK_HI;   // 0x10
+    cyg_uint16 RXGMASK_LO;   // 0x12
+    cyg_uint16 RX14MASK_HI;  // 0x14
+    cyg_uint16 RX14MASK_LO;  // 0x16
+    cyg_uint16 RX15MASK_HI;  // 0x18
+    cyg_uint16 RX15MASK_LO;  // 0x1A
+    cyg_uint16 reserved2[2]; // 0x1C
+    cyg_uint16 ESTAT;        // 0x20
+    cyg_uint16 IMASK;        // 0x22
+    cyg_uint16 IFLAG;        // 0x24
+    cyg_uint8  RXERRCNT;     // 0x26
+    cyg_uint8  TXERRCNT;     // 0x27
+    cyg_uint16 reserved3[44];// 0x28
+    flexcan_mbox mbox[16]; // 0x80
+} flexcan_regs;
+
+
+//===========================================================================
+//                                 LOCAL DATA
+//===========================================================================
+static cyg_uint16 flexcan_baud_rates[] = {
+    0,      // Unused
+    10,     // 10 kbit/s
+    20,     // 20
+    50,     // 50
+    100,    // 100
+    125,    // 125
+    250,    // 250
+    500,    // 500
+    800,    // 800
+    1000,   // 1000 kbit/s
+};
+
+
+//===========================================================================
+//                              PROTOTYPES
+//===========================================================================
+static bool        flexcan_init(struct cyg_devtab_entry* devtab_entry);
+static Cyg_ErrNo   flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
+static Cyg_ErrNo   flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
+static bool        flexcan_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
+static bool        flexcan_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
+static void        flexcan_start_xmit(can_channel* chan);
+static void        flexcan_stop_xmit(can_channel* chan);
+
+//
+// TX and RX ISRs and DSRs
+//
+static cyg_uint32  flexcan_mbox_rx_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_mbox_rx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+static cyg_uint32  flexcan_mbox_tx_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_mbox_tx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+
+//
+// All other flexcan interrupt handlers
+//
+static cyg_uint32  flexcan_err_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_err_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+static cyg_uint32  flexcan_busoff_isr(cyg_vector_t, cyg_addrword_t);
+static void        flexcan_busoff_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
+
+
+static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox, cyg_can_message  *pmsg);
+static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_uint32 canid, cyg_uint8 ext);
+static void flexcan_read_from_mbox(can_channel *chan, cyg_uint8 mbox, cyg_can_event *pevent, cyg_uint8 *ctrlstat);
+static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext);
+static void flexcan_start_chip(can_channel *chan);
+static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baudrate);
+static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
+
+
+CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs,
+                  flexcan_putmsg,
+                  flexcan_getevent,
+                  flexcan_set_config,
+                  flexcan_start_xmit,
+                  flexcan_stop_xmit
+     );
+
+
+cyg_can_event    flexcan_can0_rxbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX]; // buffer for 32 rx can events
+cyg_can_message  flexcan_can0_txbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX]; // buffer for 32 tx can messageds
+
+
+CAN_CHANNEL_USING_INTERRUPTS(flexcan_can0_chan,
+                             flexcan_lowlevel_funs,
+                             flexcan_can0_info,
+                             CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD),
+                             flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX,
+                             flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX
+    );
+
+
+DEVTAB_ENTRY(flexcan_devtab, 
+             CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME,
+             0,                     // Does not depend on a lower level interface
+             &cyg_io_can_devio, 
+             flexcan_init, 
+             flexcan_lookup,        // CAN driver may need initializing
+             &flexcan_can0_chan
+    );
+
+
+//===========================================================================
+//  Lookup the device and return its handle
+//===========================================================================
+static Cyg_ErrNo
+flexcan_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;
+}
+
+
+//===========================================================================
+//  Set device configuration
+//===========================================================================
+static Cyg_ErrNo
+flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
+{
+    Cyg_ErrNo res = ENOERR;
+    
+    switch(key) 
+    {
+        case CYG_IO_SET_CONFIG_CAN_INFO:
+             {
+                 cyg_can_info_t*  config = (cyg_can_info_t*) buf;
+                 if (*len < sizeof(cyg_can_info_t)) 
+                 {
+                    return -EINVAL;
+                 }
+                 *len = sizeof(cyg_can_info_t);
+                 if (!flexcan_config(chan, config, false)) 
+                 {
+                    return -EINVAL;
+                 }
+            }
+            break;
+    } // switch (key)
+    
+    return res;
+}
+
+
+//===========================================================================
+//  Read one event from can hardware
+//===========================================================================
+static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
+{
+    flexcan_info *info           = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan        = (flexcan_regs *)info->base;
+    cyg_uint8     mbox_ctrlstat;
+    bool          res            = true;
+    cyg_uint8     event_id       = *((cyg_uint8 *)pdata);
+    cyg_uint16    estat;
+        
+    //
+    // if event_id is 0 - 15 the we have a message box event - if is
+    //
+    if (event_id < FLEXCAN_ERR_EVENT)
+    {   
+        //
+        // read data from message box - during processing of this function
+        // the message box is locked and cannot receive further messages
+        //
+        flexcan_read_from_mbox(chan, event_id, pevent, &mbox_ctrlstat); 
+
+#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT    
+        if (pevent->msg.id == info->last_tx_id)
+        {
+            pevent->type = CYGNUM_CAN_EVENT_TX;
+        }
+        else
+        {
+            pevent->type = CYGNUM_CAN_EVENT_RX;
+        } 
+#else // !CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+        //
+        // If tx events are not supported and we received a self transmitted frame
+        // then this is not really an rx event and we return false. We rely on the
+        // fact here that two devices in network do not send the same identifier
+        //
+        if (pevent->msg.id == info->last_tx_id)    {   
+            info->last_tx_id = 0xFFFFFFFF; // set last received ID to an invalid value
+            res = false; 
+        }
+    
+        pevent->type = CYGNUM_CAN_EVENT_RX;
+#endif
+    
+        //
+        // check if an overun occured in this message box
+        //
+        if ((mbox_ctrlstat & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN)
+        {
+            pevent->type |= CYGNUM_CAN_EVENT_OVERRUN_RX;
+        }
+    }
+    else // (event_id >= FLEXCAN_ERR_EVENT)
+    {
+        //
+        // We have an status event - check if it is an bus off interrupt or an
+        // error interrupt and provide error information to upper layer
+        //
+        HAL_READ_UINT16(&flexcan->ESTAT, estat);
+        pevent->msg.data[0] = estat & 0xFF;
+        pevent->msg.data[1] = (estat >> 8) & 0xFF; 
+        HAL_READ_UINT8(&flexcan->RXERRCNT, pevent->msg.data[2]);
+        HAL_READ_UINT8(&flexcan->TXERRCNT, pevent->msg.data[3]);
+        switch (event_id)
+        {
+            case FLEXCAN_ERR_EVENT :
+                 //
+                 // indicate error passive event and provide content of estat register
+                 // for a more precise error information
+                 //
+                 if (estat & FLEXCAN_ESTAT_FCS_ERROR_PASSIVE)
+                 {
+                    pevent->type = CYGNUM_CAN_EVENT_ERR_PASSIVE;
+                 }
+                 //
+                 // If we are not in error passive state then we check if the
+                 // error counters reached the warning level
+                 //
+                 else
+                 {               
+                     //
+                     // indicate tx error counter warning level reached
+                     //
+                     if (estat & FLEXCAN_ESTAT_TXWARN)
+                     {
+                         pevent->type |= CYGNUM_CAN_EVENT_WARNING_TX;
+                     }
+                 
+                     //
+                     // indicate rx error counter warning level reached
+                     //
+                     if (estat & FLEXCAN_ESTAT_RXWARN)
+                     {
+                         pevent->type |= CYGNUM_CAN_EVENT_WARNING_RX;
+                     }
+                 }
+                 break;
+                 
+            case FLEXCAN_BUSOFF_EVENT:
+                 pevent->type = CYGNUM_CAN_EVENT_BUS_OFF;
+                 break;
+        } // switch (event_id)
+    }
+
+    return res;
+}
+
+
+//===========================================================================
+// Send one CAN message to CAN hardware
+//===========================================================================
+static bool flexcan_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint8        mbox = *((cyg_uint8 *)pdata);
+    cyg_uint16       iflag;
+   
+    HAL_READ_UINT16(&flexcan->IFLAG, iflag);
+    
+    //
+    // check if device is busy sending a message
+    //
+    if (info->tx_busy)
+    {
+        //
+        // if devise is busy and the interrupt flag is set, then we know
+        // that device is not busy any longer - if more message boxes are
+        // used for transmitting then tx_busy should be part of a message box
+        // structure to keep track of the state of different message boxes
+        //
+        if (iflag & (0x0001 << mbox))
+        {
+            HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+    info->tx_busy    = true;     // mark transmitter as busy
+    info->last_tx_id = pmsg->id; // store message in order to identify self recieved frames
+    flexcan_cfg_mbox_tx(&flexcan->mbox[mbox], pmsg);
+    
+    return true;
+}
+
+
+//===========================================================================
+// Flexcan start xmit
+//===========================================================================
+static void flexcan_start_xmit(can_channel* chan)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    imask;
+    CYG_INTERRUPT_STATE     saved_state;
+
+    HAL_DISABLE_INTERRUPTS(saved_state);
+    
+    //
+    // Now enable message box 15 interrupts
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << info->tx_mbox.num));
+    
+    //
+    // kick transmitter
+    //
+    chan->callbacks->xmt_msg(chan, &info->tx_mbox.num);  // Kick transmitter (if necessary)
+    
+    HAL_RESTORE_INTERRUPTS(saved_state);
+}
+
+
+//===========================================================================
+// Flexcan start xmit
+//===========================================================================
+static void flexcan_stop_xmit(can_channel* chan)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    imask;
+    CYG_INTERRUPT_STATE     saved_state;
+
+    HAL_DISABLE_INTERRUPTS(saved_state);
+    
+    //
+    // Now disable message box 15 interrupts
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << info->tx_mbox.num));
+
+    HAL_RESTORE_INTERRUPTS(saved_state);
+}
+
+
+//===========================================================================
+// Configure flexcan channel
+//===========================================================================
+static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    tmp16;
+    cyg_uint8     tmp8;
+    cyg_uint8     i;
+    
+    if (init)
+    {
+#if defined(CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0) && defined(HAL_MCF52xx_FLEXCAN0_PROC_INIT)
+        if (info == &flexcan_can0_info) {
+            HAL_MCF52xx_FLEXCAN0_PROC_INIT();
+        }
+#endif
+        
+        //
+        // Issue a reset in order to go into halt mode. The reset will set the
+        // the halt bit in mcr
+        //
+        HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
+        tmp16 &= ~FLEXCAN_MCR_FRZ;
+        HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
+        tmp16 |= FLEXCAN_MCR_SOFTRST;
+        HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
+        HAL_DELAY_US(10);
+    
+        //
+        // Check reset status
+        //
+        HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
+        if (tmp16 & FLEXCAN_MCR_SOFTRST)
+        {
+            return false;
+        }
+    
+        //
+        // Initialize the transmit and receive pin modes
+        //
+        HAL_WRITE_UINT8(&flexcan->CANCTRL0 , (FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT  
+                                            | FLEXCAN_CTRL0_RXMODE_0_DOMINANT)
+                                            & ~FLEXCAN_CTRL0_BOFFMSK
+                                            & ~FLEXCAN_CTRL0_ERRMASK);
+                                            
+        //
+        // setup message box acceptance filter
+        //
+        flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  info->rxgmask, 0);
+        flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, info->rx14mask, 0);
+        flexcan_set_acceptance_mask(&flexcan->RX15MASK_HI, info->rx15mask, 0);                                          
+    } // if (init)
+    
+    //
+    // stop chip
+    //
+    HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
+    HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_HALT);  
+    
+    //
+    // deactivate all message buffers - this is mandatory for configuration
+    // of message buffers
+    //
+    for (i = 0; i < 16; ++i)
+    {
+        HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE);
+    }
+    //
+    // mask all interrupts
+    //
+    HAL_WRITE_UINT16(&flexcan->IMASK, 0x0000);
+    HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
+                      
+    flexcan_set_baud(chan, config->baud);
+    
+    //
+    // setup bus arbitration mode - the LBUF bit defines the 
+    // transmit-first scheme 0 = message buffer with lowest ID
+    // 1 = message buffer with lowest number. We use lowest ID here
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & ~FLEXCAN_CTRL1_LBUF));
+        
+    //
+    // Message box 14 is our receiv message box. We configure it for
+    // reception of any message
+    //
+    flexcan_cfg_mbox_rx(&flexcan->mbox[info->rx_mbox.num], 0x100, 0);
+    flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, 0, 0);
+    
+    //
+    // enable the rx interrupt for mbox 0 (tx interrupt are enabled in start xmit)
+    // bus off interrupt and error interrupt
+    //
+    HAL_WRITE_UINT16(&flexcan->IMASK, (0x0001 << info->rx_mbox.num));
+    HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
+    
+    //
+    // now we can start the chip
+    //
+    flexcan_start_chip(chan);
+    
+    //
+    // store new config values
+    //
+    if (config != &chan->config) 
+    {
+        chan->config = *config;
+    }
+    
+    return true;
+}
+
+//===========================================================================
+//                           CAN INIT
+//
+/// First initialisation and reset of CAN modul.
+//===========================================================================
+static bool flexcan_init(struct cyg_devtab_entry* devtab_entry)
+{
+    can_channel  *chan    = (can_channel*)devtab_entry->priv;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+
+    if (!flexcan_config(chan, &chan->config, true))
+    {
+        return false;
+    }
+    
+    //
+    // prepare message box interrupt for message box 0 - the rx message box
+    //
+    cyg_drv_interrupt_create(info->rx_mbox.isr_vec,
+                             info->rx_mbox.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_mbox_rx_isr,
+                             &flexcan_mbox_rx_dsr,
+                             &(info->rx_mbox.interrupt_handle),
+                             &(info->rx_mbox.interrupt));
+    cyg_drv_interrupt_attach(info->rx_mbox.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->rx_mbox.isr_vec);
+    
+    //
+    // prepare message box interrupt for message box 15 - the tx message box
+    //
+    cyg_drv_interrupt_create(info->tx_mbox.isr_vec,
+                             info->tx_mbox.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_mbox_tx_isr,
+                             &flexcan_mbox_tx_dsr,
+                             &(info->tx_mbox.interrupt_handle),
+                             &(info->tx_mbox.interrupt));
+    cyg_drv_interrupt_attach(info->tx_mbox.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->tx_mbox.isr_vec);
+    
+    //
+    // prepare error interrupt
+    //
+    cyg_drv_interrupt_create(info->err_int.isr_vec,
+                             info->err_int.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_err_isr,
+                             &flexcan_err_dsr,
+                             &(info->err_int.interrupt_handle),
+                             &(info->err_int.interrupt));
+    cyg_drv_interrupt_attach(info->err_int.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->err_int.isr_vec);
+    
+    //
+    // prepare busoff interrupt
+    //
+    cyg_drv_interrupt_create(info->boff_int.isr_vec,
+                             info->boff_int.isr_priority,
+                             (cyg_addrword_t) chan,
+                             &flexcan_busoff_isr,
+                             &flexcan_busoff_dsr,
+                             &(info->boff_int.interrupt_handle),
+                             &(info->boff_int.interrupt));
+    cyg_drv_interrupt_attach(info->boff_int.interrupt_handle);
+    cyg_drv_interrupt_unmask(info->boff_int.isr_vec);
+        
+    return true;
+}
+
+
+//===========================================================================
+// Flexcan error interrupt handler
+//===========================================================================
+static cyg_uint32  flexcan_err_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint8     ctrl0;
+    cyg_uint16    estat;
+    
+    //
+    // first we disable error interrupts - DSR will reenable it later
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_ERRMASK);
+    
+    //
+    // for clearing the interrupt we first read the flag register as 1
+    // and then write it as 1 (and not as zero like the manual stated)
+    // we clear only the flag of this interrupt and leave all other
+    // message box interrupts untouched
+    //
+    HAL_READ_UINT16(&flexcan->ESTAT, estat);
+    HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_ERRINT); 
+    
+    //
+    // On the mcf5272 there is no need to acknowledge internal
+    // interrupts, only external ones.
+    // cyg_drv_interrupt_acknowledge(vec);
+    //
+    return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// DSR for all interrupts that are no message box interrupts
+//===========================================================================
+static void flexcan_err_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+    can_channel  *chan     = (can_channel *)data;
+    flexcan_info *info     = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan  = (flexcan_regs *)info->base;
+    cyg_uint8     ctrl0;
+    cyg_uint8     event_id = FLEXCAN_ERR_EVENT;
+
+    //
+    // signal CAN event to generic IO CAN driver - it will do any further 
+    // processing
+    //            
+    chan->callbacks->rcv_event(chan, &event_id);
+    
+    //
+    // reenable bus off interrupts
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_ERRMASK);
+}
+
+
+//===========================================================================
+// Bus off interrupt handler
+//===========================================================================
+static cyg_uint32  flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint8     ctrl0;
+    cyg_uint16    estat;
+    
+    //
+    // first we disable bus off interrupts - DSR will reenable it later
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_BOFFMSK);
+    
+    //
+    // for clearing the interrupt we first read the flag register as 1
+    // and then write it as 1 (and not as zero like the manual stated)
+    // we clear only the flag of this interrupt and leave all other
+    // message box interrupts untouched
+    //
+    HAL_READ_UINT16(&flexcan->ESTAT, estat);
+    HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_BOFFINT);  
+    
+    //
+    // On the mcf5272 there is no need to acknowledge internal
+    // interrupts, only external ones.
+    // cyg_drv_interrupt_acknowledge(vec);
+    //
+    return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// DSR for all interrupts that are no message box interrupts
+//===========================================================================
+static void flexcan_busoff_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+    can_channel  *chan     = (can_channel *)data;
+    flexcan_info *info     = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan  = (flexcan_regs *)info->base;
+    cyg_uint8     ctrl0;
+    cyg_uint8     event_id = FLEXCAN_BUSOFF_EVENT;
+
+    //
+    // signal CAN event to generic IO CAN driver - it will do any further 
+    // processing
+    //            
+    chan->callbacks->rcv_event(chan, &event_id);
+    
+    //
+    // reenable bus off interrupts
+    //
+    HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_BOFFMSK);  
+}
+
+
+//===========================================================================
+// Flexcan message box isr
+//===========================================================================
+static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    iflag;
+    cyg_uint16    imask;
+    
+    //
+    // number of message box can be calculated from vector that cause
+    // interrupt - we pass this message box number as additional data to the
+    // callback because it is required in the receive event function later
+    //
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
+    
+    //
+    // first we disable interrupts of this message box - the DSR will
+    // reenable it later
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << mbox));
+    
+    //
+    // for clearing the interrupt we first read the flag register as 1
+    // and then write it as 1 (and not as zero like the manual stated)
+    // we clear only the flag of this interrupt and leave all other
+    // message box interrupts untouched
+    //
+    HAL_READ_UINT16(&flexcan->IFLAG, iflag);
+    HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));    
+    
+    //
+    // On the mcf5272 there is no need to acknowledge internal
+    // interrupts, only external ones.
+    // cyg_drv_interrupt_acknowledge(vec);
+    //
+    return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// Flexcan message box dsr
+//===========================================================================
+static void flexcan_mbox_rx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    imask;
+    
+    //
+    // number of message box can be calculated from vector that caused
+    // interrupt - we pass this message box number as additional data to the
+    // callback
+    //
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
+    
+    //
+    // signal CAN event to generic IO CAN driver - it will do any further 
+    // processing
+    //            
+    chan->callbacks->rcv_event(chan, &mbox);
+    
+    //
+    // reenable interrupts for the message box that caused the DSR to run
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << mbox)); 
+}
+
+//===========================================================================
+// Flexcan message box isr
+//===========================================================================
+static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    iflag;
+    cyg_uint16    imask;
+    
+    // number of message box can be calculated from vector that cause
+    // interrupt - we pass this message box number as additional data to the
+    // callback
+    //
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
+    
+    //
+    // first we disable interrupts of this message box - the DSR will
+    // reenable it later
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << mbox));
+    
+    //
+    // for clearing the interrupt we first read the flag register as 1
+    // and then write it as 1 (and not as zero like the manual stated)
+    // we clear only the flag of this interrupt and leave all other
+    // message box interrupts untouched
+    //
+    HAL_READ_UINT16(&flexcan->IFLAG, iflag);
+    HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox)); 
+    info->tx_busy = false;   
+    
+    //
+    // On the mcf5272 there is no need to acknowledge internal
+    // interrupts, only external ones.
+    // cyg_drv_interrupt_acknowledge(vec);
+    //
+    return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// Flexcan message box dsr
+//===========================================================================
+static void flexcan_mbox_tx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
+{
+    can_channel  *chan    = (can_channel *)data;
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16    imask;
+    
+    //
+    // number of message box can be calculated from vector that caused
+    // interrupt - we pass this message box number as additional data to the
+    // callback
+    //
+    cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
+    
+    //
+    // send next message 
+    //            
+    chan->callbacks->xmt_msg(chan, &mbox);
+    
+    //
+    // reenable interrupts for the message box that caused the DSR to run
+    //
+    HAL_READ_UINT16(&flexcan->IMASK, imask);
+    HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << mbox));
+}
+
+
+//===========================================================================
+//                     START FLEXCAN MODUL
+//===========================================================================
+static void flexcan_start_chip(can_channel *chan)
+{
+    flexcan_info *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs *flexcan = (flexcan_regs *)info->base;
+    
+    cyg_uint16 tmp16;
+    HAL_READ_UINT16(&flexcan->CANMCR, tmp16);    
+    HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 
+                 & ~(FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT));
+}
+
+
+//===========================================================================
+//                      SET ACCEPTANCE MASK
+//===========================================================================
+static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext)
+{
+    cyg_uint16 id;
+    //
+    // 32 bit access to RXMASK filters is broken so we use  16 Bit
+    // access here
+    //
+    if (ext != 0)
+    {
+        id  = ((mask >> 13) & 0xFFE0);       // set mask bits 18 - 28
+        id |= ((mask >> 15) & 0x7);          // set mask bits 15 -17
+        HAL_WRITE_UINT16(&rxmask_reg[0], id);
+        
+        id = (mask << 1) & 0xFFFE;
+        HAL_WRITE_UINT16(&rxmask_reg[1], id);
+    }
+    else
+    {
+        id = ((mask << 5) & 0xFFE0); 
+        HAL_WRITE_UINT16(&rxmask_reg[0], id);
+        HAL_WRITE_UINT16(&rxmask_reg[1], 0xFFFF);  
+    }
+    
+}
+
+
+
+//===========================================================================
+//                 CONFIGURE MESSAGE BOX FOR TRANSMISSION
+//===========================================================================
+static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox,
+                         cyg_can_message  *pmsg)
+{
+    cyg_uint16 id;
+  
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_NOT_READY); 
+    
+    if (pmsg->ext != 0)
+    { 
+        id  = ((pmsg->id >> 13) & 0xFFE0);   // setup id bits 18 - 28
+        id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
+        id |= ((pmsg->id >> 15) & 0x7);      // set id bits 15 - 17
+        HAL_WRITE_UINT16(&pmbox->id_hi, id);
+        
+        id = ((pmsg->id << 1) & 0xFFFE);
+        
+        if (pmsg->rtr)
+        {
+            id |= MBOX_CFG_RTR_EXT;
+        }   
+        
+        HAL_WRITE_UINT16(&pmbox->id_lo, id);
+    }   
+    else
+    {
+        id = ((pmsg->id << 5) & 0xFFE0);
+        if (pmsg->rtr)
+        {
+            id |= MBOX_CFG_RTR_STD;           // set rtr bit for standard ID
+        }
+        HAL_WRITE_UINT16(&pmbox->id_hi, id);
+        HAL_WRITE_UINT16(&pmbox->id_lo, 0);
+    }
+    
+    pmsg->dlc %= 9; // limit data length to 8 bytes
+    
+    //
+    // Now copy data bytes into buffer and start transmission
+    //
+    HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1); 
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_TRANSMIT | pmsg->dlc);
+    
+    return true;
+}
+
+
+
+//===========================================================================
+//              CONFIGURE MESSAGE BOX FOR RECEPTION OF FRAMES
+//===========================================================================
+static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox,
+                                cyg_uint32    canid,
+                                cyg_uint8     ext)
+{
+    cyg_uint16 id;
+    
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_NOT_ACTIVE); 
+    
+    if (ext != 0)
+    { 
+        id  = ((canid >> 13) & 0xFFE0);      // setup id bits 18 - 28
+        id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
+        id |= ((canid >> 15) & 0x7);         // set id bits 15 - 17
+        HAL_WRITE_UINT16(&pmbox->id_hi, id);  // write ID high
+        
+        id = ((canid << 1) & 0xFFFE);
+        
+        HAL_WRITE_UINT16(&pmbox->id_lo, id);// write ID low
+    }   
+    else
+    {
+        id = ((canid << 5) & 0xFFE0);
+
+        HAL_WRITE_UINT16(&pmbox->id_hi, id);
+        HAL_WRITE_UINT16(&pmbox->id_lo, 0);
+    }
+    
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
+}
+
+
+//===========================================================================
+//                       READ DATA FROM MESSAGE BOX
+//==========================================================================
+static void flexcan_read_from_mbox(can_channel  *chan,
+                            cyg_uint8            mbox,
+                            cyg_can_event       *pevent,
+                            cyg_uint8           *ctrlstat)
+{
+    flexcan_info    *info    = (flexcan_info *)chan->dev_priv;
+    flexcan_regs    *flexcan = (flexcan_regs *)info->base;
+    flexcan_mbox    *pmbox   = &flexcan->mbox[mbox];
+    cyg_can_message *pmsg    = &pevent->msg;
+    cyg_uint16       id;
+    cyg_uint8        i;
+    
+    HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox
+    
+    //
+    // If message buffer is busy then it is now beeing filled with a new message
+    // This condition will be cleared within 20 cycles - wi simply do a 20 us
+    // delay here, that should be enougth
+    //
+    if (*ctrlstat & MBOX_RXCODE_BUSY)
+    {
+        HAL_DELAY_US(20);
+    }
+    
+    pmsg->dlc = (*ctrlstat & MBOX_CFG_DLC_MASK); // store received data len
+    pmsg->rtr = 0;
+    
+    HAL_READ_UINT16(&pmbox->id_hi, id);         // read ID high
+    
+    if (id & MBOX_CFG_IDE)
+    {
+        pmsg->ext = 1;
+        pmsg->id  = (id & 0xFFE0) << 13;
+        
+        HAL_READ_UINT16(&pmbox->id_lo, id);
+        pmsg->id |= (id & 0xFFFE) >> 1;
+    }
+    else
+    {
+        pmsg->ext = 0;
+        pmsg->id  = (id & 0xFFE0) >> 5;
+    }
+    
+    //
+    // now finally copy data
+    //
+    HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1);
+       
+    //
+    // now zero out the remaining bytes in can message in order
+    // to deliver a defined state
+    //
+    for (i = pmsg->dlc; i < 8; ++i)
+    {
+        pmsg->data[i] = 0;
+    }
+  
+    //
+    // now mark this mbox as empty and read the free running timer
+    // to unlock this mbox
+    //
+    HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
+    HAL_READ_UINT16(&flexcan->TIMER, id);
+#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP    
+    pevent->timestamp = id;
+#endif
+}
+
+
+//===========================================================================
+//                           INIT CAN BAUD RATE
+//===========================================================================
+static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baud)
+{
+    flexcan_info             *info = (flexcan_info *)chan->dev_priv;
+    flexcan_regs             *flexcan = (flexcan_regs *)info->base;
+    cyg_uint16                mcr_bck;
+    cyg_uint8                 tmp8;
+    cyg_uint8                 presdiv;
+    cyg_uint8                 propseg;
+    cyg_uint8                 pseg1_2;
+    cyg_uint16                baudrate = flexcan_baud_rates[baud];
+    
+    //
+    // Get bit timings from HAL because bit timings depend on sysclock
+    //
+    HAL_MCF52xx_FLEXCAN_GET_BIT_TIMINGS(&baudrate, &presdiv, &propseg, &pseg1_2);
+    
+    //
+    // return false if baudrate is not supported
+    //
+    if (0 == baudrate)
+    {
+        return false;
+    }
+    
+    //
+    // For setting the bit timings we have to stop the flexcan modul
+    //
+    HAL_READ_UINT16(&flexcan->CANMCR, mcr_bck);
+    HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck | FLEXCAN_MCR_HALT);
+    
+    //
+    // now we setup bit timings
+    //
+    HAL_WRITE_UINT8(&flexcan->PRESDIV, presdiv);
+    HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & 0xF8) | propseg); 
+    HAL_READ_UINT8(&flexcan->CANCTRL2, tmp8);
+    HAL_WRITE_UINT8(&flexcan->CANCTRL2, (tmp8 & 0xC0) | pseg1_2); 
+    
+    //
+    // Now restore the previous state - if the modul was started then
+    // it will no be started again, if it was stopped, then it remains stopped
+    //
+    HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck);
+    
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// end of can_mcf_flexcan.c
+
--- ecos_web_cvs/ecos/packages/ecos.db	2005-05-24 23:15:34.000000000 +0200
+++ ecos/ecos/packages/ecos.db	2005-05-26 22:49:00.000000000 +0200
@@ -94,6 +94,26 @@
            serial devices."
 }
 
+package CYGPKG_IO_CAN {
+	alias 		{ "CAN device drivers" can io_can }
+	directory	io/can
+	script		io_can.cdl
+        description "
+           This package contains drivers for basic I/O services on
+           CAN devices."
+}
+
+package CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN {
+    alias             { "MCF52xx FlexCAN device drivers"
+                        devs_can_mcf52xx_flexcan mcf52xx_flexcan_serial_driver }
+    hardware
+    directory	      devs/can/m68k/mcf52xx
+    script	          can_mcf52xx.cdl	
+    description       "Generic CAN device driver for the on-chip
+                       FlexCAN modules in MCF52xx ColdFire processors."
+}
+
+
 package CYGPKG_IO_PCMCIA {
 	alias 		{ "PCMCIA & Compact Flash support" pcmcia io_pcmcia cf }
 	directory	io/pcmcia

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]