Mercurial > ecos
changeset 2377:1ca46bebd705
* AT91SAM7 CAN driver package created
* cdl/can_at91sam7.cdl
* include/can_at91sam7.inl
* src/can_at91sam7.c
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/current/ChangeLog @@ -0,0 +1,41 @@ +2007-03-23 Uwe Kindler <uwe_kindler@web.de> + + * AT91SAM7 CAN driver package created + * cdl/can_at91sam7.cdl + * include/can_at91sam7.inl + * src/can_at91sam7.c + +//=========================================================================== +//####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#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/current/cdl/can_at91sam7.cdl @@ -0,0 +1,214 @@ +# ==================================================================== +# +# can_at91sam7.cdl +# +# eCos AT91SAM7 CAN module 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: 2007-02-10 +# +#####DESCRIPTIONEND#### +# ==================================================================== + + +cdl_package CYGPKG_DEVS_CAN_AT91SAM7 { + display "Atmel AT91SAM7 CAN device drivers" + parent CYGPKG_IO_CAN_DEVICES + active_if CYGPKG_IO_CAN + active_if CYGPKG_HAL_ARM_AT91SAM7 + requires CYGPKG_ERROR + include_dir cyg/io + description " + This option enables the CAN device drivers for the + Atmel AT91SAM7." + compile -library=libextras.a can_at91sam7.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_at91sam7.h>" + puts $::cdl_system_header "#define CYGDAT_IO_CAN_DEVICE_INL <cyg/io/can_at91sam7.inl>" + puts $::cdl_system_header "/***** CAN driver proc output end *****/" + } + + cdl_interface CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS { + display "AT91SAM7 CAN Channel" + flavor bool + description " + This interface is implemented for each single CAN channnel + of an AT91SAM7 chip and counts the number of available + channels." + } + + + # Support up one on-chip CAN module. The number may vary between + # processor variants so it is easy to update this here + for { set ::sam7can 0 } { $::sam7can < 1 } { incr ::sam7can } { + + cdl_interface CYGINT_DEVS_CAN_AT91SAM7_CAN[set ::sam7can] { + display "Platform provides CAN [set ::sam7can]" + flavor bool + description " + This interface will be implemented if the specific AT91SAM7 + processor being used has on-chip CAN [set ::sam7can], and if + that CAN module is accessible on the target hardware." + } + + cdl_component CYGPKG_DEVS_CAN_AT91SAM7_CAN[set ::sam7can] { + display "Allow access to the on-chip CAN [set ::sam7can] via a CAN driver" + flavor bool + active_if CYGINT_DEVS_CAN_AT91SAM7_CAN[set ::sam7can] + default_value 1 + implements CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS + implements CYGINT_IO_CAN_TIMESTAMP + implements CYGINT_IO_CAN_RUNTIME_MBOX_CFG + implements CYGINT_IO_CAN_REMOTE_BUF + implements CYGINT_IO_CAN_AUTOBAUD + description " + If the application needs to access the on-chip CAN module [set ::sam7can] + via an eCos CAN driver then this option should be enabled." + + cdl_option CYGPKG_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_NAME { + display "Device name for CAN module [set ::sam7can]" + flavor data + default_value [format {"\"/dev/can%d\""} $::sam7can] + 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_AT91SAM7_CAN[set ::sam7can]_KBAUD { + display "Default baud rate for CAN module [set ::sam7can]" + flavor data + default_value 100 + legal_values { 10 20 50 100 125 250 500 800 1000 "AUTO"} + description "This option determines the initial baud rate in KBaud for + CAN module [set ::sam7can]" + } + + cdl_option CYGNUM_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_QUEUESIZE_TX { + display "Size of TX Queue for the CAN module [set ::sam7can] driver" + flavor data + default_value 8 + legal_values 1 to 64 + 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_AT91SAM7_CAN[set ::sam7can]_QUEUESIZE_RX { + display "Size of RX Queue for the CAN module [set ::sam7can] driver" + flavor data + default_value 32 + legal_values 8 to 128 + 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_AT91SAM7_CAN[set ::sam7can]_ISR_PRIORITY { + display "Interrupt priority" + flavor data + default_value 4 + legal_values 0 to 7 + description " + Interrupt priority CAN module [set ::sam7can]. Each interrupt source + has a programmable priority level of 0 to 7. Level 7 is the + highest priority and level 0 the lowest." + } + + cdl_option CYGNUM_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_DEFAULT_TX_MBOX { + display "Default TX message box" + flavor data + calculated 7 + description " + By default one message buffer will be used for message transmission. + This option selects one of the 8 CAN message buffers for + transmission." + } + + cdl_option CYGNUM_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_STD_MBOXES { + display "11 Bit standard ID msg. buffers" + flavor booldata + implements CYGINT_IO_CAN_STD_CAN_ID + default_value 3 + legal_values 1 to 7 + requires CYGNUM_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_STD_MBOXES + CYGNUM_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_EXT_MBOXES < 8 + description " + The CAN module provides 8 message buffers. One message buffer + is reserved for message transmission. The remaining 7 buffers are + available for reception of messages. This configuration option + defines the number of message boxes for reception of CAN messages + with standard identifier. This configuration option does not matter + when you configure message filters at runtime. Only if the CAN + modul is configured to receive all available CAN identifiers, + then this configuration option is important. If you get + RX overrun events, you should raise the number of message boxes or + lower the CAN baud rate." + } + + cdl_option CYGNUM_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_EXT_MBOXES { + display "29 Bit extended ID msg. buffers" + flavor booldata + implements CYGINT_IO_CAN_EXT_CAN_ID + default_value 4 + legal_values 1 to 7 + requires CYGNUM_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_STD_MBOXES + CYGNUM_DEVS_CAN_AT91SAM7_CAN[set ::sam7can]_EXT_MBOXES < 8 + description " + The CAN module provides 8 message buffers. One message buffer + is reserved for message transmission. The remaining 7 buffers are + available for reception of messages. This configuration option + defines the number of message boxes for reception of CAN messages + with extended identifier. This configuration option does not matter + when you configure message filters at runtime. Only if the FlexCAN + modul is configured to receive all available CAN identifiers, + then this configuration option is important. If you get + RX overrun events, you should raise the number of message boxes or + lower the CAN baud rate." + } + } + } + + cdl_option CYGDBG_DEVS_CAN_AT91SAM7_DEBUG { + display "Support printing debug information" + default_value 0 + description " + Check this box to turn ON debug options for AT91SAM7 CAN device driver." + } +}
new file mode 100644 --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/current/include/can_at91sam7.inl @@ -0,0 +1,187 @@ +#ifndef CYGONCE_CAN_AT91SAM7_H +#define CYGONCE_CAN_AT91SAM7_H +//========================================================================== +// +// devs/can/arm/at91sam7x/current/include/can_at91sam7.inl +// +// CAN message macros for Atmel AT91SAM7X 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: 2007-02-08 +// Purpose: Support AT91SAM7X on-chip CAN moduls +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +//========================================================================== +// INCLUDE +//========================================================================== +#include <pkgconf/devs_can_at91sam7.h> + + +//========================================================================== +// DATA TYPES +//========================================================================== + +//-------------------------------------------------------------------------- +// We define our own CAN message data type here. This structure needs less +// memory than the common CAN message defined by IO layer. This is important +// because the AT91SAM7 contains only 64 KBytes RAM memory +// +typedef struct st_at91sam7_can_message +{ + cyg_can_msg_data data;// 8 data bytes +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + cyg_uint32 id; // also extended identifiers (29 Bit) are supported + cyg_uint8 ctrl;// control stores extended flag, rtr flag and dlc +#else + // + // only standard identifiers are supported - we need only 11 bit of + // the data word to store the identifier. So we have 5 bit left to store + // the the rtr flag and the dlc flag. We do not need the IDE flag because + // only standard identifiers are supported + // + cyg_uint16 id; +#endif +} at91sam7_can_message; + + +//-------------------------------------------------------------------------- +// We also define an own event structure here to store the received events +// This event structure uses the device CAN message structure and +// 16 Bit value for timestamps +// +typedef struct st_at91sam7_can_event +{ + cyg_uint16 flags; +#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP + cyg_uint16 timestamp; +#endif + at91sam7_can_message msg; +} at91sam7_can_event; + + + +//========================================================================== +// DEFINES +//========================================================================== +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID +// +// If we use extended identifier then we store the message parameters +// into control word +// +#define AT91SAM7_CAN_SET_DLC(_msg_, _dlc_) ((_msg_).ctrl = (_dlc_)) // this also clears the ctrl +#define AT91SAM7_CAN_SET_EXT(_msg_) ((_msg_).ctrl |= 0x01 << 4) +#define AT91SAM7_CAN_SET_RTR(_msg_) ((_msg_).ctrl |= 0x01 << 5) + +#define AT91SAM7_CAN_GET_DLC(_msg_) ((_msg_).ctrl & 0x0F) +#define AT91SAM7_CAN_IS_EXT(_msg_) ((((_msg_).ctrl >> 4) & 0x01) != 0) +#define AT91SAM7_CAN_IS_RTR(_msg_) ((((_msg_).ctrl >> 5) & 0x01) != 0) +#define AT91SAM7_CAN_GET_ID(_msg_) ((_msg_).id & CYG_CAN_EXT_ID_MASK) +#else // CYGOPT_IO_CAN_EXT_CAN_ID +// +// We use only standard identifiers and we can store the message parameters +// into the upper 5 bits of the 16 bit id field (only 11 bits are required for +// standard frames +// +#define AT91SAM7_CAN_SET_DLC(_msg_, _dlc_) ((_msg_).id |= (_dlc_) << 11) +#define AT91SAM7_CAN_SET_EXT(_msg_) // we do not need to support this flag - only std IDs supported +#define AT91SAM7_CAN_SET_RTR(_msg_) ((_msg_).id |= 0x01 << 15) + +#define AT91SAM7_CAN_GET_DLC(_msg_) (((_msg_).id >> 11) & 0x0F) +#define AT91SAM7_CAN_IS_EXT(_msg_) 0 // we do not support extended identifiers so this is always false +#define AT91SAM7_CAN_IS_RTR(_msg_) ((((_msg_).id >> 15) & 0x01) != 0) +#define AT91SAM7_CAN_GET_ID(_msg_) ((_msg_).id & CYG_CAN_STD_ID_MASK) +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + + +//--------------------------------------------------------------------------- +// The foolowing macros are required for CAN devicedriver. We define our own +// CAN messaeg and event structures and therefore we also need to define the +// two message conversion macros that translate out message/event into the +// standard CAN message/event +// +#define CYG_CAN_MSG_T at91sam7_can_message +#define CYG_CAN_EVENT_T at91sam7_can_event + +// +// We need to copy the timestamp field only if timestamps are supported by +// driver +// +#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP +#define CYG_CAN_READ_TIMESTAMP(_ioevent_ptr_, _devevent_ptr_) ((_ioevent_ptr_)->timestamp = (_devevent_ptr_)->timestamp) +#else +#define CYG_CAN_READ_TIMESTAMP(_ioevent_ptr_, _devevent_ptr_) +#endif + + +#define CYG_CAN_WRITE_MSG(_devmsg_ptr_, _iomsg_ptr_) \ +CYG_MACRO_START \ + (_devmsg_ptr_)->data = (_iomsg_ptr_)->data; \ + (_devmsg_ptr_)->id = (_iomsg_ptr_)->id; \ + AT91SAM7_CAN_SET_DLC(*(_devmsg_ptr_), (_iomsg_ptr_)->dlc); \ + if (CYGNUM_CAN_ID_EXT == (_iomsg_ptr_)->ext) {AT91SAM7_CAN_SET_EXT(*(_devmsg_ptr_));} \ + if (CYGNUM_CAN_FRAME_RTR == (_iomsg_ptr_)->rtr) {AT91SAM7_CAN_SET_RTR(*(_devmsg_ptr_));} \ +CYG_MACRO_END + + +#define CYG_CAN_READ_EVENT(_ioevent_ptr_, _devevent_ptr_) \ +CYG_MACRO_START \ + (_ioevent_ptr_)->flags = (_devevent_ptr_)->flags; \ + (_ioevent_ptr_)->msg.data = (_devevent_ptr_)->msg.data; \ + (_ioevent_ptr_)->msg.id = AT91SAM7_CAN_GET_ID((_devevent_ptr_)->msg); \ + (_ioevent_ptr_)->msg.dlc = AT91SAM7_CAN_GET_DLC((_devevent_ptr_)->msg); \ + if (AT91SAM7_CAN_IS_EXT((_devevent_ptr_)->msg)) { \ + (_ioevent_ptr_)->msg.ext = CYGNUM_CAN_ID_EXT; } \ + else { \ + (_ioevent_ptr_)->msg.ext = CYGNUM_CAN_ID_STD; } \ + if (AT91SAM7_CAN_IS_RTR((_devevent_ptr_)->msg)) { \ + (_ioevent_ptr_)->msg.rtr = CYGNUM_CAN_FRAME_RTR; } \ + else { \ + (_ioevent_ptr_)->msg.rtr = CYGNUM_CAN_FRAME_DATA; } \ + CYG_CAN_READ_TIMESTAMP(_ioevent_ptr_, _devevent_ptr_); \ +CYG_MACRO_END + +//--------------------------------------------------------------------------- +#endif // CYGONCE_CAN_AT91SAM7_H
new file mode 100644 --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/current/src/can_at91sam7.c @@ -0,0 +1,1594 @@ +//========================================================================== +// +// devs/can/arm/at91sam7x/current/src/can_at91sam7x.c +// +// CAN driver for Atmel AT91SAM7X 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-01-06 +// Purpose: Support at91sam7 on-chip CAN moduls +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +//========================================================================== +// INCLUDES +//========================================================================== +#include <pkgconf/system.h> +#include <pkgconf/io_can.h> +#include <pkgconf/io.h> +#include <pkgconf/devs_can_at91sam7.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> + +#include <cyg/hal/hal_diag.h> +#include <cyg/infra/cyg_ass.h> + + +//=========================================================================== +// DEFINES +//=========================================================================== + +// +// Support debug output if this option is enabled in CDL file +// +#ifdef CYGDBG_DEVS_CAN_AT91SAM7_DEBUG +#define AT91SAM7_DBG_PRINT diag_printf +#else +#define AT91SAM7_DBG_PRINT( fmt, ... ) +#endif + + +// +// we define our own set of register bits in order to be independent from +// platform specific names +// + +//--------------------------------------------------------------------------- +// Mailbox bits +// +#define BIT_MB0 (0x01 << 0) +#define BIT_MB1 (0x01 << 1) +#define BIT_MB2 (0x01 << 2) +#define BIT_MB3 (0x01 << 3) +#define BIT_MB4 (0x01 << 4) +#define BIT_MB5 (0x01 << 5) +#define BIT_MB6 (0x01 << 6) +#define BIT_MB7 (0x01 << 7) + + +//--------------------------------------------------------------------------- +// CAN Mode Register bits (CAN_MR) +// +#define MR_CAN_ENABLE (0x01 << 0) +#define MR_LOW_POWER (0x01 << 1) +#define MR_AUTOBAUD (0x01 << 2) +#define MR_OVERLOAD (0x01 << 3) +#define MR_TIMESTAMP_EOF (0x01 << 4) +#define MR_TIME_TRIG (0x01 << 5) +#define MR_TIMER_FREEZE (0x01 << 6) +#define MR_DISABLE_REPEAT (0x01 << 7) + + +//--------------------------------------------------------------------------- +// CAN Interrupt Enable/Disable, Mask and Status Register bits (CAN_IER, CAN_IDR, CAN_IMR) +// +#define INT_ERR_ACTIVE (0x01 << 16) +#define INT_WARN (0x01 << 17) +#define INT_ERR_PASSIVE (0x01 << 18) +#define INT_BUS_OFF (0x01 << 19) +#define INT_SLEEP (0x01 << 20) +#define INT_WAKEUP (0x01 << 21) +#define INT_TMR_OVF (0x01 << 22) +#define INT_TIMESTAMP (0x01 << 23) +#define INT_CRC_ERR (0x01 << 24) +#define INT_STUFF_ERR (0x01 << 25) +#define INT_ACKN_ERR (0x01 << 26) +#define INT_FORM_ERR (0x01 << 27) +#define INT_BIT_ERR (0x01 << 28) +#define INT_MB 0xFF // message box intterupt (mbox 1 - 8) +#define INT_MB_RX 0x7F // rx message box interrupts +#define INT_MB_TX 0x80 // tx message box interrupts + +// +// We do not enable INT_WARN by default because this flug is buggy and causes interrupts +// event if no counter reached warning level. +// +#define INT_ALL_ERR (INT_CRC_ERR | INT_STUFF_ERR | INT_ACKN_ERR | INT_FORM_ERR | INT_BIT_ERR) +#define INT_DEFAULT (INT_ERR_PASSIVE | INT_BUS_OFF | INT_SLEEP | INT_WAKEUP | INT_ALL_ERR) + + +// +// these bits are only in status register (CAN_SR) +// +#define SR_RX_BUSY (0x01 << 29) +#define SR_TX_BUSY (0x01 << 30) +#define SR_OVL_BUSY (0x01 << 31) + + +//--------------------------------------------------------------------------- +// CAN Baudrate Register (CAN_BR) +// +#define BR_PHASE2_BITMASK 0x00000007 +#define BR_PHASE1_BITMASK 0x00000070 +#define BR_PROPAG_BITMASK 0x00000700 +#define BR_SJW_BITMASK 0x00003000 +#define BR_BRP_BITMASK 0x007F0000 +#define BR_SMP_BITMASK 0x01000000 + + +//--------------------------------------------------------------------------- +// CAN Error Counter Register (CAN_ECR) +// +#define ECR_GET_TEC(_ecr_) (((_ecr_) >> 16) & 0xFF) +#define ECR_GET_REC(_ecr_) ((_ecr_) & 0xFF) + + +//--------------------------------------------------------------------------- +// CAN Transfer Command Resgister (CAN_TCR) +// +#define TCR_TMR_RESET 0x80000000 + + +//--------------------------------------------------------------------------- +// CAN Message Mode Register (CAN_MMRx) +// +#define MMR_TIMEMARK_BITMASK 0x0000FFFF +#define MMR_PRIOR_BITMASK 0x000F0000 + +#define MMR_MB_SHIFTER 24 +#define MMR_MB_TYPE_BITMASK (0x07 << MMR_MB_SHIFTER) // mask the mot bits +#define MMR_MB_TYPE_DISABLED (0x00 << MMR_MB_SHIFTER) // message box disabled +#define MMR_MB_TYPE_RX (0x01 << MMR_MB_SHIFTER) // rx message box +#define MMR_MB_TYPE_RX_OVW (0x02 << MMR_MB_SHIFTER) // rx message box with overwrite +#define MMR_MB_TYPE_TX (0x03 << MMR_MB_SHIFTER) // tx message box +#define MMR_MB_TYPE_CONSUME (0x04 << MMR_MB_SHIFTER) // consumer - receives RTR and sends its content +#define MMR_MB_TYPE_PRODUCE (0x05 << MMR_MB_SHIFTER) // producer - sends a RTR and waits for answer +#define MMR_MB_GET_TYPE(_mb_) ((_mb_) & MMR_MB_TYPE_BITMASK) + +//--------------------------------------------------------------------------- +// CAN Message Acceptance Mask/ID Register (CAN_MAMx, CAN_MIDx) +// +#define MID_MIDvB_BITMASK 0x0003FFFF +#define MID_MIDvA_BITMASK 0x1FFC0000 +#define MID_MIDE 0x20000000 +#define MID_MIDvA_SHIFTER 18 +#define MID_SET_STD(_id_) (((_id_) << MID_MIDvA_SHIFTER) & MID_MIDvA_BITMASK) +#define MID_SET_EXT(_id_) ((_id_) | MID_MIDE) +#define MAM_SET_STD ((((0x7FF << MID_MIDvA_SHIFTER) & MID_MIDvA_BITMASK) | MID_MIDE)) +#define MAM_SET_EXT 0xFFFFFFFF +#define MID_GET_STD(_mid_) (((_mid_) >> MID_MIDvA_SHIFTER) & CYG_CAN_STD_ID_MASK) +#define MID_GET_EXT(_mid_) ((_mid_) & CYG_CAN_EXT_ID_MASK) + + +//--------------------------------------------------------------------------- +// CAN Message Status Register (CAN_MSRx) +// +#define MSR_TIMESTAMP 0x0000FFFF +#define MSR_DLC 0x000F0000 +#define MSR_RTR 0x00100000 +#define MSR_MSG_ABORT 0x00400000 +#define MSR_RDY 0x00800000 +#define MSR_MSG_IGNORED 0x01000000 +#define MSR_DLC_SHIFTER 16 +#define MSR_DLC_GET(_msr_) (((_msr_) >> 16) & 0x0F) + +//--------------------------------------------------------------------------- +// CAN Message Control Register (CAN_MCRx) +// +#define MCR_DLC 0x000F0000 // MDLC +#define MCR_RTR 0x00100000 // MRTR +#define MCR_MSG_ABORT 0x00400000 // MACR +#define MCR_TRANSFER_CMD 0x00800000 // MTCR +#define MCR_DLC_SHIFTER 16 +#define MCR_DLC_CREATE(_len_) ((_len_) << MCR_DLC_SHIFTER) + +//--------------------------------------------------------------------------- +// CAN Module Register Layout +// +#define CANREG_MR 0x0000 +#define CANREG_IER 0x0004 +#define CANREG_IDR 0x0008 +#define CANREG_IMR 0x000C +#define CANREG_SR 0x0010 +#define CANREG_BR 0x0014 +#define CANREG_TIM 0x0018 +#define CANREG_TIMESTAMP 0x001C +#define CANREG_ECR 0x0020 +#define CANREG_TCR 0x0024 +#define CANREG_ACR 0x0028 + +#define CANREG_MB_BASE 0x0200 + +// +// Register layout of message box relativ to base register of a certain +// message box +// +#define CANREG_MMR 0x0000 +#define CANREG_MAM 0x0004 +#define CANREG_MID 0x0008 +#define CANREG_MFID 0x000C +#define CANREG_MSR 0x0010 +#define CANREG_MDL 0x0014 +#define CANREG_MDH 0x0018 +#define CANREG_MCR 0x001C + + +#define AT91SAM7_CAN_PERIPHERAL_ID 15 +#define CAN_MBOX_MIN 0 +#define CAN_MBOX_MAX 7 +#define CAN_MBOX_CNT 8 +#define CAN_MBOX_RX_MIN 0 +#define CAN_MBOX_RX_MAX (CAN_MBOX_MAX - 1) // one message box is tx +#define CAN_MBOX_RX_CNT (CAN_MBOX_CNT - 1) // one message box is tx + +#define CAN_MR(_extra_) (CAN_BASE(_extra_) + CANREG_MR) +#define CAN_IER(_extra_) (CAN_BASE(_extra_) + CANREG_IER) +#define CAN_IDR(_extra_) (CAN_BASE(_extra_) + CANREG_IDR) +#define CAN_IMR(_etxra_) (CAN_BASE(_extra_) + CANREG_IMR) +#define CAN_SR(_etxra_) (CAN_BASE(_extra_) + CANREG_SR) +#define CAN_BR(_etxra_) (CAN_BASE(_extra_) + CANREG_BR) +#define CAN_TIM(_etxra_) (CAN_BASE(_extra_) + CANREG_TIM) +#define CAN_TIMESTAMP(_etxra_) (CAN_BASE(_extra_) + CANREG_TIMESTAMP) +#define CAN_ECR(_etxra_) (CAN_BASE(_extra_) + CANREG_ECR) +#define CAN_TCR(_etxra_) (CAN_BASE(_extra_) + CANREG_TCR) +#define CAN_ACR(_etxra_) (CAN_BASE(_extra_) + CANREG_ACR) + +// +// Message box registers +// +#define CAN_MB_BASE(_extra_) (CAN_BASE(_extra_) + CANREG_MB_BASE) +#define CAN_MB_MMR(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MMR) +#define CAN_MB_MAM(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MAM) +#define CAN_MB_MID(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MID) +#define CAN_MB_MFID(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MFID) +#define CAN_MB_MSR(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MSR) +#define CAN_MB_MDL(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MDL) +#define CAN_MB_MDH(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MDH) +#define CAN_MB_MCR(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MCR) + + +//--------------------------------------------------------------------------- +// Optimize for the case of a single CAN channel, while still allowing +// multiple channels. At the moment only AT91SAM7 controllers with one +// CAN channel are known. +// +#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1 + +#define CAN_PID(_extra_) AT91SAM7_CAN_PERIPHERAL_ID +#define CAN_ISRVEC(_extra_) CAN_PID(_extra_) +#define CAN_ISRPRIO(_extra_) CYGNUM_DEVS_CAN_AT91SAM7_CAN0_ISR_PRIORITY +#define CAN_BASE(_extra_) AT91_CAN +#define CAN_DECLARE_INFO(_chan_) +#define CAN_MBOX_TX(_extra_) CYGNUM_DEVS_CAN_AT91SAM7_CAN0_DEFAULT_TX_MBOX +#define CAN_MBOX_STD_CNT(_extra_) CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES +#define CAN_MBOX_EXT_CNT(_extra_) CYGNUM_DEVS_CAN_AT91SAM7_CAN0_EXT_MBOXES +#define CAN_MBOX_RX_ALL_CNT(_extra) (CAN_MBOX_STD_CNT(_extra_) + CAN_MBOX_EXT_CNT(_extra_)) + +#ifndef CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES +#define CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES 0 +#endif + +#ifndef CYGNUM_DEVS_CAN_AT91SAM7_CAN0_EXT_MBOXES +#define CYGNUM_DEVS_CAN_AT91SAM7_CAN0_EXT_MBOXES 0 +#endif + +#else // #if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1 + +#define CAN_PID(_extra_) ((_extra_)->isrvec) +#define CAN_ISRVEC(_extra_) ((_extra_)->isrvec) +#define CAN_ISRPRIO(_extra_) ((_extra_)->isrprio) +#define CAN_BASE(_extra_) ((_extra_)->base) +#define CAN_DECLARE_INFO(_chan_) at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv; +#define CAN_MBOX_TX(_extra_) 7 // normally it is always the last mailbox +#define CAN_MBOX_STD_CNT(_extra_) ((_extra_)->mboxes_std_cnt) +#define CAN_MBOX_EXT_CNT(_extra_) ((_extra_)->mboxes_ext_cnt) +#define CAN_MBOX_RX_ALL_CNT(_extra) ((_extra_)->mboxes_rx_all_cnt) + +#endif // #if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1 + + +//=========================================================================== +// DATA TYPES +//=========================================================================== +typedef struct at91sam7_can_info_t +{ + cyg_interrupt interrupt; + cyg_handle_t interrupt_handle; + cyg_uint32 stat; // buffers status register value between ISR and DSR + cyg_uint8 free_mboxes; // number of free message boxes for msg filters and rtr buffers + bool rx_all; // true if reception of call can messages is active + cyg_can_state state; // state of CAN controller + +#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1 + cyg_uint32 base; // Per-bus h/w details + cyg_uint8 isrpri; // ISR priority + cyg_uint8 isrvec; // ISR vector (peripheral id) + cyg_uint8 mboxes_std_cnt; // contains number of standard message boxes available + cyg_uint8 mboxes_ext_cnt; // number of message boxes with ext id + cyg_uint8 mboxes_rx_all_cnt;// number of all available mboxes +#endif +} at91sam7_can_info_t; + + +// +// at91sam7 info initialisation +// +#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1 +#define AT91SAM7_CAN_INFO(_l, _base, _isrpri, _isrvec, _std_mboxes, _ext_mboxes) \ +at91sam7_can_info_t _l { \ + state : CYGNUM_CAN_STATE_STOPPED, \ + base : (_base), \ + isrpri : (_isrpri), \ + isrvec : (_isrvec), \ + mboxes_std_cnt : (_std_mboxes), \ + mboxes_ext_cnt : (_ext_mboxes), \ + mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes)), \ +}; +#else +#define AT91SAM7_CAN_INFO(_l) \ +at91sam7_can_info_t _l = { \ + state : CYGNUM_CAN_STATE_STOPPED, \ +}; +#endif + + +//=========================================================================== +// GLOBAL DATA +//=========================================================================== +#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1 +// +// ToDo - Initialisation of individual CAN channels if more than one channel +// is supported +// +#else // CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1 +// +// Only one single CAN channel supported by SAM7 chip +// +AT91SAM7_CAN_INFO(at91sam7_can0_info); +#endif + + +//=========================================================================== +// LOCAL DATA +//=========================================================================== +// +// Macro for creation of CAN_BR value for baudrate tbl +// + +#define CAN_BR_TBL_ENTRY(_brp_, _propag_, _phase1_, _phase2_, _sjw_) \ + ((_brp_ << 16) | (_propag_ << 8) | (_phase2_) | (_phase1_ << 4) | (_sjw_ << 12)) + +// +// Table with register values for baudrates at main clock of 48 MHz +// +static const cyg_uint32 at91sam7_br_tbl[] = +{ + CAN_BR_TBL_ENTRY(0xef, 0x07, 0x07, 0x02, 0), // 10 kbaud + CAN_BR_TBL_ENTRY(0x95, 0x04, 0x07, 0x01, 0), // 20 kbaud + CAN_BR_TBL_ENTRY(0x3b, 0x04, 0x07, 0x01, 0), // 50 kbaud + CAN_BR_TBL_ENTRY(0x1d, 0x04, 0x07, 0x01, 0), // 100 kbaud + CAN_BR_TBL_ENTRY(0x17, 0x04, 0x07, 0x01, 0), // 125 kbaud + CAN_BR_TBL_ENTRY(0x0b, 0x04, 0x07, 0x01, 0), // 250 kbaud + CAN_BR_TBL_ENTRY(0x05, 0x04, 0x07, 0x01, 0), // 500 kbaud + CAN_BR_TBL_ENTRY(0x03, 0x03, 0x07, 0x01, 0), // 800 kbaud + CAN_BR_TBL_ENTRY(0x02, 0x04, 0x07, 0x01, 0), // 1000 kbaud + CAN_BR_TBL_ENTRY(0x00, 0x00, 0x00, 0x00, 0), // Autobaud +}; + +// +// Macro fills baudrate register value depending on selected baudrate +// For a standard AT91 clock speed of 48 MHz we provide a pre calculated +// baudrate table. If the board uses another clock speed, then the platform +// HAL needs to provide an own HAL_AT91SAM7_GET_CAN_BR() macro that returns +// valid baudrate register values +// +#ifdef CYGNUM_HAL_ARM_AT91_CLOCK_SPEED_48000000 +#define HAL_AT91SAM7_GET_CAN_BR(_baudrate_, _br_) \ +CYG_MACRO_START \ + _br_ = at91sam7_br_tbl[(_baudrate_) - CYGNUM_CAN_KBAUD_10]; \ +CYG_MACRO_END +#endif + + +//=========================================================================== +// PROTOTYPES +//=========================================================================== + +//-------------------------------------------------------------------------- +// Device driver interface functions +// +static bool at91sam7_can_init(struct cyg_devtab_entry* devtab_entry); +static Cyg_ErrNo at91sam7_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name); +static Cyg_ErrNo at91sam7_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len); +static Cyg_ErrNo at91sam7_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len); +static bool at91sam7_can_putmsg(can_channel *priv, CYG_CAN_MSG_T *pmsg, void *pdata); +static bool at91sam7_can_getevent(can_channel *priv, CYG_CAN_EVENT_T *pevent, void *pdata); +static void at91sam7_can_start_xmit(can_channel* chan); +static void at91sam7_can_stop_xmit(can_channel* chan); + + +//-------------------------------------------------------------------------- +// ISRs and DSRs +// +static cyg_uint32 at91sam7_can_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void at91sam7_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); + + +//-------------------------------------------------------------------------- +// Private utility functions +// +static bool at91sam7_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init); +static bool at91sam7_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate); +static void at91sam7_can_mbox_config_rx_all(can_channel *chan); +static void at91sam7_can_setup_mbox(can_channel *chan, // channel + cyg_uint8 mbox, // message box number (0 -7) + cyg_uint32 mid, // message identifier + cyg_uint32 mam, // acceptance mask for this message box + cyg_uint32 rxtype); // RX or RX with overwrite are valid values +static void at91sam7_enter_lowpower_mode(can_channel *chan); +static void at91sam7_start_module(can_channel *chan); +static cyg_can_state at91sam7_get_state(at91sam7_can_info_t *info); + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +static void at91sam7_can_config_rx_none(can_channel *chan); +static Cyg_ErrNo at91sam7_can_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf); +#endif + + + + +//=========================================================================== +// GENERIC CAN IO DATA INITIALISATION +//=========================================================================== +CAN_LOWLEVEL_FUNS(at91sam7_can_lowlevel_funs, + at91sam7_can_putmsg, + at91sam7_can_getevent, + at91sam7_can_get_config, + at91sam7_can_set_config, + at91sam7_can_start_xmit, + at91sam7_can_stop_xmit + ); + + +CYG_CAN_EVENT_T at91sam7_can0_rxbuf[CYGNUM_DEVS_CAN_AT91SAM7_CAN0_QUEUESIZE_RX]; // buffer for RX can events +CYG_CAN_MSG_T at91sam7_can0_txbuf[CYGNUM_DEVS_CAN_AT91SAM7_CAN0_QUEUESIZE_TX]; // buffer for TX can messages + + +CAN_CHANNEL_USING_INTERRUPTS(at91sam7_can0_chan, + at91sam7_can_lowlevel_funs, + at91sam7_can0_info, + CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_AT91SAM7_CAN0_KBAUD), + at91sam7_can0_txbuf, CYGNUM_DEVS_CAN_AT91SAM7_CAN0_QUEUESIZE_TX, + at91sam7_can0_rxbuf, CYGNUM_DEVS_CAN_AT91SAM7_CAN0_QUEUESIZE_RX + ); + + +DEVTAB_ENTRY(at91sam7_can_devtab, + CYGPKG_DEVS_CAN_AT91SAM7_CAN0_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_can_devio, + at91sam7_can_init, + at91sam7_can_lookup, // CAN driver may need initializing + &at91sam7_can0_chan + ); + + +//=========================================================================== +// IMPLEMENTATION +//=========================================================================== + + + +//=========================================================================== +/// First initialisation and reset of CAN modul. +//=========================================================================== +static bool at91sam7_can_init(struct cyg_devtab_entry* devtab_entry) +{ + can_channel *chan = (can_channel*)devtab_entry->priv; + at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv; + +#ifdef CYGDBG_IO_INIT + diag_printf("AT91 CAN init\n"); +#endif + cyg_drv_interrupt_create(CAN_ISRVEC(info), + CAN_ISRPRIO(info), // Priority + (cyg_addrword_t)chan, // Data item passed to interrupt handler + at91sam7_can_ISR, + at91sam7_can_DSR, + &info->interrupt_handle, + &info->interrupt); + cyg_drv_interrupt_attach(info->interrupt_handle); + cyg_drv_interrupt_unmask(CAN_ISRVEC(info)); + + return at91sam7_can_config_channel(chan, &chan->config, true); +} + + +//=========================================================================== +// Lookup the device and return its handle +//=========================================================================== +static Cyg_ErrNo at91sam7_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name) +{ + can_channel* chan = (can_channel*) (*tab)->priv; + CAN_DECLARE_INFO(chan); + + chan->callbacks->can_init(chan); + HAL_WRITE_UINT32(CAN_IER(info), INT_DEFAULT); // enable wakeup and error interrupts + HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, 1 << CAN_PID(info)); // Enable the peripheral clock to the device + + // + // It is important to setup the message buffer configuration after enabling the + // peripheral clock. This is nowhere documented in the at91sam7 hardware manual. + // If the message buffer configuration is set before the peripheral clock is + // enabled, then message buffers that receive extended frames might not work + // properly + // + at91sam7_can_mbox_config_rx_all(chan); + + return ENOERR; +} + + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Setup AT91SAM7 CAN module in a state where all message boxes are disabled +// After this callit is possible to add single message buffers and filters +//=========================================================================== +static void at91sam7_can_config_rx_none(can_channel *chan) +{ + at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv; + cyg_uint8 i; + + // + // setup all RX messages moxes into a disabled state and disable all + // interrupts - maybe we have to abort pending transfers before $$$$ + // + HAL_WRITE_UINT32(CAN_IDR(info), INT_MB_RX); + for (i = 0; i < CAN_MBOX_RX_CNT; ++i) + { + HAL_WRITE_UINT32(CAN_MB_MMR(info, i), MMR_MB_TYPE_DISABLED); // first disable message box + } + + info->free_mboxes = CAN_MBOX_RX_CNT; + info->rx_all = false; +} + + +//=========================================================================== +// Add single message filter - setupm message box and enable interrupt +//=========================================================================== +static void at91sam7_can_add_rx_filter(can_channel *chan, cyg_uint8 mbox, cyg_can_message *msg) +{ + CAN_DECLARE_INFO(chan); + + if (msg->ext) + { + at91sam7_can_setup_mbox(chan, mbox, MID_SET_EXT(msg->id), MAM_SET_EXT, MMR_MB_TYPE_RX); + } + else + { + at91sam7_can_setup_mbox(chan, mbox, MID_SET_STD(msg->id), MAM_SET_STD, MMR_MB_TYPE_RX); + } + HAL_WRITE_UINT32(CAN_IER(info), 0x01 << mbox); +} +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Allocate message box +// Try to find a free message box and return its ID +//=========================================================================== +static cyg_int8 at91sam7_can_alloc_mbox(at91sam7_can_info_t *info) +{ + cyg_uint8 i; + cyg_int8 res = CYGNUM_CAN_MSGBUF_NA; + + if (info->free_mboxes) + { + for (i = (CAN_MBOX_RX_CNT - info->free_mboxes); i <= CAN_MBOX_RX_MAX; ++i) + { + cyg_uint32 mmr; + HAL_READ_UINT32(CAN_MB_MMR(info, i), mmr); + if ((mmr & MMR_MB_TYPE_BITMASK) == MMR_MB_TYPE_DISABLED) + { + info->free_mboxes--; + res = i; + break; + } + } + } // if (info->free_mboxes) + + return res; +} +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + +#ifdef CYGOPT_IO_CAN_REMOTE_BUF +//=========================================================================== +// Setup a RTR response message box +//=========================================================================== +static bool at91sam7_can_setup_rtrmbox(can_channel *chan, + cyg_uint32 mbox, + cyg_can_message *pmsg, + bool init) +{ + CAN_DECLARE_INFO(chan); + cyg_uint32 mcr; + + // + // To prevent concurrent access with the internal CAN core, the application + // must disable the mailbox before writing to CAN_MIDx registers - so we + // do this here + // + if (init) + { + if (pmsg->ext) + { + at91sam7_can_setup_mbox(chan, mbox, MID_SET_EXT(pmsg->id), MAM_SET_EXT, MMR_MB_TYPE_PRODUCE); + } + else + { + at91sam7_can_setup_mbox(chan, mbox, MID_SET_STD(pmsg->id), MAM_SET_STD, MMR_MB_TYPE_PRODUCE); + } + HAL_WRITE_UINT32(CAN_IER(info), 0x01 << mbox); // enable interrupt + } + else + { + cyg_uint32 msr; + // + // Check if this message box is ready for transmission or if it still transmits + // a message - we read the MSR register to check the ready flag + // + HAL_READ_UINT32(CAN_MB_MSR(info, mbox), msr); + if (!(msr & MSR_RDY)) + { + AT91SAM7_DBG_PRINT("(RTR) !MSR_RDY\n"); + return false; + } + } + + HAL_WRITE_UINT32(CAN_MB_MDL(info, mbox), pmsg->data.dwords[0]); // set data + HAL_WRITE_UINT32(CAN_MB_MDH(info, mbox), pmsg->data.dwords[1]); // set data + mcr = (pmsg->dlc << MCR_DLC_SHIFTER) | MCR_TRANSFER_CMD; // set data lengt and transfer request + HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), mcr); // transfer request + return true; +} +#endif // CYGOPT_IO_CAN_REMOTE_BUF + + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Configure message buffers +//=========================================================================== +static Cyg_ErrNo at91sam7_can_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf) +{ + Cyg_ErrNo res = ENOERR; + at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv; + + switch (buf->cfg_id) + { + // + // clear all message filters and remote buffers - prepare for message buffer + // configuration + // + case CYGNUM_CAN_MSGBUF_RESET_ALL : + { + at91sam7_can_config_rx_none(chan); + } + break; + + // + // setup AT91SAM7 CAN module for reception of all standard and extended messages + // + case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL : + { + if (!info->rx_all) // if rx_all is enabled we do not need to do anything + { + at91sam7_can_mbox_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 AT91SAM7 CAN module is configured to receive all messages then + // it is not allowed to add single message filters because then more + // than one message buffer would receive the same CAN id + // + if (info->rx_all) + { + return -EPERM; + } + + // + // try to allocate a free message box - if we have a free one + // then we can prepare the message box for reception of the + // desired message id + // + filter->handle = at91sam7_can_alloc_mbox(info); + if (filter->handle > CYGNUM_CAN_MSGBUF_NA) + { + at91sam7_can_add_rx_filter(chan, filter->handle, &filter->msg); + } + } + break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD + + +#ifdef CYGOPT_IO_CAN_REMOTE_BUF + // + // Try to add a new RTR response message buffer for automatic transmisson + // of data frame on reception of a remote frame + // + case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD : + { + cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; + rtr_buf->handle = at91sam7_can_alloc_mbox(info); + + if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA) + { + // + // if we have a free message buffer then we setup this buffer + // for remote frame reception + // + at91sam7_can_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg, true); + } + } + break; + + // + // write data into remote response buffer + // + case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE : + { + cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; + // + // If we have a valid rtr buf handle then we can store data into + // rtr message box + // + if ((rtr_buf->handle >= 0) && (rtr_buf->handle <= CAN_MBOX_RX_MAX)) + { + if (!at91sam7_can_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg, false)) + { + res = -EAGAIN; + } + } + else + { + res = -EINVAL; + } + } + break; +#endif // #ifdef CYGOPT_IO_CAN_REMOTE_BUF + } // 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 modiefied by DSR so if we +// read the state we need to lock DSRs to protect the data access +//=========================================================================== +static cyg_can_state at91sam7_get_state(at91sam7_can_info_t *info) +{ + cyg_can_state result; + + cyg_drv_dsr_lock(); + result = info->state; + cyg_drv_dsr_unlock(); + + return result; +} + + +//=========================================================================== +// Enter low power mode +// Before stopping the CAN clock (PMC), the CAN Controller must be in +// Low-power Mode to complete the current transfer. After restarting the +// clock, the application must disable the Low-power Mode of the +// CAN controller. If the power mode is entered, a sleep interrupt is +// generated. +//=========================================================================== +static void at91sam7_enter_lowpower_mode(can_channel *chan) +{ + CAN_DECLARE_INFO(chan); + + + cyg_uint32 mr; + HAL_READ_UINT32(CAN_MR(info), mr); + HAL_WRITE_UINT32(CAN_MR(info), mr | MR_LOW_POWER); + HAL_WRITE_UINT32(CAN_IER(info), INT_SLEEP); +} + + +//=========================================================================== +// Start CAN module (or leave the low power mode) +// If the CAN module is in STANDBY state then we enable the module clock +// and leave the low power mode by clearing the low power flag. +//=========================================================================== +static void at91sam7_start_module(can_channel *chan) +{ + CAN_DECLARE_INFO(chan); + cyg_uint32 mr; + + HAL_WRITE_UINT32(CAN_IER(info), INT_DEFAULT); // enable wakeup interrupt + HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, 1 << CAN_PID(info)); // restart peripheral clock + HAL_READ_UINT32(CAN_MR(info), mr); + mr &= ~MR_LOW_POWER ; + HAL_WRITE_UINT32(CAN_MR(info), mr | MR_CAN_ENABLE); // clear the low power flag to leave standby +} + +//=========================================================================== +// Change device configuration +//=========================================================================== +static Cyg_ErrNo at91sam7_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 (!at91sam7_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 : + { + cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *)buf; + + if (*len != sizeof(cyg_can_msgbuf_cfg)) + { + return -EINVAL; + } + + res = at91sam7_can_set_config_msgbuf(chan, msg_buf); + } + break; +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + // + // Change CAN state of AT91SAM7 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 acording 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 : at91sam7_enter_lowpower_mode(chan); break; + case CYGNUM_CAN_MODE_START : at91sam7_start_module(chan); break; + case CYGNUM_CAN_MODE_STANDBY : at91sam7_enter_lowpower_mode(chan); break; + case CYGNUM_CAN_MODE_CONFIG : at91sam7_enter_lowpower_mode(chan); break; + } + } + break; // case CYG_IO_SET_CONFIG_CAN_MODE : + } // switch (key) + + return res; +} + + +//=========================================================================== +// Query device configuration +//=========================================================================== +static Cyg_ErrNo at91sam7_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len) +{ + Cyg_ErrNo res = ENOERR; + at91sam7_can_info_t *info = (at91sam7_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 = at91sam7_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; + } + *len = sizeof(cyg_can_msgbuf_info); + + mbox_info->count = CAN_MBOX_RX_CNT; + mbox_info->free = info->free_mboxes; + } + 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 + | CYGNUM_CAN_HDI_AUTBAUD; +#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP + hdi->support_flags |= CYGNUM_CAN_HDI_TIMESTAMP; +#endif + } + break; + + default : + res = -EINVAL; + }// switch(key) + + return res; +} + + +//=========================================================================== +// Send single message +//=========================================================================== +static bool at91sam7_can_putmsg(can_channel *priv, CYG_CAN_MSG_T *pmsg, void *pdata) +{ + CAN_DECLARE_INFO(priv); + cyg_uint32 msr; + cyg_uint32 mcr = 0; + + // + // First check if this message box is ready fro transmission or if it still transmits + // a message - we read the MSR register to check the ready flag + // + HAL_READ_UINT32(CAN_MB_MSR(info, CAN_MBOX_TX(info)), msr); + if (!(msr & MSR_RDY)) + { + AT91SAM7_DBG_PRINT("!MSR_RDY\n"); + return false; + } + + // + // To prevent concurrent access with the internal CAN core, the application must disable + // the mailbox before writing to CAN_MIDx registers - so we do this now + // + HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_DISABLED); + + // + // Setup the message identifier - this depends on the frame type (standard or extended) + // +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (AT91SAM7_CAN_IS_EXT(*pmsg)) + { + HAL_WRITE_UINT32(CAN_MB_MID(info, CAN_MBOX_TX(info)), + pmsg->id | MID_MIDE); // set extended message id + } + else +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + HAL_WRITE_UINT32(CAN_MB_MID(info, CAN_MBOX_TX(info)), + (pmsg->id << MID_MIDvA_SHIFTER) & MID_MIDvA_BITMASK); // set standard message id +#endif // CYGOPT_IO_CAN_STD_CAN_ID + } + + HAL_WRITE_UINT32(CAN_MB_MDL(info, CAN_MBOX_TX(info)), pmsg->data.dwords[0]); // set data + HAL_WRITE_UINT32(CAN_MB_MDH(info, CAN_MBOX_TX(info)), pmsg->data.dwords[1]); // set data + HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_TX); // reenable the message box + mcr = (AT91SAM7_CAN_GET_DLC(*pmsg) << MCR_DLC_SHIFTER) | MCR_TRANSFER_CMD; // set data lengt and transfer request + + if (AT91SAM7_CAN_IS_RTR(*pmsg)) + { + mcr |= MCR_RTR; + } + + HAL_WRITE_UINT32(CAN_MB_MCR(info, CAN_MBOX_TX(info)), mcr); + return true; +} + + +//=========================================================================== +// Read event from device driver +//=========================================================================== +static bool at91sam7_can_getevent(can_channel *chan, CYG_CAN_EVENT_T *pevent, void *pdata) +{ + at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv; + cyg_uint32* pstat = (cyg_uint32 *)pdata; + cyg_uint8 mboxflags = (*pstat & INT_MB_RX); + cyg_uint8 mbox = 0; + bool res = true; + + // + // First check if a message box interrupt occured if a message box interrupt + // occured process the lowest message box that caused an interrupt + // + if (mboxflags) + { + cyg_uint32 msr; + cyg_uint32 mid; + cyg_uint32 mmr; + + while (!(mboxflags & 0x01)) + { + mboxflags >>= 1; + mbox++; + } + + // + // If the message box that caused the interrupt is an PRODUCER message box, + // then we received an remote request message, if not, then this is a normal + // RX message + // + HAL_READ_UINT32(CAN_MB_MMR(info, mbox), mmr); + HAL_READ_UINT32(CAN_MB_MSR(info, mbox), msr); + *pstat &= ~(0x01 << mbox); // clear flag + + if (MMR_MB_GET_TYPE(mmr) != MMR_MB_TYPE_PRODUCE) + { + HAL_READ_UINT32(CAN_MB_MID(info, mbox), mid); + pevent->flags |= CYGNUM_CAN_EVENT_RX; + if (msr & MSR_MSG_IGNORED) + { + pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX; + } + + // + // It is important to set the DLC first because this also clears the ctrl + // field if extended identifiers are supported + // + AT91SAM7_CAN_SET_DLC(pevent->msg, MSR_DLC_GET(msr)); + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (mid & MID_MIDE) + { + pevent->msg.id = MID_GET_EXT(mid); + AT91SAM7_CAN_SET_EXT(pevent->msg); + } + else +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + pevent->msg.id = MID_GET_STD(mid); +#endif // CYGOPT_IO_CAN_STD_CAN_ID + } + + if (msr & MSR_RTR) + { + AT91SAM7_CAN_SET_RTR(pevent->msg); + } + else + { + HAL_READ_UINT32(CAN_MB_MDL(info, mbox), pevent->msg.data.dwords[0]); + HAL_READ_UINT32(CAN_MB_MDH(info, mbox), pevent->msg.data.dwords[1]); + } +#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP + pevent->timestamp = msr & MSR_TIMESTAMP; +#endif + + HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), MCR_TRANSFER_CMD); // transfer request + AT91SAM7_DBG_PRINT("RXID: %x\n", AT91SAM7_CAN_GET_ID(pevent->msg)); + } // if (!(mbox & info->rtr_mboxes) + else + { + HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), (msr & MSR_DLC) | MCR_TRANSFER_CMD); // transfer request + // + // We do not need to store an event into receive queue if the stat field does + // not contain any further event flags. If stat is empty we can set res + // to false and no event will bestore + // + res = !(*pstat == 0); + } + + HAL_WRITE_UINT32(CAN_IER(info), 0x01 << mbox); // enable interruptfor this message box + } // if (mboxflags) + + // + // Now check if additional events occured + // + if (*pstat) + { + if (*pstat & INT_WAKEUP) + { + AT91SAM7_DBG_PRINT("WAKE\n"); + pevent->flags |= CYGNUM_CAN_EVENT_LEAVING_STANDBY; + *pstat &= ~INT_WAKEUP; + info->state = CYGNUM_CAN_STATE_ACTIVE; + } + + if (*pstat & INT_ERR_PASSIVE) + { + AT91SAM7_DBG_PRINT("ERRP\n"); + pevent->flags |= CYGNUM_CAN_EVENT_ERR_PASSIVE; + *pstat &= ~INT_ERR_PASSIVE; + info->state = CYGNUM_CAN_STATE_ERR_PASSIVE; + HAL_WRITE_UINT32(CAN_IER(info), INT_WAKEUP); + } + + if (*pstat & INT_WARN) + { + // + // check which counter reached its warning level (> 96) + // + cyg_uint8 ecr; + HAL_READ_UINT32(CAN_ECR(info), ecr); + if (ECR_GET_REC(ecr) > 96) + { + pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX; + AT91SAM7_DBG_PRINT("WARN TX\n"); + } + if (ECR_GET_TEC(ecr) > 96) + { + pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX; + AT91SAM7_DBG_PRINT("WARN RX\n"); + } + *pstat &= ~INT_WARN; + info->state = CYGNUM_CAN_STATE_BUS_WARN; + HAL_WRITE_UINT32(CAN_IER(info), INT_ERR_PASSIVE | INT_BUS_OFF); + } + + if (*pstat & INT_BUS_OFF) + { + pevent->flags |= CYGNUM_CAN_EVENT_BUS_OFF; + AT91SAM7_DBG_PRINT("BOFF\n"); + *pstat &= ~INT_BUS_OFF; + info->state = CYGNUM_CAN_STATE_BUS_OFF; + HAL_WRITE_UINT32(CAN_IER(info), INT_WAKEUP); + } + + if (*pstat & INT_SLEEP) + { + pevent->flags |= CYGNUM_CAN_EVENT_ENTERING_STANDBY; + AT91SAM7_DBG_PRINT("SLEEP\n"); + *pstat &= ~INT_SLEEP; + HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCDR, 1 << CAN_PID(info)); // disable module clock + info->state = CYGNUM_CAN_STATE_STANDBY; // set state variable + HAL_WRITE_UINT32(CAN_IER(info), INT_WAKEUP); // enable wakeup interrupt + } + + if (*pstat & (INT_CRC_ERR | INT_STUFF_ERR | INT_ACKN_ERR | INT_FORM_ERR | INT_BIT_ERR)) + { + pevent->flags |= CYGNUM_CAN_EVENT_CAN_ERR; + AT91SAM7_DBG_PRINT("CERR\n"); + *pstat &= ~(INT_CRC_ERR | INT_STUFF_ERR | INT_ACKN_ERR | INT_FORM_ERR | INT_BIT_ERR); + } + } // if (*pstat) + + return res; +} + + +//=========================================================================== +// Kick transmitter +//=========================================================================== +static void at91sam7_can_start_xmit(can_channel* chan) +{ + CAN_DECLARE_INFO(chan); + + AT91SAM7_DBG_PRINT("start_xmit\n"); + cyg_drv_dsr_lock(); + HAL_WRITE_UINT32(CAN_IER(info), 0x01 << CAN_MBOX_TX(info)); // enable tx interrupt + cyg_drv_dsr_unlock(); +} + + +//=========================================================================== +// Stop transmitter +//=========================================================================== +static void at91sam7_can_stop_xmit(can_channel* chan) +{ + CAN_DECLARE_INFO(chan); + + HAL_WRITE_UINT32(CAN_IDR(info), 0x01 << CAN_MBOX_TX(info)); // disable tx interrupt + AT91SAM7_DBG_PRINT("stop_xmit\n"); +} + + +//=========================================================================== +// Configure can channel +//=========================================================================== +static bool at91sam7_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init) +{ + CAN_DECLARE_INFO(chan); + cyg_uint32 temp32; + bool res = true; + + if (init) + { + // + // If the platform that uses the driver needs to do some platform specific + // initialisation steps, it can do it inside of this macro. I.e. some platforms + // need to setup the CAN transceiver properly here (this is necessary for the + // Atmel AT91SAM7X-EK) + // +#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1 && defined(HAL_AT91SAM7_CAN0_PLF_INIT) + HAL_AT91SAM7_CAN0_PLF_INIT(); +#else // CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1 +#if defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT) + if (info == &at91sam7_can0_info) { + HAL_AT91SAM7_CAN0_PLF_INIT(); + } +#endif // defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT) +#if defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN1) && defined(HAL_AT91SAM7_CAN1_PLF_INIT) + if (info == &at91sam7_can1_info) { + HAL_AT91SAM7_CAN1_PLF_INIT(); + } +#endif // defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT) +#endif // CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1 + + HAL_WRITE_UINT32(CAN_IDR(info), 0xFFFFFFFF); // disable all interrupts + HAL_WRITE_UINT32(CAN_MR(info), 0x00); // disable CAN module + HAL_ARM_AT91_PIO_CFG(AT91_CAN_CANRX); // Enable the CAN module to drive the CAN port pins + HAL_ARM_AT91_PIO_CFG(AT91_CAN_CANTX); + + HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_DISABLED); // first disable tx message box + HAL_WRITE_UINT32(CAN_MB_MAM(info, CAN_MBOX_TX(info)), 0x00000000); // set acceptance mask once + HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_TX); // setup as tx message box + + HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE); // enable CAN module + + // + // The device should go into error active state right after enabling it + // + HAL_READ_UINT32(CAN_SR(info), temp32); + if (!(temp32 & INT_ERR_ACTIVE)) + { + res = false; + } + } // if (init) + + res = at91sam7_can_set_baud(chan, &config->baud); // set baudrate + + // + // store new config values + // + if (config != &chan->config) + { + chan->config = *config; + } + + return res; +} + + +//=========================================================================== +// Low level interrupt handler +//=========================================================================== +static cyg_uint32 at91sam7_can_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + can_channel *chan = (can_channel *)data; + at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv; + cyg_uint32 sr; + cyg_uint32 imr; + + + HAL_READ_UINT32(CAN_IMR(info), imr); + HAL_READ_UINT32(CAN_SR(info), sr); + AT91SAM7_DBG_PRINT("CAN_ISR SR %x\n", sr); + sr &= imr; + HAL_WRITE_UINT32(CAN_IDR(info), sr); + + info->stat |= sr; + cyg_drv_interrupt_acknowledge(vector); + return CYG_ISR_CALL_DSR; +} + + +//=========================================================================== +// High level interrupt handler +//=========================================================================== +static void at91sam7_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + can_channel *chan = (can_channel *)data; + at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv; + cyg_uint32 stat = 0; + + do + { + // + // If a number of events occured then we process all events now in + // in this DSR the get_event() function clears the flags in the stat + // field + // + while (stat) + { + if (stat & (0x01 << CAN_MBOX_TX(info))) + { + AT91SAM7_DBG_PRINT("TX_DSR\n"); + chan->callbacks->xmt_msg(chan, 0); // send next message + stat &= ~INT_MB_TX; // clear flag + } + else if (stat) + { + AT91SAM7_DBG_PRINT("EVENT_DSR\n"); + chan->callbacks->rcv_event(chan, &stat); + } + } + + // + // We check, if a new event occured while we processed other events. If new events + // occured, then we process the new events + // + cyg_drv_interrupt_mask(vector); + stat = info->stat; + info->stat = 0; + cyg_drv_interrupt_unmask(vector); + } while (stat); +} + + +//=========================================================================== +// Set baudrate of certain can channel +//=========================================================================== +static bool at91sam7_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate) +{ + bool res = true; + cyg_uint32 mrbck; + cyg_uint32 canbr; + CAN_DECLARE_INFO(chan); + + +#ifdef CYGOPT_IO_CAN_AUTOBAUD + if (CYGNUM_CAN_KBAUD_AUTO == *baudrate) + { + cyg_can_baud_rate_t i; + cyg_uint8 j; + cyg_uint32 sr; + + res = false; + for (i = CYGNUM_CAN_KBAUD_10; i <= CYGNUM_CAN_KBAUD_1000; ++i) + { + HAL_AT91SAM7_GET_CAN_BR(i, canbr); + if (0 == canbr) + { + continue; + } + + HAL_READ_UINT32(CAN_SR(info), sr); + HAL_WRITE_UINT32(CAN_MR(info), 0); // disable the module + HAL_WRITE_UINT32(CAN_BR(info), canbr); // write baudrate register + HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE | MR_AUTOBAUD); // enable controller in auto aud mode + for(j = 0; j < 200; ++j) + { + HAL_DELAY_US(1000); // wait at least 11 bit times for synchronization + } + HAL_READ_UINT32(CAN_SR(info), sr); // read status register + if (!(sr & INT_ALL_ERR) && (sr & INT_WAKEUP)) + { + HAL_WRITE_UINT32(CAN_MR(info), 0); // disable the module + HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE); // enable controller + *baudrate = i; // store baudrate + return true; + } // if (!(sr & INT_ALL_ERR)) + } + } + else +#endif // CYGOPT_IO_CAN_AUTOBAUD + { + // + // Get bit timings from HAL because bit timings depend on sysclock + // For main clock of 48 MHz this macro is implemented in this device + // driver. If the macro fills the canbr value with 0 then the baudrate + // is not supported and the function returns false + // + HAL_AT91SAM7_GET_CAN_BR(*baudrate, canbr); + if (0 == canbr) + { + return false; + } + + // + // Any modificatons to the baudrate register must be done while CAN + // module is disabled. So we first disable CAN module, then we set + // baudrate and then we reenable the CAN module by setting the CAN enable + // flag + // + HAL_READ_UINT32(CAN_MR(info), mrbck); // backup value of mode register + HAL_WRITE_UINT32(CAN_MR(info), mrbck &~MR_CAN_ENABLE); // disable controller + HAL_WRITE_UINT32(CAN_BR(info), canbr); // write baudrate register + + // + // Now restore the previous state - if the module was started then + // it will no be started again, if it was stopped, then it remains stopped + // + HAL_WRITE_UINT32(CAN_MR(info), mrbck); + } + + return res; +} + + +//=========================================================================== +// Setup one single message box for reception of can message +//=========================================================================== +static void at91sam7_can_setup_mbox(can_channel *chan, cyg_uint8 mbox, cyg_uint32 mid, cyg_uint32 mam, cyg_uint32 rxtype) +{ + CAN_DECLARE_INFO(chan); + CYG_ASSERT(mbox < 7, "invalid rx mbox number"); + + + // + // To prevent concurrent access with the internal CAN core, the application + // must disable the mailbox before writing to CAN_MIDx registers - so we + // do this here + // + HAL_WRITE_UINT32(CAN_MB_MMR(info, mbox), MMR_MB_TYPE_DISABLED); // first disable message box + HAL_WRITE_UINT32(CAN_MB_MAM(info, mbox), mam); // set acceptance mask + HAL_WRITE_UINT32(CAN_MB_MID(info, mbox), mid); // set message identifier + HAL_WRITE_UINT32(CAN_MB_MMR(info, mbox), rxtype); // setup message box as rx message box (with or without overwrite) + HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), MCR_TRANSFER_CMD); // transfer request - we do not enable interrupts here +} + + +//=========================================================================== +// Configure message boxes for reception of any CAN message +//=========================================================================== +static void at91sam7_can_mbox_config_rx_all(can_channel *chan) +{ + at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv; + cyg_uint8 i; + cyg_uint8 mbox_int_mask = 0; + cyg_uint8 mbox_rx_all_cnt = CAN_MBOX_RX_ALL_CNT(info); +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + cyg_uint8 last_std_rx_mbox = CAN_MBOX_STD_CNT(info) - 1; +#endif // CYGOPT_IO_CAN_STD_CAN_ID +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + cyg_uint8 last_ext_rx_mbox = mbox_rx_all_cnt - 1; +#endif// CYGOPT_IO_CAN_EXT_CAN_ID + + // + // Now setup all rx message boxes. One message box (the last one - no 8) is + // used for transmission so we have 7 message boxes for reception of can messages + // We setup the message boxes 0 - 5 as RX mboxes and message box 6 as RX mbox with + // overwrite. + // + for (i = 0; i < mbox_rx_all_cnt; ++i) + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + if (i < CAN_MBOX_STD_CNT(info)) + { + // + // setup message boxes for standard frames + // + if (i < last_std_rx_mbox) + { + at91sam7_can_setup_mbox(chan, i, 0, MID_MIDE, MMR_MB_TYPE_RX); + } + else + { + at91sam7_can_setup_mbox(chan, i, 0, MID_MIDE, MMR_MB_TYPE_RX_OVW); + } + } + else +#endif // CYGOPT_IO_CAN_STD_CAN_ID + { +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + // + // setup message boxes for extended frames + // + if (i < last_ext_rx_mbox) + { + at91sam7_can_setup_mbox(chan, i, MID_MIDE, MID_MIDE, MMR_MB_TYPE_RX); + } + else + { + at91sam7_can_setup_mbox(chan, i, MID_MIDE, MID_MIDE, MMR_MB_TYPE_RX_OVW); + } +#endif// CYGOPT_IO_CAN_EXT_CAN_ID + } // if (i < CAN_MBOX_STD_CNT(info)) + + mbox_int_mask = (mbox_int_mask << 1) | 0x01; // enable interrupt + } // for (i = 0; i < CAN_MBOX_RX_CNT; ++i)*/ + + info->free_mboxes = CAN_MBOX_RX_CNT - mbox_rx_all_cnt; + info->rx_all = true; + HAL_WRITE_UINT32(CAN_IER(info), mbox_int_mask); // Now finally enable the interrupts for als RX mboxes +} + + +//--------------------------------------------------------------------------- +// EOF can_at91am7.c
new file mode 100644 --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/current/tests/can_test_aux.inl @@ -0,0 +1,148 @@ +//========================================================================== +// +// can_test_aux.inl +// +// CAN test auxiliary functions +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 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: Uwe Kindler +// Date: 2005-08-07 +// Description: Auxiliary functions for CAN driver tests +//####DESCRIPTIONEND#### + + +//=========================================================================== +// PRINT CAN EVENT +//=========================================================================== +void print_can_msg(cyg_can_message *pmsg, char *pMsg) +{ + char *pmsg_str; + static char* msg_tbl[] = + { + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:]\n", + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X]\n", + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X]\n", + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X]\n", + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X]\n", + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X]\n", + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X]\n", + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X %02X]\n", + "%s [ID:%03X] [RTR:%d] [EXT:%d] [DATA:%02X %02X %02X %02X %02X %02X %02X %02X]\n" + }; + + if (pmsg->rtr) + { + diag_printf("%s [ID:%03X] [RTR:%d] [EXT:%d] [DLC:%d]\n", + pMsg, + pmsg->id, + pmsg->rtr, + pmsg->ext, + pmsg->dlc); + + return; + } + + if (pmsg->dlc > 8) + { + pmsg_str = msg_tbl[8]; + } + else + { + pmsg_str = msg_tbl[pmsg->dlc]; + } + + diag_printf(pmsg_str, + pMsg, + pmsg->id, + pmsg->rtr, + pmsg->ext, + pmsg->data.bytes[0], + pmsg->data.bytes[1], + pmsg->data.bytes[2], + pmsg->data.bytes[3], + pmsg->data.bytes[4], + pmsg->data.bytes[5], + pmsg->data.bytes[6], + pmsg->data.bytes[7]); +} + + +//=========================================================================== +// PRINT CAN EVENT FLAGS +//=========================================================================== +void print_can_flags(cyg_uint16 flags, char *pMsg) +{ + char *pmsg_str; + cyg_uint8 i ; + static char* msg_tbl[] = + { + "RX ", + "TX ", + "WRX ", + "WTX ", + "ERRP ", + "BOFF ", + "OVRX ", + "OVTX ", + "CERR ", + "LSTY ", + "ESTY ", + "ALOS ", + "DEVC ", + "PHYF ", + "PHYH ", + "PHYL " + }; + i = 0; + while (flags && (i < 16)) + { + if (flags & 0x0001) + { + pmsg_str = msg_tbl[i]; + diag_printf(pmsg_str); + } + flags >>=1; + i++; + } + + diag_printf("\n"); +} + +//--------------------------------------------------------------------------- +// end of can_test_aux.inl
--- a/packages/devs/can/loop/current/ChangeLog +++ b/packages/devs/can/loop/current/ChangeLog @@ -1,3 +1,17 @@ +2007-03-23 Uwe Kindler <uwe_kindler@web.de> + + * cdl/can_loop.cdl: Driver now implements the interfaces + CYGINT_IO_CAN_TX_EVENTS, CYGINT_IO_CAN_STD_CAN_ID, + CYGINT_IO_CAN_EXT_CAN_ID. + Removed CYGPKG_IO_CAN_LOOP_CFLAGS_ADD and + CYGPKG_IO_CAN_LOOP_CFLAGS_REMOVE because they had no function. + + * src/loop_can.c: Added missing function loop_can_get_config + to make the driver build properly. + + * tests: Did some fixes and cleanups for all test cases to make them + work properly with the changes in the CAN I/O layer. + 2005-08-15 Uwe Kindler <uwe_kindler@web.de> * Loopback CAN driver created
--- a/packages/devs/can/loop/current/cdl/can_loop.cdl +++ b/packages/devs/can/loop/current/cdl/can_loop.cdl @@ -69,8 +69,11 @@ cdl_package CYGPKG_IO_CAN_LOOP { cdl_component CYGPKG_IO_CAN_LOOP_CAN[set ::loopcan] { display "LOOP CAN channel [set ::loopcan] driver" flavor bool - default_value 0 + default_value 1 implements CYGINT_IO_CAN_TIMESTAMP + implements CYGINT_IO_CAN_TX_EVENTS + implements CYGINT_IO_CAN_STD_CAN_ID + implements CYGINT_IO_CAN_EXT_CAN_ID description " This option includes the CAN loop device driver for channel [set ::loopcan]." @@ -124,28 +127,6 @@ cdl_package CYGPKG_IO_CAN_LOOP { compiler flags used only in building this package, and details of which tests are built." - - cdl_option CYGPKG_IO_CAN_LOOP_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_LOOP_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." - } cdl_option CYGPKG_IO_CAN_LOOP_TESTS { display "CAN loop device driver tests"
--- a/packages/devs/can/loop/current/src/loop_can.c +++ b/packages/devs/can/loop/current/src/loop_can.c @@ -82,6 +82,8 @@ static Cyg_ErrNo loop_can_lookup(struct static bool loop_can_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata); static Cyg_ErrNo loop_can_set_config(can_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len); +static Cyg_ErrNo loop_can_get_config(can_channel *chan, cyg_uint32 key, + const void* buf, cyg_uint32* len); static void loop_can_start_xmit(can_channel *chan); static void loop_can_stop_xmit(can_channel *chan); @@ -129,6 +131,7 @@ typedef struct loop_can_info { CAN_LOWLEVEL_FUNS(loop_can_lowlevel_funs, loop_can_putmsg, loop_can_getevent, + loop_can_get_config, loop_can_set_config, loop_can_start_xmit, loop_can_stop_xmit @@ -266,7 +269,9 @@ loop_can_putmsg(can_channel *chan, cyg_c loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv; struct fifo *fwr = loop_chan->write_fifo; +#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT struct fifo *frd = loop_chan->read_fifo; +#endif if( fwr->num == FIFO_SIZE ) { @@ -333,6 +338,16 @@ loop_can_set_config(can_channel *chan, c return ENOERR; } +//------------------------------------------------------------------------- +// Query device configuration + +static Cyg_ErrNo +loop_can_get_config(can_channel *chan, cyg_uint32 key, + const void* buf, cyg_uint32* len) +{ + return ENOERR; +} + //------------------------------------------------------------------------- // Enable the transmitter on the device
--- a/packages/devs/can/loop/current/tests/can_nonblock.c +++ b/packages/devs/can/loop/current/tests/can_nonblock.c @@ -70,7 +70,7 @@ #include <cyg/kernel/kapi.h> // Package option requirements -#if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING) && !defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS) +#if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING) //=========================================================================== // DATA TYPES @@ -107,6 +107,7 @@ void can0_thread(cyg_addrword_t data) cyg_uint32 len; cyg_uint32 blocking; cyg_can_event rx_event; + Cyg_ErrNo res; blocking = 0; len = sizeof(blocking); @@ -115,12 +116,17 @@ void can0_thread(cyg_addrword_t data) CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } - len = sizeof(rx_event); + len = sizeof(rx_event); + res = cyg_io_read(hDrvFlexCAN, &rx_event, &len); - if (-EAGAIN == cyg_io_read(hDrvFlexCAN, &rx_event, &len)) + if (-EAGAIN == res) { CYG_TEST_PASS_FINISH("can_test1 test OK"); } + else if (-EINTR == res) + { + CYG_TEST_PASS_FINISH("can_test1 test OK"); + } else { CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); @@ -155,9 +161,7 @@ cyg_start(void) } // - // create the two threads which access the CAN device driver - // a reader thread with a higher priority and a writer thread - // with a lower priority + // create the main thread // cyg_thread_create(4, can0_thread, (cyg_addrword_t) 0, @@ -172,8 +176,8 @@ cyg_start(void) cyg_scheduler_start(); } -#else // #if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING) && !defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS -#define N_A_MSG "Needs nonblocking calls and disabled timeouts" +#else // #if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING) +#define N_A_MSG "Needs nonblocking calls" #endif #else // CYGFUN_KERNEL_API_C
--- a/packages/devs/can/loop/current/tests/can_overrun1.c +++ b/packages/devs/can/loop/current/tests/can_overrun1.c @@ -110,7 +110,10 @@ void can0_thread(cyg_addrword_t data) cyg_can_message tx_msg = { 0x000, // CAN identifier - {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes + data : + { + {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }// 8 data bytes + }, CYGNUM_CAN_ID_STD, // standard frame CYGNUM_CAN_FRAME_DATA, // data frame 0, // data length code @@ -140,8 +143,8 @@ void can0_thread(cyg_addrword_t data) diag_printf("Sending %d CAN messages to /dev/can0\n", buf_info.rx_bufsize + 1); for (i = 0; i <= buf_info.rx_bufsize; ++i) { - tx_msg.id = 0x000 + i; - tx_msg.data[0] = i; + CYG_CAN_MSG_SET_STD_ID(tx_msg, 0x000 + i); + CYG_CAN_MSG_SET_DATA(tx_msg, 0, i); len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) @@ -190,7 +193,7 @@ void can0_thread(cyg_addrword_t data) if (rx_event.flags & CYGNUM_CAN_EVENT_TX) { print_can_msg(&rx_event.msg, ""); - if (rx_event.msg.data[0] != (i + 1)) + if (rx_event.msg.data.bytes[0] != (i + 1)) { CYG_TEST_FAIL_FINISH("Received /dev/can0 TX event contains invalid data"); }
--- a/packages/devs/can/loop/current/tests/can_overrun2.c +++ b/packages/devs/can/loop/current/tests/can_overrun2.c @@ -111,7 +111,10 @@ void can0_thread(cyg_addrword_t data) cyg_can_message tx_msg = { 0x000, // CAN identifier - {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes + data : + { + {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }// 8 data bytes + }, CYGNUM_CAN_ID_STD, // standard frame CYGNUM_CAN_FRAME_DATA, // data frame 2, // data length code @@ -148,7 +151,7 @@ void can0_thread(cyg_addrword_t data) CYG_TEST_FAIL_FINISH("Unexpected RX event for /dev/can0"); } - rx_bufsize = *((cyg_uint32 *)rx_event.msg.data); + rx_bufsize = *((cyg_uint32 *)rx_event.msg.data.bytes); // // now we send exactly one CAN message more than there is space in the receive buffer @@ -161,8 +164,8 @@ void can0_thread(cyg_addrword_t data) // we store the message number as CAN id and in first data byte so // a receiver can check this later // - tx_msg.id = 0x000 + i; - tx_msg.data[0] = i; + CYG_CAN_MSG_SET_STD_ID(tx_msg, 0x000 + i); + CYG_CAN_MSG_SET_DATA(tx_msg, 0, i); len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) @@ -216,7 +219,7 @@ void can1_thread(cyg_addrword_t data) // endianess here because this is a loopback driver test and we will receive // our own messages // - *((cyg_uint32 *)tx_msg.data) = rx_buf_info.rx_bufsize; + *((cyg_uint32 *)tx_msg.data.bytes) = rx_buf_info.rx_bufsize; len = sizeof(tx_msg); // @@ -261,7 +264,7 @@ void can1_thread(cyg_addrword_t data) if (rx_event.flags & CYGNUM_CAN_EVENT_RX) { print_can_msg(&rx_event.msg, ""); - if (rx_event.msg.data[0] != (i + 1)) + if (rx_event.msg.data.bytes[0] != (i + 1)) { CYG_TEST_FAIL_FINISH("Received /dev/can1 RX event contains invalid data"); }
--- a/packages/devs/can/loop/current/tests/can_rdwr.c +++ b/packages/devs/can/loop/current/tests/can_rdwr.c @@ -90,6 +90,8 @@ thread_data_t can0_thread_data; cyg_thread_entry_t can1_thread; thread_data_t can1_thread_data; +cyg_sem_t sem_wait; + //=========================================================================== // LOCAL FUNCTIONS @@ -108,11 +110,14 @@ void can0_thread(cyg_addrword_t data) cyg_can_buf_info_t tx_buf_info; cyg_can_message tx_msg = { - 0x000, // CAN identifier - {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes - CYGNUM_CAN_ID_STD, // standard frame - CYGNUM_CAN_FRAME_DATA, // data frame - 8, // data length code + 0x000, // CAN identifier + data : + { + {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes + }, + CYGNUM_CAN_ID_STD, // standard frame + CYGNUM_CAN_FRAME_DATA, // data frame + 8, // data length code }; if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) @@ -143,8 +148,8 @@ void can0_thread(cyg_addrword_t data) // we store the message number as CAN id and in first data byte so // a receiver can check this later // - tx_msg.id = 0x000 + i; - tx_msg.data[0] = i; + CYG_CAN_MSG_SET_STD_ID(tx_msg, 0x000 + i); + CYG_CAN_MSG_SET_DATA(tx_msg, 0, i); len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) @@ -155,15 +160,21 @@ void can0_thread(cyg_addrword_t data) { print_can_msg(&tx_msg, ""); } - } + } // for (i = 0; i < 10; ++i) // - // Now we we give the reader thread a chance to run and to read - // the messages + // Give reader thread 200 ticks time for readung all messages. The reader thread + // signals the semaphore if it received all transmitted messages // - cyg_thread_delay(100); - CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); - } + if (!cyg_semaphore_timed_wait( &sem_wait, cyg_current_time( ) + 200 )) + { + CYG_TEST_FAIL_FINISH("Waiting for reader thread timed out."); + } + else + { + CYG_TEST_PASS_FINISH("can_rdwr test OK"); + } + } // while (1) } @@ -223,7 +234,7 @@ void can1_thread(cyg_addrword_t data) // The writer thread stored the message number in CAN id and first // data byte so we can check now if we received valid data // - if ((rx_event.msg.id != i) || (rx_event.msg.data[0] != i)) + if ((rx_event.msg.id != i) || (rx_event.msg.data.bytes[0] != i)) { CYG_TEST_FAIL_FINISH("Received CAN message contains unexpected data"); } @@ -233,7 +244,10 @@ void can1_thread(cyg_addrword_t data) } } //for (i = 0; i < 10; ++i) - CYG_TEST_PASS_FINISH("can_rdwr test OK"); + // + // signal successfull reception of all messages + // + cyg_semaphore_post(&sem_wait); } // while (1) } @@ -245,6 +259,11 @@ cyg_start(void) CYG_TEST_INIT(); // + // Initialize the wait semaphore to 0 + // + cyg_semaphore_init( &sem_wait, 0 ); + + // // create the two threads which access the CAN device driver // cyg_thread_create(4, can0_thread,
--- a/packages/devs/can/loop/current/tests/can_test_aux.inl +++ b/packages/devs/can/loop/current/tests/can_test_aux.inl @@ -68,11 +68,12 @@ void print_can_msg(cyg_can_message *pmsg if (pmsg->rtr) { - diag_printf("%s [ID:%03X] [RTR:%d] [EXT:%d]\n", + diag_printf("%s [ID:%03X] [RTR:%d] [EXT:%d] [DLC:%d]\n", pMsg, pmsg->id, pmsg->rtr, - pmsg->ext); + pmsg->ext, + pmsg->dlc); return; } @@ -91,14 +92,14 @@ void print_can_msg(cyg_can_message *pmsg pmsg->id, pmsg->rtr, pmsg->ext, - pmsg->data[0], - pmsg->data[1], - pmsg->data[2], - pmsg->data[3], - pmsg->data[4], - pmsg->data[5], - pmsg->data[6], - pmsg->data[7]); + pmsg->data.bytes[0], + pmsg->data.bytes[1], + pmsg->data.bytes[2], + pmsg->data.bytes[3], + pmsg->data.bytes[4], + pmsg->data.bytes[5], + pmsg->data.bytes[6], + pmsg->data.bytes[7]); } @@ -124,7 +125,7 @@ void print_can_flags(cyg_uint16 flags, c "ESTY ", "ALOS ", "DEVC ", - "PHY ", + "PHYF ", "PHYH ", "PHYL " };
--- a/packages/devs/can/loop/current/tests/can_timeout.c +++ b/packages/devs/can/loop/current/tests/can_timeout.c @@ -113,6 +113,7 @@ void check_timeout(cyg_io_handle_t hCAN, timeout_info.tx_timeout = timeout; timeout_info.rx_timeout = timeout; + len = sizeof(timeout_info); if (ENOERR != cyg_io_set_config(hCAN, CYG_IO_SET_CONFIG_CAN_TIMEOUT ,&timeout_info, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
--- a/packages/devs/can/loop/current/tests/can_txevent.c +++ b/packages/devs/can/loop/current/tests/can_txevent.c @@ -110,7 +110,10 @@ void can0_thread(cyg_addrword_t data) cyg_can_message tx_msg = { 0x000, // CAN identifier - {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes + data : + { + {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }// 8 data bytes + }, CYGNUM_CAN_ID_STD, // standard frame CYGNUM_CAN_FRAME_DATA, // data frame 4, // data length code @@ -146,8 +149,8 @@ void can0_thread(cyg_addrword_t data) diag_printf("Sending %d CAN messages to /dev/can0 \n", buf_info.rx_bufsize); for (i = 0; i < buf_info.rx_bufsize; ++i) { - tx_msg.id = i; - tx_msg.data[0] = i; + CYG_CAN_MSG_SET_STD_ID(tx_msg, 0x000 + i); + CYG_CAN_MSG_SET_DATA(tx_msg, 0, i); len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) @@ -204,7 +207,7 @@ void can0_thread(cyg_addrword_t data) // Now check if TX events contain valid data - we know that the ID and the first // data byte contain the message number // - if ((rx_event.msg.id != i) || (rx_event.msg.data[0] != i)) + if ((rx_event.msg.id != i) || (rx_event.msg.data.bytes[0] != i)) { CYG_TEST_FAIL_FINISH("Received invalid data in TX event"); }
--- a/packages/devs/can/m68k/mcf52xx/current/ChangeLog +++ b/packages/devs/can/m68k/mcf52xx/current/ChangeLog @@ -1,33 +1,67 @@ -2006-02-15 Uwe Kindler <uwe_kindler@web.de> - - * cdl/can_mcf52xx.cdl Added two interfaces - CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID and - CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID. - The number of standard and extended message boxes is now - configurable: - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES - Channged default TX buffer to 15. - - * src/can_mcf52xx.c Added initialisation macro for second - FlexCAN modul. Driver partly rewritten - support of up to - 15 message buffers when reception of all CAN frames is - configured - improves performance when "bursts" of CAN - messages arrive. Changed message buffer configuration - - only the config key CYG_IO_SET_CONFIG_CAN_MSGBUF is - supported now. The exact configuration option is defined - in new data field cyg_can_msgbuf_cfg_id in cyg_can_msgbuf_cfg - structure. - - * tests/flexcan_filter.c - * tests/flexcan_wake.c - * tests/flexcan_remote.c - * tests/flexcan_load.c - Changed message buffer configuration to support of new - config key CYG_IO_SET_CONFIG_CAN_MSGBUF. Removed baudrate - runtime configuration of 250 kBaud - now default - value is used. - +2007-03-23 Uwe Kindler <uwe_kindler@web.de> + + * cdl/can_mcf52xx.cdl Removed interfaces + CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID and + CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID. The generic + CAN I/O layer provides some similar interfaces now. + Driver now implements the new CAN I/O interfaces + CYGINT_IO_CAN_TIMESTAMP, CYGINT_IO_CAN_RUNTIME_MBOX_CFG + CYGINT_IO_CAN_REMOTE_BUF and CYGINT_IO_CAN_TX_EVENTS, + CYGINT_IO_CAN_STD_CAN_ID, CYGINT_IO_CAN_EXT_CAN_ID + Removed make commands for removed test cases. + Removed cdl component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN_OPTIONS + because it did not have any functionality. + + * src/can_mcf52xx.c Replaced + CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID with + generic CAN I/O option CYGOPT_IO_CAN_EXT_CAN_ID and + CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID with + generic CAN I/O option CYGOPT_IO_CAN_STD_CAN_ID + Implemented CAN mode CYGNUM_CAN_MODE_CONFIG. + Changed old access to CAN data (byte array) to access + to new cyg_can_msg_data type. + + * tests/flexcan_filter: removed. This tast case is now part of + generic CAN I/O layer. + + * tests/flexcan_load: removed. This tast case is now part of + generic CAN I/O layer. + + * tests/flexcan_remote: removed. This tast case is now part of + generic CAN I/O layer. + + * tets/flexcan_wake: Did some code cleaning. + +2006-02-15 Uwe Kindler <uwe_kindler@web.de> + + * cdl/can_mcf52xx.cdl Added two interfaces + CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID and + CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID. + The number of standard and extended message boxes is now + configurable: + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES + Channged default TX buffer to 15. + + * src/can_mcf52xx.c Added initialisation macro for second + FlexCAN modul. Driver partly rewritten - support of up to + 15 message buffers when reception of all CAN frames is + configured - improves performance when "bursts" of CAN + messages arrive. Changed message buffer configuration - + only the config key CYG_IO_SET_CONFIG_CAN_MSGBUF is + supported now. The exact configuration option is defined + in new data field cyg_can_msgbuf_cfg_id in cyg_can_msgbuf_cfg + structure. + + * tests/flexcan_filter.c + * tests/flexcan_wake.c + * tests/flexcan_remote.c + * tests/flexcan_load.c + Changed message buffer configuration to support of new + config key CYG_IO_SET_CONFIG_CAN_MSGBUF. Removed baudrate + runtime configuration of 250 kBaud - now default + value is used. + 2005-09-20 Uwe Kindler <uwe_kindler@web.de> * src/can_mcf52xx.c Only support events of tx message buffers
--- a/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl +++ b/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl @@ -64,22 +64,7 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX puts $::cdl_system_header "/***** CAN driver proc output end *****/" } - cdl_interface CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID { - display "11 Bit standard ID support" - flavor bool - description " - This interface is implemented if support for CAN - messages with 11 Bit standard CAN ID is required." - } - - cdl_interface CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID { - display "29 Bit extended ID support" - flavor bool - description " - This interface is implemented if support for CAN - messages with 29 Bit standard CAN ID is required." - } - + # Support up to two on-chip FlexCAN modules. The number varies between # processor variants for { set ::flexcan 0 } { $::flexcan < 2 } { incr ::flexcan } { @@ -98,7 +83,10 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX flavor bool active_if CYGINT_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan] default_value 1 - implements CYGINT_IO_CAN_TIMESTAMP + implements CYGINT_IO_CAN_TIMESTAMP + implements CYGINT_IO_CAN_RUNTIME_MBOX_CFG + implements CYGINT_IO_CAN_REMOTE_BUF + implements CYGINT_IO_CAN_TX_EVENTS description " If the application needs to access the on-chip FlexCAN[set ::flexcan] @@ -126,8 +114,8 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX 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 64 - legal_values 16 to 1024 + default_value 64 + legal_values 16 to 1024 description " The CAN device driver will run in interrupt mode and will perform buffering of outgoing data. This option controls the number @@ -137,8 +125,8 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX 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 128 - legal_values 16 to 1024 + default_value 128 + legal_values 16 to 1024 description " The CAN device driver will run in interrupt mode and will perform buffering of incoming data. This option controls the number @@ -178,53 +166,54 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX Interrupt priority for bus off interrupt." } - cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_TX_MBOX { - display "Default TX buffer" + cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_TX_MBOX { + display "Default TX buffer" flavor data calculated 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." + 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]_STD_MBOXES { - display "11 Bit standard ID msg. buffers" - flavor booldata - implements CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID - default_value 15 - legal_values 0 to 15 + cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES { + display "11 Bit standard ID msg. buffers" + flavor booldata + requires CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES < 16 + implements CYGINT_IO_CAN_STD_CAN_ID + default_value 7 + legal_values 1 to 15 description " - The FlexCAN module contains 16 message buffers. One message buffer - is reserved for message transmission. The remaining 15 buffers are - available for reception of messages. This configuration option - defines the number of message boxes for reception of CAN messages - with standard identifier. This configuration option does not matter - when you configure message filters at runtime. Only if the FlexCAN - modul is configured to receive all available standard CAN identifiers - (0 - 0x7FF), then this configuration option is important. If you get - RX overrun events, you should raise the number of message boxes or - lower the CAN baud rate." - } - - cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES { - display "29 Bit extended ID msg. buffers" - flavor booldata - requires ((CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES) <= 15) - implements CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID - default_value 0 - legal_values 0 to 15 + The FlexCAN module contains 16 message buffers. One message buffer + is reserved for message transmission. The remaining 15 buffers are + available for reception of messages. This configuration option + defines the number of message boxes for reception of CAN messages + with standard identifier. This configuration option does not matter + when you configure message filters at runtime. Only if the FlexCAN + modul is configured to receive all available standard CAN identifiers + (0 - 0x7FF), then this configuration option is important. If you get + RX overrun events, you should raise the number of message boxes or + lower the CAN baud rate." + } + + cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES { + display "29 Bit extended ID msg. buffers" + flavor booldata + requires CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES < 16 + implements CYGINT_IO_CAN_EXT_CAN_ID + default_value 8 + legal_values 1 to 15 description " - The FlexCAN module contain 16 message buffers. One message buffer - is reserved for message transmission. The remaining 15 buffers are - available for reception of messages. This configuration option - defines the number of message boxes for reception of CAN messages - with extended identifier. This configuration option does not matter - when you configure message filters at runtime. Only if the FlexCAN - modul is configured to receive all available standard CAN identifiers - (0 - 0x7FF), then this configuration option is important. If you get - RX overrun events, you should raise the number of message boxes or - lower the CAN baud rate." + The FlexCAN module contain 16 message buffers. One message buffer + is reserved for message transmission. The remaining 15 buffers are + available for reception of messages. This configuration option + defines the number of message boxes for reception of CAN messages + with extended identifier. This configuration option does not matter + when you configure message filters at runtime. Only if the FlexCAN + modul is configured to receive all available standard CAN identifiers + (0 - 0x7FF), then this configuration option is important. If you get + RX overrun events, you should raise the number of message boxes or + lower the CAN baud rate." } cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOXCFG { @@ -268,31 +257,7 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX testing infrastructure. All tests require a properly configured CAN network with a second CAN node that can send and receive CAN messages." - - make -priority 320 { - <PREFIX>/bin/flexcan_load : <PACKAGE>/tests/flexcan_load.c - @sh -c "mkdir -p tests $(dir $@)" - $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/flexcan_load.o $< - @echo $@ ": \\" > $(notdir $@).deps - @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps - @tail -n +2 deps.tmp >> $(notdir $@).deps - @echo >> $(notdir $@).deps - @rm deps.tmp - $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ tests/flexcan_load.o - } - - make -priority 320 { - <PREFIX>/bin/flexcan_remote : <PACKAGE>/tests/flexcan_remote.c - @sh -c "mkdir -p tests $(dir $@)" - $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/flexcan_remote.o $< - @echo $@ ": \\" > $(notdir $@).deps - @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps - @tail -n +2 deps.tmp >> $(notdir $@).deps - @echo >> $(notdir $@).deps - @rm deps.tmp - $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ tests/flexcan_remote.o - } - + make -priority 320 { <PREFIX>/bin/flexcan_wake : <PACKAGE>/tests/flexcan_wake.c @sh -c "mkdir -p tests $(dir $@)" @@ -304,50 +269,5 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX @rm deps.tmp $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ tests/flexcan_wake.o } - - make -priority 320 { - <PREFIX>/bin/flexcan_filter : <PACKAGE>/tests/flexcan_filter.c - @sh -c "mkdir -p tests $(dir $@)" - $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/flexcan_filter.o $< - @echo $@ ": \\" > $(notdir $@).deps - @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps - @tail -n +2 deps.tmp >> $(notdir $@).deps - @echo >> $(notdir $@).deps - @rm deps.tmp - $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ tests/flexcan_filter.o - } - } - - - - cdl_component CYGPKG_DEVS_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_DEVS_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_DEVS_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." - } } }
--- a/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c +++ b/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c @@ -163,12 +163,12 @@ #define FLEXCAN_BUSOFF_EVENT 17 #define FLEXCAN_WAKE_EVENT 18 -// -// Acceptance mask -// -#define FLEXCAN_ACCEPTANCE_MASK_RX_ALL 0x00 // receive all messages - mbox ID does not matter -#define FLEXCAN_ACCEPTANCE_MASK_RX_ID 0x1FFFFFFF // receive only messages where ID exactly matches mbox ID - +// +// Acceptance mask +// +#define FLEXCAN_ACCEPTANCE_MASK_RX_ALL 0x00 // receive all messages - mbox ID does not matter +#define FLEXCAN_ACCEPTANCE_MASK_RX_ID 0x1FFFFFFF // receive only messages where ID exactly matches mbox ID + //--------------------------------------------------------------------------- // message buffer cfg bits @@ -199,18 +199,18 @@ //--------------------------------------------------------------------------- -// flexcan message buffer configuration +// flexcan message buffer configuration // -#define FLEXCAN_MBOX_MIN 0 +#define FLEXCAN_MBOX_MIN 0 #define FLEXCAN_MBOX_MAX 15 -#define FLEXCAN_MBOX_CNT 16 -#define FLEXCAN_MBOX_TX CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX -#define FLEXCAN_MBOX_RX_MIN 0 -#define FLEXCAN_MBOX_RX_MAX (FLEXCAN_MBOX_MAX - 1) // one msg box is tx -#define FLEXCAN_MBOX_RX_CNT (FLEXCAN_MBOX_CNT - 1) // one msg box is tx - - -#define FLEXCAN_CTRLSTAT_NOT_READ 0 // indicates that control status register is not read +#define FLEXCAN_MBOX_CNT 16 +#define FLEXCAN_MBOX_TX CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX +#define FLEXCAN_MBOX_RX_MIN 0 +#define FLEXCAN_MBOX_RX_MAX (FLEXCAN_MBOX_MAX - 1) // one msg box is tx +#define FLEXCAN_MBOX_RX_CNT (FLEXCAN_MBOX_CNT - 1) // one msg box is tx + + +#define FLEXCAN_CTRLSTAT_NOT_READ 0 // indicates that control status register is not read //=========================================================================== @@ -225,9 +225,9 @@ typedef enum MBOX_STATE_DISABLED, // message box unused (free) MBOX_STATE_TX, // TX message box MBOX_STATE_REMOTE_TX, // remote TX msaage box (data will be sent on reception of rtr frame) - MBOX_STATE_RX_ALL_STD, // RX message box for standard IDs - MBOX_STATE_RX_ALL_EXT, // RX message box for standard IDs - MBOX_STATE_RX_FILT // RX message box for filter mboxes + MBOX_STATE_RX_ALL_STD, // RX message box for standard IDs + MBOX_STATE_RX_ALL_EXT, // RX message box for standard IDs + MBOX_STATE_RX_FILT // RX message box for filter mboxes } flexcan_mbox_state; @@ -241,25 +241,25 @@ typedef struct flexcan_mbox_info_st cyg_interrupt interrupt; // stores interrupt data cyg_handle_t interrupt_handle; // stores interrupt number cyg_uint8 num; // number of message buffer - bool busy; // if true, then transmission or reception is in progress + bool busy; // if true, then transmission or reception is in progress flexcan_mbox_state state; // message box state - cyg_uint8 ctrlstat_shadow; // shadow register of message box ctrlstat register + cyg_uint8 ctrlstat_shadow; // shadow register of message box ctrlstat register } flexcan_mbox_info; // -// Between ISR and DSR handling there is some kind of circular buffer. -// A DSR is only invoked if no other message box invoked a DSR before -// the DSR will read all available message buffers. This structure -// is for exchange of information between ISR and DSR -// -typedef struct st_rxmbox_circbuf -{ - cyg_uint8 idx_rd; // the message box the DSR will read from - cyg_uint8 idx_wr; // the message box that will receive the next message - cyg_uint8 count; // the number of received message before DSR starts (number of ISR nesting) -} flexcan_rxmbox_circbuf; - -// +// Between ISR and DSR handling there is some kind of circular buffer. +// A DSR is only invoked if no other message box invoked a DSR before +// the DSR will read all available message buffers. This structure +// is for exchange of information between ISR and DSR +// +typedef struct st_rxmbox_circbuf +{ + cyg_uint8 idx_rd; // the message box the DSR will read from + cyg_uint8 idx_wr; // the message box that will receive the next message + cyg_uint8 count; // the number of received message before DSR starts (number of ISR nesting) +} flexcan_rxmbox_circbuf; + +// // flexcan interrupt (busoff, err, wake) data - stores interrupt data for // a non message box interrupt (bus off, err or wake interrupt) // @@ -278,7 +278,7 @@ typedef struct flexcan_int_st isr_vec : (_mbox0_vec) + (_mbox_no), \ isr_priority : (_prio), \ num : (_mbox_no), \ - busy : false \ + busy : false \ } // @@ -297,7 +297,7 @@ 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 mboxes[FLEXCAN_MBOX_CNT];// message boxes + flexcan_mbox_info mboxes[FLEXCAN_MBOX_CNT];// message boxes cyg_uint32 last_tx_id; // last transmitted message identifier flexcan_int boff_int; // bus off interrupt data @@ -308,14 +308,14 @@ typedef struct flexcan_info cyg_uint8 free_mboxes; // number of free message boxes for msg filters and rtr buffers cyg_can_state state; // state of CAN controller - flexcan_rxmbox_circbuf rxmbox_std_circbuf; - flexcan_rxmbox_circbuf rxmbox_ext_circbuf; - - cyg_uint8 mboxes_std_cnt; // contains number of standard message boxes available - cyg_uint8 mboxes_ext_cnt; // number of message boxes with ext id - cyg_uint8 mboxes_rx_all_cnt;// number of all available mboxes - - bool rx_all; // true if reception of call can messages is active + flexcan_rxmbox_circbuf rxmbox_std_circbuf; + flexcan_rxmbox_circbuf rxmbox_ext_circbuf; + + cyg_uint8 mboxes_std_cnt; // contains number of standard message boxes available + cyg_uint8 mboxes_ext_cnt; // number of message boxes with ext id + cyg_uint8 mboxes_rx_all_cnt;// number of all available mboxes + + bool rx_all; // true if reception of call can messages is active cyg_uint16 imask_shadow; // interrupt mask shadow register #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT cyg_can_message last_tx_msg; // stores last transmitted message for TX events @@ -356,8 +356,8 @@ typedef struct flexcan_info _boff_isr_vec, _boff_isr_prio, \ _err_isr_vec, _err_isr_prio, \ _wake_isr_vec, _wake_isr_prio, \ - _tx_all_mbox, \ - _std_mboxes, _ext_mboxes) \ + _tx_all_mbox, \ + _std_mboxes, _ext_mboxes) \ flexcan_info _l = { \ (void *)( _baseaddr), \ (_isr_vec_mbox0), \ @@ -384,12 +384,12 @@ flexcan_info _l = { err_int : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio), \ wake_int : FLEXCAN_INT_INIT(_wake_isr_vec, _wake_isr_prio), \ tx_all_mbox : _tx_all_mbox, \ - free_mboxes : ((_std_mboxes) + (_ext_mboxes)), \ - state : CYGNUM_CAN_STATE_ACTIVE, \ - rx_all : true, \ - mboxes_std_cnt : _std_mboxes, \ - mboxes_ext_cnt : _ext_mboxes, \ - mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes)) \ + free_mboxes : ((_std_mboxes) + (_ext_mboxes)), \ + state : CYGNUM_CAN_STATE_ACTIVE, \ + rx_all : true, \ + mboxes_std_cnt : _std_mboxes, \ + mboxes_ext_cnt : _ext_mboxes, \ + mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes)) \ }; @@ -402,26 +402,26 @@ flexcan_info _l = { #define _FLEXCAN_MBOX_INTPRIO(n) CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX##n #define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n) -// -// Define number of message boxes if they are not defined yet -// -#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES -#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES 0 -#endif -#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES -#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES 0 -#endif -#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES -#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES 0 -#endif -#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES -#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES 0 -#endif - +// +// Define number of message boxes if they are not defined yet +// +#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES +#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES 0 +#endif +#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES +#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES 0 +#endif +#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES +#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES 0 +#endif +#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES +#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES 0 +#endif -#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0 + +#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0 // -// FlexCAN channel initialisation for FlexCAN channel 0 +// FlexCAN channel initialisation for FlexCAN channel 0 // FLEXCAN_INFO(flexcan_can0_info, HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE, @@ -449,43 +449,43 @@ FLEXCAN_INFO(flexcan_can0_info, HAL_MCF52xx_FLEXCAN0_WAKE_ISRVEC, CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_WAKEINT, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES); -#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan] - -#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1 -// -// FlexCAN channel initialisation for FlexCAN channel 1 -// -FLEXCAN_INFO(flexcan_can0_info, - HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE, - HAL_MCF52xx_FLEXCAN1_MBOX0_ISRVEC, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX0, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX1, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX2, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX3, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX4, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX5, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX6, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX7, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX8, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX9, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX10, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX11, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX12, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX13, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX14, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX15, - HAL_MCF52xx_FLEXCAN1_BOFF_ISRVEC, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_BOFFINT, - HAL_MCF52xx_FLEXCAN1_ERR_ISRVEC, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_ERRINT, - HAL_MCF52xx_FLEXCAN1_WAKE_ISRVEC, - CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_WAKEINT, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_DEFAULT_TX_MBOX, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES); -#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1 + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES, + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES); +#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan] + +#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1 +// +// FlexCAN channel initialisation for FlexCAN channel 1 +// +FLEXCAN_INFO(flexcan_can0_info, + HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE, + HAL_MCF52xx_FLEXCAN1_MBOX0_ISRVEC, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX0, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX1, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX2, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX3, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX4, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX5, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX6, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX7, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX8, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX9, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX10, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX11, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX12, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX13, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX14, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX15, + HAL_MCF52xx_FLEXCAN1_BOFF_ISRVEC, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_BOFFINT, + HAL_MCF52xx_FLEXCAN1_ERR_ISRVEC, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_ERRINT, + HAL_MCF52xx_FLEXCAN1_WAKE_ISRVEC, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_WAKEINT, + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_DEFAULT_TX_MBOX, + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES, + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES); +#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1 // // message box structure for hardware access of message box @@ -562,18 +562,18 @@ static void flexcan_stop_xmit(can // // TX and RX ISRs and DSRs // -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID -static cyg_uint32 flexcan_mbox_rx_std_isr(cyg_vector_t, cyg_addrword_t); -static void flexcan_mbox_rx_std_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); -#endif // #ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID -static cyg_uint32 flexcan_mbox_rx_ext_isr(cyg_vector_t, cyg_addrword_t); -static void flexcan_mbox_rx_ext_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); -#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_EXT_ID -static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t, cyg_addrword_t); +#ifdef CYGOPT_IO_CAN_STD_CAN_ID +static cyg_uint32 flexcan_mbox_rx_std_isr(cyg_vector_t, cyg_addrword_t); +static void flexcan_mbox_rx_std_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); +#endif // CYGOPT_IO_CAN_STD_CAN_ID +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID +static cyg_uint32 flexcan_mbox_rx_ext_isr(cyg_vector_t, cyg_addrword_t); +static void flexcan_mbox_rx_ext_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); +#endif // CYGOPT_IO_CAN_EXT_CAN_ID +static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t, 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); -static void flexcan_mbox_rx_filt_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t ); +static void flexcan_mbox_rx_filt_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t ); // // All other flexcan interrupt handlers @@ -585,11 +585,11 @@ static void flexcan_busoff_dsr(cy static cyg_uint32 flexcan_wake_isr(cyg_vector_t, cyg_addrword_t); static void flexcan_wake_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); -// -// Flexcan utility functions -// +// +// Flexcan utility functions +// static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox, cyg_can_message *pmsg, bool rtr); -static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_can_message *pmsg, bool enable); +static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_can_message *pmsg, bool enable); 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_can_id_type ext); static void flexcan_start_chip(can_channel *chan); @@ -600,13 +600,13 @@ static bool flexcan_set_baud(can_channel static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init); static cyg_int8 flexcan_alloc_mbox(flexcan_info *info); static void flexcan_disable_mbox(can_channel *chan, cyg_uint32 mbox_id); -static void flexcan_setup_rxmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_ISR_t *isr, cyg_can_message *pmsg, bool enable, bool int_enable); +static void flexcan_setup_rxmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_ISR_t *isr, cyg_can_message *pmsg, bool enable, bool int_enable); static void flexcan_setup_txmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg); static void flexcan_setup_rtrmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg); static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id); static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id); -static void flexcan_config_rx_all(can_channel *chan); -static void flexcan_enable_rxmbox(can_channel *chan, cyg_uint32 mbox_id); +static void flexcan_config_rx_all(can_channel *chan); +static void flexcan_enable_rxmbox(can_channel *chan, cyg_uint32 mbox_id); CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs, @@ -656,33 +656,33 @@ flexcan_lookup(struct cyg_devtab_entry** //=========================================================================== -// Enable hardware message box for reception -//=========================================================================== -static __inline__ void flexcan_hwmbox_enable_rx(flexcan_regs *flexcan, cyg_uint32 mbox_id) -{ - HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_EMPTY); -} - - -//=========================================================================== -// Disable hardware message box -//=========================================================================== -static __inline__ void flexcan_hwmbox_disable(flexcan_regs *flexcan, cyg_uint32 mbox_id) -{ - HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_NOT_ACTIVE); -} - - -//=========================================================================== -// lock mbox by reading control status register -//=========================================================================== -static __inline__ void flexcan_hwmbox_lock(flexcan_regs *flexcan, cyg_uint32 mbox_id, cyg_uint8 *pctrlstat) -{ - HAL_READ_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), *pctrlstat); // this read will lock the mbox -} - - -//=========================================================================== +// Enable hardware message box for reception +//=========================================================================== +static __inline__ void flexcan_hwmbox_enable_rx(flexcan_regs *flexcan, cyg_uint32 mbox_id) +{ + HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_EMPTY); +} + + +//=========================================================================== +// Disable hardware message box +//=========================================================================== +static __inline__ void flexcan_hwmbox_disable(flexcan_regs *flexcan, cyg_uint32 mbox_id) +{ + HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_NOT_ACTIVE); +} + + +//=========================================================================== +// lock mbox by reading control status register +//=========================================================================== +static __inline__ void flexcan_hwmbox_lock(flexcan_regs *flexcan, cyg_uint32 mbox_id, cyg_uint8 *pctrlstat) +{ + HAL_READ_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), *pctrlstat); // this read will lock the mbox +} + + +//=========================================================================== // Enable message box interrupt for one message box //=========================================================================== static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id) @@ -705,7 +705,7 @@ static void flexcan_mboxint_disable(flex HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow); } - + //=========================================================================== // Allocate message box // Try to find a free message box and return its ID @@ -713,11 +713,11 @@ static void flexcan_mboxint_disable(flex static cyg_int8 flexcan_alloc_mbox(flexcan_info *info) { cyg_uint8 i; - cyg_int8 res = CYGNUM_CAN_MSGBUF_NA; + cyg_int8 res = CYGNUM_CAN_MSGBUF_NA; if (info->free_mboxes) { - for (i = (FLEXCAN_MBOX_RX_CNT - info->free_mboxes); i <= FLEXCAN_MBOX_RX_MAX; ++i) + for (i = (FLEXCAN_MBOX_RX_CNT - info->free_mboxes); i <= FLEXCAN_MBOX_RX_MAX; ++i) { if (MBOX_STATE_DISABLED == info->mboxes[i].state) { @@ -725,7 +725,7 @@ static cyg_int8 flexcan_alloc_mbox(flexc res = i; break; } - } + } } // if (info->free_mboxes) return res; @@ -733,111 +733,111 @@ static cyg_int8 flexcan_alloc_mbox(flexc //=========================================================================== -// Enable a previously configured rx mbox - a mbox ready to recive -//=========================================================================== -static void flexcan_enable_rxmbox(can_channel *chan, - cyg_uint32 mbox_id) -{ - flexcan_info *info = (flexcan_info *)chan->dev_priv; - flexcan_regs *flexcan = (flexcan_regs *)info->base; - - flexcan_hwmbox_enable_rx(flexcan, mbox_id); - flexcan_mboxint_enable(info, mbox_id); -} - -//=========================================================================== +// Enable a previously configured rx mbox - a mbox ready to recive +//=========================================================================== +static void flexcan_enable_rxmbox(can_channel *chan, + cyg_uint32 mbox_id) +{ + flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + + flexcan_hwmbox_enable_rx(flexcan, mbox_id); + flexcan_mboxint_enable(info, mbox_id); +} + +//=========================================================================== // Prepare message buffer filter -// Setup a RX message box for reception of a certain CAN identifier but do -// not enable it +// Setup a RX message box for reception of a certain CAN identifier but do +// not enable it //=========================================================================== static void flexcan_setup_rxmbox(can_channel *chan, cyg_uint32 mbox_id, - cyg_ISR_t *isr, - cyg_can_message *pmsg, - bool enable, - bool int_enable) + cyg_ISR_t *isr, + cyg_can_message *pmsg, + bool enable, + bool int_enable) { flexcan_info *info = (flexcan_info *)chan->dev_priv; flexcan_regs *flexcan = (flexcan_regs *)info->base; flexcan_mbox_info *pmbox; - cyg_DSR_t *dsr_func = &flexcan_mbox_rx_filt_dsr; + cyg_DSR_t *dsr_func = &flexcan_mbox_rx_filt_dsr; // - // Set state of message buffer accoring to ISR function that - // will be registered - // -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID - if (*isr == flexcan_mbox_rx_std_isr) - { - // - // If we have only one single RX all message box then we use - // the filter ISR instead of RX all standard ISR because it - // is better suited for a single RX mbox + // Set state of message buffer accoring to ISR function that + // will be registered + // +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + if (*isr == flexcan_mbox_rx_std_isr) + { + // + // If we have only one single RX all message box then we use + // the filter ISR instead of RX all standard ISR because it + // is better suited for a single RX mbox // - if (info->mboxes_std_cnt > 1) - { - info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_STD; - dsr_func = &flexcan_mbox_rx_std_dsr; - } - else - { - info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; - isr = flexcan_mbox_rx_filt_isr; - } - } - else -#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID - if (*isr == flexcan_mbox_rx_ext_isr) - { - // - // If we have only one single RX all message box then we use - // the filter ISR instead of RX all standard ISR because it - // is better suited for a single RX mbox - // - if (info->mboxes_ext_cnt > 1) - { - info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_EXT; - dsr_func = &flexcan_mbox_rx_ext_dsr; - } - else - { - info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; - isr = flexcan_mbox_rx_filt_isr; - } - } - else -#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID - if (*isr == flexcan_mbox_rx_filt_isr) - { - info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; - } - else - { - CYG_ASSERT(0, "Invalid ISR function pointer"); - } - - pmbox = &info->mboxes[mbox_id]; - flexcan_cfg_mbox_rx(&flexcan->mbox[mbox_id], pmsg, enable); - + if (info->mboxes_std_cnt > 1) + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_STD; + dsr_func = &flexcan_mbox_rx_std_dsr; + } + else + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; + isr = flexcan_mbox_rx_filt_isr; + } + } + else +#endif // CYGOPT_IO_CAN_STD_CAN_ID +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (*isr == flexcan_mbox_rx_ext_isr) + { + // + // If we have only one single RX all message box then we use + // the filter ISR instead of RX all standard ISR because it + // is better suited for a single RX mbox + // + if (info->mboxes_ext_cnt > 1) + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_EXT; + dsr_func = &flexcan_mbox_rx_ext_dsr; + } + else + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; + isr = flexcan_mbox_rx_filt_isr; + } + } + else +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + if (*isr == flexcan_mbox_rx_filt_isr) + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; + } + else + { + CYG_ASSERT(0, "Invalid ISR function pointer"); + } + + pmbox = &info->mboxes[mbox_id]; + flexcan_cfg_mbox_rx(&flexcan->mbox[mbox_id], pmsg, enable); + cyg_drv_interrupt_create(pmbox->isr_vec, pmbox->isr_priority, (cyg_addrword_t) chan, - isr, - dsr_func, + isr, + dsr_func, &(pmbox->interrupt_handle), &(pmbox->interrupt)); cyg_drv_interrupt_attach(pmbox->interrupt_handle); cyg_drv_interrupt_unmask(pmbox->isr_vec); // - // now enable interrupt for this message box - but only if we - // really should do it + // now enable interrupt for this message box - but only if we + // really should do it // - if (int_enable) - { + if (int_enable) + { flexcan_mboxint_enable(info, mbox_id); - } + } } @@ -911,7 +911,7 @@ static void flexcan_setup_txmbox(can_cha flexcan_mboxint_enable(info, mbox_id); } - + //=========================================================================== // Setup a RTR response message box //=========================================================================== @@ -924,168 +924,168 @@ static void flexcan_setup_rtrmbox(can_ch info->mboxes[mbox_id].state = MBOX_STATE_REMOTE_TX; flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, true); -} +} + - -//=========================================================================== -// Setup the list of message boxes ready to receive a message -//=========================================================================== -static void flexcan_setup_rxmbox_circbuf(flexcan_rxmbox_circbuf *pbuf) -{ - pbuf->count = 0; - pbuf->idx_rd = 0; - pbuf->idx_wr = 0; +//=========================================================================== +// Setup the list of message boxes ready to receive a message +//=========================================================================== +static void flexcan_setup_rxmbox_circbuf(flexcan_rxmbox_circbuf *pbuf) +{ + pbuf->count = 0; + pbuf->idx_rd = 0; + pbuf->idx_wr = 0; } //=========================================================================== -// Setup flexCAN modul for reception of any kind of message +// Setup flexCAN modul for reception of any kind of message //=========================================================================== -static void flexcan_config_rx_all(can_channel *chan) +static void flexcan_config_rx_all(can_channel *chan) { flexcan_info *info = (flexcan_info *)chan->dev_priv; - flexcan_regs *flexcan = (flexcan_regs *)info->base; - cyg_int8 i; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + cyg_int8 i; // - // setup all available message boxes for reception of of messages - // All standard and extended message buffers will be configured + // setup all available message boxes for reception of of messages + // All standard and extended message buffers will be configured // - for (i = 0; i < info->mboxes_rx_all_cnt; ++i) + for (i = 0; i < info->mboxes_rx_all_cnt; ++i) { - cyg_can_message filter_param; - filter_param.id = 0; - - // - // configure message buffers for standard frames - // -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID - if (i < info->mboxes_std_cnt) + cyg_can_message filter_param; + filter_param.id = 0; + + // + // configure message buffers for standard frames + // +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + if (i < info->mboxes_std_cnt) { - filter_param.ext = CYGNUM_CAN_ID_STD; - flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_std_isr, &filter_param, false, true); + filter_param.ext = CYGNUM_CAN_ID_STD; + flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_std_isr, &filter_param, false, true); } -#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID - - // - // configure message buffers for extended frames - // -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID - else +#endif // CYGOPT_IO_CAN_STD_CAN_ID + + // + // configure message buffers for extended frames + // +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + else { - filter_param.ext = CYGNUM_CAN_ID_EXT; - flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_ext_isr, &filter_param, false, true); + filter_param.ext = CYGNUM_CAN_ID_EXT; + flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_ext_isr, &filter_param, false, true); } -#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID +#endif // CYGOPT_IO_CAN_EXT_CAN_ID } // - // We need to receive all available CAN messages so we have to set the acceptance filter - // properly - // - flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT); - flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT); - info->free_mboxes = FLEXCAN_MBOX_RX_CNT - info->mboxes_rx_all_cnt; - info->rx_all = true; - - // - // now finally setup the first active message boxes and enable ist + // We need to receive all available CAN messages so we have to set the acceptance filter + // properly + // + flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT); + flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT); + info->free_mboxes = FLEXCAN_MBOX_RX_CNT - info->mboxes_rx_all_cnt; + info->rx_all = true; + + // + // now finally setup the first active message boxes and enable ist // -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID - if (info->mboxes_std_cnt) +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + if (info->mboxes_std_cnt) { - flexcan_setup_rxmbox_circbuf(&info->rxmbox_std_circbuf); - flexcan_enable_rxmbox(chan, 0); - } -#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID + flexcan_setup_rxmbox_circbuf(&info->rxmbox_std_circbuf); + flexcan_enable_rxmbox(chan, 0); + } +#endif // CYGOPT_IO_CAN_STD_CAN_ID -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID - if (info->mboxes_ext_cnt) +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (info->mboxes_ext_cnt) { - flexcan_setup_rxmbox_circbuf(&info->rxmbox_ext_circbuf); - flexcan_enable_rxmbox(chan, info->mboxes_std_cnt); + flexcan_setup_rxmbox_circbuf(&info->rxmbox_ext_circbuf); + flexcan_enable_rxmbox(chan, info->mboxes_std_cnt); } -#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID - -} - -//=========================================================================== -// Setup Flex CAN moduls in a state where all message boxes are disabled -// After this call single message filters and buffers can be added -//=========================================================================== -static void flexcan_config_rx_none(can_channel *chan) -{ - flexcan_info *info = (flexcan_info *)chan->dev_priv; - flexcan_regs *flexcan = (flexcan_regs *)info->base; - cyg_int8 i; +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + +} + +//=========================================================================== +// Setup Flex CAN moduls in a state where all message boxes are disabled +// After this call single message filters and buffers can be added +//=========================================================================== +static void flexcan_config_rx_none(can_channel *chan) +{ + flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + cyg_int8 i; // - // setup all RX messages moxes into a disabled state + // setup all RX messages moxes into a disabled state // - for (i = 0; i < FLEXCAN_MBOX_RX_CNT; ++i) + for (i = 0; i < FLEXCAN_MBOX_RX_CNT; ++i) { - flexcan_disable_mbox(chan, i); - } + flexcan_disable_mbox(chan, i); + } - // - // If we want to receive only certain CAN identiffiers then the ID does matter and - // we have to setup the acceptance mask properly - // - flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID, CYGNUM_CAN_ID_EXT); - flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID, CYGNUM_CAN_ID_EXT); - info->free_mboxes = FLEXCAN_MBOX_RX_CNT; - info->rx_all = false; -} - - -//=========================================================================== -// Configure message buffers -//=========================================================================== -static Cyg_ErrNo flexcan_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf) -{ - Cyg_ErrNo res = ENOERR; - flexcan_info *info = (flexcan_info *)chan->dev_priv; - - switch (buf->cfg_id) + // + // If we want to receive only certain CAN identiffiers then the ID does matter and + // we have to setup the acceptance mask properly + // + flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID, CYGNUM_CAN_ID_EXT); + flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID, CYGNUM_CAN_ID_EXT); + info->free_mboxes = FLEXCAN_MBOX_RX_CNT; + info->rx_all = false; +} + + +//=========================================================================== +// Configure message buffers +//=========================================================================== +static Cyg_ErrNo flexcan_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf) +{ + Cyg_ErrNo res = ENOERR; + flexcan_info *info = (flexcan_info *)chan->dev_priv; + + switch (buf->cfg_id) { // - // clear all message filters and remote buffers - prepare for message buffer - // configuration + // clear all message filters and remote buffers - prepare for message buffer + // configuration // - case CYGNUM_CAN_MSGBUF_RESET_ALL : + case CYGNUM_CAN_MSGBUF_RESET_ALL : { - flexcan_config_rx_none(chan); + flexcan_config_rx_none(chan); } - break; - + break; + // - // setup FlexCAN modul for reception of all standard and extended messages + // setup FlexCAN modul for reception of all standard and extended messages // - case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL : + case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL : { - if (!info->rx_all) // if rx_all is enabled we do not need to do anything + if (!info->rx_all) // if rx_all is enabled we do not need to do anything { - flexcan_config_rx_none(chan); // set into default state - flexcan_config_rx_all(chan); // setup RX all state + flexcan_config_rx_none(chan); // set into default state + flexcan_config_rx_all(chan); // setup RX all state } } break; // - // add single message filter, message with filter ID will be received + // add single message filter, message with filter ID will be received // - case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD : + case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD : { cyg_can_filter *filter = (cyg_can_filter*) buf; - // - // if FlexCAN is configured to receive all messages then it is not - // allowed to add single message filters because then more than - // one message buffer would receive the same CAN id - // - if (info->rx_all) + // + // if FlexCAN is configured to receive all messages then it is not + // allowed to add single message filters because then more than + // one message buffer would receive the same CAN id + // + if (info->rx_all) { - return -EPERM; + return -EPERM; } // @@ -1093,102 +1093,102 @@ static Cyg_ErrNo flexcan_set_config_msgb // then we can prepare the message box for reception of the // desired message id // - filter->handle = flexcan_alloc_mbox(info); - if (filter->handle > CYGNUM_CAN_MSGBUF_NA) + filter->handle = flexcan_alloc_mbox(info); + if (filter->handle > CYGNUM_CAN_MSGBUF_NA) { - flexcan_setup_rxmbox(chan, filter->handle, &flexcan_mbox_rx_filt_isr, &filter->msg, true, true); - } - } - break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD - + flexcan_setup_rxmbox(chan, filter->handle, &flexcan_mbox_rx_filt_isr, &filter->msg, true, true); + } + } + break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD + // - // Try to add a new RTR response message buffer for automatic transmisson - // of data frame on reception of a remote frame + // Try to add a new RTR response message buffer for automatic transmisson + // of data frame on reception of a remote frame // - case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD : + case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD : { - cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; - rtr_buf->handle = flexcan_alloc_mbox(info); + cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; + rtr_buf->handle = flexcan_alloc_mbox(info); - if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA) + if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA) { - // - // if we have a free message buffer then we setup this buffer - // for remote frame reception - // - flexcan_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg); - } + // + // if we have a free message buffer then we setup this buffer + // for remote frame reception + // + flexcan_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg); + } } - break; + break; // - // write data into remote response buffer - // - case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE : - { - cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; - - // - // If we have a valid rtr buf handle then we can store data into - // rtr message box + // write data into remote response buffer + // + case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE : + { + cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; + + // + // If we have a valid rtr buf handle then we can store data into + // rtr message box // - if ((rtr_buf->handle >= 0) && (rtr_buf->handle <= FLEXCAN_MBOX_RX_MAX)) - { - flexcan_regs *flexcan = (flexcan_regs *)info->base; - flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true); + if ((rtr_buf->handle >= 0) && (rtr_buf->handle <= FLEXCAN_MBOX_RX_MAX)) + { + flexcan_regs *flexcan = (flexcan_regs *)info->base; + flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true); } else { - return -EINVAL; + return -EINVAL; } } - break; - } // switch (buf->cfg_id) + break; + } // switch (buf->cfg_id) - return res; -} - -//=========================================================================== -// 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) + return res; +} + +//=========================================================================== +// 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) { // - //Setup a new CAN configuration. This will i.e. setup a new baud rate + //Setup a new CAN configuration. This will i.e. setup a new baud rate // - case CYG_IO_SET_CONFIG_CAN_INFO: + case CYG_IO_SET_CONFIG_CAN_INFO: { - cyg_can_info_t* config = (cyg_can_info_t*) buf; - if (*len < sizeof(cyg_can_info_t)) + 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; + return -EINVAL; + } + *len = sizeof(cyg_can_info_t); + if (!flexcan_config(chan, config, false)) + { + return -EINVAL; } } - break; + break; // - // configure message buffers + // configure message buffers // - case CYG_IO_SET_CONFIG_CAN_MSGBUF : - { - cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *) buf; - - if (*len != sizeof(cyg_can_msgbuf_cfg)) - { - return -EINVAL; - } - - flexcan_set_config_msgbuf(chan, msg_buf); + case CYG_IO_SET_CONFIG_CAN_MSGBUF : + { + cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *) buf; + + if (*len != sizeof(cyg_can_msgbuf_cfg)) + { + return -EINVAL; + } + + flexcan_set_config_msgbuf(chan, msg_buf); } break; @@ -1222,6 +1222,10 @@ flexcan_set_config(can_channel *chan, cy case CYGNUM_CAN_MODE_STANDBY : // set FlexCAN modul into standby state flexcan_enter_standby(chan, true); break; + + case CYGNUM_CAN_MODE_CONFIG : // stop FlexCAN modul for configuration + flexcan_stop_chip(chan); + break; } } break; // case CYG_IO_SET_CONFIG_CAN_MODE : @@ -1272,7 +1276,7 @@ flexcan_get_config(can_channel *chan, cy } *len = sizeof(cyg_can_msgbuf_info); - mbox_info->count = FLEXCAN_MBOX_RX_CNT; + mbox_info->count = FLEXCAN_MBOX_RX_CNT; mbox_info->free = info->free_mboxes; } break; @@ -1304,38 +1308,38 @@ flexcan_get_config(can_channel *chan, cy //=========================================================================== -// Check if we received self transmitted frame -//=========================================================================== -static bool flexcan_is_no_self_tx(cyg_can_event *pevent, flexcan_info *info, flexcan_mbox_info *pmbox) -{ - // - // If 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 - return false; - } - else - { - pevent->flags |= CYGNUM_CAN_EVENT_RX; - - // - // check if an overun occured in this message box - // - if ((pmbox->ctrlstat_shadow & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN) - { - pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX; - } - - return true; - } -} - - -//=========================================================================== +// Check if we received self transmitted frame +//=========================================================================== +static bool flexcan_is_no_self_tx(cyg_can_event *pevent, flexcan_info *info, flexcan_mbox_info *pmbox) +{ + // + // If 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 + return false; + } + else + { + pevent->flags |= CYGNUM_CAN_EVENT_RX; + + // + // check if an overun occured in this message box + // + if ((pmbox->ctrlstat_shadow & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN) + { + pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX; + } + + return true; + } +} + + +//=========================================================================== // Read one event from can hardware - called from high level I/O CAN driver //=========================================================================== static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata) @@ -1344,7 +1348,7 @@ static bool flexcan_getevent(can_channel flexcan_regs *flexcan = (flexcan_regs *)info->base; bool res = true; cyg_uint16 estat; - cyg_uint8 event_id = *((cyg_uint8 *)pdata); + cyg_uint8 event_id = *((cyg_uint8 *)pdata); // // if event_id is 0 - 15 the we have a message box event @@ -1362,25 +1366,25 @@ static bool flexcan_getevent(can_channel // // If we have an RX event then we need to read the received data from // message box that caused this event and fill it into message queue of - // high level I/O CAN driver. We could handle this stuff in a function - // because it is the same like MBOX_STATE_RX_ALL_EXT but speed is more - // important here than codesize - // - case MBOX_STATE_RX_ALL_STD: - case MBOX_STATE_RX_ALL_EXT: - case MBOX_STATE_RX_FILT: - { + // high level I/O CAN driver. We could handle this stuff in a function + // because it is the same like MBOX_STATE_RX_ALL_EXT but speed is more + // important here than codesize + // + case MBOX_STATE_RX_ALL_STD: + case MBOX_STATE_RX_ALL_EXT: + case MBOX_STATE_RX_FILT: + { // // 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, &(pmbox_info->ctrlstat_shadow)); - res = flexcan_is_no_self_tx(pevent, info, pmbox_info); + flexcan_read_from_mbox(chan, event_id, pevent, &(pmbox_info->ctrlstat_shadow)); + res = flexcan_is_no_self_tx(pevent, info, pmbox_info); } break; #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT - // + // // If a TX message box cause the event then we store the last transmitted // message into the receive message queue // @@ -1404,10 +1408,10 @@ static bool flexcan_getevent(can_channel // 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]); + pevent->msg.data.bytes[0] = estat & 0xFF; + pevent->msg.data.bytes[1] = (estat >> 8) & 0xFF; + HAL_READ_UINT8(&flexcan->RXERRCNT, pevent->msg.data.bytes[2]); + HAL_READ_UINT8(&flexcan->TXERRCNT, pevent->msg.data.bytes[3]); switch (event_id) { case FLEXCAN_ERR_EVENT : @@ -1473,7 +1477,7 @@ static bool flexcan_putmsg(can_channel * // // check if device is busy sending a message // - if (pmbox->busy) + if (pmbox->busy) { // // if device is busy and the interrupt flag is set, then we know @@ -1489,7 +1493,7 @@ static bool flexcan_putmsg(can_channel * } } - pmbox->busy = true; // mark transmitter as busy + pmbox->busy = true; // mark transmitter as busy info->last_tx_id = pmsg->id; // store message in order to identify self recieved frames #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT @@ -1617,7 +1621,7 @@ static bool flexcan_config(can_channel* // deactivate all message buffers - this is mandatory for configuration // of message buffers // - for (i = FLEXCAN_MBOX_MIN; i <= FLEXCAN_MBOX_MAX; ++i) + for (i = FLEXCAN_MBOX_MIN; i <= FLEXCAN_MBOX_MAX; ++i) { HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE); } @@ -1639,9 +1643,9 @@ static bool flexcan_config(can_channel* HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & ~FLEXCAN_CTRL1_LBUF)); // - // setup all rx message buffers + // setup all rx message buffers // - flexcan_config_rx_all(chan); + flexcan_config_rx_all(chan); // // bus off interrupt and error interrupt @@ -1919,10 +1923,10 @@ static void flexcan_wake_dsr(cyg_vector_ //=========================================================================== -// Flexcan message box isr for rx messages if message filtering is -// enabled +// Flexcan message box isr for rx messages if message filtering is +// enabled //=========================================================================== -static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t vec, cyg_addrword_t data) +static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t vec, cyg_addrword_t data) { can_channel *chan = (can_channel *)data; flexcan_info *info = (flexcan_info *)chan->dev_priv; @@ -1941,7 +1945,7 @@ static cyg_uint32 flexcan_mbox_rx_filt_i // reenable it later // flexcan_mboxint_disable(info, mbox); - info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; + info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; // // for clearing the interrupt we first read the flag register as 1 @@ -1961,243 +1965,243 @@ static cyg_uint32 flexcan_mbox_rx_filt_i } -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID +//=========================================================================== +// Flexcan message box isr for extended identifiers if reception of all +// available messages is enabled +//=========================================================================== +static cyg_uint32 flexcan_mbox_rx_ext_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; + flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf); + + // + // number of message box can be calculated from vector that caused + // 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; + if (++prx_mbox_list->count < info->mboxes_ext_cnt) + { + prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; + flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr + info->mboxes_std_cnt); + flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow)); + flexcan_hwmbox_disable(flexcan, mbox); // now disable this message box - it is already locked + // + // first we disable interrupts of this message box - the DSR will + // reenable it later + // + flexcan_mboxint_disable(info, mbox); + } + else + { + prx_mbox_list->count = info->mboxes_ext_cnt; + info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; + } + + // + // 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); If counter of mbox list is > 1 + // then we know that there is already a DSR running and we do not + // need to invoke one + // + if (prx_mbox_list->count > 1) + { + return CYG_ISR_HANDLED; + } + else + { + return CYG_ISR_CALL_DSR; + } +} + + +//=========================================================================== +// FlexCAN message box DSR for extended CAN frames //=========================================================================== -// Flexcan message box isr for extended identifiers if reception of all -// available messages is enabled -//=========================================================================== -static cyg_uint32 flexcan_mbox_rx_ext_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; - flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf); - - // - // number of message box can be calculated from vector that caused - // 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; - if (++prx_mbox_list->count < info->mboxes_ext_cnt) - { - prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; - flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr + info->mboxes_std_cnt); - flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow)); - flexcan_hwmbox_disable(flexcan, mbox); // now disable this message box - it is already locked - // - // first we disable interrupts of this message box - the DSR will - // reenable it later - // - flexcan_mboxint_disable(info, mbox); - } - else - { - prx_mbox_list->count = info->mboxes_ext_cnt; - info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; - } - - // - // 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); If counter of mbox list is > 1 - // then we know that there is already a DSR running and we do not - // need to invoke one - // - if (prx_mbox_list->count > 1) - { - return CYG_ISR_HANDLED; - } - else - { - return CYG_ISR_CALL_DSR; - } -} - - -//=========================================================================== -// FlexCAN message box DSR for extended CAN frames -//=========================================================================== -static void flexcan_mbox_rx_ext_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_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf); - cyg_uint8 mbox; - cyg_uint8 mbox_cnt; - - // - // we do not process the message box we received as event_id - // we take the message boxes from the ring buffer - // - do - { - cyg_drv_isr_lock(); - mbox_cnt = --prx_mbox_list->count; - cyg_drv_isr_unlock(); - - mbox = prx_mbox_list->idx_rd + info->mboxes_std_cnt; - prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_ext_cnt; - chan->callbacks->rcv_event(chan, &mbox); - flexcan_mboxint_enable(info, mbox); - - // - // if the last message box is enabled, then we have to enable - // another one now because the last message box is filled already - // - if (mbox_cnt == (info->mboxes_ext_cnt - 1)) - { - cyg_uint8 active_mbox; - cyg_uint8 next_mbox; - flexcan_regs *flexcan = (flexcan_regs *)info->base; - - cyg_drv_isr_lock(); - active_mbox = prx_mbox_list->idx_wr; - next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; - cyg_drv_isr_unlock(); - - active_mbox += info->mboxes_std_cnt; - next_mbox += info->mboxes_std_cnt; - flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow)); - flexcan_hwmbox_disable(flexcan, active_mbox); // now disable this message box - it is already locked - flexcan_hwmbox_enable_rx(flexcan, next_mbox); - } - } - while (mbox_cnt); -} - -#endif // #ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID - - -#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID -//=========================================================================== -// Flexcan message box isr for standard identifiers if reception of all -// available messages is enabled -//=========================================================================== -static cyg_uint32 flexcan_mbox_rx_std_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; - flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf); - - // - // number of message box can be calculated from vector that caused - // 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; - if (++prx_mbox_list->count < info->mboxes_std_cnt) - { - prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_std_cnt; - flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr); - flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow)); - flexcan_hwmbox_disable(flexcan, mbox); // now disable this message box - it is already locked - // - // first we disable interrupts of this message box - the DSR will - // reenable it later - // - flexcan_mboxint_disable(info, mbox); - } - else - { - prx_mbox_list->count = info->mboxes_std_cnt; - info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; - } - - // - // 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); If counter of mbox list is > 1 - // then we know that there is already a DSR running and we do not - // need to invoke one - // - if (prx_mbox_list->count > 1) - { - return CYG_ISR_HANDLED; - } - else - { - return CYG_ISR_CALL_DSR; - } -} - - -//=========================================================================== -// Flexcan message box dsr for standard CAN frames -//=========================================================================== -static void flexcan_mbox_rx_std_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_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf); - cyg_uint8 mbox; - cyg_uint8 mbox_cnt; - - // - // we do not process the message box we received as event_id - // we take the message boxes from the ring buffer - // - do - { - cyg_drv_isr_lock(); - mbox_cnt = --prx_mbox_list->count; - cyg_drv_isr_unlock(); - - mbox = prx_mbox_list->idx_rd; - prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_std_cnt; - chan->callbacks->rcv_event(chan, &mbox); - flexcan_mboxint_enable(info, mbox); - - // - // if the last message box is enabled, then we have to enable - // another one now because the last message box is filled already - // - if (mbox_cnt == (info->mboxes_std_cnt - 1)) - { - cyg_uint8 active_mbox; - cyg_uint8 next_mbox; - flexcan_regs *flexcan = (flexcan_regs *)info->base; - - cyg_drv_isr_lock(); - active_mbox = prx_mbox_list->idx_wr; - next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; - cyg_drv_isr_unlock(); - - flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow)); - flexcan_hwmbox_disable(flexcan, active_mbox); // now disable this message box - it is already locked - flexcan_hwmbox_enable_rx(flexcan, next_mbox); - } - } - while (mbox_cnt); -} -#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID - - +static void flexcan_mbox_rx_ext_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_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf); + cyg_uint8 mbox; + cyg_uint8 mbox_cnt; + + // + // we do not process the message box we received as event_id + // we take the message boxes from the ring buffer + // + do + { + cyg_drv_isr_lock(); + mbox_cnt = --prx_mbox_list->count; + cyg_drv_isr_unlock(); + + mbox = prx_mbox_list->idx_rd + info->mboxes_std_cnt; + prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_ext_cnt; + chan->callbacks->rcv_event(chan, &mbox); + flexcan_mboxint_enable(info, mbox); + + // + // if the last message box is enabled, then we have to enable + // another one now because the last message box is filled already + // + if (mbox_cnt == (info->mboxes_ext_cnt - 1)) + { + cyg_uint8 active_mbox; + cyg_uint8 next_mbox; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + + cyg_drv_isr_lock(); + active_mbox = prx_mbox_list->idx_wr; + next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; + cyg_drv_isr_unlock(); + + active_mbox += info->mboxes_std_cnt; + next_mbox += info->mboxes_std_cnt; + flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow)); + flexcan_hwmbox_disable(flexcan, active_mbox); // now disable this message box - it is already locked + flexcan_hwmbox_enable_rx(flexcan, next_mbox); + } + } + while (mbox_cnt); +} + +#endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID + + +#ifdef CYGOPT_IO_CAN_STD_CAN_ID +//=========================================================================== +// Flexcan message box isr for standard identifiers if reception of all +// available messages is enabled //=========================================================================== -// FlexCAN DSR for message filters -//=========================================================================== -static void flexcan_mbox_rx_filt_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) +static cyg_uint32 flexcan_mbox_rx_std_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; + flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf); + + // + // number of message box can be calculated from vector that caused + // 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; + if (++prx_mbox_list->count < info->mboxes_std_cnt) + { + prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_std_cnt; + flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr); + flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow)); + flexcan_hwmbox_disable(flexcan, mbox); // now disable this message box - it is already locked + // + // first we disable interrupts of this message box - the DSR will + // reenable it later + // + flexcan_mboxint_disable(info, mbox); + } + else + { + prx_mbox_list->count = info->mboxes_std_cnt; + info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; + } + + // + // 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); If counter of mbox list is > 1 + // then we know that there is already a DSR running and we do not + // need to invoke one + // + if (prx_mbox_list->count > 1) + { + return CYG_ISR_HANDLED; + } + else + { + return CYG_ISR_CALL_DSR; + } +} + + +//=========================================================================== +// Flexcan message box dsr for standard CAN frames +//=========================================================================== +static void flexcan_mbox_rx_std_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_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf); + cyg_uint8 mbox; + cyg_uint8 mbox_cnt; + + // + // we do not process the message box we received as event_id + // we take the message boxes from the ring buffer + // + do + { + cyg_drv_isr_lock(); + mbox_cnt = --prx_mbox_list->count; + cyg_drv_isr_unlock(); + + mbox = prx_mbox_list->idx_rd; + prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_std_cnt; + chan->callbacks->rcv_event(chan, &mbox); + flexcan_mboxint_enable(info, mbox); + + // + // if the last message box is enabled, then we have to enable + // another one now because the last message box is filled already + // + if (mbox_cnt == (info->mboxes_std_cnt - 1)) + { + cyg_uint8 active_mbox; + cyg_uint8 next_mbox; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + + cyg_drv_isr_lock(); + active_mbox = prx_mbox_list->idx_wr; + next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; + cyg_drv_isr_unlock(); + + flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow)); + flexcan_hwmbox_disable(flexcan, active_mbox); // now disable this message box - it is already locked + flexcan_hwmbox_enable_rx(flexcan, next_mbox); + } + } + while (mbox_cnt); +} +#endif // CYGOPT_IO_CAN_STD_CAN_ID + + +//=========================================================================== +// FlexCAN DSR for message filters +//=========================================================================== +static void flexcan_mbox_rx_filt_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; @@ -2295,7 +2299,7 @@ static void flexcan_mbox_tx_dsr(cyg_vect chan->callbacks->rcv_event(chan, &mbox); #endif - pmbox->busy = false; + pmbox->busy = false; // // send next message @@ -2532,7 +2536,7 @@ static bool flexcan_cfg_mbox_tx(flexcan_ // // Now copy data bytes into buffer and start transmission // - HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1); + HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data.bytes, pmsg->dlc, 1); if (rtr) @@ -2553,8 +2557,8 @@ static bool flexcan_cfg_mbox_tx(flexcan_ // Configure message box for reception of a certain CAN identifier //=========================================================================== static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, - cyg_can_message *pmsg, - bool enable) + cyg_can_message *pmsg, + bool enable) { cyg_uint16 id; @@ -2579,10 +2583,10 @@ static void flexcan_cfg_mbox_rx(flexcan_ HAL_WRITE_UINT16(&pmbox->id_lo, 0); } - if (enable) - { + if (enable) + { HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY); - } + } } @@ -2599,16 +2603,16 @@ static void flexcan_read_from_mbox(can_c flexcan_mbox *pmbox = &flexcan->mbox[mbox]; cyg_can_message *pmsg = &pevent->msg; cyg_uint16 id; - bool enable_mbox = false; + bool enable_mbox = false; - // - // If controlstat was not read, then read it now - // - if (FLEXCAN_CTRLSTAT_NOT_READ == *ctrlstat) - { + // + // If controlstat was not read, then read it now + // + if (FLEXCAN_CTRLSTAT_NOT_READ == *ctrlstat) + { HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox - enable_mbox = true; - } + enable_mbox = true; + } // // If message buffer is busy then it is now beeing filled with a new message @@ -2660,17 +2664,17 @@ static void flexcan_read_from_mbox(can_c // // now finally copy data // - HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1); + HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data.bytes, pmsg->dlc, 1); // // now mark this mbox as empty and read the free running timer // to unlock this mbox // - if (enable_mbox) - { + if (enable_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
--- a/packages/devs/can/m68k/mcf52xx/current/tests/can_test_aux.inl +++ b/packages/devs/can/m68k/mcf52xx/current/tests/can_test_aux.inl @@ -68,11 +68,12 @@ void print_can_msg(cyg_can_message *pmsg if (pmsg->rtr) { - diag_printf("%s [ID:%03X] [RTR:%d] [EXT:%d]\n", + diag_printf("%s [ID:%03X] [RTR:%d] [EXT:%d] [DLC:%d]\n", pMsg, pmsg->id, pmsg->rtr, - pmsg->ext); + pmsg->ext, + pmsg->dlc); return; } @@ -91,14 +92,14 @@ void print_can_msg(cyg_can_message *pmsg pmsg->id, pmsg->rtr, pmsg->ext, - pmsg->data[0], - pmsg->data[1], - pmsg->data[2], - pmsg->data[3], - pmsg->data[4], - pmsg->data[5], - pmsg->data[6], - pmsg->data[7]); + pmsg->data.bytes[0], + pmsg->data.bytes[1], + pmsg->data.bytes[2], + pmsg->data.bytes[3], + pmsg->data.bytes[4], + pmsg->data.bytes[5], + pmsg->data.bytes[6], + pmsg->data.bytes[7]); }
deleted file mode 100644 --- a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_filter.c +++ /dev/null @@ -1,356 +0,0 @@ -//========================================================================== -// -// flexcan_filter.c -// -// FlexCAN message filter test -// -//========================================================================== -//####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: Uwe Kindler -// Date: 2005-09-10 -// Description: FlexCAN hardware filter test -//####DESCRIPTIONEND#### - - -//=========================================================================== -// INCLUDES -//=========================================================================== -#include <pkgconf/system.h> - -#include <cyg/infra/testcase.h> // test macros -#include <cyg/infra/cyg_ass.h> // assertion macros -#include <cyg/infra/diag.h> - -// Package requirements -#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) - -#include <pkgconf/kernel.h> -#include <cyg/io/io.h> -#include <cyg/io/canio.h> - -// Package option requirements -#if defined(CYGFUN_KERNEL_API_C) - -#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL -#include <cyg/kernel/kapi.h> - - -//=========================================================================== -// DATA TYPES -//=========================================================================== -typedef struct st_thread_data -{ - cyg_thread obj; - long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; - cyg_handle_t hdl; -} thread_data_t; - - -//=========================================================================== -// LOCAL DATA -//=========================================================================== -cyg_thread_entry_t can0_thread; -thread_data_t can0_thread_data; - - -cyg_io_handle_t hDrvFlexCAN; - - -//=========================================================================== -// LOCAL FUNCTIONS -//=========================================================================== -#include "can_test_aux.inl" // include CAN test auxiliary functions - - -//=========================================================================== -// READER THREAD -//=========================================================================== -void can0_thread(cyg_addrword_t data) -{ - cyg_uint32 len; - cyg_can_event rx_event; - cyg_can_mode mode; - cyg_uint8 i; - cyg_can_hdi hdi; - cyg_can_msgbuf_info msgbox_info; - cyg_can_msgbuf_cfg msgbox_cfg; - - - len = sizeof(hdi); - if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_HDI ,&hdi, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); - } - - // - // Normally the FlexCAN modul should support message filters. So the - // FULLCAN flag should be set - if it is not, we treat this as an error - // - if (!(hdi.support_flags & CYGNUM_CAN_HDI_FULLCAN)) - { - CYG_TEST_FAIL_FINISH("/dev/can0 does not support message buffers"); - } - - // - // We have free message boxes available and now we can setup the message - // filters, during this configuration process we set the FlexCAN modul into - // stopped state - // - mode = CYGNUM_CAN_MODE_STOP; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - // - // Now reset message buffer configuration - this is mandatory bevore adding - // - msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; - len = sizeof(msgbox_cfg); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&msgbox_cfg, &len)) - { - CYG_TEST_FAIL_FINISH("Error restting message buffer configuration of /dev/can0"); - } - - // - // Now query number of available and free message boxes - // - len = sizeof(msgbox_info); - if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); - } - - // - // if there are no free message boxes available then this is a failure - // - if (!msgbox_info.free) - { - CYG_TEST_FAIL_FINISH("No free message boxes available for /dev/can0"); - } - - // - // Now device is stopped an we can setup all free message buffers - // we setup as many standard CAN message filters as there are free - // message buffers available. - // - for (i = 0; i < msgbox_info.free; ++i) - { - cyg_can_filter rx_filter; - - rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD; - rx_filter.msg.id = i; - - if (i % 2) - { - rx_filter.msg.ext = CYGNUM_CAN_ID_EXT; - } - else - { - rx_filter.msg.ext = CYGNUM_CAN_ID_STD; - } - - len = sizeof(rx_filter); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rx_filter, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - else if (CYGNUM_CAN_MSGBUF_NA == rx_filter.handle) - { - CYG_TEST_FAIL_FINISH("Error setting up message filter for /dev/can0"); - } - } - - // - // Now message filters have been setup and we can start the FlexCAN modul again - // - mode = CYGNUM_CAN_MODE_START; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - diag_printf("Now try to send CAN messages. The device should only\n" - "receive messages identifiers in the range of 0x00 to 0x%X.\n" - "All CAN filters with an odd identifier will receive\n" - "extended CAN messages. As soon as a standard message\n" - "with ID 0 arrives, all message filters will be cleared\n\n", (msgbox_info.free - 1)); - - // - // Now receive messages until a message arrives with largest ID of all - // available message filters - // - rx_event.msg.id = 1; - while(rx_event.msg.id != 0) - { - len = sizeof(rx_event); - - if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); - } - else if (rx_event.flags & CYGNUM_CAN_EVENT_RX) - { - print_can_msg(&rx_event.msg, ""); - } // if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len)) - } // while(1) - - // - // Stop device in order to clear all message filters and to activate - // the receive all message box - // - mode = CYGNUM_CAN_MODE_STOP; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - // - // Now enable reception of all available CAN messages - // - cyg_can_filter rx_filter; - rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ALL; - len = sizeof(rx_filter); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF , &rx_filter, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - // - // Now we can start FlexCAN modul again - // - mode = CYGNUM_CAN_MODE_START; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - diag_printf("\nAll message filters have been cleared an now the device\n" - "will receive any available CAN message identifier.\n" - "Send a CAN message with ID 0x100 to stop this test.\n\n"); - - // - // Now receive messages until a message arrives with largest ID of all - // available message filters - // - rx_event.msg.id = 1; - while(rx_event.msg.id != 0x100) - { - len = sizeof(rx_event); - - if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); - } - else if (rx_event.flags & CYGNUM_CAN_EVENT_RX) - { - print_can_msg(&rx_event.msg, ""); - } // if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len)) - } // while(1) - - CYG_TEST_PASS_FINISH("flexcan_filter test OK"); -} - - -void -cyg_start(void) -{ - CYG_TEST_INIT(); - - // - // open flexcan device driver - // - if (ENOERR != cyg_io_lookup("/dev/can0", &hDrvFlexCAN)) - { - CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); - } - - // We do not setup baudrate and take dafauklt baudrate from config tool instead - /* - // - // setup CAN baudrate 250 KBaud - // - cyg_uint32 len; - cyg_can_info_t can_cfg; - can_cfg.baud = CYGNUM_CAN_KBAUD_250; - len = sizeof(can_cfg); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - }*/ - - // - // create the two threads which access the CAN device driver - // a reader thread with a higher priority and a writer thread - // with a lower priority - // - cyg_thread_create(4, can0_thread, - (cyg_addrword_t) 0, - "can0_thread", - (void *) can0_thread_data.stack, - 1024 * sizeof(long), - &can0_thread_data.hdl, - &can0_thread_data.obj); - - cyg_thread_resume(can0_thread_data.hdl); - - cyg_scheduler_start(); -} - -#else // CYGFUN_KERNEL_API_C -#define N_A_MSG "Needs kernel C API" -#endif - -#else // CYGPKG_IO_CAN && CYGPKG_KERNEL -#define N_A_MSG "Needs IO/CAN and Kernel" -#endif - -#ifdef N_A_MSG -void -cyg_start( void ) -{ - CYG_TEST_INIT(); - CYG_TEST_NA( N_A_MSG); -} -#endif // N_A_MSG - -// EOF flexcan_filter.c
deleted file mode 100644 --- a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_load.c +++ /dev/null @@ -1,317 +0,0 @@ -//========================================================================== -// -// flexcan_load.c -// -// FlexCAN load test -// -//========================================================================== -//####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: Uwe Kindler -// Date: 2005-08-14 -// Description: FlexCAN load test -//####DESCRIPTIONEND#### - - -//=========================================================================== -// INCLUDES -//=========================================================================== -#include <pkgconf/system.h> - -#include <cyg/infra/testcase.h> // test macros -#include <cyg/infra/cyg_ass.h> // assertion macros -#include <cyg/infra/diag.h> - -// Package requirements -#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) - -#include <pkgconf/kernel.h> -#include <cyg/io/io.h> -#include <cyg/io/canio.h> - -// Package option requirements -#if defined(CYGFUN_KERNEL_API_C) - -#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL -#include <cyg/kernel/kapi.h> - - -//=========================================================================== -// DATA TYPES -//=========================================================================== -typedef struct st_thread_data -{ - cyg_thread obj; - long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; - cyg_handle_t hdl; -} thread_data_t; - - -//=========================================================================== -// LOCAL DATA -//=========================================================================== -cyg_thread_entry_t can0_thread; -thread_data_t can0_thread_data; - -cyg_thread_entry_t can1_thread; -thread_data_t can1_thread_data; - -cyg_io_handle_t hDrvFlexCAN; - - -//=========================================================================== -// LOCAL FUNCTIONS -//=========================================================================== -#include "can_test_aux.inl" // include CAN test auxiliary functions - - -//=========================================================================== -// READER THREAD -//=========================================================================== -void can0_thread(cyg_addrword_t data) -{ - cyg_uint32 len; - cyg_can_event rx_event; - cyg_can_timeout_info_t timeouts; - -#if defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS) - // - // setup large timeout values because we do not need timeouts here - // - timeouts.rx_timeout = 100000; - timeouts.tx_timeout = 100000; - - len = sizeof(timeouts); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_TIMEOUT ,&timeouts, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } -#endif // defined(CYGOPT_IO_CAN_SUPPORT_TIMEOUTS) - - // - // This thread simply receives all CAN events and prints the event flags and the - // CAN message if it was a TX or RX event. You can use this test in order to check - // when a RX overrun occurs - // - while (1) - { - len = sizeof(rx_event); - - if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); - } - else - { - print_can_flags(rx_event.flags, ""); - - if ((rx_event.flags & CYGNUM_CAN_EVENT_RX) || (rx_event.flags & CYGNUM_CAN_EVENT_TX)) - { - print_can_msg(&rx_event.msg, ""); - } - } - } -} - - -//=========================================================================== -// WRITER THREAD -//=========================================================================== -void can1_thread(cyg_addrword_t data) -{ - cyg_uint16 i = 0; - cyg_uint32 len; - cyg_can_message tx_msg = - { - 0x000, // CAN identifier - {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes - CYGNUM_CAN_ID_STD, // standard frame - CYGNUM_CAN_FRAME_DATA, // data frame - 8, // data length code - }; - - // - // This thread simply sends CAN messages. It increments the ID for each new CAN messsage - // and sends a remote frame after seven data frames. In the first byte of each data frame - // the number (0 - 7) of the data frame is stored and the length of the data frame grows - // from 1 - 8 data bytes. - // - // The received pattern should look like this way: - // ID Length Data - // ---------------------------------------------- - // 000 1 00 - // 001 2 01 F1 - // 002 3 02 F1 F2 - // 003 4 03 F1 F2 F3 - // 004 5 04 F1 F2 F3 F4 - // 005 6 05 F1 F2 F3 F4 F5 - // 006 7 06 F1 F2 F3 F4 F5 F6 - // 007 8 Remote Request - // 008 1 00 - // 009 2 01 F1 - // 00A 3 02 F1 F2 - // ... - // - while (1) - { - tx_msg.id = i; - tx_msg.dlc = (i % 8) + 1; - tx_msg.data[0] = (i % 8); - i = (i + 1) % 0x7FF; - - // - // the 6th frame is a remote frame - // - if ((i % 8) == 6) - { - tx_msg.rtr = CYGNUM_CAN_FRAME_RTR; - tx_msg.ext = CYGNUM_CAN_ID_STD; - } - // - // the 7th frame is a extended frame - // - else if ((i % 8) == 7) - { - tx_msg.ext = CYGNUM_CAN_ID_EXT; - tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; - } - // - // the 8th frame is a extended remote frame - // - else if (!(i % 8)) - { - tx_msg.ext = CYGNUM_CAN_ID_EXT; - tx_msg.rtr = CYGNUM_CAN_FRAME_RTR; - } - // - // all other frames are standard data framse - // - else - { - tx_msg.ext = CYGNUM_CAN_ID_STD; - tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; - } - - len = sizeof(tx_msg); - if (ENOERR != cyg_io_write(hDrvFlexCAN, &tx_msg, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing to /dev/can0"); - } - else - { - print_can_msg(&tx_msg, "TX: "); - } - - cyg_thread_delay(100); - } // while (1) -} - - - -void -cyg_start(void) -{ - CYG_TEST_INIT(); - - // - // open flexcan device driver - // - if (ENOERR != cyg_io_lookup("/dev/can0", &hDrvFlexCAN)) - { - CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); - } - - // We do not setup baudrate and take dafauklt baudrate from config tool instead - /* - // - // setup CAN baudrate 250 KBaud - // - cyg_uint32 len; - cyg_can_info_t can_cfg; - can_cfg.baud = CYGNUM_CAN_KBAUD_250; - len = sizeof(can_cfg); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - */ - - // - // create the two threads which access the CAN device driver - // a reader thread with a higher priority and a writer thread - // with a lower priority - // - cyg_thread_create(4, can0_thread, - (cyg_addrword_t) 0, - "can0_thread", - (void *) can0_thread_data.stack, - 1024 * sizeof(long), - &can0_thread_data.hdl, - &can0_thread_data.obj); - - cyg_thread_create(5, can1_thread, - (cyg_addrword_t) can0_thread_data.hdl, - "can1_thread", - (void *) can1_thread_data.stack, - 1024 * sizeof(long), - &can1_thread_data.hdl, - &can1_thread_data.obj); - - cyg_thread_resume(can0_thread_data.hdl); - cyg_thread_resume(can1_thread_data.hdl); - - cyg_scheduler_start(); -} - -#else // CYGFUN_KERNEL_API_C -#define N_A_MSG "Needs kernel C API" -#endif - -#else // CYGPKG_IO_CAN && CYGPKG_KERNEL -#define N_A_MSG "Needs IO/CAN and Kernel" -#endif - -#ifdef N_A_MSG -void -cyg_start( void ) -{ - CYG_TEST_INIT(); - CYG_TEST_NA( N_A_MSG); -} -#endif // N_A_MSG - -// EOF flexcan_load.c
deleted file mode 100644 --- a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_remote.c +++ /dev/null @@ -1,309 +0,0 @@ -//========================================================================== -// -// flexcan_remote.c -// -// FlexCAN remote response buffer test -// -//========================================================================== -//####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: Uwe Kindler -// Date: 2005-08-14 -// Description: FlexCAN load test -//####DESCRIPTIONEND#### - - -//=========================================================================== -// INCLUDES -//=========================================================================== -#include <pkgconf/system.h> - -#include <cyg/infra/testcase.h> // test macros -#include <cyg/infra/cyg_ass.h> // assertion macros -#include <cyg/infra/diag.h> - -// Package requirements -#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) - -#include <pkgconf/kernel.h> -#include <cyg/io/io.h> -#include <cyg/io/canio.h> - -// Package option requirements -#if defined(CYGFUN_KERNEL_API_C) - -#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL -#include <cyg/kernel/kapi.h> - - -//=========================================================================== -// DATA TYPES -//=========================================================================== -typedef struct st_thread_data -{ - cyg_thread obj; - long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; - cyg_handle_t hdl; -} thread_data_t; - - -//=========================================================================== -// LOCAL DATA -//=========================================================================== -cyg_thread_entry_t can0_thread; -thread_data_t can0_thread_data; - - -cyg_io_handle_t hDrvFlexCAN; - - -//=========================================================================== -// LOCAL FUNCTIONS -//=========================================================================== -#include "can_test_aux.inl" // include CAN test auxiliary functions - - -//=========================================================================== -// READER THREAD -//=========================================================================== -void can0_thread(cyg_addrword_t data) -{ - cyg_uint32 len; - cyg_can_event rx_event; - cyg_can_remote_buf rtr_buf; - cyg_can_remote_buf rtr_buf2; - cyg_can_msgbuf_info msgbox_info; - cyg_can_mode mode; - cyg_can_state state; - - // - // before we start configuring the CAN hardware we stop the chip - // - mode = CYGNUM_CAN_MODE_STOP; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - // - // now check if FlexCAN modul is really stopped - // - len = sizeof(state); - if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_STATE ,&state, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); - } - - if (state != CYGNUM_CAN_STATE_STOPPED) - { - CYG_TEST_FAIL_FINISH("Error stopping FlexCAN /dev/can0"); - } - - // - // We would like to setup 2 remote buffers - check if we have enough - // free message buffers - // - len = sizeof(msgbox_info); - if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); - } - else - { - diag_printf("Message boxes available: %d free: %d\n", - msgbox_info.count, msgbox_info.free); - } - - if (msgbox_info.free < 2) - { - CYG_TEST_FAIL_FINISH("Not enough free message buffers/dev/can0"); - } - - - // - // Setup the first remote response buffer for resception of standard - // remote frames - // - rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; - rtr_buf.msg.id = 0x7FF; - rtr_buf.msg.ext = CYGNUM_CAN_ID_STD; - rtr_buf.msg.rtr = CYGNUM_CAN_FRAME_DATA; - rtr_buf.msg.dlc = 1; - rtr_buf.msg.data[0] = 0xAB; - - len = sizeof(rtr_buf); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - // - // setup the second remote response buffer for reception of extended - // remote frames - // - rtr_buf2.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; - rtr_buf2.msg.id = 0x800; - rtr_buf2.msg.ext = CYGNUM_CAN_ID_EXT; - rtr_buf2.msg.rtr = CYGNUM_CAN_FRAME_DATA; - rtr_buf2.msg.dlc = 4; - rtr_buf2.msg.data[0] = 0xAB; - - len = sizeof(rtr_buf2); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf2, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - if (rtr_buf.handle == CYGNUM_CAN_MSGBUF_NA) - { - CYG_TEST_FAIL_FINISH("No free message buffer available for /dev/can0"); - } - - // - // now configuration is finished and we can start chip again - // - mode = CYGNUM_CAN_MODE_START; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - diag_printf("Test of FlexCAN remote response buffer configuration\n" - "If a CAN node sends a remote request with ID 0x7FF\n" - "or 0x800 then the FlexCAN modul should respond with\n" - "data frames.\n"); - diag_printf("!!! This test can be stopped by sending a data frame with ID 0x100 !!!\n\n"); - - len = sizeof(msgbox_info); - if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - else - { - diag_printf("Message boxes available: %d free: %d\n", - msgbox_info.count, msgbox_info.free); - } - - while (1) - { - len = sizeof(rx_event); - - if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); - } - - if (0x100 == rx_event.msg.id) - { - CYG_TEST_PASS_FINISH("flexcan_remote test OK"); - } - else - { - print_can_flags(rx_event.flags, ""); - print_can_msg(&rx_event.msg, ""); - } - } - - -} - - -void -cyg_start(void) -{ - CYG_TEST_INIT(); - - // - // open flexcan device driver - // - if (ENOERR != cyg_io_lookup("/dev/can0", &hDrvFlexCAN)) - { - CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); - } - - // - // setup CAN baudrate 250 KBaud - // We do not setup baud rate and use the default baud rate instead - /* - cyg_uint32 len; - cyg_can_info_t can_cfg; - can_cfg.baud = CYGNUM_CAN_KBAUD_250; - len = sizeof(can_cfg); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - }*/ - - // - // create the two threads which access the CAN device driver - // a reader thread with a higher priority and a writer thread - // with a lower priority - // - cyg_thread_create(4, can0_thread, - (cyg_addrword_t) 0, - "can0_thread", - (void *) can0_thread_data.stack, - 1024 * sizeof(long), - &can0_thread_data.hdl, - &can0_thread_data.obj); - - cyg_thread_resume(can0_thread_data.hdl); - - cyg_scheduler_start(); -} - -#else // CYGFUN_KERNEL_API_C -#define N_A_MSG "Needs kernel C API" -#endif - -#else // CYGPKG_IO_CAN && CYGPKG_KERNEL -#define N_A_MSG "Needs IO/CAN and Kernel" -#endif - -#ifdef N_A_MSG -void -cyg_start( void ) -{ - CYG_TEST_INIT(); - CYG_TEST_NA( N_A_MSG); -} -#endif // N_A_MSG - -// EOF flexcan_remote.c
--- a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_wake.c +++ b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_wake.c @@ -105,72 +105,18 @@ void can0_thread(cyg_addrword_t data) cyg_uint32 len; cyg_can_event rx_event1; cyg_can_event rx_event2; - cyg_can_remote_buf rtr_buf; cyg_can_msgbuf_info msgbox_info; cyg_can_mode mode; cyg_can_state state; - // - // before we start configuring the CAN hardware we stop the chip - // - mode = CYGNUM_CAN_MODE_STOP; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - // - // now check if FlexCAN modul is really stopped - // - len = sizeof(state); - if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_STATE ,&state, &len)) - { - CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); - } - - if (state != CYGNUM_CAN_STATE_STOPPED) - { - CYG_TEST_FAIL_FINISH("Error stopping FlexCAN /dev/can0"); - } - - // - // Setup the first remote response buffer for resception of standard - // remote frames - // - rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; - rtr_buf.msg.id = 0x7FF; - rtr_buf.msg.ext = CYGNUM_CAN_ID_STD; - rtr_buf.msg.rtr = CYGNUM_CAN_FRAME_DATA; - rtr_buf.msg.dlc = 1; - rtr_buf.msg.data[0] = 0xAB; - - len = sizeof(rtr_buf); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - - // - // now configuration is finished and we can start chip again - // - mode = CYGNUM_CAN_MODE_START; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - diag_printf("Test of FlexCAN standby mode with selfwakeup\n" "As soon as a message arrives the FlexCAN modul\n" "will leave standby and generates a leave standby event.\n" "Each time you send a message you should see LSTY first\n" "for \"leaving standby\" and then \"RX\" for the\n" - "RX event caused the leave standby event. You can send\n" - "a CAN data frame with any ID or a remote frame with ID\n" - "0x7FF\n" ); + "RX event that caused the leave standby event. You can send\n" + "a CAN data frame with any ID\n"); diag_printf("!!! This test can be stopped by sending a data frame with ID 0x100 !!!\n\n"); @@ -206,6 +152,7 @@ void can0_thread(cyg_addrword_t data) CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } + if (state != CYGNUM_CAN_STATE_STANDBY) { CYG_TEST_FAIL_FINISH("Error stopping FlexCAN /dev/can0"); @@ -261,20 +208,7 @@ cyg_start(void) CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); } - // We do not setup baudrate and take dafauklt baudrate from config tool instead - /* - // - // setup CAN baudrate 250 KBaud - // - cyg_uint32 len; - cyg_can_info_t can_cfg; - can_cfg.baud = CYGNUM_CAN_KBAUD_250; - len = sizeof(can_cfg); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - }*/ - + // // create the two threads which access the CAN device driver // a reader thread with a higher priority and a writer thread
