--- /dev/null
+//==========================================================================
+//
+// devs/can/arm/lpc2xxx/current/src/can_lpc2xxx.c
+//
+// CAN driver for LPC2xxx microcontrollers
+//
+//==========================================================================
+//####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: 2007-04-09
+// Purpose: Support LPC2xxx on-chip CAN moduls
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+
+//==========================================================================
+// INCLUDES
+//==========================================================================
+#include <pkgconf/system.h>
+#include <pkgconf/io_can.h>
+#include <pkgconf/io.h>
+#include <pkgconf/devs_can_lpc2xxx.h>
+
+#include <cyg/infra/diag.h>
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_io.h>
+
+#include <cyg/hal/hal_diag.h>
+#include <cyg/infra/cyg_ass.h>
+
+#include <cyg/io/io.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/can.h>
+#include <cyg/io/can_lpc2xxx.h>
+#include <cyg/io/can_lpc2xxx_baudrates.h>
+
+
+
+
+//===========================================================================
+// DEFINES
+//===========================================================================
+//
+// Check if the macro HAL_LPC2XXX_GET_CAN_BR is provided
+//
+#ifndef HAL_LPC2XXX_GET_CAN_BR
+#error "Macro HAL_LPC2XXX_GET_CAN_BR() missing"
+#endif
+
+//
+// Support debug output if this option is enabled in CDL file
+//
+#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
+#define LPC2XXX_DBG_PRINT diag_printf
+#else
+#define LPC2XXX_DBG_PRINT( fmt, ... )
+#endif
+
+
+//---------------------------------------------------------------------------
+// we define our own set of register bits in order to be independent from
+// platform specific names
+//
+
+//---------------------------------------------------------------------------
+// Memory map of CAN block
+//
+#define CAN_ACCFILT_RAM_BASE 0xE0038000
+#define CAN_ACCFILT_REG_BASE 0xE003C000
+#define CAN_CENTRAL_REG_BASE 0xE0040000
+#define CAN_CTRL_1_REG_BASE 0xE0044000
+#define CAN_CTRL_2_REG_BASE 0xE0048000
+#define CAN_CTRL_3_REG_BASE 0xE004C000
+#define CAN_CTRL_4_REG_BASE 0xE0050000
+
+
+//---------------------------------------------------------------------------
+// CAN Acceptance Filter register layout
+//
+#define CAN_ACCFILT_AFMR (CAN_ACCFILT_REG_BASE + 0x0000)
+#define CAN_ACCFILT_SFF_SA (CAN_ACCFILT_REG_BASE + 0x0004)
+#define CAN_ACCFILT_SFF_GRP_SA (CAN_ACCFILT_REG_BASE + 0x0008)
+#define CAN_ACCFILT_EFF_SA (CAN_ACCFILT_REG_BASE + 0x000C)
+#define CAN_ACCFILT_EFF_GRP_SA (CAN_ACCFILT_REG_BASE + 0x0010)
+#define CAN_ACCFILT_ENDOFTABLE (CAN_ACCFILT_REG_BASE + 0x0014)
+#define CAN_ACCFILT_LUT_ERR_ADDR (CAN_ACCFILT_REG_BASE + 0x0018)
+#define CAN_ACCFILT_LUT_ERR (CAN_ACCFILT_REG_BASE + 0x001C)
+
+//---------------------------------------------------------------------------
+// CAN_ACCFILT_AFMR Bits
+//
+#define AFMR_OFF 0x00000001 // 1 = Acceptance filter is not operational
+#define AFMR_BYPASS 0x00000002 // 1 = all Rx messages are accepted on enabled CAN controllers.
+#define AFMR_FULLCAN 0x00000004 // 1 = FullCAN mode
+#define AFMR_ON 0x00000000 // Acceptance filter on
+#define ACCFILT_RAM_SIZE 2048 // size of acceptance filter ram
+
+
+//---------------------------------------------------------------------------
+// Acceptance filter tool macros
+//
+#define ACCFILT_STD_ID_MASK 0x7FF
+#define ACCFILT_EXT_ID_MASK 0x1FFFFFFF
+#define ACCFILT_STD_DIS 0x1000
+#define ACCFILT_STD_CTRL_MASK 0xE000
+#define ACCFILT_EXT_CTRL_MASK 0xE0000000
+#define ACCFILT_STD_GET_CTRL(_entry_) (((_entry_) >> 13) & 0x7)
+#define ACCFILT_STD_GET_CTRL_LOWER(_entry_) (((_entry_) >> 29) & 0x7)
+#define ACCFILT_STD_GET_CTRL_UPPER(_entry_) (((_entry_) >> 13) & 0x7)
+#define ACCFILT_STD_GET_ID(_entry_) ((_entry_) & ACCFILT_STD_ID_MASK)
+#define ACCFILT_EXT_GET_ID(_entry_) ((_entry_) & ACCFILT_EXT_ID_MASK)
+#define ACCFILT_EXT_GET_CTRL(_entry_) (((_entry_) >> 29) & 0x7)
+#define ACCFILT_EXT_SET_CTRL(_entry_, _ctrl_) ((_entry_ & 0xE0000000) | ((_ctrl_) << 29))
+
+
+//---------------------------------------------------------------------------
+// CAN Central CAN Registers register layout
+//
+#define CAN_CENTRAL_TXSR (CAN_CENTRAL_REG_BASE + 0x0000)
+#define CAN_CENTRAL_RXSR (CAN_CENTRAL_REG_BASE + 0x0004)
+#define CAN_CENTRAL_MSR (CAN_CENTRAL_REG_BASE + 0x0008)
+
+
+//---------------------------------------------------------------------------
+// CAN Controller register offsets
+// Registers are offsets from base CAN module control register
+//
+#define CANREG_MOD 0x0000
+#define CANREG_CMR 0x0004
+#define CANREG_GSR 0x0008
+#define CANREG_ICR 0x000C
+#define CANREG_IER 0x0010
+#define CANREG_BTR 0x0014
+#define CANREG_EWL 0x0018
+#define CANREG_SR 0x001C
+#define CANREG_RFS 0x0020
+#define CANREG_RID 0x0024
+#define CANREG_RDA 0x0028
+#define CANREG_RDB 0x002C
+#define CANREG_TFI1 0x0030
+#define CANREG_TID1 0x0034
+#define CANREG_TDA1 0x0038
+#define CANREG_TDB1 0x003C
+#define CANREG_TFI2 0x0040
+#define CANREG_TID2 0x0044
+#define CANREG_TDA2 0x0048
+#define CANREG_TDB2 0x004C
+#define CANREG_TFI3 0x0050
+#define CANREG_TID3 0x0054
+#define CANREG_TDA3 0x0058
+#define CANREG_TDB3 0x005C
+
+
+//---------------------------------------------------------------------------
+// CAN Controller register layout
+//
+#define CAN_CTRL_MOD(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_MOD)
+#define CAN_CTRL_CMR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_CMR)
+#define CAN_CTRL_GSR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_GSR)
+#define CAN_CTRL_ICR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_ICR)
+#define CAN_CTRL_IER(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_IER)
+#define CAN_CTRL_BTR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_BTR)
+#define CAN_CTRL_EWL(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_EWL)
+#define CAN_CTRL_SR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_SR)
+#define CAN_CTRL_RFS(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RFS)
+#define CAN_CTRL_RID(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RID)
+#define CAN_CTRL_RDA(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RDA)
+#define CAN_CTRL_RDB(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RDB)
+#define CAN_CTRL_TFI1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI1)
+#define CAN_CTRL_TID1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID1)
+#define CAN_CTRL_TDA1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA1)
+#define CAN_CTRL_TDB1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB1)
+#define CAN_CTRL_TFI2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI2)
+#define CAN_CTRL_TID2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID2)
+#define CAN_CTRL_TDA2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA2)
+#define CAN_CTRL_TDB2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB2)
+#define CAN_CTRL_TFI3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI3)
+#define CAN_CTRL_TID3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID3)
+#define CAN_CTRL_TDA3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA3)
+#define CAN_CTRL_TDB3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB3)
+
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_ICR register bits
+//
+#define ICR_RX 0x00000001
+#define ICR_TX1 0x00000002
+#define ICR_ERR_WARN 0x00000004
+#define ICR_DATA_OVR 0x00000008
+#define ICR_WAKE_UP 0x00000010
+#define ICR_ERR_PASSIVE 0x00000020
+#define ICR_ARBITR_LOST 0x00000040
+#define ICR_BUS_ERR 0x00000080
+#define ICR_ID_READY 0x00000100
+#define ICR_TX2 0x00000200
+#define ICR_TX3 0x00000400
+#define ICR_LUT_ERR 0x00000800
+#define ICR_GET_ERRBIT(_icr_) (((_icr_) >> 16) & 0x1F)
+#define ICR_ERR_DIRECTION 0x00200000
+#define ICR_GET_ERRCODE(_icr_) (((_icr_) >> 22) & 0x03)
+#define ICR_GET_ALCBIT(_icr_) (((_icr_) >> 24) & 0x1F)
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_ALIE
+#define CAN_ALL_ERR_INT (ICR_ERR_PASSIVE | ICR_ARBITR_LOST | ICR_BUS_ERR | ICR_ERR_WARN)
+#else
+#define CAN_ALL_ERR_INT (ICR_ERR_PASSIVE | ICR_BUS_ERR | ICR_ERR_WARN)
+#endif
+#define CAN_MISC_INT (CAN_ALL_ERR_INT | ICR_WAKE_UP)
+
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_ICR register bits
+//
+#define ICR_ERRCODE_BIT_ERR 0x00
+#define ICR_ERRCODE_FORM_ERR 0x01
+#define ICR_ERRCODE_STUFF_ERR 0x02
+#define ICR_ERRCODE_OTHER_ERR 0x03
+
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_RFS register bits
+//
+#define RFS_ACCFILT_INDEX_MASK 0x000003FF
+#define RFS_RECEIVED_IN_BYPASS_MODE 0x00000400
+#define RFS_DLC_MASK 0x000F0000
+#define RFS_RTR 0x40000000
+#define RFS_EXT 0x80000000
+#define RFS_GET_DLC(_regval_) (((_regval_) >> 16) & 0xF)
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_CMR register bits
+//
+#define CMR_TX_REQ 0x00000001
+#define CMR_TX_ABORT 0x00000002
+#define CMR_RX_RELEASE_BUF 0x00000004
+#define CMR_CLEAR_DATA_OVR 0x00000008
+#define CMR_SELF_RX_REQ 0x00000010
+#define CMR_SEND_TX_BUF1 0x00000020
+#define CMR_SEND_TX_BUF2 0x00000040
+#define CMR_SEND_TX_BUF3 0x00000080
+
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_TFI register bits
+//
+#define TFI_PRIO_MASK 0x000000FF
+#define TFI_DLC_MASK 0x000F0000
+#define TFI_DLC_RTR 0x40000000
+#define TFI_DLC_EXT 0x80000000
+
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_MOD register bits
+//
+#define CANMOD_OPERATIONAL 0x00000000
+#define CANMOD_RESET 0x00000001
+#define CANMOD_LISTEN_ONLY 0x00000002
+#define CANMOD_SELF_TEST 0x00000004
+#define CANMOD_TX_BUF_CFG 0x00000008
+#define CANMOD_SLEEP 0x00000010
+#define CANMOD_REV_POLARITY 0x00000020
+#define CANMOD_TEST 0x00000040
+
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_IER register bits
+//
+#define IER_RX 0x00000001
+#define IER_TX1 0x00000002
+#define IER_ERR_WARN 0x00000004
+#define IER_DATA_OVR 0x00000008
+#define IER_WAKE_UP 0x00000010
+#define IER_ERR_PASSIVE 0x00000020
+#define IER_ARBITR_LOST 0x00000040
+#define IER_BUS_ERR 0x00000080
+#define IER_ID_READY 0x00000100
+#define IER_TX2 0x00000200
+#define IER_TX3 0x00000400
+
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_GSR register bits
+//
+#define GSR_RX_MSG_AVAILABLE 0x00000001
+#define GSR_DATA_OVR 0x00000002
+#define GSR_TX_NOT_PENDING 0x00000004
+#define GSR_ALL_TX_COMPLETE 0x00000008
+#define GSR_RECEIVING_ACTIVE 0x00000010
+#define GSR_SENDING_ACTIVE 0x00000020
+#define GSR_ERR 0x00000040
+#define GSR_BUS_OFF 0x00000080
+#define GSR_RXERR_CNT(_reg_) (((_reg_) >> 16) & 0xFF)
+#define GSR_TXERR_CNT(_reg_) (((_reg_) >> 24) & 0xFF)
+
+
+//---------------------------------------------------------------------------
+// CAN_CTRL_SR register bits
+//
+#define SR_RX_MSG_AVAILABLE 0x01
+#define SR_DATA_OVR 0x02
+#define SR_TX_BUF_WRITE_OK 0x04 // TBS1, TBS2, TBS3 (Bit 2, 10, 18)
+#define SR_TX_COMPLETE 0x08 // TCS1, TCS2, TCS3 (Bit 3, 11, 19)
+#define SR_RECEIVING_ACTIVE 0x10
+#define SR_SENDING_ACTIVE 0x20 // TS1, TS2, TS3 (5, 13, 21)
+#define SR_ERR 0x40
+#define SR_BUS_OFF 0x80
+
+
+//---------------------------------------------------------------------------
+// Optimize for the case of a single CAN channel, while still allowing
+// multiple channels.
+//
+#if CYGINT_IO_CAN_CHANNELS == 1
+#define CAN_CTRL_BASE(_extra_) CAN_CTRL_SINGLETON_BASE
+#define CAN_ISRVEC(_extra_) CAN_SINGLETON_ISRVEC
+#define CAN_CHAN_NO(_extra_) CAN_SINGLETON_CHAN_NO
+#define CAN_DECLARE_INFO(_chan_)
+#define CAN_DECLARE_CHAN(_data_)
+#else
+#define CAN_CTRL_BASE(_extra_) ((_extra_)->base)
+#define CAN_ISRVEC(_extra_) ((_extra_)->isrvec)
+#define CAN_CHAN_NO(_extra_) ((_extra_)->chan_no)
+#define CAN_DECLARE_INFO(_chan_) lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+#define CAN_DECLARE_CHAN(_data_) can_channel *chan = (can_channel *)data;
+#endif // CYGINT_IO_CAN_CHANNELS == 1
+
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN0_ACCFILT_STARTUP_CFG_RX_ALL
+#define CAN0_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL
+#else
+#define CAN0_FLAG_STARTUP_ACCFILT_SETUP 0x00
+#endif
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN1_ACCFILT_STARTUP_CFG_RX_ALL
+#define CAN1_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL
+#else
+#define CAN1_FLAG_STARTUP_ACCFILT_SETUP 0x00
+#endif
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN2_ACCFILT_STARTUP_CFG_RX_ALL
+#define CAN2_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL
+#else
+#define CAN2_FLAG_STARTUP_ACCFILT_SETUP 0x00
+#endif
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN3_ACCFILT_STARTUP_CFG_RX_ALL
+#define CAN3_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL
+#else
+#define CAN3_FLAG_STARTUP_ACCFILT_SETUP 0x00
+#endif
+
+
+//===========================================================================
+// DATA TYPES
+//===========================================================================
+//
+// Structure stores LPC2xxx CAN channel related stuff
+//
+
+// If we use Self Reception Request command instead of the Transmission Request
+// we must add last transmit message id in order to reject it in rx_ISR
+// There are two last_tx_id because tx interrupt (and so transmission of next
+// message) happens before rx interrupt (which uses last_tx_id for rejecting))
+
+// Format of last_tx_id:
+// (bits: 28:0-ID, 29-Validation, 30-RTR, 31-EXT)
+// if last_tx_id == 0xFFFFFFFF (Validation == 1) then last id is not valid
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION
+ #define LPC2XXX_CAN_INFO_LAST_TX_ID_IDMASK 0x1FFFFFFF
+ #define LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK 0xC0000000
+ #define LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID 0xFFFFFFFF
+
+ #define LPC2XXX_CAN_INFO_LAST_TX_ID_DECL cyg_uint8 last_tx_index; \
+ cyg_uint32 last_tx_id[2];
+ #define LPC2XXX_CAN_INFO_LAST_TX_ID_INIT last_tx_index : 0, \
+ last_tx_id : {LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID, LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID},
+#else
+ #define LPC2XXX_CAN_INFO_LAST_TX_ID_DECL
+ #define LPC2XXX_CAN_INFO_LAST_TX_ID_INIT
+#endif
+
+typedef struct lpc2xxx_can_info_st
+{
+//
+// Newer LPC2xxx variants like the LPC2468 do not support per channel
+// interrupts. They provide only one single interrupt vector for all
+// CAN interrupts
+//
+#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+ cyg_interrupt tx_interrupt;
+ cyg_handle_t tx_interrupt_handle;
+ cyg_uint8 tx_interrupt_priority;
+ cyg_interrupt rx_interrupt;
+ cyg_handle_t rx_interrupt_handle;
+ cyg_uint8 rx_interrupt_priority;
+#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+ cyg_can_state state; // state of CAN controller
+ cyg_uint8 flags; // flags indicating several states
+ LPC2XXX_CAN_INFO_LAST_TX_ID_DECL // last transmitted messages ids
+#if CYGINT_IO_CAN_CHANNELS > 1
+ cyg_uint32 base; // Per-bus h/w details
+#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+ cyg_uint8 isrvec; // ISR vector (peripheral id)
+#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+ cyg_uint8 chan_no; // number of CAN channel
+#endif // CYGINT_IO_CAN_CHANNELS > 1
+} lpc2xxx_can_info_t;
+
+
+#define INFO_FLAG_RX_ALL 0x01 // this bit indicates that channel receives all CAN messages - no filtering active
+#define INFO_FLAG_STARTUP_RX_ALL 0x02 // this bit indicates filter state at startup
+
+
+//
+// lpc2xxx info initialisation
+//
+#define LPC2XXX_CTRL_NOT_INITIALIZED 0xFF
+
+#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+#if CYGINT_IO_CAN_CHANNELS > 1
+#define LPC2XXX_CAN_INFO(_l, _base, _isrvec, _chan_no_, _tx_priority, _rx_priority, _flags) \
+lpc2xxx_can_info_t _l = { \
+ state : LPC2XXX_CTRL_NOT_INITIALIZED, \
+ base : (_base), \
+ isrvec : (_isrvec), \
+ chan_no : (_chan_no_), \
+ tx_interrupt_priority : (_tx_priority), \
+ rx_interrupt_priority : (_rx_priority), \
+ flags : (_flags), \
+ LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \
+};
+#else // CYGINT_IO_CAN_CHANNELS == 1
+#define LPC2XXX_CAN_INFO(_l, _tx_priority, _rx_priority, _flags) \
+lpc2xxx_can_info_t _l = { \
+ state : CYGNUM_CAN_STATE_STOPPED, \
+ tx_interrupt_priority : (_tx_priority), \
+ rx_interrupt_priority : (_rx_priority), \
+ flags : (_flags), \
+ LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \
+};
+#endif // CYGINT_IO_CAN_CHANNELS == 1
+#else // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+//
+// Newer devices support only one global CAN interrupt. We do not need
+// per channel interrupt data an ignore the values during initialisation
+//
+#if CYGINT_IO_CAN_CHANNELS > 1
+#define LPC2XXX_CAN_INFO(_l, _base, _isrvec, _chan_no_, _tx_priority, _rx_priority, _flags) \
+lpc2xxx_can_info_t _l = { \
+ state : LPC2XXX_CTRL_NOT_INITIALIZED, \
+ base : (_base), \
+ chan_no : (_chan_no_), \
+ flags : (_flags), \
+ LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \
+};
+#else // CYGINT_IO_CAN_CHANNELS == 1
+#define LPC2XXX_CAN_INFO(_l, _tx_priority, _rx_priority, _flags) \
+lpc2xxx_can_info_t _l = { \
+ state : CYGNUM_CAN_STATE_STOPPED, \
+ flags : (_flags), \
+ LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \
+};
+#endif // CYGINT_IO_CAN_CHANNELS == 1
+
+//
+// The following defines are only dummies required for proper
+// initialisation of can channel data structures
+//
+#define CYGNUM_HAL_INTERRUPT_CAN1_TX
+#define CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY
+#define CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY
+#define CYGNUM_HAL_INTERRUPT_CAN2_TX
+#define CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY
+#define CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY
+#define CYGNUM_HAL_INTERRUPT_CAN3_TX
+#define CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY
+#define CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY
+#define CYGNUM_HAL_INTERRUPT_CAN4_TX
+#define CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY
+#define CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY
+#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+
+
+//
+// Acceptance filter data
+//
+typedef struct lpc2xxx_global_can_info_st
+{
+ cyg_interrupt interrupt; // common CAN interrupt
+ cyg_handle_t interrupt_handle; // common CAN interrupt handle
+ cyg_uint16 free_filters; // number of free message filter
+#if CYGINT_IO_CAN_CHANNELS > 1 // optimize for single channel
+ cyg_uint8 init_cnt; // counts number of initialized channels
+ can_channel* active_channels[5]; // stores pointers to active channels - the last entry is just a delimiter
+#else // CYGINT_IO_CAN_CHANNELS > 1
+ can_channel* active_channels[1]; // optimize for one single channel
+#endif // CYGINT_IO_CAN_CHANNELS > 1
+} lpc2xxx_global_can_info_t;
+
+
+#if CYGINT_IO_CAN_CHANNELS > 1
+#define LPC2XXX_GET_CAN_CHANNEL(_can_info_, _chan_no_) ((can_channel*)(_can_info_).active_channels[_chan_no_])
+#else
+#define LPC2XXX_GET_CAN_CHANNEL(_can_info_, _chan_no_) ((can_channel*)(_can_info_).active_channels[0])
+#endif
+
+//
+// The number of available message filters depends on the size of the
+// acceptance filter RAM and on the size of one entry. The size of
+// one entry is 4 byte (standard ID only 2 byte, extended groups 8 byte)
+//
+#define ACCFILT_COMMON_ENTRY_SIZE 4
+#define LPC2XXX_CAN_MSG_FILTERS_MAX (ACCFILT_RAM_SIZE / ACCFILT_COMMON_ENTRY_SIZE)
+lpc2xxx_global_can_info_t lpc2xxx_global_can_info =
+{
+ .free_filters = LPC2XXX_CAN_MSG_FILTERS_MAX,
+#if CYGINT_IO_CAN_CHANNELS > 1 // optimize for single channel
+ .init_cnt = 0,
+ .active_channels = {0, 0, 0, 0, 0},
+#endif // #if CYGINT_IO_CAN_CHANNELS > 1
+};
+
+
+
+//
+// Data type for access of single bytes/words of an dword value
+//
+typedef union lsc_buf_u
+{
+ cyg_uint8 bytes[4];
+ struct
+ {
+ cyg_uint16 low;
+ cyg_uint16 high;
+ } words;
+
+ struct
+ {
+ cyg_uint16 upper; // uppper column of acceptance filter ram
+ cyg_uint16 lower; // lower column of acceptance filter ram
+ } column;
+
+ cyg_uint32 dword;
+} lsc_buf_t;
+
+
+//===========================================================================
+// GLOBAL DATA
+//===========================================================================
+#if CYGINT_IO_CAN_CHANNELS > 1
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0
+LPC2XXX_CAN_INFO(lpc2xxx_can0_info,
+ CAN_CTRL_1_REG_BASE,
+ CYGNUM_HAL_INTERRUPT_CAN1_TX,
+ 0,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY,
+ CAN0_FLAG_STARTUP_ACCFILT_SETUP);
+#endif
+
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1
+LPC2XXX_CAN_INFO(lpc2xxx_can1_info,
+ CAN_CTRL_2_REG_BASE,
+ CYGNUM_HAL_INTERRUPT_CAN2_TX,
+ 1,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY,
+ CAN1_FLAG_STARTUP_ACCFILT_SETUP);
+#endif
+
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2
+LPC2XXX_CAN_INFO(lpc2xxx_can2_info,
+ CAN_CTRL_3_REG_BASE,
+ CYGNUM_HAL_INTERRUPT_CAN3_TX,
+ 2,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY,
+ CAN2_FLAG_STARTUP_ACCFILT_SETUP);
+#endif
+
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3
+LPC2XXX_CAN_INFO(lpc2xxx_can3_info,
+ CAN_CTRL_4_REG_BASE,
+ CYGNUM_HAL_INTERRUPT_CAN4_TX,
+ 3,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY,
+ CAN3_FLAG_STARTUP_ACCFILT_SETUP);
+#endif
+#else // CYGINT_IO_CAN_CHANNELS == 1
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0
+LPC2XXX_CAN_INFO(lpc2xxx_can0_info,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY,
+ CAN0_FLAG_STARTUP_ACCFILT_SETUP);
+#define CAN_CTRL_SINGLETON_BASE CAN_CTRL_1_REG_BASE
+#define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN1_TX
+#define CAN_SINGLETON_CHAN_NO 0
+#endif
+
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1
+LPC2XXX_CAN_INFO(lpc2xxx_can1_info,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY,
+ CAN1_FLAG_STARTUP_ACCFILT_SETUP);
+#define CAN_CTRL_SINGLETON_BASE CAN_CTRL_2_REG_BASE
+#define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN2_TX
+#define CAN_SINGLETON_CHAN_NO 1
+#endif
+
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2
+LPC2XXX_CAN_INFO(lpc2xxx_can2_info,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY,
+ CAN2_FLAG_STARTUP_ACCFILT_SETUP);
+#define CAN_CTRL_SINGLETON_BASE CAN_CTRL_3_REG_BASE
+#define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN3_TX
+#define CAN_SINGLETON_CHAN_NO 2
+#endif
+
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3
+LPC2XXX_CAN_INFO(lpc2xxx_can3_info,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY,
+ CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY,
+ CAN3_FLAG_STARTUP_ACCFILT_SETUP);
+#define CAN_CTRL_SINGLETON_BASE CAN_CTRL_4_REG_BASE
+#define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN4_TX
+#define CAN_SINGLETON_CHAN_NO 3
+#endif
+
+#endif // #if CYGINT_IO_CAN_CHANNELS > 1
+
+
+//===========================================================================
+// PROTOTYPES
+//===========================================================================
+
+//--------------------------------------------------------------------------
+// Device driver interface functions
+//
+static bool lpc2xxx_can_init(struct cyg_devtab_entry* devtab_entry);
+static Cyg_ErrNo lpc2xxx_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
+static Cyg_ErrNo lpc2xxx_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
+static Cyg_ErrNo lpc2xxx_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
+static bool lpc2xxx_can_putmsg(can_channel *priv, CYG_CAN_MSG_T *pmsg, void *pdata);
+static bool lpc2xxx_can_getevent(can_channel *priv, CYG_CAN_EVENT_T *pevent, void *pdata);
+static void lpc2xxx_can_start_xmit(can_channel* chan);
+static void lpc2xxx_can_stop_xmit(can_channel* chan);
+
+
+//--------------------------------------------------------------------------
+// ISRs and DSRs
+//
+#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+static cyg_uint32 lpc2xxx_can_tx_ISR(cyg_vector_t vector, cyg_addrword_t data);
+static void lpc2xxx_can_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+static cyg_uint32 lpc2xxx_can_rx_ISR(cyg_vector_t vector, cyg_addrword_t data);
+static void lpc2xxx_can_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data);
+static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+
+
+//--------------------------------------------------------------------------
+// Private utility functions
+//
+static bool lpc2xxx_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
+static bool lpc2xxx_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate);
+static Cyg_ErrNo lpc2xxx_enter_lowpower_mode(can_channel *chan);
+static void lpc2xxx_start_module(can_channel *chan);
+static cyg_can_state lpc2xxx_get_state(lpc2xxx_can_info_t *info);
+static void lpc2xxx_set_state(lpc2xxx_can_info_t *info, cyg_can_state state);
+
+
+//--------------------------------------------------------------------------
+// Message box configuration
+//
+static void lpc2xxx_can_config_rx_all(can_channel *chan);
+#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+static void lpc2xxx_can_config_rx_none(can_channel *chan);
+static bool lpc2xxx_can_add_rx_filter(lpc2xxx_can_info_t *info, cyg_can_filter *filter);
+#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+
+
+#include "can_accfilt_lpc2xxx.c"
+
+//===========================================================================
+// GENERIC CAN IO DATA INITIALISATION
+//===========================================================================
+CAN_LOWLEVEL_FUNS(lpc2xxx_can_lowlevel_funs,
+ lpc2xxx_can_putmsg,
+ lpc2xxx_can_getevent,
+ lpc2xxx_can_get_config,
+ lpc2xxx_can_set_config,
+ lpc2xxx_can_start_xmit,
+ lpc2xxx_can_stop_xmit
+ );
+
+
+//---------------------------------------------------------------------------
+// CAN channel 0
+//
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0
+CYG_CAN_EVENT_T lpc2xxx_can0_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_RX]; // buffer for RX can events
+CYG_CAN_MSG_T lpc2xxx_can0_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_TX]; // buffer for TX can messages
+
+
+CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can0_chan,
+ lpc2xxx_can_lowlevel_funs,
+ lpc2xxx_can0_info,
+ CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN0_KBAUD),
+ lpc2xxx_can0_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_TX,
+ lpc2xxx_can0_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_RX
+ );
+
+
+DEVTAB_ENTRY(lpc2xxx_can0_devtab,
+ CYGPKG_DEVS_CAN_LPC2XXX_CAN0_NAME,
+ 0, // Does not depend on a lower level interface
+ &cyg_io_can_devio,
+ lpc2xxx_can_init,
+ lpc2xxx_can_lookup, // CAN driver may need initializing
+ &lpc2xxx_can0_chan
+ );
+#endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN0
+
+
+//---------------------------------------------------------------------------
+// CAN channel 1
+//
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1
+CYG_CAN_EVENT_T lpc2xxx_can1_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_RX]; // buffer for RX can events
+CYG_CAN_MSG_T lpc2xxx_can1_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_TX]; // buffer for TX can messages
+
+
+CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can1_chan,
+ lpc2xxx_can_lowlevel_funs,
+ lpc2xxx_can1_info,
+ CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN1_KBAUD),
+ lpc2xxx_can1_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_TX,
+ lpc2xxx_can1_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_RX
+ );
+
+
+DEVTAB_ENTRY(lpc2xxx_can1_devtab,
+ CYGPKG_DEVS_CAN_LPC2XXX_CAN1_NAME,
+ 0, // Does not depend on a lower level interface
+ &cyg_io_can_devio,
+ lpc2xxx_can_init,
+ lpc2xxx_can_lookup, // CAN driver may need initializing
+ &lpc2xxx_can1_chan
+ );
+#endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN1
+
+
+//---------------------------------------------------------------------------
+// CAN channel 2
+//
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2
+CYG_CAN_EVENT_T lpc2xxx_can2_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_RX]; // buffer for RX can events
+CYG_CAN_MSG_T lpc2xxx_can2_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_TX]; // buffer for TX can messages
+
+
+CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can2_chan,
+ lpc2xxx_can_lowlevel_funs,
+ lpc2xxx_can2_info,
+ CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN2_KBAUD),
+ lpc2xxx_can2_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_TX,
+ lpc2xxx_can2_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_RX
+ );
+
+
+DEVTAB_ENTRY(lpc2xxx_can2_devtab,
+ CYGPKG_DEVS_CAN_LPC2XXX_CAN2_NAME,
+ 0, // Does not depend on a lower level interface
+ &cyg_io_can_devio,
+ lpc2xxx_can_init,
+ lpc2xxx_can_lookup, // CAN driver may need initializing
+ &lpc2xxx_can2_chan
+ );
+#endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN2
+
+
+//---------------------------------------------------------------------------
+// CAN channel 3
+//
+#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3
+CYG_CAN_EVENT_T lpc2xxx_can3_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_RX]; // buffer for RX can events
+CYG_CAN_MSG_T lpc2xxx_can3_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_TX]; // buffer for TX can messages
+
+
+CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can3_chan,
+ lpc2xxx_can_lowlevel_funs,
+ lpc2xxx_can3_info,
+ CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN3_KBAUD),
+ lpc2xxx_can3_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_TX,
+ lpc2xxx_can3_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_RX
+ );
+
+
+DEVTAB_ENTRY(lpc2xxx_can3_devtab,
+ CYGPKG_DEVS_CAN_LPC2XXX_CAN3_NAME,
+ 0, // Does not depend on a lower level interface
+ &cyg_io_can_devio,
+ lpc2xxx_can_init,
+ lpc2xxx_can_lookup, // CAN driver may need initializing
+ &lpc2xxx_can3_chan
+ );
+#endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN3
+
+
+//===========================================================================
+// IMPLEMENTATION
+//===========================================================================
+
+
+
+//===========================================================================
+/// First initialisation and reset of CAN modul.
+//===========================================================================
+static bool lpc2xxx_can_init(struct cyg_devtab_entry* devtab_entry)
+{
+ can_channel *chan = (can_channel*)devtab_entry->priv;
+ bool res;
+
+#ifdef CYGDBG_IO_INIT
+ diag_printf("LPC2XXX CAN init\n");
+#endif
+
+ //
+ // Newer LPC2xxx variants do not support individual interrupt
+ // sources for CAN on chip peripherals
+ //
+#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+ //
+ // Create TX interrupt
+ //
+ cyg_drv_interrupt_create(CAN_ISRVEC(info),
+ info->tx_interrupt_priority,
+ (cyg_addrword_t)chan, // Data item passed to interrupt handler
+ lpc2xxx_can_tx_ISR,
+ lpc2xxx_can_tx_DSR,
+ &info->tx_interrupt_handle,
+ &info->tx_interrupt);
+ cyg_drv_interrupt_attach(info->tx_interrupt_handle);
+ cyg_drv_interrupt_unmask(CAN_ISRVEC(info));
+
+ //
+ // Create RX interrupt
+ //
+ cyg_drv_interrupt_create(CAN_ISRVEC(info) + 6,
+ info->rx_interrupt_priority,
+ (cyg_addrword_t)chan, // Data item passed to interrupt handler
+ lpc2xxx_can_rx_ISR,
+ lpc2xxx_can_rx_DSR,
+ &info->rx_interrupt_handle,
+ &info->rx_interrupt);
+ cyg_drv_interrupt_attach(info->rx_interrupt_handle);
+ cyg_drv_interrupt_unmask(CAN_ISRVEC(info) + 6);
+#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+
+ //
+ // Now create and enable global CAN interrupt. This interrupt is
+ // global for all channels and so we need to call it only one times -
+ // when the first channel is initialized
+ //
+#if CYGINT_IO_CAN_CHANNELS > 1
+ if (!lpc2xxx_global_can_info.init_cnt)
+#endif // #if CYGINT_IO_CAN_CHANNELS > 1
+ {
+ //
+ // Create err interrupt
+ //
+ cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_CAN,
+#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+ CYGNUM_DEVS_CAN_LPC2XXX_ERR_INT_PRIORITY,
+#else // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+ CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY,
+#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+ 0, // Data item passed to interrupt handler
+ lpc2xxx_can_ISR,
+ lpc2xxx_can_DSR,
+ &lpc2xxx_global_can_info.interrupt_handle,
+ &lpc2xxx_global_can_info.interrupt);
+ cyg_drv_interrupt_attach(lpc2xxx_global_can_info.interrupt_handle);
+ cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_CAN);
+ }
+
+ res = lpc2xxx_can_config_channel(chan, &chan->config, true);
+#if CYGINT_IO_CAN_CHANNELS > 1
+ lpc2xxx_global_can_info.active_channels[lpc2xxx_global_can_info.init_cnt++] = chan;
+#else // CYGINT_IO_CAN_CHANNELS > 1
+ lpc2xxx_global_can_info.active_channels[0] = chan;
+#endif
+ return res;
+}
+
+
+//===========================================================================
+// Configure can channel
+//===========================================================================
+static bool lpc2xxx_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
+{
+ CAN_DECLARE_INFO(chan);
+ bool res = true;
+
+ if (init)
+ {
+ //
+ // In case platform needs extra initialization (i.e. setup of
+ // CAN transceivers) it should implement this macro
+ //
+#ifdef CYGPRI_IO_CAN_LPC2XXX_PLF_INIT_HOOK
+ CYGPRI_IO_CAN_LPC2XXX_PLF_INIT_HOOK(chan, config);
+#endif
+
+ HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF); // Acceptance Filter Mode Register = off
+ HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET); // Go into reset mode
+ HAL_WRITE_UINT32(CAN_CTRL_IER(info), 0); // disable all interrupts
+ HAL_WRITE_UINT32(CAN_CTRL_GSR(info), 0); // Clear Status register - clears error counters
+
+ //
+ // Perform platform/variant specific initialisation here.
+ // The variant/ platform should setup the pin configuration to support
+ // CAN here
+ //
+ HAL_LPC2XXX_INIT_CAN(CAN_CHAN_NO(info));
+
+ //
+ // If this is the first channel to initialize then we reset the CAN
+ // registers and setup the CAN I/O pins
+ //
+#if CYGINT_IO_CAN_CHANNELS > 1
+ if (!lpc2xxx_global_can_info.init_cnt)
+#endif // #if CYGINT_IO_CAN_CHANNELS > 1
+ {
+ lpc2xxx_can_accfilt_reset();
+ }
+ } // if (init)
+
+ res = lpc2xxx_can_set_baud(chan, &config->baud); // set baudrate
+ // $$$$ enable receive interrupt?
+ HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_OPERATIONAL); // enter normal operating mode
+
+ //
+ // store new config values
+ //
+ if (config != &chan->config)
+ {
+ chan->config = *config;
+ }
+
+ return res;
+}
+
+
+//===========================================================================
+// Set baudrate of certain can channel
+//===========================================================================
+static bool lpc2xxx_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate)
+{
+ bool res = true;
+ cyg_uint32 canbtr;
+ cyg_uint32 canmod;
+ CAN_DECLARE_INFO(chan);
+
+ //
+ // Get bit timings from HAL because bit timings depend on sysclock
+ // If the macro fills the canbtr value with 0 then the baudrate
+ // is not supported and the function returns false
+ //
+ HAL_LPC2XXX_GET_CAN_BR(*baudrate, canbtr);
+ if (0 == canbtr)
+ {
+ return false;
+ }
+
+ //
+ // Any modificatons to the baudrate register must be done while CAN
+ // module is in reset mode. So we first set the CAN module in reset
+ // mode, then we set baudrate and then we restore content of CANMOD
+ // register
+ //
+ HAL_READ_UINT32(CAN_CTRL_MOD(info), canmod); // backup canmod register
+ HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET); // Go into reset mode
+ HAL_WRITE_UINT32(CAN_CTRL_BTR(info), canbtr); // write baudrate value
+ HAL_WRITE_UINT32(CAN_CTRL_MOD(info), canmod); // restore previous value
+
+ return res;
+}
+
+
+//===========================================================================
+// Lookup the device and return its handle
+//===========================================================================
+static Cyg_ErrNo lpc2xxx_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
+{
+ can_channel* chan = (can_channel*) (*tab)->priv;
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+ cyg_uint32 regval;
+
+ chan->callbacks->can_init(chan);
+
+ //
+ // If runtime acceptance filter configuration is supported then we only
+ // configure RX ALL if the user selected the RX ALL setup in config utility
+ //
+#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+ if (info->flags & INFO_FLAG_STARTUP_RX_ALL)
+#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+ {
+ lpc2xxx_can_config_rx_all(chan);
+ }
+
+ HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_ON); // Activate acceptance filter
+ HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
+ regval = regval | IER_RX | CAN_MISC_INT; // enable all interrupts
+ HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval);
+
+ return ENOERR;
+}
+
+
+#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+//===========================================================================
+// Setup LPC2XXX CAN module in a state where all message boxes are disabled
+// After this call it is possible to add single message buffers and filters
+//===========================================================================
+static void lpc2xxx_can_config_rx_none(can_channel *chan)
+{
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+
+ //
+ // Remove all acceptance filters
+ // $$$$ maybe we should also abort any pending transfers and
+ // disable receive interrupts ?
+ //
+ lpc2xxx_can_accfilt_remove_all_ctrl_entries(info);
+ info->flags &= ~INFO_FLAG_RX_ALL;
+#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
+ lpc2xxx_can_accfilt_dbg_dump();
+#endif
+}
+
+
+//===========================================================================
+// Add one single message filter to acceptance filter
+//===========================================================================
+static bool lpc2xxx_can_add_rx_filter(lpc2xxx_can_info_t *info, cyg_can_filter *filter)
+{
+ bool res;
+
+ res = lpc2xxx_can_accfilt_add(info, filter->msg.id, 0, filter->msg.ext);
+ if (!res)
+ {
+ filter->handle = CYGNUM_CAN_MSGBUF_NA;
+ }
+#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
+ lpc2xxx_can_accfilt_dbg_dump();
+#endif
+ return res;
+}
+#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+
+
+
+#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+//===========================================================================
+// Configure message buffers
+//===========================================================================
+static Cyg_ErrNo lpc2xxx_can_config_msgbuf(can_channel *chan, const void* buf, cyg_uint32* len)
+{
+ Cyg_ErrNo res = ENOERR;
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+ cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *)buf;
+
+ if (*len != sizeof(cyg_can_msgbuf_cfg))
+ {
+ return -EINVAL;
+ }
+
+ switch (msg_buf->cfg_id)
+ {
+ //
+ // clear all message filters and remote buffers - prepare for message buffer
+ // configuration
+ //
+ case CYGNUM_CAN_MSGBUF_RESET_ALL :
+ {
+ lpc2xxx_can_config_rx_none(chan);
+ }
+ break;
+
+ //
+ // setup driver for reception of all standard and extended messages
+ //
+ case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL :
+ {
+ if (!(info->flags & INFO_FLAG_RX_ALL)) // if rx_all is enabled we do not need to do anything
+ {
+ lpc2xxx_can_config_rx_all(chan); // setup RX all state
+ }
+ }
+ break;
+
+ //
+ // add single message filter, message with filter ID will be received
+ //
+ case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD :
+ {
+ cyg_can_filter *filter = (cyg_can_filter*) buf;
+
+ //
+ // if the acceptance filter is configured to receive all messages then
+ // it is not allowed to add single message filters because then more
+ // than one acceptance filter would receive the same CAN id
+ //
+ if (info->flags & INFO_FLAG_RX_ALL)
+ {
+ return -EPERM;
+ }
+
+ //
+ // try to allocate a free acceptance filter entry - if we have a free one
+ // then we can prepare the acceptance filter table for reception of
+ // this message
+ //
+ if (!lpc2xxx_can_add_rx_filter(info, filter))
+ {
+ return -EPERM;
+ }
+ }
+ break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD
+
+
+#ifdef CYGOPT_IO_CAN_REMOTE_BUF
+ //
+ // Try to add a new RTR response message buffer for automatic
+ // transmission of data frame on reception of a remote frame
+ //
+ case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD :
+ {
+ // $$$$ TODO implement remote response buffers in software
+ return -ENOSUPP;
+ }
+ break;
+
+ //
+ // write data into remote response buffer
+ //
+ case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE :
+ {
+ // $$$$ TODO implement remote response buffers in software
+ return -ENOSUPP;
+ }
+ break;
+#endif // #ifdef CYGOPT_IO_CAN_REMOTE_BUF
+ default:
+ return -EINVAL;
+ } // switch (buf->cfg_id)
+
+ return res;
+}
+#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+
+
+//===========================================================================
+// Read state of CAN controller
+// The CAN state variable for each channel is modified by DSR so if we
+// read the state we need to lock DSRs to protect the data access
+//===========================================================================
+static cyg_can_state lpc2xxx_get_state(lpc2xxx_can_info_t *info)
+{
+ cyg_can_state result;
+
+ cyg_drv_dsr_lock();
+ result = info->state;
+ cyg_drv_dsr_unlock();
+
+ return result;
+}
+
+
+//===========================================================================
+// Set state of CAN controller
+// The CAN state variable for each channel is modified by DSR so if we
+// write the state we need to lock DSRs to protect the data access
+//===========================================================================
+static void lpc2xxx_set_state(lpc2xxx_can_info_t *info, cyg_can_state state)
+{
+ cyg_drv_dsr_lock();
+ info->state = state;
+ cyg_drv_dsr_unlock();
+}
+
+
+//===========================================================================
+// Enter low power mode
+//===========================================================================
+static Cyg_ErrNo lpc2xxx_enter_lowpower_mode(can_channel *chan)
+{
+ cyg_uint32 regval;
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+
+ //
+ // Before we enter low power mode, we have to enable wake up interrupt
+ // Normally this interrupt is always enabled so we do not need to do
+ // anything here
+ //
+ HAL_READ_UINT32(CAN_CTRL_MOD(info), regval);
+
+ //
+ // Software can only set SM when RM in the CAN Mode register is 0
+ //
+ if (regval & CANMOD_RESET)
+ {
+ return -EPERM;
+ }
+
+ //regval &= CANMOD_SLEEP;
+ lpc2xxx_set_state(info, CYGNUM_CAN_STATE_STANDBY);
+ HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_SLEEP);
+ return ENOERR;
+}
+
+
+//===========================================================================
+// Start CAN module - set CANMOD operational and enable all interrupts
+//===========================================================================
+static void lpc2xxx_start_module(can_channel *chan)
+{
+ cyg_uint32 regval;
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+
+ HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_OPERATIONAL);
+ //
+ // The interrupt enable register is also modified by ISR and DSR so
+ // we need to protect acces here
+ //
+ cyg_drv_isr_lock();
+ HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
+ regval = regval | IER_RX | CAN_MISC_INT; // enable all interrupts
+ HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval);
+ info->state = CYGNUM_CAN_STATE_ACTIVE;
+ cyg_drv_isr_unlock();
+}
+
+
+//===========================================================================
+// Enter reset mode
+//===========================================================================
+static void lpc2xxx_enter_reset_mode(can_channel *chan)
+{
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+
+ info->state = CYGNUM_CAN_STATE_STOPPED;
+ HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET);
+}
+
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
+//===========================================================================
+// Add message filter group
+//===========================================================================
+static Cyg_ErrNo lpc2xxx_can_config_accfilt_group(can_channel *chan, const void* buf, cyg_uint32* len)
+{
+ bool res;
+ cyg_can_filtergroup_cfg *filter_grp = (cyg_can_filtergroup_cfg *)buf;
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+
+
+ if (*len != sizeof(cyg_can_filtergroup_cfg))
+ {
+ return -EINVAL;
+ }
+
+ if (filter_grp->lower_id_bound >= filter_grp->upper_id_bound)
+ {
+ return -EINVAL;
+ }
+
+ //
+ // if the acceptance filter is configured to receive all messages then
+ // it is not allowed to add single message filter groups because then more
+ // than one acceptance filter would receive the same CAN id
+ //
+ if (info->flags & INFO_FLAG_RX_ALL)
+ {
+ return -EPERM;
+ }
+
+ res = lpc2xxx_can_accfilt_add(info,
+ filter_grp->lower_id_bound,
+ filter_grp->upper_id_bound,
+ filter_grp->ext);
+
+#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
+ lpc2xxx_can_accfilt_dbg_dump();
+#endif
+ return res ? ENOERR : -EPERM;
+}
+#endif // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
+
+
+//===========================================================================
+// Change device configuration
+//===========================================================================
+static Cyg_ErrNo lpc2xxx_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
+{
+ Cyg_ErrNo res = ENOERR;
+
+ switch (key)
+ {
+ //
+ // Setup a new CAN configuration. This will i.e. setup a new baud rate
+ //
+ 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 (!lpc2xxx_can_config_channel(chan, config, false))
+ {
+ return -EINVAL;
+ }
+ }
+ break;
+
+#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+ //
+ // configure message buffers
+ //
+ case CYG_IO_SET_CONFIG_CAN_MSGBUF :
+ {
+ res = lpc2xxx_can_config_msgbuf(chan, buf, len);
+ }
+ break;
+#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
+ //
+ // Add message filter group to acceptance filter
+ //
+ case CYG_IO_SET_CONFIG_LPC2XXX_ACCFILT_GROUP :
+ {
+ return lpc2xxx_can_config_accfilt_group(chan, buf, len);
+ }
+ break;
+#endif // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
+
+ //
+ // Change CAN state of CAN module
+ //
+ case CYG_IO_SET_CONFIG_CAN_MODE :
+ {
+ cyg_can_mode *can_mode = (cyg_can_mode*) buf;
+
+ if (*len != sizeof(cyg_can_mode))
+ {
+ return -EINVAL;
+ }
+ *len = sizeof(cyg_can_mode);
+
+ //
+ // decide what to do according to mode
+ //
+ switch (*can_mode)
+ {
+ //
+ // The controller does not support a stopped and standby state so we
+ // simply enter the low power state here. This state is also safe for
+ // message buffer configuration
+ //
+ case CYGNUM_CAN_MODE_STOP : lpc2xxx_enter_reset_mode(chan); break;
+ case CYGNUM_CAN_MODE_START : lpc2xxx_start_module(chan); break;
+ case CYGNUM_CAN_MODE_STANDBY : lpc2xxx_enter_lowpower_mode(chan); break;
+ case CYGNUM_CAN_MODE_CONFIG : lpc2xxx_enter_reset_mode(chan); break;
+ }
+ }
+ break; // case CYG_IO_SET_CONFIG_CAN_MODE :
+ //
+ // Unknown config key - indicate this by returning -EINVAL
+ //
+ default:
+ return -EINVAL;
+ } // switch (key)
+
+ return res;
+}
+
+
+//===========================================================================
+// Query device configuration
+//===========================================================================
+static Cyg_ErrNo lpc2xxx_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
+{
+ Cyg_ErrNo res = ENOERR;
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+
+ switch(key)
+ {
+ //
+ // query state of CAN controller
+ //
+ case CYG_IO_GET_CONFIG_CAN_STATE :
+ {
+ cyg_can_state *can_state = (cyg_can_state*) buf;
+
+ if (*len != sizeof(cyg_can_state))
+ {
+ return -EINVAL;
+ }
+ *len = sizeof(cyg_can_state);
+ *can_state = lpc2xxx_get_state(info);
+ }
+ break;
+
+#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+ //
+ // Query message box information - returns available and free message
+ // boxes
+ //
+ case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO :
+ {
+ cyg_can_msgbuf_info *mbox_info = (cyg_can_msgbuf_info*) buf;
+
+ if (*len != sizeof(cyg_can_msgbuf_info))
+ {
+ return -EINVAL;
+ }
+ cyg_uint32 end_of_table;
+ *len = sizeof(cyg_can_msgbuf_info);
+
+ HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
+ mbox_info->count = LPC2XXX_CAN_MSG_FILTERS_MAX;
+ mbox_info->free = (ACCFILT_RAM_SIZE - end_of_table) / ACCFILT_COMMON_ENTRY_SIZE;
+ }
+ break;
+#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+
+
+ //
+ // Query hardware description of FlexCAN device driver
+ //
+ case CYG_IO_GET_CONFIG_CAN_HDI :
+ {
+ cyg_can_hdi *hdi = (cyg_can_hdi *)buf;
+ //
+ // comes from high level driver so we do not need to
+ // check buffer size here
+ //
+ hdi->support_flags = CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE
+ | CYGNUM_CAN_HDI_FULLCAN;
+ }
+ break;
+
+ default :
+ res = -EINVAL;
+ }// switch(key)
+
+ return res;
+}
+
+
+//===========================================================================
+// Send single message
+//===========================================================================
+static bool lpc2xxx_can_putmsg(can_channel *chan, CYG_CAN_MSG_T *pmsg, void *pdata)
+{
+ cyg_uint32 regval;
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *) chan->dev_priv;
+#else
+ CAN_DECLARE_INFO(info);
+#endif
+
+ //
+ // We use only one single transmit buffer of the three available buffers
+ // We use buffer 1 (buffer 2 and 3 are unused)
+ //
+ // The errata sheet tells the following about the transmit buffers:
+ // Problem: The Triple Transmit Buffer function cannot be used.
+ // Work-around: Use any one Transmit buffer only (Use either Transmit Buffer 1,
+ // Transmit Buffer 2 or Transmit Buffer 3 exclusively). The buffer you decided
+ // to use should be loaded only when there is no pending transmission.
+ //
+ HAL_READ_UINT32(CAN_CTRL_SR(info), regval);
+ if (!(regval & SR_TX_BUF_WRITE_OK))
+ {
+ return false;
+ }
+
+ regval = pmsg->dlc << 16;
+ if (pmsg->rtr)
+ {
+ regval |= TFI_DLC_RTR;
+ }
+
+#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
+ if (pmsg->ext)
+ {
+ regval |= TFI_DLC_EXT;
+ }
+#endif // #define CYGOPT_IO_CAN_EXT_CAN_ID
+ HAL_WRITE_UINT32(CAN_CTRL_TFI1(info), regval); // write DLC
+ HAL_WRITE_UINT32(CAN_CTRL_TID1(info), pmsg->id); // write ID
+ HAL_WRITE_UINT32(CAN_CTRL_TDA1(info), pmsg->data.dwords[0]); // write first 4 data bytes
+ HAL_WRITE_UINT32(CAN_CTRL_TDB1(info), pmsg->data.dwords[1]); // write second 4 data bytes
+
+ //
+ // Request transmission of message
+ // The errata sheet tells the following about tx request:
+ // Introduction: The CAN module can lose arbitration to another CAN node during an
+ // attempt to transmit a CAN message. The message of the CAN node the arbitration was
+ // lost to is supposed to be received correctly by the CAN module.
+ // Problem: Messages might not be received correctly if during a CAN Transmission the
+ // CAN bus arbitration is lost to another CAN node.
+ // Work-around: Use the Self Reception Request command instead of the Transmission
+ // Request command. However, it has to be taken into account that now all transmitted
+ // messages may be received if not prevented by appropriate Acceptance Filter settings.
+ // (Don't set up Acceptance Filter Message Identifiers for the messages you are
+ // transmitting yourself.)
+ //
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION
+ // Calc last_tx_id
+ regval = pmsg->id | (regval & LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK);
+
+ // Save last message id to next last_tx_id
+ info->last_tx_index = info->last_tx_index == 0 ? 1 : 0;
+ info->last_tx_id[info->last_tx_index] = regval;
+
+ // Write self transmission request
+ HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_SELF_RX_REQ | CMR_SEND_TX_BUF1);
+#else
+ // Write transmission request
+ HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_TX_REQ | CMR_SEND_TX_BUF1);
+#endif
+
+ return true;
+}
+
+
+//===========================================================================
+// Read event from device driver
+//===========================================================================
+static bool lpc2xxx_can_getevent(can_channel *chan, CYG_CAN_EVENT_T *pevent, void *pdata)
+{
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+ bool res = true;
+ cyg_uint32 regval;
+ cyg_uint32 event = *((cyg_uint32*)pdata);
+ lsc_buf_t data;
+
+ //
+ // Handle RX event
+ //
+ if (event & ICR_RX)
+ {
+ cyg_uint32 id;
+
+ pevent->flags |= CYGNUM_CAN_EVENT_RX;
+ HAL_READ_UINT32(CAN_CTRL_RFS(info), regval);
+ HAL_READ_UINT32(CAN_CTRL_RID(info), id);
+
+#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
+ if (regval & RFS_EXT)
+ {
+ pevent->msg.ext = CYGNUM_CAN_ID_EXT;
+ pevent->msg.id = id & 0x1FFFFFFF;
+ }
+ else
+#endif // #define CYGOPT_IO_CAN_EXT_CAN_ID
+ {
+#ifdef CYGOPT_IO_CAN_STD_CAN_ID
+ pevent->msg.ext = CYGNUM_CAN_ID_STD;
+ pevent->msg.id = id & 0x7FF;
+#endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
+ } // if (regval & RFS_EXT)
+
+ if (regval & RFS_RTR)
+ {
+ pevent->msg.rtr = CYGNUM_CAN_FRAME_RTR;
+ }
+ else
+ {
+ pevent->msg.rtr = CYGNUM_CAN_FRAME_DATA;
+ HAL_READ_UINT32(CAN_CTRL_RDA(info), pevent->msg.data.dwords[0]);
+ HAL_READ_UINT32(CAN_CTRL_RDB(info), pevent->msg.data.dwords[1]);
+ } //if (regval & RFS_RTR)
+ pevent->msg.dlc = RFS_GET_DLC(regval);
+ //
+ // Release the message buffer. Now this buffer can receive the next message
+ //
+ HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_RX_RELEASE_BUF);
+
+ //
+ // Now check if an data overrun occurred - a message was lost
+ // because the preceding message to this CAN controller was not read
+ // and released quickly enough. After reading the status we clear
+ // the overrun bit
+ //
+ HAL_READ_UINT32(CAN_CTRL_GSR(info), regval);
+ if (regval & GSR_DATA_OVR)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
+ HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_CLEAR_DATA_OVR);
+ }
+ }
+
+ //
+ // Handle TX events
+ //
+#ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+ if (event & ICR_TX1)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_TX;
+ }
+#endif
+
+ //
+ // Handle all other events
+ //
+ if (event & (CAN_MISC_INT | ICR_LUT_ERR))
+ {
+ HAL_READ_UINT32(CAN_CTRL_GSR(info), data.dword);
+
+ //
+ // 1: Error Warning Interrupt -- this bit is set on every change (set or clear) of the Error
+ // Status or Bus Status bit in CANSR, if the EIE bit in CAN is 1 at the time of the
+ // change.
+ //
+ if (event & ICR_ERR_WARN)
+ {
+ //
+ // If one of the warning counters is above 96 then the controller is in bus warning
+ // state. If both counters are below 96 the this interrupt indicates that the
+ // controller has left the bus warning state and is error active again
+ //
+ if (data.bytes[2] >= 96)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX;
+ info->state = CYGNUM_CAN_STATE_BUS_WARN;
+ }
+ else if (data.bytes[3] >= 96)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX;
+ info->state = CYGNUM_CAN_STATE_BUS_WARN;
+ }
+ else
+ {
+ info->state = CYGNUM_CAN_STATE_ACTIVE;
+ }
+ LPC2XXX_DBG_PRINT("ICR_ERR_WARN (%p)\n", (void*) chan);
+ }
+
+ //
+ // 1: Wake-Up Interrupt: this bit is set if the CAN controller is sleeping and bus activity
+ // is detected, if the WUIE bit in CANIE is 1.
+ //
+ if (event & ICR_WAKE_UP)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_LEAVING_STANDBY;
+ info->state = CYGNUM_CAN_STATE_ACTIVE;
+ LPC2XXX_DBG_PRINT("ICR_WAKE_UP (%p)\n", (void*) chan);
+ }
+
+ //
+ // Error Passive Interrupt -- this bit is set if the EPIE bit in CANIE is 1, and the CAN
+ // controller switches between Error Passive and Error Active mode in either
+ // direction. We have to check if the ERR bit is set in global status register.
+ // If it is set, then it is a switch to error passive else it is a switch to
+ // error active state
+ //
+ if (event & ICR_ERR_PASSIVE)
+ {
+ if (data.dword & GSR_ERR)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_ERR_PASSIVE;
+ info->state = CYGNUM_CAN_STATE_ERR_PASSIVE;
+ }
+ else
+ {
+ info->state = CYGNUM_CAN_STATE_ACTIVE;
+ }
+ LPC2XXX_DBG_PRINT("ICR_ERR_PASSIVE (%p)\n", (void*) chan);
+ }
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_ALIE
+ //
+ // Arbitration Lost Interrupt -- this bit is set if the ALIE bit in CANIE is 1, and the
+ // CAN controller loses arbitration while attempting to transmit.
+ //
+ if (event & ICR_ARBITR_LOST)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_ARBITRATION_LOST;
+ LPC2XXX_DBG_PRINT("ICR_ARBITR_LOST (%p)\n", (void*) chan);
+ }
+#endif // CYGOPT_DEVS_CAN_LPC2XXX_ALIE
+
+ //
+ // 1: Bus Error Interrupt -- this bit is set if the BEIE bit in CANIE is 1, and the CAN
+ // controller detects an error on the bus.
+ //
+ if (event & ICR_BUS_ERR)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_BUS_OFF;
+ LPC2XXX_DBG_PRINT("ICR_BUS_ERR (%p)\n", (void*) chan);
+ }
+
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+ //
+ // LUT error interrupt -- this bit is set if bit 0 in LUTerr is 1 and LUTerrAd
+ // points to entry in filter table for this CAN controller
+ //
+ if(event & ICR_LUT_ERR)
+ {
+ pevent->flags |= CYGNUM_CAN_EVENT_FILTER_ERR;
+ LPC2XXX_DBG_PRINT("ICR_LUT_ERR (%p)\n", (void*) chan);
+ }
+#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+
+ } // if (event & (CAN_MISC_INT | ICR_LUT_ERR))
+
+ return res;
+}
+
+
+//===========================================================================
+// Kick transmitter
+//===========================================================================
+static void lpc2xxx_can_start_xmit(can_channel* chan)
+{
+ cyg_uint32 regval;
+ CAN_DECLARE_INFO(chan);
+
+ LPC2XXX_DBG_PRINT("start_xmit (%p)\n", (void*) chan);
+
+ cyg_drv_dsr_lock();
+ HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
+ regval |= IER_TX1; // enable tx interrupt for tx buf 1
+ HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval);
+ cyg_drv_dsr_unlock();
+
+ //
+ // kick transmitter
+ //
+ chan->callbacks->xmt_msg(chan, 0); // Kick transmitter (if necessary)
+}
+
+
+//===========================================================================
+// Stop transmitter
+//===========================================================================
+static void lpc2xxx_can_stop_xmit(can_channel* chan)
+{
+ cyg_uint32 regval;
+ CAN_DECLARE_INFO(chan);
+
+ LPC2XXX_DBG_PRINT("stop_xmit (%p)\n", (void*) chan);
+
+ cyg_drv_dsr_lock();
+ HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
+ regval &= ~IER_TX1; // disable tx interrupt for tx buf 1
+ HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval);
+ cyg_drv_dsr_unlock();
+}
+
+
+#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+//===========================================================================
+// Low level transmit interrupt handler
+//===========================================================================
+static cyg_uint32 lpc2xxx_can_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+ //
+ // Now read input capture register - this clears all interrupt bits in this
+ // register and also acknowledges the interrupt - any further processing is done
+ // by the DSR
+ //
+ cyg_drv_interrupt_mask(vector);
+ cyg_drv_interrupt_acknowledge(vector);
+ LPC2XXX_DBG_PRINT("tx_ISR (%p)\n", (void*) data);
+ return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// High level transmit interrupt handler
+//===========================================================================
+static void lpc2xxx_can_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ can_channel *chan = (can_channel *)data;
+ cyg_uint32 regval;
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+
+ //
+ // First read the ICR register to acknowledge all interrupts and
+ // get all captured interrupts
+ //
+ HAL_READ_UINT32(CAN_CTRL_ICR(info), regval);
+
+ //
+ // If TX events are supported then only call the rcv_event() callback
+ // if any other event occurred - pass the event field to the getevent function
+ // to indicate the events
+ //
+#ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+ if (regval & ~ICR_TX1)
+#endif
+ {
+ chan->callbacks->rcv_event(chan, ®val);
+ }
+
+ //
+ // Now transmit next message and reenable interrupts
+ //
+ chan->callbacks->xmt_msg(chan, 0); // send next message
+ LPC2XXX_DBG_PRINT("tx_DSR (%p)\n", (void*) data);
+ cyg_drv_interrupt_unmask(vector);
+}
+
+
+//===========================================================================
+// Low level receive interrupt handler
+//===========================================================================
+static cyg_uint32 lpc2xxx_can_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION
+ cyg_uint32 regval;
+ can_channel* chan = (can_channel*)data;
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *) chan->dev_priv;
+ cyg_uint32 id;
+ cyg_uint32 index;
+
+ // We have to reject self tx message, so read message id
+ HAL_READ_UINT32(CAN_CTRL_RID(info), id);
+ HAL_READ_UINT32(CAN_CTRL_RFS(info), regval);
+ id |= (regval & LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK);
+
+ // Test message id
+ for(index = 0; index < 2; index++)
+ {
+ if(id == info->last_tx_id[index])
+ {
+ // Clear last_tx_id
+ info->last_tx_id[index] = LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID;
+
+ // Clear receive buffer
+ HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_RX_RELEASE_BUF);
+
+ // Acknowledge a vector
+ cyg_drv_interrupt_acknowledge(vector);
+
+ // Exit without calling DSR
+ LPC2XXX_DBG_PRINT("self_rx_ISR (%p)\n", (void*) data);
+ return CYG_ISR_HANDLED;
+ }
+ }
+#endif
+
+ //
+ // The ISR only disables and acknowledges the RX interrupt
+ // any further processing is done by DSR. We also need to mask the
+ // global CAN status interrupt here because the interrupt flag
+ // in ICR is not cleared yet and may still cause a status
+ // interrupt
+ //
+ cyg_drv_interrupt_mask(vector);
+ cyg_drv_interrupt_acknowledge(vector);
+ LPC2XXX_DBG_PRINT("rx_ISR (%p)\n", (void*) data);
+
+ return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// High level receive interrupt handler
+//===========================================================================
+static void lpc2xxx_can_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ can_channel *chan = (can_channel *)data;
+ cyg_uint32 icr = ICR_RX;
+
+ //
+ // Read the event, the receive buffer will be released by the
+ // get_event() function
+ //
+ chan->callbacks->rcv_event(chan, &icr);
+ LPC2XXX_DBG_PRINT("rx_DSR (%p)\n", (void*) data);
+ cyg_drv_interrupt_unmask(vector);
+}
+
+
+
+//===========================================================================
+// status ISR handler
+//===========================================================================
+static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+ //
+ // Acknowledge and disable the interrupt - any further processing is
+ // done by the DSR
+ //
+ cyg_drv_interrupt_mask(vector);
+ cyg_drv_interrupt_acknowledge(vector);
+ LPC2XXX_DBG_PRINT("err_ISR\n");
+ return CYG_ISR_CALL_DSR;
+}
+
+
+//===========================================================================
+// status ISR handler
+//===========================================================================
+static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+ // If we use acceptance filter we can get LUT error
+ cyg_uint32 luterr;
+ cyg_uint8 luterr_chan0 = 0; // Init to avoid warnings
+ cyg_uint8 luterr_chan1 = 0; // Init to avoid warnings
+
+ // Read LUT error flag
+ HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR, luterr);
+
+ if (luterr & 1)
+ {
+ cyg_uint32 lutaddr;
+ cyg_uint32 eff_sa;
+ lsc_buf_t errentry;
+
+ // Read address of failed entry (it clears interrupt flag)
+ HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR_ADDR, lutaddr);
+
+ // Read address of extended id individual table
+ HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
+
+ // Read error entry
+ HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + lutaddr, errentry.dword);
+
+ // If err entry from standard id tables then read two
+ // controllers numbers
+ if(lutaddr < eff_sa)
+ {
+ // Calc CAN controllers numbers
+ luterr_chan0 = (cyg_uint8) ACCFILT_STD_GET_CTRL_UPPER(errentry.dword);
+
+ if(errentry.column.lower & ACCFILT_STD_DIS)
+ {
+ luterr_chan1 = luterr_chan0;
+ }
+ else
+ {
+ luterr_chan1 = (cyg_uint8) ACCFILT_STD_GET_CTRL_LOWER(errentry.dword);
+ }
+ }
+ else
+ {
+ // Calc CAN controller number
+ luterr_chan0 = luterr_chan1 = (cyg_uint8) ACCFILT_EXT_GET_CTRL(errentry.dword);
+ }
+ }
+#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+
+ //
+ // Loop through all channels - we need to do this only if we have more
+ // than one channel so we can optimize here for single channel
+ //
+#if CYGINT_IO_CAN_CHANNELS > 1
+ cyg_uint8 i = 0;
+ while (lpc2xxx_global_can_info.active_channels[i])
+#endif
+ {
+ cyg_uint32 regval;
+ can_channel *chan = LPC2XXX_GET_CAN_CHANNEL(lpc2xxx_global_can_info, i++);
+ CAN_DECLARE_INFO(chan);
+
+ HAL_READ_UINT32(CAN_CTRL_ICR(info), regval);
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+ // Set ICR_LUT_ERR flag only for controller which cause LUT error
+ if ((luterr & 1) && ((luterr_chan0 == i) || (luterr_chan1 == i)))
+ {
+ regval |= ICR_LUT_ERR;
+ }
+#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+ regval &= CAN_MISC_INT; // don't care about RX and TX events here
+ if (regval)
+ {
+ chan->callbacks->rcv_event(chan, ®val);
+ }
+ } // while (lpc2xxx_global_can_info.active_channels[i])
+
+ LPC2XXX_DBG_PRINT("err_DSR\n");
+ cyg_drv_interrupt_unmask(vector);
+}
+#else // #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+
+
+//===========================================================================
+// Global CAN interrupt handler
+//===========================================================================
+static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+ //
+ // Disable interrupts, the DSR will enable it as soon as it processed
+ // the current interrupt
+ //
+ cyg_drv_interrupt_mask(vector);
+ cyg_drv_interrupt_acknowledge(vector);
+ LPC2XXX_DBG_PRINT("CAN_ISR\n");
+ return CYG_ISR_CALL_DSR;
+}
+
+//===========================================================================
+// Global CAN DSR
+//===========================================================================
+static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+ // If we use acceptance filter we can get LUT error
+ cyg_uint32 luterr;
+ cyg_uint8 luterr_chan0 = 0xFF; // Init to avoid warnings
+ cyg_uint8 luterr_chan1 = 0xFF; // Init to avoid warnings
+
+ // Read LUT error flag
+ HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR, luterr);
+
+ if (luterr & 1)
+ {
+ cyg_uint32 lutaddr;
+ cyg_uint32 eff_sa;
+ lsc_buf_t errentry;
+
+ // Read address of failed entry (it clears interrupt flag)
+ HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR_ADDR, lutaddr);
+
+ // Read address of extended id individual table
+ HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
+
+ // Read error entry
+ HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + lutaddr, errentry.dword);
+
+ // If errentry from standard id tables then read two controllers numbers
+ if(lutaddr < eff_sa)
+ {
+ // Calc CAN controllers numbers
+ luterr_chan0 = (cyg_uint8) ACCFILT_STD_GET_CTRL_UPPER(errentry.dword);
+
+ if(errentry.column.lower & ACCFILT_STD_DIS)
+ {
+ luterr_chan1 = luterr_chan0;
+ }
+ else
+ {
+ luterr_chan1 = (cyg_uint8) ACCFILT_STD_GET_CTRL_LOWER(errentry.dword);
+ }
+ }
+ else
+ {
+ // Calc CAN controller number
+ luterr_chan0 = luterr_chan1 = (cyg_uint8) ACCFILT_EXT_GET_CTRL(errentry.dword);
+ }
+ }
+#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+
+ //
+ // Walk through list of active CAN channels and process interrupts
+ // of all channels - we need to loop only if we have more than one CAN channel so
+ // we can optimize for single CAN channel here
+ //
+#if CYGINT_IO_CAN_CHANNELS > 1
+ cyg_uint8 i = 0;
+ while (lpc2xxx_global_can_info.active_channels[i])
+#endif // CYGINT_IO_CAN_CHANNELS > 1
+ {
+ cyg_uint32 icr;
+ can_channel *chan = LPC2XXX_GET_CAN_CHANNEL(lpc2xxx_global_can_info, i++);
+ CAN_DECLARE_INFO(chan);
+
+ HAL_READ_UINT32(CAN_CTRL_ICR(info), icr); // this read clears ICR
+#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+ // Set ICR_LUT_ERR flag only for controller which cause LUT error
+ if ((luterr_chan0 == i) || (luterr_chan1 == i))
+ {
+ icr |= ICR_LUT_ERR;
+ }
+#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
+ //
+ // If TX events are supported then we simply call the rcv_event()
+ // callback to store the event. If TX events are not supported then
+ // we only call the rcv_event() function if any other interrupt than
+ // the TX interrupt was captured
+ //
+#ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+ if (icr & ~ICR_TX1)
+#endif // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
+ {
+ chan->callbacks->rcv_event(chan, &icr);
+ }
+ //
+ // If this was an TX interrupt then transmit next message now
+ //
+ if (icr & ICR_TX1)
+ {
+ chan->callbacks->xmt_msg(chan, 0); // send next message
+ }
+ } // while (lpc2xxx_global_can_info.active_channels[i])
+ LPC2XXX_DBG_PRINT("CAN_DSR\n");
+ cyg_drv_interrupt_unmask(vector);
+}
+#endif // #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
+
+
+#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+//===========================================================================
+// Configure message boxes for reception of any CAN message
+//===========================================================================
+static void lpc2xxx_can_config_rx_all(can_channel *chan)
+{
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+ //
+ // First clear all acceptance filter entries and then insert the
+ // two RX all groups
+ //
+ lpc2xxx_can_config_rx_none(chan);
+#ifdef CYGOPT_IO_CAN_STD_CAN_ID
+ lpc2xxx_can_accfilt_add(info, 0x000, 0x7FF, CYGNUM_CAN_ID_STD);
+#endif // CYGOPT_IO_CAN_STD_CAN_ID
+#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
+ lpc2xxx_can_accfilt_add(info, 0x000, 0x1FFFFFFF, CYGNUM_CAN_ID_EXT);
+#endif // CYGOPT_IO_CAN_EXT_CAN_ID
+
+ info->flags |= INFO_FLAG_RX_ALL;
+#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
+ lpc2xxx_can_accfilt_dbg_dump();
+#endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
+}
+#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+
+
+#ifndef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+//===========================================================================
+// Configure message boxes for reception of any CAN message
+//===========================================================================
+static void lpc2xxx_can_config_rx_all(can_channel *chan)
+{
+ lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
+
+ lpc2xxx_can_accfilt_simple_rx_all();
+ info->flags |= INFO_FLAG_RX_ALL;
+
+#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
+ lpc2xxx_can_accfilt_dbg_dump();
+#endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
+}
+#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
+
+
+//---------------------------------------------------------------------------
+// EOF can_lpc2xxx.c