From: lothar Date: Fri, 13 Feb 2009 17:04:23 +0000 (+0000) Subject: Initial revision X-Git-Tag: v1.5.3~63 X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-redboot.git;a=commitdiff_plain;h=e37ed26bfbb2f0638fdf14673e10d69865ebd92b Initial revision --- diff --git a/packages/devs/can/arm/at91/at91sam7/v2_0/ChangeLog b/packages/devs/can/arm/at91/at91sam7/v2_0/ChangeLog new file mode 100644 index 00000000..5448c260 --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/v2_0/ChangeLog @@ -0,0 +1,41 @@ +2007-03-23 Uwe Kindler + + * 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#### +//=========================================================================== diff --git a/packages/devs/can/arm/at91/at91sam7/v2_0/cdl/can_at91sam7.cdl b/packages/devs/can/arm/at91/at91sam7/v2_0/cdl/can_at91sam7.cdl new file mode 100644 index 00000000..6b1f029d --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/v2_0/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 " + puts $::cdl_system_header "#define CYGDAT_IO_CAN_DEVICE_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." + } +} diff --git a/packages/devs/can/arm/at91/at91sam7/v2_0/include/can_at91sam7.inl b/packages/devs/can/arm/at91/at91sam7/v2_0/include/can_at91sam7.inl new file mode 100644 index 00000000..d0a4df73 --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/v2_0/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 + + +//========================================================================== +// 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 diff --git a/packages/devs/can/arm/at91/at91sam7/v2_0/src/can_at91sam7.c b/packages/devs/can/arm/at91/at91sam7/v2_0/src/can_at91sam7.c new file mode 100644 index 00000000..2f8d4baf --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/v2_0/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 +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + + +//=========================================================================== +// 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 diff --git a/packages/devs/can/arm/at91/at91sam7/v2_0/tests/can_test_aux.inl b/packages/devs/can/arm/at91/at91sam7/v2_0/tests/can_test_aux.inl new file mode 100644 index 00000000..2946b8fd --- /dev/null +++ b/packages/devs/can/arm/at91/at91sam7/v2_0/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 diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/ChangeLog b/packages/devs/can/arm/lpc2xxx/v2_0/ChangeLog new file mode 100644 index 00000000..ec01cff2 --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/ChangeLog @@ -0,0 +1,111 @@ +2008-07-21 Uwe Kindler + + * cdl/can_lpc2xxx.cdl: Added CYGOPT_DEVS_CAN_LPC2XXX_ALIE to make + arbitration lost interrupt optional. Added option + CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY to configure the interrupt + priority for global CAN interrupt in LPC24xx variants. + + * include/can_lpc2xxx_baudrates.h: Replaced CYGNUM_CAN_LPC2XXX_VPB_CLK + by CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK because newer variants like LPC24xx + do not have a global VPB_CLK. + + * src/can_accfilt_lpc2xxx.c: Adjusted LPC2XXX_CAN_FIRST_IN_LUT to + be 0 for LPC24xxx variants. Added macro CAN_CHAN_NO_LUT(_info_) to + abstract channel numbering from acceptance filter code. + + * src/can_lpc2xxx.c: Removed icr data field from lpc2xxx_can_info_st + structure because it is not required any longer. A lot of small + modifications to make the driver usable with newer LPC2xxx variants like + LPC24xx. ISR and DSR code changed - instead of disabling interrupts in + IER register they are disabled in VIC by using cyg_drv_interrupt_mask() + function calls. Added global CAN ISR and DSR for LPC24xx variants + (they do not support individual interrupt vectors for RX and TX + interrupts). Moved LUT error checking code from ISR into DSR to keep + ISR as short as possible and made LUT error checking code optional. + +2008-05-23 Alexey Shusharin + + * cdl/can_lpc2xxx.cdl: add CAN interrupt priorities + + * src/can_lpc2xxx.c: add CAN interrupt priorities, + repair "chan" definition missing in rx_ISR + + * src/can_accfilt_lpc2xxx.c: add various types of CAN controllers + numbering (depends on LPC2XXX version) + +2007-08-17 Hans Rosenfeld + + * src/can_lpc2xxx.c: The definition of "info" is missing when only + one CAN channel is configured. + +2007-08-17 Uwe Kindler + + * include/can_lpc2xxx_baudrates.h: Removed all prefixed zeros from + baudrate table entries (they aren't intended to be interpreted as + octal) + + * tests/can_baudrates.c + tests/can_busload.c + tests/can_rx_tx.c: removed #include pkgconf/devs_can_loop.h + +2007-08-02 Alexey Shusharin + + * src/can_lpc2xxx.c: Added acknowledging call in rx interrupt + (self-reception part) + +2007-07-07 Alexey Shusharin + + * cdl/can_lpx2xxx.cdl: Option + CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION added for enabling + self reception requests instead of transmission requests. + + * src/can_lpc2xxx.c: Some small bugs fixed. Added support for LUT + error. Support for self transmission request added. Debug output + improved. + + * src/can_accfilt_lpc2xxx.c: Added support for baudrates of 10kbaud + and 20 kbaud at clock speed of 60 MHz + +2007-07-01 Uwe Kindler + + * LPC2xxx CAN driver package created + * cdl/can_lpc2xxx.cdl + * include/can_lpc2xxx.h + * include/can_lpc2xxx_baudrates.h + * src/can_lpc2xxx.c + * src/can_accfilt_lpc2xxx.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#### +//=========================================================================== diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/cdl/can_lpc2xxx.cdl b/packages/devs/can/arm/lpc2xxx/v2_0/cdl/can_lpc2xxx.cdl new file mode 100644 index 00000000..ba8ebdb2 --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/cdl/can_lpc2xxx.cdl @@ -0,0 +1,405 @@ +# ==================================================================== +# +# can_lpc2xxx.cdl +# +# eCos LPC2xxx 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_LPC2XXX { + display "Philips LPC2xxx CAN device drivers" + parent CYGPKG_IO_CAN_DEVICES + active_if CYGPKG_IO_CAN + active_if CYGPKG_HAL_ARM_LPC2XXX || CYGPKG_HAL_ARM_LPC24XX + requires CYGPKG_ERROR + + implements CYGINT_IO_CAN_STD_CAN_ID + implements CYGINT_IO_CAN_EXT_CAN_ID + + include_dir cyg/io + description " + This option enables the CAN device drivers for the + Philips LPC2XXX." + compile -library=libextras.a can_lpc2xxx.c + define_proc { + puts $::cdl_system_header "/***** CAN driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_IO_CAN_DEVICE_HEADER " + puts $::cdl_system_header "/***** CAN driver proc output end *****/" + } + + cdl_component CYGOPT_DEVS_CAN_LPC2XXX_RUNTIME_ACCFILT { + display "Acceptance filter runtime configuration" + flavor bool + implements CYGINT_IO_CAN_RUNTIME_MBOX_CFG + description " + The LPC2xxx CAN module supports a global acceptance + filter. Enabling this option provides support for runtime + configuration of this acceptance filter. If each CAN + channel should receive all CAN messages and individual + message filtering is not required then disable this option + to eliminate almost the complete acceptance filter code + and to decrease code size. If this option is disabled the + option CYGOPT_IO_CAN_RUNTIME_MBOX_CFG is not available and + the configuration key CYG_IO_SET_CONFIG_CAN_MSGBUF is not + supported by this driver." + + cdl_option CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS { + display "Extended acceptance filtering" + flavor bool + default_value 0 + description " + The common CAN I/O layer supports setup of single + message filters for reception of single CAN + messages. The global LPC2xxx acceptance filter + supports not only single message filters but also + message groups. A message group is defined by a + lower bound CAN identifier and an upper bound CAN + identifier. The acceptance filter will accept all + messages within this range of CAN identifiers. The + acceptance filter supports a number of message + groups for each CAN channel. The support of + message filter groups is not conform to the + standard API of the CAN I/O layer and should only + be used for application where portability is not + important." + } + + cdl_option CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP { + display "LUT Error Support" + flavor bool + default_value 0 + description " + The CAN module contains a look-up table for + acceptance filtering of incoming CAN messages. The + look-up table indicates errors in the LUT error + registers. If this option is enabled, additional + error check code is executed if an interrupt is + serviced. Normally the acceptance filter code should + fill the look-up table properly and no LUT error + should ever occur. You need to decide if LUT error + checking is required for your application because it + adds some bytes of code and slows down the ISR/DSR + handling a little bit because of the additional code + that need to be executed." + } + } + + + cdl_option CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION { + display "Use Self Reception Request command" + flavor bool + active_if CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION < 4 + default_value 0 + description " + Enable this option for using work-around of problem with + receiving messages while arbitration is lost. If this work + around is used each transmitted CAN message will be + received. This will produce additional RX interrupts an + requires additional time for processing these interrupts + and for filtering of received messages. + + The errata sheet tells the following about this issue: + Introduction: The CAN module can lose arbitration to + another CAN node during an attempt to transmit a CAN + message. The message of the CAN node the arbitration was + lost to is supposed to be received correctly by the CAN + module. + + Problem: Messages might not be received correctly if + during a CAN Transmission the CAN bus arbitration is lost + to another CAN node. + + Work-around: Use the Self Reception Request command + instead of the Transmission Request command. However, it + has to be taken into account that now all transmitted + messages may be received if not prevented by appropriate + Acceptance Filter settings. (Don't set up Acceptance + Filter Message Identifiers for the messages you are + transmitting yourself.)." + } + + cdl_option CYGOPT_DEVS_CAN_LPC2XXX_ALIE { + display "Arbitration lost interrupt enable" + flavor bool + default_value 0 + description " + If the CAN controller loses arbitration while attempting to + transmit a message, an interrupt can be triggered. Normally + this is no real error condition and it is not necessary to + propagate these events to upper layers. But you can enable + this option if you want to check for arbitration lost events." + } + + cdl_option CYGDBG_DEVS_CAN_LPC2XXX_DEBUG { + display "Support printing debug information" + default_value 0 + description " + Check this box to turn ON debug options for LPC2XXXX + CAN device driver." + } + + # Support up to 4 on-chip CAN modules. The number may vary between + # processor variants so it is easy to update this here + for { set ::channel 0 } { $::channel < 4 } { incr ::channel } { + + cdl_interface CYGINT_DEVS_CAN_LPC2XXX_CAN[set ::channel] { + display "Platform provides CAN [set ::channel]" + flavor bool + description " + This interface will be implemented if the specific LPC2xxx + processor being used has on-chip CAN [set ::channel], and if + that CAN module is accessible on the target hardware." + } + + cdl_component CYGPKG_DEVS_CAN_LPC2XXX_CAN[set ::channel] { + display "Allow access to the on-chip CAN [set ::channel] via a CAN driver" + flavor bool + active_if CYGINT_DEVS_CAN_LPC2XXX_CAN[set ::channel] + implements CYGINT_IO_CAN_CHANNELS + default_value 1 + description " + If the application needs to access the on-chip CAN + module [set ::channel] via an eCos CAN driver then + this option should be enabled." + + cdl_option CYGPKG_DEVS_CAN_LPC2XXX_CAN[set ::channel]_NAME { + display "Device name for CAN module [set ::channel]" + flavor data + default_value [format {"\"/dev/can%d\""} $::channel] + 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_LPC2XXX_CAN[set ::channel]_KBAUD { + display "Default baud rate for CAN module [set ::channel]" + 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 ::channel]" + } + + cdl_option CYGNUM_DEVS_CAN_LPC2XXX_CAN[set ::channel]_QUEUESIZE_TX { + display "Size of TX Queue for the CAN module [set ::channel] driver" + flavor data + default_value 32 + legal_values 1 to 1024 + 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_LPC2XXX_CAN[set ::channel]_QUEUESIZE_RX { + display "Size of RX Queue for the CAN module [set ::channel] driver" + flavor data + default_value 64 + legal_values 8 to 4096 + 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 CYGOPT_DEVS_CAN_LPC2XXX_CAN[set ::channel]_ACCFILT_STARTUP_CFG { + display "Acceptance filter startup configuration" + flavor data + legal_values {"RX_ALL" "RX_NONE"} + default_value {"RX_ALL"} + active_if CYGOPT_DEVS_CAN_LPC2XXX_RUNTIME_ACCFILT + description " + Normally the acceptance filter will be configured + at startup time to receive all available CAN + messages. The application can setup single message + filters during runtime later. If RX_NONE is + selected then the acceptance filter for this + channel is configured to receive no CAN message + identifier." + } + + cdl_option CYGNUM_DEVS_CAN_LPC2XXX_CAN[set ::channel]_RX_INT_PRIORITY { + display "Priority level of CAN module [set ::channel] receive interrupt" + flavor data + active_if CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION < 4 + default_value 16 + legal_values 0 to 16 + description " + This option sets CAN module [set ::channel] + device receive interrupt priority level. We + support up to 17 interrupt levels. Interrupts + 0 - 15 are vectored interrupt + requests. Priority 16 indicates a non vectored + IRQ. Vectored IRQs have the higher priority + then non vectored IRQs and slot 0 has the + highest priority and slot 15 has the lowest." + } + + cdl_option CYGNUM_DEVS_CAN_LPC2XXX_CAN[set ::channel]_TX_INT_PRIORITY { + display "Priority level of CAN module [set ::channel] transmit interrupt" + flavor data + active_if CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION < 4 + default_value 16 + legal_values 0 to 16 + description " + This option sets CAN module [set ::channel] + device transmit interrupt priority level. We + support up to 17 interrupt levels. Interrupts + 0 - 15 are vectored interrupt + requests. Priority 16 indicates a non vectored + IRQ. Vectored IRQs have the higher priority + then non vectored IRQs and slot 0 has the + highest priority and slot 15 has the lowest." + } + } + } + + cdl_option CYGNUM_DEVS_CAN_LPC2XXX_ERR_INT_PRIORITY { + display "Priority level of CAN error interrupt" + flavor data + active_if CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION < 4 + default_value 16 + legal_values 0 to 16 + description " + This option sets CAN device error interrupt priority level. + We support up to 17 interrupt levels. Interrupts 0 - 15 + are vectored interrupt requests. Priority 16 indicates a + non vectored IRQ. Vectored IRQs have the higher priority + then non vectored IRQs and slot 0 has the highest priority + and slot 15 has the lowest." + } + + cdl_option CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY { + display "Priority level of all CAN interrupts" + flavor data + active_if CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION >= 4 + default_value 15 + legal_values 0 to 15 + description " + The LPC24xx family uses one single interrupt vector for + all CAN interrupts of all CAN channels. This if very + different from former LPC2xxx variants where each CAN + channels has its own interrupt vectors for transmit + and receive interrupts. There are 16 priority + levels, corresponding to the values 0 through 15 decimal, + of which 15 is the lowest priority. The reset value of + these interrupt priority registers defaults all interrupts + to the lowest priority 15, allowing a single write to + elevate the priority of an individual interrupt." + } + + cdl_option CYGPKG_DEVS_CAN_LPC2XXX_TESTS { + display "CAN LPC2xxx device driver tests" + flavor data + no_define + calculated { "tests/can_busload tests/can_rx_tx" } + description " + This option specifies the set of tests for the LPC2xxx + CAN device driver." + } + + cdl_option CYGBLD_DEVS_CAN_LPC2XXX_EXTRA_TESTS { + display "Build extra CAN tests" + default_value 0 + no_define + description " + This option enables the building of some extra tests which + can be used when testing / debugging the LPC2xxx CAN driver. These + are not built by default since they do not use the dedicated + 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 { + /bin/can_multichan_rx : /tests/can_multichan_rx.c + @sh -c "mkdir -p tests $(dir $@)" + $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/can_multichan_rx.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/can_multichan_rx.o + } + + make -priority 320 { + /bin/can_multichan_tx : /tests/can_multichan_tx.c + @sh -c "mkdir -p tests $(dir $@)" + $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/can_multichan_tx.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/can_multichan_tx.o + } + + make -priority 320 { + /bin/can_baudrates : /tests/can_baudrates.c + @sh -c "mkdir -p tests $(dir $@)" + $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/can_baudrates.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/can_baudrates.o + } + + make -priority 320 { + /bin/can_extended_cfg : /tests/can_extended_cfg.c + @sh -c "mkdir -p tests $(dir $@)" + $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o tests/can_extended_cfg.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/can_extended_cfg.o + } + } +} diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/include/can_lpc2xxx.h b/packages/devs/can/arm/lpc2xxx/v2_0/include/can_lpc2xxx.h new file mode 100644 index 00000000..7e4d773b --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/include/can_lpc2xxx.h @@ -0,0 +1,93 @@ +#ifndef CYGONCE_CAN_LPC2XXX_H +#define CYGONCE_CAN_LPC2XXX_H +//========================================================================== +// +// devs/can/arm/lpc2xxx/current/include/can_lpc2xxx.h +// +// Extended configuration option for LPC2xxx 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: Extended configuration options for LPC2xxx CAN driver +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +//========================================================================== +// DEFINES +//========================================================================== +// +// The LPC2XXX supports enhanced configuration options that are not supported +// be the generic CAN I/O layer. Be careful with using this extension +// because they may reduce portability of your application +// + +//-------------------------------------------------------------------------- +// Message filter configuration +// +#define CYG_IO_SET_CONFIG_LPC2XXX_ACCFILT_GROUP CYG_IO_SET_CONFIG_CAN_ABORT + 0x10 // add message filter group + + +//-------------------------------------------------------------------------- +// Mode setup of LPC2XXX +// +#define CYGNUM_CAN_MODE_LPC2XXX_LISTEN_ONLY 0x80 // set controller in listen only mode + + +//========================================================================== +// DATA TYPES +//========================================================================== +// +// structure for configuration of message filter groups +// +typedef struct cyg_can_filtergroup_cfg_st +{ + cyg_can_id_type ext; + cyg_uint32 lower_id_bound; + cyg_uint32 upper_id_bound; +} cyg_can_filtergroup_cfg; + + +//--------------------------------------------------------------------------- +#endif // CYGONCE_CAN_LPC2XXX_H diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/include/can_lpc2xxx_baudrates.h b/packages/devs/can/arm/lpc2xxx/v2_0/include/can_lpc2xxx_baudrates.h new file mode 100644 index 00000000..9569d06d --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/include/can_lpc2xxx_baudrates.h @@ -0,0 +1,214 @@ +#ifndef CYGONCE_CAN_LPC2XXX_BAUDRATES_H +#define CYGONCE_CAN_LPC2XXX_BAUDRATES_H +//========================================================================== +// +// devs/can/arm/lpc2xxx/current/include/can_lpc2xxx_baudrates.h +// +// Precalculated values for bit timing register +// +//========================================================================== +//####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-07-01 +// Purpose: Precalculated bit timing values for various baudrates +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +// +// Macro for creation of CAN_BR value for baudrate tbl +// +#define CAN_BR_TBL_ENTRY(_brp_, _tseg1_, _tseg2_, _sjw_, _sam_) \ + ((_sam_ << 23) | (_tseg2_ << 20) | (_tseg1_ << 16) | (_sjw_ << 14) | (_brp_)) + + +#ifndef CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK +#error "CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK not defined" +#endif +//========================================================================== +// BAUDRATES +//========================================================================== +#if CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 60000000 +// +// Table with register values for baudrates at peripheral clock of 60 MHz +// +static const cyg_uint32 lpc2xxx_br_tbl[] = +{ + CAN_BR_TBL_ENTRY(300, 15, 2, 0, 1), // 10 kbaud + CAN_BR_TBL_ENTRY(150, 15, 2, 0, 1), // 20 kbaud + CAN_BR_TBL_ENTRY(59, 15, 2, 0, 1), // 50 kbaud + CAN_BR_TBL_ENTRY(39, 11, 1, 0, 1), // 100 kbaud + CAN_BR_TBL_ENTRY(29, 12, 1, 0, 1), // 125 kbaud + CAN_BR_TBL_ENTRY(14, 12, 1, 0, 1), // 250 kbaud + CAN_BR_TBL_ENTRY( 7, 11, 1, 0, 0), // 500 kbaud + CAN_BR_TBL_ENTRY( 4, 11, 1, 0, 0), // 800 kbaud + CAN_BR_TBL_ENTRY( 3, 11, 1, 0, 0), // 1000 kbaud + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // Autobaud - not supported +}; +#define HAL_LPC2XXX_BAUD_TBL_DEFINED 1 +#endif // CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 60000000 + +#if CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 30000000 +// +// Table with register values for baudrates at peripheral clock of 30 MHz +// +static const cyg_uint32 lpc2xxx_br_tbl[] = +{ + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // 10 kbaud - not supported + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // 20 kbaud - not supported + CAN_BR_TBL_ENTRY(59, 15, 2, 0, 1), // 50 kbaud + CAN_BR_TBL_ENTRY(39, 11, 1, 0, 1), // 100 kbaud + CAN_BR_TBL_ENTRY(29, 12, 1, 0, 1), // 125 kbaud + CAN_BR_TBL_ENTRY(14, 12, 1, 0, 1), // 250 kbaud + CAN_BR_TBL_ENTRY( 7, 11, 1, 0, 0), // 500 kbaud + CAN_BR_TBL_ENTRY( 4, 11, 1, 0, 0), // 800 kbaud + CAN_BR_TBL_ENTRY( 3, 11, 1, 0, 0), // 1000 kbaud + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // Autobaud - not supported +}; +#define HAL_LPC2XXX_BAUD_TBL_DEFINED 1 +#endif // CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 30000000 + +#if CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 15000000 +// +// Table with register values for baudrates at peripheral clock of 15 MHz +// +static const cyg_uint32 lpc2xxx_br_tbl[] = +{ + CAN_BR_TBL_ENTRY(59, 15, 7, 0, 1), // 10 kbaud + CAN_BR_TBL_ENTRY(49, 11, 1, 0, 1), // 20 kbaud + CAN_BR_TBL_ENTRY(19, 11, 1, 0, 1), // 50 kbaud + CAN_BR_TBL_ENTRY( 9, 11, 1, 0, 1), // 100 kbaud + CAN_BR_TBL_ENTRY( 7, 11, 1, 0, 1), // 125 kbaud + CAN_BR_TBL_ENTRY( 3, 11, 1, 0, 1), // 250 kbaud + CAN_BR_TBL_ENTRY( 1, 11, 1, 0, 0), // 500 kbaud + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // 800 kbaud - not supported + CAN_BR_TBL_ENTRY( 0, 11, 1, 0, 0), // 1000 kbaud + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // Autobaud - not supported +}; +#define HAL_LPC2XXX_BAUD_TBL_DEFINED 1 +#endif // CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 15000000 + +#if CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 48000000 +// +// Table with register values for baudrates at peripheral clock of 48 MHz +// +static const cyg_uint32 lpc2xxx_br_tbl[] = +{ + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // 10 kbaud - not supported + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // 20 kbaud - not supported + CAN_BR_TBL_ENTRY(59, 12, 1, 0, 1), // 50 kbaud + CAN_BR_TBL_ENTRY(29, 12, 1, 0, 1), // 100 kbaud + CAN_BR_TBL_ENTRY(23, 12, 1, 0, 1), // 125 kbaud + CAN_BR_TBL_ENTRY(11, 12, 1, 0, 1), // 250 kbaud + CAN_BR_TBL_ENTRY( 5, 12, 1, 0, 0), // 500 kbaud + CAN_BR_TBL_ENTRY( 3, 11, 1, 0, 0), // 800 kbaud + CAN_BR_TBL_ENTRY( 2, 12, 1, 0, 0), // 1000 kbaud + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // Autobaud - not supported +}; +#define HAL_LPC2XXX_BAUD_TBL_DEFINED 1 +#endif // CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 48000000 + +#if CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 24000000 +// +// Table with register values for baudrates at peripheral clock of 24 MHz +// +static const cyg_uint32 lpc2xxx_br_tbl[] = +{ + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // 10 kbaud - not supported + CAN_BR_TBL_ENTRY(59, 15, 2, 0, 1), // 20 kbaud + CAN_BR_TBL_ENTRY(29, 12, 1, 0, 1), // 50 kbaud + CAN_BR_TBL_ENTRY(14, 12, 1, 0, 1), // 100 kbaud + CAN_BR_TBL_ENTRY(11, 12, 1, 0, 1), // 125 kbaud + CAN_BR_TBL_ENTRY( 5, 12, 1, 0, 1), // 250 kbaud + CAN_BR_TBL_ENTRY( 2, 12, 1, 0, 0), // 500 kbaud + CAN_BR_TBL_ENTRY( 1, 11, 1, 0, 0), // 800 kbaud + CAN_BR_TBL_ENTRY( 1, 5, 0, 0, 0), // 1000 kbaud + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // Autobaud - not supported +}; +#define HAL_LPC2XXX_BAUD_TBL_DEFINED 1 +#endif // CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 24000000 + +#if CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 12000000 +// +// Table with register values for baudrates at peripheral clock of 12 MHz +// +static const cyg_uint32 lpc2xxx_br_tbl[] = +{ + CAN_BR_TBL_ENTRY(59, 15, 2, 0, 1), // 10 kbaud - not supported + CAN_BR_TBL_ENTRY(39, 11, 1, 0, 1), // 20 kbaud + CAN_BR_TBL_ENTRY(14, 12, 1, 0, 1), // 50 kbaud + CAN_BR_TBL_ENTRY( 7, 11, 1, 0, 1), // 100 kbaud + CAN_BR_TBL_ENTRY( 5, 12, 1, 0, 1), // 125 kbaud + CAN_BR_TBL_ENTRY( 2, 12, 1, 0, 1), // 250 kbaud + CAN_BR_TBL_ENTRY( 2, 05, 0, 0, 0), // 500 kbaud + CAN_BR_TBL_ENTRY( 0, 11, 1, 0, 0), // 800 kbaud + CAN_BR_TBL_ENTRY( 0, 9, 0, 0, 0), // 1000 kbaud + CAN_BR_TBL_ENTRY( 0, 0, 0, 0, 0), // Autobaud - not supported +}; +#define HAL_LPC2XXX_BAUD_TBL_DEFINED 1 +#endif // CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK == 12000000 + + +//========================================================================== +// BIT TIMING MACRO +//========================================================================== +// +// Macro fills baudrate register value depending on selected baudrate +// For several LPC2XXX peripheral clock speeds we provide a pre calculated +// baudrate table. If the board uses another clock speed, then the platform +// HAL needs to provide an own HAL_LPC2XXX_GET_CAN_BR() macro that returns +// valid baudrate register values or it needs to patch this file with +// an additional table for the desired clock speed +// +// +// If a certain baudrate is not supported, then this macro shall return +// 0 as the baudrate register value +// +#ifdef HAL_LPC2XXX_BAUD_TBL_DEFINED +#define HAL_LPC2XXX_GET_CAN_BR(_baudrate_, _br_) \ +CYG_MACRO_START \ + _br_ = lpc2xxx_br_tbl[(_baudrate_) - CYGNUM_CAN_KBAUD_10]; \ +CYG_MACRO_END +#endif // HAL_LPC2XXX_BAUD_TBL_DEFINED + +//------------------------------------------------------------------------- +#endif // #ifndef CYGONCE_CAN_LPC2XXX_BAUDRATES_H diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/src/can_accfilt_lpc2xxx.c b/packages/devs/can/arm/lpc2xxx/v2_0/src/can_accfilt_lpc2xxx.c new file mode 100644 index 00000000..e7089315 --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/src/can_accfilt_lpc2xxx.c @@ -0,0 +1,1011 @@ +//========================================================================== +// +// devs/can/arm/lpc2xxx/current/src/can_accfilt_lpc2xxx.c +// +// Acceptance filter management for LPC2xxx 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-05-28 +// Purpose: Support LPC2xxx on-chip CAN acceptance filters +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +//=========================================================================== +// Data types +//=========================================================================== +// +// Acceptance filter entry +// +typedef struct lpc2xxx_accfilt_entry +{ + cyg_uint32 data; // the value inclusive channel number + cyg_uint32 id; + cyg_uint32 lower_id_bound; + cyg_uint32 upper_id_bound; + cyg_uint8 channel_no; +} lpc2xxx_accfilt_entry_t; + + +//=========================================================================== +// Declarations +//=========================================================================== +//-------------------------------------------------------------------------- +// On no-suffix and /00 devices, the CAN controllers are numbered 1 to n +// (n = 2 or 4) in the LUT tables. However, on /01 devices, the CAN controllers +// are numbered 0 to nâ1 in the LUT tables. +// +// On the LPC2468 the LUT channel numbers are also numbered from 0 - 4. +// +#if defined(CYGHWR_HAL_ARM_LPC2XXX_SUFFIX_01) || (CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION == 4) +# define LPC2XXX_CAN_FIRST_IN_LUT (0) +#else +# define LPC2XXX_CAN_FIRST_IN_LUT (1) +#endif + +// +// This macro calculates the chanel number from the channel info. The channel +// number is numbered from 0 - 3 but in the LUT the channel number may differ +// depending on the device suffix. For some devices the channel number in +// LUT are numbered 0 - 3 and for other devices the channels in LUT are +// numbered 1 - 4. This macro abstrats this fact from the acceptance filter +// code +// +#define CAN_CHAN_NO_LUT(_info_) (CAN_CHAN_NO(_info_) + LPC2XXX_CAN_FIRST_IN_LUT) + +//-------------------------------------------------------------------------- +// Lowlevel acceptance filter access +// +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +static bool lpc2xxx_can_accfilt_add(lpc2xxx_can_info_t *info, + cyg_uint32 lower_id, + cyg_uint32 upper_id, + cyg_can_id_type ext); +void lpc2xxx_can_accfilt_ram_insert_entry(cyg_uint32 TableAddress, cyg_uint16 EntryNo); +void lpc2xxx_can_accfilt_ram_remove_entry(cyg_uint32 TableAddress, cyg_uint16 EntryNo); +void lpc2xxx_can_accfilt_remove_all_ctrl_entries(lpc2xxx_can_info_t *info); +#else +static void lpc2xxx_can_accfilt_simple_rx_all(void); +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +void lpc2xxx_can_accfilt_reset(void); + +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG +void lpc2xxx_can_accfilt_dbg_dump(void); +void lpc2xxx_can_reg_dump(struct cyg_devtab_entry* devtab_entry); +#endif + + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Calculate address of entry in certain table +//=========================================================================== +static cyg_uint32 lpc2xxx_can_accfilt_calc_entry_address(cyg_uint32 TableAddressRegister, cyg_uint16 EntryNo) +{ + cyg_uint32 EntryAddress = 0xFFFFFFFF; + cyg_uint32 TableAddress; + + HAL_READ_UINT32(TableAddressRegister, TableAddress); + switch (TableAddressRegister) + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + case CAN_ACCFILT_SFF_SA: + EntryAddress = ((EntryNo / 2) << 2) + TableAddress; + break; + + case CAN_ACCFILT_SFF_GRP_SA: + EntryAddress = TableAddress + (EntryNo << 2); + break; +#endif // CYGOPT_IO_CAN_STD_CAN_ID + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + case CAN_ACCFILT_EFF_SA: + EntryAddress = TableAddress + (EntryNo << 2); + break; + + case CAN_ACCFILT_EFF_GRP_SA: + EntryAddress = TableAddress + (EntryNo << 3); + break; +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + default: + CYG_ASSERT(0, "Wrong TableAddressRegister"); + } + + return EntryAddress; +} + + +//=========================================================================== +// Remove one single entry from acceptance filter table +//=========================================================================== +void lpc2xxx_can_accfilt_ram_remove_entry(cyg_uint32 Table, cyg_uint16 EntryNo) +{ + cyg_int32 remove_address = lpc2xxx_can_accfilt_calc_entry_address(Table, EntryNo); + cyg_int32 entry_address; + lsc_buf_t lsc_val; + cyg_uint8 entry_size = sizeof(cyg_uint32); + cyg_uint32 sff_sa; + cyg_uint32 sff_grp_sa; + cyg_uint32 eff_sa; + cyg_uint32 eff_grp_sa; + cyg_int32 end_of_table; + + HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, sff_sa); + HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa); + HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa); + HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa); + HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table); + + // + // Do not try to remove from an empty table + // + if (!end_of_table) + { + return; + } + + entry_address = remove_address; + + if ((remove_address < eff_grp_sa) && (CAN_ACCFILT_EFF_GRP_SA != Table)) + { + if ((remove_address < eff_sa) && (CAN_ACCFILT_EFF_SA != Table)) + { + if ((remove_address < sff_grp_sa) && (CAN_ACCFILT_SFF_GRP_SA != Table)) + { + lsc_buf_t nextval; + + if (EntryNo % 2) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + remove_address, lsc_val.dword); + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + remove_address + sizeof(cyg_uint32), nextval.dword); + lsc_val.column.upper = nextval.column.lower; + entry_address += sizeof(cyg_uint32); + } + + // + // Start copy immediatelly after removed entry + // + while (entry_address < sff_grp_sa) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword); + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address + sizeof(cyg_uint32), nextval.dword); + lsc_val.column.lower = lsc_val.column.upper; + lsc_val.column.upper = nextval.column.lower; + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword); + entry_address += sizeof(cyg_uint32); + } + + // + // now check if the lower identifier is disabled - if it is disabled, then + // also the upper identifier is invalid and we can remove the entry completely + // if the lower identifier is not disabled, then it is valid and we need + // to disable the upper identifier because it contains an invalid entry + // + if (lsc_val.column.lower & ACCFILT_STD_DIS) + { + sff_grp_sa -= sizeof(cyg_uint32); + entry_address = sff_grp_sa; + } + else + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword); + lsc_val.column.upper = 0xffff; + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword); + entry_size = 0; // we do not need to remove anything + } + } // if (pLine < pStdGrpStart) + + eff_sa -= entry_size; + } // if (pLine < pExtIdStart) + + eff_grp_sa -= entry_size; + } // if (pLine < pExtGrpStart) + + // + // If no entry was removed then we can leave immediately without changing any + // table pointers because we only did a change inside the sff table + // + if (!entry_size) + { +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + lpc2xxx_can_accfilt_dbg_dump(); +#endif + return; + } + + if (CAN_ACCFILT_EFF_GRP_SA == Table) + { + // + // If we are in the area of extended groups then we need to remove + // 2 lines because lower and upper identifier need 1 line each + // + entry_size += sizeof(cyg_uint32); + } + + end_of_table -= entry_size; + + // + // Move all entries one or two dword downwards - that means we remove a line + // + while (entry_address < end_of_table) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address + entry_size, lsc_val.dword); + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword); + entry_address += sizeof(cyg_uint32); + } + + HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, sff_sa); + HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa); + HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, eff_sa); + HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa); + HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table); + +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + lpc2xxx_can_accfilt_dbg_dump(); +#endif +} + +//=========================================================================== +// Insert one empty line into ram - all entries behind this line will be +// moved one entry upwards +//=========================================================================== +void lpc2xxx_can_accfilt_ram_insert_entry(cyg_uint32 Table, cyg_uint16 EntryNo) +{ + cyg_int16 insert_address = lpc2xxx_can_accfilt_calc_entry_address(Table, EntryNo); + cyg_int16 entry_address; + cyg_int16 copy_start = insert_address; + lsc_buf_t lsc_val; + cyg_uint8 entry_size = sizeof(cyg_uint32); + cyg_uint32 sff_sa; + cyg_uint32 sff_grp_sa; + cyg_uint32 eff_sa; + cyg_uint32 eff_grp_sa; + cyg_uint32 end_of_table; + + + HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, sff_sa); + HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa); + HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa); + HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa); + HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table); + + if ((insert_address <= eff_grp_sa) && (CAN_ACCFILT_EFF_GRP_SA != Table)) + { + if ((insert_address <= eff_sa) && (CAN_ACCFILT_EFF_SA != Table)) + { + if ((insert_address <= sff_grp_sa) && (CAN_ACCFILT_SFF_GRP_SA != Table)) + { + // + // If we are in the range of standard identifiers then we need to + // do some special copy procedure for this area because a standard entry + // is only 2 byte long. Copy only til start of area with standard groups + // + if (sff_grp_sa) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword); // read last entry + // + // now check if the upper identifier is disabled - if it is disabled, then + // we have an odd number of std ids in the list. Then we do not need to + // insert a new line - we simply need to copy all entries 2 bytes upwards + // that means we only need to change the std id area and do not need to touch + // any other filter id area. + // If the last entry is not disabled, then we have a valid filter here. + // Then we need to insert a complete new line, that means we also have to move + // all following entries and filter tables one dword upwards. + // + if (lsc_val.words.low & ACCFILT_STD_DIS) + { + copy_start = end_of_table + sizeof(cyg_uint32); // we do not need to insert a new line and do not copy anything + entry_size = 0; + } + } + + if (entry_size) + { + copy_start = sff_grp_sa; // copy everything behind std id group + sff_grp_sa += entry_size; + } + } // if (pLine < pStdGrpStart) + + eff_sa += entry_size; + } // if (pLine < pExtIdStart) + + eff_grp_sa += entry_size; + } // if (pLine < pExtGrpStart) + + if (CAN_ACCFILT_EFF_GRP_SA == Table) + { + // + // If we are in the area of extended groups then we need to insert + // 2 lines because lower and upper identifier need 1 line each + // + entry_size += sizeof(cyg_uint32); // one entry is 2 dword long + } + + entry_address = end_of_table - sizeof(cyg_uint32); + end_of_table += entry_size; // add one additional entry + + // + // Move all entries one or two dwords upwards - that means we insert a new empty line + // + while (entry_address >= copy_start) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword); + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address + entry_size, lsc_val.dword); + entry_address -= sizeof(cyg_uint32); + } + + // + // For the std ID area we need a special procedure + // + if (CAN_ACCFILT_SFF_SA == Table) + { + lsc_buf_t preval; + // + // Start copy with last entry of std id table + // + entry_address = sff_grp_sa - sizeof(cyg_uint32); + + while (entry_address > insert_address) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword); + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address - sizeof(cyg_uint32), preval.dword); + lsc_val.column.upper = lsc_val.column.lower; + lsc_val.column.lower = preval.column.upper; + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword); + entry_address -= sizeof(cyg_uint32); + } + + // + // If we insert an entry into the lower column, then we need to move the + // content of the lower column into the upper column + // + if (!(EntryNo % 2)) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)insert_address, lsc_val.dword); + lsc_val.column.upper = lsc_val.column.lower; + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)insert_address, lsc_val.dword); + } + + // + // If we inserted a new line, then we have an odd number of identifiers now + // and need to disable the last (the upper) entry + // + if (entry_size) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32) , lsc_val.dword); + lsc_val.column.upper = 0xFFFF; // disable the entry + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32) , lsc_val.dword); + } + } + + HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, sff_sa); + HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa); + HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, eff_sa); + HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa); + HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table); +} + + +//=========================================================================== +// Query number of entries in a certain table +//=========================================================================== +static cyg_uint16 lpc2xxx_can_accfilt_get_table_entries(cyg_uint32 TableStartAddress) +{ + cyg_uint32 start; + cyg_uint32 end; + + switch (TableStartAddress) + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + case CAN_ACCFILT_SFF_SA: + HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, start); + HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, end); + if (end - start) + { + lsc_buf_t data; + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + end - sizeof(cyg_uint32), data.dword); + if (data.column.upper & ACCFILT_STD_DIS) + { + return (((end - start) >> 1) - 1); + } + } + return (end - start) >> 1; + + case CAN_ACCFILT_SFF_GRP_SA: + HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, start); + HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, end); + return (end - start) >> 2; +#endif // CYGOPT_IO_CAN_STD_CAN_ID + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + case CAN_ACCFILT_EFF_SA: + HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, start); + HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, end); + return (end - start) >> 2; + + case CAN_ACCFILT_EFF_GRP_SA: + HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, start); + HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end); + return (end - start) >> 3; +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + default: + CYG_FAIL("Invalid identifier table address"); + return 0; + } // switch (TableStartAddress) +} + +//=========================================================================== +// Query certain entry from table +//=========================================================================== +static void lpc2xxx_can_accfilt_get_entry(cyg_uint32 TableStartAddress, cyg_uint16 EntryNo, lpc2xxx_accfilt_entry_t *pEntry) +{ + cyg_uint32 EntryAddress = lpc2xxx_can_accfilt_calc_entry_address(TableStartAddress, EntryNo); + lsc_buf_t Data; + + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword); + pEntry->data = Data.dword; + switch (TableStartAddress) + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + case CAN_ACCFILT_SFF_SA: + { + cyg_uint16 column; + if (EntryNo % 2) + { + column = Data.column.upper; + } + else + { + column = Data.column.lower; + } + pEntry->id = ACCFILT_STD_GET_ID(column); + pEntry->channel_no = ACCFILT_STD_GET_CTRL(column); + } + break; + + case CAN_ACCFILT_SFF_GRP_SA: + pEntry->lower_id_bound = ACCFILT_STD_GET_ID(Data.column.lower); + pEntry->upper_id_bound = ACCFILT_STD_GET_ID(Data.column.upper); + pEntry->channel_no = ACCFILT_STD_GET_CTRL(Data.column.lower); + break; +#endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + case CAN_ACCFILT_EFF_SA: + pEntry->id = ACCFILT_EXT_GET_ID(Data.dword); + pEntry->channel_no = ACCFILT_EXT_GET_CTRL(Data.dword); + break; + + case CAN_ACCFILT_EFF_GRP_SA: + pEntry->lower_id_bound = ACCFILT_EXT_GET_ID(Data.dword); + pEntry->channel_no = ACCFILT_EXT_GET_CTRL(Data.dword); + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE+ EntryAddress + sizeof(cyg_uint32), Data.dword); + pEntry->upper_id_bound = ACCFILT_EXT_GET_ID(Data.dword); + break; +#endif // #ifedf CYGOPT_IO_CAN_EXT_CAN_ID + default: + CYG_FAIL("Invalid identifier table address"); + } // switch () +} + + +//=========================================================================== +// Set certain entry in table +//=========================================================================== +static void lpc2xxx_can_accfilt_set_entry(cyg_uint32 TableStartAddress, cyg_uint16 EntryNo, lpc2xxx_accfilt_entry_t *pEntry) +{ + cyg_uint32 EntryAddress = lpc2xxx_can_accfilt_calc_entry_address(TableStartAddress, EntryNo); + lsc_buf_t Data; + + switch (TableStartAddress) + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + case CAN_ACCFILT_SFF_SA: + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword); + if (EntryNo % 2) + { + Data.column.upper = (pEntry->channel_no << 13) | (pEntry->id & ACCFILT_STD_ID_MASK); + } + else + { + Data.column.lower = (pEntry->channel_no << 13) | (pEntry->id & ACCFILT_STD_ID_MASK); + } + } + break; + + case CAN_ACCFILT_SFF_GRP_SA: + Data.column.lower = (pEntry->channel_no << 13) | (pEntry->lower_id_bound & ACCFILT_STD_ID_MASK); + Data.column.upper = (pEntry->channel_no << 13) | (pEntry->upper_id_bound & ACCFILT_STD_ID_MASK); + break; +#endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + case CAN_ACCFILT_EFF_SA: + Data.dword = (pEntry->channel_no << 29) | (pEntry->id & ACCFILT_EXT_ID_MASK); + break; + + case CAN_ACCFILT_EFF_GRP_SA: + { + lsc_buf_t Data2; + + Data.dword = (pEntry->channel_no << 29) | (pEntry->lower_id_bound & ACCFILT_EXT_ID_MASK); + Data2.dword = (pEntry->channel_no << 29) | (pEntry->upper_id_bound & ACCFILT_EXT_ID_MASK); + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress + sizeof(cyg_uint32), Data2.dword); + } + break; +#endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID + + default: + CYG_FAIL("Invalid identifier table address"); + } // switch () + + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword); +} + + +//=========================================================================== +// Add one entry to acceptance filter RAM +// If upper ID is > lower ID then we have to add a group filter - else we +// have to add a single message filter here +//=========================================================================== +static bool lpc2xxx_can_accfilt_add(lpc2xxx_can_info_t *info, + cyg_uint32 lower_id, + cyg_uint32 upper_id, + cyg_can_id_type ext) +{ + cyg_uint32 accfilt_bck; // acceptance filter backup + cyg_uint32 end_of_table; + cyg_uint32 table; + lpc2xxx_accfilt_entry_t entry; + lpc2xxx_accfilt_entry_t new_entry; + + + // + // first step: disable acceptance filter and prepare it for modification + // + HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck); + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS); + + // + // Check if table is full + // + HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table); + if (end_of_table >= ACCFILT_RAM_SIZE) + { + return false; + } + + new_entry.id = lower_id; + new_entry.lower_id_bound = lower_id; + new_entry.upper_id_bound = upper_id; + + // + // Here we rely on the ISR vector ordering for calculation of channel number + // Maybe this is not the right way for newer LPC parts + // + new_entry.channel_no = CAN_CHAN_NO_LUT(info); + + // + // If lower_id == upper_id then we know that we have to setup a single message filter + // here. If it is not equal the it is group of identifiers to receive + // + if ((lower_id == upper_id) || (lower_id > upper_id)) + { + // + // setup single message filter (standard or extended) here + // +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (ext) + { + table = CAN_ACCFILT_EFF_SA; + } + else +#endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + table = CAN_ACCFILT_SFF_SA; +#endif // CYGOPT_IO_CAN_STD_CAN_ID + } + } + else + { + // + // setup single message filter (standard or extended) here + // +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (ext) + { + table = CAN_ACCFILT_EFF_GRP_SA; + } + else +#endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + table = CAN_ACCFILT_SFF_GRP_SA; +#endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID + } + } + + cyg_uint16 entries = lpc2xxx_can_accfilt_get_table_entries(table); + cyg_uint16 i; + + + for (i = 0; i < entries; ++i) + { + lpc2xxx_can_accfilt_get_entry(table, i, &entry); + + if (entry.channel_no > new_entry.channel_no) + { + break; + } + + if ((entry.channel_no == new_entry.channel_no) + && (entry.id > new_entry.id)) + { + break; + } + } // for (i = 0; i < entries; ++i) + + lpc2xxx_can_accfilt_ram_insert_entry(table, i); + lpc2xxx_can_accfilt_set_entry(table, i, &new_entry); + + // + // finally restore the previous state of the acceptance filter + // + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck); + return true; +} + + +//=========================================================================== +// Remove all entries from a certain controller +//=========================================================================== +void lpc2xxx_can_accfilt_remove_all_ctrl_entries(lpc2xxx_can_info_t *info) +{ + cyg_uint32 accfilt_bck; // acceptance filter backup + cyg_uint16 i; + cyg_uint16 entries; + cyg_uint32 TableStartAddress = CAN_ACCFILT_SFF_SA; + lpc2xxx_accfilt_entry_t Entry; + cyg_uint8 channel_no = CAN_CHAN_NO_LUT(info); + cyg_uint16 entry_idx; + + // + // first step: disable acceptance filter and prepare it for modification + // + HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck); + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS); + + // + // now remove all entries for a certain controller + // + for (TableStartAddress = CAN_ACCFILT_SFF_SA; TableStartAddress < CAN_ACCFILT_ENDOFTABLE; TableStartAddress += 4) + { + entries = lpc2xxx_can_accfilt_get_table_entries(TableStartAddress); + entry_idx = 0; + for (i = 0; i < entries; ++i) + { + lpc2xxx_can_accfilt_get_entry(TableStartAddress, entry_idx, &Entry); + if (Entry.channel_no == channel_no) + { + lpc2xxx_can_accfilt_ram_remove_entry(TableStartAddress, entry_idx); + } + else + { + entry_idx++; + } + } // for (i = 0; i < entries; ++i) + } // for (TableStartAddress = CAN_ACCFILT_SFF_SA ... + + // + // finally restore the previous state of the acceptance filter + // + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck); +} +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + +#ifndef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Setup reception of all CAN identifiers +// If runtime acceptance filter configuration is not required then we simply +// setup the acceptance filter here to receive all CAN identifiers +//=========================================================================== +static void lpc2xxx_can_accfilt_simple_rx_all(void) +{ + cyg_uint32 regval; + + // + // First check if it is really necessary to setup filters. If end of table is + // != 0 then the acceptance filter is already setup properly + // + HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, regval); + if (regval) + { + return; + } + + cyg_uint32 accfilt_bck; // acceptance filter backup + cyg_uint8 i = 0; // loop counter + lsc_buf_t accfilt_entry; // std group entry +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + cyg_uint8 std_address = 0; // std group entry address +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + cyg_uint8 ext_address = lpc2xxx_global_can_info.init_cnt << 2; +#endif +#else + cyg_uint8 ext_address = 0; +#endif + + // + // first step: disable acceptance filter and prepare it for modification + // + HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck); + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS); + + // + // Write table start adresses - we use only standard group and extended filter + // group + // + HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, 0); + HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, 0); + HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, ext_address); + HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, ext_address); + + // + // Now loop through all active CAN channels and setup the acceptance filter for + // each channel to receive all standard and extended CAN identifiers + // + while (lpc2xxx_global_can_info.active_channels[i]) + { + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)lpc2xxx_global_can_info.active_channels[i++]->dev_priv; + cyg_uint8 channel_no = CAN_CHAN_NO_LUT(info); + +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + accfilt_entry.column.lower = (channel_no << 13) | (0x000 & ACCFILT_STD_ID_MASK); + accfilt_entry.column.upper = (channel_no << 13) | (0x7FF & ACCFILT_STD_ID_MASK); + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + std_address, accfilt_entry.dword); + std_address += sizeof(cyg_uint32); +#endif // CYGOPT_IO_CAN_STD_CAN_ID + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + accfilt_entry.dword = (channel_no << 29) | (0x00000000 & ACCFILT_EXT_ID_MASK); + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + ext_address, accfilt_entry.dword); + ext_address += sizeof(cyg_uint32); + accfilt_entry.dword = (channel_no << 29) | (0x1FFFFFFF & ACCFILT_EXT_ID_MASK); + HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + ext_address, accfilt_entry.dword); + ext_address += sizeof(cyg_uint32); +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + } // while (lpc2xxx_global_can_info.active_channels[i]) + + // + // finally store end of table value and restore the previous state of the + // acceptance filter + // + HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, ext_address); + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck); +} +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + +//=========================================================================== +// Reset acceptance filter to poweron defaults +//=========================================================================== +void lpc2xxx_can_accfilt_reset(void) +{ + cyg_uint32 accfilt_bck; // acceptance filter backup + // + // first step: disable acceptance filter and prepare it for modification + // + HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck); + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS); + + // + // Now write zero to all addresses of acceptance filter table + // + HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, 0); + HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, 0); + HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, 0); + HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, 0); + HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, 0); + + // + // finally restore the previous state of the acceptance filter + // + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck); +} + + +//=========================================================================== +// Dump content of acceptance filter lookup table +//=========================================================================== +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG +void lpc2xxx_can_accfilt_dbg_dump(void) +{ + cyg_uint32 sff_sa; + cyg_uint32 sff_grp_sa; + cyg_uint32 eff_sa; + cyg_uint32 eff_grp_sa; + cyg_uint32 end_of_table; + cyg_uint32 entry_address; + lsc_buf_t data; + + + HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, sff_sa); + HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa); + HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa); + HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa); + HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table); + + entry_address = sff_sa; + + // + // Print lookup table registers + // + diag_printf("\n\nDUMP CAN ACCEPTANCE FILTER REGISTERS\n"); + diag_printf("----------------------------------------\n"); + diag_printf("SFF_sa:\t\t0x%08x\n", sff_sa); + diag_printf("SFF_GRP_sa:\t0x%08x\n", sff_grp_sa); + diag_printf("EFF_sa:\t\t0x%08x\n", eff_sa); + diag_printf("EFF_GRP_sa:\t0x%08x\n", eff_grp_sa); + diag_printf("EOT:\t\t0x%08x\n", end_of_table); + + // + // Print table of standard identifiers + // + diag_printf("\n\nDUMP CAN LOOKUP TABLE RAM"); + diag_printf("\nSFF_sa\t\tcolumn_lower\tcolumn_upper\traw_data\n"); + diag_printf("----------------------------------------------------------\n"); + while (entry_address < sff_grp_sa) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, data.dword); + diag_printf("0x%04x:\t\t0x%x\t\t0x%x\t\t0x%x\n", entry_address, data.column.lower, data.column.upper, data.dword); + entry_address += sizeof(cyg_uint32); + } + + // + // Print table of standard identifier groups + // + diag_printf("\nSFF_GRP_sa\tcolumn_lower\tcolumn_upper\traw_data\n"); + diag_printf("----------------------------------------------------------\n"); + while (entry_address < eff_sa) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, data.dword); + diag_printf("0x%04x:\t\t0x%x\t\t0x%x\t\t0x%x\n", entry_address, data.column.lower, data.column.upper, data.dword); + entry_address += sizeof(cyg_uint32); + } + + // + // Print table of extended identifiers + // + diag_printf("\nEFF_sa\t\t-\t\t-\t\traw_data\n"); + diag_printf("----------------------------------------------------------\n"); + while (entry_address < eff_grp_sa) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, data.dword); + diag_printf("0x%04x:\t\t\t\t\t\t0x%x\n", entry_address, data.dword); + entry_address += sizeof(cyg_uint32); + } + + // + // Print table of extended identifier groups + // + diag_printf("\nEFF_GRP_sa\t-\t\t-\t\traw_data\n"); + diag_printf("----------------------------------------------------------\n"); + while (entry_address < end_of_table) + { + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, data.dword); + diag_printf("0x%04x:\t\t\t\t\t\t0x%x\n", entry_address, data.dword); + entry_address += sizeof(cyg_uint32); + } +} +#endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + +//=========================================================================== +// Dump content of acceptance filter lookup table +//=========================================================================== +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG +void lpc2xxx_can_reg_dump(struct cyg_devtab_entry* devtab_entry) +{ + can_channel *chan = (can_channel*)devtab_entry->priv; + cyg_uint32 reg_val; + CAN_DECLARE_INFO(chan); + + chan = chan; // avoid compiler warnings for unused variables + // + // Print table of extended identifier groups + // + diag_printf("\n\nCAN REGISTER DUMP\n"); + diag_printf("\nRegister\tValue\n"); + diag_printf("----------------------------------------------------------\n"); + HAL_READ_UINT32(CAN_CTRL_MOD(info), reg_val); + diag_printf("CANMOD\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_CMR(info), reg_val); + diag_printf("CANCMR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_GSR(info), reg_val); + diag_printf("CANGSR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_ICR(info), reg_val); + diag_printf("CANICR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_IER(info), reg_val); + diag_printf("CANIER\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_BTR(info), reg_val); + diag_printf("CANBTR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_EWL(info), reg_val); + diag_printf("CANEWL\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_SR(info), reg_val); + diag_printf("CANSR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_RFS(info), reg_val); + diag_printf("CANRFS\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_RID(info), reg_val); + diag_printf("CANRID\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_RDA(info), reg_val); + diag_printf("CANRDA\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CTRL_RDB(info), reg_val); + diag_printf("CANRDB\t\t0x%08x\n", reg_val); + + diag_printf("\n\nCAN CENTRAL REGISTER DUMP\n"); + diag_printf("\nRegister\tValue\n"); + diag_printf("----------------------------------------------------------\n"); + HAL_READ_UINT32(CAN_CENTRAL_TXSR, reg_val); + diag_printf("CANTxSR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CENTRAL_RXSR, reg_val); + diag_printf("CANRxSR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_CENTRAL_MSR, reg_val); + diag_printf("CANMSR\t\t0x%08x\n", reg_val); + + diag_printf("\n\nCAN ACCEPTANCE FILTER REGISTER DUMP\n"); + diag_printf("\nRegister\tValue\n"); + diag_printf("----------------------------------------------------------\n"); + HAL_READ_UINT32(CAN_ACCFILT_AFMR, reg_val); + diag_printf("AFMR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR, reg_val); + diag_printf("LUTERR\t\t0x%08x\n", reg_val); + HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR_ADDR, reg_val); + diag_printf("LUTERRADDR\t0x%08x\n", reg_val); +} +#endif // #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + +//--------------------------------------------------------------------------- +// EOF can_accfilt_lpc2xxx.c diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/src/can_lpc2xxx.c b/packages/devs/can/arm/lpc2xxx/v2_0/src/can_lpc2xxx.c new file mode 100644 index 00000000..e1bb926e --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/src/can_lpc2xxx.c @@ -0,0 +1,2204 @@ +//========================================================================== +// +// devs/can/arm/lpc2xxx/current/src/can_lpc2xxx.c +// +// CAN driver for LPC2xxx microcontrollers +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2003 Gary Thomas +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Uwe Kindler +// Contributors: Uwe Kindler +// Date: 2007-04-09 +// Purpose: Support LPC2xxx on-chip CAN moduls +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +//========================================================================== +// INCLUDES +//========================================================================== +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + + + + +//=========================================================================== +// DEFINES +//=========================================================================== +// +// Check if the macro HAL_LPC2XXX_GET_CAN_BR is provided +// +#ifndef HAL_LPC2XXX_GET_CAN_BR +#error "Macro HAL_LPC2XXX_GET_CAN_BR() missing" +#endif + +// +// Support debug output if this option is enabled in CDL file +// +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG +#define LPC2XXX_DBG_PRINT diag_printf +#else +#define LPC2XXX_DBG_PRINT( fmt, ... ) +#endif + + +//--------------------------------------------------------------------------- +// we define our own set of register bits in order to be independent from +// platform specific names +// + +//--------------------------------------------------------------------------- +// Memory map of CAN block +// +#define CAN_ACCFILT_RAM_BASE 0xE0038000 +#define CAN_ACCFILT_REG_BASE 0xE003C000 +#define CAN_CENTRAL_REG_BASE 0xE0040000 +#define CAN_CTRL_1_REG_BASE 0xE0044000 +#define CAN_CTRL_2_REG_BASE 0xE0048000 +#define CAN_CTRL_3_REG_BASE 0xE004C000 +#define CAN_CTRL_4_REG_BASE 0xE0050000 + + +//--------------------------------------------------------------------------- +// CAN Acceptance Filter register layout +// +#define CAN_ACCFILT_AFMR (CAN_ACCFILT_REG_BASE + 0x0000) +#define CAN_ACCFILT_SFF_SA (CAN_ACCFILT_REG_BASE + 0x0004) +#define CAN_ACCFILT_SFF_GRP_SA (CAN_ACCFILT_REG_BASE + 0x0008) +#define CAN_ACCFILT_EFF_SA (CAN_ACCFILT_REG_BASE + 0x000C) +#define CAN_ACCFILT_EFF_GRP_SA (CAN_ACCFILT_REG_BASE + 0x0010) +#define CAN_ACCFILT_ENDOFTABLE (CAN_ACCFILT_REG_BASE + 0x0014) +#define CAN_ACCFILT_LUT_ERR_ADDR (CAN_ACCFILT_REG_BASE + 0x0018) +#define CAN_ACCFILT_LUT_ERR (CAN_ACCFILT_REG_BASE + 0x001C) + +//--------------------------------------------------------------------------- +// CAN_ACCFILT_AFMR Bits +// +#define AFMR_OFF 0x00000001 // 1 = Acceptance filter is not operational +#define AFMR_BYPASS 0x00000002 // 1 = all Rx messages are accepted on enabled CAN controllers. +#define AFMR_FULLCAN 0x00000004 // 1 = FullCAN mode +#define AFMR_ON 0x00000000 // Acceptance filter on +#define ACCFILT_RAM_SIZE 2048 // size of acceptance filter ram + + +//--------------------------------------------------------------------------- +// Acceptance filter tool macros +// +#define ACCFILT_STD_ID_MASK 0x7FF +#define ACCFILT_EXT_ID_MASK 0x1FFFFFFF +#define ACCFILT_STD_DIS 0x1000 +#define ACCFILT_STD_CTRL_MASK 0xE000 +#define ACCFILT_EXT_CTRL_MASK 0xE0000000 +#define ACCFILT_STD_GET_CTRL(_entry_) (((_entry_) >> 13) & 0x7) +#define ACCFILT_STD_GET_CTRL_LOWER(_entry_) (((_entry_) >> 29) & 0x7) +#define ACCFILT_STD_GET_CTRL_UPPER(_entry_) (((_entry_) >> 13) & 0x7) +#define ACCFILT_STD_GET_ID(_entry_) ((_entry_) & ACCFILT_STD_ID_MASK) +#define ACCFILT_EXT_GET_ID(_entry_) ((_entry_) & ACCFILT_EXT_ID_MASK) +#define ACCFILT_EXT_GET_CTRL(_entry_) (((_entry_) >> 29) & 0x7) +#define ACCFILT_EXT_SET_CTRL(_entry_, _ctrl_) ((_entry_ & 0xE0000000) | ((_ctrl_) << 29)) + + +//--------------------------------------------------------------------------- +// CAN Central CAN Registers register layout +// +#define CAN_CENTRAL_TXSR (CAN_CENTRAL_REG_BASE + 0x0000) +#define CAN_CENTRAL_RXSR (CAN_CENTRAL_REG_BASE + 0x0004) +#define CAN_CENTRAL_MSR (CAN_CENTRAL_REG_BASE + 0x0008) + + +//--------------------------------------------------------------------------- +// CAN Controller register offsets +// Registers are offsets from base CAN module control register +// +#define CANREG_MOD 0x0000 +#define CANREG_CMR 0x0004 +#define CANREG_GSR 0x0008 +#define CANREG_ICR 0x000C +#define CANREG_IER 0x0010 +#define CANREG_BTR 0x0014 +#define CANREG_EWL 0x0018 +#define CANREG_SR 0x001C +#define CANREG_RFS 0x0020 +#define CANREG_RID 0x0024 +#define CANREG_RDA 0x0028 +#define CANREG_RDB 0x002C +#define CANREG_TFI1 0x0030 +#define CANREG_TID1 0x0034 +#define CANREG_TDA1 0x0038 +#define CANREG_TDB1 0x003C +#define CANREG_TFI2 0x0040 +#define CANREG_TID2 0x0044 +#define CANREG_TDA2 0x0048 +#define CANREG_TDB2 0x004C +#define CANREG_TFI3 0x0050 +#define CANREG_TID3 0x0054 +#define CANREG_TDA3 0x0058 +#define CANREG_TDB3 0x005C + + +//--------------------------------------------------------------------------- +// CAN Controller register layout +// +#define CAN_CTRL_MOD(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_MOD) +#define CAN_CTRL_CMR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_CMR) +#define CAN_CTRL_GSR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_GSR) +#define CAN_CTRL_ICR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_ICR) +#define CAN_CTRL_IER(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_IER) +#define CAN_CTRL_BTR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_BTR) +#define CAN_CTRL_EWL(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_EWL) +#define CAN_CTRL_SR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_SR) +#define CAN_CTRL_RFS(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RFS) +#define CAN_CTRL_RID(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RID) +#define CAN_CTRL_RDA(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RDA) +#define CAN_CTRL_RDB(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RDB) +#define CAN_CTRL_TFI1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI1) +#define CAN_CTRL_TID1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID1) +#define CAN_CTRL_TDA1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA1) +#define CAN_CTRL_TDB1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB1) +#define CAN_CTRL_TFI2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI2) +#define CAN_CTRL_TID2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID2) +#define CAN_CTRL_TDA2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA2) +#define CAN_CTRL_TDB2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB2) +#define CAN_CTRL_TFI3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI3) +#define CAN_CTRL_TID3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID3) +#define CAN_CTRL_TDA3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA3) +#define CAN_CTRL_TDB3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB3) + + +//--------------------------------------------------------------------------- +// CAN_CTRL_ICR register bits +// +#define ICR_RX 0x00000001 +#define ICR_TX1 0x00000002 +#define ICR_ERR_WARN 0x00000004 +#define ICR_DATA_OVR 0x00000008 +#define ICR_WAKE_UP 0x00000010 +#define ICR_ERR_PASSIVE 0x00000020 +#define ICR_ARBITR_LOST 0x00000040 +#define ICR_BUS_ERR 0x00000080 +#define ICR_ID_READY 0x00000100 +#define ICR_TX2 0x00000200 +#define ICR_TX3 0x00000400 +#define ICR_LUT_ERR 0x00000800 +#define ICR_GET_ERRBIT(_icr_) (((_icr_) >> 16) & 0x1F) +#define ICR_ERR_DIRECTION 0x00200000 +#define ICR_GET_ERRCODE(_icr_) (((_icr_) >> 22) & 0x03) +#define ICR_GET_ALCBIT(_icr_) (((_icr_) >> 24) & 0x1F) + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_ALIE +#define CAN_ALL_ERR_INT (ICR_ERR_PASSIVE | ICR_ARBITR_LOST | ICR_BUS_ERR | ICR_ERR_WARN) +#else +#define CAN_ALL_ERR_INT (ICR_ERR_PASSIVE | ICR_BUS_ERR | ICR_ERR_WARN) +#endif +#define CAN_MISC_INT (CAN_ALL_ERR_INT | ICR_WAKE_UP) + + +//--------------------------------------------------------------------------- +// CAN_CTRL_ICR register bits +// +#define ICR_ERRCODE_BIT_ERR 0x00 +#define ICR_ERRCODE_FORM_ERR 0x01 +#define ICR_ERRCODE_STUFF_ERR 0x02 +#define ICR_ERRCODE_OTHER_ERR 0x03 + + +//--------------------------------------------------------------------------- +// CAN_CTRL_RFS register bits +// +#define RFS_ACCFILT_INDEX_MASK 0x000003FF +#define RFS_RECEIVED_IN_BYPASS_MODE 0x00000400 +#define RFS_DLC_MASK 0x000F0000 +#define RFS_RTR 0x40000000 +#define RFS_EXT 0x80000000 +#define RFS_GET_DLC(_regval_) (((_regval_) >> 16) & 0xF) + +//--------------------------------------------------------------------------- +// CAN_CTRL_CMR register bits +// +#define CMR_TX_REQ 0x00000001 +#define CMR_TX_ABORT 0x00000002 +#define CMR_RX_RELEASE_BUF 0x00000004 +#define CMR_CLEAR_DATA_OVR 0x00000008 +#define CMR_SELF_RX_REQ 0x00000010 +#define CMR_SEND_TX_BUF1 0x00000020 +#define CMR_SEND_TX_BUF2 0x00000040 +#define CMR_SEND_TX_BUF3 0x00000080 + + +//--------------------------------------------------------------------------- +// CAN_CTRL_TFI register bits +// +#define TFI_PRIO_MASK 0x000000FF +#define TFI_DLC_MASK 0x000F0000 +#define TFI_DLC_RTR 0x40000000 +#define TFI_DLC_EXT 0x80000000 + + +//--------------------------------------------------------------------------- +// CAN_CTRL_MOD register bits +// +#define CANMOD_OPERATIONAL 0x00000000 +#define CANMOD_RESET 0x00000001 +#define CANMOD_LISTEN_ONLY 0x00000002 +#define CANMOD_SELF_TEST 0x00000004 +#define CANMOD_TX_BUF_CFG 0x00000008 +#define CANMOD_SLEEP 0x00000010 +#define CANMOD_REV_POLARITY 0x00000020 +#define CANMOD_TEST 0x00000040 + + +//--------------------------------------------------------------------------- +// CAN_CTRL_IER register bits +// +#define IER_RX 0x00000001 +#define IER_TX1 0x00000002 +#define IER_ERR_WARN 0x00000004 +#define IER_DATA_OVR 0x00000008 +#define IER_WAKE_UP 0x00000010 +#define IER_ERR_PASSIVE 0x00000020 +#define IER_ARBITR_LOST 0x00000040 +#define IER_BUS_ERR 0x00000080 +#define IER_ID_READY 0x00000100 +#define IER_TX2 0x00000200 +#define IER_TX3 0x00000400 + + +//--------------------------------------------------------------------------- +// CAN_CTRL_GSR register bits +// +#define GSR_RX_MSG_AVAILABLE 0x00000001 +#define GSR_DATA_OVR 0x00000002 +#define GSR_TX_NOT_PENDING 0x00000004 +#define GSR_ALL_TX_COMPLETE 0x00000008 +#define GSR_RECEIVING_ACTIVE 0x00000010 +#define GSR_SENDING_ACTIVE 0x00000020 +#define GSR_ERR 0x00000040 +#define GSR_BUS_OFF 0x00000080 +#define GSR_RXERR_CNT(_reg_) (((_reg_) >> 16) & 0xFF) +#define GSR_TXERR_CNT(_reg_) (((_reg_) >> 24) & 0xFF) + + +//--------------------------------------------------------------------------- +// CAN_CTRL_SR register bits +// +#define SR_RX_MSG_AVAILABLE 0x01 +#define SR_DATA_OVR 0x02 +#define SR_TX_BUF_WRITE_OK 0x04 // TBS1, TBS2, TBS3 (Bit 2, 10, 18) +#define SR_TX_COMPLETE 0x08 // TCS1, TCS2, TCS3 (Bit 3, 11, 19) +#define SR_RECEIVING_ACTIVE 0x10 +#define SR_SENDING_ACTIVE 0x20 // TS1, TS2, TS3 (5, 13, 21) +#define SR_ERR 0x40 +#define SR_BUS_OFF 0x80 + + +//--------------------------------------------------------------------------- +// Optimize for the case of a single CAN channel, while still allowing +// multiple channels. +// +#if CYGINT_IO_CAN_CHANNELS == 1 +#define CAN_CTRL_BASE(_extra_) CAN_CTRL_SINGLETON_BASE +#define CAN_ISRVEC(_extra_) CAN_SINGLETON_ISRVEC +#define CAN_CHAN_NO(_extra_) CAN_SINGLETON_CHAN_NO +#define CAN_DECLARE_INFO(_chan_) +#define CAN_DECLARE_CHAN(_data_) +#else +#define CAN_CTRL_BASE(_extra_) ((_extra_)->base) +#define CAN_ISRVEC(_extra_) ((_extra_)->isrvec) +#define CAN_CHAN_NO(_extra_) ((_extra_)->chan_no) +#define CAN_DECLARE_INFO(_chan_) lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; +#define CAN_DECLARE_CHAN(_data_) can_channel *chan = (can_channel *)data; +#endif // CYGINT_IO_CAN_CHANNELS == 1 + + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN0_ACCFILT_STARTUP_CFG_RX_ALL +#define CAN0_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL +#else +#define CAN0_FLAG_STARTUP_ACCFILT_SETUP 0x00 +#endif + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN1_ACCFILT_STARTUP_CFG_RX_ALL +#define CAN1_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL +#else +#define CAN1_FLAG_STARTUP_ACCFILT_SETUP 0x00 +#endif + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN2_ACCFILT_STARTUP_CFG_RX_ALL +#define CAN2_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL +#else +#define CAN2_FLAG_STARTUP_ACCFILT_SETUP 0x00 +#endif + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN3_ACCFILT_STARTUP_CFG_RX_ALL +#define CAN3_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL +#else +#define CAN3_FLAG_STARTUP_ACCFILT_SETUP 0x00 +#endif + + +//=========================================================================== +// DATA TYPES +//=========================================================================== +// +// Structure stores LPC2xxx CAN channel related stuff +// + +// If we use Self Reception Request command instead of the Transmission Request +// we must add last transmit message id in order to reject it in rx_ISR +// There are two last_tx_id because tx interrupt (and so transmission of next +// message) happens before rx interrupt (which uses last_tx_id for rejecting)) + +// Format of last_tx_id: +// (bits: 28:0-ID, 29-Validation, 30-RTR, 31-EXT) +// if last_tx_id == 0xFFFFFFFF (Validation == 1) then last id is not valid +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION + #define LPC2XXX_CAN_INFO_LAST_TX_ID_IDMASK 0x1FFFFFFF + #define LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK 0xC0000000 + #define LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID 0xFFFFFFFF + + #define LPC2XXX_CAN_INFO_LAST_TX_ID_DECL cyg_uint8 last_tx_index; \ + cyg_uint32 last_tx_id[2]; + #define LPC2XXX_CAN_INFO_LAST_TX_ID_INIT last_tx_index : 0, \ + last_tx_id : {LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID, LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID}, +#else + #define LPC2XXX_CAN_INFO_LAST_TX_ID_DECL + #define LPC2XXX_CAN_INFO_LAST_TX_ID_INIT +#endif + +typedef struct lpc2xxx_can_info_st +{ +// +// Newer LPC2xxx variants like the LPC2468 do not support per channel +// interrupts. They provide only one single interrupt vector for all +// CAN interrupts +// +#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + cyg_interrupt tx_interrupt; + cyg_handle_t tx_interrupt_handle; + cyg_uint8 tx_interrupt_priority; + cyg_interrupt rx_interrupt; + cyg_handle_t rx_interrupt_handle; + cyg_uint8 rx_interrupt_priority; +#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + cyg_can_state state; // state of CAN controller + cyg_uint8 flags; // flags indicating several states + LPC2XXX_CAN_INFO_LAST_TX_ID_DECL // last transmitted messages ids +#if CYGINT_IO_CAN_CHANNELS > 1 + cyg_uint32 base; // Per-bus h/w details +#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + cyg_uint8 isrvec; // ISR vector (peripheral id) +#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + cyg_uint8 chan_no; // number of CAN channel +#endif // CYGINT_IO_CAN_CHANNELS > 1 +} lpc2xxx_can_info_t; + + +#define INFO_FLAG_RX_ALL 0x01 // this bit indicates that channel receives all CAN messages - no filtering active +#define INFO_FLAG_STARTUP_RX_ALL 0x02 // this bit indicates filter state at startup + + +// +// lpc2xxx info initialisation +// +#define LPC2XXX_CTRL_NOT_INITIALIZED 0xFF + +#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY +#if CYGINT_IO_CAN_CHANNELS > 1 +#define LPC2XXX_CAN_INFO(_l, _base, _isrvec, _chan_no_, _tx_priority, _rx_priority, _flags) \ +lpc2xxx_can_info_t _l = { \ + state : LPC2XXX_CTRL_NOT_INITIALIZED, \ + base : (_base), \ + isrvec : (_isrvec), \ + chan_no : (_chan_no_), \ + tx_interrupt_priority : (_tx_priority), \ + rx_interrupt_priority : (_rx_priority), \ + flags : (_flags), \ + LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \ +}; +#else // CYGINT_IO_CAN_CHANNELS == 1 +#define LPC2XXX_CAN_INFO(_l, _tx_priority, _rx_priority, _flags) \ +lpc2xxx_can_info_t _l = { \ + state : CYGNUM_CAN_STATE_STOPPED, \ + tx_interrupt_priority : (_tx_priority), \ + rx_interrupt_priority : (_rx_priority), \ + flags : (_flags), \ + LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \ +}; +#endif // CYGINT_IO_CAN_CHANNELS == 1 +#else // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY +// +// Newer devices support only one global CAN interrupt. We do not need +// per channel interrupt data an ignore the values during initialisation +// +#if CYGINT_IO_CAN_CHANNELS > 1 +#define LPC2XXX_CAN_INFO(_l, _base, _isrvec, _chan_no_, _tx_priority, _rx_priority, _flags) \ +lpc2xxx_can_info_t _l = { \ + state : LPC2XXX_CTRL_NOT_INITIALIZED, \ + base : (_base), \ + chan_no : (_chan_no_), \ + flags : (_flags), \ + LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \ +}; +#else // CYGINT_IO_CAN_CHANNELS == 1 +#define LPC2XXX_CAN_INFO(_l, _tx_priority, _rx_priority, _flags) \ +lpc2xxx_can_info_t _l = { \ + state : CYGNUM_CAN_STATE_STOPPED, \ + flags : (_flags), \ + LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \ +}; +#endif // CYGINT_IO_CAN_CHANNELS == 1 + +// +// The following defines are only dummies required for proper +// initialisation of can channel data structures +// +#define CYGNUM_HAL_INTERRUPT_CAN1_TX +#define CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY +#define CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY +#define CYGNUM_HAL_INTERRUPT_CAN2_TX +#define CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY +#define CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY +#define CYGNUM_HAL_INTERRUPT_CAN3_TX +#define CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY +#define CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY +#define CYGNUM_HAL_INTERRUPT_CAN4_TX +#define CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY +#define CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY +#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + + +// +// Acceptance filter data +// +typedef struct lpc2xxx_global_can_info_st +{ + cyg_interrupt interrupt; // common CAN interrupt + cyg_handle_t interrupt_handle; // common CAN interrupt handle + cyg_uint16 free_filters; // number of free message filter +#if CYGINT_IO_CAN_CHANNELS > 1 // optimize for single channel + cyg_uint8 init_cnt; // counts number of initialized channels + can_channel* active_channels[5]; // stores pointers to active channels - the last entry is just a delimiter +#else // CYGINT_IO_CAN_CHANNELS > 1 + can_channel* active_channels[1]; // optimize for one single channel +#endif // CYGINT_IO_CAN_CHANNELS > 1 +} lpc2xxx_global_can_info_t; + + +#if CYGINT_IO_CAN_CHANNELS > 1 +#define LPC2XXX_GET_CAN_CHANNEL(_can_info_, _chan_no_) ((can_channel*)(_can_info_).active_channels[_chan_no_]) +#else +#define LPC2XXX_GET_CAN_CHANNEL(_can_info_, _chan_no_) ((can_channel*)(_can_info_).active_channels[0]) +#endif + +// +// The number of available message filters depends on the size of the +// acceptance filter RAM and on the size of one entry. The size of +// one entry is 4 byte (standard ID only 2 byte, extended groups 8 byte) +// +#define ACCFILT_COMMON_ENTRY_SIZE 4 +#define LPC2XXX_CAN_MSG_FILTERS_MAX (ACCFILT_RAM_SIZE / ACCFILT_COMMON_ENTRY_SIZE) +lpc2xxx_global_can_info_t lpc2xxx_global_can_info = +{ + .free_filters = LPC2XXX_CAN_MSG_FILTERS_MAX, +#if CYGINT_IO_CAN_CHANNELS > 1 // optimize for single channel + .init_cnt = 0, + .active_channels = {0, 0, 0, 0, 0}, +#endif // #if CYGINT_IO_CAN_CHANNELS > 1 +}; + + + +// +// Data type for access of single bytes/words of an dword value +// +typedef union lsc_buf_u +{ + cyg_uint8 bytes[4]; + struct + { + cyg_uint16 low; + cyg_uint16 high; + } words; + + struct + { + cyg_uint16 upper; // uppper column of acceptance filter ram + cyg_uint16 lower; // lower column of acceptance filter ram + } column; + + cyg_uint32 dword; +} lsc_buf_t; + + +//=========================================================================== +// GLOBAL DATA +//=========================================================================== +#if CYGINT_IO_CAN_CHANNELS > 1 +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0 +LPC2XXX_CAN_INFO(lpc2xxx_can0_info, + CAN_CTRL_1_REG_BASE, + CYGNUM_HAL_INTERRUPT_CAN1_TX, + 0, + CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY, + CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY, + CAN0_FLAG_STARTUP_ACCFILT_SETUP); +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1 +LPC2XXX_CAN_INFO(lpc2xxx_can1_info, + CAN_CTRL_2_REG_BASE, + CYGNUM_HAL_INTERRUPT_CAN2_TX, + 1, + CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY, + CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY, + CAN1_FLAG_STARTUP_ACCFILT_SETUP); +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2 +LPC2XXX_CAN_INFO(lpc2xxx_can2_info, + CAN_CTRL_3_REG_BASE, + CYGNUM_HAL_INTERRUPT_CAN3_TX, + 2, + CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY, + CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY, + CAN2_FLAG_STARTUP_ACCFILT_SETUP); +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3 +LPC2XXX_CAN_INFO(lpc2xxx_can3_info, + CAN_CTRL_4_REG_BASE, + CYGNUM_HAL_INTERRUPT_CAN4_TX, + 3, + CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY, + CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY, + CAN3_FLAG_STARTUP_ACCFILT_SETUP); +#endif +#else // CYGINT_IO_CAN_CHANNELS == 1 +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0 +LPC2XXX_CAN_INFO(lpc2xxx_can0_info, + CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY, + CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY, + CAN0_FLAG_STARTUP_ACCFILT_SETUP); +#define CAN_CTRL_SINGLETON_BASE CAN_CTRL_1_REG_BASE +#define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN1_TX +#define CAN_SINGLETON_CHAN_NO 0 +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1 +LPC2XXX_CAN_INFO(lpc2xxx_can1_info, + CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY, + CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY, + CAN1_FLAG_STARTUP_ACCFILT_SETUP); +#define CAN_CTRL_SINGLETON_BASE CAN_CTRL_2_REG_BASE +#define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN2_TX +#define CAN_SINGLETON_CHAN_NO 1 +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2 +LPC2XXX_CAN_INFO(lpc2xxx_can2_info, + CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY, + CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY, + CAN2_FLAG_STARTUP_ACCFILT_SETUP); +#define CAN_CTRL_SINGLETON_BASE CAN_CTRL_3_REG_BASE +#define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN3_TX +#define CAN_SINGLETON_CHAN_NO 2 +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3 +LPC2XXX_CAN_INFO(lpc2xxx_can3_info, + CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY, + CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY, + CAN3_FLAG_STARTUP_ACCFILT_SETUP); +#define CAN_CTRL_SINGLETON_BASE CAN_CTRL_4_REG_BASE +#define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN4_TX +#define CAN_SINGLETON_CHAN_NO 3 +#endif + +#endif // #if CYGINT_IO_CAN_CHANNELS > 1 + + +//=========================================================================== +// PROTOTYPES +//=========================================================================== + +//-------------------------------------------------------------------------- +// Device driver interface functions +// +static bool lpc2xxx_can_init(struct cyg_devtab_entry* devtab_entry); +static Cyg_ErrNo lpc2xxx_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name); +static Cyg_ErrNo lpc2xxx_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len); +static Cyg_ErrNo lpc2xxx_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len); +static bool lpc2xxx_can_putmsg(can_channel *priv, CYG_CAN_MSG_T *pmsg, void *pdata); +static bool lpc2xxx_can_getevent(can_channel *priv, CYG_CAN_EVENT_T *pevent, void *pdata); +static void lpc2xxx_can_start_xmit(can_channel* chan); +static void lpc2xxx_can_stop_xmit(can_channel* chan); + + +//-------------------------------------------------------------------------- +// ISRs and DSRs +// +#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY +static cyg_uint32 lpc2xxx_can_tx_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void lpc2xxx_can_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); +static cyg_uint32 lpc2xxx_can_rx_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void lpc2xxx_can_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); +#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY +static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); + + +//-------------------------------------------------------------------------- +// Private utility functions +// +static bool lpc2xxx_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init); +static bool lpc2xxx_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate); +static Cyg_ErrNo lpc2xxx_enter_lowpower_mode(can_channel *chan); +static void lpc2xxx_start_module(can_channel *chan); +static cyg_can_state lpc2xxx_get_state(lpc2xxx_can_info_t *info); +static void lpc2xxx_set_state(lpc2xxx_can_info_t *info, cyg_can_state state); + + +//-------------------------------------------------------------------------- +// Message box configuration +// +static void lpc2xxx_can_config_rx_all(can_channel *chan); +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +static void lpc2xxx_can_config_rx_none(can_channel *chan); +static bool lpc2xxx_can_add_rx_filter(lpc2xxx_can_info_t *info, cyg_can_filter *filter); +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + +#include "can_accfilt_lpc2xxx.c" + +//=========================================================================== +// GENERIC CAN IO DATA INITIALISATION +//=========================================================================== +CAN_LOWLEVEL_FUNS(lpc2xxx_can_lowlevel_funs, + lpc2xxx_can_putmsg, + lpc2xxx_can_getevent, + lpc2xxx_can_get_config, + lpc2xxx_can_set_config, + lpc2xxx_can_start_xmit, + lpc2xxx_can_stop_xmit + ); + + +//--------------------------------------------------------------------------- +// CAN channel 0 +// +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0 +CYG_CAN_EVENT_T lpc2xxx_can0_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_RX]; // buffer for RX can events +CYG_CAN_MSG_T lpc2xxx_can0_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_TX]; // buffer for TX can messages + + +CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can0_chan, + lpc2xxx_can_lowlevel_funs, + lpc2xxx_can0_info, + CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN0_KBAUD), + lpc2xxx_can0_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_TX, + lpc2xxx_can0_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_RX + ); + + +DEVTAB_ENTRY(lpc2xxx_can0_devtab, + CYGPKG_DEVS_CAN_LPC2XXX_CAN0_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_can_devio, + lpc2xxx_can_init, + lpc2xxx_can_lookup, // CAN driver may need initializing + &lpc2xxx_can0_chan + ); +#endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN0 + + +//--------------------------------------------------------------------------- +// CAN channel 1 +// +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1 +CYG_CAN_EVENT_T lpc2xxx_can1_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_RX]; // buffer for RX can events +CYG_CAN_MSG_T lpc2xxx_can1_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_TX]; // buffer for TX can messages + + +CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can1_chan, + lpc2xxx_can_lowlevel_funs, + lpc2xxx_can1_info, + CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN1_KBAUD), + lpc2xxx_can1_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_TX, + lpc2xxx_can1_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_RX + ); + + +DEVTAB_ENTRY(lpc2xxx_can1_devtab, + CYGPKG_DEVS_CAN_LPC2XXX_CAN1_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_can_devio, + lpc2xxx_can_init, + lpc2xxx_can_lookup, // CAN driver may need initializing + &lpc2xxx_can1_chan + ); +#endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN1 + + +//--------------------------------------------------------------------------- +// CAN channel 2 +// +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2 +CYG_CAN_EVENT_T lpc2xxx_can2_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_RX]; // buffer for RX can events +CYG_CAN_MSG_T lpc2xxx_can2_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_TX]; // buffer for TX can messages + + +CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can2_chan, + lpc2xxx_can_lowlevel_funs, + lpc2xxx_can2_info, + CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN2_KBAUD), + lpc2xxx_can2_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_TX, + lpc2xxx_can2_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_RX + ); + + +DEVTAB_ENTRY(lpc2xxx_can2_devtab, + CYGPKG_DEVS_CAN_LPC2XXX_CAN2_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_can_devio, + lpc2xxx_can_init, + lpc2xxx_can_lookup, // CAN driver may need initializing + &lpc2xxx_can2_chan + ); +#endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN2 + + +//--------------------------------------------------------------------------- +// CAN channel 3 +// +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3 +CYG_CAN_EVENT_T lpc2xxx_can3_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_RX]; // buffer for RX can events +CYG_CAN_MSG_T lpc2xxx_can3_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_TX]; // buffer for TX can messages + + +CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can3_chan, + lpc2xxx_can_lowlevel_funs, + lpc2xxx_can3_info, + CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN3_KBAUD), + lpc2xxx_can3_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_TX, + lpc2xxx_can3_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_RX + ); + + +DEVTAB_ENTRY(lpc2xxx_can3_devtab, + CYGPKG_DEVS_CAN_LPC2XXX_CAN3_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_can_devio, + lpc2xxx_can_init, + lpc2xxx_can_lookup, // CAN driver may need initializing + &lpc2xxx_can3_chan + ); +#endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN3 + + +//=========================================================================== +// IMPLEMENTATION +//=========================================================================== + + + +//=========================================================================== +/// First initialisation and reset of CAN modul. +//=========================================================================== +static bool lpc2xxx_can_init(struct cyg_devtab_entry* devtab_entry) +{ + can_channel *chan = (can_channel*)devtab_entry->priv; + bool res; + +#ifdef CYGDBG_IO_INIT + diag_printf("LPC2XXX CAN init\n"); +#endif + + // + // Newer LPC2xxx variants do not support individual interrupt + // sources for CAN on chip peripherals + // +#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + // + // Create TX interrupt + // + cyg_drv_interrupt_create(CAN_ISRVEC(info), + info->tx_interrupt_priority, + (cyg_addrword_t)chan, // Data item passed to interrupt handler + lpc2xxx_can_tx_ISR, + lpc2xxx_can_tx_DSR, + &info->tx_interrupt_handle, + &info->tx_interrupt); + cyg_drv_interrupt_attach(info->tx_interrupt_handle); + cyg_drv_interrupt_unmask(CAN_ISRVEC(info)); + + // + // Create RX interrupt + // + cyg_drv_interrupt_create(CAN_ISRVEC(info) + 6, + info->rx_interrupt_priority, + (cyg_addrword_t)chan, // Data item passed to interrupt handler + lpc2xxx_can_rx_ISR, + lpc2xxx_can_rx_DSR, + &info->rx_interrupt_handle, + &info->rx_interrupt); + cyg_drv_interrupt_attach(info->rx_interrupt_handle); + cyg_drv_interrupt_unmask(CAN_ISRVEC(info) + 6); +#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + + // + // Now create and enable global CAN interrupt. This interrupt is + // global for all channels and so we need to call it only one times - + // when the first channel is initialized + // +#if CYGINT_IO_CAN_CHANNELS > 1 + if (!lpc2xxx_global_can_info.init_cnt) +#endif // #if CYGINT_IO_CAN_CHANNELS > 1 + { + // + // Create err interrupt + // + cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_CAN, +#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + CYGNUM_DEVS_CAN_LPC2XXX_ERR_INT_PRIORITY, +#else // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY, +#endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + 0, // Data item passed to interrupt handler + lpc2xxx_can_ISR, + lpc2xxx_can_DSR, + &lpc2xxx_global_can_info.interrupt_handle, + &lpc2xxx_global_can_info.interrupt); + cyg_drv_interrupt_attach(lpc2xxx_global_can_info.interrupt_handle); + cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_CAN); + } + + res = lpc2xxx_can_config_channel(chan, &chan->config, true); +#if CYGINT_IO_CAN_CHANNELS > 1 + lpc2xxx_global_can_info.active_channels[lpc2xxx_global_can_info.init_cnt++] = chan; +#else // CYGINT_IO_CAN_CHANNELS > 1 + lpc2xxx_global_can_info.active_channels[0] = chan; +#endif + return res; +} + + +//=========================================================================== +// Configure can channel +//=========================================================================== +static bool lpc2xxx_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init) +{ + CAN_DECLARE_INFO(chan); + bool res = true; + + if (init) + { + // + // In case platform needs extra initialization (i.e. setup of + // CAN transceivers) it should implement this macro + // +#ifdef CYGPRI_IO_CAN_LPC2XXX_PLF_INIT_HOOK + CYGPRI_IO_CAN_LPC2XXX_PLF_INIT_HOOK(chan, config); +#endif + + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF); // Acceptance Filter Mode Register = off + HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET); // Go into reset mode + HAL_WRITE_UINT32(CAN_CTRL_IER(info), 0); // disable all interrupts + HAL_WRITE_UINT32(CAN_CTRL_GSR(info), 0); // Clear Status register - clears error counters + + // + // Perform platform/variant specific initialisation here. + // The variant/ platform should setup the pin configuration to support + // CAN here + // + HAL_LPC2XXX_INIT_CAN(CAN_CHAN_NO(info)); + + // + // If this is the first channel to initialize then we reset the CAN + // registers and setup the CAN I/O pins + // +#if CYGINT_IO_CAN_CHANNELS > 1 + if (!lpc2xxx_global_can_info.init_cnt) +#endif // #if CYGINT_IO_CAN_CHANNELS > 1 + { + lpc2xxx_can_accfilt_reset(); + } + } // if (init) + + res = lpc2xxx_can_set_baud(chan, &config->baud); // set baudrate + // $$$$ enable receive interrupt? + HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_OPERATIONAL); // enter normal operating mode + + // + // store new config values + // + if (config != &chan->config) + { + chan->config = *config; + } + + return res; +} + + +//=========================================================================== +// Set baudrate of certain can channel +//=========================================================================== +static bool lpc2xxx_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate) +{ + bool res = true; + cyg_uint32 canbtr; + cyg_uint32 canmod; + CAN_DECLARE_INFO(chan); + + // + // Get bit timings from HAL because bit timings depend on sysclock + // If the macro fills the canbtr value with 0 then the baudrate + // is not supported and the function returns false + // + HAL_LPC2XXX_GET_CAN_BR(*baudrate, canbtr); + if (0 == canbtr) + { + return false; + } + + // + // Any modificatons to the baudrate register must be done while CAN + // module is in reset mode. So we first set the CAN module in reset + // mode, then we set baudrate and then we restore content of CANMOD + // register + // + HAL_READ_UINT32(CAN_CTRL_MOD(info), canmod); // backup canmod register + HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET); // Go into reset mode + HAL_WRITE_UINT32(CAN_CTRL_BTR(info), canbtr); // write baudrate value + HAL_WRITE_UINT32(CAN_CTRL_MOD(info), canmod); // restore previous value + + return res; +} + + +//=========================================================================== +// Lookup the device and return its handle +//=========================================================================== +static Cyg_ErrNo lpc2xxx_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name) +{ + can_channel* chan = (can_channel*) (*tab)->priv; + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + cyg_uint32 regval; + + chan->callbacks->can_init(chan); + + // + // If runtime acceptance filter configuration is supported then we only + // configure RX ALL if the user selected the RX ALL setup in config utility + // +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + if (info->flags & INFO_FLAG_STARTUP_RX_ALL) +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + { + lpc2xxx_can_config_rx_all(chan); + } + + HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_ON); // Activate acceptance filter + HAL_READ_UINT32(CAN_CTRL_IER(info), regval); + regval = regval | IER_RX | CAN_MISC_INT; // enable all interrupts + HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval); + + return ENOERR; +} + + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Setup LPC2XXX CAN module in a state where all message boxes are disabled +// After this call it is possible to add single message buffers and filters +//=========================================================================== +static void lpc2xxx_can_config_rx_none(can_channel *chan) +{ + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + + // + // Remove all acceptance filters + // $$$$ maybe we should also abort any pending transfers and + // disable receive interrupts ? + // + lpc2xxx_can_accfilt_remove_all_ctrl_entries(info); + info->flags &= ~INFO_FLAG_RX_ALL; +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + lpc2xxx_can_accfilt_dbg_dump(); +#endif +} + + +//=========================================================================== +// Add one single message filter to acceptance filter +//=========================================================================== +static bool lpc2xxx_can_add_rx_filter(lpc2xxx_can_info_t *info, cyg_can_filter *filter) +{ + bool res; + + res = lpc2xxx_can_accfilt_add(info, filter->msg.id, 0, filter->msg.ext); + if (!res) + { + filter->handle = CYGNUM_CAN_MSGBUF_NA; + } +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + lpc2xxx_can_accfilt_dbg_dump(); +#endif + return res; +} +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Configure message buffers +//=========================================================================== +static Cyg_ErrNo lpc2xxx_can_config_msgbuf(can_channel *chan, const void* buf, cyg_uint32* len) +{ + Cyg_ErrNo res = ENOERR; + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *)buf; + + if (*len != sizeof(cyg_can_msgbuf_cfg)) + { + return -EINVAL; + } + + switch (msg_buf->cfg_id) + { + // + // clear all message filters and remote buffers - prepare for message buffer + // configuration + // + case CYGNUM_CAN_MSGBUF_RESET_ALL : + { + lpc2xxx_can_config_rx_none(chan); + } + break; + + // + // setup driver for reception of all standard and extended messages + // + case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL : + { + if (!(info->flags & INFO_FLAG_RX_ALL)) // if rx_all is enabled we do not need to do anything + { + lpc2xxx_can_config_rx_all(chan); // setup RX all state + } + } + break; + + // + // add single message filter, message with filter ID will be received + // + case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD : + { + cyg_can_filter *filter = (cyg_can_filter*) buf; + + // + // if the acceptance filter is configured to receive all messages then + // it is not allowed to add single message filters because then more + // than one acceptance filter would receive the same CAN id + // + if (info->flags & INFO_FLAG_RX_ALL) + { + return -EPERM; + } + + // + // try to allocate a free acceptance filter entry - if we have a free one + // then we can prepare the acceptance filter table for reception of + // this message + // + if (!lpc2xxx_can_add_rx_filter(info, filter)) + { + return -EPERM; + } + } + break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD + + +#ifdef CYGOPT_IO_CAN_REMOTE_BUF + // + // Try to add a new RTR response message buffer for automatic + // transmission of data frame on reception of a remote frame + // + case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD : + { + // $$$$ TODO implement remote response buffers in software + return -ENOSUPP; + } + break; + + // + // write data into remote response buffer + // + case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE : + { + // $$$$ TODO implement remote response buffers in software + return -ENOSUPP; + } + break; +#endif // #ifdef CYGOPT_IO_CAN_REMOTE_BUF + default: + return -EINVAL; + } // switch (buf->cfg_id) + + return res; +} +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + +//=========================================================================== +// Read state of CAN controller +// The CAN state variable for each channel is modified by DSR so if we +// read the state we need to lock DSRs to protect the data access +//=========================================================================== +static cyg_can_state lpc2xxx_get_state(lpc2xxx_can_info_t *info) +{ + cyg_can_state result; + + cyg_drv_dsr_lock(); + result = info->state; + cyg_drv_dsr_unlock(); + + return result; +} + + +//=========================================================================== +// Set state of CAN controller +// The CAN state variable for each channel is modified by DSR so if we +// write the state we need to lock DSRs to protect the data access +//=========================================================================== +static void lpc2xxx_set_state(lpc2xxx_can_info_t *info, cyg_can_state state) +{ + cyg_drv_dsr_lock(); + info->state = state; + cyg_drv_dsr_unlock(); +} + + +//=========================================================================== +// Enter low power mode +//=========================================================================== +static Cyg_ErrNo lpc2xxx_enter_lowpower_mode(can_channel *chan) +{ + cyg_uint32 regval; + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + + // + // Before we enter low power mode, we have to enable wake up interrupt + // Normally this interrupt is always enabled so we do not need to do + // anything here + // + HAL_READ_UINT32(CAN_CTRL_MOD(info), regval); + + // + // Software can only set SM when RM in the CAN Mode register is 0 + // + if (regval & CANMOD_RESET) + { + return -EPERM; + } + + //regval &= CANMOD_SLEEP; + lpc2xxx_set_state(info, CYGNUM_CAN_STATE_STANDBY); + HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_SLEEP); + return ENOERR; +} + + +//=========================================================================== +// Start CAN module - set CANMOD operational and enable all interrupts +//=========================================================================== +static void lpc2xxx_start_module(can_channel *chan) +{ + cyg_uint32 regval; + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + + HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_OPERATIONAL); + // + // The interrupt enable register is also modified by ISR and DSR so + // we need to protect acces here + // + cyg_drv_isr_lock(); + HAL_READ_UINT32(CAN_CTRL_IER(info), regval); + regval = regval | IER_RX | CAN_MISC_INT; // enable all interrupts + HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval); + info->state = CYGNUM_CAN_STATE_ACTIVE; + cyg_drv_isr_unlock(); +} + + +//=========================================================================== +// Enter reset mode +//=========================================================================== +static void lpc2xxx_enter_reset_mode(can_channel *chan) +{ + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + + info->state = CYGNUM_CAN_STATE_STOPPED; + HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET); +} + + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS +//=========================================================================== +// Add message filter group +//=========================================================================== +static Cyg_ErrNo lpc2xxx_can_config_accfilt_group(can_channel *chan, const void* buf, cyg_uint32* len) +{ + bool res; + cyg_can_filtergroup_cfg *filter_grp = (cyg_can_filtergroup_cfg *)buf; + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + + + if (*len != sizeof(cyg_can_filtergroup_cfg)) + { + return -EINVAL; + } + + if (filter_grp->lower_id_bound >= filter_grp->upper_id_bound) + { + return -EINVAL; + } + + // + // if the acceptance filter is configured to receive all messages then + // it is not allowed to add single message filter groups because then more + // than one acceptance filter would receive the same CAN id + // + if (info->flags & INFO_FLAG_RX_ALL) + { + return -EPERM; + } + + res = lpc2xxx_can_accfilt_add(info, + filter_grp->lower_id_bound, + filter_grp->upper_id_bound, + filter_grp->ext); + +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + lpc2xxx_can_accfilt_dbg_dump(); +#endif + return res ? ENOERR : -EPERM; +} +#endif // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS + + +//=========================================================================== +// Change device configuration +//=========================================================================== +static Cyg_ErrNo lpc2xxx_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len) +{ + Cyg_ErrNo res = ENOERR; + + switch (key) + { + // + // Setup a new CAN configuration. This will i.e. setup a new baud rate + // + case CYG_IO_SET_CONFIG_CAN_INFO: + { + cyg_can_info_t* config = (cyg_can_info_t*) buf; + if (*len < sizeof(cyg_can_info_t)) + { + return -EINVAL; + } + *len = sizeof(cyg_can_info_t); + if (!lpc2xxx_can_config_channel(chan, config, false)) + { + return -EINVAL; + } + } + break; + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + // + // configure message buffers + // + case CYG_IO_SET_CONFIG_CAN_MSGBUF : + { + res = lpc2xxx_can_config_msgbuf(chan, buf, len); + } + break; +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS + // + // Add message filter group to acceptance filter + // + case CYG_IO_SET_CONFIG_LPC2XXX_ACCFILT_GROUP : + { + return lpc2xxx_can_config_accfilt_group(chan, buf, len); + } + break; +#endif // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS + + // + // Change CAN state of CAN module + // + case CYG_IO_SET_CONFIG_CAN_MODE : + { + cyg_can_mode *can_mode = (cyg_can_mode*) buf; + + if (*len != sizeof(cyg_can_mode)) + { + return -EINVAL; + } + *len = sizeof(cyg_can_mode); + + // + // decide what to do according to mode + // + switch (*can_mode) + { + // + // The controller does not support a stopped and standby state so we + // simply enter the low power state here. This state is also safe for + // message buffer configuration + // + case CYGNUM_CAN_MODE_STOP : lpc2xxx_enter_reset_mode(chan); break; + case CYGNUM_CAN_MODE_START : lpc2xxx_start_module(chan); break; + case CYGNUM_CAN_MODE_STANDBY : lpc2xxx_enter_lowpower_mode(chan); break; + case CYGNUM_CAN_MODE_CONFIG : lpc2xxx_enter_reset_mode(chan); break; + } + } + break; // case CYG_IO_SET_CONFIG_CAN_MODE : + // + // Unknown config key - indicate this by returning -EINVAL + // + default: + return -EINVAL; + } // switch (key) + + return res; +} + + +//=========================================================================== +// Query device configuration +//=========================================================================== +static Cyg_ErrNo lpc2xxx_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len) +{ + Cyg_ErrNo res = ENOERR; + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + + switch(key) + { + // + // query state of CAN controller + // + case CYG_IO_GET_CONFIG_CAN_STATE : + { + cyg_can_state *can_state = (cyg_can_state*) buf; + + if (*len != sizeof(cyg_can_state)) + { + return -EINVAL; + } + *len = sizeof(cyg_can_state); + *can_state = lpc2xxx_get_state(info); + } + break; + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + // + // Query message box information - returns available and free message + // boxes + // + case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO : + { + cyg_can_msgbuf_info *mbox_info = (cyg_can_msgbuf_info*) buf; + + if (*len != sizeof(cyg_can_msgbuf_info)) + { + return -EINVAL; + } + cyg_uint32 end_of_table; + *len = sizeof(cyg_can_msgbuf_info); + + HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table); + mbox_info->count = LPC2XXX_CAN_MSG_FILTERS_MAX; + mbox_info->free = (ACCFILT_RAM_SIZE - end_of_table) / ACCFILT_COMMON_ENTRY_SIZE; + } + break; +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + + // + // Query hardware description of FlexCAN device driver + // + case CYG_IO_GET_CONFIG_CAN_HDI : + { + cyg_can_hdi *hdi = (cyg_can_hdi *)buf; + // + // comes from high level driver so we do not need to + // check buffer size here + // + hdi->support_flags = CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE + | CYGNUM_CAN_HDI_FULLCAN; + } + break; + + default : + res = -EINVAL; + }// switch(key) + + return res; +} + + +//=========================================================================== +// Send single message +//=========================================================================== +static bool lpc2xxx_can_putmsg(can_channel *chan, CYG_CAN_MSG_T *pmsg, void *pdata) +{ + cyg_uint32 regval; +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *) chan->dev_priv; +#else + CAN_DECLARE_INFO(info); +#endif + + // + // We use only one single transmit buffer of the three available buffers + // We use buffer 1 (buffer 2 and 3 are unused) + // + // The errata sheet tells the following about the transmit buffers: + // Problem: The Triple Transmit Buffer function cannot be used. + // Work-around: Use any one Transmit buffer only (Use either Transmit Buffer 1, + // Transmit Buffer 2 or Transmit Buffer 3 exclusively). The buffer you decided + // to use should be loaded only when there is no pending transmission. + // + HAL_READ_UINT32(CAN_CTRL_SR(info), regval); + if (!(regval & SR_TX_BUF_WRITE_OK)) + { + return false; + } + + regval = pmsg->dlc << 16; + if (pmsg->rtr) + { + regval |= TFI_DLC_RTR; + } + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (pmsg->ext) + { + regval |= TFI_DLC_EXT; + } +#endif // #define CYGOPT_IO_CAN_EXT_CAN_ID + HAL_WRITE_UINT32(CAN_CTRL_TFI1(info), regval); // write DLC + HAL_WRITE_UINT32(CAN_CTRL_TID1(info), pmsg->id); // write ID + HAL_WRITE_UINT32(CAN_CTRL_TDA1(info), pmsg->data.dwords[0]); // write first 4 data bytes + HAL_WRITE_UINT32(CAN_CTRL_TDB1(info), pmsg->data.dwords[1]); // write second 4 data bytes + + // + // Request transmission of message + // The errata sheet tells the following about tx request: + // Introduction: The CAN module can lose arbitration to another CAN node during an + // attempt to transmit a CAN message. The message of the CAN node the arbitration was + // lost to is supposed to be received correctly by the CAN module. + // Problem: Messages might not be received correctly if during a CAN Transmission the + // CAN bus arbitration is lost to another CAN node. + // Work-around: Use the Self Reception Request command instead of the Transmission + // Request command. However, it has to be taken into account that now all transmitted + // messages may be received if not prevented by appropriate Acceptance Filter settings. + // (Don't set up Acceptance Filter Message Identifiers for the messages you are + // transmitting yourself.) + // +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION + // Calc last_tx_id + regval = pmsg->id | (regval & LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK); + + // Save last message id to next last_tx_id + info->last_tx_index = info->last_tx_index == 0 ? 1 : 0; + info->last_tx_id[info->last_tx_index] = regval; + + // Write self transmission request + HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_SELF_RX_REQ | CMR_SEND_TX_BUF1); +#else + // Write transmission request + HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_TX_REQ | CMR_SEND_TX_BUF1); +#endif + + return true; +} + + +//=========================================================================== +// Read event from device driver +//=========================================================================== +static bool lpc2xxx_can_getevent(can_channel *chan, CYG_CAN_EVENT_T *pevent, void *pdata) +{ + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + bool res = true; + cyg_uint32 regval; + cyg_uint32 event = *((cyg_uint32*)pdata); + lsc_buf_t data; + + // + // Handle RX event + // + if (event & ICR_RX) + { + cyg_uint32 id; + + pevent->flags |= CYGNUM_CAN_EVENT_RX; + HAL_READ_UINT32(CAN_CTRL_RFS(info), regval); + HAL_READ_UINT32(CAN_CTRL_RID(info), id); + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (regval & RFS_EXT) + { + pevent->msg.ext = CYGNUM_CAN_ID_EXT; + pevent->msg.id = id & 0x1FFFFFFF; + } + else +#endif // #define CYGOPT_IO_CAN_EXT_CAN_ID + { +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + pevent->msg.ext = CYGNUM_CAN_ID_STD; + pevent->msg.id = id & 0x7FF; +#endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID + } // if (regval & RFS_EXT) + + if (regval & RFS_RTR) + { + pevent->msg.rtr = CYGNUM_CAN_FRAME_RTR; + } + else + { + pevent->msg.rtr = CYGNUM_CAN_FRAME_DATA; + HAL_READ_UINT32(CAN_CTRL_RDA(info), pevent->msg.data.dwords[0]); + HAL_READ_UINT32(CAN_CTRL_RDB(info), pevent->msg.data.dwords[1]); + } //if (regval & RFS_RTR) + pevent->msg.dlc = RFS_GET_DLC(regval); + // + // Release the message buffer. Now this buffer can receive the next message + // + HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_RX_RELEASE_BUF); + + // + // Now check if an data overrun occurred - a message was lost + // because the preceding message to this CAN controller was not read + // and released quickly enough. After reading the status we clear + // the overrun bit + // + HAL_READ_UINT32(CAN_CTRL_GSR(info), regval); + if (regval & GSR_DATA_OVR) + { + pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX; + HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_CLEAR_DATA_OVR); + } + } + + // + // Handle TX events + // +#ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT + if (event & ICR_TX1) + { + pevent->flags |= CYGNUM_CAN_EVENT_TX; + } +#endif + + // + // Handle all other events + // + if (event & (CAN_MISC_INT | ICR_LUT_ERR)) + { + HAL_READ_UINT32(CAN_CTRL_GSR(info), data.dword); + + // + // 1: Error Warning Interrupt -- this bit is set on every change (set or clear) of the Error + // Status or Bus Status bit in CANSR, if the EIE bit in CAN is 1 at the time of the + // change. + // + if (event & ICR_ERR_WARN) + { + // + // If one of the warning counters is above 96 then the controller is in bus warning + // state. If both counters are below 96 the this interrupt indicates that the + // controller has left the bus warning state and is error active again + // + if (data.bytes[2] >= 96) + { + pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX; + info->state = CYGNUM_CAN_STATE_BUS_WARN; + } + else if (data.bytes[3] >= 96) + { + pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX; + info->state = CYGNUM_CAN_STATE_BUS_WARN; + } + else + { + info->state = CYGNUM_CAN_STATE_ACTIVE; + } + LPC2XXX_DBG_PRINT("ICR_ERR_WARN (%p)\n", (void*) chan); + } + + // + // 1: Wake-Up Interrupt: this bit is set if the CAN controller is sleeping and bus activity + // is detected, if the WUIE bit in CANIE is 1. + // + if (event & ICR_WAKE_UP) + { + pevent->flags |= CYGNUM_CAN_EVENT_LEAVING_STANDBY; + info->state = CYGNUM_CAN_STATE_ACTIVE; + LPC2XXX_DBG_PRINT("ICR_WAKE_UP (%p)\n", (void*) chan); + } + + // + // Error Passive Interrupt -- this bit is set if the EPIE bit in CANIE is 1, and the CAN + // controller switches between Error Passive and Error Active mode in either + // direction. We have to check if the ERR bit is set in global status register. + // If it is set, then it is a switch to error passive else it is a switch to + // error active state + // + if (event & ICR_ERR_PASSIVE) + { + if (data.dword & GSR_ERR) + { + pevent->flags |= CYGNUM_CAN_EVENT_ERR_PASSIVE; + info->state = CYGNUM_CAN_STATE_ERR_PASSIVE; + } + else + { + info->state = CYGNUM_CAN_STATE_ACTIVE; + } + LPC2XXX_DBG_PRINT("ICR_ERR_PASSIVE (%p)\n", (void*) chan); + } + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_ALIE + // + // Arbitration Lost Interrupt -- this bit is set if the ALIE bit in CANIE is 1, and the + // CAN controller loses arbitration while attempting to transmit. + // + if (event & ICR_ARBITR_LOST) + { + pevent->flags |= CYGNUM_CAN_EVENT_ARBITRATION_LOST; + LPC2XXX_DBG_PRINT("ICR_ARBITR_LOST (%p)\n", (void*) chan); + } +#endif // CYGOPT_DEVS_CAN_LPC2XXX_ALIE + + // + // 1: Bus Error Interrupt -- this bit is set if the BEIE bit in CANIE is 1, and the CAN + // controller detects an error on the bus. + // + if (event & ICR_BUS_ERR) + { + pevent->flags |= CYGNUM_CAN_EVENT_BUS_OFF; + LPC2XXX_DBG_PRINT("ICR_BUS_ERR (%p)\n", (void*) chan); + } + +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + // + // LUT error interrupt -- this bit is set if bit 0 in LUTerr is 1 and LUTerrAd + // points to entry in filter table for this CAN controller + // + if(event & ICR_LUT_ERR) + { + pevent->flags |= CYGNUM_CAN_EVENT_FILTER_ERR; + LPC2XXX_DBG_PRINT("ICR_LUT_ERR (%p)\n", (void*) chan); + } +#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + + } // if (event & (CAN_MISC_INT | ICR_LUT_ERR)) + + return res; +} + + +//=========================================================================== +// Kick transmitter +//=========================================================================== +static void lpc2xxx_can_start_xmit(can_channel* chan) +{ + cyg_uint32 regval; + CAN_DECLARE_INFO(chan); + + LPC2XXX_DBG_PRINT("start_xmit (%p)\n", (void*) chan); + + cyg_drv_dsr_lock(); + HAL_READ_UINT32(CAN_CTRL_IER(info), regval); + regval |= IER_TX1; // enable tx interrupt for tx buf 1 + HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval); + cyg_drv_dsr_unlock(); + + // + // kick transmitter + // + chan->callbacks->xmt_msg(chan, 0); // Kick transmitter (if necessary) +} + + +//=========================================================================== +// Stop transmitter +//=========================================================================== +static void lpc2xxx_can_stop_xmit(can_channel* chan) +{ + cyg_uint32 regval; + CAN_DECLARE_INFO(chan); + + LPC2XXX_DBG_PRINT("stop_xmit (%p)\n", (void*) chan); + + cyg_drv_dsr_lock(); + HAL_READ_UINT32(CAN_CTRL_IER(info), regval); + regval &= ~IER_TX1; // disable tx interrupt for tx buf 1 + HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval); + cyg_drv_dsr_unlock(); +} + + +#ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY +//=========================================================================== +// Low level transmit interrupt handler +//=========================================================================== +static cyg_uint32 lpc2xxx_can_tx_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + // + // Now read input capture register - this clears all interrupt bits in this + // register and also acknowledges the interrupt - any further processing is done + // by the DSR + // + cyg_drv_interrupt_mask(vector); + cyg_drv_interrupt_acknowledge(vector); + LPC2XXX_DBG_PRINT("tx_ISR (%p)\n", (void*) data); + return CYG_ISR_CALL_DSR; +} + + +//=========================================================================== +// High level transmit interrupt handler +//=========================================================================== +static void lpc2xxx_can_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + can_channel *chan = (can_channel *)data; + cyg_uint32 regval; + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + + // + // First read the ICR register to acknowledge all interrupts and + // get all captured interrupts + // + HAL_READ_UINT32(CAN_CTRL_ICR(info), regval); + + // + // If TX events are supported then only call the rcv_event() callback + // if any other event occurred - pass the event field to the getevent function + // to indicate the events + // +#ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT + if (regval & ~ICR_TX1) +#endif + { + chan->callbacks->rcv_event(chan, ®val); + } + + // + // Now transmit next message and reenable interrupts + // + chan->callbacks->xmt_msg(chan, 0); // send next message + LPC2XXX_DBG_PRINT("tx_DSR (%p)\n", (void*) data); + cyg_drv_interrupt_unmask(vector); +} + + +//=========================================================================== +// Low level receive interrupt handler +//=========================================================================== +static cyg_uint32 lpc2xxx_can_rx_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION + cyg_uint32 regval; + can_channel* chan = (can_channel*)data; + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *) chan->dev_priv; + cyg_uint32 id; + cyg_uint32 index; + + // We have to reject self tx message, so read message id + HAL_READ_UINT32(CAN_CTRL_RID(info), id); + HAL_READ_UINT32(CAN_CTRL_RFS(info), regval); + id |= (regval & LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK); + + // Test message id + for(index = 0; index < 2; index++) + { + if(id == info->last_tx_id[index]) + { + // Clear last_tx_id + info->last_tx_id[index] = LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID; + + // Clear receive buffer + HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_RX_RELEASE_BUF); + + // Acknowledge a vector + cyg_drv_interrupt_acknowledge(vector); + + // Exit without calling DSR + LPC2XXX_DBG_PRINT("self_rx_ISR (%p)\n", (void*) data); + return CYG_ISR_HANDLED; + } + } +#endif + + // + // The ISR only disables and acknowledges the RX interrupt + // any further processing is done by DSR. We also need to mask the + // global CAN status interrupt here because the interrupt flag + // in ICR is not cleared yet and may still cause a status + // interrupt + // + cyg_drv_interrupt_mask(vector); + cyg_drv_interrupt_acknowledge(vector); + LPC2XXX_DBG_PRINT("rx_ISR (%p)\n", (void*) data); + + return CYG_ISR_CALL_DSR; +} + + +//=========================================================================== +// High level receive interrupt handler +//=========================================================================== +static void lpc2xxx_can_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + can_channel *chan = (can_channel *)data; + cyg_uint32 icr = ICR_RX; + + // + // Read the event, the receive buffer will be released by the + // get_event() function + // + chan->callbacks->rcv_event(chan, &icr); + LPC2XXX_DBG_PRINT("rx_DSR (%p)\n", (void*) data); + cyg_drv_interrupt_unmask(vector); +} + + + +//=========================================================================== +// status ISR handler +//=========================================================================== +static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + // + // Acknowledge and disable the interrupt - any further processing is + // done by the DSR + // + cyg_drv_interrupt_mask(vector); + cyg_drv_interrupt_acknowledge(vector); + LPC2XXX_DBG_PRINT("err_ISR\n"); + return CYG_ISR_CALL_DSR; +} + + +//=========================================================================== +// status ISR handler +//=========================================================================== +static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + // If we use acceptance filter we can get LUT error + cyg_uint32 luterr; + cyg_uint8 luterr_chan0 = 0; // Init to avoid warnings + cyg_uint8 luterr_chan1 = 0; // Init to avoid warnings + + // Read LUT error flag + HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR, luterr); + + if (luterr & 1) + { + cyg_uint32 lutaddr; + cyg_uint32 eff_sa; + lsc_buf_t errentry; + + // Read address of failed entry (it clears interrupt flag) + HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR_ADDR, lutaddr); + + // Read address of extended id individual table + HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa); + + // Read error entry + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + lutaddr, errentry.dword); + + // If err entry from standard id tables then read two + // controllers numbers + if(lutaddr < eff_sa) + { + // Calc CAN controllers numbers + luterr_chan0 = (cyg_uint8) ACCFILT_STD_GET_CTRL_UPPER(errentry.dword); + + if(errentry.column.lower & ACCFILT_STD_DIS) + { + luterr_chan1 = luterr_chan0; + } + else + { + luterr_chan1 = (cyg_uint8) ACCFILT_STD_GET_CTRL_LOWER(errentry.dword); + } + } + else + { + // Calc CAN controller number + luterr_chan0 = luterr_chan1 = (cyg_uint8) ACCFILT_EXT_GET_CTRL(errentry.dword); + } + } +#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + + // + // Loop through all channels - we need to do this only if we have more + // than one channel so we can optimize here for single channel + // +#if CYGINT_IO_CAN_CHANNELS > 1 + cyg_uint8 i = 0; + while (lpc2xxx_global_can_info.active_channels[i]) +#endif + { + cyg_uint32 regval; + can_channel *chan = LPC2XXX_GET_CAN_CHANNEL(lpc2xxx_global_can_info, i++); + CAN_DECLARE_INFO(chan); + + HAL_READ_UINT32(CAN_CTRL_ICR(info), regval); +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + // Set ICR_LUT_ERR flag only for controller which cause LUT error + if ((luterr & 1) && ((luterr_chan0 == i) || (luterr_chan1 == i))) + { + regval |= ICR_LUT_ERR; + } +#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + regval &= CAN_MISC_INT; // don't care about RX and TX events here + if (regval) + { + chan->callbacks->rcv_event(chan, ®val); + } + } // while (lpc2xxx_global_can_info.active_channels[i]) + + LPC2XXX_DBG_PRINT("err_DSR\n"); + cyg_drv_interrupt_unmask(vector); +} +#else // #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + + +//=========================================================================== +// Global CAN interrupt handler +//=========================================================================== +static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + // + // Disable interrupts, the DSR will enable it as soon as it processed + // the current interrupt + // + cyg_drv_interrupt_mask(vector); + cyg_drv_interrupt_acknowledge(vector); + LPC2XXX_DBG_PRINT("CAN_ISR\n"); + return CYG_ISR_CALL_DSR; +} + +//=========================================================================== +// Global CAN DSR +//=========================================================================== +static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + // If we use acceptance filter we can get LUT error + cyg_uint32 luterr; + cyg_uint8 luterr_chan0 = 0xFF; // Init to avoid warnings + cyg_uint8 luterr_chan1 = 0xFF; // Init to avoid warnings + + // Read LUT error flag + HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR, luterr); + + if (luterr & 1) + { + cyg_uint32 lutaddr; + cyg_uint32 eff_sa; + lsc_buf_t errentry; + + // Read address of failed entry (it clears interrupt flag) + HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR_ADDR, lutaddr); + + // Read address of extended id individual table + HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa); + + // Read error entry + HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + lutaddr, errentry.dword); + + // If errentry from standard id tables then read two controllers numbers + if(lutaddr < eff_sa) + { + // Calc CAN controllers numbers + luterr_chan0 = (cyg_uint8) ACCFILT_STD_GET_CTRL_UPPER(errentry.dword); + + if(errentry.column.lower & ACCFILT_STD_DIS) + { + luterr_chan1 = luterr_chan0; + } + else + { + luterr_chan1 = (cyg_uint8) ACCFILT_STD_GET_CTRL_LOWER(errentry.dword); + } + } + else + { + // Calc CAN controller number + luterr_chan0 = luterr_chan1 = (cyg_uint8) ACCFILT_EXT_GET_CTRL(errentry.dword); + } + } +#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + + // + // Walk through list of active CAN channels and process interrupts + // of all channels - we need to loop only if we have more than one CAN channel so + // we can optimize for single CAN channel here + // +#if CYGINT_IO_CAN_CHANNELS > 1 + cyg_uint8 i = 0; + while (lpc2xxx_global_can_info.active_channels[i]) +#endif // CYGINT_IO_CAN_CHANNELS > 1 + { + cyg_uint32 icr; + can_channel *chan = LPC2XXX_GET_CAN_CHANNEL(lpc2xxx_global_can_info, i++); + CAN_DECLARE_INFO(chan); + + HAL_READ_UINT32(CAN_CTRL_ICR(info), icr); // this read clears ICR +#ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + // Set ICR_LUT_ERR flag only for controller which cause LUT error + if ((luterr_chan0 == i) || (luterr_chan1 == i)) + { + icr |= ICR_LUT_ERR; + } +#endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP + // + // If TX events are supported then we simply call the rcv_event() + // callback to store the event. If TX events are not supported then + // we only call the rcv_event() function if any other interrupt than + // the TX interrupt was captured + // +#ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT + if (icr & ~ICR_TX1) +#endif // CYGOPT_IO_CAN_TX_EVENT_SUPPORT + { + chan->callbacks->rcv_event(chan, &icr); + } + // + // If this was an TX interrupt then transmit next message now + // + if (icr & ICR_TX1) + { + chan->callbacks->xmt_msg(chan, 0); // send next message + } + } // while (lpc2xxx_global_can_info.active_channels[i]) + LPC2XXX_DBG_PRINT("CAN_DSR\n"); + cyg_drv_interrupt_unmask(vector); +} +#endif // #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY + + +#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Configure message boxes for reception of any CAN message +//=========================================================================== +static void lpc2xxx_can_config_rx_all(can_channel *chan) +{ + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + // + // First clear all acceptance filter entries and then insert the + // two RX all groups + // + lpc2xxx_can_config_rx_none(chan); +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + lpc2xxx_can_accfilt_add(info, 0x000, 0x7FF, CYGNUM_CAN_ID_STD); +#endif // CYGOPT_IO_CAN_STD_CAN_ID +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + lpc2xxx_can_accfilt_add(info, 0x000, 0x1FFFFFFF, CYGNUM_CAN_ID_EXT); +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + + info->flags |= INFO_FLAG_RX_ALL; +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + lpc2xxx_can_accfilt_dbg_dump(); +#endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG +} +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + +#ifndef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +//=========================================================================== +// Configure message boxes for reception of any CAN message +//=========================================================================== +static void lpc2xxx_can_config_rx_all(can_channel *chan) +{ + lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv; + + lpc2xxx_can_accfilt_simple_rx_all(); + info->flags |= INFO_FLAG_RX_ALL; + +#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG + lpc2xxx_can_accfilt_dbg_dump(); +#endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG +} +#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG + + +//--------------------------------------------------------------------------- +// EOF can_lpc2xxx.c diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_baudrates.c b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_baudrates.c new file mode 100644 index 00000000..2dc8d2ed --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_baudrates.c @@ -0,0 +1,231 @@ +//========================================================================== +// +// can_baudrates.c +// +// CAN test of all supported baudrates +// +//========================================================================== +//####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: 2007-06-26 +// Description: CAN LPC2xxx baudrate test +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + + +#include "can_test_aux.inl" // include CAN test auxiliary functions +//=========================================================================== +// 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 hCAN; + + +// +// The table of baudrates to test +// +static cyg_can_baud_rate_t baudrate_tbl[9] = +{ + CYGNUM_CAN_KBAUD_10, + CYGNUM_CAN_KBAUD_20, + CYGNUM_CAN_KBAUD_50, + CYGNUM_CAN_KBAUD_100, + CYGNUM_CAN_KBAUD_125, + CYGNUM_CAN_KBAUD_250, + CYGNUM_CAN_KBAUD_500, + CYGNUM_CAN_KBAUD_800, + CYGNUM_CAN_KBAUD_1000, +}; + +// +// String table forprinting supported baudrates +// +static char* baudrate_strings_tbl[9] = +{ + "10", + "20", + "50", + "100", + "125", + "250", + "500", + "800", + "1000", +}; + + +//=========================================================================== +// Thread 0 +//=========================================================================== +void can0_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_event rx_event; + cyg_uint32 i; + cyg_can_info_t can_info; + + diag_printf("\n\nWhen the LPC2xxx driver selects a new baudrate then you need\n" + "to setup your hardware to the new baudrate and send one CAN\n" + "single CAN standard message.\n"); + // + // Test all supported baudrates + // + for (i = 0; i < 9; ++i) + { + diag_printf("\n\nBaudrate: %s Kbaud\n", baudrate_strings_tbl[i]); + can_info.baud = baudrate_tbl[i]; + len = sizeof(can_info); + if (ENOERR != cyg_io_set_config(hCAN, CYG_IO_SET_CONFIG_CAN_INFO, &can_info, &len)) + { + diag_printf("not supported\n"); + continue; + } + else + { + diag_printf("waiting for CAN message...\n"); + } + + len = sizeof(rx_event); + // + // First receive CAN event from real CAN hardware + // + len = sizeof(rx_event); + if (ENOERR != cyg_io_read(hCAN, &rx_event, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading from channel 0"); + } + + if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + { + print_can_msg(&rx_event.msg, "RX chan 1:"); + } // if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + else + { + print_can_flags(rx_event.flags, ""); + CYG_TEST_FAIL_FINISH("Rx message expected"); + } + } // for (i = 0; i < 9; ++i) + + CYG_TEST_PASS_FINISH("CAN baudrate test OK"); +} + + +//=========================================================================== +// Entry point +//=========================================================================== +void cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // open CAN device driver channel 1 + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN0_NAME, &hCAN)) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 0"); + } + + // + // create the main thread + // + cyg_thread_create(5, can0_thread, + (cyg_addrword_t) 0, + "can_tx_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 Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG + +//--------------------------------------------------------------------------- +// EOF can_busload.c diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_busload.c b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_busload.c new file mode 100644 index 00000000..37c81987 --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_busload.c @@ -0,0 +1,253 @@ +//========================================================================== +// +// can_busload.c +// +// CAN bus 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: 2007-06-26 +// Description: CAN bus load test +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + +// We need two CAN channels +#if defined(CYGPKG_DEVS_CAN_LPC2XXX_CAN0) && defined(CYGPKG_DEVS_CAN_LPC2XXX_CAN1) + + +// The same baud rates are required because we send from one channel to the other one +#if CYGNUM_DEVS_CAN_LPC2XXX_CAN0_KBAUD == CYGNUM_DEVS_CAN_LPC2XXX_CAN1_KBAUD + + +// We need a large RX buffer +#ifdef CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_RX_1024 + +#include "can_test_aux.inl" // include CAN test auxiliary functions +//=========================================================================== +// 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 hCAN_Tbl[2]; + + +//=========================================================================== +// Thread 0 +//=========================================================================== +void can0_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_message tx_msg; + cyg_can_event rx_event; + cyg_uint32 i; + cyg_uint32 rx_msg_cnt = 0; + + + // + // Prepeare message - we use a data length of 0 bytes here. Each received message + // causes an iterrupt. The shortest message is a 0 data byte message. This will generate + // the highest interrupt rate + // + CYG_CAN_MSG_SET_PARAM(tx_msg, 0, CYGNUM_CAN_ID_STD, 0, CYGNUM_CAN_FRAME_DATA); + + // + // Now send 1024 CAN messages as fast as possible to stress the receiver of CAN + // channel 1 + // + for (i = 0; i< 1024; ++i) + { + tx_msg.id = i; + len = sizeof(tx_msg); + if (ENOERR != cyg_io_write(hCAN_Tbl[1], &tx_msg, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing to channel 0"); + } + } + + // + // Now try to receive all 1024 CAN messages. If all messages are received + // and no overrun occured then the message processing is fast enought + // + while (1) + { + len = sizeof(rx_event); + // + // First receive CAN event from real CAN hardware + // + len = sizeof(rx_event); + if (ENOERR != cyg_io_read(hCAN_Tbl[0], &rx_event, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading from channel 1"); + } + + if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + { + print_can_msg(&rx_event.msg, "RX chan 1:"); + rx_msg_cnt++; + if (rx_msg_cnt == 1024) + { + CYG_TEST_PASS_FINISH("CAN load test OK"); + } + } // if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + else + { + print_can_flags(rx_event.flags, ""); + if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX) + { + CYG_TEST_FAIL_FINISH("RX overrun for channel 1"); + } + + if (rx_event.flags & CYGNUM_CAN_EVENT_ERR_PASSIVE) + { + CYG_TEST_FAIL_FINISH("Channel 1 error passive event"); + } + + if (rx_event.flags & CYGNUM_CAN_EVENT_BUS_OFF) + { + CYG_TEST_FAIL_FINISH("Channel 1 bus off event"); + } + } + } // while (1) +} + + +//=========================================================================== +// Entry point +//=========================================================================== +void cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // open CAN device driver channel 1 + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN0_NAME, &hCAN_Tbl[0])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 0"); + } + + + // + // open CAN device driver channel 2 + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN1_NAME, &hCAN_Tbl[1])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 1"); + } + + // + // create the main thread + // + cyg_thread_create(5, can0_thread, + (cyg_addrword_t) 0, + "can_tx_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 // CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_RX_1024 +#define N_A_MSG "Channel 0 needs RX buffer size for 1024 events" +#endif + +#else // CYGNUM_DEVS_CAN_LPC2XXX_CAN0_KBAUD == CYGNUM_DEVS_CAN_LPC2XXX_CAN1_KBAUD +#define N_A_MSG "Baudrate of channel 0 and 1 need to be equal" +#endif + +#else // defined(CYGPKG_DEVS_CAN_LPC2XXX_CAN0) && defined(CYGPKG_DEVS_CAN_LPC2XXX_CAN1) +#define N_A_MSG "Needs support for CAN channel 1 and 2" +#endif + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG + +//--------------------------------------------------------------------------- +// EOF can_busload.c diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_extended_cfg.c b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_extended_cfg.c new file mode 100644 index 00000000..8ff3d9cf --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_extended_cfg.c @@ -0,0 +1,252 @@ +//========================================================================== +// +// can_extended_cfg.c +// +// Test of extended CAN configuration keys for LPC2xxx CAN driver +// +//========================================================================== +//####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: 2006-06-20 +// Description: LPC2xxx CAN extended configuration test +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + +// Package option requirements +#if defined(CYGOPT_IO_CAN_RUNTIME_MBOX_CFG) +#include "can_test_aux.inl" + +#if defined(CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS) +#include + +//=========================================================================== +// 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 hCAN0; + + +//=========================================================================== +// READER THREAD +//=========================================================================== +void can0_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_event rx_event; + cyg_can_filtergroup_cfg acc_filt_grp; + cyg_can_msgbuf_cfg msgbox_cfg; + + // + // First we reset message buffer configuration - this is mandatory bevore starting + // message buffer runtime configuration. This call clears/frees all message buffers + // The CAN controller cannot receive any further CAN message after this call + // + msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; + len = sizeof(msgbox_cfg); + if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&msgbox_cfg, &len)) + { + CYG_TEST_FAIL_FINISH("Error resetting message buffer configuration of /dev/can0"); + } + + // + // Now we setup two different acceptance filter groups. Acceptance filter + // groups are not part of the CAN I/O layer and are a LPC2xxx specific + // feature. You should not use appcetance filter groups if you would like + // to code portable eCos CAN applications + // +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + acc_filt_grp.ext = CYGNUM_CAN_ID_STD; + acc_filt_grp.lower_id_bound = 0x100; + acc_filt_grp.upper_id_bound = 0x110; + len = sizeof(acc_filt_grp); + + if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_LPC2XXX_ACCFILT_GROUP ,&acc_filt_grp, &len)) + { + CYG_TEST_FAIL_FINISH("Error adding filter group to /dev/can0"); + } +#endif // CYGOPT_IO_CAN_STD_CAN_ID + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + acc_filt_grp.ext = CYGNUM_CAN_ID_EXT; + acc_filt_grp.lower_id_bound = 0x2000; + acc_filt_grp.upper_id_bound = 0x2200; + len = sizeof(acc_filt_grp); + + if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_LPC2XXX_ACCFILT_GROUP ,&acc_filt_grp, &len)) + { + CYG_TEST_FAIL_FINISH("Error adding filter group to /dev/can0"); + } +#endif // CYGOPT_IO_CAN_STD_CAN_ID + + diag_printf("\n\nNow try to send CAN messages. The device should only\n" + "receive standard messages identifiers in the range of 0x100\n" + "to 0x110 and/or extended identifiers in the range 0x2000 to\n" + "0x2200. As soon as a standard message with ID 0x110 or an\n" + "extended message with ID 0x2200 arrives, the test finishes\n\n"); + + while (1) + { + len = sizeof(rx_event); + + if (ENOERR != cyg_io_read(hCAN0, &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) + { + print_can_msg(&rx_event.msg, ""); +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + if (rx_event.msg.id == 0x110) + { + CYG_TEST_PASS_FINISH("LPC2xxx CAN message filter group test OK"); + } +#endif // CYGOPT_IO_CAN_STD_CAN_ID + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + if (rx_event.msg.id == 0x2200) + { + CYG_TEST_PASS_FINISH("LPC2xxx CAN message filter group test OK"); + } +#endif // CYGOPT_IO_CAN_EXT_CAN_ID + + if (((rx_event.msg.id > 0x110) && (rx_event.msg.id < 0x2000)) + || (rx_event.msg.id > 0x2200)) + { + CYG_TEST_FAIL_FINISH("Received CAN identifier outside filter group bounds"); + } + } + } + } // while (1) +} + + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) + { + CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); + } + + // + // create the thread that accesses the CAN device driver + // + cyg_thread_create(4, can0_thread, + (cyg_addrword_t) 0, + "can0_thread", + (void *) can0_thread_data.stack, + 1024 * sizeof(long), + &can0_thread_data.hdl, + &can0_thread_data.obj); + + cyg_thread_resume(can0_thread_data.hdl); + + cyg_scheduler_start(); +} + +#else // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS +#define N_A_MSG "Needs support for extended LPC2xxx CAN configuration keys" +#endif + +#else // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +#define N_A_MSG "Needs CAN message box runtime confuguration support" +#endif + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs 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 diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_multichan_rx.c b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_multichan_rx.c new file mode 100644 index 00000000..b7a16daa --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_multichan_rx.c @@ -0,0 +1,339 @@ +//========================================================================== +// +// can_multichan_rx.c +// +// CAN RX test for multiple CAN channels +// +//========================================================================== +//####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: 2007-06-26 +// Description: CAN RX test for multiple CAN controller channels +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + +// Package option requirements +#if defined(CYGOPT_IO_CAN_SUPPORT_NONBLOCKING) + +#include "can_test_aux.inl" // include CAN test auxiliary functions +//=========================================================================== +// DATA TYPES +//=========================================================================== +typedef struct st_thread_data +{ + cyg_thread obj; + long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; + cyg_handle_t hdl; +} thread_data_t; + + +//=========================================================================== +// LOCAL DATA +//=========================================================================== +cyg_thread_entry_t can_thread; +thread_data_t can0_thread_data; +cyg_io_handle_t hCAN_Tbl[4]; + + +//=========================================================================== +// Setup acceptance filter +//=========================================================================== +void can_setup_channel(cyg_io_handle_t hCAN, unsigned char Channel) +{ + cyg_uint32 len; + cyg_can_msgbuf_cfg msgbox_cfg; + cyg_uint8 i; + cyg_uint32 blocking; + + // + // First we reset message buffer configuration - this is mandatory bevore starting + // message buffer runtime configuration. This call clears/frees all message buffers + // The CAN controller cannot receive any further CAN message after this call + // + msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; + len = sizeof(msgbox_cfg); + if (ENOERR != cyg_io_set_config(hCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&msgbox_cfg, &len)) + { + CYG_TEST_FAIL_FINISH("Error resetting message buffer configuration of /dev/can0"); + } + + // + // Now setup 10 message filters for this channel + // + for (i = 0; i < 10; ++i) + { + cyg_can_filter rx_filter; + + rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD; + rx_filter.msg.id = Channel * 0x100 + i; + rx_filter.msg.ext = CYGNUM_CAN_ID_STD; + + len = sizeof(rx_filter); + if (ENOERR != cyg_io_set_config(hCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rx_filter, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing config"); + } + else if (CYGNUM_CAN_MSGBUF_NA == rx_filter.handle) + { + CYG_TEST_FAIL_FINISH("Error setting up message filter"); + } + } + + // + // Now set driver into nonblocking mode because the receiver thread will + // receive the messages from all channels + // + blocking = 0; + len = sizeof(blocking); + if (ENOERR != cyg_io_set_config(hCAN, CYG_IO_SET_CONFIG_READ_BLOCKING ,&blocking, &len)) + { + CYG_TEST_FAIL_FINISH("Error setting channel into nonblocking mode"); + } + + // + // If timeouts are supported we need to setup a timeout value of 0 because + // the driver should return immediatelly if no message is available + // +#ifdef CYGOPT_IO_CAN_SUPPORT_TIMEOUTS + cyg_can_timeout_info_t timeouts; + + timeouts.rx_timeout = 0; + timeouts.tx_timeout = 0; + len = sizeof(timeouts); + if (ENOERR != cyg_io_set_config(hCAN, CYG_IO_SET_CONFIG_CAN_TIMEOUT ,&timeouts, &len)) + { + CYG_TEST_FAIL_FINISH("Error setting timeout for channel"); + } +#endif +} + + +//=========================================================================== +// READER THREAD +//=========================================================================== +void can_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_uint8 i = 0; + + // + // Check that all cannels have the same baudrate + // +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0 + can_setup_channel(hCAN_Tbl[0], 0); +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1 + can_setup_channel(hCAN_Tbl[1], 1); +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2 + can_setup_channel(hCAN_Tbl[2], 2); +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3 + can_setup_channel(hCAN_Tbl[3], 3); +#endif + + diag_printf("\n\nThis test uses all available CAN channels for reception\n" + "of CAN standard messages. The following messages will be received:\n\n"); + + for (i = 0; i < 4; ++i) + { + if (hCAN_Tbl[i]) + { + diag_printf("CAN channel %d: msg: 0x%03x - 0x%03x\n", i, i * 0x100, i * 0x100 + 9); + } + } + + diag_printf("\n\nYou can stop this test by sending a message with ID 0xX09\n"); + + while (1) + { + for (i = 0; i < 4; ++i) + { + if (hCAN_Tbl[i]) + { + Cyg_ErrNo ret; + cyg_can_event rx_event; + + len = sizeof(rx_event); + ret = cyg_io_read(hCAN_Tbl[i], &rx_event, &len); + if ((ret == -EAGAIN) || (ret == -EINTR)) + { + continue; + } + + if (ENOERR != ret) + { + CYG_TEST_FAIL_FINISH("Error reading from channel"); + } + else + { + diag_printf("Channel %d events: ", i); + print_can_flags(rx_event.flags, ""); + if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + { + print_can_msg(&rx_event.msg, ""); + if ((rx_event.msg.id & 9) == 9) + { + CYG_TEST_PASS_FINISH("LPC2xxx CAN multi channel RX test OK"); + } + } // if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + } + } // if (hCAN_Tbl[i]) + } // for (i = 0; i < 4; ++i) + } // while (1) +} + + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0 + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN0_NAME, &hCAN_Tbl[0])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 0"); + } +#else + hCAN_Tbl[0] = 0; +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1 + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN1_NAME, &hCAN_Tbl[1])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 1"); + } +#else + hCAN_Tbl[1] = 0; +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2 + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN2_NAME, &hCAN_Tbl[2])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 2"); + } +#else + hCAN_Tbl[2] = 0; +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3 + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN3_NAME, &hCAN_Tbl[3])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 3"); + } +#else + hCAN_Tbl[3] = 0; +#endif + + // + // create the thread that accesses the CAN device driver + // + cyg_thread_create(4, can_thread, + (cyg_addrword_t) 0, + "can0_thread", + (void *) can0_thread_data.stack, + 1024 * sizeof(long), + &can0_thread_data.hdl, + &can0_thread_data.obj); + + cyg_thread_resume(can0_thread_data.hdl); + + cyg_scheduler_start(); +} +#else // CYGOPT_IO_CAN_SUPPORT_NONBLOCKING +#define N_A_MSG "Needs support for nonblocking calls" +#endif + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG + +//--------------------------------------------------------------------------- +// EOF can_multichan_rx.c diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_multichan_tx.c b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_multichan_tx.c new file mode 100644 index 00000000..4aa2f52d --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_multichan_tx.c @@ -0,0 +1,292 @@ +//========================================================================== +// +// can_multichan_tx.c +// +// CAN TX test for multiple CAN channels +// +//========================================================================== +//####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: 2007-06-26 +// Description: CAN TX test for multiple CAN controller channels +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + + +//=========================================================================== +// DATA TYPES +//=========================================================================== +typedef struct st_thread_data +{ + cyg_thread obj; + long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; + cyg_handle_t hdl; +} thread_data_t; + + +//=========================================================================== +// LOCAL DATA +//=========================================================================== +cyg_thread_entry_t can_thread; +thread_data_t can0_thread_data; +cyg_io_handle_t hCAN_Tbl[4]; + + +//=========================================================================== +// READER THREAD +//=========================================================================== +void can_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_message tx_msg; + cyg_can_info_t can_info; + cyg_can_baud_rate_t baud; + cyg_uint8 i = 0; + cyg_uint8 j = 0; + + // + // Check that all cannels have the same baudrate + // +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0 + len = sizeof(can_info); + if (ENOERR != cyg_io_get_config(hCAN_Tbl[0], CYG_IO_GET_CONFIG_CAN_INFO, &can_info, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading baudrate of CAN channel 0"); + } + else + { + baud = can_info.baud; + ++i; + } +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1 + len = sizeof(can_info); + if (ENOERR != cyg_io_get_config(hCAN_Tbl[1], CYG_IO_GET_CONFIG_CAN_INFO, &can_info, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading baudrate of CAN channel 1"); + } + else + { + if (i && (baud != can_info.baud)) + { + CYG_TEST_FAIL_FINISH("Error - different baudrates for CAN channel 0 and 1"); + } + baud = can_info.baud; + ++i; + } +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2 + len = sizeof(can_info); + if (ENOERR != cyg_io_get_config(hCAN_Tbl[2], CYG_IO_GET_CONFIG_CAN_INFO, &can_info, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading baudrate of CAN channel 2"); + } + else + { + if (i && (baud != can_info.baud)) + { + CYG_TEST_FAIL_FINISH("Error - different baudrates for CAN channel 1 and 2"); + } + baud = can_info.baud; + ++i; + } +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3 + len = sizeof(can_info); + if (ENOERR != cyg_io_get_config(hCAN_Tbl[3], CYG_IO_GET_CONFIG_CAN_INFO, &can_info, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading baudrate of CAN channel 3"); + } + else + { + if (i && (baud != can_info.baud)) + { + CYG_TEST_FAIL_FINISH("Error - different baudrates for CAN channel 2 and 3"); + } + baud = can_info.baud; + ++i; + } +#endif + + diag_printf("\n\nYou should no receive 4 CAN messages from each active CAN channel\n"); + + // + // Now each CAN channel sends 10 CAN messages + // + for (i = 0; i < 4; ++i) + { + if (hCAN_Tbl[i]) + { + CYG_CAN_MSG_SET_PARAM(tx_msg, i * 0x100, CYGNUM_CAN_ID_STD, 4, CYGNUM_CAN_FRAME_DATA); + tx_msg.data.dwords[0] = 0; + tx_msg.data.dwords[1] = 0; + char err_msg[64]; + diag_snprintf(err_msg, sizeof(err_msg), "Error sending TX using CAN channel %d", i); + for (j = 0; j < 4; ++j) + { + tx_msg.id = i * 0x100 + j; + tx_msg.data.bytes[0] = j; + len = sizeof(tx_msg); + if (ENOERR != cyg_io_write(hCAN_Tbl[i], &tx_msg, &len)) + { + CYG_TEST_FAIL_FINISH(err_msg); + } + } + } // if (hCAN_Tbl[i]) + } // for (i = 0; i < 4; ++i) + + CYG_TEST_PASS_FINISH("LPC2xxx CAN multi channel TX test OK"); +} + + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0 + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN0_NAME, &hCAN_Tbl[0])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 0"); + } +#else + hCAN_Tbl[0] = 0; +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1 + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN1_NAME, &hCAN_Tbl[1])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 1"); + } +#else + hCAN_Tbl[1] = 0; +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2 + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN2_NAME, &hCAN_Tbl[2])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 2"); + } +#else + hCAN_Tbl[2] = 0; +#endif + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3 + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN3_NAME, &hCAN_Tbl[3])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 3"); + } +#else + hCAN_Tbl[3] = 0; +#endif + + // + // create the thread that accesses the CAN device driver + // + cyg_thread_create(4, can_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 Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG + +//--------------------------------------------------------------------------- +// EOF can_multichan_tx.c diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_rx_tx.c b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_rx_tx.c new file mode 100644 index 00000000..ffab4a5c --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_rx_tx.c @@ -0,0 +1,349 @@ +//========================================================================== +// +// can_rx_tx.c +// +// CAN RX / TX 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: 2007-06-26 +// Description: CAN RX/TX test for 2 CAN channels +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + +// We need two CAN channels +#if defined(CYGPKG_DEVS_CAN_LPC2XXX_CAN0) && defined(CYGPKG_DEVS_CAN_LPC2XXX_CAN1) + + +// The same baud rates are required because we send from one channel to the other one +#if CYGNUM_DEVS_CAN_LPC2XXX_CAN0_KBAUD == CYGNUM_DEVS_CAN_LPC2XXX_CAN1_KBAUD + + +// We need the loop can driver +#if defined(CYGPKG_DEVS_CAN_LOOP) +#include + +#include "can_test_aux.inl" // include CAN test auxiliary functions +//=========================================================================== +// DATA TYPES +//=========================================================================== +typedef struct st_thread_data +{ + cyg_thread obj; + long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; + cyg_handle_t hdl; +} thread_data_t; + + +//=========================================================================== +// LOCAL DATA +//=========================================================================== +cyg_thread_entry_t can_tx_thread; +thread_data_t can0_thread_data; +cyg_thread_entry_t can_rx_thread; +thread_data_t can1_thread_data; +cyg_io_handle_t hCAN_Tbl[2]; +cyg_io_handle_t hLoopCAN_Tbl[2]; + + +//=========================================================================== +// Thread 0 +//=========================================================================== +void can_rx_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_event rx_event; + cyg_can_event loop_rx_event; + cyg_uint32 msg_cnt = 0; + cyg_uint8 i; + + while (msg_cnt < 0xF0) + { + + // + // First receive CAN event from real CAN hardware + // + len = sizeof(rx_event); + if (ENOERR != cyg_io_read(hCAN_Tbl[1], &rx_event, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading from channel 1"); + } + + if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + { + print_can_msg(&rx_event.msg, "RX chan 1:"); + } // if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + else + { + print_can_flags(rx_event.flags, ""); + } + + // + // Now receive CAN event from loop CAN driver + // + len = sizeof(loop_rx_event); + if (ENOERR != cyg_io_read(hLoopCAN_Tbl[1], &loop_rx_event, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading from loop channel 1"); + } + + if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + { + print_can_msg(&rx_event.msg, "RX loop 1:"); + } // if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + else + { + print_can_flags(rx_event.flags, ""); + } + + // + // Chaeck message ID and DLC of HW CAN message and CAN message from loop driver + // booth should be the same + // + if (rx_event.msg.id != loop_rx_event.msg.id) + { + CYG_TEST_FAIL_FINISH("Received message IDs of hw CAN channel and loop CAN channel are not equal"); + } + + if (rx_event.msg.dlc != loop_rx_event.msg.dlc) + { + CYG_TEST_FAIL_FINISH("Received DLCs of hw CAN msg and loop CAN msg are not equal"); + } + + // + // Now check each data byte of the receive message + // + for (i = 0; i < rx_event.msg.dlc; ++i) + { + if (rx_event.msg.data.bytes[i] != loop_rx_event.msg.data.bytes[i]) + { + CYG_TEST_FAIL_FINISH("Data of hw CAN msg and loop CAN msg are not equal"); + } + + if (rx_event.msg.data.bytes[i] != (i + msg_cnt)) + { + CYG_TEST_FAIL_FINISH("CAN message contains unexpected data"); + } + } + + msg_cnt++; + } // while (1) + + CYG_TEST_PASS_FINISH("CAN rx/tx test OK"); +} + + +//=========================================================================== +// Thread 1 +//=========================================================================== +void can_tx_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_message tx_msg; + cyg_uint32 msg_cnt = 0; + cyg_uint8 i; + + + CYG_CAN_MSG_SET_PARAM(tx_msg, 0, CYGNUM_CAN_ID_STD, 0, CYGNUM_CAN_FRAME_DATA); + + // + // Prepare CAN message with a known CAN state + // + for (i = 0; i < 8; ++i) + { + tx_msg.data.bytes[i] = i; + } + + while (msg_cnt < 0xF0) + { + tx_msg.id = msg_cnt; + len = sizeof(tx_msg); + if (ENOERR != cyg_io_write(hCAN_Tbl[0], &tx_msg, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing to channel 0"); + } + + + tx_msg.id = msg_cnt; + len = sizeof(tx_msg); + if (ENOERR != cyg_io_write(hLoopCAN_Tbl[0], &tx_msg, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing to channel 1"); + } + + // + // Increment data in each single data byte + // + for (i = 0; i < 8; ++i) + { + tx_msg.data.bytes[i] += 1; + } + + msg_cnt++; + tx_msg.dlc = (tx_msg.dlc + 1) % 9; + } // while (msg_cnt < 0x100) +} + + +//=========================================================================== +// Entry point +//=========================================================================== +void cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // open CAN device driver channel 1 + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN0_NAME, &hCAN_Tbl[0])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 0"); + } + + + // + // open CAN device driver channel 2 + // + if (ENOERR != cyg_io_lookup(CYGPKG_DEVS_CAN_LPC2XXX_CAN1_NAME, &hCAN_Tbl[1])) + { + CYG_TEST_FAIL_FINISH("Error opening CAN channel 1"); + } + + // + // open Loop CAN device driver channel 1 + // + if (ENOERR != cyg_io_lookup(CYGDAT_DEVS_CAN_LOOP_CAN0_NAME, &hLoopCAN_Tbl[0])) + { + CYG_TEST_FAIL_FINISH("Error opening loop CAN channel 0"); + } + + + // + // open Loop CAN device driver channel 2 + // + if (ENOERR != cyg_io_lookup(CYGDAT_DEVS_CAN_LOOP_CAN1_NAME, &hLoopCAN_Tbl[1])) + { + CYG_TEST_FAIL_FINISH("Error opening loop CAN channel 1"); + } + + + + + + // + // create the first thread that access the CAN device driver + // + cyg_thread_create(5, can_tx_thread, + (cyg_addrword_t) 0, + "can_tx_thread", + (void *) can0_thread_data.stack, + 1024 * sizeof(long), + &can0_thread_data.hdl, + &can0_thread_data.obj); + + // + // create the second thread that access the CAN device driver + // + cyg_thread_create(4, can_rx_thread, + (cyg_addrword_t) 0, + "can_rx_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 // defined(CYGPKG_DEVS_CAN_LOOP) +#define N_A_MSG "Needs support for loop CAN device driver" +#endif + +#else // CYGNUM_DEVS_CAN_LPC2XXX_CAN0_KBAUD == CYGNUM_DEVS_CAN_LPC2XXX_CAN1_KBAUD +#define N_A_MSG "Baudrate of channel 0 and 1 need to be equal" +#endif + +#else // defined(CYGPKG_DEVS_CAN_LPC2XXX_CAN0) && defined(CYGPKG_DEVS_CAN_LPC2XXX_CAN1) +#define N_A_MSG "Needs support for CAN channel 1 and 2" +#endif + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(N_A_MSG); +} +#endif // N_A_MSG + +//--------------------------------------------------------------------------- +// EOF can_rx_tx.c diff --git a/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_test_aux.inl b/packages/devs/can/arm/lpc2xxx/v2_0/tests/can_test_aux.inl new file mode 100644 index 00000000..2946b8fd --- /dev/null +++ b/packages/devs/can/arm/lpc2xxx/v2_0/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 diff --git a/packages/devs/can/loop/v2_0/doc/README b/packages/devs/can/loop/v2_0/doc/README new file mode 100644 index 00000000..78195b63 --- /dev/null +++ b/packages/devs/can/loop/v2_0/doc/README @@ -0,0 +1,2 @@ +The file synth_test.ecm can be used to configure a synthetic target +work tree to enable the various options to allow the tests to be run. \ No newline at end of file diff --git a/packages/devs/can/loop/v2_0/doc/synth_test.ecm b/packages/devs/can/loop/v2_0/doc/synth_test.ecm new file mode 100644 index 00000000..634924ad --- /dev/null +++ b/packages/devs/can/loop/v2_0/doc/synth_test.ecm @@ -0,0 +1,66 @@ +cdl_savefile_version 1; +cdl_savefile_command cdl_savefile_version {}; +cdl_savefile_command cdl_savefile_command {}; +cdl_savefile_command cdl_configuration { description hardware template package }; +cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value }; + +cdl_configuration eCos { + description "" ; + hardware linux ; + template default ; + package -hardware CYGPKG_HAL_SYNTH current ; + package -hardware CYGPKG_HAL_SYNTH_I386 current ; + package -hardware CYGPKG_DEVS_FLASH_SYNTH current ; + package -hardware CYGPKG_DEVS_ETH_ECOSYNTH current ; + package -hardware CYGPKG_DEVS_WATCHDOG_SYNTH current ; + package -hardware CYGPKG_DEVS_WALLCLOCK_SYNTH current ; + package -template CYGPKG_HAL current ; + package -template CYGPKG_IO current ; + package -template CYGPKG_IO_SERIAL current ; + package -template CYGPKG_INFRA current ; + package -template CYGPKG_KERNEL current ; + package -template CYGPKG_MEMALLOC current ; + package -template CYGPKG_ISOINFRA current ; + package -template CYGPKG_LIBC current ; + package -template CYGPKG_LIBC_I18N current ; + package -template CYGPKG_LIBC_SETJMP current ; + package -template CYGPKG_LIBC_SIGNALS current ; + package -template CYGPKG_LIBC_STARTUP current ; + package -template CYGPKG_LIBC_STDIO current ; + package -template CYGPKG_LIBC_STDLIB current ; + package -template CYGPKG_LIBC_STRING current ; + package -template CYGPKG_LIBC_TIME current ; + package -template CYGPKG_LIBM current ; + package -template CYGPKG_IO_WALLCLOCK current ; + package -template CYGPKG_ERROR current ; + package CYGPKG_IO_CAN current ; + package CYGPKG_DEVS_CAN_LOOP current ; +}; + +cdl_component CYGPKG_DEVS_CAN_LOOP_CAN0 { + user_value 1 +}; + +cdl_component CYGPKG_DEVS_CAN_LOOP_CAN1 { + user_value 1 +}; + +cdl_option CYGOPT_IO_CAN_TX_EVENT_SUPPORT { + user_value 1 +}; + +cdl_option CYGOPT_IO_CAN_SUPPORT_NONBLOCKING { + user_value 1 +}; + +cdl_option CYGOPT_IO_CAN_SUPPORT_CALLBACK { + user_value 1 +}; + +cdl_component CYGOPT_IO_CAN_SUPPORT_TIMEOUTS { + user_value 1 +}; + diff --git a/packages/devs/can/loop/v2_0/tests/can_callback.c b/packages/devs/can/loop/v2_0/tests/can_callback.c new file mode 100644 index 00000000..afdf3228 --- /dev/null +++ b/packages/devs/can/loop/v2_0/tests/can_callback.c @@ -0,0 +1,241 @@ +//========================================================================== +// +// can_callback.c +// +// CAN driver test of callback on event +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 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, Alexey Shusharin +// Contributors: Uwe Kindler, Alexey Shusharin +// Date: 2007-08-23 +// Description: CAN driver test of callback on event +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + +// Package option requirements +#if defined(CYGOPT_IO_CAN_SUPPORT_CALLBACK) + +//=========================================================================== +// DATA TYPES +//=========================================================================== +typedef struct st_thread_data +{ + cyg_thread obj; + long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; + cyg_handle_t hdl; +} thread_data_t; + + +//=========================================================================== +// LOCAL DATA +//=========================================================================== +cyg_thread_entry_t can_thread; +thread_data_t can_thread_data; + +cyg_mutex_t can_lock; +cyg_cond_t can_wait; + +cyg_io_handle_t hCAN0; +cyg_io_handle_t hCAN1; + +//=========================================================================== +// LOCAL FUNCTIONS +//=========================================================================== +#include "can_test_aux.inl" // include CAN test auxiliary functions + + +//=========================================================================== +// CALLBACK FUNCTION +//=========================================================================== + +static void callback_func(cyg_uint16 flags, CYG_ADDRWORD data) +{ + if (data == ((CYG_ADDRWORD) hCAN0) && (flags & CYGNUM_CAN_EVENT_RX)) + { + // Wake up thread + cyg_cond_signal(&can_wait); + } +} + +//=========================================================================== +// READER THREAD +//=========================================================================== +void can_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_callback_cfg callback_cfg; + cyg_can_message tx_msg; + cyg_bool_t wait_res; + + // + // open CAN0 device driver + // + if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) + { + CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); + } + + // + // open CAN1 device driver + // + if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1)) + { + CYG_TEST_FAIL_FINISH("Error opening /dev/can1"); + } + + // + // configure CAN0 callback + // + len = sizeof(callback_cfg); + callback_cfg.flag_mask = 0xFFFF; + callback_cfg.data = (CYG_ADDRWORD) hCAN0; + callback_cfg.callback_func = callback_func; + + if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_CALLBACK, + &callback_cfg, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); + } + + // + // transmit message from CAN1 to CAN0 + // + tx_msg.id = 0x001; + tx_msg.ext = CYGNUM_CAN_ID_STD; + tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; + tx_msg.dlc = 0; + len = sizeof(tx_msg); + + if (ENOERR != cyg_io_write(hCAN1, &tx_msg, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing message to /dev/can1"); + } + + // + // Wait CAN0 callback + // + cyg_mutex_lock(&can_lock); + + wait_res = cyg_cond_timed_wait(&can_wait, 100); + + cyg_mutex_unlock(&can_lock); + + // + // If result of wait is a signal operation, test is successed + // If timeout - test is failed, because callback_func() hasn't been + // called with correct parameters + // + if(wait_res) + { + CYG_TEST_PASS_FINISH("can_callback test OK"); + } + else + { + CYG_TEST_FAIL_FINISH("can_callback test FAILED"); + } +} + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + + cyg_mutex_init(&can_lock); + cyg_cond_init(&can_wait, &can_lock); + + // + // create the main thread + // + cyg_thread_create(4, can_thread, + (cyg_addrword_t) 0, + "can_thread", + (void *) can_thread_data.stack, + 1024 * sizeof(long), + &can_thread_data.hdl, + &can_thread_data.obj); + + cyg_thread_resume(can_thread_data.hdl); + + cyg_scheduler_start(); +} + +#else // #if defined(CYGOPT_IO_CAN_SUPPORT_CALLBACK) +#define N_A_MSG "Needs callback support" +#endif + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs IO/CAN and Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG); +} +#endif // N_A_MSG + +// EOF can_callback.c diff --git a/packages/devs/can/m68k/mcf52xx/v2_0/tests/flexcan_wake.c b/packages/devs/can/m68k/mcf52xx/v2_0/tests/flexcan_wake.c new file mode 100644 index 00000000..92400a21 --- /dev/null +++ b/packages/devs/can/m68k/mcf52xx/v2_0/tests/flexcan_wake.c @@ -0,0 +1,247 @@ +//========================================================================== +// +// flexcan_wake.c +// +// FlexCAN wake 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 test of standby and wake +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + + +//=========================================================================== +// 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_event1; + cyg_can_event rx_event2; + cyg_can_msgbuf_info msgbox_info; + cyg_can_mode mode; + cyg_can_state state; + + + 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 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"); + + 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) + { + // + // now we set FlexCAN into standby mode + // + mode = CYGNUM_CAN_MODE_STANDBY; + 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 in standby mode + // + 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_STANDBY) + { + CYG_TEST_FAIL_FINISH("Error stopping FlexCAN /dev/can0"); + } + + // + // as soon as a message arrives the FlexCAN modul leaves standby mode + // and we should receive a CYGNUM_CAN_EVENT_LEAVING_STANDBY event but + // we will also receive a RX event because a message arrived + // + len = sizeof(rx_event1); + if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event1, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); + } + + len = sizeof(rx_event2); + if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event2, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); + } + + print_can_flags(rx_event1.flags, ""); + print_can_flags(rx_event2.flags, ""); + + // + // The first event we receive should be a leaving standby event because + // first flexcan leaves standby and then a message will be received + // + if (!(rx_event1.flags & CYGNUM_CAN_EVENT_LEAVING_STANDBY)) + { + CYG_TEST_FAIL_FINISH("CYGNUM_CAN_EVENT_LEAVING_STANDBY event expexted /dev/can0"); + } + + if (rx_event2.msg.id == 0x100) + { + CYG_TEST_PASS_FINISH("flexcan_wake 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"); + } + + + // + // 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_wake.c diff --git a/packages/devs/disk/generic/mmc/v2_0/ChangeLog b/packages/devs/disk/generic/mmc/v2_0/ChangeLog new file mode 100644 index 00000000..981767da --- /dev/null +++ b/packages/devs/disk/generic/mmc/v2_0/ChangeLog @@ -0,0 +1,110 @@ +2007-05-30 Hajime Ishitani + + * src/mmc_spi.c: Revise debug information with addition. + Add idle to operational retry wait. + * cdl/devs_disk_mmc.cdl: Add idle to operational retry wait parameter. + +2006-09-27 Sergei Gavrikov + + * src/mmc_spi.c: (mmc_spi_disk_lookup): just fixed a missed + semicolon. + +2006-09-21 Jonathan Larmour + + * Contribution of MMC/SPI package from eCosCentric. eCosCentric + changes prior to contribution are included below for reference: + + 2006-09-20 Jonathan Larmour + + * src/mmc_spi.c: DISK_FUNS, DISK_CHANNEL and DISK_CONTROLLER are now + implicitly static. + Update DISK_CHANNEL for new io/disk macro definition. + + 2006-04-05 John Dallaway + + * cdl/devs_disk_mmc.cdl: Add reference to package documentation. + + 2006-03-17 Jonathan Larmour + + * src/mmc_spi.c (struct cyg_mmc_spi_disk_info_t): Store underlying + medium's read/write block length. + (mmc_spi_check_for_disk): Store underlying medium's + read/write block length. + (mmc_spi_disk_lookup): Report medium block size to disk layer. + (mmc_spi_disk_read): API now requires sector reads to be with length + of sectors not bytes. + (mmc_spi_disk_write): Ditto. + + 2005-10-28 Jonathan Larmour + + * include/mmc_protocol.h: Move from src/ to here. + * src/mmc_spi.c: Reflect above move. + + 2004-08-30 Bart Veer + + * src/mmc_spi.c (mmc_spi_write_disk_block): disable background + writes. Some MMC cards don't seem to implement this correctly so + if you are trying to talking to another SPI device the MMC card + still replies. + + 2004-07-03 Bart Veer + + * src/mmc_spi.c (MMC_SPI_READ_DATA_TOKEN_RETRIES): increase the + number of iterations. With some cards a read can occasionally take + 50* longer than normal. + + 2004-07-01 Bart Veer + + * src/mmc_spi.c: reorganize write code, to work around problems + with some cards. + + 2004-06-29 Bart Veer + + * src/mmc_spi.c: some cards require an extra delay during a mount + sequence, when doing the first read of a data block. Also added + some recovery code to the mount code in case a previous session + left the card still sending data. + + 2004-06-15 Bart Veer + + * src/mmc_spi.c (mmc_spi_check_for_disk): allow platform HALs to + customize the mount sequence. + + * doc/disk_mmc.sgml: document the above change. + + 2004-04-25 Bart Veer + + * MMC package created + + //=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004, 2005, 2006 eCosCentric Ltd. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/disk/generic/mmc/v2_0/cdl/devs_disk_mmc.cdl b/packages/devs/disk/generic/mmc/v2_0/cdl/devs_disk_mmc.cdl new file mode 100644 index 00000000..cf813c35 --- /dev/null +++ b/packages/devs/disk/generic/mmc/v2_0/cdl/devs_disk_mmc.cdl @@ -0,0 +1,113 @@ +# ==================================================================== +# +# devs_disk_mmc.cdl +# +# Support for MMC cards +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2004, 2005, 2006 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): bartv,jlarmour +# Date: 2004-04-25 +# +#####DESCRIPTIONEND#### +# ==================================================================== + +cdl_package CYGPKG_DEVS_DISK_MMC { + display "Disk driver for MMC cards" + doc ecos-ref/devs-disk-mmc-part.html + + include_dir cyg/io + + parent CYGPKG_IO_DISK_DEVICES + active_if CYGPKG_IO_DISK + + cdl_interface CYGINT_DEVS_DISK_MMC_SPI_CONNECTORS { + active_if CYGPKG_IO_SPI + display "Number of MMC connectors accessed via SPI" + } + + cdl_component CYGPKG_DEVS_DISK_MMC_SPI { + display "Access an MMC card via an SPI bus" + default_value { CYGINT_DEVS_DISK_MMC_SPI_CONNECTORS > 0 } + compile -library=libextras.a mmc_spi.c + requires CYGPKG_ERROR CYGPKG_LIBC_STRING + description " + This option enables support for accessing an MMC card via an + SPI bus." + + define_proc { + puts $::cdl_system_header "/***** MMC/SPI disk driver output start *****/" + puts $::cdl_system_header "#ifndef CYGDAT_DEVS_DISK_CFG" + puts $::cdl_system_header "#define CYGDAT_DEVS_DISK_CFG " + puts $::cdl_system_header "#endif" + puts $::cdl_system_header "/***** MMC/SPI disk driver output end *****/" + } + + cdl_option CYGDAT_DEVS_DISK_MMC_SPI_DISK0_NAME { + display "Device name for the MMC/SPI disk 0 device" + flavor data + default_value { "\"/dev/hd0/\"" } + description " + This is the device name used to access the raw disk device + in eCos, for example for mount operations. Note that the + trailing slash must be present." + + # Testing support. For now just hard-code some values for partition 0 + # on the card. + define_proc { + puts $::cdl_header "#define CYGDAT_DEVS_DISK_TEST_DEVICE CYGDAT_DEVS_DISK_MMC_SPI_DISK0_NAME \"1\"" + puts $::cdl_header "#define CYGDAT_DEVS_DISK_TEST_MOUNTPOINT \"/dosfs\"" + puts $::cdl_header "#define CYGDAT_DEVS_DISK_TEST_DIRECTORY \"/test\"" + } + } + + cdl_option CYGIMP_DEVS_DISK_MMC_SPI_POLLED { + display "Run the driver in polled mode rather than interrupt-driven" + default_value !CYGPKG_KERNEL + description " + By default the MMC disk driver will operate in interrupt-driven + mode if the kernel is present, i.e. if the application is likely + to be multi-threaded. Otherwise it will operate in polled mode." + } + cdl_option CYGPKG_DEVS_DISK_MMC_SPI_IDLE_RETRIES_WAIT { + display "Idle to operational retry wait" + flavor booldata + default_value 10000 + description " + This option sets how long to wait between retries of attempts to change the + card state from idle to operational. It is measured in microseconds." + } +} + +# EOF devs_disk_mmc.cdl diff --git a/packages/devs/disk/generic/mmc/v2_0/doc/disk_mmc.sgml b/packages/devs/disk/generic/mmc/v2_0/doc/disk_mmc.sgml new file mode 100644 index 00000000..f1afe05f --- /dev/null +++ b/packages/devs/disk/generic/mmc/v2_0/doc/disk_mmc.sgml @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +MMC MultiMedia Card Disk Driver + + + + Device Driver for MMC MultiMedia Cards + + + CYGPKG_DEVS_DISK_MMC + eCos Support for MMC MultiMedia Cards + + + Description + +This package provides a disk device driver for MultiMediaCards (MMC). +A MultiMediaCard provides non-volatile storage in a small footprint +(24mm * 32mm * 1.4mm), and weighing less than 2 grams. Typical +card sizes are 16MB to 128MB, with an upper limit of 4GB. It +should be noted that these sizes are measured in millions of bytes, +not 2^20. The MultiMediaCard +Association defines the standard for these cards. + + +At the hardware level there are two ways of accessing an MMC card, +either using a custom interface or via an SPI bus. A card will detect +the interface in use at run-time. The custom interface allows for +better performance but requires additional hardware. Currently only +SPI mode is supported by this package. + + +Theoretically an MMC card can be used with any file system. In +practice all cards are formatted for PC compatibility, with a +partition table in the first block and a single FAT file system on the +rest of the card. Currently this package checks the format of the MMC +card and will only allow access to a card if it is formatted this way. + + +An MMC socket allows cards to be removed and inserted at any time. The +device driver will detect removal events when the next I/O operation +happens and will report them to higher-level code via an error code +ENODEV. However there are no guarantees that the +higher-level code will be able to recover from this error. The +expected usage is that application code will explicitly +mount the card before attempting any file I/O, +and will umount the card before it is removed. +Between these operations the system is likely to keep some disk blocks +cached, for performance reasons. If the card is removed before the +umount then it may end up with a corrupted file +system, and the disk subsystem may be left in an inconsistent state. +Regular uses of sync will reduce the risk +of file system corruption. + + + + Configuration Options + +CYGPKG_DEVS_DISK_MMC is a hardware package which +should get loaded automatically when you configure for a suitable eCos +target platform. In this case suitable means that the hardware has an +MMC socket connected to an SPI bus, that an SPI bus driver package +exists and is also automatically loaded, and that the platform HAL +provides information +on how the card is connected to the SPI bus. + + +The package depends on support from the generic disk package +CYGPKG_IO_DISK. That will not be loaded +automatically: the presence of an MMC socket on the board does not +mean that the application has any need for a file system. Hence by +default CYGPKG_DEVS_DISK_MMC will be inactive and +will not contribute any code or data to the application's memory +footprint. To activate the driver it will be necessary to add one or +more packages to the configuration using +ecosconfig add or the graphical configuration +tool: the generic disk support CYGPKG_IO_DISK; +usually a file system, CYGPKG_FS_FAT; support for +the file I/O API CYGPKG_IO_FILEIO; and possibly +additional support packages that may be needed by the file system, for +example CYGPKG_LINUX_COMPAT. Depending on the +template used to create the initial configuration some of these may be +loaded already. + + +The package provides two main configuration options. +CYGDAT_DEVS_DISK_MMC_SPI_DISK0_NAME specifies the +name of the raw disk device, for example /dev/hd0. +Allowing for partition tables that makes /dev/hd0/1 +the first argument that shoul be passed to a +mount call. If the hardware has multiple disk +devices then each one will need a unique name. +CYGIMP_DEVS_DISK_MMC_SPI_POLLED controls whether +the SPI bus will be accessed in interrupt-driven or polled mode. It +will default to interrupt-driven if the application is multi-threaded, +which is assumed to be the case if the kernel is present. If the +kernel is absent, for example in a RedBoot configuration, then the +driver will default to polled mode. With some hardware polled mode may +significantly increase disk throughput even in a multi-threaded +application, but will consume cpu cycles that could be used by other +threads. + + + + Additional Functionality + +The disk driver package exports a variable +cyg_mmc_spi_polled. This defaults to true or false +depending on the configuration option +CYGIMP_DEVS_DISK_MMC_SPI_POLLED. If the default +mode is interrupt-driven then file I/O, including mount operations, +are only allowed when the scheduler has started and interrupts have +been enabled. Any attempts at file I/O earlier during system +initialization, for example inside a C++ static constructor, will lock +up. If it is necessary to perform file I/O at this time then the +driver can be temporarily switched to polling mode before the I/O +operation by setting cyg_mmc_spi_polled, and +clearing it again after the I/O. Alternatively the default mode can be +changed to polling by editing the configuration, and then the +main() thread can change the mode to +interrupt-driven once the scheduler has started. + + + + Porting to New Hardware + +Assuming that the MMC connector is hooked up to a standard SPI bus and +that there is already an eCos SPI bus driver, porting the MMC disk +driver package should be straightforward. Some other package, usually +the platform HAL, should provide a cyg_spi_device +structure cyg_spi_mmc_dev0. That structure contains +the information needed by this package to interact with the MMC card +via the usual SPI interface, for example how to activate the +appropriate chip select. The platform HAL should also implement the +CDL interface CYGINT_DEVS_DISK_MMC_SPI_CONNECTORS. + + +When defining cyg_spi_mmc_dev0 special care must be +taken with the chip select. The MMC protocol is transaction-oriented. +For example a read operation involves an initial command sent to the +card, then a reply, then the actual data, and finally a checksum. The +card's chip select must be kept asserted for the entire operation, and +there can be no interactions with other devices on the same SPI bus +during this time. + + +Optionally the platform HAL may define a macro +HAL_MMC_SPI_INIT which will be invoked during a +mount operation. This can take any hardware-specific actions that may +be necessary, for example manipulating GPIO pins. Usually no such +macro is needed because the hardware is set up during platform +initialization. + + +Currently the package does not provide any support for accessing MMC +cards using an interface other than SPI. On some targets there may be +additional hardware to detect events such as card insertion or +removal, but there is no support for exploiting such hardware at +present. + + +Only a single MMC socket is supported. Extending the package to +support multiple sockets would be straightforward but it seems +unlikely that any hardware would come with multiple MMC sockets. Given +the nature of SPI buses there is a problem if the MMC socket is hooked +up via an expansion connector rather than being attached to the main +board. The platform HAL would not know about the socket so would not +implement the CDL interface +CYGINT_DEVS_DISK_MMC_SPI_CONNECTORS, and the +ecos.db target entry would not include +CYGPKG_DEVS_DISK_MMC. Because this is a hardware +package it cannot easily be added by hand. Instead this scenario would +require some editing of the existing platform HAL and target entry. + + + + + diff --git a/packages/devs/disk/generic/mmc/v2_0/include/mmc_protocol.h b/packages/devs/disk/generic/mmc/v2_0/include/mmc_protocol.h new file mode 100644 index 00000000..b59b8b38 --- /dev/null +++ b/packages/devs/disk/generic/mmc/v2_0/include/mmc_protocol.h @@ -0,0 +1,175 @@ +#ifndef CYGONCE_DEVS_DISK_MMC_PROTOCOL_H +#define CYGONCE_DEVS_DISK_MMC_PROTOCOL_H +//========================================================================== +// +// mmc_protocol.h +// +// Define the protocol used for interacting with MMC cards +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004, 2005 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: bartv +// Contributors: jlarmour +// Date: 2004-04-25 +// Usage: Only this package and implementing device drivers should +// include this header file. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include /* Common types */ + +// The MMC command set. A request is a six-byte sequence. First a +// single command byte, one of the following with bit 6 (0x40) or'd in +// and bit 7 clear as a start bit. Then a four-byte argument, usually +// a 32-bit integer most significant byte first. Finally a 7-bit CRC +// and a stop bit. In SPI mode the CRC is usually optional, except for +// the GO_IDLE_STATE command. +// +// Commands ALL_SEND_CID, SEND_RELATIVE_ADDR, SET_DSR, +// SELECT_DESELECT, READ_DATA_UNTIL_STOP, STOP_TRANSMISSION, +// GO_INACTIVE, READ_MULTIPLE_BLOCK, WRITE_DATA_UNTIL_STOP, +// WRITE_MULTIPLE_BLOCK, and PROGRAM_CID are MMC only, and not +// available in SPI mode. +// +// Device drivers may use values with bit 7 set to indicate +// driver-specific commands. + +#define MMC_REQUEST_GO_IDLE_STATE 0x00 +#define MMC_REQUEST_SEND_OP_COND 0x01 +#define MMC_REQUEST_ALL_SEND_CID 0x02 +#define MMC_REQUEST_SEND_RELATIVE_ADDR 0x03 +#define MMC_REQUEST_SET_DSR 0x04 +#define MMC_REQUEST_SELECT_DESELECT 0x07 +#define MMC_REQUEST_SEND_CSD 0x09 +#define MMC_REQUEST_SEND_CID 0x0A +#define MMC_REQUEST_READ_DATA_UNTIL_STOP 0x0B +#define MMC_REQUEST_STOP_TRANSMISSION 0x0C +#define MMC_REQUEST_SEND_STATUS 0x0D +#define MMC_REQUEST_GO_INACTIVE 0x0F +#define MMC_REQUEST_SET_BLOCKLEN 0x10 +#define MMC_REQUEST_READ_SINGLE_BLOCK 0x11 +#define MMC_REQUEST_READ_MULTIPLE_BLOCK 0x12 +#define MMC_REQUEST_WRITE_DATA_UNTIL_STOP 0x14 +#define MMC_REQUEST_WRITE_BLOCK 0x18 +#define MMC_REQUEST_WRITE_MULTIPLE_BLOCK 0x19 +#define MMC_REQUEST_PROGRAM_CID 0x1A +#define MMC_REQUEST_PROGRAM_CSD 0x1B +#define MMC_REQUEST_SET_WRITE_PROT 0x1C +#define MMC_REQUEST_CLR_WRITE_PROT 0x1D +#define MMC_REQUEST_SEND_WRITE_PROT 0x1E +#define MMC_REQUEST_TAG_SECTOR_START 0x20 +#define MMC_REQUEST_TAG_SECTOR_END 0x21 +#define MMC_REQUEST_UNTAG_SECTOR 0x22 +#define MMC_REQUEST_TAG_ERASE_GROUP_START 0x23 +#define MMC_REQUEST_TAG_ERASE_GROUP_END 0x24 +#define MMC_REQUEST_UNTAG_ERASE_GROUP 0x25 +#define MMC_REQUEST_ERASE 0x26 +#define MMC_REQUEST_LOCK_UNLOCK 0x2A +#define MMC_REQUEST_READ_OCR 0x3A +#define MMC_REQUEST_CRC_ON_OFF 0x3B + +// Response formats are different for MMC vs. SPI mode, so are defined +// in the appropriate source files. + +// The CID register is generally treated as an opaque data structure +// used only for unique identification of cards. +typedef struct mmc_cid_register { + cyg_uint8 cid_data[16]; +} mmc_cid_register; + +#define MMC_CID_REGISTER_MID(_data_) ((_data_)->cid_data[0]) +#define MMC_CID_REGISTER_OID(_data_) (((_data_)->cid_data[1] << 8) | \ + ((_data_)->cid_data[2])) +#define MMC_CID_REGISTER_PNM(_data_) ((const char*)&((_data_)->cid_data[3])) +#define MMC_CID_REGISTER_PRV(_data_) ((_data_)->cid_data[9]) +#define MMC_CID_REGISTER_PSN(_data_) (((_data_)->cid_data[10] << 24) | \ + ((_data_)->cid_data[11] << 16) | \ + ((_data_)->cid_data[12] << 8) | \ + ((_data_)->cid_data[13])) +#define MMC_CID_REGISTER_MDT(_data_) ((_data_)->cid_data[14]) +#define MMC_CID_REGISTER_CRC(_data_) ((_data_)->cid_data[15] >> 1) + + +// The CSD register is just lots of small bitfields. For now keep it +// as an array of 16 bytes and provide macros to read the fields. +typedef struct mmc_csd_register { + cyg_uint8 csd_data[16]; +} mmc_csd_register; + +#define MMC_CSD_REGISTER_CSD_STRUCTURE(_data_) (((_data_)->csd_data[0] & 0x00C0) >> 6) +#define MMC_CSD_REGISTER_SPEC_VERS(_data_) (((_data_)->csd_data[0] & 0x003C) >> 2) +#define MMC_CSD_REGISTER_TAAC_MANTISSA(_data_) (((_data_)->csd_data[1] & 0x0078) >> 3) +#define MMC_CSD_REGISTER_TAAC_EXPONENT(_data_) ((_data_)->csd_data[1] & 0x0007) +#define MMC_CSD_REGISTER_NSAC(_data_) ((_data_)->csd_data[2]) +#define MMC_CSD_REGISTER_TRAN_SPEED_MANTISSA(_data_) (((_data_)->csd_data[3] & 0x0078) >> 3) +#define MMC_CSD_REGISTER_TRAN_SPEED_EXPONENT(_data_) ((_data_)->csd_data[3] & 0x0007) +#define MMC_CSD_REGISTER_CCC(_data_) (((_data_)->csd_data[4] << 4) | (((_data_)->csd_data[5] & 0x00F0) >> 4)) +#define MMC_CSD_REGISTER_READ_BL_LEN(_data_) ((_data_)->csd_data[5] & 0x000F) +#define MMC_CSD_REGISTER_READ_BL_PARTIAL(_data_) (((_data_)->csd_data[6] & 0x0080) >> 7) +#define MMC_CSD_REGISTER_WRITE_BLK_MISALIGN(_data_) (((_data_)->csd_data[6] & 0x0040) >> 6) +#define MMC_CSD_REGISTER_READ_BLK_MISALIGN(_data_) (((_data_)->csd_data[6] & 0x0020) >> 5) +#define MMC_CSD_REGISTER_DSR_IMP(_data_) (((_data_)->csd_data[6] & 0x0010) >> 4) +#define MMC_CSD_REGISTER_C_SIZE(_data_) ((((_data_)->csd_data[6] & 0x0003) << 10) | \ + ((_data_)->csd_data[7] << 2) | \ + (((_data_)->csd_data[8] & 0x00C0) >> 6)) +#define MMC_CSD_REGISTER_VDD_R_CURR_MIN(_data_) (((_data_)->csd_data[8] & 0x0038) >> 3) +#define MMC_CSD_REGISTER_VDD_R_CURR_MAX(_data_) ((_data_)->csd_data[8] & 0x0007) +#define MMC_CSD_REGISTER_VDD_W_CURR_MIN(_data_) (((_data_)->csd_data[9] & 0x00E0) >> 5) +#define MMC_CSD_REGISTER_VDD_W_CURR_MAX(_data_) (((_data_)->csd_data[9] & 0x001C) >> 2) +#define MMC_CSD_REGISTER_C_SIZE_MULT(_data_) ((((_data_)->csd_data[9] & 0x0003) << 1) | \ + (((_data_)->csd_data[10] & 0x0080) >> 7)) +#define MMC_CSD_REGISTER_SECTOR_SIZE(_data_) (((_data_)->csd_data[10] & 0x007C) >> 2) +#define MMC_CSD_REGISTER_ERASE_GRP_SIZE(_data_) ((((_data_)->csd_data[10] & 0x0003) << 3) | \ + (((_data_)->csd_data[11] & 0x00E0) >> 5)) +#define MMC_CSD_REGISTER_WR_GRP_SIZE(_data_) ((_data_)->csd_data[11] & 0x001F) +#define MMC_CSD_REGISTER_WR_GRP_ENABLE(_data_) (((_data_)->csd_data[12] & 0x0080) >> 7) +#define MMC_CSD_REGISTER_DEFAULT_ECC(_data_) (((_data_)->csd_data[12] & 0x0060) >> 5) +#define MMC_CSD_REGISTER_R2W_FACTOR(_data_) (((_data_)->csd_data[12] & 0x001C) >> 2) +#define MMC_CSD_REGISTER_WRITE_BL_LEN(_data_) ((((_data_)->csd_data[12] & 0x0003) << 2) | \ + (((_data_)->csd_data[13] & 0x00C0) >> 6)) +#define MMC_CSD_REGISTER_WR_BL_PARTIAL(_data_) (((_data_)->csd_data[13] & 0x0020) >> 5) +#define MMC_CSD_REGISTER_FILE_FORMAT_GROUP(_data_) (((_data_)->csd_data[14] & 0x0080) >> 7) +#define MMC_CSD_REGISTER_COPY(_data_) (((_data_)->csd_data[14] & 0x0040) >> 6) +#define MMC_CSD_REGISTER_PERM_WRITE_PROTECT(_data_) (((_data_)->csd_data[14] & 0x0020) >> 5) +#define MMC_CSD_REGISTER_TMP_WRITE_PROTECT(_data_) (((_data_)->csd_data[14] & 0x0010) >> 4) +#define MMC_CSD_REGISTER_FILE_FORMAT(_data_) (((_data_)->csd_data[14] & 0x000C) >> 2) +#define MMC_CSD_REGISTER_ECC(_data_) ((_data_)->csd_data[14] & 0x0003) +#define MMC_CSD_REGISTER_CRC(_data_) (((_data_)->csd_data[15] & 0xFE) >> 1) + + +#endif // ifdef CYGONCE_DEVS_DISK_MMC_PROTOCOL_H + +/* EOF mmc_protocol.h */ diff --git a/packages/devs/disk/generic/mmc/v2_0/src/mmc_spi.c b/packages/devs/disk/generic/mmc/v2_0/src/mmc_spi.c new file mode 100644 index 00000000..6ee0d407 --- /dev/null +++ b/packages/devs/disk/generic/mmc/v2_0/src/mmc_spi.c @@ -0,0 +1,1194 @@ +//========================================================================== +// +// mmc_spi.c +// +// Provide a disk device driver for MMC cards over SPI +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004, 2006 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: bartv +// Date: 2004-04-25 +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include +#include +#include +#include +#include +#include // delays +#include +#include +#include +#include +#include +#include +#include +#include + +// Communication parameters. First some debug support +#define DEBUG 0 +#if DEBUG > 0 +# define DEBUG1(format, ...) diag_printf(format, ## __VA_ARGS__) +#else +# define DEBUG1(format, ...) +#endif +#if DEBUG > 1 +# define DEBUG2(format, ...) diag_printf(format, ## __VA_ARGS__) +#else +# define DEBUG2(format, ...) +#endif + +// Should the SPI operations run in polled or interrupt-driven mode? +// The default value is determined by CDL, but can be overridden at +// run-time if necessary. For example if configured for +// interrupt-driven I/O then it will be impossible to perform disk +// operations during system initialization, e.g. from a static +// constructor, unless this flag is changed for the duration. +#ifdef CYGIMP_DEVS_DISK_MMC_SPI_POLLED +cyg_bool cyg_mmc_spi_polled = true; +#else +cyg_bool cyg_mmc_spi_polled = false; +#endif + +// Should write operations be allowed to complete in the background, +// or must the operation complete in the foreground. The latter +// requires polling for potentially a long time, up to some 100's of +// milliseconds, but the former appears unreliable if there are other +// devices on the SPI bus. In theory the MMC card should detect that +// the chip select line is dropped and tristate the output line, but +// in practice this does not always happen. +#undef MMC_SPI_BACKGROUND_WRITES + +// The size of each disk block +#define MMC_SPI_BLOCK_SIZE 512 +// The number of retries during a mount operation when switching to +// IDLE mode. +#define MMC_SPI_GO_IDLE_RETRIES 16 +// The number of retries during a mount operation when switching from +// idle to operational +#define MMC_SPI_OP_COND_RETRIES 128 +// The number of retries when waiting for a response to any command +#define MMC_SPI_COMMAND_RETRIES 32 +// Retries when waiting for a data response token during a read +#define MMC_SPI_READ_DATA_TOKEN_RETRIES 32768 +// Retries during a write while waiting for completion +#define MMC_SPI_WRITE_BUSY_RETRIES 32768 + +// ---------------------------------------------------------------------------- +// SPI-specific parts of the MMC protocol. +// +// The main response byte. 0 indicates success, other bits +// indicate various error conditions. +#define MMC_REPLY_SUCCESS 0x00 +#define MMC_REPLY_PARAMETER_ERROR (0x01 << 6) +#define MMC_REPLY_ADDRESS_ERROR (0x01 << 5) +#define MMC_REPLY_ERASE_SEQUENCE_ERROR (0x01 << 4) +#define MMC_REPLY_COM_CRC_ERROR (0x01 << 3) +#define MMC_REPLY_ILLEGAL_COMMAND (0x01 << 2) +#define MMC_REPLY_ERASE_RESET (0x01 << 1) +#define MMC_REPLY_IN_IDLE_STATE (0x01 << 0) + +// A send-status command generates a second response byte +#define MMC_REPLY2_OUT_OF_RANGE (0x01 << 7) +#define MMC_REPLY2_ERASE_PARAM (0x01 << 6) +#define MMC_REPLY2_WP_VIOLATION (0x01 << 5) +#define MMC_REPLY2_CARD_ECC_FAILED (0x01 << 4) +#define MMC_REPLY2_CC_ERROR (0x01 << 3) +#define MMC_REPLY2_ERROR (0x01 << 2) +#define MMC_REPLY2_WP_ERASE_SKIP (0x01 << 1) +// Alias for the above +#define MMC_REPLY2_LOCK_UNLOCK_FAILED (0x01 << 1) +#define MMC_REPLY2_CARD_LOCKED (0x01 << 0) + +// The data error token byte which may get sent if a read +// operation fails. The top 3 bits will be 0. A successful +// response will have these bits 1. +#define MMC_DATA_TOKEN_SUCCESS (0x00FE) +#define MMC_DATA_ERROR_TOKEN_CARD_LOCKED (0x01 << 4) +#define MMC_DATA_ERROR_TOKEN_OUT_OF_RANGE (0x01 << 3) +#define MMC_DATA_ERROR_TOKEN_CARD_ECC_FAILED (0x01 << 2) +#define MMC_DATA_ERROR_TOKEN_CC_ERROR (0x01 << 1) +#define MMC_DATA_ERROR_TOKEN_ERROR (0x01 << 0) + +// ---------------------------------------------------------------------------- +// Structures and statics. +// +// There should be an SPI device cyg_spi_mmc_dev0, probably provided by +// the HAL, possibly by the application. Because of the latter we cannot +// assume the variable will be defined in a header. +extern cyg_spi_device cyg_spi_mmc_dev0; + +// When retrieving data it is necessary to send an 0xff byte stream, +// which the card will not confuse with further commands. The largest +// transfer is 512 bytes, too large a buffer to place on the stack. +static cyg_uint8 mmc_spi_ff_data[512]; +#define MMC_SPI_INIT_FF_DATA() \ + CYG_MACRO_START \ + memset(mmc_spi_ff_data, 0x00FF, 512); \ + CYG_MACRO_END + +// Details of a specific MMC card +typedef struct cyg_mmc_spi_disk_info_t { + cyg_spi_device* mmc_spi_dev; + cyg_uint32 mmc_saved_baudrate; + cyg_uint32 mmc_block_count; +#ifdef MMC_SPI_BACKGROUND_WRITES + cyg_bool mmc_writing; +#endif + cyg_bool mmc_read_only; + cyg_bool mmc_connected; + cyg_uint32 mmc_heads_per_cylinder; + cyg_uint32 mmc_sectors_per_head; + cyg_uint32 mmc_read_block_length; + cyg_uint32 mmc_write_block_length; + mmc_cid_register mmc_id; +} cyg_mmc_spi_disk_info_t; + +// There is no need for a hardware-specific disk controller structure. +// The closest equivalent is probably an SPI bus, i.e. if there were +// MMC connectors attached to different SPI buses then these would +// have separate controllers with independent locking. However that +// can be handled without a cyg_mmc_spi_controller_info_t structure. + +// ---------------------------------------------------------------------------- +// The low-level MMC operations + +// After power-on an MMC card is in idle state and needs at least 74 +// clock cycles before any communication. These might be supplied +// courtesy of another SPI device, but no guarantees, so generate some +// ticks. +static void +mmc_spi_send_init(cyg_mmc_spi_disk_info_t* disk) +{ + cyg_spi_bus *bus; + cyg_spi_device *dev; + + DEBUG2("mmc_spi_send_init(): dev pointer 0x%p, %d\n", disk->mmc_spi_dev, cyg_mmc_spi_polled ); + dev = disk->mmc_spi_dev; + bus = dev->spi_bus; + DEBUG2(" : begin pointer %p\n", bus->spi_transaction_begin ); + cyg_spi_tick(disk->mmc_spi_dev, cyg_mmc_spi_polled, 10); +} + +// Send the first part of a command sequence. This consists of the +// command itself, an argument, a CRC, and then waiting for a +// reply byte from the card. +static cyg_uint32 +mmc_spi_send_command_start(cyg_mmc_spi_disk_info_t* disk, cyg_uint32 command, cyg_uint32 arg) +{ + cyg_spi_device* dev = disk->mmc_spi_dev; + cyg_uint8 request[7]; + cyg_uint8 response[7]; + cyg_uint8 reply; + int i; + +#ifdef MMC_SPI_BACKGROUND_WRITES + // If the last operation was a block write, those can take a while + // to complete. Rather than wait at the end of the write(), do so + // at the beginning of the next operation i.e. here. This also + // allows the chip select to be dropped while the write comples, + // so communication is possible with other devices. The polling is + // done as a sequence of transactions rather than in a single + // transaction, again to let other threads in to communicate with + // other devices. + // + // The card will send a stream of 0x00 bytes while the write + // completes. Some cards have been observed to send a byte 0x03 at + // the end, Either way, when the card sends a byte 0xff it should + // be ready for the next command. + if (disk->mmc_writing) { + DEBUG2("mmc_spi_send_command_start(): polling for completion of previous write\n"); + disk->mmc_writing = 0; + response[0] = 0x00; + for (i = 0; (i < MMC_SPI_WRITE_BUSY_RETRIES) && (0x00FF != response[0]); i++) { + cyg_spi_transfer(dev, cyg_mmc_spi_polled, 1, mmc_spi_ff_data, response); + } + } +#endif + + request[0] = command | 0x0040; + request[1] = (arg >> 24) & 0x00FF; + request[2] = (arg >> 16) & 0x00FF; + request[3] = (arg >> 8) & 0x00FF; + request[4] = arg & 0x00FF; + // A CRC is needed for the go-idle-state command, because that + // command switches the device from MMC to SPI mode. That CRC is + // well-known. Once in SPI mode the card will not use CRCs by + // default. + request[5] = (command == 0x00) ? 0x0095 : 0x00ff; + // There will need to be at least one extra byte transfer to get + // the card's response, so send that straightaway. Extra + // outgoing data like this should be 0xff so that the card + // does not confuse it with a new incoming command. + request[6] = 0x00ff; + + // Lock the SPI bus. It remains locked until a subsequent call to + // mmc_spi_end_command(). + cyg_spi_transaction_begin(dev); + + // Transfer the whole command, and try to read the response back + // immediately. + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, 7, request, response, 0); + DEBUG2("Sent command %02x %d: reply bytes %02x %02x %02x %02x %02x %02x %02x\n", command, arg, \ + response[0], response[1], response[2], response[3], response[4], response[5], response[6]); + + // The response will be a single byte with the top bit clear. + // The remaining bits are error/status flags. If the command + // involves an additional response then that will be handled + // by the calling code. + reply = response[6]; + for (i = 0; (i < MMC_SPI_COMMAND_RETRIES) && (0 != (reply & 0x0080)); i++) { + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, 1, mmc_spi_ff_data, response, 0); + reply = response[0]; + DEBUG2(" loop %d, additional reply %02x\n", i, reply); + } + + // Leave the interpretation of the reply code to the caller + return (cyg_uint32) reply; +} + +// At the end of each command the card needs eight clocks to finish +// its processing. A tick() call takes care of that, and will have +// the side effect of dropping the chip select. Ending the transaction +// unlocks the bus for other SPI I/O operations +static void +mmc_spi_end_command(cyg_mmc_spi_disk_info_t* disk) +{ + cyg_spi_device* dev = disk->mmc_spi_dev; + cyg_spi_transaction_tick(dev, cyg_mmc_spi_polled, 1); + cyg_spi_transaction_end(dev); +} + +// A utility combination of the above two for simple commands which do +// not involve any other data. +static cyg_uint32 +mmc_spi_send_command(cyg_mmc_spi_disk_info_t* disk, cyg_uint32 command, cyg_uint32 arg) +{ + cyg_uint32 reply; + reply = mmc_spi_send_command_start(disk, command, arg); + mmc_spi_end_command(disk); + return reply; +} + +// The card will return a data block when reading a disk block, or +// for certain other commands like reading card registers. Each +// data block consists of: +// 1) some number of padding bytes 0xff while the card is still +// processing the command and preparing the data +// 2) a data token byte, usually 0xFE for success +// 3) n bytes of data +// 4) two bytes of crc, which can be ignored. +// +// The data token byte is the only indication of success or failure, +// so that gets returned. +// +// When mounting certain types of card an extra delay may be needed +// before reading the first data block. This is handled by the +// extra_delay argument. +static cyg_uint32 +mmc_spi_read_data(cyg_mmc_spi_disk_info_t* disk, cyg_uint8* buf, cyg_uint32 count, cyg_bool extra_delay) +{ + cyg_spi_device* dev = disk->mmc_spi_dev; + int i; + cyg_uint8 response[2]; + cyg_uint32 retries; + + if (extra_delay) { + retries = MMC_SPI_READ_DATA_TOKEN_RETRIES * 100; + } else { + retries = MMC_SPI_READ_DATA_TOKEN_RETRIES; + } + + response[0] = 0x00FF; + for (i = 0; (i < retries) && (0x00FF == response[0]); i++) { + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, 1, mmc_spi_ff_data, response, 0); + } + + if (MMC_DATA_TOKEN_SUCCESS != response[0]) { + DEBUG1("mmc_spi_read_data(): got error response %02x after %d iterations\n", response[0], i); + return response[0]; + } + + // Now for the actual data. There is no way of detecting a failure from + // this point on. + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, count, mmc_spi_ff_data, buf, 0); + // And the CRC, which can be ignored + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, 2, mmc_spi_ff_data, response, 0); + DEBUG2("mmc_spi_read_data(): got data and CRC %02x %02x\n", response[0], response[1]); + + return MMC_DATA_TOKEN_SUCCESS; +} + +// Read one of the card registers, e.g. CSD or CID +static Cyg_ErrNo +mmc_spi_read_register(cyg_mmc_spi_disk_info_t* disk, cyg_uint32 command, cyg_uint8* buf, cyg_uint32 count) +{ + cyg_uint32 reply; + + reply = mmc_spi_send_command_start(disk, command, 0); + if (MMC_REPLY_SUCCESS != reply) { + DEBUG1("mmc_spi_read_register(): unexpected response to command %02x, reply code %02x\n", command, reply); + mmc_spi_end_command(disk); + return (0x00FF == reply) ? -ENODEV : -EIO; + } + reply = mmc_spi_read_data(disk, buf, count, false); + mmc_spi_end_command(disk); + if (MMC_DATA_TOKEN_SUCCESS != reply) { + DEBUG1("mmc_spi_read_register(): unexpected response to command %02x, expected 0x00FE data token, got %02x\n", command, reply); + return -EIO; + } + return ENOERR; +} + +// Reading a disk block is just a combination of the above utilities. +// This code is also responsible for translating error codes, since +// higher-level code does not get to see the initial response vs. the +// data token byte. +static Cyg_ErrNo +mmc_spi_read_disk_block(cyg_mmc_spi_disk_info_t* disk, cyg_uint8* buf, cyg_uint32 block, cyg_bool extra_delay) +{ + cyg_uint32 reply; + + // First the command itself. + DEBUG2("mmc_spi_read_disk_block(%d): sending command\n", block); + reply = mmc_spi_send_command_start(disk, MMC_REQUEST_READ_SINGLE_BLOCK, block * MMC_SPI_BLOCK_SIZE); + if (MMC_REPLY_SUCCESS != reply) { + DEBUG1("mmc_spi_read_disk_block(%d): unexpected response to READ_SINGLE_BLOCK command, code %02x\n", block, reply); + mmc_spi_end_command(disk); + // A byte 0xFF indicates the card has been removed. + if (0x00FF == reply) { + return -ENODEV; + } + // Parameter or address error should not occur, higher-level + // code should have checked the block to ensure that it is + // in range. + if (0 != (reply & (MMC_REPLY_PARAMETER_ERROR | MMC_REPLY_ADDRESS_ERROR))) { + return -EINVAL; + } + // The disk should not be in idle state or in an erase sequence. The + // command is definitely legal and CRCs should be disabled. So everything + // else is an I/O error. + return -EIO; + } + + // Now read back the data block. That code can be shared with other read + // operations, e.g. for retrieving registers. + DEBUG2("mmc_spi_read_disk_block(%d): reading data token/data/crc\n", block); + reply = mmc_spi_read_data(disk, buf, MMC_SPI_BLOCK_SIZE, extra_delay); + mmc_spi_end_command(disk); + if (MMC_DATA_TOKEN_SUCCESS != reply) { + DEBUG1("mmc_spi_read_disk_block(%d): failed to retrieve data, error token %02x\n", block, reply); + + // Possibilities are password-locked, range error, ECC failure + // if the raw data is corrupt, CC error for an internal card + // error, or some other error. A byte 0xFF indicates the card + // has been removed. + if (0x00FF == reply) { + return -ENODEV; + } else if (0 != (MMC_DATA_ERROR_TOKEN_CARD_LOCKED & reply)) { + // This should have been caught by a mount operation. + return -EPERM; + } else if (0 != (MMC_DATA_ERROR_TOKEN_OUT_OF_RANGE & reply)) { + return -EINVAL; + } else { + return -EIO; + } + } + return ENOERR; +} + +// Writing a block involves a bit more work. Some of this could be +// moved into a utility routine if necessary, shared with code for +// e.g. updating the CSD register, but for now that other functionality +// is not needed. +static Cyg_ErrNo +mmc_spi_write_disk_block(cyg_mmc_spi_disk_info_t* disk, const cyg_uint8* buf, cyg_uint32 block) +{ + cyg_spi_device* dev = disk->mmc_spi_dev; + cyg_uint32 reply; + cyg_uint8 extra[4]; + int i; + + // First, send the command itself and get the initial response + DEBUG2("mmc_spi_write_disk_block(), sending command\n"); + reply = mmc_spi_send_command_start(disk, MMC_REQUEST_WRITE_BLOCK, block * MMC_SPI_BLOCK_SIZE); + if (MMC_REPLY_SUCCESS != reply) { + DEBUG1("mmc_spi_write_disk_block(): unexpected response to WRITE_BLOCK command, code %02x\n", reply); + mmc_spi_end_command(disk); + if (0x00FF == reply) { + return -ENODEV; + } + // Parameter or address error should not occur, higher-level + // code should have checked the block to ensure that it is + // in range. + if (0 != (reply & (MMC_REPLY_PARAMETER_ERROR | MMC_REPLY_ADDRESS_ERROR))) { + return -EINVAL; + } + // The disk should not be in idle state or in an erase sequence. The + // command is definitely legal and CRCs should be disabled. So everything + // else is an I/O error. + return -EIO; + } + + // The card is now expecting a data block. This consists of a single byte + // 0x00FE, then the data itself, and a dummy CRC. The reply from the card + // does not contain any useful information. + DEBUG2("mmc_spi_write_disk_block(): sending data token/data/crc\n"); + extra[0] = 0x00FE; + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, 1, extra, (cyg_uint8*)0, 0); + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, MMC_SPI_BLOCK_SIZE, buf, (cyg_uint8*)0, 0); + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, 2, mmc_spi_ff_data, (cyg_uint8*)0, 0); + + // The card should respond immediately with a data response token. + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, 1, mmc_spi_ff_data, extra, 0); + DEBUG2("mmc_spi_write_disk_block(): got data response token %02x\n", extra[0]); + + // The bottom five bits contain the response. 00101 indicates success, + // anything else is a CRC error. Everything else will have been checked + // before the data got transferred. + if (0x05 != (extra[0] & 0x1F)) { + DEBUG1("mmc_spi_write_disk_block(): invalid data response token %02x\n", extra[0]); + mmc_spi_end_command(disk); + if (0x00FF == extra[0]) { + return -ENODEV; + } + return -EIO; + } + +#ifdef MMC_SPI_BACKGROUND_WRITES + // Mark the card as writing. The next operation will poll for completion. + disk->mmc_writing = true; +#else + // The card is now busy doing the write and will output a stream of 0's + // while busy. The timeout should really be calculated using the CSD + // register settings. + // + // It should be legal to drop the chip select here, i.e. to end + // the current transaction and start a new one for each poll + // operation. That would allow other SPI devices to be accessed. + // However it appears that this does not work with all MMC cards. + extra[0] = 0x00; + for (i = 0; (i < MMC_SPI_WRITE_BUSY_RETRIES) && (0x00 == extra[0]); i++) { + cyg_spi_transaction_transfer(dev, cyg_mmc_spi_polled, 1, mmc_spi_ff_data, extra, 0); + DEBUG2("mmc_spi_write_disk_block(), polling for ! busy, got response %02x\n", extra[0]); + } +#endif + + // Assume that the loop did in fact terminate. + mmc_spi_end_command(disk); + return ENOERR; +} + +// MMC sockets will default to a slow clockrate. During a successful mount +// the SPI device settings will be changed to the fastest supported by the +// card, as per the CSD register. This will need to be undone during an +// unmount, or if the final stages of a mount are unsuccessful. +static void +mmc_spi_restore_baud(cyg_mmc_spi_disk_info_t* disk) +{ + cyg_uint32 len = sizeof(cyg_uint32); + (void) cyg_spi_set_config(disk->mmc_spi_dev, CYG_IO_SET_CONFIG_SPI_CLOCKRATE, (void*) &(disk->mmc_saved_baudrate), &len); +} + +// check_for_disk() tries to communicate with an MMC card that is not +// currently mounted. It performs the appropriate initialization so +// that read and write operations are possible, checks the disk format, +// distinguishes between read-only and read-write cards, calculates the +// card size, stores the unique id, etc. +// +// The main error conditions are ENODEV (no card), EIO (card not +// responding sensibly to requests), ENOTDIR (wrong format), or EPERM +// (card is password-locked). +static Cyg_ErrNo +mmc_spi_check_for_disk(cyg_mmc_spi_disk_info_t* disk) +{ + cyg_spi_device* dev = disk->mmc_spi_dev; + int i; + cyg_uint32 reply; + Cyg_ErrNo code; + mmc_csd_register csd; + +#ifdef MMC_SPI_BACKGROUND_WRITES + // If we have unmounted a disk and are remounting it, assume that + // any writes have completed. + disk->mmc_writing = false; +#endif + reply = 0x00ff; + + for (i = 0; (i < MMC_SPI_GO_IDLE_RETRIES) && (0x01 != reply); i++) { + // Allow platform HALs to provide additional initialization, + // if the hardware needs it. +#ifdef HAL_MMC_SPI_INIT + HAL_MMC_SPI_INIT(dev, reply); + if (! reply) { + return -ENODEV; + } +#endif + // MMC cards generic initialization. The card may have just + // been plugged in so there is no guarantee that any previous + // init() calls or other traffic will have affected this card. + mmc_spi_send_init(disk); + + // Now set the card to idle state. This involves the GO_IDLE_STATE + // command which will be accepted irrespective of whether the card is + // currently in MMC or SPI mode, and will leave the card in SPI mode. + reply = mmc_spi_send_command(disk, MMC_REQUEST_GO_IDLE_STATE, 0); + + // The card should reply with 0x01. FF suggests that there is + // no card. Any other response indicates some synchronization + // problem. For example the card might still be responding to + // some request from a previous session which aborted at an + // inconvenient moment. Some dummy traffic is generated in the + // hope that this gets things back in sync. + if (0x01 != reply) { + DEBUG1("mmc_spi_check_for_disk(): loop %d, card did not enter idle state, code %02x\n", i, reply); + if (0x0ff != reply) { + cyg_spi_transfer(dev, cyg_mmc_spi_polled, 128, mmc_spi_ff_data, (cyg_uint8*) 0); + } + } + } + if (0x0ff == reply) { + DEBUG1("mmc_spi_check_for_disk(): unable to get a response from the MMC card: code %02x\n", reply); + // A working card should be returning some data + return -ENODEV; + } + if (0x01 != reply) { + DEBUG1("mmc_spi_check_for_disk(): card did not enter idle state, code %02x\n", reply); + return -EIO; + } + + // Next, wait for the card to initialize. This involves repeatedly + // trying the SEND_OP_COND command until we get a reply that is + // not idle + reply = 0x00ff; + for (i = 0; (i < MMC_SPI_OP_COND_RETRIES) && ((0x00ff == reply) || (0 != (MMC_REPLY_IN_IDLE_STATE & reply))); i++) { +#ifdef CYGPKG_DEVS_DISK_MMC_SPI_IDLE_RETRIES_WAIT + CYGACC_CALL_IF_DELAY_US(CYGPKG_DEVS_DISK_MMC_SPI_IDLE_RETRIES_WAIT); +#endif + reply = mmc_spi_send_command(disk, MMC_REQUEST_SEND_OP_COND, 0); + } + if (MMC_REPLY_SUCCESS != reply) { + DEBUG1("mmc_spi_check_for_disk(): card has not entered operational state: reply code %02x\n", reply); + return (0x00FF == reply) ? -ENODEV : -EIO; + } + + // The card has now generated sufficient responses that we don't need to + // worry about a missing card anymore. + // Get hold of the card's unique ID and store it, to allow disk changes + // to be detected. + code = mmc_spi_read_register(disk, MMC_REQUEST_SEND_CID, (cyg_uint8*) &(disk->mmc_id), 16); + if (code) { + mmc_spi_end_command(disk); + return code; + } + DEBUG2("CID data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + disk->mmc_id.cid_data[ 0], disk->mmc_id.cid_data[ 1], disk->mmc_id.cid_data[ 2], disk->mmc_id.cid_data[ 3], \ + disk->mmc_id.cid_data[ 4], disk->mmc_id.cid_data[ 5], disk->mmc_id.cid_data[ 6], disk->mmc_id.cid_data[ 7], \ + disk->mmc_id.cid_data[ 8], disk->mmc_id.cid_data[ 9], disk->mmc_id.cid_data[10], disk->mmc_id.cid_data[11], \ + disk->mmc_id.cid_data[12], disk->mmc_id.cid_data[13], disk->mmc_id.cid_data[14], disk->mmc_id.cid_data[15]); +#if DEBUG > 0 + DEBUG1("CID data: register\n"); + DEBUG1(" : Manufacturer ID : MID = 0x%02x\n", MMC_CID_REGISTER_MID(&(disk->mmc_id)) & 0xff); + DEBUG1(" : OEM/Application ID : OID = 0x%04x\n", MMC_CID_REGISTER_OID(&(disk->mmc_id)) & 0xffff); + DEBUG1(" : Product name : PNM = 0x%02x%02x%02x%02x%02x%02x\n", + MMC_CID_REGISTER_PNM(&(disk->mmc_id))[0] & 0xff, + MMC_CID_REGISTER_PNM(&(disk->mmc_id))[1] & 0xff, + MMC_CID_REGISTER_PNM(&(disk->mmc_id))[2] & 0xff, + MMC_CID_REGISTER_PNM(&(disk->mmc_id))[3] & 0xff, + MMC_CID_REGISTER_PNM(&(disk->mmc_id))[4] & 0xff, + MMC_CID_REGISTER_PNM(&(disk->mmc_id))[5] & 0xff); + DEBUG1(" : Product revision : PRV = 0x%02x\n", MMC_CID_REGISTER_PRV(&(disk->mmc_id)) & 0xff); + DEBUG1(" : Product serial number : PSN = 0x%08x\n", MMC_CID_REGISTER_PSN(&(disk->mmc_id)) & 0xffffffff); + DEBUG1(" : Manufacturing date : MDT = 0x%02x\n", MMC_CID_REGISTER_MDT(&(disk->mmc_id)) & 0xff); + DEBUG1(" : 7-bit CRC checksum : CRC = 0x%02x\n", MMC_CID_REGISTER_CRC(&(disk->mmc_id)) & 0xff); +#endif + + // And retrieve the card's configuration data. + code = mmc_spi_read_register(disk, MMC_REQUEST_SEND_CSD, (cyg_uint8*) &csd, 16); + if (code) { + mmc_spi_end_command(disk); + return code; + } + DEBUG2("CSD data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + csd.csd_data[ 0], csd.csd_data[ 1], csd.csd_data[ 2], csd.csd_data[3], \ + csd.csd_data[ 4], csd.csd_data[ 5], csd.csd_data[ 6], csd.csd_data[7], \ + csd.csd_data[ 8], csd.csd_data[ 9], csd.csd_data[10], csd.csd_data[11], \ + csd.csd_data[12], csd.csd_data[13], csd.csd_data[14], csd.csd_data[15]); + + // Optionally dump the whole CSD register. This takes a lot of + // code but gives a lot of info about the card. If the info looks + // correct then we really are interacting properly with an MMC card. +#if DEBUG > 0 + DEBUG1("CSD data: structure 0x%02x, version 0x%02x\n", MMC_CSD_REGISTER_CSD_STRUCTURE(&csd), MMC_CSD_REGISTER_SPEC_VERS(&csd)); + if (0 != MMC_CSD_REGISTER_FILE_FORMAT_GROUP(&csd)) { + DEBUG1(" : Reserved (unknown), FILE_FORMAT_GROUP %d, FILE_FORMAT %d\n", \ + MMC_CSD_REGISTER_FILE_FORMAT_GROUP(&csd), MMC_CSD_REGISTER_FILE_FORMAT(&csd)); + } else if (0 == MMC_CSD_REGISTER_FILE_FORMAT(&csd)) { + DEBUG1(" : Partioned disk, FILE_FORMAT_GROUP 0, FILE_FORMAT 0\n"); + } else if (1 == MMC_CSD_REGISTER_FILE_FORMAT(&csd)) { + DEBUG1(" : FAT disk, FILE_FORMAT_GROUP 0, FILE_FORMAT 1\n"); + } else if (2 == MMC_CSD_REGISTER_FILE_FORMAT(&csd)) { + DEBUG1(" : Universal File format, FILE_FORMAT_GROUP 0, FILE_FORMAT 2\n"); + } else { + DEBUG1(" : Others/Unknown disk, FILE_FORMAT_GROUP 0, FILE_FORMAT 3\n"); + } + { + static const cyg_uint32 mantissa_speeds_x10[16] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; + static const cyg_uint32 exponent_speeds_div10[8] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; + cyg_uint32 speed = mantissa_speeds_x10[MMC_CSD_REGISTER_TRAN_SPEED_MANTISSA(&csd)] * + exponent_speeds_div10[MMC_CSD_REGISTER_TRAN_SPEED_EXPONENT(&csd)]; + speed /= 1000; + DEBUG1(" : TRAN_SPEED %d %d -> %d kbit/s\n", \ + MMC_CSD_REGISTER_TRAN_SPEED_MANTISSA(&csd), MMC_CSD_REGISTER_TRAN_SPEED_EXPONENT(&csd), speed); + } + DEBUG1(" : READ_BL_LEN block length 2^%d (%d)\n", MMC_CSD_REGISTER_READ_BL_LEN(&csd), \ + 0x01 << MMC_CSD_REGISTER_READ_BL_LEN(&csd)); + DEBUG1(" : C_SIZE %d, C_SIZE_MULT %d\n", MMC_CSD_REGISTER_C_SIZE(&csd), MMC_CSD_REGISTER_C_SIZE_MULT(&csd)); + { + cyg_uint32 block_len = 0x01 << MMC_CSD_REGISTER_READ_BL_LEN(&csd); + cyg_uint32 mult = 0x01 << (MMC_CSD_REGISTER_C_SIZE_MULT(&csd) + 2); + cyg_uint32 size = block_len * mult * (MMC_CSD_REGISTER_C_SIZE(&csd) + 1); + cyg_uint32 sizeK = (cyg_uint32) (size / 1024); + cyg_uint32 sizeM = sizeK / 1024; + sizeK -= (sizeM * 1024); + DEBUG1(" : total card size %dM%dK\n", sizeM, sizeK); + } + DEBUG1(" : WR_BL_LEN block length 2^%d (%d)\n", \ + MMC_CSD_REGISTER_WRITE_BL_LEN(&csd), 0x01 << MMC_CSD_REGISTER_WRITE_BL_LEN(&csd)); + { + static cyg_uint32 taac_mantissa_speeds_x10[16] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; + static cyg_uint32 taac_exponent_speeds_div10[8] = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; + cyg_uint32 taac_speed = taac_mantissa_speeds_x10[MMC_CSD_REGISTER_TAAC_MANTISSA(&csd)] * + taac_exponent_speeds_div10[MMC_CSD_REGISTER_TAAC_EXPONENT(&csd)]; + taac_speed /= 100; + DEBUG1(" : asynchronous read access time TAAC %d %d -> %d ns\n", \ + MMC_CSD_REGISTER_TAAC_MANTISSA(&csd), MMC_CSD_REGISTER_TAAC_EXPONENT(&csd), taac_speed); + } + DEBUG1(" : synchronous read access time NSAC %d * 100 cycles\n", \ + MMC_CSD_REGISTER_NSAC(&csd)); + DEBUG1(" : typical write program time %d * read time\n", MMC_CSD_REGISTER_R2W_FACTOR(&csd)); + DEBUG1(" : CCC command classes 0x%04x\n", MMC_CSD_REGISTER_CCC(&csd)); + DEBUG1(" : READ_BL_PARTIAL %d, WRITE_BLK_MISALIGN %d, READ_BLK_MISALIGN %d, DSR_IMP %d\n", \ + MMC_CSD_REGISTER_READ_BL_PARTIAL(&csd), MMC_CSD_REGISTER_WRITE_BLK_MISALIGN(&csd), \ + MMC_CSD_REGISTER_READ_BLK_MISALIGN(&csd), MMC_CSD_REGISTER_DSR_IMP(&csd)); + DEBUG1(" : WR_BL_PARTIAL %d\n", MMC_CSD_REGISTER_WR_BL_PARTIAL(&csd)); + { + static cyg_uint8 min_currents[8] = { 1, 1, 5, 10, 25, 35, 60, 100 }; + static cyg_uint8 max_currents[8] = { 1, 5, 10, 25, 35, 45, 80, 200 }; + DEBUG1(" : read current min %dmA, max %dmA\n", \ + min_currents[MMC_CSD_REGISTER_VDD_R_CURR_MIN(&csd)], \ + max_currents[MMC_CSD_REGISTER_VDD_R_CURR_MAX(&csd)]); + DEBUG1(" : write current min %dmA, max %dmA\n", \ + min_currents[MMC_CSD_REGISTER_VDD_W_CURR_MIN(&csd)], \ + max_currents[MMC_CSD_REGISTER_VDD_W_CURR_MAX(&csd)]); + } + DEBUG1(" : erase sector size %d, erase group size %d\n", \ + MMC_CSD_REGISTER_SECTOR_SIZE(&csd) + 1, MMC_CSD_REGISTER_ERASE_GRP_SIZE(&csd) + 1); + DEBUG1(" : write group enable %d, write group size %d\n", \ + MMC_CSD_REGISTER_WR_GRP_ENABLE(&csd), MMC_CSD_REGISTER_WR_GRP_SIZE(&csd) + 1); + DEBUG1(" : copy bit %d\n", MMC_CSD_REGISTER_COPY(&csd)); + DEBUG1(" : permanent write protect %d, temporary write protect %d\n", \ + MMC_CSD_REGISTER_PERM_WRITE_PROTECT(&csd), MMC_CSD_REGISTER_TMP_WRITE_PROTECT(&csd)); + DEBUG1(" : ecc %d, default ecc %d\n", MMC_CSD_REGISTER_ECC(&csd), MMC_CSD_REGISTER_DEFAULT_ECC(&csd)); + DEBUG1(" : crc 0x%08x\n", MMC_CSD_REGISTER_CRC(&csd)); +#endif + + // There is information available about the file format, e.g. + // partitioned vs. simple FAT. With the current version of the + // generic disk code this needs to be known statically, via + // the mbr field of the disk channel structure. If the card + // is inappropriately formatted, reject the mount request. + if ((0 != MMC_CSD_REGISTER_FILE_FORMAT_GROUP(&csd)) || + (0 != MMC_CSD_REGISTER_FILE_FORMAT(&csd))) { + return -ENOTDIR; + } + + // Look for a write-protect bit (permanent or temporary), and set + // the disk as read-only or read-write as appropriate. The + // temporary write-protect could be cleared by rewriting the CSD + // register (including recalculating the CRC) but the effort + // involves does not seem worth-while. + if ((0 != MMC_CSD_REGISTER_PERM_WRITE_PROTECT(&csd)) || (0 != MMC_CSD_REGISTER_TMP_WRITE_PROTECT(&csd))) { + disk->mmc_read_only = true; + } else { + disk->mmc_read_only = false; + } + DEBUG1("Disk read-only flag %d\n", disk->mmc_read_only); + + // Calculate the disk size, primarily for assertion purposes. + // By design MMC cards are limited to 4GB, which still doesn't + // quite fit into 32 bits. + disk->mmc_block_count = (((cyg_uint64)(0x01 << MMC_CSD_REGISTER_READ_BL_LEN(&csd))) * + ((cyg_uint64)(0x01 << (MMC_CSD_REGISTER_C_SIZE_MULT(&csd) + 2))) * + ((cyg_uint64)(MMC_CSD_REGISTER_C_SIZE(&csd) + 1))) / (cyg_uint64)MMC_SPI_BLOCK_SIZE; + DEBUG1("Disk blockcount %d (0x%08x)\n", disk->mmc_block_count, disk->mmc_block_count); + + // Assume for now that the block length is 512 bytes. This is + // probably a safe assumption since we have just got the card + // initialized out of idle state. If it ever proves to be a problem + // the SET_BLOCK_LEN command can be used. + // Nevertheless store the underlying block sizes + disk->mmc_read_block_length = 0x01 << MMC_CSD_REGISTER_READ_BL_LEN(&csd); + disk->mmc_write_block_length = 0x01 << MMC_CSD_REGISTER_WRITE_BL_LEN(&csd); + + // The CSD contains the maximum supported transfer speed. Adjust + // the SPI device to match, saving the old value for an unmount + // operation. It is assumed that the SPI bus driver will munge + // the supplied speed to something appropriate. + { + static const cyg_uint32 mantissa_speeds_x10[16] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; + static const cyg_uint32 exponent_speeds_div10[8] = { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; + cyg_uint32 speed, len; + + len = sizeof(cyg_uint32); + if (cyg_spi_get_config(dev, CYG_IO_GET_CONFIG_SPI_CLOCKRATE, (void*) &disk->mmc_saved_baudrate, &len)) { + DEBUG1("Failed to retrieve current SPI device clockrate\n"); + return -EIO; + } + speed = mantissa_speeds_x10[MMC_CSD_REGISTER_TRAN_SPEED_MANTISSA(&csd)] * exponent_speeds_div10[MMC_CSD_REGISTER_TRAN_SPEED_EXPONENT(&csd)]; + if (speed > disk->mmc_saved_baudrate) { + DEBUG1("Old SPI speed %d, switching to %d\n", disk->mmc_saved_baudrate, speed); + cyg_spi_set_config(dev, CYG_IO_SET_CONFIG_SPI_CLOCKRATE, (void*) &speed, &len); + } else { + DEBUG1("Old SPI speed %d already greater than max speed %d, leaving it alone\n", + disk->mmc_saved_baudrate, speed); + } + } + + // Read the partition table off the card. This is a way of + // checking that the card is not password-locked. It also + // provides information about the "disk geometry" which is + // needed by higher-level code. + // FIXME: the higher-level code should be made to use LBA + // addressing instead. + { + cyg_uint8 data[MMC_SPI_BLOCK_SIZE]; + cyg_uint8* partition; + cyg_uint32 lba_first, lba_size, lba_end, head, cylinder, sector; + + code = mmc_spi_read_disk_block(disk, data, 0, true); + if (code) { + mmc_spi_restore_baud(disk); + return code; + } +#if DEBUG > 1 + { + cyg_uint8 *ptr_data; + + DEBUG2("MBR dump\n"); + for (i = 0; i < MMC_SPI_BLOCK_SIZE; i += 16) { + ptr_data = &data[i]; + DEBUG2(" %04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + i, + ptr_data[ 0], ptr_data[ 1], ptr_data[ 2], ptr_data[ 3], + ptr_data[ 4], ptr_data[ 5], ptr_data[ 6], ptr_data[ 7], + ptr_data[ 8], ptr_data[ 9], ptr_data[10], ptr_data[11], + ptr_data[12], ptr_data[13], ptr_data[14], ptr_data[15]); + } + } +#endif +#if DEBUG > 0 + DEBUG1("Read block 0 (partition table)\n"); + DEBUG1("Signature 0x%02x 0x%02x, should be 0x55 0xaa\n", data[0x1fe], data[0x1ff]); + // There should be four 16-byte partition table entries at offsets + // 0x1be, 0x1ce, 0x1de and 0x1ee. The numbers are stored little-endian + for (i = 0; i < 4; i++) { + partition = &(data[0x1be + (0x10 * i)]); + DEBUG1("Partition %d: boot %02x, first sector %02x %02x %02x, file system %02x, last sector %02x %02x %02x\n", i, \ + partition[0], partition[1], partition[2], partition[3], partition[4], \ + partition[5], partition[6], partition[7]); + DEBUG1(" : first sector (linear) %02x %02x %02x %02x, sector count %02x %02x %02x %02x\n", \ + partition[11], partition[10], partition[9], partition[8], \ + partition[15], partition[14], partition[13], partition[12]); + } +#endif + if ((0x0055 != data[0x1fe]) || (0x00aa != data[0x1ff])) { + mmc_spi_restore_baud(disk); + return -ENOTDIR; + } + partition = &(data[0x1be]); + lba_first = (partition[11] << 24) | (partition[10] << 16) | (partition[9] << 8) | partition[8]; + lba_size = (partition[15] << 24) | (partition[14] << 16) | (partition[13] << 8) | partition[12]; + lba_end = lba_first + lba_size - 1; + + // First sector in c/h/s format + cylinder = ((partition[2] & 0xC0) << 2) | partition[3]; + head = partition[1]; + sector = partition[2] & 0x3F; + + // lba_start == (((cylinder * Nh) + head) * Ns) + sector - 1, where (Nh == heads/cylinder) and (Ns == sectors/head) + // Strictly speaking we should be solving some simultaneous + // equations here for lba_start/lba_end, but that gets messy. + // The first partition is at the start of the card so cylinder will be 0, + // and we can ignore Nh. + CYG_ASSERT(0 == cylinder, "Driver assumption - partition 0 is at start of card\n"); + CYG_ASSERT(0 != head, "Driver assumption - partition table is sensible\n"); + disk->mmc_sectors_per_head = ((lba_first + 1) - sector) / head; + + // Now for lba_end. + cylinder = ((partition[6] & 0xC0) << 2) | partition[7]; + head = partition[5]; + sector = partition[6] & 0x3F; + disk->mmc_heads_per_cylinder = ((((lba_end + 1) - sector) / disk->mmc_sectors_per_head) - head) / cylinder; + } + + return ENOERR; +} + +// Check that the current card is the one that was previously +// accessed. This may fail if the card has been removed and the +// slot is empty, or if the card has been removed and a different +// one inserted. It may pass incorrectly if a card is removed, +// modified elsewhere, and reinserted without eCos noticing. +// There is no way around that without some way of detecting +// disk removal in hardware. +// +// Re-reading the cid may actually be overkill. If a new card +// has been plugged in then it will not have been initialized so +// it will respond with 0xff anyway. It is very unlikely that +// an init sequence will have happened by accident. +static cyg_bool +mmc_spi_disk_changed(cyg_mmc_spi_disk_info_t* disk) +{ + mmc_cid_register cid; + Cyg_ErrNo code; + + code = mmc_spi_read_register(disk, MMC_REQUEST_SEND_CID, (cyg_uint8*) &cid, 16); + if (-ENODEV == code) { + return true; + } + + if (0 != memcmp(&cid, &(disk->mmc_id), sizeof(mmc_cid_register))) { + return true; + } + return false; +} + +// ---------------------------------------------------------------------------- + +// No hardware initialization is performed here. Even if a card is +// currently plugged in it may get removed before it gets mounted, so +// there is no point looking at the card here. It is still necessary +// to invoke the callback init function so that higher-level code gets +// a chance to do its bit. +static cyg_bool +mmc_spi_disk_init(struct cyg_devtab_entry* tab) +{ + disk_channel* chan = (disk_channel*) tab->priv; + MMC_SPI_INIT_FF_DATA(); + return (*chan->callbacks->disk_init)(tab); +} + +// lookup() is called during a mount() operation, so this is the right +// place to check whether or not there is a card. + +static char* +mmc_spi_disk_lookup_itoa(cyg_uint32 num, char* where) +{ + if (0 == num) { + *where++ = '0'; + } else { + char local[10]; // 2^32 just fits into 10 places + int index = 9; + while (num > 0) { + local[index--] = (num % 10) + '0'; + num /= 10; + } + for (index += 1; index < 10; index++) { + *where++ = local[index]; + } + } + return where; +} + +static Cyg_ErrNo +mmc_spi_disk_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry *sub_tab, const char* name) +{ + disk_channel* chan = (disk_channel*) (*tab)->priv; + cyg_mmc_spi_disk_info_t* disk = (cyg_mmc_spi_disk_info_t*) chan->dev_priv; + Cyg_ErrNo result; + + DEBUG2("mmc_spi_disk_lookup(): target name=%s\n", name ); + DEBUG2(" : device name=%s dep_name=%s\n", tab[0]->name, tab[0]->dep_name ); + DEBUG2(" : sub name=%s dep_name=%s\n", sub_tab->name, sub_tab->dep_name ); + + if (disk->mmc_connected) { + // There was a card plugged in last time we looked. Is it still there? + if (mmc_spi_disk_changed(disk)) { + // The old card is gone. Either there is no card plugged in, or + // it has been replaced with a different one. If the latter the + // existing mounts must be removed before anything sensible + // can be done. + disk->mmc_connected = false; + (*chan->callbacks->disk_disconnected)(chan); + if (0 != chan->info->mounts) { + return -ENODEV; + } + } + } + + if ((0 != chan->info->mounts) && !disk->mmc_connected) { + // There are still mount points to an old card. We cannot accept + // new mount requests until those have been cleaned out. + return -ENODEV; + } + + if (!disk->mmc_connected) { + cyg_disk_identify_t ident; + cyg_uint32 id_data; + char* where; + int i; + + // The world is consistent and the higher-level code does not + // know anything about the current card, if any. Is there a + // card? + result = mmc_spi_check_for_disk(disk); + if (ENOERR != result) { + return result; + } + // A card has been found. Tell the higher-level code about it. + // This requires an identify structure, although it is not + // entirely clear what purpose that serves. + disk->mmc_connected = true; + // Serial number, up to 20 characters; The CID register contains + // various fields which can be used for this. + where = &(ident.serial[0]); + id_data = disk->mmc_id.cid_data[0]; // 1-byte manufacturer id -> 3 chars, 17 left + where = mmc_spi_disk_lookup_itoa(id_data, where); + id_data = (disk->mmc_id.cid_data[1] << 8) + disk->mmc_id.cid_data[2]; // 2-byte OEM ID, 5 chars, 12 left + where = mmc_spi_disk_lookup_itoa(id_data, where); + id_data = (disk->mmc_id.cid_data[10] << 24) + (disk->mmc_id.cid_data[11] << 16) + + (disk->mmc_id.cid_data[12] << 8) + disk->mmc_id.cid_data[13]; + where = mmc_spi_disk_lookup_itoa(id_data, where); // 4-byte OEM ID, 10 chars, 2 left + // And terminate the string with a couple of places to spare. + *where = '\0'; + + // Firmware revision number. There is a one-byte product + // revision number in the CID, BCD-encoded + id_data = disk->mmc_id.cid_data[9] >> 4; + if (id_data <= 9) { + ident.firmware_rev[0] = id_data + '0'; + } else { + ident.firmware_rev[0] = id_data - 10 + 'A'; + } + id_data = disk->mmc_id.cid_data[9] & 0x0F; + if (id_data <= 9) { + ident.firmware_rev[1] = id_data + '0'; + } else { + ident.firmware_rev[1] = id_data - 10 + 'A'; + } + ident.firmware_rev[2] = '\0'; + + // Model number. There is a six-byte product name in the CID. + for (i = 0; i < 6; i++) { + if ((disk->mmc_id.cid_data[i + 3] >= 0x20) && (disk->mmc_id.cid_data[i+3] <= 0x7E)) { + ident.model_num[i] = disk->mmc_id.cid_data[i + 3]; + } else { + break; + } + } + ident.model_num[i] = '\0'; + + // We don't have no cylinders, heads, or sectors, but + // higher-level code may interpret partition data using C/H/S + // addressing rather than LBA. Hence values for some of these + // settings were calculated above. + ident.cylinders_num = 1; + ident.heads_num = disk->mmc_heads_per_cylinder; + ident.sectors_num = disk->mmc_sectors_per_head; + ident.lba_sectors_num = disk->mmc_block_count; + ident.phys_block_size = disk->mmc_write_block_length/512; + ident.max_transfer = disk->mmc_write_block_length; + + DEBUG1("Calling disk_connected(): serial %s, firmware %s, model %s, heads %d, sectors %d, lba_sectors_num %d, phys_block_size %d\n", \ + ident.serial, ident.firmware_rev, ident.model_num, ident.heads_num, ident.sectors_num, + ident.lba_sectors_num, ident.phys_block_size); + (*chan->callbacks->disk_connected)(*tab, &ident); + + // We now have a valid card and higher-level code knows about it. Fall through. + } + + // And leave it to higher-level code to finish the lookup, taking + // into accounts partitions etc. + return (*chan->callbacks->disk_lookup)(tab, sub_tab, name); +} + +static Cyg_ErrNo +mmc_spi_disk_read(disk_channel* chan, void* buf_arg, cyg_uint32 blocks, cyg_uint32 first_block) +{ + cyg_mmc_spi_disk_info_t* disk = (cyg_mmc_spi_disk_info_t*) chan->dev_priv; + cyg_uint32 i; + cyg_uint8* buf = (cyg_uint8*) buf_arg; + Cyg_ErrNo code = ENOERR; + + DEBUG1("mmc_spi_disk_read(): first block %d, buf %p, len %lu blocks (%lu bytes)\n", + first_block, buf, (unsigned long)blocks, (unsigned long)blocks*512); + + if (! disk->mmc_connected) { + return -ENODEV; + } + if ((first_block + blocks) >= disk->mmc_block_count) { + return -EINVAL; + } + + for (i = 0; (i < blocks) && (ENOERR == code); i++) { + code = mmc_spi_read_disk_block(disk, buf, first_block + i, false); + buf += MMC_SPI_BLOCK_SIZE; + } + return code; +} + +static Cyg_ErrNo +mmc_spi_disk_write(disk_channel* chan, const void* buf_arg, cyg_uint32 blocks, cyg_uint32 first_block) +{ + cyg_mmc_spi_disk_info_t* disk = (cyg_mmc_spi_disk_info_t*) chan->dev_priv; + cyg_uint32 i; + const cyg_uint8* buf = (cyg_uint8*) buf_arg; + Cyg_ErrNo code = ENOERR; + + DEBUG1("mmc_spi_disk_write(): first block %d, buf %p, len %lu blocks (%lu bytes)\n", + first_block, buf, (unsigned long)blocks, (unsigned long)blocks*512); + + if (! disk->mmc_connected) { + return -ENODEV; + } + if (disk->mmc_read_only) { + return -EROFS; + } + if ((first_block + blocks) >= disk->mmc_block_count) { + return -EINVAL; + } + + for (i = 0; (i < blocks) && (ENOERR == code); i++) { + code = mmc_spi_write_disk_block(disk, buf, first_block + i); + buf += MMC_SPI_BLOCK_SIZE; + } + return code; +} + +// get_config() and set_config(). There are no supported get_config() operations +// at this time. +static Cyg_ErrNo +mmc_spi_disk_get_config(disk_channel* chan, cyg_uint32 key, const void* buf, cyg_uint32* len) +{ + CYG_UNUSED_PARAM(disk_channel*, chan); + CYG_UNUSED_PARAM(cyg_uint32, key); + CYG_UNUSED_PARAM(const void*, buf); + CYG_UNUSED_PARAM(cyg_uint32*, len); + + return -EINVAL; +} + +static Cyg_ErrNo +mmc_spi_disk_set_config(disk_channel* chan, cyg_uint32 key, const void* buf, cyg_uint32* len) +{ + Cyg_ErrNo result = ENOERR; + cyg_mmc_spi_disk_info_t* disk = (cyg_mmc_spi_disk_info_t*) chan->dev_priv; + + switch(key) { + case CYG_IO_SET_CONFIG_DISK_MOUNT: + // There will have been a successful lookup(), so there's + // little point in checking the disk again. + break; + + case CYG_IO_SET_CONFIG_DISK_UMOUNT: + if (0 == chan->info->mounts) { + // If this is the last unmount of the card, mark it as + // disconnected. If the user then removes the card and + // plugs in a new one everything works cleanly. Also + // reset the SPI device's clockrate. + disk->mmc_connected = false; + mmc_spi_restore_baud(disk); + result = (chan->callbacks->disk_disconnected)(chan); + } + break; + } + + return result; +} + +// ---------------------------------------------------------------------------- +// And finally the data structures that define this disk. Some of this +// should be moved into an exported header file so that applications can +// define additional disks. +// +// It is not obvious why there are quite so many structures. Apart +// from the devtab entries there are no tables involved, so there is +// no need to keep everything the same size. The cyg_disk_info_t could +// be the common part of a h/w info_t. The channel structure is +// redundant and its fields could be merged into the cyg_disk_info_t +// structure. That would leave a devtab entry, a disk info structure +// (h/w specific but with a common base), and a disk controller +// structure (ditto). + +DISK_FUNS(cyg_mmc_spi_disk_funs, + mmc_spi_disk_read, + mmc_spi_disk_write, + mmc_spi_disk_get_config, + mmc_spi_disk_set_config + ); + +static cyg_mmc_spi_disk_info_t cyg_mmc_spi_disk0_hwinfo = { + .mmc_spi_dev = &cyg_spi_mmc_dev0, +#ifdef MMC_SPI_BACKGROUND_WRITES + .mmc_writing = 0, +#endif + .mmc_connected = 0 +}; + +// No h/w controller structure is needed, but the address of the +// second argument is taken anyway. +DISK_CONTROLLER(cyg_mmc_spi_disk_controller_0, cyg_mmc_spi_disk0_hwinfo); + +DISK_CHANNEL(cyg_mmc_spi_disk0_channel, + cyg_mmc_spi_disk_funs, + cyg_mmc_spi_disk0_hwinfo, + cyg_mmc_spi_disk_controller_0, + true, /* MBR support */ + 1 /* Number of partitions supported */ + ); + +BLOCK_DEVTAB_ENTRY(cyg_mmc_spi_disk0_devtab_entry, + CYGDAT_DEVS_DISK_MMC_SPI_DISK0_NAME, + 0, + &cyg_io_disk_devio, + &mmc_spi_disk_init, + &mmc_spi_disk_lookup, + &cyg_mmc_spi_disk0_channel); + +// EOF mmc_spi.c diff --git a/packages/devs/eth/arm/at91/v2_0/ChangeLog b/packages/devs/eth/arm/at91/v2_0/ChangeLog new file mode 100755 index 00000000..7adee0ea --- /dev/null +++ b/packages/devs/eth/arm/at91/v2_0/ChangeLog @@ -0,0 +1,53 @@ +2007-04-08 Uwe Kindler + + * cdl/at91_eth.cdl: Fixed typo. (Removed AT91RM9200 from + CYGPKG_DEVS_ETH_ARM_AT91_DEBUG_LEVEL) + +2007-03-23 John Eigelaar + + * src/if_at91.c: Added support for the ETH_DRV_SET_MAC_ADDRESS + control key. Added functionality to clear the transmit buffer + ownershiop bits when the TXCOMP status is detected. + +2007-01-17 John Eigelaar + + * src/if_at91.c * include/at91_eth.cdl: Working implementation + of a device driver for the AT91 EMAC device. + +2006-06-02 Andrew Lunn + + * src/if_at91.c * include/at91_eth.cdl: Partially implementation + of a device driver for the AT91 EMAC device. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright 2006 Andrew Lunn +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/eth/arm/at91/v2_0/cdl/at91_eth.cdl b/packages/devs/eth/arm/at91/v2_0/cdl/at91_eth.cdl new file mode 100755 index 00000000..46cfb574 --- /dev/null +++ b/packages/devs/eth/arm/at91/v2_0/cdl/at91_eth.cdl @@ -0,0 +1,164 @@ +#========================================================================== +# +# at91_eth.cdl +# +# Ethernet drivers for Atmel AT91 Cores +# +#========================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2002 Jonathan Larmour +## Copyright (C) 2006 Andrew Lunn +## +## 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): Andrew Lunn +# Contributors: +# Date: 2006-05-10 +# Purpose: +# Description: +# +#####DESCRIPTIONEND#### +# +#========================================================================*/ + +cdl_package CYGPKG_DEVS_ETH_ARM_AT91 { + display "Atmel AT91 ethernet driver" + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + implements CYGHWR_NET_DRIVERS + implements CYGHWR_NET_DRIVER_ETH0 + + include_dir net + description " + Ethernet driver for Atmel AT91 core. This has been tested with the + AT91SAM7X, but should be easy to get to work on other AT91 cores that + have the EMAC core." + + compile -library=libextras.a if_at91.c + + cdl_option CYGPKG_DEVS_ETH_ARM_AT91_DEBUG_LEVEL { + display "Driver debug output level" + flavor data + legal_values {0 1 2} + default_value 1 + description " + This option specifies the level of debug data output by + the AT91 ethernet device driver. A value of 0 signifies + no debug data output; 1 signifies normal debug data + output; and 2 signifies maximum debug data output (not + suitable when GDB and application are sharing an ethernet + port)." + } + + cdl_option CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS { + display "Number of RX buffers" + flavor data + default_value 32 + description " + Number of receive buffers. Each buffer is 128 bytes in size" + } + + cdl_option CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS { + display "Number of TX buffers" + flavor data + default_value 10 + description " + Number of transmit buffer descriptors. We need one descriptor + for each element in the scatter/gather list." + } + + cdl_option CYGPKG_DEVS_ETH_ARM_AT91_PHYADDR { + display "PHY MII address" + flavor data + legal_values 0 to 31 + default_value 1 + description "This option specifies the MII address of the PHY" + } + + cdl_component CYGPKG_DEVS_ETH_ARM_AT91_REDBOOT_HOLDS_ESA { + display "RedBoot manages ESA initialization data" + flavor bool + default_value 0 + + active_if CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + active_if (CYGPKG_REDBOOT || CYGSEM_HAL_USE_ROM_MONITOR) + + description " + Enabling this option will allow the ethernet station + address to be acquired from RedBoot's configuration data, + stored in flash memory. It can be overridden individually + by the 'Set the ethernet station address' option for each + interface." + + + cdl_component CYGPKG_DEVS_ETH_ARM_AT91_REDBOOT_HOLDS_ESA_VARS { + display "Export RedBoot command to set ESA in FLASH config" + flavor none + no_define + description " + This component contains options which, when enabled, allow + RedBoot to support the setting of the ESA in the FLASH + configuration. This can then subsequently be accessed by + applications using virtual vector calls if those applications + are also built with + CYGPKG_DEVS_ETH_ARM_AT91_REDBOOT_HOLDS_ESA enabled." + + cdl_option CYGSEM_DEVS_ETH_ARM_AT91_REDBOOT_HOLDS_ESA_ETH0 { + display "RedBoot manages ESA for eth0" + flavor bool + default_value 1 + active_if CYGSEM_REDBOOT_FLASH_CONFIG + active_if CYGPKG_REDBOOT_NETWORKING + } + } + } + cdl_option CYGPKG_DEVS_ETH_ARM_AT91_MACADDR { + display "Ethernet station (MAC) address for eth0" + flavor data + default_value {"0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC"} + description "The default ethernet station address. This is the + MAC address used when no value is found in the + RedBoot FLASH configuration field." + } + + cdl_option CYGPKG_DEVS_ETH_ARM_AT91_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS" } + description " + This option modifies the set of compiler flags for + building the Atmel AT91 ethernet driver package. + These flags are used in addition to the set of global flags." + } +} + +# EOF at91_eth.cdl diff --git a/packages/devs/eth/arm/at91/v2_0/src/if_at91.c b/packages/devs/eth/arm/at91/v2_0/src/if_at91.c new file mode 100755 index 00000000..587e42f3 --- /dev/null +++ b/packages/devs/eth/arm/at91/v2_0/src/if_at91.c @@ -0,0 +1,1029 @@ +//========================================================================== +// +// if_at91.c +// +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 Andrew Lunn +// +// 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): Andrew Lunn, John Eigelaar +// Contributors: +// Date: 2006-05-10 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include +#include +#include +#include +#if defined(CYGPKG_REDBOOT) + #include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Set up the level of debug output +#if CYGPKG_DEVS_ETH_ARM_AT91_DEBUG_LEVEL > 0 + #define debug1_printf(args...) diag_printf(args) +#else + #define debug1_printf(args...) +#endif +#if CYGPKG_DEVS_ETH_ARM_AT91_DEBUG_LEVEL > 1 + #define debug2_printf(args...) diag_printf(args) +#else + #define debug2_printf(args...) +#endif + +//Driver interface callbacks +#define _eth_drv_init(sc,mac) \ + (sc->funs->eth_drv->init)(sc,(unsigned char *)mac) +#define _eth_drv_tx_done(sc,key,status) \ + (sc->funs->eth_drv->tx_done)(sc,key,status) +#define _eth_drv_recv(sc,len) \ + (sc->funs->eth_drv->recv)(sc,len) + +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED +static cyg_uint32 +at91_eth_isr (cyg_vector_t vector, cyg_addrword_t data); +#endif + +// -------------------------------------------------------------- +// RedBoot configuration options for managing ESAs for us + +// Decide whether to have redboot config vars for it... +#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGPKG_REDBOOT_NETWORKING) + #include + #include + + #ifdef CYGSEM_DEVS_ETH_ARM_AT91_REDBOOT_HOLDS_ESA_ETH0 +RedBoot_config_option("Network hardware address [MAC] for eth0", + eth0_esa_data, + ALWAYS_ENABLED, true, + CONFIG_ESA, 0); + #endif + +#endif // CYGPKG_REDBOOT_NETWORKING && CYGSEM_REDBOOT_FLASH_CONFIG + +// and initialization code to read them +// - independent of whether we are building RedBoot right now: +#ifdef CYGPKG_DEVS_ETH_ARM_AT91_REDBOOT_HOLDS_ESA + + #include + + #ifndef CONFIG_ESA + #define CONFIG_ESA (6) + #endif + + #define CYGHWR_DEVS_ETH_ARM_AT91_GET_ESA( mac_address, ok ) \ + CYG_MACRO_START \ + ok = CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET, \ + "eth0_esa_data", \ + mac_address, \ + CONFIG_ESA); \ + CYG_MACRO_END + +#endif // CYGPKG_DEVS_ETH_AT91_ETH_REDBOOT_HOLDS_ESA + +//============================================================================ + +// Private Data structures + +#ifndef AT91_EMAC_RX_BUFF_SIZE +#define AT91_EMAC_RX_BUFF_SIZE 128 +#endif + +// Receive Buffer Descriptor +typedef struct rbd_s +{ + cyg_uint32 addr; + cyg_uint32 sr; +} rbd_t; + +// Receive Buffer +typedef struct rb_s +{ + cyg_uint8 rb[AT91_EMAC_RX_BUFF_SIZE]; +} rb_t; + +// Transmit Buffer Descriptor +typedef struct tbd_s +{ + cyg_uint32 addr; + cyg_uint32 sr; +} tbd_t; + +// AT91 Ethernet private data +typedef struct at91_eth_priv_s +{ + cyg_uint32 intr_vector; + char *esa_key; // RedBoot 'key' for device ESA + cyg_uint8 *enaddr; + cyg_uint32 base; // Base address of device + eth_phy_access_t *phy; + rbd_t rbd[CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS]; + rb_t rb[CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS]; + tbd_t tbd[CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS]; + unsigned long curr_tx_key; + cyg_bool tx_busy; + cyg_uint32 last_tbd_idx; + cyg_uint32 curr_tbd_idx; + cyg_uint32 curr_rbd_idx; +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED + cyg_interrupt intr; + cyg_handle_t intr_handle; +#endif +} at91_eth_priv_t; + +//============================================================================ +// PHY access bits and pieces +// + +static void +at91_mdio_enable(void) +{ + cyg_uint32 val; + HAL_READ_UINT32(AT91_EMAC + AT91_EMAC_NCR, val); + val |= AT91_EMAC_NCR_MPE; /* enable management port */ + HAL_WRITE_UINT32(AT91_EMAC + AT91_EMAC_NCR, val); +} + +static void +at91_mdio_disable(void) +{ + cyg_uint32 val; + HAL_READ_UINT32(AT91_EMAC + AT91_EMAC_NCR, val); + val &= ~AT91_EMAC_NCR_MPE; /* disable management port */ + HAL_WRITE_UINT32(AT91_EMAC + AT91_EMAC_NCR, val); +} + +// Write one of the PHY registers via the MII bus +static void +at91_write_phy(int reg_addr, int phy_addr, unsigned short data) +{ + cyg_uint32 val, cnt=0; + + CYG_ASSERTC(reg_addr >= 0 && reg_addr <= AT91_EMAC_MAN_REGA_MASK); + CYG_ASSERTC(phy_addr >= 0 && phy_addr <= AT91_EMAC_MAN_PHY_MASK); + + val = (AT91_EMAC_MAN_SOF | + AT91_EMAC_MAN_WR | + AT91_EMAC_MAN_CODE | + AT91_EMAC_MAN_PHYA(phy_addr) | + AT91_EMAC_MAN_REGA(reg_addr) | + AT91_EMAC_MAN_DATA(data)); + + HAL_WRITE_UINT32(AT91_EMAC + AT91_EMAC_MAN, val); + + /* Wait until IDLE bit in Network Status register is cleared */ + while (cnt < 1000000) + { + HAL_READ_UINT32((AT91_EMAC + AT91_EMAC_NSR), val); + if (!(val & AT91_EMAC_NSR_IDLE)) + break; + } + CYG_ASSERTC(cnt < 1000000); +} + + +// Read one of the PHY registers via the MII bus +static bool +at91_read_phy(int reg_addr, int phy_addr, unsigned short *data) +{ + cyg_uint32 val; + + CYG_ASSERTC(reg_addr >= 0 && reg_addr <= AT91_EMAC_MAN_REGA_MASK); + CYG_ASSERTC(phy_addr >= 0 && phy_addr <= AT91_EMAC_MAN_PHY_MASK); + + val = (AT91_EMAC_MAN_SOF | + AT91_EMAC_MAN_RD | + AT91_EMAC_MAN_CODE | + AT91_EMAC_MAN_PHYA(phy_addr) | + AT91_EMAC_MAN_REGA(reg_addr)); + + + HAL_WRITE_UINT32(AT91_EMAC + AT91_EMAC_MAN, val); + /* Wait until IDLE bit in Network Status register is cleared */ + do + { + HAL_READ_UINT32((AT91_EMAC + AT91_EMAC_NSR), val); + }while(val & AT91_EMAC_NSR_IDLE); + + HAL_DELAY_US(50); + + HAL_READ_UINT32(AT91_EMAC + AT91_EMAC_MAN, val); + *data = val & AT91_EMAC_MAN_DATA_MASK; + + return (true); +} + +// Enable the MDIO bit in MAC control register so that we can talk to +// the PHY. Also set the clock divider so that MDC is less than 2.5MHz. +static void +at91_init_phy(void) +{ + cyg_uint32 cfg; + cyg_uint32 div; + + HAL_READ_UINT32(AT91_EMAC + AT91_EMAC_NCFG, cfg); + cfg &=~ AT91_EMAC_NCFG_CLK_MASK; + + div = (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / 2500000); + if (div < 8) + { + cfg |= AT91_EMAC_NCFG_CLK_HCLK_8; + } + else if (div < 16) + { + cfg |= AT91_EMAC_NCFG_CLK_HCLK_16; + } + else if (div < 32) + { + cfg |= AT91_EMAC_NCFG_CLK_HCLK_32; + } + else if (div < 64) + { + cfg |= AT91_EMAC_NCFG_CLK_HCLK_64; + } + else + { + CYG_FAIL("Unable to program MII clock"); + } + + HAL_WRITE_UINT32(AT91_EMAC + AT91_EMAC_NCFG, cfg); +} + +ETH_PHY_REG_LEVEL_ACCESS_FUNS(at91_phy, + at91_init_phy, + NULL, + at91_write_phy, + at91_read_phy); + +//====================================================================== +// Receiver buffer handling + +// Initialize the receiver buffers and descriptors +static void +at91_rb_init(at91_eth_priv_t *priv) +{ + int i; + for (i = 0 ; i < CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS; i++) + { + priv->rbd[i].addr = ((cyg_uint32)&priv->rb[i]) & AT91_EMAC_RBD_ADDR_MASK; + priv->rbd[i].sr = 0; + } + // Set the wrap bit on the last entry + priv->rbd[CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS-1].addr |= + AT91_EMAC_RBD_ADDR_WRAP; +} + +//====================================================================== +// Transmit buffer handling + +// Initialize the transmit buffer descriptors +static void +at91_tb_init(at91_eth_priv_t *priv) +{ + int i; + for (i = 0 ; i < CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS; i++) + { + priv->tbd[i].addr = 0; + priv->tbd[i].sr = AT91_EMAC_TBD_SR_USED; + } + // Set the wrap bit on the last entry + priv->tbd[CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS-1].sr |= AT91_EMAC_TBD_SR_WRAP; +} + +//====================================================================== +// Enable and Disable of the receiver and transmitter. + +static void +at91_disable_rx(at91_eth_priv_t *priv) +{ + cyg_uint32 ctl; + + HAL_READ_UINT32(priv->base + AT91_EMAC_NCR, ctl); + ctl &= ~AT91_EMAC_NCR_RE; + HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCR, ctl); +} + +static void +at91_disable_tx(at91_eth_priv_t *priv) +{ + cyg_uint32 ctl; + + HAL_READ_UINT32(priv->base + AT91_EMAC_NCR, ctl); + ctl &= ~AT91_EMAC_NCR_TX; + HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCR, ctl); +} + +static void +at91_enable_rx(at91_eth_priv_t *priv) +{ + cyg_uint32 ctl; + + HAL_READ_UINT32(priv->base + AT91_EMAC_NCR, ctl); + ctl |= AT91_EMAC_NCR_RE; + HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCR, ctl); +} + +static void +at91_enable_tx(at91_eth_priv_t *priv) +{ + cyg_uint32 ctl; + + HAL_READ_UINT32(priv->base + AT91_EMAC_NCR, ctl); + ctl |= AT91_EMAC_NCR_TX; + HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCR, ctl); +} + +static void +at91_enable(at91_eth_priv_t *priv) +{ + at91_enable_tx(priv); + at91_enable_rx(priv); +} + +static void +at91_disable(at91_eth_priv_t *priv) +{ + at91_disable_tx(priv); + at91_disable_rx(priv); +} + +static void +at91_start_transmitter(at91_eth_priv_t *priv) +{ + cyg_uint32 ctl; + + HAL_READ_UINT32(priv->base + AT91_EMAC_NCR, ctl); + ctl |= AT91_EMAC_NCR_TSTART; + HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCR, ctl); +} + + +//====================================================================== +// Initialization code + +// Configure the pins so that the EMAC has control of them. This +// assumes the MII is used, not the RMII +static void +at91_cfg_pins(void) +{ + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_EREFCK); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ECRS); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ECOL); + + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ERXDV); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ERX0); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ERX1); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ERX2); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ERX3); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ERXER); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ERXCK); + + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ETXEN); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ETX0); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ETX1); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ETX2); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ETX3); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_ETXER); + + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_EMDC); + HAL_ARM_AT91_PIO_CFG(AT91_EMAC_EMDIO); +} + +// Set a specific address match to a given address. Packets received which +// match this address will be passed on. +static void +at91_set_mac(at91_eth_priv_t * priv, cyg_uint8 * enaddr, int sa) +{ + cyg_uint32 hi, lo; + + CYG_ASSERTC(sa > 0 && sa < 5); + sa--; + + lo = ((enaddr[3] << 24) | + (enaddr[2] << 16) | + (enaddr[1] << 8) | + (enaddr[0])); + + hi = ((enaddr[5] << 8) | + (enaddr[4])); + + HAL_WRITE_UINT32(priv->base + AT91_EMAC_SA1L + (8*sa), lo); + HAL_WRITE_UINT32(priv->base + AT91_EMAC_SA1H + (8*sa), hi); +} + +static void +at91_clear_stats(at91_eth_priv_t *priv) +{ + cyg_uint32 ctl; + + HAL_READ_UINT32(priv->base + AT91_EMAC_NCR, ctl); + ctl |= AT91_EMAC_NCR_CSR; + HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCR, ctl); +} + +// Enable and Disable of the receiver and transmitter. +// Initialize the interface. This configures the interface ready for use. +// Interrupts are grabbed etc. This means the start function has +// little to do except enable the receiver +static bool +at91_eth_init(struct cyg_netdevtab_entry *tab) +{ + struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; + at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private; + bool esa_ok = false; + unsigned char enaddr[6] = { CYGPKG_DEVS_ETH_ARM_AT91_MACADDR}; + unsigned char enzero[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + unsigned short phy_state = 0; + cyg_uint32 ncfg = 0; + + debug1_printf("\nAT91_ETH: Initialising @ %x\n",priv->base); + + priv->tx_busy = false; + priv->curr_tbd_idx = 0; + priv->curr_rbd_idx = 0; + + // Enable the clock to the EMAC + HAL_WRITE_UINT32(AT91_PMC + AT91_PMC_PCER, AT91_PMC_PCER_EMAC); + HAL_WRITE_UINT32(AT91_PMC + AT91_PMC_PCER, AT91_PMC_PCER_PIOB); + HAL_WRITE_UINT32(AT91_PMC + AT91_PMC_PCER, AT91_PMC_PCER_PIOA); + + //at91_disable(priv); + at91_cfg_pins(); + + /* Enable IO Clock */ + HAL_WRITE_UINT32(priv->base+AT91_EMAC_USRIO,AT91_EMAC_USRIO_CLKEN); + + /* Disable all the interrupts for the moment */ + /* The Start function actually enables all that we need */ + //HAL_WRITE_UINT32(priv->base + AT91_EMAC_IDR, 0x3FFF); + + // If we are building an interrupt enabled version, install the + // interrupt handler +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED + debug1_printf("AT91_ETH: Installing Interrupts on IRQ %d\n", + priv->intr_vector); + cyg_drv_interrupt_create(priv->intr_vector, + 4, + (cyg_addrword_t)sc, + at91_eth_isr, + eth_drv_dsr, + &priv->intr_handle, + &priv->intr); + + cyg_drv_interrupt_attach(priv->intr_handle); + cyg_drv_interrupt_unmask(priv->intr_vector); +#endif + +#ifdef CYGHWR_DEVS_ETH_ARM_AT91_GET_ESA + // Get MAC address from RedBoot configuration variables + CYGHWR_DEVS_ETH_ARM_AT91_GET_ESA(&enaddr[0], esa_ok); + // If this call fails myMacAddr is unchanged and MAC address from + // CDL is used +#endif + + if (!esa_ok) + { + // Can't figure out ESA + debug1_printf("AT91_ETH - Warning! ESA unknown\n"); + } + debug1_printf("AT91_ETH: %02x:%02x:%02x:%02x:%02x:%02x\n", + enaddr[0],enaddr[1],enaddr[2], + enaddr[3],enaddr[4],enaddr[5]); + + // Give the EMAC its address + at91_set_mac(priv, enaddr, 1); + at91_set_mac(priv, enzero, 2); + at91_set_mac(priv, enzero, 3); + at91_set_mac(priv, enzero, 4); + + // Setup the receiver buffers and descriptors + at91_rb_init(priv); + + // And tell the EMAC where the first receive buffer descriptor is + HAL_WRITE_UINT32(priv->base + AT91_EMAC_RBQP, (cyg_uint32)priv->rbd); + + // Setup the transmit descriptors + at91_tb_init(priv); + + // And tell the EMAC where the first transmit buffer descriptor is + HAL_WRITE_UINT32(priv->base + AT91_EMAC_TBQP, (cyg_uint32)priv->tbd); + + // Setup the PHY + CYG_ASSERTC(priv->phy); + + at91_mdio_enable(); + if (!_eth_phy_init(priv->phy)) + { + at91_mdio_disable(); + return (false); + } + + // Get the current mode and print it + phy_state = _eth_phy_state(priv->phy); + at91_mdio_disable(); + + HAL_READ_UINT32(priv->base + AT91_EMAC_NCFG,ncfg); + + + if ((phy_state & ETH_PHY_STAT_LINK) != 0) + { + if (((phy_state & ETH_PHY_STAT_100MB) != 0)) + { + debug1_printf("AT91_ETH: 100Mbyte/s"); + ncfg |= AT91_EMAC_NCFG_SPD_100Mbps; + } + else + { + debug1_printf("AT91_ETH: 10Mbyte/s"); + ncfg &= ~(AT91_EMAC_NCFG_SPD_100Mbps); + } + if((phy_state & ETH_PHY_STAT_FDX)) + { + debug1_printf(" Full Duplex\n"); + ncfg |= AT91_EMAC_NCFG_FD; + } + else + { + debug1_printf(" Half Duplex\n"); + ncfg &= ~(AT91_EMAC_NCFG_FD); + } + } + else + { + debug1_printf("AT91_ETH: No Link\n"); + } + + + //Setup the network configuration + ncfg |= (AT91_EMAC_NCFG_RLCE); + + HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCFG,ncfg); + + // Clear the Statistics counters; + at91_clear_stats(priv); + + + /* Clear the status registers */ + HAL_READ_UINT32(priv->base + AT91_EMAC_ISR,ncfg); + HAL_READ_UINT32(priv->base + AT91_EMAC_RSR,ncfg); + HAL_WRITE_UINT32(priv->base + AT91_EMAC_RSR,ncfg); + HAL_READ_UINT32(priv->base + AT91_EMAC_TSR,ncfg); + HAL_WRITE_UINT32(priv->base + AT91_EMAC_TSR,ncfg); + + // Initialize the upper layer driver + _eth_drv_init(sc,enaddr); + + return (true); +} + +// This function is called to stop the interface. +static void +at91_eth_stop(struct eth_drv_sc *sc) +{ + at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private; + + at91_disable(priv); +} + +// This function is called to "start up" the interface. It may be called +// multiple times, even when the hardware is already running. +static void +at91_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags) +{ + at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private; + cyg_uint32 bits; + + // Enable the interrupts we are interested in + // TODO: We probably need to add at least the RBNA interrupt here + // as well in order to do some error handling + bits = (AT91_EMAC_ISR_RCOM | AT91_EMAC_ISR_TCOM); + + HAL_WRITE_UINT32(priv->base + AT91_EMAC_IER, bits); + + // Enable the receiver and transmitter + at91_enable(priv); +} + +// This function is called for low level "control" operations +static int +at91_eth_control(struct eth_drv_sc *sc, unsigned long key, + void *data, int length) +{ + + switch (key) + { + case ETH_DRV_SET_MAC_ADDRESS: + { + if(length >= ETHER_ADDR_LEN) + { + at91_eth_stop(sc); + + cyg_uint8 * enaddr = (cyg_uint8 *)data; + debug1_printf("AT91_ETH: %02x:%02x:%02x:%02x:%02x:%02x\n", + enaddr[0],enaddr[1],enaddr[2], + enaddr[3],enaddr[4],enaddr[5]); + + at91_set_mac((at91_eth_priv_t *)sc->driver_private,enaddr,1); + at91_eth_start(sc,enaddr,0); + return 0; + } + return 1; + } + default: + { + diag_printf("%s.%d: key %lx\n", __FUNCTION__, __LINE__, key); + return (1); + } + } + +} + +// This function is called to see if another packet can be sent. +// It should return the number of packets which can be handled. +// Zero should be returned if the interface is busy and can not send +// any more. +// +// We allocate one buffer descriptor per scatter/gather entry. We assume that +// a typical packet will not have more than 3 such entries, and so we say we +// can send a packet when we have 3 or more buffer descriptors free +// +// TODO: Implement what the comment actually says! +static int +at91_eth_can_send(struct eth_drv_sc *sc) +{ + int can_send; + at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private; + if(priv->tx_busy) + { + can_send = 0; + } + else + { + can_send = 1; + } + return (can_send); +} + +// This routine is called to send data to the hardware +static void +at91_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, + int total_len, unsigned long key) +{ + at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private; + int i; + cyg_uint32 sr; + + priv->tx_busy = true; + + priv->last_tbd_idx = priv->curr_tbd_idx; + + for(i = 0;itbd[priv->curr_tbd_idx].addr = sg_list[i].buf; + + sr = (sg_list[i].len & AT91_EMAC_TBD_SR_LEN_MASK); + // Set the End Of Frame bit in the last descriptor + if(i == (sg_len-1)) + { + sr |= AT91_EMAC_TBD_SR_EOF; + } + + if(priv->curr_tbd_idx < (CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS-1)) + { + priv->tbd[priv->curr_tbd_idx].sr = sr; + priv->curr_tbd_idx++; + } + else + { + priv->tbd[priv->curr_tbd_idx].sr = (sr | AT91_EMAC_TBD_SR_WRAP); + priv->curr_tbd_idx = 0; + } + } + + // Store away the key for when the transmit has completed + // and we need to tell the stack which transmit has completed. + priv->curr_tx_key = key; + + at91_start_transmitter(priv); +} + +static void at91_reset_tbd(at91_eth_priv_t *priv) +{ + while(priv->curr_tbd_idx != priv->last_tbd_idx) + { + if(priv->last_tbd_idx == (CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS-1)) + { + priv->tbd[priv->last_tbd_idx].sr = + (AT91_EMAC_TBD_SR_USED|AT91_EMAC_TBD_SR_WRAP); + priv->last_tbd_idx = 0; + } + else + { + priv->tbd[priv->last_tbd_idx].sr = AT91_EMAC_TBD_SR_USED; + priv->last_tbd_idx++; + } + } +} + + +//====================================================================== + +#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED +static cyg_uint32 +at91_eth_isr (cyg_vector_t vector, cyg_addrword_t data) +{ + struct eth_drv_sc *sc = (struct eth_drv_sc *)data; + at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private; + cyg_uint32 ret; + cyg_uint32 isr; + + /* Get the interrupt status */ + HAL_READ_UINT32(priv->base+AT91_EMAC_ISR,isr); + + ret = CYG_ISR_HANDLED; + + //TODO: We should probably be handling some of the error interrupts as well + if(isr & AT91_EMAC_ISR_TCOM) + { + ret = CYG_ISR_CALL_DSR; + } + + if(isr & AT91_EMAC_ISR_RCOM) + { + ret = CYG_ISR_CALL_DSR; + } + cyg_interrupt_acknowledge(vector); + return(ret); +} +#endif + +static void +at91_eth_deliver(struct eth_drv_sc *sc) +{ + at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private; + + cyg_uint32 tsr; + cyg_uint32 rsr; + + cyg_uint32 ctr; + cyg_uint32 cnt; + cyg_uint32 idx; + + /* Get the Transmit Status */ + HAL_READ_UINT32(priv->base+AT91_EMAC_TSR,tsr); + HAL_WRITE_UINT32(priv->base+AT91_EMAC_TSR,tsr); + + /* Get the Receive Status */ + HAL_READ_UINT32(priv->base+AT91_EMAC_RSR,rsr); + HAL_WRITE_UINT32(priv->base+AT91_EMAC_RSR,rsr); + + + //TODO: The interrupts other than RCOMP and TCOMP needs to be + // handled properly especially stuff like RBNA which could have + // serious effects on driver performance + + /* Service the TX buffers */ + if (tsr&AT91_EMAC_TSR_COL) //1 + { + debug1_printf("AT91_ETH: Tx COL\n"); + } + + if (tsr&AT91_EMAC_TSR_RLE) //2 + { + debug1_printf("AT91_ETH: Tx RLE\n"); + } + + if (tsr&AT91_EMAC_TSR_BNQ) //4 + { + debug1_printf("AT91_ETH: Tx BEX\n"); + } + + if (tsr&AT91_EMAC_TSR_UND) //6 + { + debug1_printf("AT91_ETH: Tx UND\n"); + } + + /* Check that the last transmission is completed */ + if (tsr&AT91_EMAC_TSR_COMP) //5 + { + at91_reset_tbd(priv); + _eth_drv_tx_done(sc,priv->curr_tx_key,0); + priv->tx_busy = false; + } + + /* Service the RX buffers when we get something */ + if (rsr&AT91_EMAC_RSR_REC) + { + /* Do this all until we find the first EMAC Buffer */ + while (priv->rbd[priv->curr_rbd_idx].addr & AT91_EMAC_RBD_ADDR_OWNER_SW) + { + + //Firstly walk through to either the first buffer that belongs + // to the controller or the first SOF + while ((priv->rbd[priv->curr_rbd_idx].addr & + AT91_EMAC_RBD_ADDR_OWNER_SW) && + !(priv->rbd[priv->curr_rbd_idx].sr & + AT91_EMAC_RBD_SR_SOF)) + { + priv->rbd[priv->curr_rbd_idx].addr &= + ~(AT91_EMAC_RBD_ADDR_OWNER_SW); + priv->curr_rbd_idx++; + if (priv->curr_rbd_idx >= CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS) + { + priv->curr_rbd_idx = 0; + } + } + + /* Check that we did find a SOF*/ + if ((priv->rbd[priv->curr_rbd_idx].addr & + AT91_EMAC_RBD_ADDR_OWNER_SW) && + (priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_SOF)) + { + cnt = 0; + for (ctr=0;ctrcurr_rbd_idx)%CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS; + cnt += (priv->rbd[idx].sr & AT91_EMAC_RBD_SR_LEN_MASK); + if (priv->rbd[idx].sr & AT91_EMAC_RBD_SR_EOF) + { + /* The recv function will adjust the current buffer idx + after the buffer has been cleared + */ + if (cnt) + _eth_drv_recv(sc,cnt); + break; + } + } + } + } + } + + if (rsr&AT91_EMAC_RSR_BNA) + { + debug1_printf("AT91_ETH: Rx BNA\n"); + } + if (rsr&AT91_EMAC_RSR_OVR) + { + debug1_printf("AT91_ETH: Rx OVR\n"); + } + +} + +static void +at91_eth_recv(struct eth_drv_sc *sc, + struct eth_drv_sg *sg_list, + int sg_len) +{ + at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private; + int i; + cyg_uint32 bytes_in_buffer; + cyg_uint32 bytes_in_list = 0; + cyg_uint32 bytes_needed_list = 0; + cyg_uint32 buffer_pos = 0; + cyg_uint8 * sg_buf; + cyg_uint32 total_bytes = 0; + + for(i = 0;irbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_EOF) + { + bytes_in_buffer = + ((priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_LEN_MASK) + - total_bytes) - buffer_pos; + } + else + { + bytes_in_buffer = AT91_EMAC_RX_BUFF_SIZE - buffer_pos; + } + + sg_buf = (cyg_uint8 *)(sg_list[i].buf); + + if(bytes_needed_list < bytes_in_buffer) + { + if(sg_buf != NULL) + memcpy(&sg_buf[bytes_in_list], + &priv->rb[priv->curr_rbd_idx].rb[buffer_pos], + bytes_needed_list); + bytes_in_list += bytes_needed_list; + buffer_pos += bytes_needed_list; + total_bytes += bytes_needed_list; + } + else + { + if(sg_buf != NULL) + memcpy(&sg_buf[bytes_in_list], + &priv->rb[priv->curr_rbd_idx].rb[buffer_pos], + bytes_in_buffer); + bytes_in_list += bytes_in_buffer; + total_bytes += bytes_in_buffer; + + /* Step our buffer on one */ + priv->rbd[priv->curr_rbd_idx].addr &= + ~(AT91_EMAC_RBD_ADDR_OWNER_SW); + priv->curr_rbd_idx++; + if(priv->curr_rbd_idx >= CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS) + { + priv->curr_rbd_idx = 0; + } + buffer_pos = 0; + } + } + } +} + +// routine called to handle ethernet controller in polled mode +static void +at91_eth_poll(struct eth_drv_sc *sc) +{ + /* Service the buffers */ + at91_eth_deliver(sc); +} + +static int +at91_eth_int_vector(struct eth_drv_sc *sc) +{ + return(CYGNUM_HAL_INTERRUPT_EMAC); +} + +at91_eth_priv_t at91_priv_data = +{ + .intr_vector = CYGNUM_HAL_INTERRUPT_EMAC, + .base = AT91_EMAC, + .phy = &at91_phy +}; + +ETH_DRV_SC(at91_sc, + &at91_priv_data, // Driver specific data + "eth0", // Name for this interface + at91_eth_start, + at91_eth_stop, + at91_eth_control, + at91_eth_can_send, + at91_eth_send, + at91_eth_recv, + at91_eth_deliver, + at91_eth_poll, + at91_eth_int_vector); + +NETDEVTAB_ENTRY(at91_netdev, + "at91", + at91_eth_init, + &at91_sc); + +// EOF if_at91.c diff --git a/packages/devs/eth/arm/phycore229x/v2_0/ChangeLog b/packages/devs/eth/arm/phycore229x/v2_0/ChangeLog new file mode 100644 index 00000000..55a205f8 --- /dev/null +++ b/packages/devs/eth/arm/phycore229x/v2_0/ChangeLog @@ -0,0 +1,38 @@ +2008-01-01 Uwe Kindler + + * cdl/phycore229x_eth_drivers.cdl: + * include/devs_eth_phycore229x.inl: + release of phyCORE-LPC229x ethernet driver package + +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2008 eCosCentric Ltd. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== diff --git a/packages/devs/eth/arm/phycore229x/v2_0/cdl/phycore229x_eth_drivers.cdl b/packages/devs/eth/arm/phycore229x/v2_0/cdl/phycore229x_eth_drivers.cdl new file mode 100755 index 00000000..b6c5e0ae --- /dev/null +++ b/packages/devs/eth/arm/phycore229x/v2_0/cdl/phycore229x_eth_drivers.cdl @@ -0,0 +1,116 @@ +# ==================================================================== +# +# phycore229x_eth_drivers.cdl +# +# Ethernet drivers - platform support for phyCORE-LPC229x +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2008 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-11-24 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_ARM_PHYCORE229X { + display "LAN ethernet driver for phyCORE-LPC229x" + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_HAL_ARM_LPC2XXX_PHYCORE229X + + include_dir cyg/io + + # 32-bit mode, with EEPROM + implements CYGHWR_NET_DRIVERS + implements CYGHWR_NET_DRIVER_ETH0 + implements CYGINT_DEVS_ETH_SMSC_LAN91CXX_REQUIRED + + requires CYGPKG_DEVS_ETH_SMSC_LAN91CXX + requires CYGNUM_DEVS_ETH_SMSC_LAN91CXX_INT_PRIO == CYGHWR_HAL_ARM_PHYCORE229X_ETH_INT_PRIO + + description "This option includes the ethernet device driver for the + phyCORE-LPC229x board." + + define_proc { + puts $::cdl_system_header "/***** ethernet driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_SMSC_LAN91CXX_INL " + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_SMSC_LAN91CXX_CFG " + puts $::cdl_system_header "/***** ethernet driver proc output end *****/" + } + + # Arguably this should do in the generic package + # but then there is a logic loop so you can never enable it. + + cdl_interface CYGINT_DEVS_ETH_SMSC_LAN91CXX_REQUIRED { + display "SMSC LAN91CXX driver required" + } + + cdl_option CYGDAT_DEVS_ETH_ARM_PHYCORE229X_NAME { + display "Device name for the ETH0 ethernet driver" + flavor data + default_value {"\"eth0\""} + description " + This option sets the name of the ethernet device." + } + + cdl_component CYGSEM_DEVS_ETH_ARM_PHYCORE229X_SET_ESA { + display "Set the ethernet station address" + flavor bool + default_value 0 + description " + Enabling this option will allow the ethernet + station address to be forced to the value set by the + configuration. This may be required if the hardware does + not include a serial EEPROM for the ESA. The phyCORE + board contains an EEPROM so setting the ESA here is not + required. If RedBoot supports FLASH configuration then + the MAC address is configurable and a static MAC address + is not required." + + cdl_option CYGDAT_DEVS_ETH_ARM_PHYCORE229X_ESA { + display "The ethernet station address (MAC)" + flavor data + default_value {"{0x12, 0x13, 0x14, 0x15, 0x16, 0x17}"} + description " + A static ethernet station address. Caution: Booting two systems + with the same MAC on the same network, will cause severe conflicts." + } + } +} + +# EOF phycore229x_eth_drivers.cdl diff --git a/packages/devs/eth/arm/phycore229x/v2_0/include/devs_eth_phycore229x.inl b/packages/devs/eth/arm/phycore229x/v2_0/include/devs_eth_phycore229x.inl new file mode 100755 index 00000000..14d0a204 --- /dev/null +++ b/packages/devs/eth/arm/phycore229x/v2_0/include/devs_eth_phycore229x.inl @@ -0,0 +1,203 @@ +#ifndef CYGONCE_DEVS_ETH_PHYCORE229X_INL +#define CYGONCE_DEVS_ETH_PHYCORE229X_INL +//========================================================================== +// +// devs_eth_phycore_229x.inl +// +// phyCORE-LPC229x ethernet I/O definitions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 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-11-24 +// Purpose: +//####DESCRIPTIONEND#### +//========================================================================== + + +//========================================================================== +// INCLUDES +//========================================================================== +#include +#include +#include + +#ifdef CYGPKG_REDBOOT + #include + #ifdef CYGSEM_REDBOOT_FLASH_CONFIG + #include + #include + #endif // CYGSEM_REDBOOT_FLASH_CONFIG +#endif // CYGPKG_REDBOOT + + + +//-------------------------------------------------------------------------- +// Configure LAN91CXX driver +// +#define LAN91CXX_IS_LAN91C111 1 +#define LAN91CXX_FORCE_10MHZ 1 // due a PCB tracking problem only + // 10 MHz is possible +#define LAN91CXX_32BIT_RX 1 // 32 bit access + + +//-------------------------------------------------------------------------- +// RedBoot ESA Flash configuration options +// When this option is enabled, RedBoot will keep configuration +// data in a separate block of FLASH memory. +// +#if defined(CYGPKG_REDBOOT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG) +RedBoot_config_option("Set " CYGDAT_DEVS_ETH_ARM_PHYCORE229X_NAME " network hardware address [MAC]", + eth0_esa, + ALWAYS_ENABLED, true, + CONFIG_BOOL, false + ); +RedBoot_config_option(CYGDAT_DEVS_ETH_ARM_PHYCORE229X_NAME " network hardware address [MAC]", + eth0_esa_data, + "eth0_esa", true, + CONFIG_ESA, 0 + ); +#endif // CYGPKG_REDBOOT && CYGSEM_REDBOOT_FLASH_CONFIG + + +//-------------------------------------------------------------------------- +// Application ESA Flash configuration options +// Note that this section *is* active in an application, outside +// RedBoot, where the above section is not included. +// +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT +#include + +#ifndef CONFIG_ESA + #define CONFIG_ESA (6) +#endif +#ifndef CONFIG_BOOL + #define CONFIG_BOOL (1) +#endif + + +//-------------------------------------------------------------------------- +// Provide ESA function +// Returns true if ESA is configured by flash, else false +// +cyg_bool phycore229x_provide_esa(struct lan91cxx_priv_data *cpd) +{ + cyg_bool set_esa; + int ok; + + + // + // first we check, if the ESA should be set according to flash + // configuration + // + ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, + "eth0_esa", + &set_esa, + CONFIG_BOOL); + // + // if esa should be set by flash configuration, then we store the + // esa from flash in driver configuration data and return true + // + if (ok && set_esa) + { + ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, + "eth0_esa_data", + cpd->enaddr, + CONFIG_ESA); + } + return ok && set_esa; +} +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + + +//--------------------------------------------------------------------------- +// Stores configuration data for generic smsc91xxx driver +// +static lan91cxx_priv_data lan91cxx_eth0_priv_data = { + base : (unsigned short *)(CYGHWR_HAL_ARM_PHYCORE229X_ETH_MEM_AREA + + 0x0300), + interrupt : ( CYGHWR_HAL_ARM_PHYCORE229X_ETH_EINT + + CYGNUM_HAL_INTERRUPT_EINT0) , + // + // if user selects a hardwired ESA in configuration then + // we fill the ESA here + // +#ifdef CYGSEM_DEVS_ETH_PHYCORE229X_SET_ESA + enaddr : CYGDAT_DEVS_ETH_PHYCORE229X_ESA, + hardwired_esa : true, +#else + hardwired_esa : false, +#endif +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + provide_esa : &phycore229x_provide_esa, +#else + provide_esa : NULL, // read MAC from associated EEPROM +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT +}; // lan91cxx_priv_data + + +//--------------------------------------------------------------------------- +// Driver configuration +// +ETH_DRV_SC( + lan91cxx_sc, + &lan91cxx_eth0_priv_data, // driver specific data + CYGDAT_DEVS_ETH_ARM_PHYCORE229X_NAME, // device name + lan91cxx_start, + lan91cxx_stop, + lan91cxx_control, + lan91cxx_can_send, + lan91cxx_send, + lan91cxx_recv, + lan91cxx_deliver, + lan91cxx_poll, + lan91cxx_int_vector +); + + +//--------------------------------------------------------------------------- +// Entry into net device table +// +NETDEVTAB_ENTRY( + lan91cxx_netdev, + "lan91cxx_" CYGDAT_DEVS_ETH_ARM_PHYCORE229X_NAME, + smsc_lan91cxx_init, + &lan91cxx_sc +); + +//--------------------------------------------------------------------------- +#endif // CYGONCE_DEVS_ETH_PHYCORE229X_INL diff --git a/packages/devs/eth/phy/v2_0/src/DM9161A.c b/packages/devs/eth/phy/v2_0/src/DM9161A.c new file mode 100644 index 00000000..af19dab5 --- /dev/null +++ b/packages/devs/eth/phy/v2_0/src/DM9161A.c @@ -0,0 +1,134 @@ +//========================================================================== +// +// dev/DM9161A.c +// +// Ethernet transceiver (PHY) support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// 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): John Eigelaar +// Contributors: Gary Thomas +// Date: 2006-12-07 +// Purpose: +// Description: Support for Davicom DM9161A PHY +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#define DM9161A_BMSR 0x01 +#define DM9161A_BMSR_ANEG_COMP (1<<5) +#define DM9161A_BMSR_LINK (1<<2) + +#define DM9161A_BMCR 0x00 + +#define DM9161A_DSCSR 17 +#define DM9161A_DSCSR_100FDX (1<<15) +#define DM9161A_DSCSR_100HDX (1<<14) +#define DM9161A_DSCSR_10FDX (1<<13) +#define DM9161A_DSCSR_10HDX (1<<12) + +static bool dm9161a_stat(eth_phy_access_t *f, int *state) +{ + unsigned short phy_state; + int tries; + + *state = 0; + // Read negotiated state + + if (_eth_phy_read(f, DM9161A_BMSR, f->phy_addr, &phy_state)) + { + if ((phy_state & DM9161A_BMSR_ANEG_COMP) == 0) + { + eth_phy_printf("... waiting for auto-negotiation"); + for (tries = 0; tries < CYGINT_DEVS_ETH_PHY_AUTO_NEGOTIATION_TIME; + tries++) + { + if (_eth_phy_read(f, DM9161A_BMSR, f->phy_addr, &phy_state)) + { + if ((phy_state & DM9161A_BMSR_ANEG_COMP) != 0) + { + break; + } + } + CYGACC_CALL_IF_DELAY_US(1000000); // 1 second + eth_phy_printf("."); + } + eth_phy_printf("\n"); + } + if ((phy_state & DM9161A_BMSR_ANEG_COMP) != 0) + { + *state = 0; + if (!_eth_phy_read(f, DM9161A_DSCSR, f->phy_addr, &phy_state)) + return false; + + if (phy_state & 0xF000) + { + *state |= ETH_PHY_STAT_LINK; + } + if ((phy_state & DM9161A_DSCSR_100FDX) || + (phy_state & DM9161A_DSCSR_100HDX)) + { + *state |= ETH_PHY_STAT_100MB; + } + if ((phy_state & DM9161A_DSCSR_100FDX) || + (phy_state & DM9161A_DSCSR_10FDX)) + { + *state |= ETH_PHY_STAT_FDX; + } + + return (true); + } + } + return (false); +} + +_eth_phy_dev("Davicom DM9161A", 0x0181B8A0, dm9161a_stat) diff --git a/packages/devs/eth/phy/v2_0/src/KS8721.c b/packages/devs/eth/phy/v2_0/src/KS8721.c new file mode 100644 index 00000000..12c29c74 --- /dev/null +++ b/packages/devs/eth/phy/v2_0/src/KS8721.c @@ -0,0 +1,115 @@ +//========================================================================== +// +// dev/KS8721.c +// +// Ethernet transceiver (PHY) support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005 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: Markus Schade +// Date: 2007-04-04 +// Purpose: +// Description: Support for ethernet Micrel KS8721 PHY +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + + +static bool ks8721_stat(eth_phy_access_t *f, int *state) +{ + unsigned short phy_state; + unsigned short phy_anadv_reg; + int tries; + int ms; + + // Read negotiated state + if (_eth_phy_read(f, PHY_BMSR, f->phy_addr, &phy_state)) + { + if ((phy_state & PHY_BMSR_AUTO_NEG) == 0) + { + eth_phy_printf("... waiting for auto-negotiation"); + for (tries = 0; tries < CYGINT_DEVS_ETH_PHY_AUTO_NEGOTIATION_TIME; tries++) + { + if (_eth_phy_read(f, PHY_BMSR, f->phy_addr, &phy_state)) + { + if ((phy_state & PHY_BMSR_AUTO_NEG) != 0) + { + break; + } + } + + // + // Wait for 1 second + // + for (ms = 0; ms < 1000; ++ms) + { + CYGACC_CALL_IF_DELAY_US(1000); // 1 ms + } + eth_phy_printf("."); + } + eth_phy_printf("\n"); + } + if ((phy_state & PHY_BMSR_AUTO_NEG) != 0) + { + _eth_phy_read(f, PHY_AN_ADV, f->phy_addr, &phy_anadv_reg); + eth_phy_printf("\nAuto negotiation advertisement: %x\n", phy_anadv_reg); + *state = 0; + if ((phy_state & PHY_BMSR_LINK) != 0) *state |= ETH_PHY_STAT_LINK; + if ((phy_anadv_reg & PHY_AN_ADV_100FDX) != 0) *state |= ETH_PHY_STAT_100MB | ETH_PHY_STAT_FDX; + return true; + } + } + return false; +} + +_eth_phy_dev("Micrel KS8721", 0x00221619, ks8721_stat) diff --git a/packages/devs/eth/phy/v2_0/src/ics189x.c b/packages/devs/eth/phy/v2_0/src/ics189x.c new file mode 100644 index 00000000..5e13969f --- /dev/null +++ b/packages/devs/eth/phy/v2_0/src/ics189x.c @@ -0,0 +1,119 @@ +//========================================================================== +// +// ics189x.c +// +// Ethernet transceiver (PHY) support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005 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): gthomas +// Contributors: Jay Foster +// Date: 2006-03-17 +// Purpose: +// Description: Support for ethernet ICS 189x PHYs +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#define Bit(n) (1<<(n)) + +static bool ics189x_stat(eth_phy_access_t *f, int *state) +{ + unsigned short phy_state; + int tries; + + // Read negotiated state from the Quick Poll Detailed Status Register + if (_eth_phy_read(f, 17, f->phy_addr, &phy_state)) + { + if ((phy_state & Bit(4)) == 0) + { + eth_phy_printf("... waiting for auto-negotiation"); + for (tries = 0; tries < CYGINT_DEVS_ETH_PHY_AUTO_NEGOTIATION_TIME; tries++) + { + if (_eth_phy_read(f, 17, f->phy_addr, &phy_state)) + { + if ((phy_state & Bit(4)) != 0) + { + break; + } + } + CYGACC_CALL_IF_DELAY_US(1000000); // 1 second + eth_phy_printf("."); + } + eth_phy_printf("\n"); + } + if ((phy_state & Bit(4)) != 0) + { + *state = 0; + if (phy_state & Bit(0)) + *state |= ETH_PHY_STAT_LINK; + if (phy_state & Bit(14)) + *state |= ETH_PHY_STAT_FDX; + if (phy_state & Bit(15)) + *state |= ETH_PHY_STAT_100MB; + return true; + } + } + return false; +} + +#ifdef CYGHWR_DEVS_ETH_PHY_ICS1890 +_eth_phy_dev("ICS 1890", 0x0015F422, ics189x_stat) // 1st general release +_eth_phy_dev("ICS 1890", 0x0015F423, ics189x_stat) // 1890 "J" release +#endif +#ifdef CYGHWR_DEVS_ETH_PHY_ICS1892 +_eth_phy_dev("ICS 1892", 0x0015F430, ics189x_stat) +#endif +#ifdef CYGHWR_DEVS_ETH_PHY_ICS1893 +_eth_phy_dev("ICS 1893", 0x0015F441, ics189x_stat) +#endif + diff --git a/packages/devs/flash/arm/ea2468/v2_0/ChangeLog b/packages/devs/flash/arm/ea2468/v2_0/ChangeLog new file mode 100755 index 00000000..4b61c1a7 --- /dev/null +++ b/packages/devs/flash/arm/ea2468/v2_0/ChangeLog @@ -0,0 +1,39 @@ +2008-07-08 Uwe Kindler + + * src/flash_ea2468.c: + * cdl/flash_ea2468.cdl: New package/file(s). + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/flash/arm/ea2468/v2_0/cdl/flash_ea2468.cdl b/packages/devs/flash/arm/ea2468/v2_0/cdl/flash_ea2468.cdl new file mode 100755 index 00000000..f200d9e0 --- /dev/null +++ b/packages/devs/flash/arm/ea2468/v2_0/cdl/flash_ea2468.cdl @@ -0,0 +1,71 @@ +# ==================================================================== +# +# flash_ea2468.cdl +# +# FLASH memory - Hardware support on EA LPC2468 OEM board +# +# ==================================================================== +#####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 Andrew Lunn +## +## 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: +# Date: 2008-07-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_EA2468 { + display "EA LPC2468 OEM board FLASH memory support" + description "FLASH memory device support for Embedded Artists LPC2468 OEM board" + + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + requires CYGPKG_HAL_ARM_LPC24XX + + compile -library=libextras.a flash_ea2468.c + + # Arguably this should do in the generic package + # but then there is a logic loop so you can never enable it. + cdl_interface CYGINT_DEVS_FLASH_SST_39VFXXX_REQUIRED { + display "Generic SST 39VFXXX driver required" + } + + implements CYGINT_DEVS_FLASH_SST_39VFXXX_REQUIRED +} + +# EOF flash_ea2468.cdl \ No newline at end of file diff --git a/packages/devs/flash/arm/ea2468/v2_0/src/flash_ea2468.c b/packages/devs/flash/arm/ea2468/v2_0/src/flash_ea2468.c new file mode 100755 index 00000000..3fe230aa --- /dev/null +++ b/packages/devs/flash/arm/ea2468/v2_0/src/flash_ea2468.c @@ -0,0 +1,72 @@ +//========================================================================== +// +// flash_ea2468.c +// +// Flash programming for SST Flash device on EA LPC2468 OEM board +// +//========================================================================== +//####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 Andrew Lunn +// +// 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: 2008-07-07 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +//-------------------------------------------------------------------------- +// Device properties +#include + + +// The EA LPC2468 OEM board has one SST 39VF3201 part +#define CYGNUM_FLASH_INTERLEAVE (1) +#define CYGNUM_FLASH_SERIES (1) +#define CYGNUM_FLASH_WIDTH (16) +#define CYGNUM_FLASH_BASE (0x80000000) + +//-------------------------------------------------------------------------- +// Platform specific extras +#define CYGPKG_DEVS_FLASH_SST_39VF3201 + +//-------------------------------------------------------------------------- +// Now include the driver code. +#include "cyg/io/flash_sst_39vfxxx.inl" + + +// ------------------------------------------------------------------------ +// EOF flash_ea2468.c diff --git a/packages/devs/flash/arm/lpc2xxx/v2_0/ChangeLog b/packages/devs/flash/arm/lpc2xxx/v2_0/ChangeLog new file mode 100644 index 00000000..5d0263da --- /dev/null +++ b/packages/devs/flash/arm/lpc2xxx/v2_0/ChangeLog @@ -0,0 +1,35 @@ +2007-07-12 Hans Rosenfeld + + * lpc2xxx: driver for on-chip flash memory + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/flash/arm/lpc2xxx/v2_0/cdl/flash_arm_lpc2xxx.cdl b/packages/devs/flash/arm/lpc2xxx/v2_0/cdl/flash_arm_lpc2xxx.cdl new file mode 100644 index 00000000..7eda995e --- /dev/null +++ b/packages/devs/flash/arm/lpc2xxx/v2_0/cdl/flash_arm_lpc2xxx.cdl @@ -0,0 +1,83 @@ +# ==================================================================== +# +# flash_arm_lpc2xxx.cdl +# +# Philips LPC2XXX flash memory package +# +# ==================================================================== +#####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. +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Hans Rosenfeld +# Contributors: +# Date: 2007-07-12 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_ARM_LPC2XXX { + display "LPC2xxx internal FLASH memory support" + description "Support for the internal FLASH memory of LPC2xxx controllers" + + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + requires CYGPKG_HAL_ARM_LPC2XXX + implements CYGHWR_IO_FLASH_DEVICE + + # These chips use two erase block sizes, the access to flash is + # limited to the last few of the 8k blocks. I don't have a chip + # using only 8k block sizes, so I can't test and therefore won't + # implement support for these devices. + active_if { + CYGHWR_HAL_ARM_LPC2XXX == "LPC2124" || + CYGHWR_HAL_ARM_LPC2XXX == "LPC2129" || + CYGHWR_HAL_ARM_LPC2XXX == "LPC2194" || + CYGHWR_HAL_ARM_LPC2XXX == "LPC2214" || + CYGHWR_HAL_ARM_LPC2XXX == "LPC2292" || + CYGHWR_HAL_ARM_LPC2XXX == "LPC2294" + } + + compile flash_arm_lpc2xxx.c + include_dir . + + cdl_option CYGPKG_DEVS_FLASH_ARM_LPC2XXX_BUFSIZE { + display "copy buffer size" + description " + Size of the buffer reserved at the end of the internal + SRAM area for flash writing (copy) operations. Additional + 32 bytes are reserved for use by the IAP routine." + flavor data + legal_values 512 1024 4096 8192 + default_value 8192 + } +} diff --git a/packages/devs/flash/arm/lpc2xxx/v2_0/include/flash_arm_lpc2xxx.h b/packages/devs/flash/arm/lpc2xxx/v2_0/include/flash_arm_lpc2xxx.h new file mode 100644 index 00000000..2ee0f42a --- /dev/null +++ b/packages/devs/flash/arm/lpc2xxx/v2_0/include/flash_arm_lpc2xxx.h @@ -0,0 +1,81 @@ +#ifndef CYGONCE_FLASH_ARM_LPC2XXX_H +#define CYGONCE_FLASH_ARM_LPC2XXX_H + +//========================================================================== +// +// flash_arm_lpc2xxx.h +// +// Flash programming for LPC2xxx +// +//========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Hans Rosenfeld +// Contributors: +// Date: 2007-07-12 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +struct iap_param { + cyg_uint32 code; + cyg_uint32 p[4]; +}; + +#define IAP_PREPARE 50 +#define IAP_COPY 51 +#define IAP_ERASE 52 +#define IAP_CHECK 53 +#define IAP_PARTID 54 +#define IAP_VERSION 55 +#define IAP_COMPARE 56 + +#define IAP_CMD_SUCCESS 0 +#define IAP_CMD_INVALID 1 +#define IAP_SRC_ADDRERR 2 +#define IAP_DST_ADDRERR 3 +#define IAP_SRC_ADDRMAP 4 +#define IAP_DST_ADDRMAP 5 +#define IAP_CNT_INVALID 6 +#define IAP_SEC_INVALID 7 +#define IAP_SEC_NOTBLNK 8 +#define IAP_SEC_NOTPREP 9 +#define IAP_CMP_INEQUAL 10 +#define IAP_BSY 11 + +#define IAP_LOCATION 0x7ffffff1 + +#endif diff --git a/packages/devs/flash/arm/lpc2xxx/v2_0/src/flash_arm_lpc2xxx.c b/packages/devs/flash/arm/lpc2xxx/v2_0/src/flash_arm_lpc2xxx.c new file mode 100644 index 00000000..d612dc83 --- /dev/null +++ b/packages/devs/flash/arm/lpc2xxx/v2_0/src/flash_arm_lpc2xxx.c @@ -0,0 +1,216 @@ +//========================================================================== +// +// flash_arm_lpc2xxx.c +// +// Flash programming for LPC2xxx +// +//========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Hans Rosenfeld +// Contributors: +// Date: 2007-07-12 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include +#include +#include + +#define _FLASH_PRIVATE_ +#include + +#include "flash_arm_lpc2xxx.h" + +/* gcc builtins */ +extern void* memcpy(void *, const void *, size_t); +extern void* memset(void *, int, size_t); + +/* wrapper for simpler IAP access */ +static void +iap(struct iap_param *param, struct iap_param *result) +{ + static void (* const iap)(struct iap_param *, struct iap_param *) + = (void (*)(struct iap_param *, struct iap_param *)) IAP_LOCATION; + cyg_uint32 cpsr; + + HAL_DISABLE_INTERRUPTS(cpsr); + iap(param, result); + HAL_RESTORE_INTERRUPTS(cpsr); +} + +void +flash_query(void *data) +{ + /* nothing to do here */ +} + +/* + * 248k in 31 blocks by 8k there actually less blocks since two of + * them are 64k, but accessing anything but the last few 8k blocks is + * not supported anyway + */ +int +flash_hwr_init(void) +{ + flash_info.block_size = 8 * 1024; + flash_info.blocks = 31; + flash_info.start = (void *) 0; + flash_info.end = (void *) (248 * 1024); + + return FLASH_ERR_OK; +} + + +static const cyg_uint8 flash_errors[12] = { + FLASH_ERR_OK, /* IAP_CMD_SUCCESS */ + FLASH_ERR_PROTOCOL, /* IAP_INV_COMMAND */ + FLASH_ERR_INVALID, /* IAP_SRC_ADDRERR */ + FLASH_ERR_INVALID, /* IAP_DST_ADDRERR */ + FLASH_ERR_INVALID, /* IAP_SRC_ADDRMAP */ + FLASH_ERR_INVALID, /* IAP_DST_ADDRMAP */ + FLASH_ERR_INVALID, /* IAP_CNT_INVALID */ + FLASH_ERR_INVALID, /* IAP_SEC_INVALID */ + FLASH_ERR_PROTOCOL, /* IAP_SEC_NOTBLNK */ + FLASH_ERR_PROTOCOL, /* IAP_SEC_NOTPREP */ + FLASH_ERR_DRV_VERIFY, /* IAP_CMP_INEQUAL */ + FLASH_ERR_DRV_TIMEOUT, /* IAP_BSY */ +}; + +int +flash_hwr_map_error(e) +{ + if(e > 11) + return FLASH_ERR_PROTOCOL; + return flash_errors[e]; +} + +/* this will not work for flash addresses < 0x30000 */ +static int +block_by_addr(cyg_uint32 addr) +{ + int block; + + block = (addr >> 13) & 0x1f; + block -= 14; + + return block; +} + +int +flash_erase_block(void *block, unsigned int size) +{ + struct iap_param param, result; + + param.code = IAP_PREPARE; + + param.p[0] = param.p[1] = block_by_addr((cyg_uint32) block); + if(param.p[0] < 10) + return FLASH_ERR_INVALID; + + /* prepare sector(s) */ + iap(¶m, &result); + if(result.code != IAP_CMD_SUCCESS) + return result.code; + + param.code = IAP_ERASE; + param.p[2] = CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED / 1000; + + /* erase sector(s) */ + iap(¶m, &result); + return result.code; +} + +int +flash_program_buf(void *addr, void *data, int len) +{ + static const int size = CYGPKG_DEVS_FLASH_ARM_LPC2XXX_BUFSIZE; + static const cyg_uint32 b = (0x40004000 - 32 - + CYGPKG_DEVS_FLASH_ARM_LPC2XXX_BUFSIZE); + static void * const buf = (void *) (0x40004000 - 32 - + CYGPKG_DEVS_FLASH_ARM_LPC2XXX_BUFSIZE); + cyg_uint32 a = (cyg_uint32) addr; + char *d = (char *) data; + struct iap_param param, result; + + param.code = IAP_PREPARE; + param.p[0] = block_by_addr(a); + param.p[1] = block_by_addr(a + len - 1); + if(param.p[0] < 10 || param.p[1] > 16) + return FLASH_ERR_INVALID; + + do { + /* prepare sector(s) */ + iap(¶m, &result); + if(result.code != IAP_CMD_SUCCESS) + return result.code; + + if(len < size) + memset(buf, 0xff, size); + memcpy(buf, d, size); + + param.code = IAP_COPY; + param.p[0] = a; + param.p[1] = b; + param.p[2] = size; + param.p[3] = CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED / 1000; + + /* copy ram to flash */ + iap(¶m, &result); + if(result.code != IAP_CMD_SUCCESS) + return result.code; + + len -= size; + a += size; + d += size; + } while(len > 0); + + return(result.code); +} + +bool +flash_code_overlaps(void *start, void *end) +{ + extern unsigned char _stext[], _etext[]; + + return ((((unsigned long)&_stext >= (unsigned long)start) && + ((unsigned long)&_stext < (unsigned long)end)) || + (((unsigned long)&_etext >= (unsigned long)start) && + ((unsigned long)&_etext < (unsigned long)end))); +} diff --git a/packages/devs/flash/arm/phycore229x/v2_0/ChangeLog b/packages/devs/flash/arm/phycore229x/v2_0/ChangeLog new file mode 100755 index 00000000..1aa4fa64 --- /dev/null +++ b/packages/devs/flash/arm/phycore229x/v2_0/ChangeLog @@ -0,0 +1,41 @@ +2007-11-24 Uwe Kindler + + * src/flash_phycore229x.c: + * cdl/flash_phycore229x.cdl: + Initial release of FLASH driver for Phytec phyCORE-LPC229x board. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2008 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. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/flash/arm/phycore229x/v2_0/cdl/flash_phycore229x.cdl b/packages/devs/flash/arm/phycore229x/v2_0/cdl/flash_phycore229x.cdl new file mode 100755 index 00000000..61ebb862 --- /dev/null +++ b/packages/devs/flash/arm/phycore229x/v2_0/cdl/flash_phycore229x.cdl @@ -0,0 +1,104 @@ +# ==================================================================== +# +# flash_phycore229x.cdl +# +# FLASH memory - Hardware support on Phytec phyCORE LPC229x board +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2008 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. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Uwe Kindler +# Original data: gthomas +# Contributors: gthomas +# Date: 2007-11-21 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_PHYCORE229X { + display "phyCORE-LPC229x board FLASH memory support" + description "FLASH memory device support for Phytec phyCORE-LPC229x board" + + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + requires CYGPKG_HAL_ARM_LPC2XXX + + compile -library=libextras.a flash_phycore229x.c + + # Arguably this should do in the generic package + # but then there is a logic loop so you can never enable it. + cdl_interface CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED { + display "Generic AMD AM29XXXXX driver required" + } + + implements CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED + + cdl_option CYGHWR_DEVS_FLASH_PHYCORE229X_AM29DL800 { + display "AMD AM29DL800 device fitted" + flavor bool + active_if { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29DL800" } + requires CYGHWR_DEVS_FLASH_AMD_AM29DL800 + calculated { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29DL800" ? 1 : 0 } + } + + cdl_option CYGHWR_DEVS_FLASH_PHYCORE229X_AM29LV800 { + display "AMD AM29LV800 device fitted" + flavor bool + active_if { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV800" } + requires CYGHWR_DEVS_FLASH_AMD_AM29LV800 + calculated { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV800" ? 1 : 0 } + } + + cdl_option CYGHWR_DEVS_FLASH_PHYCORE229X_AM29LV160 { + display "AMD AM29LV160 device fitted" + flavor bool + active_if { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV160" } + requires CYGHWR_DEVS_FLASH_AMD_AM29LV160 + calculated { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV160" ? 1 : 0 } + } + + cdl_option CYGHWR_DEVS_FLASH_PHYCORE229X_AM29LV320 { + display "AMD AM29LV320 device fitted" + flavor bool + active_if { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV320" } + requires CYGHWR_DEVS_FLASH_AMD_AM29LV320D + calculated { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV320" ? 1 : 0 } + } +} + +# EOF flash_phycore229x.cdl diff --git a/packages/devs/flash/arm/phycore229x/v2_0/src/flash_phycore229x.c b/packages/devs/flash/arm/phycore229x/v2_0/src/flash_phycore229x.c new file mode 100755 index 00000000..2da552a0 --- /dev/null +++ b/packages/devs/flash/arm/phycore229x/v2_0/src/flash_phycore229x.c @@ -0,0 +1,69 @@ +//========================================================================== +// +// flash_phycore229x.c +// +// Flash programming for AMD device on Phytec phyCORE-LPC229x board +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 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. +// +// 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: jskov, nickg,jlarmour, block +// Date: 2007-11-21 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +// +// There are pairs of +// +#define CYGNUM_FLASH_INTERLEAVE (2) +#define CYGNUM_FLASH_WIDTH (16) +#define CYGNUM_FLASH_SERIES (CYGHWR_HAL_ARM_PHYCORE229X_FLASH_CNT >> 1) +#define CYGNUM_FLASH_BASE (0x80000000u) + +#include "cyg/io/flash_am29xxxxx.inl" + +// ------------------------------------------------------------------------ +// EOF phycore_flash.c diff --git a/packages/devs/flash/fr30/skmb91302/v2_0/ChangeLog b/packages/devs/flash/fr30/skmb91302/v2_0/ChangeLog new file mode 100644 index 00000000..40bfde71 --- /dev/null +++ b/packages/devs/flash/fr30/skmb91302/v2_0/ChangeLog @@ -0,0 +1,44 @@ +2008-07-01 Lars Poeschel + + * src/skmb91302_flash.c: Changed CYGNUM_FLASH_BASE to 0x1000000 + for real flash support + +2007-07-09 Lars Poeschel + + * src/skmb91302_flash.c: + * cdl/flash_skmb91302.cdl: New package - platform specifics. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/flash/fr30/skmb91302/v2_0/cdl/flash_skmb91302.cdl b/packages/devs/flash/fr30/skmb91302/v2_0/cdl/flash_skmb91302.cdl new file mode 100644 index 00000000..176a90f7 --- /dev/null +++ b/packages/devs/flash/fr30/skmb91302/v2_0/cdl/flash_skmb91302.cdl @@ -0,0 +1,74 @@ +# ==================================================================== +# +# flash_skmb91302.cdl +# +# FLASH memory - Hardware support on Fujitsu Starterkit MB91302 +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2002 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): gthomas +# Original data: gthomas +# Contributors: +# Date: 2002-09-03 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_FR30_SKMB91302 { + display "Fujitsu Starterkit MB91302 FLASH memory support" + + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + requires CYGPKG_HAL_FR30_MB91301_SKMB91302 + + implements CYGHWR_IO_FLASH_DEVICE + + compile skmb91302_flash.c + + # Arguably this should do in the generic package + # but then there is a logic loop so you can never enable it. + cdl_interface CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED { + display "Generic AMD flash driver required" + } + + implements CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED + requires CYGHWR_DEVS_FLASH_AMD_AM29DL640D + +} + diff --git a/packages/devs/flash/fr30/skmb91302/v2_0/src/skmb91302_flash.c b/packages/devs/flash/fr30/skmb91302/v2_0/src/skmb91302_flash.c new file mode 100644 index 00000000..f3f8db17 --- /dev/null +++ b/packages/devs/flash/fr30/skmb91302/v2_0/src/skmb91302_flash.c @@ -0,0 +1,73 @@ +//========================================================================== +// +// skmb91302_flash.c +// +// Flash programming support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 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): gthomas +// Contributors: gthomas +// Date: 2000-10-20 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +//-------------------------------------------------------------------------- +// Device properties + +#define CYGNUM_FLASH_INTERLEAVE (1) +#define CYGNUM_FLASH_SERIES (1) +#define CYGNUM_FLASH_WIDTH (16) +#define CYGNUM_FLASH_BASE (0x1000000) + +//-------------------------------------------------------------------------- +// Platform specific extras +#define CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT // This feature fails :-( + +//-------------------------------------------------------------------------- +// Now include the driver code. +#include "cyg/io/flash_am29xxxxx.inl" + +// ------------------------------------------------------------------------ +// EOF skmb91302_flash.c diff --git a/packages/devs/i2c/arm/lpc2xxx/v2_0/ChangeLog b/packages/devs/i2c/arm/lpc2xxx/v2_0/ChangeLog new file mode 100644 index 00000000..68b6b70b --- /dev/null +++ b/packages/devs/i2c/arm/lpc2xxx/v2_0/ChangeLog @@ -0,0 +1,35 @@ +2007-07-12 Hans Rosenfeld + + * lpc2xxx: driver for on-chip I2C unit + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/i2c/arm/lpc2xxx/v2_0/cdl/i2c_lpc2xxx.cdl b/packages/devs/i2c/arm/lpc2xxx/v2_0/cdl/i2c_lpc2xxx.cdl new file mode 100644 index 00000000..ab8b21bf --- /dev/null +++ b/packages/devs/i2c/arm/lpc2xxx/v2_0/cdl/i2c_lpc2xxx.cdl @@ -0,0 +1,59 @@ +# ==================================================================== +# +# i2c_lpc2xxx.cdl +# +# I2C driver for LPC2xxx +# +# ==================================================================== +#####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. +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Hans Rosenfeld +# Contributors: +# Date: 2007-07-12 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_I2C_ARM_LPC2XXX { + display "I2C driver for LPC2xxx family of ARM controllers" + + parent CYGPKG_IO_I2C + active_if CYGPKG_IO_I2C + active_if CYGPKG_HAL_ARM_LPC2XXX + + description "This package provides a driver for the I2C module found in + Philips LPC2xxx controllers." + + compile i2c_lpc2xxx.c +} \ No newline at end of file diff --git a/packages/devs/i2c/arm/lpc2xxx/v2_0/src/i2c_lpc2xxx.c b/packages/devs/i2c/arm/lpc2xxx/v2_0/src/i2c_lpc2xxx.c new file mode 100644 index 00000000..54629d21 --- /dev/null +++ b/packages/devs/i2c/arm/lpc2xxx/v2_0/src/i2c_lpc2xxx.c @@ -0,0 +1,414 @@ +//========================================================================== +// +// i2c_lpc2xxx.c +// +// I2C driver for LPC2xxx +// +//========================================================================== +//####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): Hans Rosenfeld +// Contributors: +// Date: 2007-07-12 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * According to the Users Manual the LPC2xxx I2C module is very + * similar to the I2C module of the Philips 8xC552/556 controllers. I + * guess it is used in other Philips/NXP controllers, too. Using these + * macros should make it easier to split off the common parts of the + * driver once it's necessary. + */ + +#define I2C_XFER 8 +#define I2C_INTR CYGNUM_HAL_INTERRUPT_I2C +#define I2C_FREQ (CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED / \ + CYGNUM_HAL_ARM_LPC2XXX_VPBDIV) +#define I2C_BASE CYGARC_HAL_LPC2XXX_REG_I2_BASE + +#define I2C_CONSET CYGARC_HAL_LPC2XXX_REG_I2CONSET +#define I2C_CONCLR CYGARC_HAL_LPC2XXX_REG_I2CONCLR +#define I2C_CON I2C_CONSET +#define I2C_STAT CYGARC_HAL_LPC2XXX_REG_I2STAT +#define I2C_DAT CYGARC_HAL_LPC2XXX_REG_I2DAT +#define I2C_ADR CYGARC_HAL_LPC2XXX_REG_I2ADR +#define I2C_SCLH CYGARC_HAL_LPC2XXX_REG_I2SCLH +#define I2C_SCLL CYGARC_HAL_LPC2XXX_REG_I2SCLL + +#define I2C_R8(r, x) HAL_READ_UINT8 (I2C_BASE + (r), (x)) +#define I2C_W8(r, x) HAL_WRITE_UINT8 (I2C_BASE + (r), (x)) +#define I2C_R16(r, x) HAL_READ_UINT16 (I2C_BASE + (r), (x)) +#define I2C_W16(r, x) HAL_WRITE_UINT16(I2C_BASE + (r), (x)) + +/* Special case for setting/clearing bits in I2C_CON */ +#define SET_CON(x) I2C_W8(I2C_CONSET, (x)) +#define CLR_CON(x) I2C_W8(I2C_CONCLR, (x)) + +#define CON_EN CYGARC_HAL_LPC2XXX_REG_I2CONSET_I2EN +#define CON_STA CYGARC_HAL_LPC2XXX_REG_I2CONSET_STA +#define CON_STO CYGARC_HAL_LPC2XXX_REG_I2CONSET_STO +#define CON_SI CYGARC_HAL_LPC2XXX_REG_I2CONSET_SI +#define CON_AA CYGARC_HAL_LPC2XXX_REG_I2CONSET_AA + +static cyg_uint8 i2c_addr; +static cyg_uint32 i2c_count = 0; +static const cyg_uint8* i2c_txbuf = NULL; +static cyg_uint8* i2c_rxbuf = NULL; +static cyg_bool i2c_rxnak; + +volatile +static cyg_uint32 i2c_flag = 0; +static cyg_uint32 i2c_delay; + +static cyg_drv_mutex_t i2c_lock; +static cyg_drv_cond_t i2c_wait; +static cyg_handle_t i2c_hand; +static cyg_interrupt i2c_data; + +#define I2C_FLAG_FINISH 1 /* transfer finished */ +#define I2C_FLAG_ACT 2 /* bus still active, no STOP condition sent */ +#define I2C_FLAG_ERROR (1<<31) /* one of the following errors occured: */ +#define I2C_FLAG_ADDR (1<<30) /* - address was not ACKed */ +#define I2C_FLAG_DATA (1<<29) /* - data was not ACKed */ +#define I2C_FLAG_LOST (1<<28) /* - bus arbitration was lost */ +#define I2C_FLAG_BUF (1<<27) /* - no buffer for reading or writing */ +#define I2C_FLAG_UNK (1<<26) /* - unknown I2C status */ + +/* + * set up I2C bus timing + * I2C clock period is in PCLK ticks + */ +static void +i2c_lpc2xxx_delay(cyg_uint32 delay) +{ + cyg_uint32 period; + + if(delay == i2c_delay) + return; + + period = I2C_FREQ / (1000000000 / delay); + period /= 2; + + I2C_W16(I2C_SCLL, period); + I2C_W16(I2C_SCLH, period); + i2c_delay = delay; +} + +/* + * The ISR does the actual work. It is not that much work to justify + * putting it in the DSR, and it is also not clear whether this would + * even work. If an error occurs we try to leave the bus in the same + * state as we would if there was no error. + */ +static cyg_uint32 +i2c_lpc2xxx_isr(cyg_vector_t vec, cyg_addrword_t data) +{ + cyg_uint8 status; + I2C_R8(I2C_STAT, status); + + switch(status) { + case 0x08: /* START sent, send Addr+R/W */ + case 0x10: /* ReSTART sent, send Addr+R/W */ + CLR_CON(CON_STA); + I2C_W8(I2C_DAT, i2c_addr); + break; + + case 0x18: /* Addr ACKed, send data */ + case 0x28: /* Data ACKed, send more */ + if(i2c_count == 0) { + i2c_flag = I2C_FLAG_FINISH; + cyg_drv_interrupt_mask_intunsafe(vec); + cyg_drv_interrupt_acknowledge(vec); + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } + + if(i2c_txbuf == NULL) { + i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_BUF; + cyg_drv_interrupt_mask_intunsafe(vec); + cyg_drv_interrupt_acknowledge(vec); + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } + + I2C_W8(I2C_DAT, *i2c_txbuf); + i2c_txbuf++; + i2c_count--; + break; + + case 0x50: /* Data ACKed, receive more */ + case 0x58: /* Data not ACKed, end reception */ + if(i2c_rxbuf == NULL) { + i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_BUF; + cyg_drv_interrupt_mask_intunsafe(vec); + cyg_drv_interrupt_acknowledge(vec); + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } + + I2C_R8(I2C_DAT, *i2c_rxbuf); + i2c_rxbuf++; + i2c_count--; + case 0x40: /* Addr ACKed, receive data */ + if(status == 0x58 || i2c_count == 0) { + i2c_flag = I2C_FLAG_FINISH; + cyg_drv_interrupt_mask_intunsafe(vec); + cyg_drv_interrupt_acknowledge(vec); + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } + + if(i2c_count == 1 && i2c_rxnak) + CLR_CON(CON_AA); + else + SET_CON(CON_AA); + break; + + case 0x20: /* Addr not ACKed */ + case 0x48: + i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_ADDR; + cyg_drv_interrupt_mask_intunsafe(vec); + cyg_drv_interrupt_acknowledge(vec); + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + break; + case 0x30: /* Data not ACKed */ + i2c_count++; + i2c_txbuf--; + i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_DATA; + cyg_drv_interrupt_mask_intunsafe(vec); + cyg_drv_interrupt_acknowledge(vec); + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + break; + case 0x38: /* Arbitration lost */ + i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_LOST; + break; + default: /* lots of unused states... */ + i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_UNK; + break; + } + + CLR_CON(CON_SI); + cyg_drv_interrupt_acknowledge(vec); + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; +} + +static void +i2c_lpc2xxx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) +{ + if(i2c_flag) + cyg_drv_cond_signal(&i2c_wait); +} + +/* + * Initialize driver & hardware state + */ +static void +i2c_lpc2xxx_init(struct cyg_i2c_bus *bus) +{ + cyg_uint32 addr, tmp; + + /* enable I2C pins */ + addr = CYGARC_HAL_LPC2XXX_REG_PIN_BASE + CYGARC_HAL_LPC2XXX_REG_PINSEL0; + HAL_READ_UINT32(addr, tmp); + tmp |= 0x50; + HAL_WRITE_UINT32(addr, tmp); + + cyg_drv_mutex_init(&i2c_lock); + cyg_drv_cond_init(&i2c_wait, &i2c_lock); + cyg_drv_interrupt_create(I2C_INTR, 0, (cyg_addrword_t) 0, &i2c_lpc2xxx_isr, + &i2c_lpc2xxx_dsr, &i2c_hand, &i2c_data); + cyg_drv_interrupt_attach(i2c_hand); + + CLR_CON(CON_EN | CON_STA | CON_SI | CON_AA); + I2C_W8(I2C_ADR, 0); + SET_CON(CON_EN); +} + +/* + * transmit a buffer to a device + */ +static cyg_uint32 +i2c_lpc2xxx_tx(const cyg_i2c_device *dev, + cyg_bool send_start, + const cyg_uint8 *tx_data, + cyg_uint32 count, + cyg_bool send_stop) +{ + i2c_lpc2xxx_delay(dev->i2c_delay); + + i2c_addr = dev->i2c_address << 1; + i2c_count = count; + i2c_txbuf = tx_data; + + /* + * for a repeated start the SI bit has to be reset + * if we continue a previous transfer, load the next byte + */ + if(send_start && i2c_flag == I2C_FLAG_ACT) { + SET_CON(CON_STA); + CLR_CON(CON_SI); + } else if(send_start) { + SET_CON(CON_STA); + } else { + I2C_W8(I2C_DAT, *i2c_txbuf); + i2c_txbuf++; + i2c_count--; + CLR_CON(CON_SI); + } + + i2c_flag = 0; + + /* + * the isr will do most of the work, and the dsr will signal when an + * error occured or the transfer finished + */ + cyg_drv_mutex_lock(&i2c_lock); + cyg_drv_dsr_lock(); + cyg_drv_interrupt_unmask(I2C_INTR); + while(!(i2c_flag & (I2C_FLAG_FINISH|I2C_FLAG_ERROR))) + cyg_drv_cond_wait(&i2c_wait); + cyg_drv_interrupt_mask(I2C_INTR); + cyg_drv_dsr_unlock(); + cyg_drv_mutex_unlock(&i2c_lock); + + /* too bad we have no way to tell the caller */ + if(i2c_flag & I2C_FLAG_ERROR) + diag_printf("I2C TX error flag: %x\n", i2c_flag); + + if(send_stop) { + SET_CON(CON_STO); + CLR_CON(CON_SI | CON_STA); + } else i2c_flag = I2C_FLAG_ACT; + + count -= i2c_count; + + i2c_addr = 0; + i2c_count = 0; + i2c_txbuf = NULL; + + return count; +} + +/* + * receive into a buffer from a device + */ +static cyg_uint32 +i2c_lpc2xxx_rx(const cyg_i2c_device *dev, + cyg_bool send_start, + cyg_uint8 *rx_data, + cyg_uint32 count, + cyg_bool send_nak, + cyg_bool send_stop) +{ + i2c_lpc2xxx_delay(dev->i2c_delay); + + i2c_addr = dev->i2c_address << 1 | 1; + i2c_count = count; + i2c_rxbuf = rx_data; + i2c_rxnak = send_nak; + + /* + * for a repeated start the SI bit has to be reset + * if we continue a previous transfer, start reception + */ + if(send_start && i2c_flag == I2C_FLAG_ACT) { + SET_CON(CON_STA); + CLR_CON(CON_SI); + } else if(send_start) + SET_CON(CON_STA); + + i2c_flag = 0; + + /* + * the isr will do most of the work, and the dsr will signal when an + * error occured or the transfer finished + */ + cyg_drv_mutex_lock(&i2c_lock); + cyg_drv_dsr_lock(); + cyg_drv_interrupt_unmask(I2C_INTR); + while(!(i2c_flag & (I2C_FLAG_FINISH|I2C_FLAG_ERROR))) + cyg_drv_cond_wait(&i2c_wait); + cyg_drv_interrupt_mask(I2C_INTR); + cyg_drv_dsr_unlock(); + cyg_drv_mutex_unlock(&i2c_lock); + + /* too bad we have no way to tell the caller */ + if(i2c_flag & I2C_FLAG_ERROR) + diag_printf("I2C RX error flag: %x\n", i2c_flag); + + if(send_stop) { + SET_CON(CON_STO); + CLR_CON(CON_SI | CON_STA); + } else i2c_flag = I2C_FLAG_ACT; + + count -= i2c_count; + + i2c_addr = 0; + i2c_count = 0; + i2c_rxbuf = NULL; + + return count; + +} + + +/* + * generate a STOP + */ +static void +i2c_lpc2xxx_stop(const cyg_i2c_device *dev) +{ + SET_CON(CON_STO); +} + +CYG_I2C_BUS(cyg_i2c_lpc2xxx_bus, + &i2c_lpc2xxx_init, + &i2c_lpc2xxx_tx, + &i2c_lpc2xxx_rx, + &i2c_lpc2xxx_stop, + (void *) 0); diff --git a/packages/devs/i2c/m68k/mcf52xx/v2_0/ChangeLog b/packages/devs/i2c/m68k/mcf52xx/v2_0/ChangeLog new file mode 100644 index 00000000..415b7bc0 --- /dev/null +++ b/packages/devs/i2c/m68k/mcf52xx/v2_0/ChangeLog @@ -0,0 +1,41 @@ +2006-02-28 Bart Veer + + * doc/mcf52xx_i2c.sgml, include/i2c_mcf52xx.h: new files + + * src/i2c_mcf52xx.c, cdl/i2c_mcf52xx.cdl: various clean-ups + +2005-10-23 Uwe Kindler + + * mcf52xx I2C driver package created + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005, 2006 eCosCentric Ltd. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/i2c/m68k/mcf52xx/v2_0/cdl/i2c_mcf52xx.cdl b/packages/devs/i2c/m68k/mcf52xx/v2_0/cdl/i2c_mcf52xx.cdl new file mode 100644 index 00000000..3421520a --- /dev/null +++ b/packages/devs/i2c/m68k/mcf52xx/v2_0/cdl/i2c_mcf52xx.cdl @@ -0,0 +1,105 @@ +# ==================================================================== +# +# i2c_mcf52xx.cdl +# +# eCos MCF52xx I2C configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2005, 2006 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. +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Uwe Kindler +# Contributors: Bart Veer +# Date: 2005-10-23 +# +#####DESCRIPTIONEND#### +# ==================================================================== + + +cdl_package CYGPKG_DEVS_I2C_MCF52xx { + display "I2C driver for coldfire MCF52xx family" + + parent CYGPKG_IO_I2C + active_if CYGPKG_IO_I2C + active_if CYGPKG_HAL_M68K_MCF52xx + + description " + This package provides a generic I2C device driver for the on-chip + I2C modules in MCF52xx ColdFire processors." + + include_dir cyg/io + compile i2c_mcf52xx.c + + cdl_option CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES { + display "Target hardware may have multiple MCF52xx I2C buses" + flavor bool + default_value 0 + description " + The MCF52xx I2C driver can support multiple I2C bus devices, but + typically the coldfire processor only provides a single device. By + default the driver assumes only a single device is present and will + optimize for that case, using constant definitions provided by the + platform HAL rather than per-device structure fields. If the hardware + has multiple I2C bus devices, or if a singleton bus is instantiated + by some other package and hence the platform HAL cannot provide the + necessary definitions, then this option should be enabled." + } + + cdl_component CYGPKG_DEVS_I2C_MCF52xx_OPTIONS { + display "I2C driver build options" + flavor none + active_if { CYGINT_DEVS_I2C_MCF52xx_BUS_DEVICES > 0 } + description " + Package specific build options including control over + compiler flags used only in building the MCF52xx I2C + bus driver." + + cdl_option CYGPKG_DEVS_I2C_MCF52xx_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the MCF52xx I2C bus driver. These flags are + used in addition to the set of global flags." + } + + cdl_option CYGPKG_DEVS_I2C_MCF52xx_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the MCF52xx I2C bus driver. These flags are + removed from the set of global flags if present." + } + } +} diff --git a/packages/devs/i2c/m68k/mcf52xx/v2_0/doc/mcf52xx_i2c.sgml b/packages/devs/i2c/m68k/mcf52xx/v2_0/doc/mcf52xx_i2c.sgml new file mode 100644 index 00000000..a0ae383e --- /dev/null +++ b/packages/devs/i2c/m68k/mcf52xx/v2_0/doc/mcf52xx_i2c.sgml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Motorola MCF52xx ColdFire I<superscript>2</superscript>C Bus Driver + + + + Motorola MCF52xx Coldfire I2C Bus Driver + + + CYGPKG_DEVS_I2C_MCF52xx + eCos Support for the Motorola Coldfire I2C Bus + + + Description + +Several processors in the Motorola ColdFire family come with one or +more on-chip I2C bus devices. This package +provides an eCos I2C bus driver. It was +originally developed on an MCF5280 but should work with any ColdFire +processor that uses a compatible bus device. The driver implements the +functionality defined by the generic I2C +package CYGPKG_IO_I2C. + + +The hardware does not support DMA or fifos, so usually a transfer will +involve an interrupt for every byte transferred. Since the +I2C bus typically runs at 100KHz large +transfers will consume much of the available cpu time. + + +This package does not provide any cyg_i2c_bus +structures. The number of I2C buses varies +between ColdFire processors. If multiple buses are available then +exactly which one(s) are in use on a given hardware platform depends +entirely on that platform. The desired I2C +bus speed also depends on the platform, and there may be other issues +such as how the processor pins should be set up. Hence it is left to +other code, usually the platform HAL, to instantiate the bus +structure(s). This driver package supplies the necessary functions and +utility macros. Similarly this package does not provide any +cyg_i2c_device structures. Which +I2C devices are hooked up to which +I2C bus is entirely a characteristic of the +hardware platform, so again it is up to the platform HAL to +instantiate the necessary structures. + + +The driver will operate in interrupt-driven mode if interrupts are +enabled when a transfer is initiated. Otherwise it will operate in +polled mode. This allows the driver to be used in a variety of +configurations including inside RedBoot. + + + + Configuration Options + +The I2C bus driver package should be loaded +automatically when selecting a target containing a suitable ColdFire +processor, and it should never be necessary to load the package +explicitly. If the application does not use any of the +I2C functionality, directly or indirectly, +then all the I2C code should be removed at +link-time and the application does not suffer any overheads. + + +By default the driver assumes a single I2C +bus and optimizes for that case. For example options like the ISR +vector and priority are handled by compile-time +#define's in the platform HAL's exported header +files rather than by per-bus structure fields. This helps to reduce +both code and data overheads. If the driver should support multiple +I2C buses then +CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES should be +enabled. Typically this will be done by the platform HAL using a CDL +requires property. If bus instantiation happens +outside the platform HAL and hence the HAL's header files do not +provide the appropriate definitions, then this configuration option +should also be defined. + + +The only other configuration options in this package provide control +over the compiler flags used to build the driver code. + + + + Defining the Bus and Devices + +For most hardware targets the platform HAL will instantiate the +cyg_i2c_bus and +cyg_i2c_device structures, and it will also +initialize the hardware so that the +I2C-related pins are connected +appropriately. Some development boards have no +I2C devices, but the +I2C bus signals are accessible via an +expansion connector and I2C devices can be +put on a daughter board. In such cases it may be necessary for the +application to instantiate both the bus and all the device structures. +Alternatively the platform HAL may provide a configuration option to +enable just the bus, with the devices still left to application code. + + +To facilitate bus instantiation the header file cyg/io/i2c_mcf52xx.h provides a utility +macro CYG_MCF52xx_I2C_BUS. This takes six +parameters: + + + +The name of the bus, for example +hal_dnp5280_i2c_bus. This name will be used when +instantiating the I2C devices. + + +An initialization function. If no platform-specific initialization is +needed then this can be the cyg_mcf52xx_i2c_init +function exported by this driver. Otherwise it can be a +platform-specific function which, for example, sets up the relevant +pins appropriately and then chains into +cyg_mcf52xx_i2c_init. + + +The base address of the I2C bus. For +example on an MCF5282 with the IPSBAR set to its usual value of +0x40000000, the I2C bus is at location +0x40000300. + + +The interrupt vector, for example +CYGNUM_HAL_ISR_I2C_IIF on an MCF5282. + + +The interrupt priority. Typically this will be a configurable option +within the platform HAL. + + +A value for the I2C bus's I2FDR register. +That register controls the bus speed. Typical bus speeds are 100KHz +and 400KHz, depending on the capabilities of the attached devices. +There is no simple relationship between the system clock speed, the +desired bus speed, and the FDR register. Although the driver could +determine the FDR setting using a lookup table and appropriate code, +it is better to determine the correct value once during the porting +process and avoid unnecessary run-time overheads. + + + +For the common case where only a single I2C +bus should be supported +(CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES is +disabled), the last four parameters should be provided by preprocessor +#define's, typically in cyg/hal/plf_io.h which gets +#include'd automatically via +cyg/hal/hal_io.h. This header can also define the +HAL_I2C_EXPORTED_DEVICES macro as per the generic +I2C package: + + +#include <pkgconf/hal_m68k_dnp5280.h> +… +#ifdef CYGHWR_HAL_M68K_DNP5280_I2C +#define HAL_MCF52xx_I2C_SINGLETON_BASE (HAL_MCF52xx_MBAR+HAL_MCF5282_I2C0_BASE) +#define HAL_MCF52xx_I2C_SINGLETON_ISRVEC CYGNUM_HAL_ISR_I2C_IIF +#define HAL_MCF52xx_I2C_SINGLETON_ISRPRI CYGNUM_HAL_M68K_DNP5280_I2C_ISRPRI +#define HAL_MCF52xx_I2C_SINGLETON_FDR CYGNUM_HAL_M68K_DNP5280_I2C_FDR + +#define HAL_I2C_EXPORTED_DEVICES \ + extern cyg_i2c_bus hal_dnp5280_i2c_bus; +#endif + + +On this particular platform the I2C bus is +only accessible on an expansion connector so the support is +conditional on a configuration option +CYGHWR_HAL_M68K_DNP5280_I2C. The interrupt priority +and I2FDR values are also controlled by configuration options. On +other platforms the I2C support may not be +conditional and the priority and/or FDR values may be hard-wired. + + +The I2C bus instantiation should happen in +an ordinary C or C++ file, typically in the platform HAL. The +corresponding object file should go into +libtarget.a and the file should only contain +I2C-related code to get the maximum benefit +of linker garbage collection. + + +#include <cyg/infra/cyg_type.h> +#include <cyg/hal/hal_io.h> +#include <cyg/io/i2c.h> +#include <cyg/io/i2c_mcf52xx.h> + +static void +dnp5280_i2c_init(struct cyg_i2c_bus* bus) +{ + cyg_uint16 paspar; + // Reset GPIO pins PAS0/1 to their alternative SCL/SDA settings + HAL_READ_UINT16(HAL_MCF5282_IPSBAR + HAL_MCF5282_GPIO_PASPAR, paspar); + paspar &= ~(HAL_MCF5282_GPIO_PASPAR_A0_MASK | HAL_MCF5282_GPIO_PASPAR_A1_MASK); + paspar |= (HAL_MCF5282_GPIO_PASPAR_A0_SCL | HAL_MCF5282_GPIO_PASPAR_A1_SDA); + HAL_WRITE_UINT16(HAL_MCF5282_IPSBAR + HAL_MCF5282_GPIO_PASPAR, paspar); + + // And leave the driver to take care of the rest. + cyg_mcf52xx_i2c_init(bus); +} + +CYG_MCF52xx_I2C_BUS(hal_dnp5280_i2c_bus, + &dnp5280_i2c_init, + HAL_MCF52xx_I2C_SINGLETON_BASE, + HAL_MCF52xx_I2C_SINGLETON_ISRVEC, + HAL_MCF52xx_I2C_SINGLETON_ISRPRI, + HAL_MCF52xx_I2C_SINGLETON_FDR); + + + +Obviously if CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES +is enabled then the singleton macros may not be defined and the +appropriate numbers should be used directly. This example uses a +custom initialization function which sets up the relevant pins and +then chains into the I2C drivers' +cyg_mcf52xx_i2c_init function. If the platform +HAL has already set up the pins correctly then +cyg_mcf52xx_i2c_init could be used directly in +the bus instantiation, saving a small amount of code for the custom +initialization function. + + +I2C device structures can be instantiated +in the usual way, for example: + + +CYG_I2C_DEVICE(cyg_i2c_wallclock_ds1307, + &hal_dnp5280_i2c_bus, + 0x68, + 0x00, + CYG_I2C_DEFAULT_DELAY); + + + + + diff --git a/packages/devs/i2c/m68k/mcf52xx/v2_0/include/i2c_mcf52xx.h b/packages/devs/i2c/m68k/mcf52xx/v2_0/include/i2c_mcf52xx.h new file mode 100644 index 00000000..219721c4 --- /dev/null +++ b/packages/devs/i2c/m68k/mcf52xx/v2_0/include/i2c_mcf52xx.h @@ -0,0 +1,117 @@ +//========================================================================== +// +// devs/i2c/m68k/mcf52xx/current/src/i2c_mcf52xx.h +// +// I2C driver for Motorola coldfire processors +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005, 2006 eCosCentric Ltd. +// +// 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): Bart Veer +// Contributors: +// Date: 2005-11-20 +// Description: I2C driver for motorola coldfire processor +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include +#include + +typedef enum cyg_mcf52xx_i2c_xfer_mode { + CYG_MCF52xx_I2C_XFER_MODE_INVALID = 0x00, + CYG_MCF52xx_I2C_XFER_MODE_TX = 0x01, + CYG_MCF52xx_I2C_XFER_MODE_RX = 0x02, + CYG_MCF52xx_I2C_XFER_MODE_STARTRX = 0x03 +} cyg_mcf52xx_i2c_xfer_mode; + +typedef struct cyg_mcf52xx_i2c_extra { +#ifdef CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES + // Put statically initialized fields first. + cyg_uint8* i2c_base; // Per-bus h/w details + cyg_vector_t i2c_isrvec; + int i2c_isrpri; + int i2c_fdr; +#endif + + cyg_uint8 i2c_owner; // We have bus ownership + cyg_uint8 i2c_lost_arb; // Error condition leading to loss of bus ownership + cyg_uint8 i2c_send_nack; // As per rx send_nack argument + cyg_uint8 i2c_got_nack; // The last tx resulted in a nack + cyg_uint8 i2c_completed; // Set by DSR, checked by thread + + union { + const cyg_uint8* i2c_tx_data; + cyg_uint8* i2c_rx_data; + } i2c_data; // The current buffer for rx or tx + cyg_uint32 i2c_count; // Number of bytes left in buffer + cyg_mcf52xx_i2c_xfer_mode i2c_mode; // TX, RX, ... + + + cyg_drv_mutex_t i2c_lock; // For synchronizing between DSR and foreground + cyg_drv_cond_t i2c_wait; + cyg_handle_t i2c_interrupt_handle; // For initializing the interrupt + cyg_interrupt i2c_interrupt_data; +} cyg_mcf52xx_i2c_extra; + +externC void cyg_mcf52xx_i2c_init(struct cyg_i2c_bus*); +externC cyg_uint32 cyg_mcf52xx_i2c_tx(const cyg_i2c_device*, cyg_bool, const cyg_uint8*, cyg_uint32, cyg_bool); +externC cyg_uint32 cyg_mcf52xx_i2c_rx(const cyg_i2c_device*, cyg_bool, cyg_uint8*, cyg_uint32, cyg_bool, cyg_bool); +externC void cyg_mcf52xx_i2c_stop(const cyg_i2c_device*); + +#ifdef CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES +# define CYG_MCF52xx_I2C_BUS(_name_, _init_fn_, _base_, _isr_vec_, _isr_pri_, _fdr_) \ + static cyg_mcf52xx_i2c_extra _name_ ## _extra = { \ + _base_, \ + _isr_vec_, \ + _isr_pri_, \ + _fdr_ \ + } ; \ + CYG_I2C_BUS(_name_, \ + _init_fn_, \ + &cyg_mcf52xx_i2c_tx, \ + &cyg_mcf52xx_i2c_rx, \ + &cyg_mcf52xx_i2c_stop, \ + (void*) & ( _name_ ## _extra)) ; + +#else +# define CYG_MCF52xx_I2C_BUS(_name_, _init_fn_, _base_, _isr_vec_, _isr_pri_, _fdr_) \ + static cyg_mcf52xx_i2c_extra _name_ ## _extra; \ + CYG_I2C_BUS(_name_, \ + _init_fn_, \ + cyg_mcf52xx_i2c_tx, \ + cyg_mcf52xx_i2c_rx, \ + cyg_mcf52xx_i2c_stop, \ + (void*) & ( _name_ ## _extra)) ; +#endif + diff --git a/packages/devs/i2c/m68k/mcf52xx/v2_0/src/i2c_mcf52xx.c b/packages/devs/i2c/m68k/mcf52xx/v2_0/src/i2c_mcf52xx.c new file mode 100644 index 00000000..235abdb6 --- /dev/null +++ b/packages/devs/i2c/m68k/mcf52xx/v2_0/src/i2c_mcf52xx.c @@ -0,0 +1,451 @@ +//========================================================================== +// +// devs/i2c/m68k/mcf52xx/current/src/i2c_mcf52xx.c +// +// I2C driver for Motorola coldfire processors +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005, 2006 eCosCentric Ltd. +// +// 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, Bart Veer +// Contributors: +// Date: 2005-10-23 +// Description: I2C driver for motorola coldfire processor +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Optimize for the case of a single bus device, while still allowing +// multiple devices. +#ifndef CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES +# define I2C_BASE(_extra_) (cyg_uint8*)HAL_MCF52xx_I2C_SINGLETON_BASE +# define I2C_ISRVEC(_extra_) HAL_MCF52xx_I2C_SINGLETON_ISRVEC +# define I2C_ISRPRI(_extra_) HAL_MCF52xx_I2C_SINGLETON_ISRPRI +# define I2C_FDR(_extra_) HAL_MCF52xx_I2C_SINGLETON_FDR +#else +# define I2C_BASE(_extra_) ((_extra_)->i2c_base) +# define I2C_ISRVEC(_extra_) ((_extra_)->i2c_isrvec) +# define I2C_ISRPRI(_extra_) ((_extra_)->i2c_isrpri) +# define I2C_FDR(_extra_) ((_extra_)->i2c_fdr) +#endif + +// If building for a singleton but the macros are no defined, assume +// the I2C support is conditional on a disabled platform HAL +// configuration option. This handles the common case of an I2C bus +// accessed only via an expansion connector. +#if defined(CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES) || defined(HAL_MCF52xx_I2C_SINGLETON_BASE) + +// ---------------------------------------------------------------------------- +// Interrupt handling and polling +// +// The MCF52xx I2C bus device does not have a fifo or any kind of DMA +// capability, so can generate interrupts at a very high rate: ~10K +// interrupts per second if the bus is running at the standard 100KHz, +// or 50K for a high-speed 400KHz bus. To keep the cpu load down to +// something vaguely reasonable as much work as possible has to be +// done in the ISR, with the DSR used only for completion. +static cyg_uint32 +mcf52xx_i2c_isr(cyg_vector_t vec, cyg_addrword_t data) +{ + cyg_mcf52xx_i2c_extra* extra = (cyg_mcf52xx_i2c_extra*)data; + cyg_uint8 sr, dr; + cyg_uint8* base = I2C_BASE(extra); + cyg_uint32 result = CYG_ISR_HANDLED; + + // Read the current status, then clear the interrupt and + // arbitration-lost flags. No later code will look at the + // SR register again. + HAL_READ_UINT8( base + HAL_MCF52xx_I2C_SR_OFF, sr); + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_SR_OFF, 0x00); + + // What to do next depends on the current transfer mode. + if (CYG_MCF52xx_I2C_XFER_MODE_TX == extra->i2c_mode) { + // We are in a transmit, or sending the address byte just + // before a transmit. + if (sr & HAL_MCF52xx_I2C_SR_IAL) { + // Lost the bus, abort the transfer. count has already been + // decremented. Assume the byte did not actually arrive. + extra->i2c_count += 1; + result = CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } else if (sr & HAL_MCF52xx_I2C_SR_RXAK) { + // This byte has been sent but the device cannot accept + // any more. The nack must be remembered. Otherwise if + // we got a nack for the last byte in a tx then the + // calling code will think the entire tx succeeded, + // and there will be problems if the next call is + // another tx without a repeated start. + extra->i2c_got_nack = 1; + result = CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } else if (0 == extra->i2c_count) { + // No more bytes to send. + result = CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } else { + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_DR_OFF, *(extra->i2c_data.i2c_tx_data)); + extra->i2c_data.i2c_tx_data += 1; + extra->i2c_count -= 1; + } + } else if (CYG_MCF52xx_I2C_XFER_MODE_RX == extra->i2c_mode) { + if (sr & HAL_MCF52xx_I2C_SR_IAL) { + // Lost the bus? Maybe a spurious stop + result = CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } else { + if (extra->i2c_send_nack && (2 == extra->i2c_count)) { + // Received one, one more to go, and that one should be nacked. + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, + HAL_MCF52xx_I2C_CR_IEN | + HAL_MCF52xx_I2C_CR_IIEN | + HAL_MCF52xx_I2C_CR_MSTA | + HAL_MCF52xx_I2C_CR_TXAK); + } else if (1 == extra->i2c_count) { + // Received the last byte. The docs say to send a stop, + // but there may be another transaction_rx() call. We + // cannot just read DR again, that would trigger another + // read. So instead switch to transmit mode for now, + // which should cause the h/w to wait until a byte is + // written to DR. + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, + HAL_MCF52xx_I2C_CR_IEN | + HAL_MCF52xx_I2C_CR_IIEN | + HAL_MCF52xx_I2C_CR_MSTA | + HAL_MCF52xx_I2C_CR_MTX); + result = CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } + + HAL_READ_UINT8(base + HAL_MCF52xx_I2C_DR_OFF, dr); + *(extra->i2c_data.i2c_rx_data) = dr; + extra->i2c_data.i2c_rx_data += 1; + extra->i2c_count -= 1; + } + } else if (CYG_MCF52xx_I2C_XFER_MODE_STARTRX == extra->i2c_mode) { + // Start followed by RX. The address byte has been sent, we + // need to switch to receiving. + if (sr & HAL_MCF52xx_I2C_SR_IAL) { + // Looks like no device acknowledged the address. + result = CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; + } else { + extra->i2c_mode = CYG_MCF52xx_I2C_XFER_MODE_RX; + if (extra->i2c_send_nack && (1 == extra->i2c_count)) { + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, + HAL_MCF52xx_I2C_CR_IEN | + HAL_MCF52xx_I2C_CR_IIEN | + HAL_MCF52xx_I2C_CR_MSTA | + HAL_MCF52xx_I2C_CR_TXAK); + } else { + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, + HAL_MCF52xx_I2C_CR_IEN | + HAL_MCF52xx_I2C_CR_IIEN | + HAL_MCF52xx_I2C_CR_MSTA); + } + // This dummy read causes the next rx to start + HAL_READ_UINT8(base + HAL_MCF52xx_I2C_DR_OFF, dr); + } + } else { + // Invalid state? Some kind of spurious interrupt? Just ignore + // it. + CYG_FAIL("I2C spurious interrupt"); + } + + // NOTE: this will acknowledge the interrupt even in polled mode. + // Probably harmless. Using I2C_ISRVEC rather than the vec arg + // means a constant number for the singleton case, which may + // allow the HAL to optimize the acknowledge away completely. + HAL_INTERRUPT_ACKNOWLEDGE(I2C_ISRVEC(extra)); + return result; +} + +static void +mcf52xx_i2c_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) +{ + cyg_mcf52xx_i2c_extra* extra = (cyg_mcf52xx_i2c_extra*)data; + extra->i2c_completed = 1; + cyg_drv_cond_signal(&(extra->i2c_wait)); +} + +// A transfer has been started. Wait for completion, allowing for both +// polled and interrupt-driven mode. +static inline void +mcf52xx_i2c_doit(cyg_mcf52xx_i2c_extra* extra) +{ + cyg_uint8* base = I2C_BASE(extra); + int ints_state; + int sr; + + HAL_QUERY_INTERRUPTS(ints_state); + if (((ints_state >> 8) & 0x07) > CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL) { + // Interrupts are currently disabled. We'll have to poll. + for ( ; ; ) { + HAL_READ_UINT8(base + HAL_MCF52xx_I2C_SR_OFF, sr); + if (sr & HAL_MCF52xx_I2C_SR_IIF) { + if (CYG_ISR_CALL_DSR & mcf52xx_i2c_isr(I2C_ISRVEC(extra), (cyg_addrword_t)extra)) { + break; + } + } + } + } else { + cyg_drv_mutex_lock(&(extra->i2c_lock)); + cyg_drv_dsr_lock(); + while (! extra->i2c_completed) { + cyg_drv_cond_wait(&(extra->i2c_wait)); + } + cyg_drv_dsr_unlock(); + cyg_drv_mutex_unlock(&(extra->i2c_lock)); + } +} + +static cyg_bool +mcf52xx_i2c_send_start(cyg_mcf52xx_i2c_extra* extra, int address) +{ + cyg_uint8* base = I2C_BASE(extra); + cyg_uint8 sr; + + // This may be a repeated start or the beginning of a transaction. + // If the former then we still own the bus. + if (!extra->i2c_owner) { + // The bus is currently in slave mode. See if another master + // currently owns the bus and if so fail immediately. It is up + // to higher level code to decide when to retry. Alternatively + // if the bus has somehow got stuck in busy mode it is again + // up to higher level code to sort things out. + HAL_READ_UINT8(I2C_BASE(extra) + HAL_MCF52xx_I2C_SR_OFF, sr); + if (sr & HAL_MCF52xx_I2C_SR_IBB) { + return 0; + } + + // Now we can put the bus into master mode + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, + HAL_MCF52xx_I2C_CR_IEN | + HAL_MCF52xx_I2C_CR_IIEN | + HAL_MCF52xx_I2C_CR_MSTA | // This implicitly generates the start + HAL_MCF52xx_I2C_CR_MTX); // The address byte needs to be transmitted. + extra->i2c_owner = 1; + } else { + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, + HAL_MCF52xx_I2C_CR_IEN | + HAL_MCF52xx_I2C_CR_IIEN | + HAL_MCF52xx_I2C_CR_MSTA | // Already set so no start generated by this + HAL_MCF52xx_I2C_CR_MTX | + HAL_MCF52xx_I2C_CR_RSTA); // Repeated start + } + + // Any previous nack is no longer relevant. If the device cannot accept + // more data it will nack the address. + extra->i2c_got_nack = 0; + // Now send the address. The rest of the transfer is handled by the + // interrupt/polling code. + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_DR_OFF, address); + return 1; +} + +static inline void +mcf52xx_i2c_stopit(cyg_mcf52xx_i2c_extra* extra) +{ + // If we still own the bus this releases it (by clearing MSTA) and + // generating a stop. If we have lost arbitration then this write + // has no effect (other than disabling interrupts). Either way the + // bus should end up in a consistent state. + HAL_WRITE_UINT8(I2C_BASE(extra) + HAL_MCF52xx_I2C_CR_OFF, HAL_MCF52xx_I2C_CR_IEN); + extra->i2c_lost_arb = 0; + extra->i2c_owner = 0; + extra->i2c_mode = CYG_MCF52xx_I2C_XFER_MODE_INVALID; +} + +// ---------------------------------------------------------------------------- +// The functions needed for all I2C devices. + +void +cyg_mcf52xx_i2c_init(struct cyg_i2c_bus* bus) +{ + cyg_mcf52xx_i2c_extra* extra = (cyg_mcf52xx_i2c_extra*)bus->i2c_extra; + cyg_uint8 reg; + cyg_uint8* base = I2C_BASE(extra); + + cyg_drv_mutex_init(&extra->i2c_lock); + cyg_drv_cond_init(&extra->i2c_wait, &extra->i2c_lock); + cyg_drv_interrupt_create(I2C_ISRVEC(extra), + I2C_ISRPRI(extra), + (cyg_addrword_t) extra, + &mcf52xx_i2c_isr, + &mcf52xx_i2c_dsr, + &(extra->i2c_interrupt_handle), + &(extra->i2c_interrupt_data)); + cyg_drv_interrupt_attach(extra->i2c_interrupt_handle); + + // Before unmasking the interrupt sort out the hardware. + // + // The bus frequency is set by the platform HAL or user, since + // it depends on what mixture of devices are present on the bus. + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_FDR_OFF, I2C_FDR(extra)); + // The device will operate in slave mode when idle. If there is + // another bus master then the coldfire might accidentally accept + // requests intended for another device. Address 0 is installed + // as the slave address. This is the General Call address, used + // for broadcasting. It might be better to use another address + // like an Hs-mode one, but conflicts are still possible. + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_ADR_OFF, 0x0); + // Enable the I2C device but do not start any transfers and + // leave interrupts disabled. + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, HAL_MCF52xx_I2C_CR_IEN); + + // As per the documentation, if IBB is set then issue a stop. It + // is not really clear this is the right thing to do in + // multimaster setups, if another master happens to start a + // transfer at this exact time. Presumably it solves more problems + // than it might cause. + HAL_READ_UINT8(base + HAL_MCF52xx_I2C_SR_OFF, reg); + if (reg & HAL_MCF52xx_I2C_SR_IBB) { + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, 0x0000); + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, 0x00A0); + HAL_READ_UINT8( base + HAL_MCF52xx_I2C_DR_OFF, reg); + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_SR_OFF, 0x0000); + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, 0x0000); + + // Don't forget to reenable the device. + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, HAL_MCF52xx_I2C_CR_IEN); + } + + // Clear any pending conditions including interrupts. + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_SR_OFF, 0); + + // Interrupts can now be safely unmasked + HAL_INTERRUPT_UNMASK(I2C_ISRVEC(extra)); +} + +cyg_uint32 +cyg_mcf52xx_i2c_tx(const cyg_i2c_device* dev, cyg_bool send_start, const cyg_uint8* tx_data, cyg_uint32 count, cyg_bool send_stop) +{ + cyg_mcf52xx_i2c_extra* extra = (cyg_mcf52xx_i2c_extra*)dev->i2c_bus->i2c_extra; + + extra->i2c_count = count; + if (! extra->i2c_lost_arb) { + extra->i2c_completed = 0; + extra->i2c_mode = CYG_MCF52xx_I2C_XFER_MODE_TX; + + if (send_start) { + extra->i2c_data.i2c_tx_data = tx_data; + if (! mcf52xx_i2c_send_start(extra, (dev->i2c_address << 1) | 0x00)) { + diag_printf("send_start failed\n"); + return 0; + } + mcf52xx_i2c_doit(extra); + } else if ( !extra->i2c_got_nack) { + // We are in the middle of a transaction and not + // generating a repeated start, so the device must already + // be set up for writes. + extra->i2c_data.i2c_tx_data = &(tx_data[1]); + extra->i2c_count = count - 1; + HAL_WRITE_UINT8(I2C_BASE(extra) + HAL_MCF52xx_I2C_DR_OFF, *tx_data); + mcf52xx_i2c_doit(extra); + } + } + if (send_stop) { + mcf52xx_i2c_stopit(extra); + } + + // tx() should return the number of bytes actually transmitted. + // ISR() increments extra->count after a failure, which leads to + // an edge condition when send_start and there is no acknowledgment + // of the address byte. + if (extra->i2c_count > count) { + return 0; + } + return count - extra->i2c_count; +} + +cyg_uint32 +cyg_mcf52xx_i2c_rx(const cyg_i2c_device* dev, cyg_bool send_start, cyg_uint8* rx_data, cyg_uint32 count, cyg_bool send_nack, cyg_bool send_stop) +{ + cyg_mcf52xx_i2c_extra* extra = (cyg_mcf52xx_i2c_extra*)dev->i2c_bus->i2c_extra; + cyg_uint8* base = I2C_BASE(extra); + cyg_uint8 discard; + + extra->i2c_count = count; + extra->i2c_send_nack = send_nack; + + if (! extra->i2c_lost_arb) { + extra->i2c_completed = 0; + extra->i2c_data.i2c_rx_data = rx_data; + if (send_start) { + extra->i2c_mode = CYG_MCF52xx_I2C_XFER_MODE_STARTRX; + if (! mcf52xx_i2c_send_start(extra, (dev->i2c_address << 1) | 0x01) ) { + return 0; + } + } else { + // In the middle of a transaction. The previous transfer + // will have left the device in tx mode. + extra->i2c_mode = CYG_MCF52xx_I2C_XFER_MODE_RX; + if (send_nack && (1 == count)) { + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, + HAL_MCF52xx_I2C_CR_IEN | + HAL_MCF52xx_I2C_CR_IIEN | + HAL_MCF52xx_I2C_CR_MSTA | + HAL_MCF52xx_I2C_CR_TXAK); + } else { + HAL_WRITE_UINT8(base + HAL_MCF52xx_I2C_CR_OFF, + HAL_MCF52xx_I2C_CR_IEN | + HAL_MCF52xx_I2C_CR_IIEN | + HAL_MCF52xx_I2C_CR_MSTA); + } + // So reading the data register here should get the device + // reading the next byte. + HAL_READ_UINT8(base + HAL_MCF52xx_I2C_DR_OFF, discard); + } + mcf52xx_i2c_doit(extra); + } + if (send_stop) { + mcf52xx_i2c_stopit(extra); + } + return count - extra->i2c_count; +} + +void +cyg_mcf52xx_i2c_stop(const cyg_i2c_device* dev) +{ + cyg_mcf52xx_i2c_extra* extra = (cyg_mcf52xx_i2c_extra*)dev->i2c_bus->i2c_extra; + mcf52xx_i2c_stopit(extra); +} + +#endif // defined(CYGHWR_DEVS_I2C_MCF52xx_MULTIPLE_BUSES) || defined(HAL_MCF52xx_I2C_SINGLETON_BASE) +//--------------------------------------------------------------------------- +// EOF i2c_mcf52xx.c diff --git a/packages/devs/serial/arm/lpc24xx/v2_0/ChangeLog b/packages/devs/serial/arm/lpc24xx/v2_0/ChangeLog new file mode 100755 index 00000000..5b5c2c1c --- /dev/null +++ b/packages/devs/serial/arm/lpc24xx/v2_0/ChangeLog @@ -0,0 +1,37 @@ +2008-07-07 Uwe Kindler + + * include/arm_lpc24xx_ser.inl: + Serial driver for ARM LPC24XX, using generic 16X5X 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) 2004 eCosCentric Limited +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/serial/arm/lpc24xx/v2_0/cdl/ser_arm_lpc24xx.cdl b/packages/devs/serial/arm/lpc24xx/v2_0/cdl/ser_arm_lpc24xx.cdl new file mode 100755 index 00000000..a4c15ba2 --- /dev/null +++ b/packages/devs/serial/arm/lpc24xx/v2_0/cdl/ser_arm_lpc24xx.cdl @@ -0,0 +1,179 @@ +# ==================================================================== +# +# ser_arm_lpc24xx.cdl +# +# eCos serial ARM/LPC24XX configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 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 +# Original data: gthomas, jskov +# Contributors: +# Date: 2008-07-06 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_IO_SERIAL_ARM_LPC24XX { + display "ARM LPC24xx serial device drivers" + + parent CYGPKG_IO_SERIAL_DEVICES + active_if CYGPKG_IO_SERIAL + active_if CYGPKG_HAL_ARM_LPC24XX + implements CYGINT_IO_SERIAL_GENERIC_16X5X_CHAN_INTPRIO + requires CYGPKG_ERROR + include_dir cyg/io + + description " + This option enables the serial device drivers for the + ARM LPC24xx." + + # FIXME: This really belongs in the GENERIC_16X5X package + cdl_interface CYGINT_IO_SERIAL_GENERIC_16X5X_REQUIRED { + display "Generic 16x5x serial driver required" + } + define_proc { + puts $::cdl_header "#define CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP 4" + } + + + define_proc { + puts $::cdl_system_header "/***** serial driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_GENERIC_16X5X_INL " + puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_GENERIC_16X5X_CFG " + puts $::cdl_system_header "/***** serial driver proc output end *****/" + } + + # Support up to 4 on-chip UART modules. The number may vary between + # processor variants so it is easy to update this here + for { set ::channel 0 } { $::channel < 4 } { incr ::channel } { + + cdl_interface CYGINT_IO_SERIAL_LPC24XX_UART[set ::channel] { + display "Platform provides UART [set ::channel]" + flavor bool + description " + This interface will be implemented if the specific LPC24xx + processor being used has on-chip UART [set ::channel], and if + that UART is accessible on the target hardware." + } + + cdl_component CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL[set ::channel] { + display "ARM LPC24cxx UART [set ::channel] driver" + flavor bool + active_if CYGINT_IO_SERIAL_LPC24XX_UART[set ::channel] + default_value 1 + + implements CYGINT_IO_SERIAL_GENERIC_16X5X_REQUIRED + implements CYGINT_IO_SERIAL_FLOW_CONTROL_HW + implements CYGINT_IO_SERIAL_LINE_STATUS_HW + + description " + This option includes the serial device driver for the ARM + LPC24xx UART [set ::channel]." + + cdl_option CYGDAT_IO_SERIAL_ARM_LPC24XX_SERIAL[set ::channel]_NAME { + display "Device name for UART [set ::channel]" + flavor data + default_value [format {"\"/dev/ser%d\""} $::channel] + description " + This option specifies the name of the serial device + for the ARM LPC24xx UART [set ::channel]." + } + + cdl_option CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL[set ::channel]_BAUD { + display "Baud rate for UART [set ::channel]" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 + 2400 3600 4800 7200 9600 14400 19200 38400 + 57600 115200 230400 } + default_value 38400 + description " + This option specifies the default baud rate (speed) + for the ARM LPC24xx UART [set ::channel]." + } + + cdl_option CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL[set ::channel]_BUFSIZE { + display "Buffer size for the UART [set ::channel]" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers + used for the ARM LPC24xx UART [set ::channel]." + } + + cdl_option CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL[set ::channel]_INTPRIO { + display "Interrupt priority of UART [set ::channel]" + flavor data + legal_values 0 to 15 + default_value 15 + description " + This option selects the interupt priority for the + UART [set ::channel] interrupts. There are 16 + priority levels corresponding to the values 0 + through 15 decimal, of which 15 is the lowest + priority. The reset value of these registers + defaults all interrupt to the lowest priority, + allowing a single write to elevate the priority of + an individual interrupt." + } + } + } + + cdl_component CYGPKG_IO_SERIAL_ARM_LPC24XX_TESTING { + display "Testing parameters" + flavor bool + calculated 1 + active_if CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL0 + + implements CYGINT_IO_SERIAL_TEST_SKIP_9600 + implements CYGINT_IO_SERIAL_TEST_SKIP_115200 + implements CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN + + cdl_option CYGPRI_SER_TEST_SER_DEV { + display "Serial device used for testing" + flavor data + default_value { CYGDAT_IO_SERIAL_ARM_LPC24XX_SERIAL0_NAME } + } + + define_proc { + puts $::cdl_header "#define CYGPRI_SER_TEST_CRASH_ID \"armlpc24xx\"" + puts $::cdl_header "#define CYGPRI_SER_TEST_TTY_DEV \"/dev/tty0\"" + } + } +} + +# EOF ser_arm_lpc24xx.cdl diff --git a/packages/devs/serial/arm/lpc24xx/v2_0/include/arm_lpc24xx_ser.inl b/packages/devs/serial/arm/lpc24xx/v2_0/include/arm_lpc24xx_ser.inl new file mode 100755 index 00000000..e23e1256 --- /dev/null +++ b/packages/devs/serial/arm/lpc24xx/v2_0/include/arm_lpc24xx_ser.inl @@ -0,0 +1,345 @@ +//========================================================================== +// +// io/serial/arm/arm_lpc24xx_ser.inl +// +// ARM LPC24XX Serial I/O definitions +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 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: gthomas, jlarmour +// Date: 2008-06-07 +// Purpose: LPC24XX Serial I/O module (interrupt driven version) +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +//========================================================================== +// INCLUDES +//========================================================================== +#include +#include + + +//========================================================================== +// STATIC DATA +//========================================================================== +// Baud rate specification +static const unsigned int select_baud[] = +{ + 9999, // Unused + 50, + 75, + 110, + 134.5, + 150, + 200, + 300, + 600, + 1200, + 1800, + 2400, + 3600, + 4800, + 7200, + 9600, + 14400, + 19200, + 38400, + 57600, + 115200, + 230400 +}; + + +//========================================================================== +// Return baudrate devisor for certain baudrate +//========================================================================== +unsigned short lpc24xx_baud_generator(pc_serial_info *ser_chan, + cyg_serial_baud_rate_t baud) +{ + cyg_uint8 pclk_id = CYNUM_HAL_LPC24XX_PCLK_UART0; + switch (ser_chan->base) + { + case CYGARC_HAL_LPC24XX_REG_UART0_BASE: + pclk_id = CYNUM_HAL_LPC24XX_PCLK_UART0; + break; + + case CYGARC_HAL_LPC24XX_REG_UART1_BASE: + pclk_id = CYNUM_HAL_LPC24XX_PCLK_UART1; + break; + + case CYGARC_HAL_LPC24XX_REG_UART2_BASE: + pclk_id = CYNUM_HAL_LPC24XX_PCLK_UART2; + break; + + case CYGARC_HAL_LPC24XX_REG_UART3_BASE: + pclk_id = CYNUM_HAL_LPC24XX_PCLK_UART3; + break; + + default: + CYG_FAIL("Invalid UART base address"); + } // (ser_chan->base) + + return CYG_HAL_ARM_LPC24XX_BAUD_GENERATOR(pclk_id, select_baud[baud]); +} + + +#define CYG_IO_SERIAL_GENERIC_16X5X_CHAN_BAUD_GENERATOR(_ser_chan_, _baud_) \ + lpc24xx_baud_generator((_ser_chan_), (_baud_)) + + + +//========================================================================== +// SERIAL CHANNEL 0 +//========================================================================== +#ifdef CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL0 +static pc_serial_info lpc24xx_serial_info0 = +{ + CYGARC_HAL_LPC24XX_REG_UART0_BASE, + CYGNUM_HAL_INTERRUPT_UART0, + CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL0_INTPRIO +}; + +#if CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL0_BUFSIZE > 0 +static unsigned char +lpc24xx_serial_out_buf0[CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL0_BUFSIZE]; +static unsigned char +lpc24xx_serial_in_buf0[CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL0_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(lpc24xx_serial_channel0, + pc_serial_funs, + lpc24xx_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL0_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &lpc24xx_serial_out_buf0[0], + sizeof(lpc24xx_serial_out_buf0), + &lpc24xx_serial_in_buf0[0], + sizeof(lpc24xx_serial_in_buf0) + ); +#else +static SERIAL_CHANNEL(lpc24xx_serial_channel0, + pc_serial_funs, + lpc24xx_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL0_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif + +DEVTAB_ENTRY(lpc24xx_serial_io0, + CYGDAT_IO_SERIAL_ARM_LPC24XX_SERIAL0_NAME, + 0, // Does not depend on a lower + // level interface + &cyg_io_serial_devio, + pc_serial_init, + pc_serial_lookup, // Serial driver may need initializing + &lpc24xx_serial_channel0 + ); +#endif // CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL0 + + +//========================================================================== +// SERIAL CHANNEL 1 +//========================================================================== +#ifdef CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL1 +static pc_serial_info lpc24xx_serial_info1 = +{ + CYGARC_HAL_LPC24XX_REG_UART1_BASE, + CYGNUM_HAL_INTERRUPT_UART1, + CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL1_INTPRIO +}; + +#if CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL1_BUFSIZE > 0 +static unsigned char +lpc24xx_serial_out_buf1[CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL1_BUFSIZE]; +static unsigned char +lpc24xx_serial_in_buf1[CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL1_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(lpc24xx_serial_channel1, + pc_serial_funs, + lpc24xx_serial_info1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL1_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &lpc24xx_serial_out_buf1[0], + sizeof(lpc24xx_serial_out_buf1), + &lpc24xx_serial_in_buf1[0], + sizeof(lpc24xx_serial_in_buf1) + ); +#else +static SERIAL_CHANNEL(lpc24xx_serial_channel1, + pc_serial_funs, + lpc24xx_serial_info1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL1_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif + +DEVTAB_ENTRY(lpc24xx_serial_io1, + CYGDAT_IO_SERIAL_ARM_LPC24XX_SERIAL1_NAME, + 0, // Does not depend on a lower + // level interface + &cyg_io_serial_devio, + pc_serial_init, + pc_serial_lookup, // Serial driver may need initializing + &lpc24xx_serial_channel1 + ); +#endif // CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL1 + + +//========================================================================== +// SERIAL CHANNEL 2 +//========================================================================== +#ifdef CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL2 +static pc_serial_info lpc24xx_serial_info2 = +{ + CYGARC_HAL_LPC24XX_REG_UART2_BASE, + CYGNUM_HAL_INTERRUPT_UART2, + CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL2_INTPRIO +}; + +#if CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL2_BUFSIZE > 0 +static unsigned char +lpc24xx_serial_out_buf2[CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL2_BUFSIZE]; +static unsigned char +lpc24xx_serial_in_buf2[CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL2_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(lpc24xx_serial_channel2, + pc_serial_funs, + lpc24xx_serial_info2, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL2_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &lpc24xx_serial_out_buf2[0], + sizeof(lpc24xx_serial_out_buf2), + &lpc24xx_serial_in_buf2[0], + sizeof(lpc24xx_serial_in_buf2) + ); +#else +static SERIAL_CHANNEL(lpc24xx_serial_channel2, + pc_serial_funs, + lpc24xx_serial_info2, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL2_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif + +DEVTAB_ENTRY(lpc24xx_serial_io2, + CYGDAT_IO_SERIAL_ARM_LPC24XX_SERIAL2_NAME, + 0, // Does not depend on a lower + // level interface + &cyg_io_serial_devio, + pc_serial_init, + pc_serial_lookup, // Serial driver may need initializing + &lpc24xx_serial_channel2 + ); +#endif // CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL2 + + +//========================================================================== +// SERIAL CHANNEL 3 +//========================================================================== +#ifdef CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL3 +static pc_serial_info lpc24xx_serial_info3 = +{ + CYGARC_HAL_LPC24XX_REG_UART3_BASE, + CYGNUM_HAL_INTERRUPT_UART3, + CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL3_INTPRIO +}; + +#if CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL3_BUFSIZE > 0 +static unsigned char +lpc24xx_serial_out_buf3[CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL3_BUFSIZE]; +static unsigned char +lpc24xx_serial_in_buf3[CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL3_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(lpc24xx_serial_channel3, + pc_serial_funs, + lpc24xx_serial_info3, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL3_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &lpc24xx_serial_out_buf3[0], + sizeof(lpc24xx_serial_out_buf3), + &lpc24xx_serial_in_buf3[0], + sizeof(lpc24xx_serial_in_buf3) + ); +#else +static SERIAL_CHANNEL(lpc24xx_serial_channel3, + pc_serial_funs, + lpc24xx_serial_info3, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC24XX_SERIAL3_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif + +DEVTAB_ENTRY(lpc24xx_serial_io3, + CYGDAT_IO_SERIAL_ARM_LPC24XX_SERIAL3_NAME, + 0, // Does not depend on a lower + // level interface + &cyg_io_serial_devio, + pc_serial_init, + pc_serial_lookup, // Serial driver may need initializing + &lpc24xx_serial_channel3 + ); +#endif // CYGPKG_IO_SERIAL_ARM_LPC24XX_SERIAL3 + + +//---------------------------------------------------------------------------- +// EOF arm_lpc2xxx_ser.inl diff --git a/packages/devs/serial/arm/pxa2x0/v2_0/ChangeLog b/packages/devs/serial/arm/pxa2x0/v2_0/ChangeLog new file mode 100644 index 00000000..8f0c2c7a --- /dev/null +++ b/packages/devs/serial/arm/pxa2x0/v2_0/ChangeLog @@ -0,0 +1,48 @@ +2006-11-21 Alexander Neundorf + + * generic PXA 2X0 serial IO support, based on the IQ80321 driver + +2003-02-24 Jonathan Larmour + + * cdl/ser_arm_iq80321.cdl: Remove irrelevant doc link. + +2002-01-25 Nick Garnett + + * include/arm_iq80321_ser.inl: + * cdl/ser_arm_iq80321.cdl: + IQ80321 files created, by copying the IQ80310 versions and editing. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/serial/arm/pxa2x0/v2_0/cdl/ser_arm_xscale_pxa2x0.cdl b/packages/devs/serial/arm/pxa2x0/v2_0/cdl/ser_arm_xscale_pxa2x0.cdl new file mode 100644 index 00000000..4cb41c50 --- /dev/null +++ b/packages/devs/serial/arm/pxa2x0/v2_0/cdl/ser_arm_xscale_pxa2x0.cdl @@ -0,0 +1,155 @@ +# ==================================================================== +# +# ser_arm_xscale_pxa2x0.cdl +# +# eCos serial PXA 2X0 configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): msalter +# Original data: msalter +# Contributors: Alexander Neundorf +# Date: 21st November 2006 (last modification) +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + + +cdl_package CYGPKG_IO_SERIAL_ARM_XSCALE_PXA2X0 { + display "PXA2X0 serial device drivers" + + parent CYGPKG_IO_SERIAL_DEVICES + active_if CYGPKG_IO_SERIAL + active_if CYGPKG_HAL_ARM_XSCALE_PXA2X0 + + requires CYGPKG_ERROR + include_dir cyg/io + + description " + This option enables the serial device drivers for pxa." + doc redirect/ecos-device-drivers.html + + # FIXME: This really belongs in the GENERIC_16X5X package + cdl_interface CYGINT_IO_SERIAL_GENERIC_16X5X_REQUIRED { + display "Generic 16x5x serial driver required" + } + define_proc { + puts $::cdl_header "#define CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP 4" + } + + + define_proc { + puts $::cdl_system_header "/***** serial driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_GENERIC_16X5X_INL " + puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_GENERIC_16X5X_CFG " + puts $::cdl_system_header "/***** serial driver proc output end *****/" + } + + cdl_component CYGPKG_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0 { + display "ARM XSCALE PXA2X0 serial port 0 driver" + flavor bool + default_value 1 + + implements CYGINT_IO_SERIAL_GENERIC_16X5X_REQUIRED + implements CYGINT_IO_SERIAL_FLOW_CONTROL_HW + implements CYGINT_IO_SERIAL_LINE_STATUS_HW + implements CYGNUM_SERIAL_FLOW_RTSCTS_RX + implements CYGNUM_SERIAL_FLOW_RTSCTS_TX + + + description " + This option includes the serial device driver for the PXA 2X0." + + cdl_option CYGDAT_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_NAME { + display "Device name for PXA 2X0 serial port 0 driver" + flavor data + default_value {"\"/dev/ser0\""} + description " + This option specifies the name of the serial device + for the PXA 2X0 port 0." + } + + cdl_option CYGNUM_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_BAUD { + display "Baud rate for the PXA2X0 serial port 0 driver" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 2400 + 3600 4800 7200 9600 14400 19200 38400 + 57600 115200 } + default_value 115200 + description " + This option specifies the default baud rate (speed) + for the PXA2X0 port 0." + } + + cdl_option CYGNUM_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_BUFSIZE { + display "Buffer size for the serial port 0 driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers + used for port 0." + } + } + + + cdl_component CYGPKG_IO_SERIAL_ARM_XSCALE_PXA2X0_TESTING { + display "Testing parameters" + flavor bool + calculated 1 + active_if CYGPKG_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0 + + implements CYGINT_IO_SERIAL_TEST_SKIP_9600 + implements CYGINT_IO_SERIAL_TEST_SKIP_115200 + implements CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN + + cdl_option CYGPRI_SER_TEST_SER_DEV { + display "Serial device used for testing" + flavor data + default_value { CYGDAT_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_NAME } + } + + define_proc { + puts $::cdl_header "#define CYGPRI_SER_TEST_CRASH_ID \"pxa2x0\"" + puts $::cdl_header "#define CYGPRI_SER_TEST_TTY_DEV \"/dev/tty0\"" + } + } + +} + +# EOF ser_arm_xscale_pxa2x0.cdl diff --git a/packages/devs/serial/arm/pxa2x0/v2_0/include/arm_xscale_pxa2x0_ser.inl b/packages/devs/serial/arm/pxa2x0/v2_0/include/arm_xscale_pxa2x0_ser.inl new file mode 100644 index 00000000..ca0908a8 --- /dev/null +++ b/packages/devs/serial/arm/pxa2x0/v2_0/include/arm_xscale_pxa2x0_ser.inl @@ -0,0 +1,123 @@ +//========================================================================== +// +// io/serial/arm/arm_xscale_pxa2x0_ser.inl +// +// Generic PXA 2X0 Serial I/O definitions +// +//========================================================================== +//#####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): msalter +// Contributors: msalter, Alexander Neundorf +// Date: 21st November 2006 +// Purpose: PXA2X0 Serial I/O module (interrupt driven version) +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +//----------------------------------------------------------------------------- +// Baud rate specification + +static unsigned short select_baud[] = { + 0, // Unused + 0, // 50 + 0, // 75 + 0, // 110 + 0, // 134.5 + 0, // 150 + 0, // 200 + 0, // 300 + 0, // 600 + 0, // 1200 + 0, // 1800 + 0, // 2400 + 0, // 3600 + 0, // 4800 + 0, // 7200 + 0, // 9600 + 64, // 14400 + 48, // 19200 + 24, // 38400 + 16, // 57600 + 8, // 115200 +}; + +#ifdef CYGPKG_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0 +static pc_serial_info pxa2x0_serial_info0 = {PXA2X0_FFUART_BASE, + CYGNUM_HAL_INTERRUPT_FFUART}; +#if CYGNUM_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_BUFSIZE > 0 +static unsigned char pxa2x0_serial_out_buf0[CYGNUM_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_BUFSIZE]; +static unsigned char pxa2x0_serial_in_buf0[CYGNUM_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(pxa2x0_serial_channel0, + pc_serial_funs, + pxa2x0_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &pxa2x0_serial_out_buf0[0], sizeof(pxa2x0_serial_out_buf0), + &pxa2x0_serial_in_buf0[0], sizeof(pxa2x0_serial_in_buf0) + ); +#else +static SERIAL_CHANNEL(pxa2x0_serial_channel0, + pc_serial_funs, + pxa2x0_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif + +DEVTAB_ENTRY(pxa2x0_serial_io0, + CYGDAT_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_serial_devio, + pc_serial_init, + pc_serial_lookup, // Serial driver may need initializing + &pxa2x0_serial_channel0 + ); +#endif // CYGPKG_IO_SERIAL_ARM_XSCALE_PXA2X0_SERIAL0 + + +// EOF arm_xscale_pxa2x0_ser.inl diff --git a/packages/devs/serial/coldfire/mcf5272/v2_0/ChangeLog b/packages/devs/serial/coldfire/mcf5272/v2_0/ChangeLog new file mode 100644 index 00000000..65ecb6a7 --- /dev/null +++ b/packages/devs/serial/coldfire/mcf5272/v2_0/ChangeLog @@ -0,0 +1,47 @@ +2006-05-09 Andrew Lunn + + * src/mcf5272_serial.c (MCF5272_uart_init): Fix compiler warning + with diag_printf(). + +2005-06-24 Enrico Piria + + * src/mcf5272_serial.c: + * src/mcf5272_serial.h: + * cdl/mcf5272_serial.cdl: + Rework of the original driver contributed by Wade Jensen. + +2003-02-24 Jonathan Larmour + + * cdl/ser_mcf5272_uart.cdl: Remove irrelevant doc link. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/serial/coldfire/mcf5272/v2_0/cdl/mcf5272_serial.cdl b/packages/devs/serial/coldfire/mcf5272/v2_0/cdl/mcf5272_serial.cdl new file mode 100644 index 00000000..9740dc4f --- /dev/null +++ b/packages/devs/serial/coldfire/mcf5272/v2_0/cdl/mcf5272_serial.cdl @@ -0,0 +1,191 @@ +# ==================================================================== +# +# ser_MCF5272_uart.cdl +# +# eCos serial driver for MCF5272 UART +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2006 eCosCentric Ltd. +## +## 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#### +# ==================================================================== + +cdl_package CYGPKG_IO_SERIAL_COLDFIRE_MCF5272 { + display "Serial driver for MCF5272 UART" + + parent CYGPKG_IO_SERIAL_DEVICES + active_if CYGPKG_IO_SERIAL + requires CYGPKG_ERROR + include_dir cyg/io + description " + This option enables the serial device drivers for the + ColdFire MCF5272." + + compile -library=libextras.a mcf5272_serial.c + + cdl_component CYGPKG_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0 { + display "MCF5272 UART serial port 0 driver" + flavor bool + default_value 1 + + implements CYGINT_IO_SERIAL_FLOW_CONTROL_HW + implements CYGINT_IO_SERIAL_LINE_STATUS_HW + + description "This option includes the serial device driver + for the MCF5272 UART port 0." + + cdl_option CYGDAT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_NAME { + display "Device name for the MCF5272 UART serial port 0" + flavor data + default_value {"\"/dev/ser0\""} + description " + This option specifies the name of serial device for the + MCF5272 UART port 0." + } + + cdl_option CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BAUD { + display "Baud rate for the MCF5272 UART serial port 0" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 2400 3600 + 4800 7200 9600 14400 19200 38400 57600 115200 230400 + } + default_value 19200 + description " + This option specifies the default baud rate (speed) for the + MCF5272 UART port 0." + } + + cdl_option CYGOPT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_AUTOBAUD { + display "Enable automatic baud rate detection for the MCF5272 UART serial port 0." + flavor bool + default_value 0 + active_if CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BUFSIZE > 0 + description " + This option enables automatic baud rate detection for + MCF5272 UART port 0. Sending a BREAK character on the + line will start the detection. The first character following + the BREAK should occupy an odd position in the character table + (like \'a\'). This option requires interrupts to be enabled + for the port." + } + + cdl_option CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BUFSIZE { + display "Buffer size for the MCF5272 UART serial port 0" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the MCF5272 UART port 0. If the size specified is 0, the + driver will not use interrupts." + } + + cdl_option CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_PRIORITY { + display "Interrupt priority level for MCF5272 UART serial port 0" + flavor data + legal_values 1 to 6 + default_value 2 + active_if CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BUFSIZE > 0 + description " + This option specifies the priority associated to interrupts + coming from the MCF5272 UART port 0." + } + } + + cdl_component CYGPKG_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1 { + display "MCF5272 UART serial port 1 driver" + flavor bool + default_value 0 + + implements CYGINT_IO_SERIAL_FLOW_CONTROL_HW + implements CYGINT_IO_SERIAL_LINE_STATUS_HW + + description "This option includes the serial device driver for the + MCF5272 UART port 1." + + cdl_option CYGDAT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_NAME { + display "Device name for the MCF5272 UART serial port 1" + flavor data + default_value {"\"/dev/ser1\""} + description " + This option specifies the name of serial device for the + MCF5272 UART port 1." + } + + cdl_option CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BAUD { + display "Baud rate for the MCF5272 UART serial port 1" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 2400 3600 + 4800 7200 9600 14400 19200 38400 57600 115200 230400 + } + default_value 19200 + description " + This option specifies the default baud rate (speed) for the + MCF5272 UART port 1." + } + + cdl_option CYGOPT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_AUTOBAUD { + display "Enable automatic baud rate detection for the MCF5272 UART serial port 1." + flavor bool + default_value 0 + active_if CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BUFSIZE > 0 + description " + This option enables automatic baud rate detection for + MCF5272 UART port 1. Sending a BREAK character on the + line will start the detection. The first character following + the BREAK should occupy an odd position in the character table + (like \'a\'). This option requires interrupts to be enabled + for the port." + } + + cdl_option CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BUFSIZE { + display "Buffer size for the MCF5272 UART serial port 1" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the MCF5272 UART port 1. If the size specified is 0, the + driver will not use interrupts." + } + + cdl_option CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_PRIORITY { + display "Interrupt priority level for MCF5272 UART serial port 1" + flavor data + legal_values 1 to 6 + default_value 2 + active_if CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BUFSIZE > 0 + description " + This option specifies the priority associated to interrupts + coming from the MCF5272 UART port 1." + } + } +} + diff --git a/packages/devs/serial/coldfire/mcf5272/v2_0/src/mcf5272_serial.c b/packages/devs/serial/coldfire/mcf5272/v2_0/src/mcf5272_serial.c new file mode 100644 index 00000000..ab4300bc --- /dev/null +++ b/packages/devs/serial/coldfire/mcf5272/v2_0/src/mcf5272_serial.c @@ -0,0 +1,1137 @@ +//========================================================================== +// +// devs/serial/coldfire/mcf5272/mcf5272_serial.c +// +// ColdFire MCF5272 UART Serial I/O Interface Module (interrupt driven) +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Wade Jensen, Enrico Piria +// Contributors: +// Date: 2005-06-25 +// Purpose: MCF5272 Serial I/O module (interrupt driven version). +// Description: +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // memset, strcmp + +#include "mcf5272_serial.h" + + +// Use this macro to determine if at least one of the ports uses +// autobaud detection. +#if defined(CYGOPT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_AUTOBAUD) || \ + defined(CYGOPT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_AUTOBAUD) +#define REQUESTED_AUTOBAUD +#endif + +// Autobaud states +typedef enum autobaud_states_t +{ + AB_IDLE = 0, // Normal state. Autobaud process hasn't been initiated yet. + AB_BEGIN_BREAK, // Detected a start of the break. + AB_BEGIN, // Detected the end of the break and has set up the autobaud. + AB_DISABLED // Autobaud detection disabled for this port. +} autobaud_states_t; + +typedef struct MCF5272_uart_info_t +{ + volatile mcf5272_uart_t *base; // Base address of the UART registers + cyg_uint32 uart_vector; // UART interrupt vector number + + cyg_interrupt serial_interrupt; // Interrupt context + cyg_handle_t serial_interrupt_handle; // Interrupt handle + + volatile cyg_uint8 imr_mirror; // Interrupt mask register mirror + + cyg_serial_info_t config; // The channel configuration + + autobaud_states_t autobaud_state; // The autobaud state + + +} MCF5272_uart_info_t; + +// Function prototypes for the MCF5272 UART ISR and DSR. +static cyg_uint32 MCF5272_uart_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void MCF5272_uart_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); + +// Function prototypes for the serial functions. +static bool MCF5272_uart_init(struct cyg_devtab_entry * tab); +static Cyg_ErrNo MCF5272_uart_lookup(struct cyg_devtab_entry **tab, + struct cyg_devtab_entry *sub_tab, const char *name); +static bool MCF5272_uart_putc(serial_channel *chan, unsigned char c); +static unsigned char MCF5272_uart_getc(serial_channel *chan); +Cyg_ErrNo MCF5272_uart_set_config(serial_channel *chan, cyg_uint32 key, + const void *xbuf, cyg_uint32 *len); +static void MCF5272_uart_start_xmit(serial_channel *chan); +static void MCF5272_uart_stop_xmit(serial_channel * chan); + +// Declare the serial functions that are called by the common serial +// driver layer. +static SERIAL_FUNS +( + MCF5272_uart_funs, + MCF5272_uart_putc, + MCF5272_uart_getc, + MCF5272_uart_set_config, + MCF5272_uart_start_xmit, + MCF5272_uart_stop_xmit +); + + +// Definition for channel 0 UART configuration. +//*********************************************** +#ifdef CYGPKG_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0 + +// Data structure contains channel information. +static MCF5272_uart_info_t MCF5272_uart_channel_info_0; + +// If the channel buffer size is zero, do not include interrupt UART processing +#if CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BUFSIZE > 0 + +// Allocate receive and transmit buffer. The size of the buffer is +// configured by the configtool. +static unsigned char +MCF5272_uart_out_buf0[CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BUFSIZE]; +static unsigned char +MCF5272_uart_in_buf0[CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BUFSIZE]; + +// Channel function table. We register the UART functions here so +// that uppper serial drivers can call the serial driver's routines. +static SERIAL_CHANNEL_USING_INTERRUPTS( + MCF5272_uart_channel_0, + MCF5272_uart_funs, + MCF5272_uart_channel_info_0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + MCF5272_uart_out_buf0, sizeof(MCF5272_uart_out_buf0), + MCF5272_uart_in_buf0, sizeof(MCF5272_uart_in_buf0) +); + +#else + +// Don't use interrupt processing for the UART. +static SERIAL_CHANNEL( + MCF5272_uart_channel_0, + MCF5272_uart_funs, + MCF5272_uart_channel_info_0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT +); +#endif + +DEVTAB_ENTRY( + MCF5272_uart_io0, + CYGDAT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_serial_devio, // The table of I/O functions. + MCF5272_uart_init, // UART initialization function. + MCF5272_uart_lookup, // The UART lookup function. This + // function typically sets + // up the device for actual use, + // turning on interrupts, + // configuring the port, etc. + &MCF5272_uart_channel_0 +); +#endif // ifdef CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0 + + +// Definition for channel 1 UART configuration. +//*********************************************** +#ifdef CYGPKG_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1 + +// Data structure contains channel informtion. +static MCF5272_uart_info_t MCF5272_uart_channel_info_1; + +// If the channel buffer size is zero, do not include interrupt UART processing +#if CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BUFSIZE > 0 + +// Allocate receive and transmit buffer. The size of the buffer is +// configured by the configtool. +static unsigned char +MCF5272_uart_out_buf1[CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BUFSIZE]; +static unsigned char +MCF5272_uart_in_buf1[CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BUFSIZE]; + +// Channel function table. We register the UART functions here so +// that uppper serial drivers can call the serial driver's routines. +static SERIAL_CHANNEL_USING_INTERRUPTS( + MCF5272_uart_channel_1, + MCF5272_uart_funs, + MCF5272_uart_channel_info_1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + MCF5272_uart_out_buf1, sizeof(MCF5272_uart_out_buf1), + MCF5272_uart_in_buf1, sizeof(MCF5272_uart_in_buf1) +); + +#else + +static SERIAL_CHANNEL( + MCF5272_uart_channel_1, + MCF5272_uart_funs, + MCF5272_uart_channel_info_1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT +); +#endif + +DEVTAB_ENTRY( + MCF5272_uart_io1, + CYGDAT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_serial_devio, // The table of I/O functions. + MCF5272_uart_init, // UART initialization function. + MCF5272_uart_lookup, // The UART lookup function. This function + // typically sets up the device for actual use, + // turing on interrupts, configuring the port, etc. + &MCF5272_uart_channel_1 +); +#endif // ifdef CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1 + + +// Function Prototypes + +// Internal function to actually configure the hardware to desired +// baud rate, etc. +static bool MCF5272_uart_config_port(serial_channel*, cyg_serial_info_t*); +static void MCF5272_uart_start_xmit(serial_channel*); + + +// The table contains dividers to divide the clock to configure an +// approppriate baud rate for the UART. + +#define DIVIDER(_baudrate_) \ + ((CYGHWR_HAL_SYSTEM_CLOCK_MHZ * 1000000) / ((_baudrate_) * 32)) + +static unsigned long dividers_table[]= +{ + 0, + DIVIDER(50), // CYGNUM_SERIAL_BAUD_50 = 1 + DIVIDER(75), // CYGNUM_SERIAL_BAUD_75 + DIVIDER(110), // CYGNUM_SERIAL_BAUD_110 + DIVIDER(134.5), // CYGNUM_SERIAL_BAUD_134_5 + DIVIDER(150), // CYGNUM_SERIAL_BAUD_150 + DIVIDER(200), // CYGNUM_SERIAL_BAUD_200 + DIVIDER(300), // CYGNUM_SERIAL_BAUD_300 + DIVIDER(600), // CYGNUM_SERIAL_BAUD_600 + DIVIDER(1200), // CYGNUM_SERIAL_BAUD_1200 + DIVIDER(1800), // CYGNUM_SERIAL_BAUD_1800 + DIVIDER(2400), // CYGNUM_SERIAL_BAUD_2400 + DIVIDER(3600), // CYGNUM_SERIAL_BAUD_3600 + DIVIDER(4800), // CYGNUM_SERIAL_BAUD_4800 + DIVIDER(7200), // CYGNUM_SERIAL_BAUD_7200 + DIVIDER(9600), // CYGNUM_SERIAL_BAUD_9600 + DIVIDER(14400), // CYGNUM_SERIAL_BAUD_14400 + DIVIDER(19200), // CYGNUM_SERIAL_BAUD_19200 + DIVIDER(38400), // CYGNUM_SERIAL_BAUD_38400 + DIVIDER(57600), // CYGNUM_SERIAL_BAUD_57600 + DIVIDER(115200), // CYGNUM_SERIAL_BAUD_115200 + DIVIDER(230400) // CYGNUM_SERIAL_BAUD_230400 +}; + + +// **************************************************************************** +// MCF5272_uart_init() - This routine is called during bootstrap to set up the +// UART driver. +// +// INPUT: +// Pointer to the the device table. +// +// RETURN: +// Returns true if the initialization is successful. Otherwise, it retuns +// false. + +static bool MCF5272_uart_init(struct cyg_devtab_entry * tab) +{ + serial_channel *chan = (serial_channel *) tab->priv; + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + int priority_level = 0; + + +#ifdef CYGPKG_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0 + + // Instantiation of the UART channel 0 data structure. This data + // structure contains channel information. + if (strcmp(tab->name, CYGDAT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_NAME) + == 0) + { + + cyg_uint32 pbcnt; + + // A priority makes sense only if interrupts are enabled +#ifdef CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_PRIORITY + priority_level = CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_PRIORITY; +#else + priority_level = 0; +#endif + + // Initialize the UART information data to all zeros + memset(port, sizeof(MCF5272_uart_info_t), 0); + + // Set the base address of the UART registers to differentiate + // itself from the different registers for the other UART port. + port->base = (mcf5272_uart_t *) &MCF5272_DEVS->uart[0]; + + // Set the UART interrupt vector number + port->uart_vector = CYGNUM_HAL_INTERRUPT_UART1; + +#ifdef CYGOPT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0_AUTOBAUD + + // Set the autobaud state to idle + port->autobaud_state = AB_IDLE; +#else + // Disable autobaud detection for this port + port->autobaud_state = AB_DISABLED; +#endif + + // Initialize the UART 0 output pins + HAL_READ_UINT32(&MCF5272_DEVS->gpio.pbcnt, pbcnt); + HAL_WRITE_UINT32(&MCF5272_DEVS->gpio.pbcnt, + MCF5272_GPIO_PBCNT_URT0_EN | + (pbcnt & ~MCF5272_GPIO_PBCNT_URT0_MSK)); + } +#endif // CYGPKG_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL0 + +#ifdef CYGPKG_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1 + + // Instantiation of the UART channel 1 data strucutre. This data + // structure contains channel information. + if (strcmp(tab->name, CYGDAT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_NAME) + == 0) + { + cyg_uint32 pdcnt; + + // A priority makes sense only if interrupts are enabled +#ifdef CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_PRIORITY + priority_level = CYGNUM_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_PRIORITY; +#else + priority_level = 0; +#endif + + // Initialize the UART information data to all zeros + memset(port, sizeof(MCF5272_uart_info_t), 0); + + // Set the base address of the UART registers to differentiate + // itself from the different regusters for the other UART port. + port->base = (mcf5272_uart_t *) &MCF5272_DEVS->uart[1]; + + // Set the UART interrupt vector number + port->uart_vector = CYGNUM_HAL_INTERRUPT_UART2; + +#ifdef CYGOPT_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1_AUTOBAUD + + // Set the autobaud state to idle + port->autobaud_state = AB_IDLE; +#else + // Disable autobaud detection for this port + port->autobaud_state = AB_DISABLED; +#endif + + // Initialize the UART 1 output pins + HAL_READ_UINT32(&MCF5272_DEVS->gpio.pdcnt, pdcnt); + HAL_WRITE_UINT32(&MCF5272_DEVS->gpio.pdcnt, + MCF5272_GPIO_PDCNT_URT1_EN | + (pdcnt & ~MCF5272_GPIO_PDCNT_URT1_MSK)); + + } +#endif // CYGPKG_IO_SERIAL_COLDFIRE_MCF5272_CHANNEL1 + + + if (chan->out_cbuf.len > 0) + { + // If the the buffer is greater than zero, then the driver will + // use interrupt driven I/O. Hence, the driver creates an + // interrupt context for the UART device. + + cyg_drv_interrupt_create(port->uart_vector, + priority_level, // Priority + (cyg_addrword_t)chan, // Data item passed + // to interrupt handler + MCF5272_uart_ISR, + MCF5272_uart_DSR, + &port->serial_interrupt_handle, + &port->serial_interrupt); + + cyg_drv_interrupt_attach(port->serial_interrupt_handle); + + cyg_drv_interrupt_unmask(port->uart_vector); + } + + // Really only required for interrupt driven devices + (chan->callbacks->serial_init)(chan); + +#ifdef CYGDBG_IO_INIT + diag_printf("MCF5272 UART init - dev: %p.%d\n", port->base, + port->uart_vector); +#endif + + // Configure Serial device + return (MCF5272_uart_config_port(chan, &chan->config)); +} + + +// *************************************************************************** +// MCF5272_uart_config_port() - Configure the UART port. +// +// Internal function to actually configure the hardware to desired baud rate, +// etc. +// +// INPUT: +// chan - The channel information. +// new_confg - The port configuration which include the desired +// baud rate, etc. +// +// RETURN: +// Returns true if the port configuration is successful. Otherwise, +// it retuns false. + +static bool MCF5272_uart_config_port(serial_channel *chan, + cyg_serial_info_t *new_config) +{ + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + cyg_uint8 mode_reg = 0; + cyg_uint32 ubgs; + + + // If we are configuring the port once again, disable all interrupts + HAL_WRITE_UINT8(&port->base->uisr_uimr, 0); + + // If the baud rate is null, we don't configure the port + if (new_config->baud == 0) return false; + + // Get the divider from the baudrate table which will use to + // configure the port's baud rate. + ubgs = (cyg_uint16) dividers_table[new_config->baud]; + + // Save the configuration value for later use + port->config = *new_config; + + // We first write the reset values into the device and then configure + // the device the way we want to use it. + + // Reset Transmitter + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_RESET_TX); + + // Reset Receiver + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_RESET_RX); + + // Reset Mode Register + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_RESET_MR); + + // Translate the parity configuration to UART mode bits + switch(port->config.parity) + { + default: + case CYGNUM_SERIAL_PARITY_NONE: + mode_reg = 0 | MCF5272_UART_UMR1_PM_NONE; + break; + + case CYGNUM_SERIAL_PARITY_EVEN: + mode_reg = 0 | MCF5272_UART_UMR1_PM_EVEN; + break; + + case CYGNUM_SERIAL_PARITY_ODD: + mode_reg = 0 | MCF5272_UART_UMR1_PM_ODD; + break; + + case CYGNUM_SERIAL_PARITY_MARK: + mode_reg = 0 | MCF5272_UART_UMR1_PM_FORCE_HI; + break; + + case CYGNUM_SERIAL_PARITY_SPACE: + mode_reg = 0 | MCF5272_UART_UMR1_PM_FORCE_LO; + break; + } + + // Translate the number of bits per character configuration to + // UART mode bits + switch(port->config.word_length) + { + case CYGNUM_SERIAL_WORD_LENGTH_5: + mode_reg |= MCF5272_UART_UMR1_BC_5; + break; + + case CYGNUM_SERIAL_WORD_LENGTH_6: + mode_reg |= MCF5272_UART_UMR1_BC_6; + break; + + case CYGNUM_SERIAL_WORD_LENGTH_7: + mode_reg |= MCF5272_UART_UMR1_BC_7; + break; + + default: + case CYGNUM_SERIAL_WORD_LENGTH_8: + mode_reg |= MCF5272_UART_UMR1_BC_8; + break; + } + + // Enable HW flow control for receiver + if(port->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX) + mode_reg |= MCF5272_UART_UMR1_RXRTS; + + // Configure the parity, HW flow control and the bits per character. + // After this write MR pointer points to mode register 2. + HAL_WRITE_UINT8(&port->base->umr, mode_reg); + + // Translate the stop bit length to UART mode bits + switch(port->config.stop) + { + default: + case CYGNUM_SERIAL_STOP_1: + mode_reg = MCF5272_UART_UMR2_STOP_BITS_1; + break; + + case CYGNUM_SERIAL_STOP_1_5: + mode_reg = MCF5272_UART_UMR2_STOP_BITS_15; + break; + + case CYGNUM_SERIAL_STOP_2: + mode_reg = MCF5272_UART_UMR2_STOP_BITS_2; + break; + } + + // Enable HW flow control for transmitter + if(port->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_TX) + mode_reg |= MCF5272_UART_UMR2_TXCTS; + + // No echo or loopback + mode_reg |= MCF5272_UART_UMR2_CM_NORMAL; + + // Write to mode register 2 + HAL_WRITE_UINT8(&port->base->umr, mode_reg); + + // Set Rx and Tx baud by timer + HAL_WRITE_UINT8(&port->base->usr_ucsr, 0 | MCF5272_UART_UCSR_RCS(0xD) | + MCF5272_UART_UCSR_TCS(0xD)); + + // Mask all UART interrupts + HAL_WRITE_UINT8(&port->base->uisr_uimr, 0); + + // Program the baud settings to the device + HAL_WRITE_UINT8(&port->base->udu, (cyg_uint8)((ubgs & 0xFF00) >> 8)); + HAL_WRITE_UINT8(&port->base->udl, (cyg_uint8)(ubgs & 0x00FF)); + + // Enable receiver and transmitter + HAL_WRITE_UINT8(&port->base->ucr, 0 | MCF5272_UART_UCR_TXRXEN); + + // Enable both transmit and receive interrupt + port->imr_mirror = MCF5272_UART_UIMR_TXRDY | MCF5272_UART_UIMR_FFULL_RXRDY; + + // Enable break interrupt only if autobaud is enabled + if (port->autobaud_state != AB_DISABLED) + port->imr_mirror |= MCF5272_UART_UIMR_DB; + + HAL_WRITE_UINT8(&port->base->uisr_uimr, port->imr_mirror); + + // Return true to indicate a successful configuration + return true; +} + + +// *************************************************************************** +// MCF5272_uart_lookup() - This routine is called when the device is "looked" +// up (i.e. attached) +// +// INPUT: +// tab - pointer to a pointer of the device table. +// sub_tab - Pointer to the sub device table. +// name - name of the device. +// +// RETURN: +// Always return ENOERR. + +static Cyg_ErrNo MCF5272_uart_lookup(struct cyg_devtab_entry **tab, + struct cyg_devtab_entry *sub_tab, + const char *name) +{ + serial_channel *chan = (serial_channel *)(*tab)->priv; + + // Really only required for interrupt driven devices + (chan->callbacks->serial_init)(chan); + return ENOERR; +} + + +// *************************************************************************** +// MCF5272_uart_putc() - Send a character to the device output buffer. +// +// INPUT: +// chan - pointer to the serial private data. +// c - the character to output. +// +// RETURN: +// 'true' if character is sent to device, return 'false' when we've +// ran out of buffer space in the device itself. + +static bool MCF5272_uart_putc(serial_channel *chan, unsigned char c) +{ + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + cyg_uint8 usr_ucsr; + + // Make sure the transmitter is not full. If it is full, return false. + HAL_READ_UINT8(&port->base->usr_ucsr, usr_ucsr); + if (!(usr_ucsr & MCF5272_UART_USR_TXRDY)) + return false; + + // Send the character + HAL_WRITE_UINT8(&port->base->urb_utb, c); + + return true ; +} + + +// *************************************************************************** +// MCF5272_uart_getc() - Fetch a character from the device input buffer and +// return it to the calling routine. Wait until there +// is a character ready. +// +// INPUT: +// chan - pointer to the serial private data. +// +// RETURN: +// the character read from the UART. + +static unsigned char MCF5272_uart_getc(serial_channel *chan) +{ + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + cyg_uint8 usr_ucsr, urb_utb; + + // Wait until character has been received + do + { + HAL_READ_UINT8(&port->base->usr_ucsr, usr_ucsr); + } + while (!(usr_ucsr & MCF5272_UART_USR_RXRDY)) ; + + // Read the character from the FIFO queue + HAL_READ_UINT8(&port->base->urb_utb, urb_utb); + + return urb_utb; +} + + +// *************************************************************************** +// MCF5272_uart_set_config() - Set up the device characteristics; baud rate, +// etc. +// +// INPUT: +// chan - pointer to the serial private data. +// key - configuration key (command). +// xbuf - pointer to the configuration buffer. +// len - the length of the configuration buffer. +// +// RETURN: +// NOERR - If the configuration is successful. +// EINVAL - If the argument is invalid. + +Cyg_ErrNo MCF5272_uart_set_config(serial_channel *chan, + cyg_uint32 key, + const void *xbuf, + cyg_uint32 *len) +{ + cyg_serial_info_t *config = (cyg_serial_info_t *) xbuf; + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + + switch (key) + { + case CYG_IO_SET_CONFIG_SERIAL_INFO: + { + // Set serial configuration + if (*len < sizeof(cyg_serial_info_t)) + return EINVAL; + + *len = sizeof(cyg_serial_info_t); + + if (!MCF5272_uart_config_port(chan, config)) + return EINVAL; + } + break; + + case CYG_IO_GET_CONFIG_SERIAL_INFO: + // Retrieve UART configuration + *config = port->config; + break; + +#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW + case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE: + { + cyg_uint32 *f = (cyg_uint32 *)xbuf; + + if (*len < sizeof(*f)) + return -EINVAL; + + // we should throttle + if (*f) HAL_WRITE_UINT8(&port->base->uop0, MCF5272_UART_UOP0_RTS); + // we should no longer throttle + else HAL_WRITE_UINT8(&port->base->uop1, MCF5272_UART_UOP1_RTS); + } + break; + + case CYG_IO_SET_CONFIG_SERIAL_HW_FLOW_CONFIG: + // We only support RTSCTS (and software) flow control. + // We clear any unsupported flags here and + // then return -ENOSUPP - the higher layer can then query + // what flags are set and decide what to do. + { + unsigned int flags_mask; + cyg_uint8 umr1_mask, umr2_mask; + + // These are the control flow modes we support + flags_mask = (CYGNUM_SERIAL_FLOW_RTSCTS_RX | + CYGNUM_SERIAL_FLOW_RTSCTS_RX); +#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE + flags_mask |= (CYGNUM_SERIAL_FLOW_XONXOFF_RX | + CYGNUM_SERIAL_FLOW_XONXOFF_TX); +#endif + if (chan->config.flags & ~flags_mask) + { + chan->config.flags &= flags_mask; + return -ENOSUPP; + } + + // For security, mask UART interrupt while we change configuration + cyg_drv_interrupt_mask(port->uart_vector); + + // Reset mode register pointer + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_RESET_MR); + + // Read mode register 1 + HAL_READ_UINT8(&port->base->umr, umr1_mask); + + // Read mode register 2 + HAL_READ_UINT8(&port->base->umr, umr2_mask); + + if (chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX) + umr1_mask |= MCF5272_UART_UMR1_RXRTS; + else umr1_mask &= ~MCF5272_UART_UMR1_RXRTS; + + if (chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_TX) + umr2_mask |= MCF5272_UART_UMR2_TXCTS; + else umr2_mask &= ~MCF5272_UART_UMR2_TXCTS; + + // Reset mode register pointer + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_RESET_MR); + + // Write mode register 1 + HAL_WRITE_UINT8(&port->base->umr, umr1_mask); + + // Write mode register 2 + HAL_WRITE_UINT8(&port->base->umr, umr2_mask); + + // Unmask UART interrupt + cyg_drv_interrupt_unmask(port->uart_vector); + } + break; +#endif // CYGOPT_IO_SERIAL_FLOW_CONTROL_HW + + default: + return EINVAL; + } + + return ENOERR; +} + + +// *************************************************************************** +// MCF5272_uart_start_xmit() - Enable the transmitter on the device. +// +// INPUT: +// chan - pointer to the serial private data. + +static void MCF5272_uart_start_xmit(serial_channel *chan) +{ + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + + + // Mask UART interrupt to prevent race conditions + cyg_drv_interrupt_mask(port->uart_vector); + + // Enable the UART transmitter. + // Eventually, preserve the ongoing autobaud calculation. +#ifdef REQUESTED_AUTOBAUD + if(port->autobaud_state == AB_BEGIN) + HAL_WRITE_UINT8(&port->base->ucr, (MCF5272_UART_UCR_TX_ENABLED | + MCF5272_UART_UCR_ENAB)); + else +#endif + { + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_TX_ENABLED); + } + + // Enable transmitter interrupt + port->imr_mirror |= MCF5272_UART_UIMR_TXRDY; + HAL_WRITE_UINT8(&port->base->uisr_uimr, port->imr_mirror); + + // Unmask UART interrupt + cyg_drv_interrupt_unmask(port->uart_vector); +} + + +// *************************************************************************** +// MCF5272_uart_stop_xmit() - Disable the transmitter on the device +// +// INPUT: +// chan - pointer to the serial private data. + +static void MCF5272_uart_stop_xmit(serial_channel * chan) +{ + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + + + // Mask UART interrupt to prevent race conditions + cyg_drv_interrupt_mask(port->uart_vector); + + // Disable transmitter interrupt + port->imr_mirror &= ~MCF5272_UART_UIMR_TXRDY; + HAL_WRITE_UINT8(&port->base->uisr_uimr, port->imr_mirror); + + // Disable the UART transmitter. + // Eventually, preserve the ongoing autobaud calculation. + // !!!!!!!!!!!!! + // !!!WARNING!!! + // !!!!!!!!!!!!! + // If the transmitter is disabled + // the diag_printf routines will poll forever to transmit the + // a character. Hence, don't ever disable the transmitter if + // you want it to work with diag_printf. +#ifdef REQUESTED_AUTOBAUD + if(port->autobaud_state == AB_BEGIN) + HAL_WRITE_UINT8(&port->base->ucr, (MCF5272_UART_UCR_TX_DISABLED | + MCF5272_UART_UCR_ENAB)); + else +#endif + { + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_TX_DISABLED); + } + + // Unmask UART interrupt + cyg_drv_interrupt_unmask(port->uart_vector); +} + + +// *************************************************************************** +// MCF5272_uart_ISR() - UART I/O interrupt interrupt service routine (ISR). +// +// INPUT: +// vector - the interrupt vector number. +// data - user parameter. +// +// RETURN: +// returns CYG_ISR_CALL_DSR to call the DSR. + +static cyg_uint32 MCF5272_uart_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + serial_channel *chan = (serial_channel *) data; + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + + + // Write the value in the interrupt status register back + // to the mask register to disable the interrupt temporarily. + HAL_WRITE_UINT8(&port->base->uisr_uimr, 0); + + // Cause DSR to run + return CYG_ISR_CALL_DSR; +} + + +// *************************************************************************** +// MCF5272_uart_DSR() - Defered Service Routine (DSR) - This routine processes +// the interrupt from the device. +// +// INPUT: +// vector - The interrupt vector number. +// count - The nunber of DSR requests. +// data - Device specific information. +// +// The autobaud feature is implemented by means of a simple finite state +// machine which can take the following states: +// AB_DISABLED: autobaud is disabled. +// AB_IDLE: no autobaud calculation is in progress. If autobaud calculation +// has completed, retrieve the new baud rate. +// AB_BEGIN_BREAK: the start of a break character was detected. +// AB_BEGIN: the end of a break character was detected. Start autobaud +// calculation. +// +// The state diagram is the following: +// AB_IDLE --> AB_BEGIN_BREAK --> AB_BEGIN --> Back to AB_IDLE +// The state AB_DISABLED is isolated and means that the autobaud feature is +// not active for that port. + +static void MCF5272_uart_DSR(cyg_vector_t vector, cyg_ucount32 count, + cyg_addrword_t data) +{ + serial_channel *chan = (serial_channel *) data; + MCF5272_uart_info_t *port = (MCF5272_uart_info_t *) chan->dev_priv; + volatile cyg_uint8 isr; + cyg_uint8 uisr_uimr; + + + while (1) + { + // First of all, the exit condition + + // Retrieve the interrupt status bits. We use these status bits to + // figure out what process should we perform: read from the UART or + // inform of a completion of a data transmission. + HAL_READ_UINT8(&port->base->uisr_uimr, uisr_uimr); + isr = uisr_uimr & port->imr_mirror; + + // If there are no more events pending, exit the loop + if (!isr) break; + +#ifdef REQUESTED_AUTOBAUD + switch (port->autobaud_state) + { + case AB_DISABLED: + // Nothing to check for + break; + + case AB_BEGIN_BREAK: + if (isr & MCF5272_UART_UISR_DB) + { + // Detected the end of a break, set the state to + // AB_BEGIN, and setup autobaud detection. + port->autobaud_state = AB_BEGIN; + + // Initialize divider + HAL_WRITE_UINT8(&port->base->udu, 0); + HAL_WRITE_UINT8(&port->base->udl, 0); + + // Reset the Delta Break bit in the UISR and + //Enable autobaud + HAL_WRITE_UINT8(&port->base->ucr, + MCF5272_UART_UCR_RESET_BKCHGINT); + + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_ENAB); + + // Enable autobaud completion interrupt + port->imr_mirror |= MCF5272_UART_UIMR_ABC; + + // Disable the delta break interrupt so we can't receive + // anymore break interrupt. + port->imr_mirror &= ~MCF5272_UART_UIMR_DB; + + } + break; + + case AB_BEGIN: + if (isr & MCF5272_UART_UISR_ABC) + { + int count; + unsigned int threshold; + cyg_uint8 uabu, uabl; + + // Retrieve the detected baud rate + HAL_READ_UINT8(&port->base->uabu, uabu); + HAL_READ_UINT8(&port->base->uabl, uabl); + + cyg_uint16 divider = (uabu << 8) + uabl; + + // Search in the list to find a match + for (count = sizeof(dividers_table)/ + sizeof(unsigned long) - 1; + count > 1; count--) + { + if (divider < dividers_table[count - 1]) break; + } + + // Modify baud rate only if it is in range + if (count > 1) + { + // Set the baud rate to the nearest standard rate + threshold = (dividers_table[count] + + dividers_table[count - 1]) / 2; + port->config.baud = (divider < threshold) ? count : + count - 1; + } + + divider = dividers_table[port->config.baud]; + + // Program the baud settings to the device + HAL_WRITE_UINT8(&port->base->udu, + (cyg_uint8)((divider & 0xFF00) >> 8)); + HAL_WRITE_UINT8(&port->base->udl, + (cyg_uint8)(divider & 0x00FF)); + + // Autobaud completion + port->autobaud_state = AB_IDLE; + + // Disable autobaud + HAL_WRITE_UINT8(&port->base->ucr, MCF5272_UART_UCR_NONE); + +#if 0 + // In case patch submitted July 11, 2005 gets committed +#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS + // Inform upper layers of the new baud rate + { + cyg_serial_line_status_t stat; + + stat.which = CYGNUM_SERIAL_STATUS_NEWBAUDRATE; + stat.value = port->config.baud; + + (chan->callbacks->indicate_status)(chan, &stat); + } +#endif +#endif + // Ignore autobaud completion interrupt + port->imr_mirror &= ~MCF5272_UART_UIMR_ABC; + + // Reenable delta break interrupt + port->imr_mirror |= MCF5272_UART_UIMR_DB; + + } + break; + + default: + case AB_IDLE: + if (isr & MCF5272_UART_UISR_DB) + { + // Detected the begin of a break, set the state to + // AB_BEGIN_BREAK + port->autobaud_state = AB_BEGIN_BREAK; + + // Reset the delta break bit in the UISR + HAL_WRITE_UINT8(&port->base->ucr, + MCF5272_UART_UCR_RESET_BKCHGINT); + } + break; + } +#endif // REQUESTED_AUTOBAUD + + // Receive character interrupt + if ((isr & MCF5272_UART_UISR_RXRDY)) + { + char c; + cyg_uint8 usr_ucsr; +#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS + cyg_serial_line_status_t stat; +#endif + + // Read all the characters in the fifo + while (1) + { + // First of all, the exit condition + + // If there are no more characters waiting, exit the loop + HAL_READ_UINT8(&port->base->uisr_uimr, uisr_uimr); + if (!(uisr_uimr & MCF5272_UART_UISR_RXRDY)) break; + + // Read port status + HAL_READ_UINT8(&port->base->usr_ucsr, usr_ucsr); + + // Received break + if (usr_ucsr & MCF5272_UART_USR_RB) + { + // Ignore break character + HAL_READ_UINT8(&port->base->urb_utb, c); +#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS + stat.which = CYGNUM_SERIAL_STATUS_BREAK; + (chan->callbacks->indicate_status)(chan, &stat); +#endif + continue; + } + +#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS + // Overrun error + if (usr_ucsr & MCF5272_UART_USR_OE) + { + stat.which = CYGNUM_SERIAL_STATUS_OVERRUNERR; + (chan->callbacks->indicate_status)(chan, &stat); + } +#endif + +#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS + // Framing error + if (usr_ucsr & MCF5272_UART_USR_FE) + { + stat.which = CYGNUM_SERIAL_STATUS_FRAMEERR; + (chan->callbacks->indicate_status)(chan, &stat); + } +#endif + +#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS + // Parity error + if (usr_ucsr & MCF5272_UART_USR_PE) + { + stat.which = CYGNUM_SERIAL_STATUS_PARITYERR; + (chan->callbacks->indicate_status)(chan, &stat); + } +#endif + + // Read the character from the UART + HAL_READ_UINT8(&port->base->urb_utb, c); + + // Pass the read character to the upper layer + (chan->callbacks->rcv_char)(chan, c); + } + } + + // Transmit complete interrupt + if ((isr & MCF5272_UART_UISR_TXRDY)) + { + // Transmit holding register is empty + (chan->callbacks->xmt_char)(chan); + } + } + + // Unmask all the UART interrupts that were masked in the ISR, so + // that we can receive the next interrupt. + HAL_WRITE_UINT8(&port->base->uisr_uimr, port->imr_mirror); +} diff --git a/packages/devs/serial/coldfire/mcf5272/v2_0/src/mcf5272_serial.h b/packages/devs/serial/coldfire/mcf5272/v2_0/src/mcf5272_serial.h new file mode 100644 index 00000000..790dafc2 --- /dev/null +++ b/packages/devs/serial/coldfire/mcf5272/v2_0/src/mcf5272_serial.h @@ -0,0 +1,140 @@ +#ifndef CYGONCE_MCF5272_SERIAL_H +#define CYGONCE_MCF5272_SERIAL_H + +//========================================================================== +// +// devs/serial/coldfire/mcf5272/mcf5272_serial.h +// +// ColdFire MCF5272 serial I/O module definitions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria, Wade Jensen +// Contributors: +// Date: 2005-06-25 +// Purpose: MCF5272 serial I/O module definitions. +// Description: +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#include + +// Bit level definitions and macros +#define MCF5272_UART_UMR1_RXRTS (0x80) +#define MCF5272_UART_UMR1_RXIRQ (0x40) +#define MCF5272_UART_UMR1_ERR (0x20) +#define MCF5272_UART_UMR1_PM_MULTI_ADDR (0x1C) +#define MCF5272_UART_UMR1_PM_MULTI_DATA (0x18) +#define MCF5272_UART_UMR1_PM_NONE (0x10) +#define MCF5272_UART_UMR1_PM_FORCE_HI (0x0C) +#define MCF5272_UART_UMR1_PM_FORCE_LO (0x08) +#define MCF5272_UART_UMR1_PM_ODD (0x04) +#define MCF5272_UART_UMR1_PM_EVEN (0x00) +#define MCF5272_UART_UMR1_BC_5 (0x00) +#define MCF5272_UART_UMR1_BC_6 (0x01) +#define MCF5272_UART_UMR1_BC_7 (0x02) +#define MCF5272_UART_UMR1_BC_8 (0x03) + +#define MCF5272_UART_UMR2_CM_NORMAL (0x00) +#define MCF5272_UART_UMR2_CM_ECHO (0x40) +#define MCF5272_UART_UMR2_CM_LOCAL_LOOP (0x80) +#define MCF5272_UART_UMR2_CM_REMOTE_LOO (0xC0) +#define MCF5272_UART_UMR2_TXRTS (0x20) +#define MCF5272_UART_UMR2_TXCTS (0x10) +#define MCF5272_UART_UMR2_STOP_BITS_1 (0x07) +#define MCF5272_UART_UMR2_STOP_BITS_15 (0x08) +#define MCF5272_UART_UMR2_STOP_BITS_2 (0x0F) +// Stop Bit Length +#define MCF5272_UART_UMR2_STOP_BITS(a) ((a)&0x0f) + +#define MCF5272_UART_USR_RB (0x80) +#define MCF5272_UART_USR_FE (0x40) +#define MCF5272_UART_USR_PE (0x20) +#define MCF5272_UART_USR_OE (0x10) +#define MCF5272_UART_USR_TXEMP (0x08) +#define MCF5272_UART_USR_TXRDY (0x04) +#define MCF5272_UART_USR_FFULL (0x02) +#define MCF5272_UART_USR_RXRDY (0x01) + +// Rx Clk Select +#define MCF5272_UART_UCSR_RCS(a) (((a) & 0x0f) << 4) +// Tx Clk Select +#define MCF5272_UART_UCSR_TCS(a) ((a) & 0x0f) + + +#define MCF5272_UART_UCR_NONE (0x00) +#define MCF5272_UART_UCR_ENAB (0x80) +#define MCF5272_UART_UCR_STOP_BREAK (0x70) +#define MCF5272_UART_UCR_START_BREAK (0x60) +#define MCF5272_UART_UCR_RESET_BKCHGINT (0x50) +#define MCF5272_UART_UCR_RESET_ERROR (0x40) +#define MCF5272_UART_UCR_RESET_TX (0x30) +#define MCF5272_UART_UCR_RESET_RX (0x20) +#define MCF5272_UART_UCR_RESET_MR (0x10) +#define MCF5272_UART_UCR_TX_DISABLED (0x08) +#define MCF5272_UART_UCR_TX_ENABLED (0x04) +#define MCF5272_UART_UCR_RX_DISABLED (0x02) +#define MCF5272_UART_UCR_RX_ENABLED (0x01) + +#define MCF5272_UART_UCR_TXRXEN \ + (MCF5272_UART_UCR_TX_ENABLED | MCF5272_UART_UCR_RX_ENABLED) + +#define MCF5272_UART_UCCR_COS (0x10) +#define MCF5272_UART_UCCR_CTS (0x01) + +#define MCF5272_UART_UACR_BRG (0x80) +#define MCF5272_UART_UACR_CTMS_TIMER (0x60) +#define MCF5272_UART_UACR_IEC (0x01) + +#define MCF5272_UART_UISR_COS (0x80) +#define MCF5272_UART_UISR_ABC (0x40) +#define MCF5272_UART_UISR_DB (0x04) +#define MCF5272_UART_UISR_RXRDY (0x02) +#define MCF5272_UART_UISR_TXRDY (0x01) + +#define MCF5272_UART_UIMR_COS (0x80) +#define MCF5272_UART_UIMR_ABC (0x40) +#define MCF5272_UART_UIMR_DB (0x04) +#define MCF5272_UART_UIMR_FFULL_RXRDY (0x02) +#define MCF5272_UART_UIMR_TXRDY (0x01) + +#define MCF5272_UART_UOP0_RTS (0x01) +#define MCF5272_UART_UOP1_RTS (0x01) + +// --------------------------------------------------------------------------- +// End of mcf5272_serial.h +#endif // CYGONCE_MCF5272_SERIAL_H diff --git a/packages/devs/serial/freescale/esci/drv/v2_0/ChangeLog b/packages/devs/serial/freescale/esci/drv/v2_0/ChangeLog new file mode 100644 index 00000000..a91f2806 --- /dev/null +++ b/packages/devs/serial/freescale/esci/drv/v2_0/ChangeLog @@ -0,0 +1,55 @@ +2007-01-10 Ilija Koco + + * ser_freescale_esci_h.cdl: CYGPKG_IO_SERIAL_FREESCALE_ESCI_H + moved in a new directory due ecosadmin.tcl issue + reported by John Dallaway + +2006-08-31 Ilija Koco + + * ser_freescale_esci.cdl: driver now requires at least 1 selected + channel + +2006-08-08 Ilija Koco + + * ser_esci.h : platform dependent clock related macros + removed and placed in platform/var header + +2006-05-24 Ilija Koco + + * cdl/ser_freescale_esci.cdl: + * include/ser_esci.h: + * src/ser_esci.c + New package + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/serial/freescale/esci/drv/v2_0/cdl/ser_freescale_esci.cdl b/packages/devs/serial/freescale/esci/drv/v2_0/cdl/ser_freescale_esci.cdl new file mode 100644 index 00000000..d7e5ad41 --- /dev/null +++ b/packages/devs/serial/freescale/esci/drv/v2_0/cdl/ser_freescale_esci.cdl @@ -0,0 +1,304 @@ +# ==================================================================== +# +# ser_freescale_esci.cdl +# +# eCos serial Freescale/esci configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2006 eCosCentric Ltd +## +## 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): Ilija Koco +# Original data: +# Contributors: +# Date: 2006-04-20 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_IO_SERIAL_FREESCALE_ESCI { + display "eSCI device driver" + + parent CYGPKG_IO_SERIAL_DEVICES + active_if CYGPKG_IO_SERIAL + + requires CYGPKG_IO_SERIAL_FREESCALE_ESCI_H + + requires (CYGPKG_ERROR && (CYGPKG_IO_SERIAL_FREESCALE_ESCI_A || \ + CYGPKG_IO_SERIAL_FREESCALE_ESCI_B || \ + CYGPKG_IO_SERIAL_FREESCALE_ESCI_C || \ + CYGPKG_IO_SERIAL_FREESCALE_ESCI_D) \ + ) + + include_dir cyg/devs + + description " + This option enables the serial device drivers for the + Freescale eSCI - Enhanced Serial Communication Interface. + eSCI is on-chip serial controller found on some freescale + microcontrollers such as: MAC7100 familly, etc. + " + compile -library=libextras.a ser_esci.c + + define_proc { + puts $::cdl_system_header "/***** serial driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_DEVICE_HEADER " + puts $::cdl_system_header "/***** serial driver proc output end *****/" + } + + cdl_component CYGPKG_IO_SERIAL_FREESCALE_ESCI_A { + display "eSCI port A driver" + flavor bool + default_value 0 + description " + This option includes the serial device driver for the eSCI port A." + + cdl_option CYGDAT_IO_SERIAL_FREESCALE_ESCI_A_NAME { + display "Device name for eSCI port A" + flavor data + default_value {"\"/dev/ser0\""} + description " + This option specifies the device name for the eSCI port A." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BAUD { + display "Baud rate for the eSCI serial port A driver" + flavor data + legal_values { 300 600 1200 2400 4800 9600 14400 19200 38400 + 57600 115200 } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + eSCI port A." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE { + display "Buffer size for the sSCI port A driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the eSCI port A." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_PRIORITY { + display "eSCI port A INTC priority" + flavor data + legal_values 0 to 15 + default_value 7 + description " + INTC has 16 interrupt levels: 0 (lowest) to 15 (highest). + " + } + } + + cdl_component CYGPKG_IO_SERIAL_FREESCALE_ESCI_B { + display "eSCI port B driver" + flavor bool + default_value 0 + description " + This option includes the serial device driver for the eSCI port B." + + cdl_option CYGDAT_IO_SERIAL_FREESCALE_ESCI_B_NAME { + display "Device name for eSCI port B" + flavor data + default_value {"\"/dev/ser1\""} + description " + This option specifies the device name for the eSCI port B." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BAUD { + display "Baud rate for the eSCI serial port A driver" + flavor data + legal_values { 300 600 1200 2400 4800 9600 14400 19200 38400 + 57600 115200 } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + eSCI port B." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE { + display "Buffer size for the sSCI port A driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the eSCI port B." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_PRIORITY { + display "eSCI prot B INTC priority" + flavor data + legal_values 0 to 15 + default_value 7 + description " + INTC has 16 interrupt levels: 0 (lowest) to 15 (highest). + " + } + + } + + cdl_component CYGPKG_IO_SERIAL_FREESCALE_ESCI_C { + display "eSCI port C driver" + flavor bool + default_value 0 + description " + This option includes the serial device driver for the eSCI port C." + + cdl_option CYGDAT_IO_SERIAL_FREESCALE_ESCI_C_NAME { + display "Device name for eSCI port C" + flavor data + default_value {"\"/dev/ser2\""} + description " + This option specifies the device name for the eSCI port C." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BAUD { + display "Baud rate for the eSCI serial port A driver" + flavor data + legal_values { 300 600 1200 2400 4800 9600 14400 19200 38400 + 57600 115200 } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + eSCI port C." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE { + display "Buffer size for the sSCI port A driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the eSCI port C." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_PRIORITY { + display "eSCI prot B INTC priority" + flavor data + legal_values 0 to 15 + default_value 6 + description " + INTC has 16 interrupt levels: 0 (lowest) to 15 (highest). + " + } + + } + + cdl_component CYGPKG_IO_SERIAL_FREESCALE_ESCI_D { + display "eSCI port D driver" + flavor bool + default_value 0 + description " + This option includes the serial device driver for the eSCI port D." + + cdl_option CYGDAT_IO_SERIAL_FREESCALE_ESCI_D_NAME { + display "Device name for eSCI port D" + flavor data + default_value {"\"/dev/ser3\""} + description " + This option specifies the device name for the eSCI port D." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BAUD { + display "Baud rate for the eSCI serial port A driver" + flavor data + legal_values { 300 600 1200 2400 4800 9600 14400 19200 38400 + 57600 115200 } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + eSCI port D." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE { + display "Buffer size for the sSCI port A driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the eSCI port D." + } + + cdl_option CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_PRIORITY { + display "eSCI prot B INTC priority" + flavor data + legal_values 0 to 15 + default_value 6 + description " + INTC has 16 interrupt levels: 0 (lowest) to 15 (highest). + " + } + } + + + cdl_component CYGPKG_IO_SERIAL_FREESCALE_ESCI_OPTIONS { + display "Serial device driver build options" + flavor none + description " + Package specific build options including control over + compiler flags used only in building this package, + and details of which tests are built." + + + cdl_option CYGPKG_IO_SERIAL_FREESCALE_ESCI_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building these serial device drivers. These flags are + used in addition to the set of global flags." + } + + cdl_option CYGPKG_IO_SERIAL_FREESCALE_ESCI_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building these serial device drivers. These flags are + removed from the set of global flags if present." + } + } +} + +# EOF ser_freescale_esci.cdl diff --git a/packages/devs/serial/freescale/esci/drv/v2_0/src/ser_esci.c b/packages/devs/serial/freescale/esci/drv/v2_0/src/ser_esci.c new file mode 100644 index 00000000..10930277 --- /dev/null +++ b/packages/devs/serial/freescale/esci/drv/v2_0/src/ser_esci.c @@ -0,0 +1,547 @@ +//========================================================================== +// +// ser_esci.c +// +// Freescale sSCI Serial I/O Interface Module (interrupt driven) +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2996 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-04-20 +// Purpose: eSCI Serial I/O module (interrupt driven version) +// Description: +// +// +//####DESCRIPTIONEND#### +//========================================================================== +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// Only build this driver for if ESCI is needed. +#ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI + +typedef struct esci_serial_info { + CYG_ADDRWORD esci_base; // Base address of the esci port + CYG_WORD interrupt_num; // INTC interrupt vector + cyg_priority_t interrupt_priority; // INTC interupt priority + cyg_interrupt interrupt_obj; // Interrupt object + cyg_handle_t interrupt_handle; // Interrupt handle +} esci_serial_info; + +static bool esci_serial_init(struct cyg_devtab_entry * tab); +static bool esci_serial_putc(serial_channel * chan, unsigned char c); +static Cyg_ErrNo esci_serial_lookup(struct cyg_devtab_entry ** tab, + struct cyg_devtab_entry * sub_tab, + const char * name); +static unsigned char esci_serial_getc(serial_channel *chan); +static Cyg_ErrNo esci_serial_set_config(serial_channel *chan, cyg_uint32 key, + const void *xbuf, cyg_uint32 *len); +static void esci_serial_start_xmit(serial_channel *chan); +static void esci_serial_stop_xmit(serial_channel *chan); + +// Interrupt servers +static cyg_uint32 esci_serial_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void esci_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, + cyg_addrword_t data); + +static SERIAL_FUNS(esci_serial_funs, + esci_serial_putc, + esci_serial_getc, + esci_serial_set_config, + esci_serial_start_xmit, + esci_serial_stop_xmit); + +// Available baud rates +static unsigned short select_baud[] = { + 0, // Unused + 0, // 50 bps unsupported + 0, // 75 bps unsupported + 0, // 110 bps unsupported + 0, // 134_5 bps unsupported + 0, // 150 bps unsupported + 0, // 200 bps unsupported + FREESCALE_ESCI_BAUD(300), // 300 bps + FREESCALE_ESCI_BAUD(600), // 600 bps + FREESCALE_ESCI_BAUD(1200), // 1200 bps + 0, // 1800 bps unsupported + FREESCALE_ESCI_BAUD(2400), // 2400 bps + 0, // 3600 bps unsupported + FREESCALE_ESCI_BAUD(4800), // 4800 bps + 0, // 7200 bps unsupported + FREESCALE_ESCI_BAUD(9600), // 9600 bps + FREESCALE_ESCI_BAUD(14400), // 14400 bps + FREESCALE_ESCI_BAUD(19200), // 19200 bps + FREESCALE_ESCI_BAUD(38400), // 38400 bps + FREESCALE_ESCI_BAUD(57600), // 57600 bps + FREESCALE_ESCI_BAUD(115200), // 115200 bps + 0 // 230400 bps unsupported +}; + +#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_A +static esci_serial_info esci_serial_info0 = { + esci_base : CYGADDR_IO_SERIAL_FREESCALE_ESCI_A_BASE, + interrupt_num : CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_VECTOR, + interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_PRIORITY +}; +#if CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE > 0 +static unsigned char + esci_serial_out_buf0[CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE]; +static unsigned char + esci_serial_in_buf0[CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE]; + +static +SERIAL_CHANNEL_USING_INTERRUPTS( + esci_serial_channel0, + esci_serial_funs, + esci_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &esci_serial_out_buf0[0], + sizeof(esci_serial_out_buf0), + &esci_serial_in_buf0[0], + sizeof(esci_serial_in_buf0)); +#else +static +SERIAL_CHANNEL(esci_serial_channel0, + esci_serial_funs, + esci_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT); +#endif +DEVTAB_ENTRY(esci_serial_io0, + CYGDAT_IO_SERIAL_FREESCALE_ESCI_A_NAME, + 0, // does not depend on a lower level device driver + &cyg_io_serial_devio, + esci_serial_init, + esci_serial_lookup, + &esci_serial_channel0); +#endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_A + +#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_B +static esci_serial_info esci_serial_info1 = { + esci_base : CYGADDR_IO_SERIAL_FREESCALE_ESCI_B_BASE, + interrupt_num : CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_VECTOR, + interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_PRIORITY +}; +#if CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE > 0 +static unsigned char + esci_serial_out_buf1[CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE]; +static unsigned char + esci_serial_in_buf1[CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE]; + +static +SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel1, + esci_serial_funs, + esci_serial_info1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &esci_serial_out_buf1[0], + sizeof(esci_serial_out_buf1), + &esci_serial_in_buf1[0], + sizeof(esci_serial_in_buf1)); +#else +static +SERIAL_CHANNEL(esci_serial_channel1, + esci_serial_funs, + esci_serial_info1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT); +#endif +DEVTAB_ENTRY(esci_serial_io1, + CYGDAT_IO_SERIAL_FREESCALE_ESCI_B_NAME, + 0, // does not depend on a lower level device driver + &cyg_io_serial_devio, + esci_serial_init, + esci_serial_lookup, + &esci_serial_channel1); +#endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_B + +#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_C +static esci_serial_info esci_serial_info2 = { + esci_base : CYGADDR_IO_SERIAL_FREESCALE_ESCI_C_BASE, + interrupt_num : CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_VECTOR, + interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_PRIORITY +}; +#if CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE > 0 +static unsigned char + esci_serial_out_buf2[CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE]; +static unsigned char + esci_serial_in_buf2[CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE]; + +static +SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel2, + esci_serial_funs, + esci_serial_info2, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &esci_serial_out_buf2[0], + sizeof(esci_serial_out_buf2), + &esci_serial_in_buf2[0], + sizeof(esci_serial_in_buf2)); +#else +static +SERIAL_CHANNEL(esci_serial_channel2, + esci_serial_funs, + esci_serial_info2, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT); +#endif +DEVTAB_ENTRY(esci_serial_io2, + CYGDAT_IO_SERIAL_FREESCALE_ESCI_C_NAME, + 0, // does not depend on a lower level device driver + &cyg_io_serial_devio, + esci_serial_init, + esci_serial_lookup, + &esci_serial_channel2); +#endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_C + + +#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_D +static esci_serial_info esci_serial_info3 = { + esci_base : CYGADDR_IO_SERIAL_FREESCALE_ESCI_D_BASE, + interrupt_num : CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_VECTOR, + interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_PRIORITY +}; +#if CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE > 0 +static unsigned char + esci_serial_out_buf3[CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE]; +static unsigned char + esci_serial_in_buf3[CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE]; + +static +SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel3, + esci_serial_funs, + esci_serial_info3, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &esci_serial_out_buf3[0], + sizeof(esci_serial_out_buf3), + &esci_serial_in_buf3[0], + sizeof(esci_serial_in_buf3)); +#else +static +SERIAL_CHANNEL(esci_serial_channel3, + esci_serial_funs, + esci_serial_info3, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT); +#endif +DEVTAB_ENTRY(esci_serial_io3, + CYGDAT_IO_SERIAL_FREESCALE_ESCI_D_NAME, + 0, // does not depend on a lower level device driver + &cyg_io_serial_devio, + esci_serial_init, + esci_serial_lookup, + &esci_serial_channel3); +#endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_D + +//---------------------------------------------------------------------------- +// Internal function to actually configure the hardware to desired +// baud rate, etc. +//---------------------------------------------------------------------------- +static bool +esci_serial_config_port(serial_channel * chan, cyg_serial_info_t * new_config, + bool init) +{ + esci_serial_info * esci_chan = (esci_serial_info *)(chan->dev_priv); + cyg_addrword_t esci_base = esci_chan->esci_base; + cyg_uint16 baud_rate = ((new_config->baud >= 0) && + (new_config->baud < (sizeof(select_baud)/ + sizeof(select_baud[0])))) + ? select_baud[new_config->baud] : 0; + + cyg_uint16 esci_cr12=0, esci_cr12_old; + + HAL_WRITE_UINT8(FREESCALE_ESCI_CR3(esci_base), 0); + HAL_WRITE_UINT16(FREESCALE_ESCI_LINCTRL(esci_base), 0); + HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), 0); + + if(!baud_rate) return false; // Invalid baud rate selected + + switch(new_config->word_length){ + case 8: break; + default: return false; + } + + switch(new_config->parity){ + case CYGNUM_SERIAL_PARITY_ODD: + esci_cr12 |= FREESCALE_ESCI_CR12_PT; + case CYGNUM_SERIAL_PARITY_EVEN: + esci_cr12 |= FREESCALE_ESCI_CR12_PE; + case CYGNUM_SERIAL_PARITY_NONE: + break; + default: return false; + } + + if(new_config->stop!=CYGNUM_SERIAL_STOP_1) return false; + + // Enable the device + esci_cr12 |= FREESCALE_ESCI_CR12_TE | FREESCALE_ESCI_CR12_RE; + + if(init){ // Enable the receiver interrupt + esci_cr12 |= FREESCALE_ESCI_CR12_RIE; + }else{ // Restore the old interrupt state + HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12_old); + esci_cr12 |= (esci_cr12_old & FREESCALE_ESCI_CR12_RIE); + } + HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12); + + if(new_config != &chan->config) + chan->config = *new_config; + + return true; +} + +//-------------------------------------------------------------- +// Function to initialize the device. Called at bootstrap time. +//-------------------------------------------------------------- +static bool +esci_serial_init(struct cyg_devtab_entry * tab) +{ + serial_channel * chan = (serial_channel *)tab->priv; + esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv; + + // Really only required for interrupt driven devices + (chan->callbacks->serial_init)(chan); + if(chan->out_cbuf.len != 0){ + cyg_drv_interrupt_create(esci_chan->interrupt_num, + esci_chan->interrupt_priority, + // Data item passed to interrupt handler + (cyg_addrword_t)chan, + esci_serial_ISR, + esci_serial_DSR, + &esci_chan->interrupt_handle, + &esci_chan->interrupt_obj); + + cyg_drv_interrupt_attach(esci_chan->interrupt_handle); + cyg_drv_interrupt_unmask(esci_chan->interrupt_num); + } + return esci_serial_config_port(chan, &chan->config, true); +} + +//---------------------------------------------------------------------- +// This routine is called when the device is "looked" up (i.e. attached) +//---------------------------------------------------------------------- +static Cyg_ErrNo +esci_serial_lookup(struct cyg_devtab_entry ** tab, + struct cyg_devtab_entry * sub_tab, const char * name) +{ + serial_channel * chan = (serial_channel *)(*tab)->priv; + // Really only required for interrupt driven devices + (chan->callbacks->serial_init)(chan); + + return ENOERR; +} + +//----------------------------------------------------------------- +// Send a character to Tx +//----------------------------------------------------------------- +static bool +esci_serial_putc(serial_channel * chan, unsigned char ch_out) +{ + esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv; + cyg_addrword_t esci_base = esci_chan->esci_base; + cyg_uint16 esci_sr; + + HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr); + if(esci_sr & FREESCALE_ESCI_SR_TDRE){ + HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_TDRE); + HAL_WRITE_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_out); + return true; + }else + return false; +} + +//--------------------------------------------------------------------- +// Fetch a character Rx (for polled operation only) +//--------------------------------------------------------------------- +static unsigned char +esci_serial_getc(serial_channel * chan) +{ + cyg_uint8 ch_in; + esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv; + cyg_addrword_t esci_base = esci_chan->esci_base; + + cyg_uint16 esci_sr; + + do{ + HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr); + }while(esci_sr & FREESCALE_ESCI_SR_RDRF); + + HAL_READ_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_in); + HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_RDRF); + + return ch_in; +} + +//--------------------------------------------------- +// Set up the device characteristics; baud rate, etc. +//--------------------------------------------------- +static bool +esci_serial_set_config(serial_channel * chan, cyg_uint32 key, + const void *xbuf, cyg_uint32 * len) +{ + switch(key) { + case CYG_IO_SET_CONFIG_SERIAL_INFO:{ + cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf; + if(*len < sizeof(cyg_serial_info_t)) { + return -EINVAL; + } + *len = sizeof(cyg_serial_info_t); + if(true != esci_serial_config_port(chan, config, false)) + return -EINVAL; + } + break; + default: + return -EINVAL; + } + return ENOERR; +} + +//------------------------------------- +// Enable the transmitter on the device +//------------------------------------- +static void esci_serial_start_xmit(serial_channel * chan) +{ + esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv; + cyg_addrword_t esci_base = esci_chan->esci_base; + cyg_uint16 esci_cr12; + + HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12); + esci_cr12 |= FREESCALE_ESCI_CR12_TIE; + HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12); +} + +//-------------------------------------- +// Disable the transmitter on the device +//-------------------------------------- +static void esci_serial_stop_xmit(serial_channel * chan) +{ + esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv; + + cyg_addrword_t esci_base = esci_chan->esci_base; + cyg_uint16 esci_cr12; + + HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12); + esci_cr12 &= ~FREESCALE_ESCI_CR12_TIE; + HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12); +} + +//----------------------------------------- +// The low level interrupt handler +//----------------------------------------- +static +cyg_uint32 esci_serial_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + serial_channel * chan = (serial_channel *)data; + esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv; + + cyg_drv_interrupt_mask(esci_chan->interrupt_num); + cyg_drv_interrupt_acknowledge(esci_chan->interrupt_num); + + return CYG_ISR_CALL_DSR; // cause the DSR to run +} + + +//------------------------------------------ +// The high level interrupt handler +//------------------------------------------ + +#define FREESCALE_ESCI_SR_ERRORS (FREESCALE_ESCI_SR_OR | \ + FREESCALE_ESCI_SR_NF | \ + FREESCALE_ESCI_SR_FE | \ + FREESCALE_ESCI_SR_PF) + +static void +esci_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + serial_channel * chan = (serial_channel *)data; + esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv; + cyg_addrword_t esci_base = esci_chan->esci_base; + cyg_uint16 esci_sr; + cyg_uint8 esci_dr; + + HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr); + if(esci_sr & FREESCALE_ESCI_SR_RDRF){ // Receiver full + HAL_READ_UINT8(FREESCALE_ESCI_DRL(esci_base), esci_dr); + HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_RDRF); + if(esci_sr &= (cyg_uint16)FREESCALE_ESCI_SR_ERRORS){ + HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr); + }else{ + (chan->callbacks->rcv_char)(chan, (cyg_uint8)esci_dr); + } + }else if(esci_sr & FREESCALE_ESCI_SR_TDRE){ //Transmitter empty + (chan->callbacks->xmt_char)(chan); + } + + cyg_drv_interrupt_unmask(esci_chan->interrupt_num); +} + +#endif // CYGPKG_IO_SERIAL_FREESCALE_ESCI_[ABCD] +// EOF ser_esci.c diff --git a/packages/devs/serial/freescale/esci/hdr/v2_0/ChangeLog b/packages/devs/serial/freescale/esci/hdr/v2_0/ChangeLog new file mode 100644 index 00000000..bdc339a0 --- /dev/null +++ b/packages/devs/serial/freescale/esci/hdr/v2_0/ChangeLog @@ -0,0 +1,56 @@ +2007-01-10 Ilija Koco + + * ser_freescale_esci_h.cdl: moved in a newly created directory for + CYGPKG_IO_SERIAL_FREESCALE_ESCI_H due ecosadmin.tcl issue + reported by John Dallaway + + +2006-08-31 Ilija Koco + + * ser_freescale_esci.cdl: driver now requires at least 1 selected + channel + +2006-08-08 Ilija Koco + + * ser_esci.h : platform dependent clock related macros + removed and placed in platform/var header + +2006-05-24 Ilija Koco + + * cdl/ser_freescale_esci.cdl: + * include/ser_esci.h: + * src/ser_esci.c + New package + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/serial/freescale/esci/hdr/v2_0/cdl/ser_freescale_esci_h.cdl b/packages/devs/serial/freescale/esci/hdr/v2_0/cdl/ser_freescale_esci_h.cdl new file mode 100644 index 00000000..98bac8eb --- /dev/null +++ b/packages/devs/serial/freescale/esci/hdr/v2_0/cdl/ser_freescale_esci_h.cdl @@ -0,0 +1,66 @@ +# ==================================================================== +# +# ser_freescale_esci_h.cdl +# +# eCos serial Freescale/esci configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2006 eCosCentric Ltd +## +## 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): Ilija Koco +# Original data: +# Contributors: +# Date: 2006-05-30 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_IO_SERIAL_FREESCALE_ESCI_H { + display "eSCI header" + + include_dir cyg/devs + description " + This option provides header for Freescale eSCI - Enhanced + Serial Communication Interface. eSCI is on-chip serial + controller found on some Freescale micro controllers such as: + MAC7100 familly, etc. " + + define_proc { + puts $::cdl_system_header "/***** serial driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_DEVICE_HEADER " + puts $::cdl_system_header "/***** serial driver proc output end *****/" + } +} + +# EOF ser_freescale_esci_h.cdl diff --git a/packages/devs/serial/freescale/esci/hdr/v2_0/include/ser_esci.h b/packages/devs/serial/freescale/esci/hdr/v2_0/include/ser_esci.h new file mode 100644 index 00000000..bb568c2b --- /dev/null +++ b/packages/devs/serial/freescale/esci/hdr/v2_0/include/ser_esci.h @@ -0,0 +1,161 @@ +#ifndef CYGONCE_DEVS_SERIAL_FREESCALE_ESCI_H +#define CYGONCE_DEVS_SERIAL_FREESCALE_ESCI_H +//========================================================================== +// +// ser_esci.h +// +// Freescale eSCI Serial I/O definitions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-04-20 +// Purpose: eSCI Serial I/O definitions. +// Description: +// +// +//####DESCRIPTIONEND#### +//========================================================================== + +// Note: Following macros are platform dependent +// and have to be defined in var_io.h or plf_io.h +// Macros referenced by serial driver: +// CYGADDR_IO_SERIAL_FREESCALE_ESCI_A_BASE +// CYGADDR_IO_SERIAL_FREESCALE_ESCI_B_BASE +// CYGADDR_IO_SERIAL_FREESCALE_ESCI_C_BASE +// CYGADDR_IO_SERIAL_FREESCALE_ESCI_D_BASE +// CYGNUM_DEV_SER_FREESCALE_ESCI_SYSTEM_CLOCK +// FREESCALE_ESCI_BAUD(baud_rate) + +// Macros not referenced by serial driver +// but by interrupt controller +// CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_VECTOR +// CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_VECTOR +// CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_VECTOR +// CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_VECTOR +// MAC7100_ESCI_A_IV +// MAC7100_ESCI_B_IV +// MAC7100_ESCI_C_IV +// MAC7100_ESCI_D_IV +// + +#define FREESCALE_ESCI_A_BASE (CYGADDR_IO_SERIAL_FREESCALE_ESCI_A_BASE) +#define FREESCALE_ESCI_B_BASE (CYGADDR_IO_SERIAL_FREESCALE_ESCI_B_BASE) +#define FREESCALE_ESCI_C_BASE (CYGADDR_IO_SERIAL_FREESCALE_ESCI_C_BASE) +#define FREESCALE_ESCI_D_BASE (CYGADDR_IO_SERIAL_FREESCALE_ESCI_D_BASE) + +#define FREESCALE_ESCI_A_I 0 +#define FREESCALE_ESCI_B_I 1 +#define FREESCALE_ESCI_C_I 2 +#define FREESCALE_ESCI_D_I 3 + +#define FREESCALE_ESCI_BD(esci_base) \ + (esci_base + FREESCALE_ESCI_BD_OFFSET) //short +#define FREESCALE_ESCI_CR12(esci_base) \ + (esci_base + FREESCALE_ESCI_CR12_OFFSET) //short +#define FREESCALE_ESCI_CR34(esci_base) \ + (esci_base + FREESCALE_ESCI_CR34_OFFSET) //short +#define FREESCALE_ESCI_CR1(esci_base) \ + (esci_base + FREESCALE_ESCI_CR1_OFFSET) //char +#define FREESCALE_ESCI_CR2(esci_base) \ + (esci_base + FREESCALE_ESCI_CR2_OFFSET) //char +#define FREESCALE_ESCI_CR3(esci_base) \ + (esci_base + FREESCALE_ESCI_CR3_OFFSET) //char +#define FREESCALE_ESCI_CR4(esci_base) \ + (esci_base + FREESCALE_ESCI_CR4_OFFSET) //short +#define FREESCALE_ESCI_LINCTRL(esci_base) \ + (esci_base + FREESCALE_ESCI_LINCTRL_OFFSET) //short +#define FREESCALE_ESCI_LINCRCP(esci_base) \ + (esci_base + FREESCALE_ESCI_LINCRCP_OFFSET) //short +#define FREESCALE_ESCI_SR(esci_base) \ + (esci_base + FREESCALE_ESCI_SR_OFFSET) //short +#define FREESCALE_ESCI_DRL(esci_base) \ + (esci_base + FREESCALE_ESCI_DRL_OFFSET) //char + +#define FREESCALE_ESCI_BD_OFFSET (0x0000) +#define FREESCALE_ESCI_CR12_OFFSET (0x0002) +#define FREESCALE_ESCI_CR34_OFFSET (0x0002) +#define FREESCALE_ESCI_CR1_OFFSET (0x0002) +#define FREESCALE_ESCI_CR2_OFFSET (0x0003) +#define FREESCALE_ESCI_CR3_OFFSET (0x0004) +#define FREESCALE_ESCI_CR4_OFFSET (0x0005) +#define FREESCALE_ESCI_DRL_OFFSET (0x0007) +#define FREESCALE_ESCI_SR_OFFSET (0x0008) +#define FREESCALE_ESCI_LINSTAT_OFFSET (0x000A) +#define FREESCALE_ESCI_LINCTRL_OFFSET (0x000C) +#define FREESCALE_ESCI_LINRX_OFFSET (0x0010) +#define FREESCALE_ESCI_LINTX_OFFSET (0x0014) +#define FREESCALE_ESCI_LINCRCP_OFFSET (0x0018) + +#define FREESCALE_ESCI_CR12_LOOPS (0x8000) +#define FREESCALE_ESCI_CR12_SCISDOZ (0x4000) +#define FREESCALE_ESCI_CR12_RSRC (0x2000) +#define FREESCALE_ESCI_CR12_M (0x1000) +#define FREESCALE_ESCI_CR12_WAKE (0x0800) +#define FREESCALE_ESCI_CR12_ILT (0x0400) +#define FREESCALE_ESCI_CR12_PE (0x0200) +#define FREESCALE_ESCI_CR12_PT (0x0100) +#define FREESCALE_ESCI_CR12_TIE (0x0080) +#define FREESCALE_ESCI_CR12_TCIE (0x0040) +#define FREESCALE_ESCI_CR12_RIE (0x0020) +#define FREESCALE_ESCI_CR12_ILIE (0x0010) +#define FREESCALE_ESCI_CR12_TE (0x0008) +#define FREESCALE_ESCI_CR12_RE (0x0004) +#define FREESCALE_ESCI_CR12_RWU (0x0002) +#define FREESCALE_ESCI_CR12_SBK (0x0001) + +#define FREESCALE_ESCI_CR3_MDIS (0x80) +#define FREESCALE_ESCI_CR3_FBR (0x40) +#define FREESCALE_ESCI_CR3_BSTP (0x20) +#define FREESCALE_ESCI_CR3_IEBERR (0x10) +#define FREESCALE_ESCI_CR3_RXDMA (0x08) +#define FREESCALE_ESCI_CR3_TXDMA (0x04) +#define FREESCALE_ESCI_CR3_BRK13 (0x02) +#define FREESCALE_ESCI_CR3_TXDIR (0x01) + +#define FREESCALE_ESCI_SR_TDRE (0x8000) +#define FREESCALE_ESCI_SR_TC (0x4000) +#define FREESCALE_ESCI_SR_RDRF (0x2000) +#define FREESCALE_ESCI_SR_IDLE (0x1000) +#define FREESCALE_ESCI_SR_OR (0x0800) +#define FREESCALE_ESCI_SR_NF (0x0400) +#define FREESCALE_ESCI_SR_FE (0x0200) +#define FREESCALE_ESCI_SR_PF (0x0100) +#define FREESCALE_ESCI_SR_BERR (0x0010) +#define FREESCALE_ESCI_SR_RAF (0x0001) + +#endif // CYGONCE_DEVS_SERIAL_FREESCALE_ESCI_H +// EOF ser_esci.h diff --git a/packages/devs/serial/powerpc/mpc555/v2_0/ChangeLog b/packages/devs/serial/powerpc/mpc555/v2_0/ChangeLog new file mode 100644 index 00000000..647f7a5d --- /dev/null +++ b/packages/devs/serial/powerpc/mpc555/v2_0/ChangeLog @@ -0,0 +1,48 @@ +2008-04-06 Steven Clugston + + * Refactored cme555 package to more generic mpc555 + +2003-02-24 Jonathan Larmour + + * cdl/ser_powerpc_cme555.cdl: Remove irrelevant doc link. + +2002-11-11 Bob Koninckx + + * src/cme555_serial_with_ints.c: + interrupt arbiter slightly modified to make GDB CTRL-C work + +2002-04-24 Bob Koninckx + + * New package. + +//=========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/serial/powerpc/mpc555/v2_0/cdl/ser_powerpc_mpc555.cdl b/packages/devs/serial/powerpc/mpc555/v2_0/cdl/ser_powerpc_mpc555.cdl new file mode 100644 index 00000000..f3243399 --- /dev/null +++ b/packages/devs/serial/powerpc/mpc555/v2_0/cdl/ser_powerpc_mpc555.cdl @@ -0,0 +1,181 @@ +# ==================================================================== +# +# ser_powerpc_mpc555.cdl +# +# eCos serial PowerPC/mpc555 configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Bob Koninckx +# Original data: +# Contributors: +# Date: 1999-07-14 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_IO_SERIAL_POWERPC_MPC555 { + display "mpc555 PowerPC serial device drivers" + + parent CYGPKG_IO_SERIAL_DEVICES + active_if CYGPKG_IO_SERIAL + active_if CYGPKG_HAL_POWERPC_MPC555 + + requires CYGPKG_ERROR + include_dir cyg/io + include_files ; # none _exported_ whatsoever + description " + This option enables the serial device drivers for the + mpc555 mpc555 development board." + + compile -library=libextras.a mpc555_serial_with_ints.c + + define_proc { + puts $::cdl_system_header "/***** serial driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_DEVICE_HEADER " + puts $::cdl_system_header "/***** serial driver proc output end *****/" + } + +cdl_component CYGPKG_IO_SERIAL_POWERPC_MPC555_SERIAL_A { + display "mpc555 PowerPC serial port A driver" + flavor bool + default_value 0 + description " + This option includes the serial device driver for the mpc555 + PowerPC port A." + + cdl_option CYGDAT_IO_SERIAL_POWERPC_MPC555_SERIAL_A_NAME { + display "Device name for mpc555 PowerPC serial port A" + flavor data + default_value {"\"/dev/ser1\""} + description " + This option specifies the device name for the mpc555 PowerPC + port A." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_A_BAUD { + display "Baud rate for the mpc555 PowerPC serial port A driver" + flavor data + legal_values { 300 600 1200 2400 4800 9600 14400 19200 38400 57600 115200 } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + mpc555 PowerPC port A." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_A_BUFSIZE { + display "Buffer size for the mpc555 PowerPC serial port A driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used for + the mpc555 PowerPC port A." + } +} + +cdl_component CYGPKG_IO_SERIAL_POWERPC_MPC555_SERIAL_B { + display "mpc555 PowerPC serial port B driver" + flavor bool + default_value 1 + description " + This option includes the serial device driver for the mpc555 + PowerPC port B." + + cdl_option CYGDAT_IO_SERIAL_POWERPC_MPC555_SERIAL_B_NAME { + display "Device name for mpc555 PowerPC serial port B" + flavor data + default_value {"\"/dev/ser2\""} + description " + This option specifies the device name for the mpc555 PowerPC + port B." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_B_BAUD { + display "Baud rate for the mpc555 PowerPC serial port B driver" + flavor data + legal_values { 300 600 1200 2400 4800 9600 14400 19200 38400 57600 115200 } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + mpc555 PowerPC port B." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_B_BUFSIZE { + display "Buffer size for the mpc555 PowerPC serial port B driver" + flavor data + legal_values 0 to 8192 + default_value 128 + description " + This option specifies the size of the internal buffers used + for the mpc555 PowerPC port B." + } +} + + cdl_component CYGPKG_IO_SERIAL_POWERPC_MPC555_OPTIONS { + display "Serial device driver build options" + flavor none + description " + Package specific build options including control over + compiler flags used only in building this package, + and details of which tests are built." + + + cdl_option CYGPKG_IO_SERIAL_POWERPC_MPC555_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building these serial device drivers. These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_IO_SERIAL_POWERPC_MPC555_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building these serial device drivers. These flags are removed from + the set of global flags if present." + } + } + +} + +# EOF ser_powerpc_mpc555.cdl diff --git a/packages/devs/serial/powerpc/mpc555/v2_0/src/mpc555_serial.h b/packages/devs/serial/powerpc/mpc555/v2_0/src/mpc555_serial.h new file mode 100644 index 00000000..72141a4f --- /dev/null +++ b/packages/devs/serial/powerpc/mpc555/v2_0/src/mpc555_serial.h @@ -0,0 +1,154 @@ +#ifndef CYGONCE_DEVS_SERIAL_POWERPC_MPC555_SERIAL_H +#define CYGONCE_DEVS_SERIAL_POWERPC_MPC555_SERIAL_H +//========================================================================== +// +// mpc555_serial.h +// +// PowerPC 5xx MPC555 Serial I/O definitions. +// +//========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Bob Koninckx +// Contributors: +// Date: 2002-04-25 +// Purpose: MPC555 Serial I/O definitions. +// Description: +// +// +//####DESCRIPTIONEND#### +//========================================================================== + +//---------------------------------- +// Includes and forward declarations +//---------------------------------- + +//---------------------- +// Constants definitions +//---------------------- +// Base addresses for the two serial ports +#define MPC555_SERIAL_BASE_A 0x305008 +#define MPC555_SERIAL_BASE_B 0x305020 + +// The offset from the base for all serial registers +#define MPC555_SERIAL_SCCxR0 0 +#define MPC555_SERIAL_SCCxR1 2 +#define MPC555_SERIAL_SCxSR 4 +#define MPC555_SERIAL_SCxDR 6 + +// The bits in the serial registers +#define MPC555_SERIAL_SCCxR0_OTHR 0x8000 +#define MPC555_SERIAL_SCCxR0_LINKBD 0x4000 +#define MPC555_SERIAL_SCCxR0_SCxBR 0x1fff + +#define MPC555_SERIAL_SCCxR1_LOOPS 0x4000 +#define MPC555_SERIAL_SCCxR1_WOMS 0x2000 +#define MPC555_SERIAL_SCCxR1_ILT 0x1000 +#define MPC555_SERIAL_SCCxR1_PT 0x0800 +#define MPC555_SERIAL_SCCxR1_PE 0x0400 +#define MPC555_SERIAL_SCCxR1_M 0x0200 +#define MPC555_SERIAL_SCCxR1_WAKE 0x0100 +#define MPC555_SERIAL_SCCxR1_TIE 0x0080 +#define MPC555_SERIAL_SCCxR1_TCIE 0x0040 +#define MPC555_SERIAL_SCCxR1_RIE 0x0020 +#define MPC555_SERIAL_SCCxR1_ILIE 0x0010 +#define MPC555_SERIAL_SCCxR1_TE 0x0008 +#define MPC555_SERIAL_SCCxR1_RE 0x0004 +#define MPC555_SERIAL_SCCxR1_RWU 0x0002 +#define MPC555_SERIAL_SCCxR1_SBK 0x0001 + +#define MPC555_SERIAL_SCxSR_TDRE 0x0100 +#define MPC555_SERIAL_SCxSR_TC 0x0080 +#define MPC555_SERIAL_SCxSR_RDRF 0x0040 +#define MPC555_SERIAL_SCxSR_RAF 0x0020 +#define MPC555_SERIAL_SCxSR_IDLE 0x0010 +#define MPC555_SERIAL_SCxSR_OR 0x0008 +#define MPC555_SERIAL_SCxSR_NF 0x0004 +#define MPC555_SERIAL_SCxSR_FE 0x0002 +#define MPC555_SERIAL_SCxSR_PF 0x0001 + +// The available baud rates +// These are calculated for a busclock of 40 MHz +// It is not necessary to let the compiler calculate these +// values, we did not provide clockfrequency as a configuarion +// option anyway. +static unsigned short select_baud[] = { + 0, // Unused + 0, // 50 bps unsupported + 0, // 75 bps unsupported + 0, // 110 bps unsupported + 0, // 134_5 bps unsupported + 0, // 150 bps unsupported + 0, // 200 bps unsupported + 4167, // 300 bps + 2083, // 600 bps + 1042, // 1200 bps + 0, // 1800 bps unsupported + 521, // 2400 bps + 0, // 3600 bps unsupported + 260, // 4800 bps + 0, // 7200 bps unsupported + 130, // 9600 bps + 87, // 14400 bps + 65, // 19200 bps + 33, // 38400 bps + 22, // 57600 bps + 11, // 115200 bps + 0 // 230400 bps unsupported +}; + +static unsigned char select_word_length[] = { + 0, // 5 bits / word (char) not supported + 0, // 6 bits / word (char) not supported + 7, // 7 bits / word (char) ->> 7 bits per frame + 8 // 8 bits / word (char) ->> 8 bits per frame +}; + +static unsigned char select_stop_bits[] = { + 0, + 1, // 1 stop bit ->> 1 bit per frame + 0, // 1.5 stop bit not supported + 2 // 2 stop bits ->> 2 bits per frame +}; + +static unsigned char select_parity[] = { + 0, // No parity ->> 0 bits per frame + 1, // Even parity ->> 1 bit per frame + 1, // Odd parityv ->> 1 bit per frame + 0, // Mark parity not supported + 0, // Space parity not supported +}; + +#endif // CYGONCE_DEVS_SERIAL_POWERPC_MPC555_SERIAL_H + +// EOF mpc555_serial.h diff --git a/packages/devs/serial/powerpc/mpc555/v2_0/src/mpc555_serial_with_ints.c b/packages/devs/serial/powerpc/mpc555/v2_0/src/mpc555_serial_with_ints.c new file mode 100644 index 00000000..a2c94b64 --- /dev/null +++ b/packages/devs/serial/powerpc/mpc555/v2_0/src/mpc555_serial_with_ints.c @@ -0,0 +1,631 @@ +//========================================================================== +// +// mpc555_serial_with_ints.c +// +// PowerPC 5xx MPC555 Serial I/O Interface Module (interrupt driven) +// +//========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Bob Koninckx +// Contributors: +// Date: 2002-04-25 +// Purpose: MPC555 Serial I/O module (interrupt driven version) +// Description: +// +// +//####DESCRIPTIONEND#### +//========================================================================== +//---------------------------------- +// Includes and forward declarations +//---------------------------------- +#include +#include + +#include +#include +#include +#include +#include +#include + +// Only build this driver for the MPC555 based boards +#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC555 + +#include "mpc555_serial.h" + +//----------------- +// Type definitions +//----------------- +typedef struct mpc555_serial_info { + CYG_ADDRWORD base; // The base address of the serial port + CYG_WORD tx_interrupt_num; // trivial + CYG_WORD rx_interrupt_num; // trivial + cyg_priority_t tx_interrupt_priority; // trivial + cyg_priority_t rx_interrupt_priority; // trivial + bool tx_interrupt_enable; // tells if the transmit interrupt may be re-enabled + cyg_interrupt tx_interrupt; // the tx interrupt object + cyg_handle_t tx_interrupt_handle; // the tx interrupt handle + cyg_interrupt rx_interrupt; // the rx interrupt object + cyg_handle_t rx_interrupt_handle; // the rx interrupt handle +} mpc555_serial_info; + +//-------------------- +// Function prototypes +//-------------------- +static bool mpc555_serial_init(struct cyg_devtab_entry * tab); +static bool mpc555_serial_putc(serial_channel * chan, unsigned char c); +static Cyg_ErrNo mpc555_serial_lookup(struct cyg_devtab_entry ** tab, + struct cyg_devtab_entry * sub_tab, + const char * name); +static unsigned char mpc555_serial_getc(serial_channel *chan); +static Cyg_ErrNo mpc555_serial_set_config(serial_channel *chan, cyg_uint32 key, + const void *xbuf, cyg_uint32 *len); +static void mpc555_serial_start_xmit(serial_channel *chan); +static void mpc555_serial_stop_xmit(serial_channel *chan); + +// The interrupt servers +static cyg_uint32 mpc555_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data); +static cyg_uint32 mpc555_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void mpc555_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); +static void mpc555_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); + +//------------------------------------------- +// Register the device driver with the kernel +//------------------------------------------- +static SERIAL_FUNS(mpc555_serial_funs, + mpc555_serial_putc, + mpc555_serial_getc, + mpc555_serial_set_config, + mpc555_serial_start_xmit, + mpc555_serial_stop_xmit); + +//------------------- +// Device driver data +//------------------- +#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC555_SERIAL_A +static mpc555_serial_info mpc555_serial_info0 = {MPC555_SERIAL_BASE_A, + CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TX, + CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX, + CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TX_PRIORITY, + CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX_PRIORITY, + false}; +#if CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_A_BUFSIZE > 0 +static unsigned char mpc555_serial_out_buf0[CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_A_BUFSIZE]; +static unsigned char mpc555_serial_in_buf0[CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_A_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(mpc555_serial_channel0, + mpc555_serial_funs, + mpc555_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_A_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &mpc555_serial_out_buf0[0], + sizeof(mpc555_serial_out_buf0), + &mpc555_serial_in_buf0[0], + sizeof(mpc555_serial_in_buf0)); +#else +static SERIAL_CHANNEL(mpc555_serial_channel0, + mpc555_serial_funs, + mpc555_serial_info0, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_A_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT); +#endif +DEVTAB_ENTRY(mpc555_serial_io0, + CYGDAT_IO_SERIAL_POWERPC_MPC555_SERIAL_A_NAME, + 0, // does not depend on a lower level device driver + &cyg_io_serial_devio, + mpc555_serial_init, + mpc555_serial_lookup, + &mpc555_serial_channel0); +#endif // ifdef CYGPKG_IO_SERIAL_POWERPC_MPC555_SERIAL_A + +#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC555_SERIAL_B +static mpc555_serial_info mpc555_serial_info1 = {MPC555_SERIAL_BASE_B, + CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TX, + CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RX, + CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TX_PRIORITY, + CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RX_PRIORITY, + false}; +#if CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_B_BUFSIZE > 0 +static unsigned char mpc555_serial_out_buf1[CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_B_BUFSIZE]; +static unsigned char mpc555_serial_in_buf1[CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_B_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(mpc555_serial_channel1, + mpc555_serial_funs, + mpc555_serial_info1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_B_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &mpc555_serial_out_buf1[0], + sizeof(mpc555_serial_out_buf1), + &mpc555_serial_in_buf1[0], + sizeof(mpc555_serial_in_buf1)); +#else +static SERIAL_CHANNEL(mpc555_serial_channel1, + mpc555_serial_funs, + mpc555_serial_info1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_MPC555_SERIAL_B_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT); +#endif +DEVTAB_ENTRY(mpc555_serial_io1, + CYGDAT_IO_SERIAL_POWERPC_MPC555_SERIAL_B_NAME, + 0, // does not depend on a lower level device driver + &cyg_io_serial_devio, + mpc555_serial_init, + mpc555_serial_lookup, + &mpc555_serial_channel1); +#endif // ifdef CYGPKG_IO_SERIAL_POWERPC_MPC555_SERIAL_B + +//----------------------------- +// Device driver implementation +//----------------------------- + +// The arbitration isr. +// I think this is the best place to implement it. The device driver is the only place +// in the code where the knowledge is present about how the hardware is used +// +// Always check receive interrupts. Some rom monitor might be waiting for CTRL-C +static cyg_uint32 hal_arbitration_isr_qsci(CYG_ADDRWORD a_vector, CYG_ADDRWORD a_data) +{ + cyg_uint16 status; + cyg_uint16 control; + + HAL_READ_UINT16(CYGARC_REG_IMM_SC1SR, status); + HAL_READ_UINT16(CYGARC_REG_IMM_SCC1R1, control); + if((status & CYGARC_REG_IMM_SCxSR_RDRF) && (control & CYGARC_REG_IMM_SCCxR1_RIE)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX); +#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC555_SERIAL_A // Do not waist time on unused hardware + if((status & CYGARC_REG_IMM_SCxSR_TDRE) && (control & CYGARC_REG_IMM_SCCxR1_TIE)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TX); +// Don't waist time on unused interrupts +// if((status & CYGARC_REG_IMM_SCxSR_TC) && (control & CYGARC_REG_IMM_SCCxR1_TCIE)) +// return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TXC); +// Don't waist time on unused interrupts +// if((status & CYGARC_REG_IMM_SCxSR_IDLE) && (control & CYGARC_REG_IMM_SCCxR1_ILIE)) +// return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_IDLE); +#endif + + HAL_READ_UINT16(CYGARC_REG_IMM_SC2SR, status); + HAL_READ_UINT16(CYGARC_REG_IMM_SCC2R1, control); + if((status & CYGARC_REG_IMM_SCxSR_RDRF) && (control & CYGARC_REG_IMM_SCCxR1_RIE)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RX); +#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC555_SERIAL_B // Do not waist time on unused hardware + if((status & CYGARC_REG_IMM_SCxSR_TDRE) && (control & CYGARC_REG_IMM_SCCxR1_TIE)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TX); +// Don't waist time on unused interrupts +// if((status & CYGARC_REG_IMM_SCxSR_TC) && (control & CYGARC_REG_IMM_SCCxR1_TCIE)) +// return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXC); +// Don't waist time on unused interrupts +// if((status & CYGARC_REG_IMM_SCxSR_IDLE) && (control & CYGARC_REG_IMM_SCCxR1_ILIE)) +// return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_IDLE); + +#if 0 + // The driver doesn't use the queue operation of the hardware (It would need different code for serial 1 and 2 + // since oly one port supports queue mode). So the following is not needed. + // Leave it there. It is easyer for later implementations to remove the comments than finding + // out how the hardware works again. + HAL_READ_UINT16(CYGARC_REG_IMM_QSCI1SR, status); + HAL_READ_UINT16(CYGARC_REG_IMM_QSCI1CR, control); + if((status & CYGARC_REG_IMM_QSCI1SR_QTHF) && (control & CYGARC_REG_IMM_QSCI1CR_QTHFI)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RXQTHF); + if((status & CYGARC_REG_IMM_QSCI1SR_QBHF) && (control & CYGARC_REG_IMM_QSCI1CR_QBHFI)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RXQBHF); + if((status & CYGARC_REG_IMM_QSCI1SR_QTHE) && (control & CYGARC_REG_IMM_QSCI1CR_QTHEI)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXQTHE); + if((status & CYGARC_REG_IMM_QSCI1SR_QBHE) && (control & CYGARC_REG_IMM_QSCI1CR_QBHEI)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXQBHE); + + cyg_uint16 status; + cyg_uint16 control; + + HAL_READ_UINT16(CYGARC_REG_IMM_SPSR, status); + HAL_READ_UINT16(CYGARC_REG_IMM_SPCR2, control); + if((status & CYGARC_REG_IMM_SPSR_SPIF) && (control & CYGARC_REG_IMM_SPCR2_SPIFIE)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_FI); + + HAL_READ_UINT16(CYGARC_REG_IMM_SPCR3, control); + if((status & CYGARC_REG_IMM_SPSR_MODF) && (control & CYGARC_REG_IMM_SPCR3_HMIE)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_MODF); + + if((status & CYGARC_REG_IMM_SPSR_HALTA) && (control & CYGARC_REG_IMM_SPCR3_HMIE)) + return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_HALTA); +#endif + +#endif + + return 0; +} + +//-------------------------------------------------------------------------------- +// Internal function to actually configure the hardware to desired baud rate, etc. +//-------------------------------------------------------------------------------- +static bool mpc555_serial_config_port(serial_channel * chan, cyg_serial_info_t * new_config, bool init) +{ + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)(chan->dev_priv); + + cyg_addrword_t port = mpc555_chan->base; + cyg_uint16 baud_rate = select_baud[new_config->baud]; + unsigned char frame_length = 1; // The start bit + + cyg_uint16 old_isrstate; + cyg_uint16 sccxr; + + if(!baud_rate) + return false; // Invalid baud rate selected + + if((new_config->word_length != CYGNUM_SERIAL_WORD_LENGTH_7) && + (new_config->word_length != CYGNUM_SERIAL_WORD_LENGTH_8)) + return false; // Invalid word length selected + + if((new_config->parity != CYGNUM_SERIAL_PARITY_NONE) && + (new_config->parity != CYGNUM_SERIAL_PARITY_EVEN) && + (new_config->parity != CYGNUM_SERIAL_PARITY_ODD)) + return false; // Invalid parity selected + + if((new_config->stop != CYGNUM_SERIAL_STOP_1) && + (new_config->stop != CYGNUM_SERIAL_STOP_2)) + return false; // Invalid stop bits selected + + frame_length += select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5]; + frame_length += select_stop_bits[new_config->stop]; + frame_length += select_parity[new_config->parity]; + + if((frame_length != 10) && (frame_length != 11)) + return false; // Invalid frame format selected + + // Disable port interrupts while changing hardware + HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + old_isrstate = sccxr; + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_LOOPS); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_WOMS); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_ILT); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PT); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PE); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_M); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_WAKE); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TE); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RE); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RWU); + old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_SBK); + sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TIE); + sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TCIE); + sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RIE); + sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_ILIE); + HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + + // Set databits, stopbits and parity. + HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + + if(frame_length == 11) + sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_M; + else + sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_M); + + switch(new_config->parity) + { + case CYGNUM_SERIAL_PARITY_NONE: + sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PE); + break; + case CYGNUM_SERIAL_PARITY_EVEN: + sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PE; + sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PT); + break; + case CYGNUM_SERIAL_PARITY_ODD: + sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PE; + sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PT; + break; + default: + break; + } + HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + + // Set baud rate. + baud_rate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR0_OTHR); + baud_rate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR0_LINKBD); + HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR0, sccxr); + sccxr &= ~(MPC555_SERIAL_SCCxR0_SCxBR); + sccxr |= baud_rate; + HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR0, sccxr); + + // Enable the device + HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + sccxr |= MPC555_SERIAL_SCCxR1_TE; + sccxr |= MPC555_SERIAL_SCCxR1_RE; + HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + + if(init) + { // enable the receiver interrupt + HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + sccxr |= MPC555_SERIAL_SCCxR1_RIE; + HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + } + else // Restore the old interrupt state + { + HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + sccxr |= old_isrstate; + HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr); + } + + if(new_config != &chan->config) + chan->config = *new_config; + + return true; +} + +//-------------------------------------------------------------- +// Function to initialize the device. Called at bootstrap time. +//-------------------------------------------------------------- +static hal_mpc5xx_arbitration_data arbiter; + +static bool mpc555_serial_init(struct cyg_devtab_entry * tab) +{ + serial_channel * chan = (serial_channel *)tab->priv; + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + + if(!mpc555_serial_config_port(chan, &chan->config, true)) + return false; + + (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices + if(chan->out_cbuf.len != 0) + { + arbiter.priority = CYGNUM_HAL_ISR_SOURCE_PRIORITY_QSCI; + arbiter.data = 0; + arbiter.arbiter = hal_arbitration_isr_qsci; + + // Install the arbitration isr, Make sure that is is not installed twice + hal_mpc5xx_remove_arbitration_isr(CYGNUM_HAL_ISR_SOURCE_PRIORITY_QSCI); + hal_mpc5xx_install_arbitration_isr(&arbiter); + + // Create the Tx interrupt, do not enable it yet + cyg_drv_interrupt_create(mpc555_chan->tx_interrupt_num, + mpc555_chan->tx_interrupt_priority, + (cyg_addrword_t)chan, // Data item passed to interrupt handler + mpc555_serial_tx_ISR, + mpc555_serial_tx_DSR, + &mpc555_chan->tx_interrupt_handle, + &mpc555_chan->tx_interrupt); + cyg_drv_interrupt_attach(mpc555_chan->tx_interrupt_handle); + + // Create the Rx interrupt, this can be safely unmasked now + cyg_drv_interrupt_create(mpc555_chan->rx_interrupt_num, + mpc555_chan->rx_interrupt_priority, + (cyg_addrword_t)chan, + mpc555_serial_rx_ISR, + mpc555_serial_rx_DSR, + &mpc555_chan->rx_interrupt_handle, + &mpc555_chan->rx_interrupt); + cyg_drv_interrupt_attach(mpc555_chan->rx_interrupt_handle); + cyg_drv_interrupt_unmask(mpc555_chan->rx_interrupt_num); + } + + return true; +} + +//---------------------------------------------------------------------- +// This routine is called when the device is "looked" up (i.e. attached) +//---------------------------------------------------------------------- +static Cyg_ErrNo mpc555_serial_lookup(struct cyg_devtab_entry ** tab, + struct cyg_devtab_entry * sub_tab, + const char * name) +{ + serial_channel * chan = (serial_channel *)(*tab)->priv; + (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices + + return ENOERR; +} + +//---------------------------------------------- +// Send a character to the device output buffer. +// Return 'true' if character is sent to device +//---------------------------------------------- +static bool mpc555_serial_putc(serial_channel * chan, unsigned char c) +{ + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + cyg_addrword_t port = mpc555_chan->base; + + cyg_uint16 scsr; + cyg_uint16 scdr; + + HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr); + if(scsr & MPC555_SERIAL_SCxSR_TDRE) + { // Ok, we have space, write the character and return success + scdr = (cyg_uint16)c; + HAL_WRITE_UINT16(port + MPC555_SERIAL_SCxDR, scdr); + return true; + } + else + // We cannot write to the transmitter, return failure + return false; +} + +//--------------------------------------------------------------------- +// Fetch a character from the device input buffer, waiting if necessary +//--------------------------------------------------------------------- +static unsigned char mpc555_serial_getc(serial_channel * chan) +{ + unsigned char c; + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + cyg_addrword_t port = mpc555_chan->base; + + cyg_uint16 scsr; + cyg_uint16 scdr; + + do { + HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr); + } while(!(scsr & MPC555_SERIAL_SCxSR_RDRF)); + + // Ok, data is received, read it out and return + HAL_READ_UINT16(port + MPC555_SERIAL_SCxDR, scdr); + c = (unsigned char)scdr; + + return c; +} + +//--------------------------------------------------- +// Set up the device characteristics; baud rate, etc. +//--------------------------------------------------- +static bool mpc555_serial_set_config(serial_channel * chan, cyg_uint32 key, + const void *xbuf, cyg_uint32 * len) +{ + switch(key) { + case CYG_IO_SET_CONFIG_SERIAL_INFO: + { + cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf; + if(*len < sizeof(cyg_serial_info_t)) { + return -EINVAL; + } + *len = sizeof(cyg_serial_info_t); + if(true != mpc555_serial_config_port(chan, config, false)) + return -EINVAL; + } + break; + default: + return -EINVAL; + } + return ENOERR; +} + +//------------------------------------- +// Enable the transmitter on the device +//------------------------------------- +static void mpc555_serial_start_xmit(serial_channel * chan) +{ + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + + mpc555_chan->tx_interrupt_enable = true; + cyg_drv_interrupt_unmask(mpc555_chan->tx_interrupt_num); + + // No need to call xmt_char, this will generate an interrupt immediately. +} + +//-------------------------------------- +// Disable the transmitter on the device +//-------------------------------------- +static void mpc555_serial_stop_xmit(serial_channel * chan) +{ + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + + cyg_drv_dsr_lock(); + mpc555_chan->tx_interrupt_enable = false; + cyg_drv_interrupt_mask(mpc555_chan->tx_interrupt_num); + cyg_drv_dsr_unlock(); +} + +//----------------------------------------- +// The low level transmit interrupt handler +//----------------------------------------- +static cyg_uint32 mpc555_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + serial_channel * chan = (serial_channel *)data; + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + + cyg_drv_interrupt_mask(mpc555_chan->tx_interrupt_num); + cyg_drv_interrupt_acknowledge(mpc555_chan->tx_interrupt_num); + + return CYG_ISR_CALL_DSR; // cause the DSR to run +} + +//---------------------------------------- +// The low level receive interrupt handler +//---------------------------------------- +static cyg_uint32 mpc555_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data) +{ + serial_channel * chan = (serial_channel *)data; + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + + cyg_drv_interrupt_mask(mpc555_chan->rx_interrupt_num); + cyg_drv_interrupt_acknowledge(mpc555_chan->rx_interrupt_num); + + return CYG_ISR_CALL_DSR; // cause the DSR to run +} + +//------------------------------------------ +// The high level transmit interrupt handler +//------------------------------------------ +static void mpc555_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + serial_channel * chan = (serial_channel *)data; + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + + (chan->callbacks->xmt_char)(chan); + if(mpc555_chan->tx_interrupt_enable) + cyg_drv_interrupt_unmask(mpc555_chan->tx_interrupt_num); +} + +//----------------------------------------- +// The high level receive interrupt handler +//----------------------------------------- +#define MPC555_SERIAL_SCxSR_ERRORS (MPC555_SERIAL_SCxSR_OR | \ + MPC555_SERIAL_SCxSR_NF | \ + MPC555_SERIAL_SCxSR_FE | \ + MPC555_SERIAL_SCxSR_PF) + +static void mpc555_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + serial_channel * chan = (serial_channel *)data; + mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv; + cyg_addrword_t port = mpc555_chan->base; + cyg_uint16 scdr; + cyg_uint16 scsr; + + // Allways read out the received character, in order to clear receiver flags + HAL_READ_UINT16(port + MPC555_SERIAL_SCxDR, scdr); + + HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr); + if(scsr & (cyg_uint16)MPC555_SERIAL_SCxSR_ERRORS) + { + scsr &= ~((cyg_uint16)MPC555_SERIAL_SCxSR_ERRORS); + HAL_WRITE_UINT16(port + MPC555_SERIAL_SCxSR, scsr); + } + else + { + (chan->callbacks->rcv_char)(chan, (cyg_uint8)scdr); + } + + cyg_drv_interrupt_unmask(mpc555_chan->rx_interrupt_num); +} + +#endif // CYGPKG_IO_SERIAL_POWERPC_MPC555 + +// EOF mpc555_serial_with_ints.c diff --git a/packages/devs/spi/arm/lpc2xxx/v2_0/ChangeLog b/packages/devs/spi/arm/lpc2xxx/v2_0/ChangeLog new file mode 100644 index 00000000..723c8bd2 --- /dev/null +++ b/packages/devs/spi/arm/lpc2xxx/v2_0/ChangeLog @@ -0,0 +1,35 @@ +2007-07-12 Hans Rosenfeld + + * lpc2xxx: driver for on-chip SPI units + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/spi/arm/lpc2xxx/v2_0/cdl/spi_lpc2xxx.cdl b/packages/devs/spi/arm/lpc2xxx/v2_0/cdl/spi_lpc2xxx.cdl new file mode 100644 index 00000000..80487e65 --- /dev/null +++ b/packages/devs/spi/arm/lpc2xxx/v2_0/cdl/spi_lpc2xxx.cdl @@ -0,0 +1,73 @@ +# ==================================================================== +# +# spi_lpc2xxx.cdl +# +# SPI driver for LPC2xxx +# +# ==================================================================== +#####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. +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Hans Rosenfeld +# Contributors: +# Date: 2007-07-12 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_SPI_ARM_LPC2XXX { + display "LPC2xxx SPI driver" + requires CYGPKG_HAL_ARM_LPC2XXX + + parent CYGPKG_IO_SPI + active_if CYGPKG_IO_SPI + + include_dir cyg/io + compile spi_lpc2xxx.cxx + + cdl_option CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS0 { + display "Enable SPI interface 0" + flavor bool + default_value 1 + description "The LPC2xxx controllers contain two SPI interfaces. + Enable this option to get support for SPI interface 0." + } + + cdl_option CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS1 { + display "Enable SPI interface 1" + flavor bool + default_value 1 + description "The LPC2xxx controllers contain two SPI interfaces. + Enable this option to get support for SPI interface 1." + } +} \ No newline at end of file diff --git a/packages/devs/spi/arm/lpc2xxx/v2_0/include/spi_lpc2xxx.h b/packages/devs/spi/arm/lpc2xxx/v2_0/include/spi_lpc2xxx.h new file mode 100644 index 00000000..c1507e70 --- /dev/null +++ b/packages/devs/spi/arm/lpc2xxx/v2_0/include/spi_lpc2xxx.h @@ -0,0 +1,105 @@ +#ifndef CYGONCE_DEVS_SPI_ARM_LPC2XXX_H +#define CYGONCE_DEVS_SPI_ARM_LPC2XXX_H + +//========================================================================== +// +// spi_lpc2xxx.h +// +// SPI driver for LPC2xxx +// +//========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Hans Rosenfeld +// Contributors: +// Date: 2007-07-12 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +#include +#include +#include + +struct spi_dev { + volatile cyg_uint32 spcr; + volatile cyg_uint32 spsr; + volatile cyg_uint32 spdr; + volatile cyg_uint32 spccr; + cyg_uint32 d1, d2, d3; + volatile cyg_uint32 spint; +}; + +typedef struct { + cyg_spi_bus spi_bus; + + cyg_interrupt spi_intr; + cyg_handle_t spi_hand; + cyg_vector_t spi_vect; + cyg_drv_mutex_t spi_lock; + cyg_drv_cond_t spi_wait; + + struct spi_dev *spi_dev; + + volatile cyg_uint32 count; + volatile const cyg_uint8 *tx; + volatile cyg_uint8 *rx; +} cyg_spi_lpc2xxx_bus_t; + +typedef struct { + cyg_spi_device spi_device; + + cyg_uint8 spi_cpha; + cyg_uint8 spi_cpol; + cyg_uint8 spi_lsbf; + cyg_uint32 spi_baud; + + void (*spi_cs)(int); +} cyg_spi_lpc2xxx_dev_t; + +#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS0 +externC cyg_spi_lpc2xxx_bus_t cyg_spi_lpc2xxx_bus0; +#endif + +#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS1 +externC cyg_spi_lpc2xxx_bus_t cyg_spi_lpc2xxx_bus1; +#endif + +#endif diff --git a/packages/devs/spi/arm/lpc2xxx/v2_0/src/spi_lpc2xxx.cxx b/packages/devs/spi/arm/lpc2xxx/v2_0/src/spi_lpc2xxx.cxx new file mode 100644 index 00000000..4c5c2d3c --- /dev/null +++ b/packages/devs/spi/arm/lpc2xxx/v2_0/src/spi_lpc2xxx.cxx @@ -0,0 +1,364 @@ +//========================================================================== +// +// spi_lpc2xxx.cxx +// +// SPI driver for LPC2xxx +// +//========================================================================== +//####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): Hans Rosenfeld +// Contributors: +// Date: 2007-07-12 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPI_SPCR_SPIE 0x80 +#define SPI_SPCR_LSBF 0x40 +#define SPI_SPCR_MSTR 0x20 +#define SPI_SPCR_CPOL 0x10 +#define SPI_SPCR_CPHA 0x08 + +#define SPI_SPSR_SPIF 0x80 +#define SPI_SPSR_WCOL 0x40 +#define SPI_SPSR_ROVR 0x20 +#define SPI_SPSR_MODF 0x10 +#define SPI_SPSR_ABRT 0x08 + +#define SPI_SPINT 0x01 + +#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS0 +cyg_spi_lpc2xxx_bus_t cyg_spi_lpc2xxx_bus0; +CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_lpc2xxx_dev_t, 0); +#endif +#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS1 +cyg_spi_lpc2xxx_bus_t cyg_spi_lpc2xxx_bus1; +CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_lpc2xxx_dev_t, 1); +#endif + +/* + * Interrupt routine + * read & write the next byte until count reaches zero + */ +static cyg_uint32 +spi_lpc2xxx_isr(cyg_vector_t vec, cyg_addrword_t data) +{ + cyg_spi_lpc2xxx_bus_t *bus = (cyg_spi_lpc2xxx_bus_t *) data; + cyg_uint8 tmp; + + tmp = bus->spi_dev->spsr; + + if(tmp & SPI_SPSR_MODF) + bus->spi_dev->spcr = bus->spi_dev->spcr | SPI_SPCR_MSTR; + + tmp = bus->spi_dev->spdr; + + if(bus->count) { + if(bus->rx) + *bus->rx++ = tmp; + if(--bus->count) { + bus->spi_dev->spint = SPI_SPINT; + bus->spi_dev->spdr = bus->tx ? *bus->tx++ : 0; + cyg_drv_interrupt_acknowledge(bus->spi_vect); + return CYG_ISR_HANDLED; + } + } + + bus->count = 0; + bus->tx = NULL; + bus->rx = NULL; + + bus->spi_dev->spint = SPI_SPINT; + cyg_drv_interrupt_acknowledge(bus->spi_vect); + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; +} + +static void +spi_lpc2xxx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) +{ + cyg_drv_cond_signal(&((cyg_spi_lpc2xxx_bus_t *) data)->spi_wait); +} + + +/* + * Configure bus for a specific baud rate + */ +static void +spi_lpc2xxx_baud(cyg_spi_lpc2xxx_bus_t *bus, cyg_uint32 baud) +{ + cyg_uint32 ccr = 8; + + if(baud) { + ccr = (CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED + / CYGNUM_HAL_ARM_LPC2XXX_VPBDIV) / baud; + if(((CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED + / CYGNUM_HAL_ARM_LPC2XXX_VPBDIV) / ccr) > baud) + ccr++; + ccr++; + ccr &= 0xfe; + } + + bus->spi_dev->spccr = ccr < 8 ? 8 : ccr; +} + +/* + * get/set configuration + */ +static int +spi_lpc2xxx_get_config(cyg_spi_device *device, cyg_uint32 key, void *buf, + cyg_uint32 *len) +{ + cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device; + + switch(key) { + case CYG_IO_GET_CONFIG_SPI_CLOCKRATE: + if(*len == sizeof(cyg_uint32)) { + cyg_uint32 *b = (cyg_uint32 *) buf; + *b = dev->spi_baud; + } else return -EINVAL; + break; + default: + return -EINVAL; + } + + return ENOERR; +} + +static int +spi_lpc2xxx_set_config(cyg_spi_device *device, cyg_uint32 key, const void *buf, + cyg_uint32 *len) +{ + cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device; + + switch(key) { + case CYG_IO_GET_CONFIG_SPI_CLOCKRATE: + if(*len == sizeof(cyg_uint32)) { + dev->spi_baud = * (cyg_uint32 *) buf; + spi_lpc2xxx_baud((cyg_spi_lpc2xxx_bus_t *) dev->spi_device.spi_bus, + dev->spi_baud); + } + else return -EINVAL; + break; + default: + return -EINVAL; + } + + return ENOERR; +} + + +/* + * Begin transaction + * configure bus for device and drive CS by calling device cs() function + */ +static void +spi_lpc2xxx_begin(cyg_spi_device *device) +{ + cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device; + cyg_spi_lpc2xxx_bus_t *bus = + (cyg_spi_lpc2xxx_bus_t *) dev->spi_device.spi_bus; + + cyg_uint8 cr = + (dev->spi_cpha ? SPI_SPCR_CPHA : 0) | + (dev->spi_cpol ? SPI_SPCR_CPOL : 0) | + (dev->spi_lsbf ? SPI_SPCR_LSBF : 0); + + bus->spi_dev->spcr = SPI_SPCR_MSTR | cr; + + spi_lpc2xxx_baud(bus, dev->spi_baud); + + dev->spi_cs(1); +} + + +/* + * Transfer a buffer to a device, + * fill another buffer with data from the device + */ +static void +spi_lpc2xxx_transfer(cyg_spi_device *device, cyg_bool polled, cyg_uint32 count, + const cyg_uint8 *tx_data, cyg_uint8 *rx_data, + cyg_bool drop_cs) +{ + cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device; + cyg_spi_lpc2xxx_bus_t *bus = + (cyg_spi_lpc2xxx_bus_t *) dev->spi_device.spi_bus; + cyg_uint8 tmp; + + if(!count) return; + + if(!polled) { + bus->count = count; + bus->tx = tx_data; + bus->rx = rx_data; + + bus->spi_dev->spcr |= SPI_SPCR_SPIE; + bus->spi_dev->spdr = bus->tx ? *bus->tx++ : 0; + + cyg_drv_mutex_lock(&bus->spi_lock); + cyg_drv_dsr_lock(); + cyg_drv_interrupt_unmask(bus->spi_vect); + while(bus->count) + cyg_drv_cond_wait(&bus->spi_wait); + cyg_drv_interrupt_mask(bus->spi_vect); + cyg_drv_dsr_unlock(); + cyg_drv_mutex_unlock(&bus->spi_lock); + } else do { + bus->spi_dev->spdr = tx_data ? *tx_data++ : 0; + while(!(bus->spi_dev->spsr & SPI_SPSR_SPIF)); + tmp = bus->spi_dev->spdr; + if(rx_data) + *rx_data++ = tmp; + count--; + } while(count); + + if(drop_cs) + dev->spi_cs(0); + + return; +} + + +/* + * Tick + */ +static void +spi_lpc2xxx_tick(cyg_spi_device *device, cyg_bool polled, cyg_uint32 count) +{ + spi_lpc2xxx_transfer(device, polled, count, NULL, NULL, false); +} + + +/* + * End transaction + * disable SPI bus, drop CS, reset transfer variables + */ +static void +spi_lpc2xxx_end(cyg_spi_device *device) +{ + cyg_spi_lpc2xxx_dev_t *dev = (cyg_spi_lpc2xxx_dev_t *) device; + cyg_spi_lpc2xxx_bus_t *bus = + (cyg_spi_lpc2xxx_bus_t *) dev->spi_device.spi_bus; + + bus->spi_dev->spcr = 0; + dev->spi_cs(0); + + bus->count = 0; + bus->tx = NULL; + bus->rx = NULL; +} + + +/* + * Driver & bus initialization + */ +static void +spi_lpc2xxx_init_bus(cyg_spi_lpc2xxx_bus_t *bus, + cyg_addrword_t dev, + cyg_vector_t vec) +{ + bus->spi_bus.spi_transaction_begin = spi_lpc2xxx_begin; + bus->spi_bus.spi_transaction_transfer = spi_lpc2xxx_transfer; + bus->spi_bus.spi_transaction_tick = spi_lpc2xxx_tick; + bus->spi_bus.spi_transaction_end = spi_lpc2xxx_end; + bus->spi_bus.spi_get_config = spi_lpc2xxx_get_config; + bus->spi_bus.spi_set_config = spi_lpc2xxx_set_config; + CYG_SPI_BUS_COMMON_INIT(&bus->spi_bus); + + cyg_drv_mutex_init(&bus->spi_lock); + cyg_drv_cond_init(&bus->spi_wait, &bus->spi_lock); + + bus->spi_dev = (struct spi_dev *) dev; + bus->spi_vect = vec; + cyg_drv_interrupt_create( + vec, 0, (cyg_addrword_t) bus, + &spi_lpc2xxx_isr, &spi_lpc2xxx_dsr, + &bus->spi_hand, &bus->spi_intr); + cyg_drv_interrupt_attach(bus->spi_hand); +} + +/* + * initialization class + */ +class cyg_spi_lpc2xxx_init_class { +public: + cyg_spi_lpc2xxx_init_class(void) { + cyg_uint32 addr, tmp; + +#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS0 + addr = (CYGARC_HAL_LPC2XXX_REG_PIN_BASE + + CYGARC_HAL_LPC2XXX_REG_PINSEL0); + HAL_READ_UINT32(addr, tmp); + tmp |= 0x5500; + HAL_WRITE_UINT32(addr, tmp); + + spi_lpc2xxx_init_bus(&cyg_spi_lpc2xxx_bus0, + CYGARC_HAL_LPC2XXX_REG_SPI0_BASE, + CYGNUM_HAL_INTERRUPT_SPI0); +#endif +#ifdef CYGPKG_DEVS_SPI_ARM_LPC2XXX_BUS1 + addr = (CYGARC_HAL_LPC2XXX_REG_PIN_BASE + + CYGARC_HAL_LPC2XXX_REG_PINSEL1); + HAL_READ_UINT32(addr, tmp); + tmp |= 0x2a8; + HAL_WRITE_UINT32(addr, tmp); + spi_lpc2xxx_init_bus(&cyg_spi_lpc2xxx_bus1, + CYGARC_HAL_LPC2XXX_REG_SPI1_BASE, + CYGNUM_HAL_INTERRUPT_SPI1); +#endif + } +}; + +static cyg_spi_lpc2xxx_init_class spi_lpc2xxx_init + CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO); + diff --git a/packages/devs/usb/at91/v2_0/ChangeLog b/packages/devs/usb/at91/v2_0/ChangeLog new file mode 100644 index 00000000..cd70abac --- /dev/null +++ b/packages/devs/usb/at91/v2_0/ChangeLog @@ -0,0 +1,120 @@ +2007-11-20 Andrew Lunn + + * cdl/usbs_at91.cdl: Fixed typos in + CYGNUM_DEVS_USB_AT91_GPIO_PULLUP_INVERTED and + CYGNUM_DEVS_USB_AT91_GPIO_READ_POWER_INVERTED. Fixing the typo. + + * src/usbs_at91.c (usbs_at91_set_pullup): Change the logic so that + CYGNUM_DEVS_USB_AT91_GPIO_PULLUP_INVERTED does actually cause an + invert when set true. + +2006-09-07 John Eigelaar + + * cdl/usbs_at91.c: Read actual EP addresses from the EP configuartion + rather than relying on the order in the configuration list. + +2006-06-06 Andrew Lunn + + * cdl/usbs_at91.cdl: Allow EP0 to be enabled when there are no + slave clients. + +2006-05-25 Andrew Lunn + + * src/usbs_at91_data.cxx: Change the initialization priority. The + USB tty driver is initialized at priority CYG_INIT_IO, so the USB + device has to be initialized before that. + +2006-05-19 Andrew Lunn + + * src/usbs_at91.c: Rework pullup and power dectect to use the AT91 + GPIO macros. + +2006-05-07 Andrew Lunn + + * Included into eCos anonymous CVS. + + Note: There appears to be a hardware bug with OUT transfers. It + appears that after resetting the endpoint, the first OUT transfer + does not trigger a receive interrupt. The BK0 bit is not set, + however the number of bytes in the receiver FIFO is correct. The + second OUT transfer causes both BK0 and BK1 bits to be set and an + interrupt generated. Currently no workaround is used to correct + this behavoiour. + +2006-04-23 Andrew Lunn + + * src/usbs_at91.c: Endpoint 3 can send upto 64 bytes at a time, + not 8. + +2006-04-20 Andrew Lunn + + * src/usbs_at91.c (usbs_at91_control_data_sent): Send a zero byte + packet when the transfer is an exact multiple of the endpoint + buffer size. + +2006-04-16 Andrew Lunn + + * src/usbs_at91.c (usbs_testing_endpoints): Added support for the + USB testcase framework by exporting what endpoint we have. + * src/usbs_at91.c (usbs_at91_control_setup): Make requests other + than standard requests work, eg CLASS, VENDOR etc. + * src/usbs_at91.c (usbs_at91_handle_reset): Configure the endpoint + hardware using the configuration information. + * src/usbs_at91.c (usbs_at91_control_data_sent): Transaction is + complete when the buffer is empty _and_ there is no refill + function defined. + +2006-03-10 Oliver Munz + + * CDL-Update for PLL-Freuenzy. + +2006-03-06 Oliver Munz + + * USB device driver work finished - haha. + + What's missing: + The set_... and get_freature-host-commands are not implemented yet. + The dynamical configuration of the data-endpoints is not reflectet in + the "usbs.h" API. + Isochronus transfer is not implemented. + Polling routines are not implemented. + USB-Tests are not done. + The PowerDetectPin is not used for the state. + AT91SAM7X's are not supported at the moment. + + But it works for me... + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/usb/at91/v2_0/cdl/usbs_at91.cdl b/packages/devs/usb/at91/v2_0/cdl/usbs_at91.cdl new file mode 100644 index 00000000..040a2b17 --- /dev/null +++ b/packages/devs/usb/at91/v2_0/cdl/usbs_at91.cdl @@ -0,0 +1,210 @@ +# ==================================================================== +# +# usbs_at91.cdl +# +# USB device driver for the ATMEL AT91 family of processors. +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2006 eCosCentric +## Copyright (C) 2006 Andrew Lunn +## +## 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): Oliver Munz, Andrew Lunn +# Original data: bartv +# Contributors: +# Date: 2006-02-25 +# +#####DESCRIPTIONEND#### +# ==================================================================== + +cdl_package CYGPKG_DEVS_USB_AT91 { + display "Atmel AT91 USB Device Driver" + include_dir "cyg/io/usb" + parent CYGPKG_IO_USB + implements CYGHWR_IO_USB_SLAVE + + cdl_interface CYGINT_DEVS_USB_AT91_HAS_USB { + description " + This interface is implemented by HALs for devices which have + the USB hardware." + } + + description " + This package provides a suitable eCos device driver + for AT91 USB. + In this version the driver will support the AT91SAM7S. + Other AT92 devices may work, but have not been tested. + The Driver needs 48, 96 or 192MHz plus minus 0.25%. + Buffers are allocated only in the higher level. There + is no need to configure the endpoints in this CDL, because + they will be configured dynamical at the set_configuration + call from the host... + The endpoints 1..3 can be configured as bulk or interrupt + IN or OUT endpoint. Isochronous transfer is not supported." + + cdl_component CYGFUN_DEVS_USB_AT91_EP0 { + display "Support the control endpoint 0" + flavor bool + default_value CYGINT_IO_USB_SLAVE_CLIENTS + requires CYGPKG_IO_USB CYGPKG_IO_USB_SLAVE + requires { + ((CYGNUM_HAL_ARM_AT91_CLOCK_SPEED < 48120000 && + CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 47880000) || + (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED < 96240000 && + CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 95760000)) + } + + active_if CYGINT_DEVS_USB_AT91_HAS_USB + implements CYGHWR_IO_USB_SLAVE_OUT_ENDPOINTS + implements CYGHWR_IO_USB_SLAVE_IN_ENDPOINTS + + compile usbs_at91.c + compile -library=libextras.a usbs_at91_data.cxx + description " + Enable support for endpoint 0. If this support is disabled + then the entire USB port is unusable." + + cdl_option CYGDAT_DEVS_USB_AT91_GPIO_SET_PULLUP_PIN { + display "PIO-Pin who controls the pullup resistor" + flavor data + default_value { "AT91_GPIO_PA16" } + description " + Every GPIO pin is able to do it. If you don't need + a pin because your HW has the pullup fixed wired + then select NONE" + } + + cdl_option CYGNUM_DEVS_USB_AT91_GPIO_SET_PULLUP_INVERTED { + display "Has the signal to be inverted?" + flavor bool + default_value 1 + description " + This option indicates that the pullup pin should + be inverted. ie VDD is active, VCC is inactive. For the + AT91SAM7SEK it needs to be inverted, hence this default." + } + + cdl_option CYGDAT_DEVS_USB_AT91_GPIO_READ_POWER_PIN { + display "PIO-Pin who see the USB-Power" + flavor data + default_value { "AT91_GPIO_PA13"} + description " + Every GPIO pin is able to do it. If you don't need + a pin then select NONE" + } + + cdl_option CYGNUM_DEVS_USB_AT91_GPIO_READ_POWER_INVERTED { + display "Has the signal to be inverted?" + flavor bool + default_value 0 + description " + This option indicates that the power detect pin should + be inverted. ie VDD is active, VCC is inactive." + } + } + + cdl_component CYGPKG_DEVS_USB_AT91_DEVTAB_ENTRIES { + display "Provide a devtab entry for endpoints" + active_if CYGFUN_DEVS_USB_AT91_EP0 + default_value 0 + description " + This component controls if /dev/usb entries will be created." + + cdl_option CYGVAR_DEVS_USB_AT91_EP0_DEVTAB_ENTRY { + display "Provide a devtab entry for endpoint 0" + flavor bool + default_value 0 + requires CYGPKG_IO + description " + If endpoint 0 will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and ioctl calls then a devtab entry is needed." + } + + cdl_option CYGVAR_DEVS_USB_AT91_EP1_DEVTAB_ENTRY { + display "Provide a devtab entry for endpoint 1" + flavor bool + default_value 1 + requires CYGPKG_IO + description " + If this endpoint will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and read calls then a devtab entry is needed." + } + + cdl_option CYGVAR_DEVS_USB_AT91_EP2_DEVTAB_ENTRY { + display "Provide a devtab entry for endpoint 2" + flavor bool + default_value 1 + requires CYGPKG_IO + description " + If this endpoint will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and read calls then a devtab entry is needed." + } + + cdl_option CYGVAR_DEVS_USB_AT91_EP3_DEVTAB_ENTRY { + display "Provide a devtab entry for endpoint 3" + flavor bool + default_value 1 + requires CYGPKG_IO + description " + If this endpoint will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and read calls then a devtab entry is needed." + } + + cdl_option CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME { + display "Base name for devtab entries" + flavor data + default_value { "\"/dev/usbs\"" } + description " + If the uAT91 USB device driver package provides devtab + entries for any of the endpoints then this option gives + control over the names of these entries. By default the + endpoints will be called \"/dev/usbs0c\", \"/dev/usbs3w\" + and \"/dev/usbs4r\" (assuming all three endpoints are + enabled. The common part \"/dev/usbs\" is determined + by this configuration option. It may be necessary to + change this if there are multiple USB slave-side + devices on the target hardware to prevent a name clash." + } + } +} diff --git a/packages/devs/usb/at91/v2_0/include/usbs_at91.h b/packages/devs/usb/at91/v2_0/include/usbs_at91.h new file mode 100644 index 00000000..3554c435 --- /dev/null +++ b/packages/devs/usb/at91/v2_0/include/usbs_at91.h @@ -0,0 +1,63 @@ +#ifndef CYGONCE_USBS_AT91_H +#define CYGONCE_USBS_AT91_H +//========================================================================== +// +// include/usbs_at91.h +// +// The interface exported by the AT91 USB device driver +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric Ltd +// Copyright (C) 2007 Andrew Lunn +// +// 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): Oliver Munz +// Contributors: bartv +// Date: 2006-02-25 +// Purpose: +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#define AT91_USB_ENDPOINTS 4 + +extern usbs_control_endpoint usbs_at91_ep0; +extern usbs_rx_endpoint usbs_at91_ep1; +extern usbs_rx_endpoint usbs_at91_ep2; +extern usbs_rx_endpoint usbs_at91_ep3; + +extern void usbs_at91_endpoint_init(usbs_rx_endpoint * pep, + cyg_uint8 endpoint_type, cyg_bool enable); +#endif /* CYGONCE_USBS_AT91_H */ diff --git a/packages/devs/usb/at91/v2_0/src/bitops.h b/packages/devs/usb/at91/v2_0/src/bitops.h new file mode 100644 index 00000000..e23482a3 --- /dev/null +++ b/packages/devs/usb/at91/v2_0/src/bitops.h @@ -0,0 +1,97 @@ +#ifndef CYGONCE_USBS_AT91_BITOPS_H +#define CYGONCE_USBS_AT91_BITOPS_H + +//========================================================================== +// +// bitops.h +// +// Hardware Bit manipulation macros for the AT91 USB device +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2002 Bart Veer +// 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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Oliver Munz +// Contributors: bartv +// Date: 2006-02-22 +// +//####DESCRIPTIONEND#### +//========================================================================== + +// Set the given bits in a device register +#define SET_BITS(_register_, _bits_) \ + CYG_MACRO_START \ + cyg_uint32 _value_; \ + HAL_READ_UINT32(_register_, _value_); \ + _value_ |= _bits_; \ + HAL_WRITE_UINT32(_register_, _value_); \ + CYG_MACRO_END + +// Clear the given bits in a device register +#define CLEAR_BITS(_register_, _bits_) \ + CYG_MACRO_START \ + cyg_uint32 _value_; \ + HAL_READ_UINT32(_register_, _value_); \ + _value_ &= ~_bits_; \ + HAL_WRITE_UINT32(_register_, _value_); \ + CYG_MACRO_END + +#define BITS_ARE_SET(_register_, _bits) \ + bits_are_set(_register_, _bits) + +#define BITS_ARE_CLEARED(_register_, _bits) \ + bits_are_cleared(_register_, _bits) + +static inline cyg_bool +bits_are_set (cyg_addrword_t addr, cyg_uint32 bits) +{ + cyg_uint32 read; + + HAL_READ_UINT32 (addr, read); + + return (read & bits) == bits; +} + +static inline cyg_bool +bits_are_cleared (cyg_addrword_t addr, cyg_uint32 bits) +{ + cyg_uint32 read; + + HAL_READ_UINT32 (addr, read); + + return (read | ~bits) == ~bits; +} + + +#endif // CYGONCE_USBS_AT91_BITOPS_H + diff --git a/packages/devs/usb/at91/v2_0/src/usbs_at91.c b/packages/devs/usb/at91/v2_0/src/usbs_at91.c new file mode 100644 index 00000000..1cb77414 --- /dev/null +++ b/packages/devs/usb/at91/v2_0/src/usbs_at91.c @@ -0,0 +1,1408 @@ +//========================================================================== +// +// usbs_at91.c +// +// Driver for the AT91 USB device +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric +// Copyright (C) 2006 Andrew Lunn +// +// 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): Oliver Munz, +// Contributors: Andrew Lunn, bartv +// Date: 2006-02-22 +// +// This code implements support for the on-chip USB port on the AT91 +// family of processors. The code has been developed on the AT91SAM7S +// and may or may not work on other members of the AT91 family. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "bitops.h" + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#define AT91_UDP_CSR0 (AT91_UDP_CSR) +#define AT91_UDP_FDR0 (AT91_UDP_FDR) + +#define pIER (AT91_UDP + AT91_UDP_IER) +#define pIDR (AT91_UDP + AT91_UDP_IDR) +#define pISR (AT91_UDP + AT91_UDP_ISR) +#define pIMR (AT91_UDP + AT91_UDP_IMR) +#define pICR (AT91_UDP + AT91_UDP_ICR) + +#define pCSR0 (AT91_UDP + AT91_UDP_CSR0) +#define pFDR0 (AT91_UDP + AT91_UDP_FDR0) + +#define pCSRn(N) (pCSR0 + (N * 4)) +#define pFDRn(N) (pFDR0 + (N * 4)) + +#define AT91_UDP_ALLOWED_IRQs \ + (AT91_UDP_WAKEUP | AT91_UDP_ENDBUSRES | AT91_UDP_EXTRSM | \ + AT91_UDP_RXRSM | AT91_UDP_RXSUSP | AT91_UDP_EPINT0 | \ + AT91_UDP_EPINT1 | AT91_UDP_EPINT2 | AT91_UDP_EPINT3) + +#define THERE_IS_A_NEW_PACKET_IN_THE_UDP 0xffff + +// Fifo size for each end point. +static const cyg_uint16 usbs_at91_endpoint_fifo_size[AT91_USB_ENDPOINTS] = { + 8, + 64, + 64, + 64, +}; + +// Does an endpoint support ping pong buffering? +static const bool usbs_at91_endpoint_pingpong[AT91_USB_ENDPOINTS] = { + false, + true, + true, + false +}; + +static cyg_uint8 *usbs_at91_endpoint_pbegin[AT91_USB_ENDPOINTS] = + { 0, 0, 0, 0 }; +static cyg_uint8 *usbs_at91_endpoint_pend[AT91_USB_ENDPOINTS] = + { 0, 0 ,0, 0 }; +static bool usbs_at91_endpoint_bank1[AT91_USB_ENDPOINTS] = + { false, false, false, false }; +static cyg_uint16 usbs_at91_endpoint_bytes_in_fifo[AT91_USB_ENDPOINTS] = + { 0, 0, 0, 0 }; +static cyg_uint16 usbs_at91_endpoint_bytes_received[AT91_USB_ENDPOINTS] = + { THERE_IS_A_NEW_PACKET_IN_THE_UDP, THERE_IS_A_NEW_PACKET_IN_THE_UDP, + THERE_IS_A_NEW_PACKET_IN_THE_UDP, THERE_IS_A_NEW_PACKET_IN_THE_UDP}; + +static cyg_interrupt usbs_at91_intr_data; +static cyg_handle_t usbs_at91_intr_handle; + +static void usbs_at91_ep0_start(usbs_control_endpoint *); +static void usbs_at91_poll(usbs_control_endpoint *); + +static void usbs_at91_endpoint_start(usbs_rx_endpoint * pep); +static void usbs_at91_endpoint_set_halted(usbs_rx_endpoint * pep, + cyg_bool new_value); +void usbs_at91_endpoint_init(usbs_rx_endpoint * pep, + cyg_uint8 endpoint_type, + cyg_bool enable); + +// Endpoint 0, the control endpoint, structure. +usbs_control_endpoint usbs_at91_ep0 = { + // The hardware does not distinguish between detached, attached and powered. + state: USBS_STATE_POWERED, + enumeration_data: (usbs_enumeration_data *) 0, + start_fn: usbs_at91_ep0_start, + poll_fn: usbs_at91_poll, + interrupt_vector: CYGNUM_HAL_INTERRUPT_UDP, + control_buffer: {0, 0, 0, 0, 0, 0, 0, 0}, + state_change_fn: (void (*) (usbs_control_endpoint *, + void *, usbs_state_change, int)) 0, + state_change_data: (void *) 0, + standard_control_fn: (usbs_control_return (*) + (usbs_control_endpoint *, void *)) 0, + standard_control_data: (void *) 0, + class_control_fn: (usbs_control_return (*) + (usbs_control_endpoint *, void *)) 0, + class_control_data: (void *) 0, + vendor_control_fn: (usbs_control_return (*) + (usbs_control_endpoint *, void *)) 0, + vendor_control_data: (void *) 0, + reserved_control_fn: (usbs_control_return (*) + (usbs_control_endpoint *, void *)) 0, + reserved_control_data: (void *) 0, + buffer: (unsigned char *) 0, + buffer_size: 0, + fill_buffer_fn: (void (*)(usbs_control_endpoint *)) 0, + fill_data: (void *) 0, + fill_index: 0, + complete_fn: (usbs_control_return (*)(usbs_control_endpoint *, + int)) 0 +}; + +// Endpoint 1 receive control structure +usbs_rx_endpoint usbs_at91_ep1 = { + start_rx_fn: usbs_at91_endpoint_start, + set_halted_fn: usbs_at91_endpoint_set_halted, + complete_fn: (void (*)(void *, int)) 0, + complete_data: (void *) 0, + buffer: (unsigned char *) 0, + buffer_size: 0, + halted: 0, +}; + +// Endpoint 2 Receive control structure +usbs_rx_endpoint usbs_at91_ep2 = { + start_rx_fn: usbs_at91_endpoint_start, + set_halted_fn: usbs_at91_endpoint_set_halted, + complete_fn: (void (*)(void *, int)) 0, + complete_data: (void *) 0, + buffer: (unsigned char *) 0, + buffer_size: 0, + halted: 0, +}; + +// Endpoint 3 Receive control structure +usbs_rx_endpoint usbs_at91_ep3 = { + start_rx_fn: usbs_at91_endpoint_start, + set_halted_fn: usbs_at91_endpoint_set_halted, + complete_fn: (void (*)(void *, int)) 0, + complete_data: (void *) 0, + buffer: (unsigned char *) 0, + buffer_size: 0, + halted: 0, +}; + +// Array of end points. Used for translating end point pointer to an +// end point number +static const void *usbs_at91_endpoints[AT91_USB_ENDPOINTS] = { + (void *) &usbs_at91_ep0, + (void *) &usbs_at91_ep1, + (void *) &usbs_at91_ep2, + (void *) &usbs_at91_ep3 +}; + +// Convert an endpoint pointer to an endpoint number, using the array +// of endpoint structures +static int +usbs_at91_pep_to_number(const usbs_rx_endpoint * pep) +{ + int epn; + + for(epn=0; epn < AT91_USB_ENDPOINTS; epn++) { + if (pep == usbs_at91_endpoints[epn]) + return epn; + } + CYG_FAIL("Unknown endpoint"); + return 0; +} + +typedef enum ep0_low_level_status_t { + EP0_LL_IDLE = 0, + EP0_LL_REQUEST, + EP0_LL_SEND_READY, + EP0_LL_ACK, + EP0_LL_RECEIVE_READY, + EP0_LL_ISOERROR, + EP0_LL_STALL, + EP0_LL_SET_ADDRESS, +} ep0_low_level_status_t; + +// Enable/Disable interrupts for a specific endpoint. +static void +usbs_at91_endpoint_interrupt_enable (cyg_uint8 epn, bool enable) +{ + CYG_ASSERT (epn < AT91_USB_ENDPOINTS, "Invalid endpoint"); + + if (enable) { + HAL_WRITE_UINT32 (pIER, 1 << epn); + } else { + HAL_WRITE_UINT32 (pIDR, 1 << epn); + } +} + +static cyg_uint8 * +read_fifo_uint8 (cyg_uint8 * pdest, cyg_addrword_t psource, cyg_uint32 size) +{ + cyg_uint8 *preqbyte = pdest; + cyg_uint8 reqbyte; + + while (size--) { + HAL_READ_UINT8 (psource, reqbyte); + *preqbyte = reqbyte; + preqbyte++; + } + + return preqbyte; +} + +static cyg_uint8 * +write_fifo_uint8 (cyg_addrword_t pdest, cyg_uint8 * psource, + cyg_uint8 * psource_end) +{ + cyg_uint8 *preqbyte; + + for (preqbyte = psource; preqbyte < psource_end; preqbyte++) { + HAL_WRITE_UINT8 (pdest, (*preqbyte)); + } + + return preqbyte; +} + +/* Tell the host that the device is ready to start communication */ +static void +usbs_at91_set_pullup (bool set) +{ + +#ifndef CYGDAT_DEVS_USB_AT91_GPIO_SET_PULLUP_PIN_NONE + if ( +#ifdef CYGNUM_DEVS_USB_AT91_GPIO_SET_PULLUP_INVERTED + !set +#else + set +#endif + ) { + HAL_ARM_AT91_GPIO_SET(CYGDAT_DEVS_USB_AT91_GPIO_SET_PULLUP_PIN); + } else { + HAL_ARM_AT91_GPIO_RESET(CYGDAT_DEVS_USB_AT91_GPIO_SET_PULLUP_PIN); + } +#endif +} + +/* Is the USB powered? */ +bool +usbs_at91_read_power (void) +{ +#ifndef CYGDAT_DEVS_USB_AT91_GPIO_READ_POWER_PIN_NONE + cyg_bool state; + + HAL_ARM_AT91_GPIO_GET(CYGDAT_DEVS_USB_AT91_GPIO_READ_POWER_PIN, state); +#ifdef CYGNUM_DEVS_USB_AT91_GPIO_READ_POWER_INVERTED + return !state; +#else + return state; +#endif +#endif + return true; +} + +// Stop all transfers that are currently active. +static void +usbs_end_all_transfers (usbs_control_return returncode) +{ + cyg_uint32 epn; + usbs_rx_endpoint *pep; + + for (epn = 1; epn < AT91_USB_ENDPOINTS; epn++) { + if (BITS_ARE_SET (pIMR, 1 << epn)) { + // If the end point is transmitting, call the complete function + // to terminate to transfer + pep = (usbs_rx_endpoint *) usbs_at91_endpoints[epn]; + + if (pep->complete_fn) { + (*pep->complete_fn) (pep->complete_data, returncode); + } + // Disable interrupts from the endpoint + usbs_at91_endpoint_interrupt_enable (epn, false); + } + } +} + +// There has been a change in state. Update the end point. +static void +usbs_state_notify (usbs_control_endpoint * pcep) +{ + static int old_state = USBS_STATE_CHANGE_POWERED; + int state = pcep->state & USBS_STATE_MASK; + + if (pcep->state != old_state) { + usbs_end_all_transfers (-EPIPE); + switch (state) { + case USBS_STATE_DETACHED: + case USBS_STATE_ATTACHED: + case USBS_STATE_POWERED: + // Nothing to do + break; + case USBS_STATE_DEFAULT: + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_GLB_STATE, 0); + break; + case USBS_STATE_ADDRESSED: + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_GLB_STATE, AT91_UDP_GLB_FADDEN); + break; + case USBS_STATE_CONFIGURED: + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_GLB_STATE, AT91_UDP_GLB_CONFG); + break; + default: + CYG_FAIL("Unknown endpoint state"); + } + + if (pcep->state_change_fn) { + (*pcep->state_change_fn) (pcep, 0, pcep->state, old_state); + } + + old_state = pcep->state; + } +} + +static usbs_control_return +usbs_parse_host_get_command (usbs_control_endpoint * pcep) +{ + usbs_control_return retcode; + cyg_uint8 dev_req_type = + (((usb_devreq *) pcep->control_buffer)->type) & USB_DEVREQ_TYPE_MASK; + + switch (dev_req_type) { + case USB_DEVREQ_TYPE_STANDARD: + if (!pcep->standard_control_fn) { + return usbs_handle_standard_control (pcep); + } + + retcode = + (*pcep->standard_control_fn) (pcep, pcep->standard_control_data); + + if (retcode == USBS_CONTROL_RETURN_UNKNOWN) { + return usbs_handle_standard_control (pcep); + } + return retcode; + + case USB_DEVREQ_TYPE_CLASS: + if (!pcep->class_control_fn) { + return USBS_CONTROL_RETURN_STALL; + } + return (*pcep->class_control_fn) (pcep, pcep->class_control_data); + + case USB_DEVREQ_TYPE_VENDOR: + if (!pcep->class_control_fn) { + return USBS_CONTROL_RETURN_STALL; + } + return (*pcep->class_control_fn) (pcep, pcep->vendor_control_data); + + case USB_DEVREQ_TYPE_RESERVED: + if (!pcep->reserved_control_fn) { + return USBS_CONTROL_RETURN_STALL; + } + return (*pcep->reserved_control_fn) (pcep, pcep->reserved_control_data); + default: + return USBS_CONTROL_RETURN_STALL; + } +} + +static void +usbs_at91_endpoint_set_halted (usbs_rx_endpoint * pep, cyg_bool new_value) +{ + int epn = usbs_at91_pep_to_number(pep); + cyg_addrword_t pCSR = pCSRn(epn); + + cyg_drv_dsr_lock (); + + if (pep->halted != new_value) { + /* There is something is to do */ + pep->halted = new_value; + + if (new_value && BITS_ARE_SET (pIMR, 1 << epn)) { + /* Ready to transmit */ + if (pep->complete_fn) { + (*pep->complete_fn) (pep->complete_data, -EAGAIN); + } + usbs_at91_endpoint_interrupt_enable (epn, false); + SET_BITS (pCSR, AT91_UDP_CSR_FORCESTALL); + } else { + CLEAR_BITS (pCSR, AT91_UDP_CSR_FORCESTALL); + } + } + cyg_drv_dsr_unlock (); +} + +void +usbs_at91_endpoint_init (usbs_rx_endpoint * pep, cyg_uint8 endpoint_type, + cyg_bool enable) +{ + int epn = usbs_at91_pep_to_number(pep); + cyg_addrword_t pCSR = pCSRn(epn); + + CYG_ASSERT (AT91_USB_ENDPOINTS > epn, "Invalid end point"); + + usbs_at91_endpoint_interrupt_enable (epn, false); + /* Reset endpoint */ + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_RST_EP, 1 << epn); + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_RST_EP, 0); + + pep->halted = false; + + /* Type | In */ + HAL_WRITE_UINT32 (pCSR, (((((cyg_uint32) endpoint_type) & 0x03) << 8) | + ((((cyg_uint32) endpoint_type) & 0x80) << 3))); + + usbs_at91_endpoint_bytes_in_fifo[epn] = 0; + usbs_at91_endpoint_bytes_received[epn] = THERE_IS_A_NEW_PACKET_IN_THE_UDP; + usbs_at91_endpoint_bank1[epn] = false; + + if (enable) { + SET_BITS (pCSR, AT91_UDP_CSR_EPEDS); + } +} + +static void +usbs_at91_handle_reset (void) +{ + int epn; + const usb_endpoint_descriptor *usb_endpoints; + cyg_uint8 endpoint_type; + + cyg_uint8 endpoint_number; + + usbs_end_all_transfers (-EPIPE); + + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_IDR, 0xffffffff); + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_ICR, 0xffffffff); + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_RST_EP, 0xffffffff); + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_RST_EP, 0x00000000); + + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_FADDR, AT91_UDP_FADDR_FEN); + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_CSR0, + AT91_UDP_CSR_EPEDS | AT91_UDP_CSR_EPTYPE_CTRL); + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_IER, AT91_UDP_ALLOWED_IRQs); + + for (epn=1; epn < AT91_USB_ENDPOINTS; epn++) { + usbs_at91_endpoint_init ((usbs_rx_endpoint *)usbs_at91_endpoints[epn], + 0, false); + } + + // Now walk the endpoints configuring them correctly. This only + // works if there is one interface. + usb_endpoints = usbs_at91_ep0.enumeration_data->endpoints; + + for (epn = 1; + epn <= usbs_at91_ep0.enumeration_data->total_number_endpoints; + epn++) { + + endpoint_type = (usb_endpoints[epn-1].attributes | + (usb_endpoints[epn-1].endpoint & + USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN ? + USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN : + USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT)); + endpoint_number = usb_endpoints[epn-1].endpoint & ~(USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN); + if ( endpoint_number < AT91_USB_ENDPOINTS ) + { + usbs_at91_endpoint_init((usbs_rx_endpoint *)usbs_at91_endpoints[endpoint_number], + endpoint_type, + true); + } + } +} + +static void +usbs_at91_ep0_start (usbs_control_endpoint * endpoint) +{ + usbs_at91_handle_reset (); + + // If there is additional platform-specific initialization to + // perform, do it now. This macro can come from the platform HAL, + // but may not be available on all platforms. +#ifdef AT91_USB_PLATFORM_INIT + AT91_USB_PLATFORM_INIT (); +#endif + + usbs_at91_set_pullup (true); +} + +static void +usbs_at91_endpoint_start (usbs_rx_endpoint * pep) +{ + int epn = usbs_at91_pep_to_number(pep); + cyg_addrword_t pCSR = pCSRn(epn); + cyg_addrword_t pFDR = pFDRn(epn); + cyg_uint16 space = 0; + cyg_uint16 endpoint_size = usbs_at91_endpoint_fifo_size[epn]; + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[epn]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[epn]; + + CYG_ASSERT (pep->complete_fn, "No complete_fn()"); + + cyg_drv_dsr_lock (); + if (usbs_at91_ep0.state != USBS_STATE_CONFIGURED) { + /* If not configured it means there is nothing to do */ + cyg_drv_dsr_unlock (); + + if (pep->complete_fn) { + (*pep->complete_fn) (pep->complete_data, -EPIPE); + } + return; + } + + if (pep->halted) { + /* Halted means nothing to do */ + cyg_drv_dsr_unlock (); + + if (pep->complete_fn) { + (*pep->complete_fn) (pep->complete_data, -EAGAIN); + } + return; + } + + if (BITS_ARE_SET (pIMR, 1 << epn)) { + cyg_drv_dsr_unlock (); + + if (pep->complete_fn) { + (*pep->complete_fn) (pep->complete_data, -EIO); + } + + return; + } + + CYG_ASSERT (BITS_ARE_SET (pCSR, 1 << 9), "Wrong endpoint type"); + + *ppbegin = pep->buffer; /* Set the working pointers */ + *ppend = (cyg_uint8 *) ((cyg_uint32) pep->buffer + pep->buffer_size); + + if (BITS_ARE_SET (pCSR, 0x400)) { /* IN: tx_endpoint */ + space = (cyg_uint32) * ppend - (cyg_uint32) * ppbegin; + if (space == endpoint_size) { + *ppend = *ppbegin; /* Send zero-packet */ + } + + *ppbegin = + write_fifo_uint8 (pFDR, *ppbegin, + (cyg_uint8 *) ((cyg_uint32) * ppbegin + + MIN (space, endpoint_size))); + SET_BITS (pCSR, AT91_UDP_CSR_TXPKTRDY); + + if (*ppend == *ppbegin) { /* Last packet ? */ + *ppend = *ppbegin - 1; /* The packet hasn't been sent yet */ + } + } + + usbs_at91_endpoint_interrupt_enable (epn, true); + + cyg_drv_dsr_unlock (); +} + +// Perform transmit handling on an endpoint +static bool +usbs_at91_endpoint_isr_tx(cyg_uint8 epn) +{ + cyg_addrword_t pCSR = pCSRn(epn); + cyg_addrword_t pFDR = pFDRn(epn); + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[epn]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[epn]; + cyg_uint32 space = 0; + cyg_uint16 endpoint_size = usbs_at91_endpoint_fifo_size[epn]; + + CLEAR_BITS (pCSR, AT91_UDP_CSR_TXCOMP); + + if (BITS_ARE_CLEARED (pCSR, AT91_UDP_CSR_TXPKTRDY)) { + /* Ready to transmit ? */ + if (*ppend > *ppbegin) { + /* Something to send */ + + space = (cyg_uint32) * ppend - (cyg_uint32) * ppbegin; + if (space == endpoint_size) { + *ppend = *ppbegin; /* Send zero-packet */ + } + + *ppbegin = + write_fifo_uint8 (pFDR, *ppbegin, + (cyg_uint8 *) ((cyg_uint32) * ppbegin + + MIN (space, endpoint_size))); + SET_BITS (pCSR, AT91_UDP_CSR_TXPKTRDY); + + if (*ppend == *ppbegin) { /* Last packet ? */ + *ppend = *ppbegin - 1; /* The packet isn't sent yet */ + } + } else { + if (*ppend + 1 == *ppbegin) { + *ppend = *ppbegin; /* Flag for DSR */ + return true; + } else { + *ppend = *ppbegin - 1; /* Flag for zero-packet */ + SET_BITS (pCSR, AT91_UDP_CSR_TXPKTRDY); /* Send no data */ + } + } + } + + CLEAR_BITS (pCSR, + AT91_UDP_CSR_RX_DATA_BK0 | AT91_UDP_CSR_RX_DATA_BK1 | + AT91_UDP_CSR_RXSETUP | AT91_UDP_CSR_ISOERROR); + return false; +} + +static bool +usbs_at91_endpoint_isr_rx(cyg_uint8 epn) +{ + cyg_addrword_t pCSR = pCSRn(epn); + cyg_addrword_t pFDR = pFDRn(epn); + cyg_uint16 *pinfifo = &usbs_at91_endpoint_bytes_in_fifo[epn]; + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[epn]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[epn]; + cyg_uint16 *preceived = &usbs_at91_endpoint_bytes_received[epn]; + cyg_uint16 endpoint_size = usbs_at91_endpoint_fifo_size[epn]; + + if (*preceived == THERE_IS_A_NEW_PACKET_IN_THE_UDP) { + /* There is a new packet */ + *preceived = ((*(cyg_uint32 *)pCSR) >> 16) & 0x7ff; + *pinfifo = *preceived; + } + + while ((*ppbegin < *ppend) && *pinfifo) { + /* If we have buffer-space AND data in the FIFO */ + HAL_READ_UINT8(pFDR, **ppbegin); + (*ppbegin)++; + (*pinfifo)--; + } + + if (*ppbegin == *ppend) { + /* The buffer is full... call the DSR */ + return true; + } + + if (*pinfifo == 0) { + /* If the FIFO is empty, then we can release it */ + if (usbs_at91_endpoint_pingpong[epn]) { + /* Time to clear the interrupt flag */ + + if (usbs_at91_endpoint_bank1[epn]) { + CLEAR_BITS (pCSR, AT91_UDP_CSR_RX_DATA_BK1); + } else { + CLEAR_BITS (pCSR, AT91_UDP_CSR_RX_DATA_BK0); + } + usbs_at91_endpoint_bank1[epn] = !usbs_at91_endpoint_bank1[epn]; + } else { + CLEAR_BITS (pCSR, AT91_UDP_CSR_RX_DATA_BK0); + } + + if (*preceived < endpoint_size) { + /* If the last packet was smaller then the endpoint-size... */ + *ppend = *ppbegin; + *preceived = THERE_IS_A_NEW_PACKET_IN_THE_UDP; /* Set flag */ + + return true; /* We can call the completion-function in the DSR */ + } + + *preceived = THERE_IS_A_NEW_PACKET_IN_THE_UDP; /* Set flag */ + } + return false; +} + +// ISR for an endpoint. Handle receive and transmit interrupts. +static bool +usbs_at91_endpoint_isr (cyg_uint8 epn) +{ + cyg_addrword_t pCSR = pCSRn(epn); + + CYG_ASSERT (AT91_USB_ENDPOINTS > epn && epn, "Invalid end point"); + + if (BITS_ARE_SET (pCSR, 0x400)) { /* IN: tx_endpoint */ + if (usbs_at91_endpoint_isr_tx(epn)) + return true; // Call the DSR + } else { /* OUT: rx_endpoint */ + if (!BITS_ARE_CLEARED (pCSR, AT91_UDP_CSR_RX_DATA_BK0) || + !BITS_ARE_CLEARED (pCSR, AT91_UDP_CSR_RX_DATA_BK1)) { + /* Sometime something received ? */ + if(usbs_at91_endpoint_isr_rx(epn)) + return true; // Call the DSR; + } + + CLEAR_BITS (pCSR, + AT91_UDP_CSR_TXCOMP | AT91_UDP_CSR_RXSETUP | + AT91_UDP_CSR_ISOERROR); + } + + return false; +} + +// Handle a DSR for an endpoint +static void +usbs_at91_endpoint_dsr (cyg_uint8 epn) +{ + usbs_rx_endpoint *pep = (usbs_rx_endpoint *) usbs_at91_endpoints[epn]; + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[epn]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[epn]; + + CYG_ASSERT (AT91_USB_ENDPOINTS > epn && epn, "Invalid end point"); + CYG_ASSERT (pep->complete_fn, "No complete_fn()"); + + if (*ppend == *ppbegin) { /* Transmitted/Received ? */ + + pep->buffer_size = (cyg_uint32) * ppbegin - (cyg_uint32) pep->buffer; + if (pep->buffer_size && pep->complete_fn) { + if (!pep->halted) { + (*pep->complete_fn) (pep->complete_data, pep->buffer_size); + } else { + (*pep->complete_fn) (pep->complete_data, -EAGAIN); + } + } + usbs_at91_endpoint_interrupt_enable (epn, false); + } +} + +// Handle an error condition on the control endpoint +static ep0_low_level_status_t +usbs_at91_control_error(ep0_low_level_status_t status) +{ + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[0]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[0]; + + usbs_at91_ep0.buffer_size = 0; + usbs_at91_ep0.fill_buffer_fn = 0; + usbs_at91_ep0.complete_fn = 0; + + *ppbegin = usbs_at91_ep0.buffer; + *ppend = *ppbegin; + + if (status == EP0_LL_IDLE) { + if (usbs_at91_ep0.complete_fn) { + (*usbs_at91_ep0.complete_fn) (&usbs_at91_ep0, + USBS_CONTROL_RETURN_STALL); + } + } + + status = EP0_LL_IDLE; + + CLEAR_BITS (pCSR0, AT91_UDP_CSR_ISOERROR | AT91_UDP_CSR_FORCESTALL); + + return status; +} + +// Handle a get status setup message on the control end point +static ep0_low_level_status_t +usbs_at91_control_setup_get_status(void) +{ + ep0_low_level_status_t status; + usb_devreq *req = (usb_devreq *)usbs_at91_ep0.control_buffer; + cyg_uint8 recipient = req->type & USB_DEVREQ_RECIPIENT_MASK; + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[0]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[0]; + cyg_uint16 word = 0; + + status = EP0_LL_SEND_READY; + + switch (recipient) { + case USB_DEVREQ_RECIPIENT_DEVICE: + case USB_DEVREQ_RECIPIENT_INTERFACE: + // Nothing to do + break; + case USB_DEVREQ_RECIPIENT_ENDPOINT: + if ((usbs_at91_ep0.state == USBS_STATE_CONFIGURED) && + (req->index_lo > 0) && + (req->index_lo < AT91_USB_ENDPOINTS)) { + cyg_uint32 CSR; + + HAL_READ_UINT32(pCSRn(req->index_lo), CSR); + if (CSR & AT91_UDP_CSR_EPEDS) { + word = 1; + } + } else { + status = EP0_LL_STALL; + } + break; + default: + status = EP0_LL_STALL; + } + + *ppbegin = (cyg_uint8 *)&word; + *ppend = *ppbegin + sizeof (word); + return status; +} + +// Setup the begin and end pointers such that an ACK is sent +static void +usbs_at91_control_setup_send_ack(void) +{ + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[0]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[0]; + + *ppbegin = usbs_at91_ep0.buffer; + *ppend = *ppbegin; +} + +// Handle a get status set feature message on the control endpoint +static ep0_low_level_status_t +usbs_at91_control_setup_set_feature(void) +{ + ep0_low_level_status_t status; + usb_devreq *req = (usb_devreq *)usbs_at91_ep0.control_buffer; + cyg_uint8 recipient = req->type & USB_DEVREQ_RECIPIENT_MASK; + + usbs_at91_control_setup_send_ack(); + status = EP0_LL_SEND_READY; + + switch(recipient) { + case USB_DEVREQ_RECIPIENT_DEVICE: + status = EP0_LL_STALL; + break; + case USB_DEVREQ_RECIPIENT_INTERFACE: + // Nothing to do + break; + case USB_DEVREQ_RECIPIENT_ENDPOINT: + if ((usbs_at91_ep0.state == USBS_STATE_CONFIGURED) && + (req->index_lo > 0) && + (req->index_lo < AT91_USB_ENDPOINTS)) { + cyg_uint32 CSR; + + HAL_READ_UINT32(pCSRn(req->index_lo), CSR); + if (CSR & AT91_UDP_CSR_EPEDS) { + /* TODO */ + } + } else { + status = EP0_LL_STALL; + } + default: + status = EP0_LL_STALL; + } + return status; +} + +// Handle a get status clear feature message on the control endpoint +static ep0_low_level_status_t +usbs_at91_control_setup_clear_feature(void) +{ + ep0_low_level_status_t status; + usb_devreq *req = (usb_devreq *)usbs_at91_ep0.control_buffer; + cyg_uint8 recipient = req->type & USB_DEVREQ_RECIPIENT_MASK; + + usbs_at91_control_setup_send_ack(); + status = EP0_LL_SEND_READY; + + switch (recipient) { + case USB_DEVREQ_RECIPIENT_DEVICE: + status = EP0_LL_STALL; + break; + case USB_DEVREQ_RECIPIENT_INTERFACE: + // Nothing to do + break; + case USB_DEVREQ_RECIPIENT_ENDPOINT: + if ((usbs_at91_ep0.state == USBS_STATE_CONFIGURED) && + (req->index_lo > 0) && + (req->index_lo < AT91_USB_ENDPOINTS)) { + cyg_uint32 CSR; + + HAL_READ_UINT32(pCSRn(req->index_lo), CSR); + if (CSR & AT91_UDP_CSR_EPEDS) { + /* TODO */ + } + } else { + status = EP0_LL_STALL; + } + default: + status = EP0_LL_STALL; + } + return status; +} + +// Handle a setup message from the host +static ep0_low_level_status_t +usbs_at91_control_setup(ep0_low_level_status_t status) +{ + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[0]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[0]; + usb_devreq *req = (usb_devreq *) usbs_at91_ep0.control_buffer; + cyg_uint8 protocol; + cyg_uint16 length; + bool dev_to_host; + usbs_control_return usbcode; + bool handled = false; + + usbs_at91_ep0.buffer_size = 0; + usbs_at91_ep0.fill_buffer_fn = 0; + usbs_at91_ep0.complete_fn = 0; + + read_fifo_uint8 ((cyg_uint8 *)req, pFDR0, sizeof (usb_devreq)); + + length = (req->length_hi << 8) | req->length_lo;; + dev_to_host = req->type & USB_DEVREQ_DIRECTION_IN; + + CLEAR_BITS (pCSR0, AT91_UDP_CSR_DTGLE); + + status = EP0_LL_REQUEST; + + protocol = req->type & (USB_DEVREQ_TYPE_MASK); + + // Set the next transfer direction + if (dev_to_host) { + SET_BITS (pCSR0, AT91_UDP_CSR_DIR); /* Set IN direction */ + } else { + CLEAR_BITS (pCSR0, AT91_UDP_CSR_DIR); /* Set OUT direction */ + } + + if (protocol == USB_DEVREQ_TYPE_STANDARD) { + handled = true; + switch (req->request) { + case USB_DEVREQ_GET_STATUS: + status = usbs_at91_control_setup_get_status(); + break; + case USB_DEVREQ_SET_ADDRESS: + // Most of the hard work is done by the hardware. We just need + // to send an ACK. + usbs_at91_control_setup_send_ack(); + status = EP0_LL_SEND_READY; + break; + case USB_DEVREQ_SET_FEATURE: + status = usbs_at91_control_setup_set_feature(); + break; + case USB_DEVREQ_CLEAR_FEATURE: + status = usbs_at91_control_setup_clear_feature(); + break; + default: + handled = false; + } + } + if ((protocol != USB_DEVREQ_TYPE_STANDARD) || !handled) { + // Ask the layer above to process the message + usbcode = usbs_parse_host_get_command (&usbs_at91_ep0); + usbs_at91_ep0.buffer_size = MIN (usbs_at91_ep0.buffer_size, length); + + *ppbegin = usbs_at91_ep0.buffer; + *ppend = *ppbegin + usbs_at91_ep0.buffer_size; /* Ready to send... */ + + if (usbcode == USBS_CONTROL_RETURN_HANDLED) { /* OK */ + if (dev_to_host) { + status = EP0_LL_SEND_READY; + } else { + status = EP0_LL_RECEIVE_READY; + } + } else { + status = EP0_LL_STALL; + } + } + // Clear the setup bit so indicating we have processed the message + CLEAR_BITS (pCSR0, AT91_UDP_CSR_RXSETUP); + + return status; +} + +static ep0_low_level_status_t +usbs_at91_control_data_recv(ep0_low_level_status_t status) +{ + cyg_uint32 received = 0; + cyg_uint32 length; + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[0]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[0]; + usbs_control_return usbcode; + + if (status == EP0_LL_RECEIVE_READY) { + received = ((*(cyg_uint32 *) pCSR0) >> 16) & 0x7ff; + length = MIN (received, (cyg_uint32) *ppend - (cyg_uint32) *ppbegin); + *ppbegin = read_fifo_uint8 (*ppbegin, pFDR0, length); + + if (received < usbs_at91_endpoint_fifo_size[0]) { /* Last packet ? */ + *ppend = *ppbegin; + } + + if (*ppbegin == *ppend) { /* All received ? */ + usbs_at91_ep0.buffer_size = + (cyg_uint32) *ppend - (cyg_uint32) usbs_at91_ep0.buffer; + usbcode = USBS_CONTROL_RETURN_STALL; + + if (usbs_at91_ep0.complete_fn) { + usbcode = (*usbs_at91_ep0.complete_fn) (&usbs_at91_ep0, 0); + } + + if (usbcode == USBS_CONTROL_RETURN_HANDLED) { + status = EP0_LL_SEND_READY; + } else { + status = EP0_LL_STALL; + } + } + } + + CLEAR_BITS (pCSR0, AT91_UDP_CSR_RX_DATA_BK0); + + return status; +} + +static ep0_low_level_status_t +usbs_at91_control_data_sent(ep0_low_level_status_t status) +{ + cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[0]; + cyg_uint8 **ppend = &usbs_at91_endpoint_pend[0]; + cyg_uint32 bytes_to_write = 0; + usb_devreq *req = (usb_devreq *)usbs_at91_ep0.control_buffer; + cyg_uint16 value; + + switch (status) { + case EP0_LL_SEND_READY: + if (*ppbegin == *ppend && + usbs_at91_ep0.fill_buffer_fn == NULL) { + // All bytes are sent, send ACK + status = EP0_LL_ACK; + SET_BITS (pCSR0, AT91_UDP_CSR_TXPKTRDY); // Signal FIFO loaded + } else { + // We have more bytes to send + bytes_to_write = + MIN (*ppend - *ppbegin, usbs_at91_endpoint_fifo_size[0]); + *ppbegin = write_fifo_uint8 (pFDR0, *ppbegin, (cyg_uint8 *) + ((cyg_uint32) *ppbegin + bytes_to_write)); + // Send next few bytes + if (*ppbegin == *ppend) { /* Control-Endoints don't need ACK's */ + if (usbs_at91_ep0.fill_buffer_fn) { // More Records ? + (*usbs_at91_ep0.fill_buffer_fn) (&usbs_at91_ep0); + + *ppbegin = usbs_at91_ep0.buffer; + *ppend = *ppbegin + usbs_at91_ep0.buffer_size; + + /* Ready to send... */ + bytes_to_write = + MIN (*ppend - *ppbegin, + usbs_at91_endpoint_fifo_size[0] - bytes_to_write); + + *ppbegin = write_fifo_uint8 (pFDR0, *ppbegin, (cyg_uint8 *) + ((cyg_uint32) *ppbegin + bytes_to_write)); + // Send next few bytes + } else { + if (bytes_to_write == usbs_at91_endpoint_fifo_size[0]) { + // Last packet is full, so we need to send a zero bytes + // packet next time + status = EP0_LL_SEND_READY; + } else { + status = EP0_LL_IDLE; + } + + } + } + SET_BITS (pCSR0, AT91_UDP_CSR_TXPKTRDY); // Signal FIFO loaded + } + break; + case EP0_LL_RECEIVE_READY: + /* Maybe we have to send an ACK */ + if (*ppbegin == *ppend) { // All bytes are received, send ACK + status = EP0_LL_ACK; + SET_BITS (pCSR0, AT91_UDP_CSR_TXPKTRDY); // Signal FIFO loaded + } + break; + case EP0_LL_ACK: + if (req->request == USB_DEVREQ_SET_ADDRESS) { // Special-processing + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_FADDR, + req->value_lo | AT91_UDP_FADDR_FEN); + value = (req->value_hi << 8) | req->value_lo; + if (value) { + usbs_at91_ep0.state = USBS_STATE_ADDRESSED; + } + } + + if (usbs_at91_ep0.complete_fn) { + (*usbs_at91_ep0.complete_fn) (&usbs_at91_ep0, + USBS_CONTROL_RETURN_HANDLED); + } + status = EP0_LL_IDLE; + usbs_state_notify (&usbs_at91_ep0); + break; + default: + break; + } + return status; +} + +static void +usbs_at91_control_dsr (void) +{ + static ep0_low_level_status_t status = EP0_LL_IDLE; + + while (!BITS_ARE_CLEARED(pCSR0, + AT91_UDP_CSR_TXCOMP | AT91_UDP_CSR_RX_DATA_BK0 | + AT91_UDP_CSR_RXSETUP | AT91_UDP_CSR_ISOERROR | + AT91_UDP_CSR_RX_DATA_BK1)) { + + // Check and handle any error conditions + if (BITS_ARE_SET (pCSR0, AT91_UDP_CSR_ISOERROR)) { + status = usbs_at91_control_error(status); + } + + // Check for a setup message and handle it + if (BITS_ARE_SET (pCSR0, AT91_UDP_CSR_RXSETUP)) { + status = usbs_at91_control_setup(status); + } + + // Check for received data on the control endpoint + if (BITS_ARE_SET (pCSR0, AT91_UDP_CSR_RX_DATA_BK0)) { + status = usbs_at91_control_data_recv(status); + } + + // Check if the last packet has been sent + if (BITS_ARE_CLEARED (pCSR0, AT91_UDP_CSR_TXPKTRDY)) { + status = usbs_at91_control_data_sent(status); + } + + // Received an ACK packet + if (BITS_ARE_SET (pCSR0, AT91_UDP_CSR_TXCOMP)) { + CLEAR_BITS (pCSR0, AT91_UDP_CSR_TXCOMP); + } + + if (status == EP0_LL_STALL) { + CLEAR_BITS (pCSR0, 0x7f); + SET_BITS (pCSR0, AT91_UDP_CSR_FORCESTALL); + } + } +} + +static void +usbs_at91_dsr (cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + cyg_uint8 n; + + CYG_ASSERT (CYGNUM_HAL_INTERRUPT_UDP == vector, "Wrong interrupts"); + CYG_ASSERT (0 == data, "DSR needs no data"); + + CLEAR_BITS (AT91_UDP + AT91_UDP_GLB_STATE, 0x10); + + if (BITS_ARE_SET (pISR, AT91_UDP_WAKEUP)) { + usbs_at91_ep0.state = USBS_STATE_DEFAULT; + usbs_state_notify (&usbs_at91_ep0); + + HAL_WRITE_UINT32 (pICR, AT91_UDP_WAKEUP); + } + + if (BITS_ARE_SET (pISR, AT91_UDP_ENDBUSRES)) { // RESET UDP + usbs_at91_ep0.state = USBS_STATE_POWERED; + usbs_state_notify (&usbs_at91_ep0); + usbs_at91_handle_reset (); + + HAL_WRITE_UINT32 (pCSR0, AT91_UDP_CSR_EPEDS | AT91_UDP_CSR_EPTYPE_CTRL); + HAL_WRITE_UINT32 (pIER, AT91_UDP_EPINT0); + + usbs_at91_ep0.state = USBS_STATE_DEFAULT; + usbs_state_notify (&usbs_at91_ep0); + + HAL_WRITE_UINT32 (pICR, AT91_UDP_ENDBUSRES); + } + + if (BITS_ARE_SET (pISR, AT91_UDP_SOFINT)) { + HAL_WRITE_UINT32 (pICR, AT91_UDP_SOFINT); + } + + if (BITS_ARE_SET (pISR, AT91_UDP_EXTRSM)) { + usbs_at91_ep0.state = usbs_at91_ep0.state & ~USBS_STATE_SUSPENDED; + usbs_state_notify (&usbs_at91_ep0); + HAL_WRITE_UINT32 (pICR, AT91_UDP_EXTRSM); + } + + if (BITS_ARE_SET (pISR, AT91_UDP_RXRSM)) { + usbs_at91_ep0.state = usbs_at91_ep0.state & ~USBS_STATE_SUSPENDED; + usbs_state_notify (&usbs_at91_ep0); + HAL_WRITE_UINT32 (pICR, AT91_UDP_RXRSM); + } + + if (BITS_ARE_SET (pISR, AT91_UDP_RXSUSP)) { + usbs_at91_ep0.state = usbs_at91_ep0.state | USBS_STATE_SUSPENDED; + usbs_state_notify (&usbs_at91_ep0); + HAL_WRITE_UINT32 (pICR, AT91_UDP_RXSUSP); + } + + if (BITS_ARE_SET (pISR, AT91_UDP_EPINT0)) { + usbs_at91_control_dsr (); + } + + for (n = 1; n < AT91_USB_ENDPOINTS; n++) { + if (*(cyg_uint32 *) pIMR & (1 << n)) { + usbs_at91_endpoint_dsr (n); + } + } + + cyg_drv_interrupt_unmask (vector); +} + +static cyg_uint32 +usbs_at91_isr (cyg_vector_t vector, cyg_addrword_t data) +{ + cyg_uint8 n; + bool need_dsr = false; + cyg_uint32 IMR; + cyg_uint32 ISR; + + CYG_ASSERT (CYGNUM_HAL_INTERRUPT_UDP == vector, "Wrong interrupts"); + CYG_ASSERT (0 == data, "ISR needs no data"); + + HAL_READ_UINT32(pIMR, IMR); + HAL_READ_UINT32(pISR, ISR); + + for (n = 1; n < AT91_USB_ENDPOINTS; n++) { + /* Do any data endpoint need a data transfer ? */ + if (IMR & ISR & (1 << n)) { + need_dsr = usbs_at91_endpoint_isr (n) || need_dsr; + } + } + /* If we don't need any DSR re-enable interrupts and finish */ + if (BITS_ARE_CLEARED (pISR, AT91_UDP_ALLOWED_IRQs & 0xffffff01) + && !need_dsr) { + cyg_drv_interrupt_acknowledge (vector); + return CYG_ISR_HANDLED; + } + + /* Call the DSR */ + cyg_drv_interrupt_mask (vector); + cyg_drv_interrupt_acknowledge (vector); + + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; +} + + + +// ---------------------------------------------------------------------------- +// Polling support. It is not clear that this is going to work particularly +// well since according to the documentation the hardware does not generate +// NAKs automatically - instead the ISR has to set the appropriate bits +// sufficiently quickly to avoid confusing the host. +// +// Calling the isr directly avoids duplicating code, but means that +// cyg_drv_interrupt_acknowledge() will get called when not inside a +// real interrupt handler. This should be harmless. + +static void +usbs_at91_poll (usbs_control_endpoint * endpoint) +{ + CYG_ASSERT (endpoint == &usbs_at91_ep0, "Wrong endpoint"); + if (CYG_ISR_CALL_DSR == usbs_at91_isr (CYGNUM_HAL_INTERRUPT_UDP, 0)) { + usbs_at91_dsr (CYGNUM_HAL_INTERRUPT_UDP, 0, 0); + } +} + +// ---------------------------------------------------------------------------- +// Initialization +// +// This routine gets called from a prioritized static constructor during +// eCos startup. + +void +usbs_at91_init (void) +{ + + cyg_uint32 reg; + + HAL_READ_UINT32 (AT91_PMC + AT91_PMC_PLLR, reg); + + /* Set USB divider so we have a 48MHz clock */ +#if ((CYGNUM_HAL_ARM_AT91_CLOCK_SPEED < 48120000) && \ + (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 47880000)) + + // 48MHz clock, divider set to 1 + HAL_WRITE_UINT32 (AT91_PMC + AT91_PMC_PLLR, + (reg & 0x0fffffff) | AT91_PMC_PLLR_USBDIV_1); + +#elif ((CYGNUM_HAL_ARM_AT91_CLOCK_SPEED < 96240000) && \ + (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 95760000)) + + // 96MHz clock, divider set to 2 + HAL_WRITE_UINT32 (AT91_PMC + AT91_PMC_PLLR, + (reg & 0x0fffffff) | AT91_PMC_PLLR_USBDIV_2); +#else +#error CYGNUM_HAL_ARM_AT91_CLOCK_SPEED is not 48, 96 or 192MHz plusminus 0.25% ... +#endif + + /* Enable USB clock */ + HAL_WRITE_UINT32 (AT91_PMC + AT91_PMC_SCER, AT91_PMC_SCER_UDP); + HAL_WRITE_UINT32 (AT91_PMC + AT91_PMC_PCER, AT91_PMC_PCER_UDP); + + usbs_at91_set_pullup (false); +#ifndef CYGDAT_DEVS_USB_AT91_GPIO_SET_PULLUP_PIN_NONE + HAL_ARM_AT91_GPIO_CFG_DIRECTION(CYGDAT_DEVS_USB_AT91_GPIO_SET_PULLUP_PIN, + AT91_PIN_OUT); +#endif +#ifndef CYGDAT_DEVS_USB_AT91_GPIO_READ_POWER_PIN_NONE + HAL_ARM_AT91_GPIO_CFG_DIRECTION(CYGDAT_DEVS_USB_AT91_GPIO_READ_POWER_PIN, + AT91_PIN_IN); +#endif + usbs_at91_handle_reset (); + + cyg_drv_interrupt_create (CYGNUM_HAL_INTERRUPT_UDP, + 6, // priority + 0, // data + &usbs_at91_isr, + &usbs_at91_dsr, + &usbs_at91_intr_handle, &usbs_at91_intr_data); + + cyg_drv_interrupt_attach (usbs_at91_intr_handle); + cyg_drv_interrupt_unmask (CYGNUM_HAL_INTERRUPT_UDP); + + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_TXVC, 0); + + usbs_at91_ep0.state = USBS_STATE_POWERED; + usbs_state_notify (&usbs_at91_ep0); +} + +// ---------------------------------------------------------------------------- +// Testing support. +usbs_testing_endpoint usbs_testing_endpoints[] = { + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL, + endpoint_number : 0, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, + endpoint : (void*) &usbs_at91_ep0, +#ifdef CYGVAR_DEVS_USB_AT91_EP0_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME "0c", +#else + devtab_entry : (const char*) 0, +#endif + min_size : 1, // zero-byte control transfers are meaningless + max_size : 0x0FFFF, // limit imposed by protocol + max_in_padding : 0, + alignment : 0 + }, + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_BULK, + endpoint_number : 1, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT, + endpoint : (void*) &usbs_at91_ep1, +#ifdef CYGVAR_DEVS_USB_AT91_EP1_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME "1r", +#else + devtab_entry : (const char*) 0, +#endif + min_size : 1, + max_size : -1, // No hardware or driver limitation + max_in_padding : 0, + alignment : 0 + }, + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_BULK, + endpoint_number : 2, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, + endpoint : (void*) &usbs_at91_ep2, +#ifdef CYGVAR_DEVS_USB_AT91_EP2_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME "2w", +#else + devtab_entry : (const char*) 0, +#endif + min_size : 1, + max_size : -1, // No hardware or driver limitation + max_in_padding : 1, // hardware limitation + alignment : 0 + }, + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_BULK, + endpoint_number : 3, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, + endpoint : (void*) &usbs_at91_ep3, +#ifdef CYGVAR_DEVS_USB_AT91_EP3_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME "3w", +#else + devtab_entry : (const char*) 0, +#endif + min_size : 1, + max_size : -1, // No hardware or driver limitation + max_in_padding : 1, // hardware limitation + alignment : 0 + }, + USBS_TESTING_ENDPOINTS_TERMINATOR +}; diff --git a/packages/devs/usb/at91/v2_0/src/usbs_at91_data.cxx b/packages/devs/usb/at91/v2_0/src/usbs_at91_data.cxx new file mode 100644 index 00000000..6c0da3ce --- /dev/null +++ b/packages/devs/usb/at91/v2_0/src/usbs_at91_data.cxx @@ -0,0 +1,183 @@ +//========================================================================== +// +// usbs_at91_data.cxx +// +// Static data for the ATMEL AT91 USB device driver +// +//========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Oliver Munz +// Contributors: bartv +// Date: 2006-02-22 +// +// This file contains various objects that should go into extras.o +// rather than libtarget.a, e.g. devtab entries that would normally +// be eliminated by the selective linking. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Initialization. The goal here is to call usbs_at91_init() +// early on during system startup, to take care of things like +// registering interrupt handlers etc. which are best done +// during system init. +// +// If the endpoint 0 devtab entry is available then its init() +// function can be used to take care of this. However the devtab +// entries are optional so an alternative mechanism must be +// provided. Unfortunately although it is possible to give +// a C function the constructor attribute, it cannot be given +// an initpri attribute. Instead it is necessary to define a +// dummy C++ class. + +extern "C" void usbs_at91_init(void); + +#ifndef CYGVAR_DEVS_USB_AT91_EP0_DEVTAB_ENTRY + +class usbs_at91_initialization { +public: + usbs_at91_initialization() { + usbs_at91_init(); + } +}; + +static usbs_at91_initialization CYGBLD_ATTRIB_INIT_BEFORE(CYG_INIT_IO) + usbs_at91_init_object; +#endif + +// ---------------------------------------------------------------------------- +// The devtab entries. Each of these is optional, many applications +// will want to use the lower-level API rather than go via +// open/read/write/ioctl. + +#ifdef CYGVAR_DEVS_USB_AT91_EP0_DEVTAB_ENTRY +// For endpoint 0 the only legal operations are get_config() and +// set_config(), and these are provided by the common package. + +static bool usbs_at91_devtab_ep0_init(struct cyg_devtab_entry* tab){ + + CYG_UNUSED_PARAM(struct cyg_devtab_entry*, tab); + + usbs_at91_init(); + + return true; +} + +CHAR_DEVIO_TABLE(usbs_at91_ep0_devtab_functions, + &cyg_devio_cwrite, + &cyg_devio_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +CHAR_DEVTAB_ENTRY(usbs_at91_ep0_devtab_entry, + CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME "0", + 0, + &usbs_at91_ep0_devtab_functions, + &usbs_at91_devtab_ep0_init, + 0, + (void*) &usbs_at91_ep0); +#endif + +// ---------------------------------------------------------------------------- +// Common routines for ep1..3 + +#if defined(CYGVAR_DEVS_USB_AT91_EP1_DEVTAB_ENTRY) || \ + defined(CYGVAR_DEVS_USB_AT91_EP2_DEVTAB_ENTRY) || \ + defined(CYGVAR_DEVS_USB_AT91_EP3_DEVTAB_ENTRY) + +static bool usbs_at91_devtab_dummy_init(struct cyg_devtab_entry* tab){ + + CYG_UNUSED_PARAM(struct cyg_devtab_entry*, tab); + return true; +} + +#endif + +#ifdef CYGVAR_DEVS_USB_AT91_EP1_DEVTAB_ENTRY +CHAR_DEVIO_TABLE(usbs_at91_ep1_devtab_functions, + &usbs_devtab_cwrite, + &usbs_devtab_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +CHAR_DEVTAB_ENTRY(usbs_at91_ep1_devtab_entry, + CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME "1", + 0, + &usbs_at91_ep1_devtab_functions, + &usbs_at91_devtab_dummy_init, + 0, + (void*) &usbs_at91_ep1); +#endif + +#ifdef CYGVAR_DEVS_USB_AT91_EP2_DEVTAB_ENTRY +CHAR_DEVIO_TABLE(usbs_at91_ep2_devtab_functions, + &usbs_devtab_cwrite, + &usbs_devtab_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +CHAR_DEVTAB_ENTRY(usbs_at91_ep2_devtab_entry, + CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME "2", + 0, + &usbs_at91_ep2_devtab_functions, + &usbs_at91_devtab_dummy_init, + 0, + (void*) &usbs_at91_ep2); +#endif + +#ifdef CYGVAR_DEVS_USB_AT91_EP3_DEVTAB_ENTRY +CHAR_DEVIO_TABLE(usbs_at91_ep3_devtab_functions, + &usbs_devtab_cwrite, + &usbs_devtab_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +CHAR_DEVTAB_ENTRY(usbs_at91_ep3_devtab_entry, + CYGDAT_DEVS_USB_AT91_DEVTAB_BASENAME "3", + 0, + &usbs_at91_ep3_devtab_functions, + &usbs_at91_devtab_dummy_init, + 0, + (void*) &usbs_at91_ep3); +#endif diff --git a/packages/devs/usb/d12/v2_0/ChangeLog b/packages/devs/usb/d12/v2_0/ChangeLog new file mode 100644 index 00000000..7d98fec4 --- /dev/null +++ b/packages/devs/usb/d12/v2_0/ChangeLog @@ -0,0 +1,35 @@ +2006-06-06 Frank Pagliughi + + * First version of the USB device driver for the philips D12 + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric Ltd +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/usb/d12/v2_0/cdl/usbs_d12.cdl b/packages/devs/usb/d12/v2_0/cdl/usbs_d12.cdl new file mode 100644 index 00000000..6628289e --- /dev/null +++ b/packages/devs/usb/d12/v2_0/cdl/usbs_d12.cdl @@ -0,0 +1,317 @@ +# ==================================================================== +# +# usbs_d12.cdl +# +# USB device driver for the Philips PDIUSBD12 Full Speed USB +# peripheral chip. +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2003, 2004 eCosCentric Limited +## Copyright (C) 2006 eCosCentric Ltd +## +## 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): Frank M. Pagliughi (fmp), SoRo Systems, Inc. +# Contributors: +# Date: 2004-05-24 +# +#####DESCRIPTIONEND#### +# ==================================================================== + +cdl_package CYGPKG_DEVS_USB_D12 { + display "Philips D12 USB Device Driver" + include_dir "cyg/io/usb" + parent CYGPKG_USB + implements CYGHWR_IO_USB_SLAVE + doc ref/devs-usb-philips-pdiusbd12.html + + description " + The Philips PDIUSBD12 is a USB peripheral controller (slave) + chip that can connect to a microcontroller or microprocessor + through an 8-bit parallel bus. The SoRo Systems USB-D12-104 is + a slave board for the PC's ISA or PC/104 bus that contains a + D12 chip placed in the PC's I/O space with jumpered selections + for IRQ and DMA settings. This package provides an eCos device + driver." + + requires CYGIMP_DEVS_USB_D12_HW_ACCESS_HEADER + + cdl_option CYGIMP_DEVS_USB_D12_HW_ACCESS_HEADER { + display "Inline file implementing hardware access" + flavor booldata + default_value false + description " + This option should contain the header file which + implements basic access to the D12 registers" + } + + cdl_component CYGFUN_DEVS_USB_D12_EP0 { + display "Support the Control Endpoint 0" + default_value CYGINT_IO_USB_SLAVE_CLIENTS + requires CYGPKG_IO_USB CYGPKG_IO_USB_SLAVE + compile usbs_d12.c + compile -library=libextras.a usbs_d12_data.cxx + description " + Enable support for endpoint 0. If this support is disabled + then the entire USB port is unusable." + + cdl_option CYGVAR_DEVS_USB_D12_EP0_DEVTAB_ENTRY { + display "Provide a devtab entry for endpoint 0" + default_value CYGGLO_IO_USB_SLAVE_PROVIDE_DEVTAB_ENTRIES + requires CYGPKG_IO + description " + If endpoint 0 will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and ioctl calls then a devtab entry is needed. + " + } + cdl_option CYGNUM_DEVS_USB_D12_EP0_TXBUFSIZE { + display "Size of statically-allocated endpoint 0 transmit buffer" + flavor data + default_value 256 + requires { CYGNUM_DEVS_USB_D12_EP0_TXBUFSIZE >= + CYGNUM_DEVS_USB_D12_EP0_PKTSIZE } + description " + The implementation of the support for endpoint 0 uses + a single static buffer to hold the response to the + current control message. Typically this buffer can be + fairly small since replies to control messages tend to + be small: typically some tens of bytes for the enumeration + data, perhaps a bit more for unicode-encoded string + descriptors. However if some application-specific protocol + depends on larger control messages then this buffer + size may need to be increased." + } + } + + cdl_option CYGNUM_DEVS_USB_D12_BASEADDR { + display "Base Address of D12 chip" + flavor data + active_if CYGFUN_DEVS_USB_D12_EP0 + description " + The base memory or I/O address where the USB chip resides. + The value is set by the hardware specific driver's CDL." + } + + cdl_option CYGNUM_DEVS_USB_D12_IRQ { + display "IRQ for the D12 chip" + active_if CYGFUN_DEVS_USB_D12_EP0 + flavor data + description " + The IRQ assigned to the D12 chip. The value + is set by the hardware specific drivers's CDL." + } + + cdl_option CYGNUM_DEVS_USB_D12_INT { + display "INT for the D12 chip" + active_if CYGFUN_DEVS_USB_D12_EP0 + flavor data + default_value { CYGNUM_DEVS_USB_D12_IRQ + 32 } + description " + The interrupt vector assigned to the D12 chip." + } + + cdl_component CYGPKG_DEVS_USB_D12_THREAD { + display "Use a thread to service D12 chip" + active_if CYGFUN_DEVS_USB_D12_EP0 + default_value 0 + description " + Services the D12 USB chip with a thread, rather than at + the DSR level. This allows for increased debug support, + like TRACE output from the driver at the expense of some + throughput & reaction time. The service thread MUST be at + a higher priority than any application thread that uses + the USB port. " + + cdl_option CYGNUM_DEVS_USB_D12_THREAD_PRIORITY { + display "Thread Priority" + flavor data + legal_values 1 to 30 + default_value 4 + description " + The priority of the D12 device driver thread." + } + + cdl_option CYGNUM_DEVS_USB_D12_THREAD_STACK_SIZE { + display "USB Thread Stack Size" + flavor data + default_value 4096 + description " + The stack size for the D12 device driver thread." + } + } + + cdl_component CYGFUN_DEVS_USB_D12_DEBUG { + display "Debug output from the D12 Device Driver" + requires CYGPKG_DEVS_USB_D12_THREAD + default_value 0 + description " + Provide debugging output from the D12 Device Driver" + + cdl_option CYGSEM_DEVS_USB_D12_DEBUG_DUMP_EP0_BUFS { + display "Dump the contents of EP0 buffers" + flavor bool + default_value 0 + description " + + Dump the contents of the packages going through + EP0. This allows you to see things like device + requests and responses." + } + + cdl_option CYGSEM_DEVS_USB_D12_DEBUG_DUMP_BUFS { + display "Dump the contents of data buffers" + flavor bool + default_value 0 + description " + Dump the contents of the packages going through the generic + endpoints. This allow you to see all of the data going through + the device." + } + } + + cdl_component CYGPKG_DEVS_USB_D12_TX_EP1 { + display "Endpoint 1 Interrupt IN, (tx_ep1)" + implements CYGHWR_IO_USB_SLAVE_IN_ENDPOINTS + requires CYGFUN_DEVS_USB_D12_EP0 + default_value CYGFUN_DEVS_USB_D12_EP0 + description " + On the D12, Endpoint 1 IN can be used for Interrupt, + Bulk, or Control packages. This driver currently only supports + Interrupt packages on Endpoint 1 (slave -> host) transfers." + + cdl_option CYGVAR_DEVS_USB_D12_TX_EP1_DEVTAB_ENTRY { + display "Provide a devtab entry for Endpoint 1 IN" + default_value CYGGLO_IO_USB_SLAVE_PROVIDE_DEVTAB_ENTRIES + requires CYGPKG_IO + description " + If Endpoint 1 IN will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and write calls then a devtab entry is needed." + } + } + + cdl_component CYGPKG_DEVS_USB_D12_RX_EP1 { + display "Endpoint 1 Interrupt OUT, (rx_ep1)" + implements CYGHWR_IO_USB_SLAVE_OUT_ENDPOINTS + requires CYGFUN_DEVS_USB_D12_EP0 + default_value CYGFUN_DEVS_USB_D12_EP0 + description " + In the D12, Endpoint 1 OUT can be used for Interrupt, + Bulk, or Control packages. This driver currently only supports + Interrupt packages on Endpoint 1 for (host -> slave) transfers" + + cdl_option CYGVAR_DEVS_USB_D12_RX_EP1_DEVTAB_ENTRY { + display "Provide a devtab entry for Endpoint 1 OUT" + default_value CYGGLO_IO_USB_SLAVE_PROVIDE_DEVTAB_ENTRIES + requires CYGPKG_IO + description " + If Endpoint 1 OUT will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and write calls then a devtab entry is needed." + } + } + + cdl_component CYGPKG_DEVS_USB_D12_TX_EP2 { + display "Endpoint 2 Bulk IN, (tx_ep2)" + implements CYGHWR_IO_USB_SLAVE_IN_ENDPOINTS + requires CYGFUN_DEVS_USB_D12_EP0 + default_value CYGFUN_DEVS_USB_D12_EP0 + description " + In the D12, Endpoint 2 IN can be used for Bulk, Interrupt, + or Control packages. This driver currently only supports + Bulk packages on Endpoint 2 for (slave -> host) transfers." + + cdl_option CYGVAR_DEVS_USB_D12_TX_EP2_DEVTAB_ENTRY { + display "Provide a devtab entry for Endpoint 2 IN" + default_value CYGGLO_IO_USB_SLAVE_PROVIDE_DEVTAB_ENTRIES + requires CYGPKG_IO + description " + If Endpoint 2 IN will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and write calls then a devtab entry is needed." + } + } + + cdl_component CYGPKG_DEVS_USB_D12_RX_EP2 { + display "Endpoint 2 Bulk OUT, (rx_ep2)" + implements CYGHWR_IO_USB_SLAVE_OUT_ENDPOINTS + requires CYGFUN_DEVS_USB_D12_EP0 + default_value CYGFUN_DEVS_USB_D12_EP0 + description " + In the D12, Endpoint 2 OUT can be used for Bulk, Interrupt, + Control packages. This driver currently only supports + Bulk packages on Endpoint 2 for (host -> slave) transfers." + + cdl_option CYGVAR_DEVS_USB_D12_RX_EP2_DEVTAB_ENTRY { + display "Provide a devtab entry for Endpoint 2 OUT" + default_value CYGGLO_IO_USB_SLAVE_PROVIDE_DEVTAB_ENTRIES + requires CYGPKG_IO + description " + If Endpoint 2 OUT will only be accessed via the low-level + USB-specific calls then there is no need for an entry + in the device table, saving some memory. If the + application intends to access the endpoint by means + of open and write calls then a devtab entry is needed." + } + } + + cdl_option CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME { + display "Base name for devtab entries" + flavor data + active_if { CYGVAR_DEVS_USB_D12_EP0_DEVTAB_ENTRY || + CYGVAR_DEVS_USB_D12_TX_EP1_DEVTAB_ENTRY || + CYGVAR_DEVS_USB_D12_RX_EP1_DEVTAB_ENTRY || + CYGVAR_DEVS_USB_D12_TX_EP2_DEVTAB_ENTRY || + CYGVAR_DEVS_USB_D12_RX_EP2_DEVTAB_ENTRY } + default_value { "\"/dev/usbs\"" } + description " + If the D12 USB device driver package provides devtab entries + for any of the endpoints then this option gives + control over the names of these entries. By default the + endpoints will be called \"/dev/usbs0c\", \"/dev/usbs1r\" + \"/dev/usbs1w\", \"/dev/usbs2r\", \"/dev/usbs2w\" + (assuming those endpoints are all enabled. The common + part \"/dev/usbs\" is determined by this configuration + option. It may be necessary to change this if there are + multiple USB slave-side devices on the target hardware to + prevent a name clash." + } +} + diff --git a/packages/devs/usb/d12/v2_0/include/usbs_d12.h b/packages/devs/usb/d12/v2_0/include/usbs_d12.h new file mode 100644 index 00000000..e66e55b2 --- /dev/null +++ b/packages/devs/usb/d12/v2_0/include/usbs_d12.h @@ -0,0 +1,73 @@ +#ifndef CYGONCE_USBS_D12_H +#define CYGONCE_USBS_D12_H +//========================================================================== +// +// include/usbs_d12.h +// +// The interface exported by the D12 USB device 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) 2006 eCosCentric Ltd +// +// 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): Frank Pagliughi (fmp) +// Contributors: fmp +// Date: 2004-05-24 +// Purpose: +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The Philips D12 is a full speed (12Mbps) USB peripheral controller + * chip, with a parallel interface allowing it to be connected to nearly + * any microcontroller or microprocessor. + */ +extern usbs_control_endpoint usbs_d12_ep0; + +extern usbs_rx_endpoint usbs_d12_rx_ep1; +extern usbs_tx_endpoint usbs_d12_tx_ep1; +extern usbs_rx_endpoint usbs_d12_rx_ep2; +extern usbs_tx_endpoint usbs_d12_tx_ep2; + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +#endif /* CYGONCE_USBS_D12_H */ diff --git a/packages/devs/usb/d12/v2_0/src/usbs_d12.c b/packages/devs/usb/d12/v2_0/src/usbs_d12.c new file mode 100644 index 00000000..955f196a --- /dev/null +++ b/packages/devs/usb/d12/v2_0/src/usbs_d12.c @@ -0,0 +1,2322 @@ +//========================================================================== +// +// usbs_d12.c +// +// Driver for the D12 USB Slave Board +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Frank M. Pagliughi (fmp) +// Date: 2004-05-22 +// +// This code is a device driver for the SoRo Systems USB-D12-104, a PC/104 +// (ISA) Full-Speed USB slave board, which turns a PC/104 stack into a USB +// slave device. The board contains a Philips PDIUSBD12 Peripheral Controller +// Chip mapped into the PC's I/O space, with jumper-selectable I/O base +// address, IRQ, and DMA settings. The eCos config tool is used to adjust +// settings for this driver to match the physical jumper settings. The chip +// could run in polled mode without an IRQ, but this wouldn't be a great idea +// other than maybe a debug environment. +// +// The board supports DMA transfers over the Main endpoint, but I temporarily +// removed that code to make the driver portable to other platforms. +// +// *** This driver should also work with the Philips ISA Eval Board +// for the D12, but I couldn't get one of them from Philips, so +// I couldn't test it. +// +// The D12 uses an indexed register set, which it describes as "commands." +// You first write a command (index) to the command register then you can +// read or write data to that register. Each multi-byte command read or write +// must be dione atomically, so all access to the chip must be serialized. +// +// The D12 requests service through a single interrupt. The driver can +// be configured to service the chip through a DSR or a thread. In either +// case, the "service" code assumes it has unfettered access to the chip. +// The interrupt, therefore never touches the chip. It just schedules the +// DSR or service thread. +// Currently, the code gets exclusive access to the chip by locking the +// scheduler. This is suboptimal (locking the whole OS to touch one I/O +// chip), and better method should be explored. +// +// This version of the driver does not support Isocronous transfers. +// +// Additional notes on the D12: +// +// - The D12 has 4 endpoints (2 IN, and 2 OUT) in addition to the main +// control endpoint: +// - Endp 0 (Control In & Out, 16 byte buffer) +// - Endp 1 (IN & OUT, Bulk or Interrupt, 16 byte ea) +// - Endp 2 (IN and/or OUT, Bulk, Interrupt, or Isoc, 64 bytes ea) +// +// - The "main" endpoint (as Philips calls it) is Endp 2. It's double +// buffered and has a DMA interface, and thus, is suited for high +// throughput. For applications that perform either Isoc In or Out, +// the buffers for Endp 2 can be combined for a 128 byte space. +// This driver, however, currently does not support this. +// +// - There may be a flaw in the double buffering of the rx main endpoint. +// According to the documentation it should be invisible to the software, +// but if both buffers fill (on an rx/OUT), they must both be read +// together, otherwise it appears that the buffers/packets are returned +// in reverse order. ReadMainEndpointBuf() returns the data properly. +// +// - All the interrupt sources on the chip - individual endpoints, bus reset, +// suspend, and DMA - are OR'ed together and can be checked via the +// interrupt status register. When using edge-sensitive interrupts, as +// we do here, the ISR/DSR must be sure all interrupts are cleared before +// returning otherwise no new interrupts will be latched. +// +// - If the DMA controller is not used for the Main Endpoint, you MUST enable +// the main endpoint interrupts in the DMA register (bits 6 & 7). +// Personally, I think this should be the default at reset, to make it +// compatible with the other endpoints, but Philips didn't see it that +// way. +// +// - When a Setup (Device Request) packet arrives in the control endpoint, a +// bit is set in the endpoint's status register indicating the packet is +// setup and not data. By the USB standard, a setup packet can not be +// NAK'ed or STALL'ed, so when the chip receives a setup packet, it +// flushes the Ctrl (EP0) IN buffer and disables the Validate and Clear +// Buffer commands. We must send an "acknowledge setup" to both +// EP0 IN and OUT before a Validate or Clear Buffer command is effective. +// See ReadSetupPacket(). +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +// -------------------------------------------------------------------------- +// Common Types +// -------------------------------------------------------------------------- + +typedef cyg_uint8 byte; +typedef cyg_uint8 uint8; +typedef cyg_int16 int16; +typedef cyg_uint16 uint16; +typedef cyg_int32 int32; +typedef cyg_uint32 uint32; + +// -------------------------------------------------------------------------- +// Tracing & Debug +// -------------------------------------------------------------------------- +// If the driver is configured to use a thread to service the chip, then it +// can also be configured to dump a lot of debug output. +// Care must be taken that USB timing requirements are not violated by +// dumping debug info. If the data is sent to a serial port, it should use +// a hardware driver and have a large output buffer (115200 baud & 2kB +// buffer works for me). + +#if defined(CYGFUN_DEVS_USB_D12_DEBUG) && CYGFUN_DEVS_USB_D12_DEBUG +#define TRACE_D12 diag_printf +#else +#define TRACE_D12 (1) ? (void)0 : diag_printf +#endif + +#if defined(CYGSEM_DEVS_USB_D12_DEBUG_DUMP_EP0_BUFS) && CYGSEM_DEVS_USB_D12_DEBUG_DUMP_EP0_BUFS +#define TRACE_EP0 1 +#endif + +#if defined(CYGSEM_DEVS_USB_D12_DEBUG_DUMP_BUFS) && CYGSEM_DEVS_USB_D12_DEBUG_DUMP_BUFS +#define TRACE_EP 1 +#endif + +#if defined(TRACE_EP0) || defined(TRACE_EP) +static void _trace_buf(const char *hdr, const byte* buf, unsigned n) +{ + unsigned i; + + if (buf != 0 && n != 0) { + if (hdr && hdr[0]) + TRACE_D12("%s ", hdr); + + TRACE_D12("["); + for (i=0; i> 8)); +} + +// ------------------------------------------------------------------------ +// Command & Data I/O +// ------------------------------------------------------------------------ +// +// These routines read & write the registers in the D12. The procedure is +// to write a register/command value to the command address (A0=1) then +// read or write any required data a byte at a time to the data address +// (A0=0). The data can be one byte or two. If two, the low byte is read/ +// written first. + +// NOTE: These MUST be atomic operations. It's up to the caller +// to insure this. + +// The hardware specific driver provides the basic access function. +// + +static inline void +d12_write_byte(d12_addr_type base_addr, byte cmd, byte val) +{ + d12_write_cmd(base_addr, cmd); + d12_write_data_byte(base_addr, val); +} + +static inline void +d12_write_word(d12_addr_type base_addr, byte cmd, uint16 val) +{ + d12_write_cmd(base_addr, cmd); + d12_write_data_word(base_addr, val); +} + +static inline byte +d12_read_byte(d12_addr_type base_addr, byte cmd) +{ + d12_write_cmd(base_addr, cmd); + return d12_read_data_byte(base_addr); +} + +static inline uint16 +d12_read_word(d12_addr_type base_addr, byte cmd) +{ + d12_write_cmd(base_addr, cmd); + return d12_read_data_word(base_addr); +} + +// ------------------------------------------------------------------------ +// Higher Level Commands +// ------------------------------------------------------------------------ + +// Stalls or Unstalls the endpoint. Bit0=1 for stall, =0 to unstall. + +static inline void +d12_set_endp_status(d12_addr_type base_addr, byte endp_idx, byte stat) +{ + d12_write_byte(base_addr, CMD_SET_ENDP_STAT + endp_idx, stat); +} + +// ------------------------------------------------------------------------ +// Stalls the control endpoint (both in & out). + +static void +d12_stall_ctrl_endp(d12_addr_type base_addr, bool stall) +{ + d12_set_endp_status(base_addr, D12_TX_CTRL_ENDP, stall ? 1 : 0); + d12_set_endp_status(base_addr, D12_RX_CTRL_ENDP, stall ? 1 : 0); +} + +// ------------------------------------------------------------------------ +// Stalls/unstalls the specified endpoint. + +void inline +d12_stall_endp(d12_addr_type base_addr, byte endp_idx, bool stall) +{ + d12_set_endp_status(base_addr, endp_idx, stall ? 1 : 0); +} + +// ------------------------------------------------------------------------ */ +// Tells the chip that the selected endpoint buffer has been completely +// read. This should be called after the application reads all the data +// from an endpoint. While there's data in the buffer the chip will +// automatically NAK any additional OUT packets from the host. + +static inline void +d12_clear_buffer(d12_addr_type base_addr) +{ + d12_write_cmd(base_addr, CMD_CLEAR_BUF); +} + +// ------------------------------------------------------------------------ +// Tells the chip that the data in the selected endpoint buffer is complete +// and ready to be sent to the host. + +static inline void +d12_validate_buffer(d12_addr_type base_addr) +{ + d12_write_cmd(base_addr, CMD_VALIDATE_BUF); +} + +// ------------------------------------------------------------------------ +// Sends an upstream resume signal for 10ms. This command is normally +// issued when the device is in suspend. + +static inline void +d12_send_resume(d12_addr_type base_addr) +{ + d12_write_cmd(base_addr, CMD_SEND_RESUME); +} + +// ------------------------------------------------------------------------ +// Gets the frame number of the last successfully received +// start-of-frame (SOF). + +static inline uint16 +d12_read_curr_frame_num(d12_addr_type base_addr) +{ + return d12_read_word(base_addr, CMD_READ_CURR_FRAME_NUM); +} + +// ------------------------------------------------------------------------ +// This routine acknowledges a setup packet by writing an Ack Setup command +// to the currently selected Endpoint. This must be done for both EP0 out +// and EP0 IN whenever a setup packet is received. + +static inline void +d12_ack_setup(d12_addr_type base_addr) +{ + d12_write_cmd(base_addr, CMD_ACK_SETUP); +} + +// ------------------------------------------------------------------------ +// Gets the value of the 16-bit interrupt register, which indicates the +// source of an interrupt (if interrupts are not used, this reg can be +// polled to find when service is required). + +static inline uint16 +d12_read_intr_reg(d12_addr_type base_addr) +{ + return d12_read_word(base_addr, CMD_READ_INTR_REG) & 0x01FF; +} + +// ------------------------------------------------------------------------ +// Gets/Sets the contents of the DMA register. + +static inline byte +d12_get_dma(d12_addr_type base_addr) +{ + return d12_read_byte(base_addr, CMD_SET_DMA); +} + +static inline void +d12_set_dma(d12_addr_type base_addr, byte mode) +{ + d12_write_byte(base_addr, CMD_SET_DMA, mode); +} + +// ------------------------------------------------------------------------ +// Sends the "Select Endpoint" command (0x00 - 0x0D) to the chip. +// This command initializes an internal pointer to the start of the +// selected buffer. +// +// Returns: Bitfield containing status of the endpoint + +static byte +d12_select_endp(d12_addr_type base_addr, byte endp_idx) +{ + return d12_read_byte(base_addr, CMD_SEL_ENDP + endp_idx); +} + +// ------------------------------------------------------------------------ +// Gets the status of the last transaction of the endpoint. It also resets +// the corresponding interrupt flag in the interrupt register, and clears +// the status, indicating that it was read. +// +// Returns: Bitfield containing the last transaction status. + +static inline byte +d12_read_last_trans_status(d12_addr_type base_addr, byte endp_idx) +{ + return d12_read_byte(base_addr, CMD_READ_LAST_TRANS_STAT + endp_idx); +} + +// ------------------------------------------------------------------------ +// Reads the status of the requested endpoint. +// Just for the heck of it, we mask off the reserved bits. +// +// Returns: Bitfield containing the endpoint status. + +static inline byte +d12_read_endp_status(d12_addr_type base_addr, byte endp_idx) +{ + return d12_read_byte(base_addr, CMD_READ_ENDP_STAT + endp_idx) & 0xE4; +} + +// ------------------------------------------------------------------------ +// Returns true if there is data available in the specified endpoint's +// ram buffer. This is determined by the buf full flags in the endp status +// register. + +static inline bool +d12_data_available(d12_addr_type base_addr, byte endp_idx) +{ + byte by = d12_read_endp_status(base_addr, endp_idx); + return (bool) (by & D12_ENDP_STAT_ANY_BUF_FULL); +} + +// ------------------------------------------------------------------------ +// Clears the transaction status for each of the endpoints by calling the +// d12_read_last_trans_status() function for each. + +static void +d12_clear_all_intr(d12_addr_type base_addr) +{ + uint8 endp; + + d12_read_intr_reg(base_addr); + + for (endp=D12_ENDP_MIN; endp<=D12_ENDP_MAX; ++endp) + d12_read_last_trans_status(base_addr, endp); +} + +// ------------------------------------------------------------------------ +// Loads a value into the Set Address / Enable register. This sets the +// device's USB address (lower 7 bits) and enables/disables the function +// (msb). + +static void +d12_set_addr_enable(d12_addr_type base_addr, byte usb_addr, bool enable) +{ + if (enable) + usb_addr |= 0x80; + + d12_write_byte(base_addr, CMD_SET_ADDR_EN, usb_addr); +} + +// ------------------------------------------------------------------------ +// Enables/disables the generic endpoints. + +static inline void +d12_set_endp_enable(d12_addr_type base_addr, bool enable) +{ + d12_write_byte(base_addr, CMD_SET_ENDP_EN, + (enable) ? ENDP_ENABLE : ENDP_DISABLE); +} + +// ------------------------------------------------------------------------ +// Sets the device's configuration and CLKOUT frequency. + +static void +d12_set_mode(d12_addr_type base_addr, byte config, byte clk_div) +{ + uint16 w = make_word(clk_div, config); + d12_write_word(base_addr, CMD_SET_MODE, w); +} + +// ------------------------------------------------------------------------ +// Reads a setup packet from the control endpoint. This procedure is +// somewhat different than reading a data packet. By the USB standard, a +// setup packet can not be NAK'ed or STALL'ed, so when the chip receives a +// setup packet, it flushes the Ctrl (EP0) IN buffer and disables the +// Validate and Clear Buffer commands. The processor must send an +// acknowledge setup to both EP0 IN and OUT before a Validate or Clear +// Buffer command is effective. +// +// Parameters: +// buf buffer to receive the contents of the setup packet. Must +// be at least 8 bytes. +// Returns: +// true if there are 8 bytes waiting in the EP0 OUT RAM buffer +// on the D12 (i.e., true if successful) +// false otherwise + +static bool +d12_read_setup_packet(d12_addr_type base_addr, byte *buf) +{ + uint8 n; + + d12_select_endp(base_addr, D12_RX_CTRL_ENDP); + + d12_read_byte(base_addr, CMD_READ_BUF); // Read & discard reserved byte + n = d12_read_data_byte(base_addr); // # bytes available + + if (n > USB_SETUP_PACKET_LEN) { + //TRACE("* Warning: Setup Packet too large: %u *\n", (unsigned) n); + n = USB_SETUP_PACKET_LEN; + } + + n = d12_read_data(base_addr, buf, n); + + d12_ack_setup(base_addr); + d12_clear_buffer(base_addr); + + // ----- Ack Setup to EP0 IN ------ + + d12_select_endp(base_addr, D12_TX_CTRL_ENDP); + d12_ack_setup(base_addr); + + return n == USB_SETUP_PACKET_LEN; +} + +// ------------------------------------------------------------------------ +// Reads the contents of the currently selected endpoint's RAM buffer into +// the buf[] array. +// +// The D12's buffer comes in as follows: +// [0] junk ("reserved" - can be anything). Just disregard +// [1] # data bytes to follow +// [2] data byte 0, ... +// up to +// [N+2] data byte N-1 +// +// Parameters: +// buf byte array to receive data. This MUST be at least the size +// of the chip's RAM buffer for the currently selected endpoint. +// If buf is NULL, the data is read & discarded. +// +// Returns: the actual number of bytes read (could be <= n) + +static uint8 +d12_read_selected_endp_buf(d12_addr_type base_addr, byte *buf) +{ + uint8 n; + + d12_read_byte(base_addr, CMD_READ_BUF); // Read & discard reserved byte + n = d12_read_data_byte(base_addr); // # bytes in chip's buf + d12_read_data(base_addr, buf, n); + d12_clear_buffer(base_addr); + + return n; +} + +// ------------------------------------------------------------------------ +// Selects the specified endpoint and reads the contents of it's RAM buffer +// into the buf[] array. For the Main OUT endpoint, it will check whether +// both buffers are full, and if so, read them both. +// +// Side Effects: +// - Leaves endp_idx as the currently selected endpoint. +// +// Parameters: +// endp_idx the endpoint from which to read +// buf buffer to receive the data. This MUST be at least the size +// of the chip's RAM buffer for the specified endpoint. +// For the Main endp, it must be 2x the buffer size (128 total) +// +// Returns: the # of bytes read. + +static uint8 +d12_read_endp_buf(d12_addr_type base_addr, byte endp_idx, byte *buf) +{ + return (d12_select_endp(base_addr, endp_idx) & SEL_ENDP_FULL) + ? d12_read_selected_endp_buf(base_addr, buf) : 0; +} + +// ------------------------------------------------------------------------ +// Does a read of the "main" endpoint (#2). Since it's double buffered, +// this will check if both buffers are full, and if so it will read them +// both. Thus the caller's buffer, buf, must be large enough to hold all +// the data - 128 bytes total. +// +// If either buffer contains less than the full amount, the done flag +// is set indicating that a Bulk OUT transfer is complete. +// +// This determines if a bulk transfer is done, since the caller can't +// necessarily determine this from the size of the return buffer. +// If either buffer is less than full, '*done' is set to a non-zero value. + +static uint8 +d12_read_main_endp_buf(d12_addr_type base_addr, byte *buf, int *done) +{ + int nBuf = 1; + uint8 n = 0; + byte stat = d12_read_endp_status(base_addr, D12_RX_MAIN_ENDP) & + D12_ENDP_STAT_ANY_BUF_FULL; + + if (stat == 0) + return 0; + + if (stat == D12_ENDP_STAT_BOTH_BUF_FULL) + nBuf++; + + *done = false; + + while (nBuf--) { + if (d12_select_endp(base_addr, D12_RX_MAIN_ENDP) & SEL_ENDP_FULL) { + uint8 n1 = d12_read_selected_endp_buf(base_addr, buf+n); + n += n1; + if (n1 < D12_MAIN_ENDP_SIZE) { + *done = true; + break; + } + } + else + *done = true; + } + return n; +} + +// ------------------------------------------------------------------------ +// Writes the contents of the buf[] array to the currently selected +// endpoint's RAM buffer. The host will get the data on the on the next IN +// packet from the endpoint. +// +// Note: +// - The length of the buffer, n, must be no more than the size of the +// endpoint's RAM space, though, currently, this is not checked. +// - It's feasible that the application needs to send an empty (NULL) +// packet. It's valid for 'n' to be zero, and/or buf NULL. + +static uint8 +d12_write_selected_endp_buf(d12_addr_type base_addr, const byte *buf, uint8 n) +{ + d12_write_byte(base_addr, CMD_WRITE_BUF, 0); + d12_write_data_byte(base_addr, n); + d12_write_data(base_addr, buf, n); + d12_validate_buffer(base_addr); + + return n; +} + +// ------------------------------------------------------------------------ +// Writes the contents of the buf[] array to the specified endoint's RAM +// buffer. The host will get this data on the next IN packet from the +// endpoint. +// +// Side Effects: +// - Leaves endp_idx as the currently selected endpoint. + +static uint8 +d12_write_endp_buf(d12_addr_type base_addr, byte endp_idx, + const byte *buf, uint8 n) +{ + d12_select_endp(base_addr, endp_idx); + return d12_write_selected_endp_buf(base_addr, buf, n); +} + +// ------------------------------------------------------------------------ +// Reads & returns the contents of the Chip ID register. + +static inline uint16 +d12_read_chip_id(d12_addr_type base_addr) +{ + return d12_read_word(base_addr, CMD_READ_CHIP_ID); +} + + +// ========================================================================== +// eCos-Specific Device Driver Code +// ========================================================================== + +static void usbs_d12_reset(void); + +// Make some abbreviations for the configuration options. + +#if defined(CYGPKG_DEVS_USB_D12_RX_EP1) +#define _RX_EP1 +#endif + +#if defined(CYGPKG_DEVS_USB_D12_TX_EP1) +#define _TX_EP1 +#endif + +#if defined(CYGPKG_DEVS_USB_D12_RX_EP2) +#define _RX_EP2 +#endif + +#if defined(CYGPKG_DEVS_USB_D12_TX_EP2) +#define _TX_EP2 +#endif + +// -------------------------------------------------------------------------- +// Endpoint 0 Data +// -------------------------------------------------------------------------- + +static cyg_interrupt usbs_d12_intr_data; +static cyg_handle_t usbs_d12_intr_handle; + +static byte ep0_tx_buffer[CYGNUM_DEVS_USB_D12_EP0_TXBUFSIZE]; + +static void usbs_d12_start(usbs_control_endpoint*); +static void usbs_d12_poll(usbs_control_endpoint*); + +typedef enum endp_state { + ENDP_STATE_IDLE, + ENDP_STATE_IN, + ENDP_STATE_OUT +} endp_state; + +typedef struct ep0_impl { + usbs_control_endpoint common; + endp_state ep_state; + int length; + int transmitted; + bool tx_empty; +} ep0_impl; + +static ep0_impl ep0 = { + common: + { + state: USBS_STATE_POWERED, + enumeration_data: (usbs_enumeration_data*) 0, + start_fn: &usbs_d12_start, + poll_fn: &usbs_d12_poll, + interrupt_vector: CYGNUM_DEVS_USB_D12_IRQ, + control_buffer: { 0, 0, 0, 0, 0, 0, 0, 0 }, + state_change_fn: 0, + state_change_data: 0, + standard_control_fn: 0, + standard_control_data: 0, + class_control_fn: 0, + class_control_data: 0, + vendor_control_fn: 0, + vendor_control_data: 0, + reserved_control_fn: 0, + reserved_control_data: 0, + buffer: 0, + buffer_size: 0, + fill_buffer_fn: 0, + fill_data: 0, + fill_index: 0, + complete_fn: 0 + }, + ep_state: ENDP_STATE_IDLE, + length: 0, + transmitted: 0, + tx_empty: 0 +}; + +extern usbs_control_endpoint usbs_d12_ep0 __attribute__((alias ("ep0"))); + +// -------------------------------------------------------------------------- +// Rx Endpoints 1 & 2 Data +// -------------------------------------------------------------------------- + +#if defined(_RX_EP1) || defined(_RX_EP2) + +typedef struct rx_endpoint { + usbs_rx_endpoint common; + int endp, received; +} rx_endpoint; + +static void usbs_d12_api_start_rx_ep(usbs_rx_endpoint*); +static void usbs_d12_api_stall_rx_ep(usbs_rx_endpoint*, cyg_bool); + +static void usbs_d12_ep_rx_complete(rx_endpoint *ep, int result); +static void usbs_d12_stall_rx_ep(rx_endpoint*, cyg_bool); + +#endif + + +#if defined(_RX_EP1) + +static rx_endpoint rx_ep1 = { + common: { + start_rx_fn: &usbs_d12_api_start_rx_ep, + set_halted_fn: &usbs_d12_api_stall_rx_ep, + halted: 0 + }, + endp: 1 +}; + +extern usbs_rx_endpoint usbs_d12_rx_ep1 __attribute__((alias ("rx_ep1"))); + +#endif + + +#if defined(_RX_EP2) + +static rx_endpoint rx_ep2 = { + common: { + start_rx_fn: &usbs_d12_api_start_rx_ep, + set_halted_fn: &usbs_d12_api_stall_rx_ep, + halted: 0 + }, + endp: 2 +}; + +extern usbs_rx_endpoint usbs_d12_rx_ep2 __attribute__((alias ("rx_ep2"))); + +#endif + +// -------------------------------------------------------------------------- +// Tx Endpoints 1 & 2 Data +// -------------------------------------------------------------------------- + +#if defined(_TX_EP1) || defined(_TX_EP2) + +typedef struct tx_endpoint { + usbs_tx_endpoint common; + int endp, transmitted; + bool tx_empty; +} tx_endpoint; + +static void usbs_d12_api_start_tx_ep(usbs_tx_endpoint*); +static void usbs_d12_api_stall_tx_ep(usbs_tx_endpoint*, cyg_bool); + +static void usbs_d12_ep_tx_complete(tx_endpoint *ep, int result); +static void usbs_d12_stall_tx_ep(tx_endpoint*, cyg_bool); +#endif + +#if defined(_TX_EP1) + +static tx_endpoint tx_ep1 = { + common: { + start_tx_fn: &usbs_d12_api_start_tx_ep, + set_halted_fn: &usbs_d12_api_stall_tx_ep, + halted: 0 + }, + endp: 1 +}; + +extern usbs_tx_endpoint usbs_d12_tx_ep1 __attribute__((alias ("tx_ep1"))); +#endif + +#if defined(_TX_EP2) + +static tx_endpoint tx_ep2 = { + common: { + start_tx_fn: &usbs_d12_api_start_tx_ep, + set_halted_fn: &usbs_d12_api_stall_tx_ep, + halted: 0 + }, + endp: 2 +}; + +extern usbs_tx_endpoint usbs_d12_tx_ep2 __attribute__((alias ("tx_ep2"))); + +#endif + +// -------------------------------------------------------------------------- +// Synchronization + +static inline void usbs_d12_lock(void) { cyg_scheduler_lock(); } +static inline void usbs_d12_unlock(void) { cyg_scheduler_unlock(); } + +// -------------------------------------------------------------------------- +// Control Endpoint +// -------------------------------------------------------------------------- + +// Fills the EP0 transmit buffer with a packet. Partial data packets are +// retrieved by repeatedly calling the fill function. + +static int +ep0_fill_tx_buffer(void) +{ + int nFilled = 0; + + while (nFilled < CYGNUM_DEVS_USB_D12_EP0_TXBUFSIZE) { + if (ep0.common.buffer_size != 0) { + if ((nFilled + ep0.common.buffer_size) < + CYGNUM_DEVS_USB_D12_EP0_TXBUFSIZE) { + memcpy(&ep0_tx_buffer[nFilled], ep0.common.buffer, + ep0.common.buffer_size); + nFilled += ep0.common.buffer_size; + ep0.common.buffer_size = 0; + } + else { + break; + } + } + else if (ep0.common.fill_buffer_fn) { + (*ep0.common.fill_buffer_fn)(&ep0.common); + } + else { + break; + } + } + CYG_ASSERT((ep0.common.buffer_size == 0) && (!ep0.common.fill_buffer_fn), + "EP0 transmit buffer overflow"); + TRACE_D12("EP0: Filled Tx Buf with %d bytes\n", nFilled); + + ep0.length = nFilled; + + ep0.common.fill_buffer_fn = 0; + ep0.common.fill_data = 0; + ep0.common.fill_index = 0; + + return nFilled; +} + +// -------------------------------------------------------------------------- +// Called when a transfer is complete on the control endpoint EP0. +// It resets the endpoint's data structure and calls the completion function, +// if any. +// +// PARAMETERS: +// result 0, on success +// -EPIPE or -EIO to indicate a cancellation + +static usbs_control_return +usbs_d12_ep0_complete(int result) +{ + usbs_control_return ret = USBS_CONTROL_RETURN_UNKNOWN; + + ep0.ep_state = ENDP_STATE_IDLE; + + if (ep0.common.complete_fn) + ret = (*ep0.common.complete_fn)(&ep0.common, result); + + ep0.common.buffer = 0; + ep0.common.buffer_size = 0; + ep0.common.complete_fn = 0; + //ep0.common.fill_buffer_fn = 0; + + return ret; +} + +// -------------------------------------------------------------------------- +// This routine is called when we want to send the next packet to the tx ep0 +// on the chip. It is used to start a new transfer, and is also called when +// the chip interrupts to indicate that the ep0 tx buffer is empty and ready +// to receive a new packet. +// +// NOTE: +// On the D12, when you send a zero-length packet to a tx endpoint, the +// chip transmits the empty packet to the host, but doesn't interrupt +// indicating that it is complete. So immediately after sending the +// empty packet we complete the transfer. + +static void +usbs_d12_ep0_tx(void) +{ + int nRemaining = ep0.length - ep0.transmitted; + uint8 n; + + // ----- Intermittent interrupt? Get out ----- + + if (!ep0.common.buffer) { + TRACE_D12("EP0: Tx no buffer (%d)\n", nRemaining); + return; + } + + // ----- If prev packet was last, signal that we're done ----- + + if (nRemaining == 0 && !ep0.tx_empty) { + TRACE_D12("\tEP0: Tx Complete (%d) %p\n", ep0.transmitted, + ep0.common.complete_fn); + usbs_d12_ep0_complete(0); + return; + } + + // ----- Load the next tx packet onto the chip ----- + + if (nRemaining < D12_ENDP0_SIZE) { + n = (uint8) nRemaining; + ep0.tx_empty = false; + } + else + n = D12_ENDP0_SIZE; + + d12_write_endp_buf(D12_BASE_ADDR, D12_TX_ENDP0, + &ep0_tx_buffer[ep0.transmitted], n); + + TRACE_D12("EP0: Wrote %u bytes\n", (unsigned) n); + TRACE_BUF0("\t", &ep0_tx_buffer[ep0.transmitted], n); + + ep0.transmitted += n; + + // ----- If empty packet, D12 won't interrupt, so end now ----- */ + + if (n == 0) { + TRACE_D12("\tEP0: Tx Complete (%d) %p\n", ep0.transmitted, + ep0.common.complete_fn); + usbs_d12_ep0_complete(0); + } +} + +// -------------------------------------------------------------------------- +// This function is called when a packet has been successfully sent on the +// primary control endpoint (ep0). It indicates that the chip is ready for +// another packet. We read the LastTransStatus for the endpoint to clear +// the interrupt bit, then call ep0_tx() to continue the transfer. + +static void +usbs_d12_ep0_tx_intr(void) +{ + d12_read_last_trans_status(D12_BASE_ADDR, D12_TX_ENDP0); + usbs_d12_ep0_tx(); +} + +// -------------------------------------------------------------------------- +// Try to handle standard requests. This is a three step process: +// 1. If it's something we should handle internally we take care of it. +// Currently we can handle SET_ADDRESS requests, and a few others. +// 2. If the upper level code has installed a standard control handler +// we let that function have a crack at it. +// 3. If neither of those handle the packet we let +// usbs_handle_standard_control() have a last try at it. +// +// Locally: +// SET_ADDRESS: The host is demanding that we change our USB address. +// This is done by updating the Address/Enable register on the D12. +// Note, however that the USB protocol requires us to ack at the old +// address, change address, and then accept the next control message +// at the new address. The D12 address reg is buffered to do this +// automatically for us. The updated address on the chip won't take +// affect until after the empty ack is sent. Nice. +// + +static usbs_control_return +usbs_d12_handle_std_req(usb_devreq *req) +{ + usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN; + int recipient = req->type & USB_DEVREQ_RECIPIENT_MASK; + + if (req->request == USB_DEVREQ_SET_ADDRESS) { + TRACE_D12("Setting Addr: %u\n", (unsigned) req->value_lo); + d12_set_addr_enable(D12_BASE_ADDR, req->value_lo, true); + result = USBS_CONTROL_RETURN_HANDLED; + } + else if (req->request == USB_DEVREQ_GET_STATUS) { + if (recipient == USB_DEVREQ_RECIPIENT_DEVICE) { + const usbs_enumeration_data *enum_data = ep0.common.enumeration_data; + if (enum_data && enum_data->device.number_configurations == 1 && + enum_data->configurations) { + ep0.common.control_buffer[0] = + (enum_data->configurations[0].attributes + & USB_CONFIGURATION_DESCRIPTOR_ATTR_SELF_POWERED) ? 1 : 0; + ep0.common.control_buffer[0] |= + (enum_data->configurations[0].attributes + & USB_CONFIGURATION_DESCRIPTOR_ATTR_REMOTE_WAKEUP) ? 2 : 0; + ep0.common.control_buffer[1] = 0; + result = USBS_CONTROL_RETURN_HANDLED; + } + } + else if (recipient == USB_DEVREQ_RECIPIENT_ENDPOINT) { + bool halted = false; + result = USBS_CONTROL_RETURN_HANDLED; + + switch (req->index_lo) { +#if defined(_RX_EP1) + case 0x01 : halted = rx_ep1.common.halted; break; +#endif +#if defined(_TX_EP1) + case 0x81 : halted = tx_ep1.common.halted; break; +#endif +#if defined(_RX_EP2) + case 0x02 : halted = rx_ep2.common.halted; break; +#endif +#if defined(_TX_EP2) + case 0x82 : halted = tx_ep2.common.halted; break; +#endif + + default: + result = USBS_CONTROL_RETURN_STALL; + } + + TRACE_D12("Get Status: Endp [0x%02X] %s\n", (unsigned) req->index_lo, + halted ? "Halt" : "Unhalt"); + if (result == USBS_CONTROL_RETURN_HANDLED) { + ep0.common.control_buffer[0] = (halted) ? 1 : 0; + ep0.common.control_buffer[1] = 0; + } + } + + if (result == USBS_CONTROL_RETURN_HANDLED) { + ep0.common.buffer = ep0.common.control_buffer; + ep0.common.buffer_size = 2; + ep0.common.fill_buffer_fn = 0; + ep0.common.complete_fn = 0; + } + } + else if ((req->request == USB_DEVREQ_SET_FEATURE || + req->request == USB_DEVREQ_CLEAR_FEATURE) && + recipient == USB_DEVREQ_RECIPIENT_ENDPOINT) { + + bool halt = (req->request == USB_DEVREQ_SET_FEATURE); + result = USBS_CONTROL_RETURN_HANDLED; + TRACE_D12("Endpoint [0x%02X] %s\n", (unsigned) req->index_lo, + halt ? "Halt" : "Unhalt"); + + switch (req->index_lo) { +#if defined(_RX_EP1) + case 0x01 : usbs_d12_stall_rx_ep(&rx_ep1, halt); break; +#endif +#if defined(_TX_EP1) + case 0x81 : usbs_d12_stall_tx_ep(&tx_ep1, halt); break; +#endif +#if defined(_RX_EP2) + case 0x02 : usbs_d12_stall_rx_ep(&rx_ep2, halt); break; +#endif +#if defined(_TX_EP2) + case 0x82 : usbs_d12_stall_tx_ep(&tx_ep2, halt); break; +#endif + + default: + result = USBS_CONTROL_RETURN_STALL; + } + } + else if (ep0.common.standard_control_fn != 0) { + result = (*ep0.common.standard_control_fn) + (&ep0.common, + ep0.common.standard_control_data); + } + + if (result == USBS_CONTROL_RETURN_UNKNOWN) + result = usbs_handle_standard_control(&ep0.common); + + return result; +} + +// -------------------------------------------------------------------------- +// Handler for the receipt of a setup (dev request) packet from the host. +// We examine the packet to determine what function(s) should get a crack +// at trying to handle it, then pass control to the proper function. If +// the function handles the message we either ACK (len==0) or prepare for +// an IN or OUT data phase. If no one handled the message, we stall the +// control endpoint. + +static void +usbs_d12_ep0_setup_packet(usb_devreq* req) +{ + int len, dir, protocol, recipient; + usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN; + + // ----- See who should take the request ----- + + len = make_word(req->length_hi, req->length_lo); + + dir = req->type & USB_DEVREQ_DIRECTION_MASK; + protocol = req->type & USB_DEVREQ_TYPE_MASK; + recipient = req->type & USB_DEVREQ_RECIPIENT_MASK; + + TRACE_BUF0("DevReq: ", ep0.common.control_buffer, sizeof(usb_devreq)); + + if (protocol == USB_DEVREQ_TYPE_STANDARD) + result = usbs_d12_handle_std_req(req); + else { + // Pass on non-standard requests to registered handlers + + usbs_control_return (*callback_fn)(usbs_control_endpoint*, void*); + void *callback_arg; + + if (protocol == USB_DEVREQ_TYPE_CLASS) { + callback_fn = ep0.common.class_control_fn; + callback_arg = ep0.common.class_control_data; + } + else if (protocol == USB_DEVREQ_TYPE_VENDOR) { + callback_fn = ep0.common.vendor_control_fn; + callback_arg = ep0.common.vendor_control_data; + } + else { + callback_fn = ep0.common.reserved_control_fn; + callback_arg = ep0.common.reserved_control_data; + } + + result = (callback_fn) ? (*callback_fn)(&ep0.common, callback_arg) + : USBS_CONTROL_RETURN_STALL; + } + + // ----- If handled prep/handle data phase, otherwise stall ----- + + if (result == USBS_CONTROL_RETURN_HANDLED) { + if (len == 0) { + TRACE_D12("\tCtrl ACK\n"); + d12_write_endp_buf(D12_BASE_ADDR, D12_TX_ENDP0, 0, 0); + } + else { + // Set EP0 state to IN or OUT mode for data phase + ep0.transmitted = 0; + ep0.length = len; + + if (dir == USB_DEVREQ_DIRECTION_OUT) { + // Wait for the next packet from the host. + ep0.ep_state = ENDP_STATE_OUT; + CYG_ASSERT(ep0.common.buffer != 0, + "A rx buffer should have been provided for EP0"); + CYG_ASSERT(ep0.common.complete_fn != 0, + "A completion function should be provided for EP0 OUT control messages"); + } + else { + ep0.tx_empty = true; + ep0.ep_state = ENDP_STATE_IN; + ep0_fill_tx_buffer(); + usbs_d12_ep0_tx(); + } + } + } + else { + TRACE_D12("\t*** Unhandled Device Request ***\n"); + // The request wasn't handled, so stall control endpoint + d12_stall_ctrl_endp(D12_BASE_ADDR, true); + } +} + +// -------------------------------------------------------------------------- +// This is called when the chip indicates that a packet has been received +// on control endpoint 0. If it's a setup packet, we handle it accordingly, +// otherwise it's a data packet coming in on ep0. +// + +static void +usbs_d12_ep0_rx_intr(void) +{ + byte byStat = d12_read_last_trans_status(D12_BASE_ADDR, D12_RX_ENDP0); + TRACE_D12("\tEP0 Status: 0x%02X\n", (unsigned) byStat); + + if (byStat & D12_LAST_TRANS_SETUP_PACKET) { + usb_devreq *req = (usb_devreq *) ep0.common.control_buffer; + + if (!d12_read_setup_packet(D12_BASE_ADDR, (byte*) req)) { + TRACE_D12("ep0_rx_dsr: Error reading setup packet\n"); + d12_stall_ctrl_endp(D12_BASE_ADDR, true); + } + else + usbs_d12_ep0_setup_packet(req); + } + else { + if (ep0.common.buffer) { + uint8 n = d12_read_endp_buf(D12_BASE_ADDR, D12_RX_ENDP0, + ep0.common.buffer + ep0.transmitted); + ep0.transmitted += n; + + TRACE_D12("EP0: Received %d bytes\n", (unsigned) n); + + if (n < D12_ENDP0_SIZE || + ep0.common.buffer_size - ep0.transmitted < D12_ENDP0_SIZE) { + TRACE_D12("\tEP0: Rx Complete (%d) %p\n", + ep0.transmitted, ep0.common.complete_fn); + + if (usbs_d12_ep0_complete(0) == USBS_CONTROL_RETURN_HANDLED) + d12_write_endp_buf(D12_BASE_ADDR, D12_TX_ENDP0, 0, 0); + else + d12_stall_ctrl_endp(D12_BASE_ADDR, true); + } + } + else { + TRACE_D12("EP0: No Rx buffer. Discarding packet\n"); + d12_read_endp_buf(D12_BASE_ADDR, D12_RX_ENDP0, NULL); + } + } +} + +// -------------------------------------------------------------------------- +// Handler for when the device is put into or taken out of suspend mode. +// It updates the state variable in the control endpoint and calls the +// registered state change function, if any. + +// TODO: Put the chip into low power mode??? Stop clocks, etc??? + +static void +usbs_d12_suspend(bool suspended) +{ + int old_state = ep0.common.state; + usbs_state_change state_change; + + if (suspended) { + ep0.common.state |= USBS_STATE_SUSPENDED; + state_change = USBS_STATE_CHANGE_SUSPENDED; + } + else { + ep0.common.state &= USBS_STATE_MASK; + state_change = USBS_STATE_CHANGE_RESUMED; + } + + if (ep0.common.state_change_fn) { + (*ep0.common.state_change_fn)(&ep0.common, ep0.common.state_change_data, + state_change, old_state); + } +} + +// -------------------------------------------------------------------------- +// Common Rx Endpoint 1 & 2 +// -------------------------------------------------------------------------- + +#if defined(_RX_EP1) || defined(_RX_EP2) + +static void usbs_d12_clear_rx_ep(rx_endpoint *ep) +{ + ep->common.buffer = 0; + ep->common.buffer_size = 0; + ep->common.complete_fn = 0; + ep->common.complete_data = 0; + + ep->received = 0; +} + +// -------------------------------------------------------------------------- +// This is called when an rx operation is completed. It resets the endpoint +// vars and calls the registered completion function. +// + +static void +usbs_d12_ep_rx_complete(rx_endpoint *ep, int result) +{ + completion_fn fn = ep->common.complete_fn; + void *data = ep->common.complete_data; + + usbs_d12_clear_rx_ep(ep); + + if (fn) + (*fn)(data, result); +} + +// -------------------------------------------------------------------------- +// This routine is called when an rx buffer in the chip is full and ready to +// be read. If there's an endpoint buffer available and room to hold the data +// we read it in, otherwise we call the completion function, but leave the +// data in the chip. The hardware will automatically NAK packages from the +// host until the app calls another start read to continue receiving data. +// +// CONTEXT: +// Called from either the DSR or application thread, via start rx. +// In either case, it's assumed that the chip is locked. +// + +static void +usbs_d12_ep_rx(rx_endpoint *ep) +{ + int n, ep_size, buf_remaining, endp = ep->endp; + bool done; + + // The main endp is double buffered and we need to be prepared + // to read both simultaneously. + ep_size = (endp == D12_MAIN_ENDP) ? (2 * D12_MAIN_ENDP_SIZE) + : RX_ENDP_SIZE[endp]; + + buf_remaining = ep->common.buffer_size - ep->received; + + // ----- If no space left in buffer, call completion fn ----- + + if (!ep->common.buffer || buf_remaining < ep_size) { + int ret = ep->received; + + // See if caller requested a read smaller than the endp. Read & + // throw away extra + if (ep->common.buffer_size < ep_size) { + byte tmp_buf[D12_MAX_PACKET_SIZE]; + + if (endp == D12_MAIN_ENDP) + n = d12_read_main_endp_buf(D12_BASE_ADDR, tmp_buf, &done); + else + n = d12_read_endp_buf(D12_BASE_ADDR, RX_ENDP_INDEX[endp], tmp_buf); + + if (n > ep->common.buffer_size) { + n = ep->received = ep->common.buffer_size; + ret = -ENOMEM; + TRACE_D12("\tEP%d: *** Rx Buffer too small. Data Lost ***\n", endp); + } + else + ret = ep->received = n; + + memcpy(ep->common.buffer, tmp_buf, n); + buf_remaining = ep->common.buffer_size - n; + } + + TRACE_D12("\tEP%d: Rx Complete. Buffer (nearly) full. [%d]\n", + endp, buf_remaining); + usbs_d12_ep_rx_complete(ep, ret); + return; + } + + // ----- Read the data from the chip ----- + + if (endp == D12_MAIN_ENDP) + n = d12_read_main_endp_buf(D12_BASE_ADDR, + ep->common.buffer + ep->received, &done); + else { + n = d12_read_endp_buf(D12_BASE_ADDR, RX_ENDP_INDEX[endp], + ep->common.buffer + ep->received); + done = (n < RX_ENDP_SIZE[endp]); + } + + ep->received += n; + buf_remaining = ep->common.buffer_size - ep->received; + + done = done || (buf_remaining < ep_size); + + TRACE_D12("EP%d: Received %d bytes.\n", endp, n); + TRACE_BUF("\t", ep->common.buffer + ep->received-n, n); + + // ----- If we're done, complete the receive ----- + + if (done) { + TRACE_D12("\tEP%d Rx Complete (%d) %p\n", endp, + ep->received, ep->common.complete_fn); + usbs_d12_ep_rx_complete(ep, ep->received); + } +} + +// -------------------------------------------------------------------------- +// Stalls/unstalls the specified endpoint. + +static void +usbs_d12_stall_rx_ep(rx_endpoint *ep, cyg_bool halt) +{ + ep->common.halted = halt; + d12_stall_endp(D12_BASE_ADDR, RX_ENDP_INDEX[ep->endp], halt); +} + +// -------------------------------------------------------------------------- +// Handler for an Rx endpoint full interrupt. It clears the interrupt on the +// D12 by reading the endpoint's status register then calls the routine to +// read the data into the buffer. +// +// Called from the DSR context only. +// + +static void +usbs_d12_ep_rx_intr(rx_endpoint *ep) +{ + d12_read_last_trans_status(D12_BASE_ADDR, RX_ENDP_INDEX[ep->endp]); + usbs_d12_ep_rx(ep); +} + +#endif + +// -------------------------------------------------------------------------- +// Common Tx Endpoint 1 & 2 +// -------------------------------------------------------------------------- + +#if defined(_TX_EP1) || defined(_TX_EP2) + +// Clears out the endpoint data structure before/after a tx is complete. + +static void usbs_d12_clear_tx_ep(tx_endpoint *ep) +{ + ep->common.buffer = 0; + ep->common.buffer_size = 0; + ep->common.complete_fn = 0; + ep->common.complete_data = 0; + + ep->transmitted = 0; + ep->tx_empty = false; +} + +// -------------------------------------------------------------------------- +// This is called when a transmit is completed. It resets the endpoint vars +// and calls the registered completion function, if any. +// +// CONTEXT: +// Called from either the DSR or the app thread that started tx. + +static void usbs_d12_ep_tx_complete(tx_endpoint *ep, int result) +{ + completion_fn fn = ep->common.complete_fn; + void *data = ep->common.complete_data; + + usbs_d12_clear_tx_ep(ep); + + if (fn) + (*fn)(data, result); +} + +// -------------------------------------------------------------------------- +// The routine writes data to the chip and updates the endpoint's counters. +// It gets called at the start of a transfer operation to prime the device +// and then gets called each time the chip finishes sending a packet to the +// host and is ready for more data. If the amount of data remaining is +// smaller than can fit in the chip's endpoint buffer, then this is the last +// packet to send, so we call the completion function. +// +// CONTEXT: +// Called from either the DSR or the app thread that started the tx +// In either case, it's assumed the chip is locked. + +static void +usbs_d12_ep_tx(tx_endpoint *ep) +{ + int n, nRemaining; + + // ----- Already done. Intermittent interrupt, so get out ----- + + if (!ep->common.buffer) + return; + + // ----- See how many bytes remaining in buffer ----- + + nRemaining = ep->common.buffer_size - ep->transmitted; + + TRACE_D12("EP%d: Tx %p, %d Done, %d Remaining\n", ep->endp, + ep->common.buffer, ep->transmitted, nRemaining); + + // ----- If prev packet was last, signal that we're done ----- + + if (nRemaining == 0 && !ep->tx_empty) { + TRACE_D12("\tEP%d: Tx complete (%d) %p\n", ep->endp, + ep->transmitted, ep->common.complete_fn); + usbs_d12_ep_tx_complete(ep, ep->transmitted); + return; + } + + // ----- Write the next packet to chip ----- + + if (nRemaining < TX_ENDP_SIZE[ep->endp]) { + n = nRemaining; + ep->tx_empty = false; + } + else + n = TX_ENDP_SIZE[ep->endp]; + + TRACE_D12("EP%d: Writing %d bytes. %s\n", ep->endp, + n, (n == 0) ? "DONE" : ""); + TRACE_BUF("\t", ep->common.buffer + ep->transmitted, n); + + d12_write_endp_buf(D12_BASE_ADDR, TX_ENDP_INDEX[ep->endp], + ep->common.buffer + ep->transmitted, (uint8) n); + + ep->transmitted += n; + + // ----- If empty packet, complete now ----- + + if (n == 0) { + TRACE_D12("\tEP%d: Tx complete (%d) %p\n", ep->endp, + ep->transmitted, ep->common.complete_fn); + usbs_d12_ep_tx_complete(ep, ep->transmitted); + return; + } +} + +// -------------------------------------------------------------------------- +// Stalls/unstalls the specified tx endpoint. + +static void +usbs_d12_stall_tx_ep(tx_endpoint *ep, cyg_bool halt) +{ + ep->common.halted = halt; + d12_stall_endp(D12_BASE_ADDR, TX_ENDP_INDEX[ep->endp], halt); +} + +// -------------------------------------------------------------------------- +// Handler for when the chip's tx RAM for an endoint has just been emptied +// (sent to the host) and the chip is ready for more data. +// We read the endpoint's last trans status register to clear the interrupt +// on the D12, then call the tx function to send the next packet or +// complete the transfer. + +static void +usbs_d12_ep_tx_intr(tx_endpoint *ep) +{ + d12_read_last_trans_status(D12_BASE_ADDR, TX_ENDP_INDEX[ep->endp]); + usbs_d12_ep_tx(ep); +} + +#endif // defined(_TX_EP1) || defined(_TX_EP2) + +// -------------------------------------------------------------------------- +// Application Program Interface (API) +// -------------------------------------------------------------------------- + +#if defined(_RX_EP1) || defined(_RX_EP2) +// Starts a receive operation on the specified endpoint. If the buffer size +// is zero the completion function is called immediately. The routine checks +// if tehre is data in the chip's endpoint buffer, and if so it will call +// ep_rx() to start reading the data out of the chip. +// +// If the endpoint is currently stalled, a read size of zero can be used to +// block the calling thread until the stall is cleared. If the read size is +// non-zero and the endpoint is stalled the completion function is called +// immediately with an error result. + +static void +usbs_d12_api_start_rx_ep(usbs_rx_endpoint *ep) +{ + rx_endpoint *epx = (rx_endpoint *) ep; + + if (ep->halted) { + if (ep->buffer_size != 0) + usbs_d12_ep_rx_complete(epx, -EAGAIN); + } + else if (ep->buffer_size == 0) { + usbs_d12_ep_rx_complete(epx, 0); + } + else { + TRACE_D12("EP%d: Starting Rx, %p, %d\n", epx->endp, ep->buffer, + ep->buffer_size); + usbs_d12_lock(); + + epx->received = 0; + if (d12_data_available(D12_BASE_ADDR, RX_ENDP_INDEX[epx->endp])) + usbs_d12_ep_rx(epx); + + usbs_d12_unlock(); + } +} + +// -------------------------------------------------------------------------- +// Halts/unhalts one of the generic rx (OUT) endpoints. +// + +static void usbs_d12_api_stall_rx_ep(usbs_rx_endpoint *ep, cyg_bool halt) +{ + usbs_d12_lock(); + usbs_d12_stall_rx_ep((rx_endpoint*) ep, halt); + usbs_d12_unlock(); +} + +#endif // defined(_RX_EP1) || defined(_RX_EP2) + +// -------------------------------------------------------------------------- +// Tx API +// -------------------------------------------------------------------------- + +#if defined(_TX_EP1) || defined(_TX_EP2) + +// This starts a transmit on one of the data endpoints. If the endpoint is +// stalled a buffer size of zero can be used to block until the stall is +// cleared. Any other size on a stalled endpoint will result in an error +// callback immediately. The first packet is sent to the chip immediately, +// in the application context. If the chip's buffer can contain the whole +// transfer, the completion function will be called immediately, again, +// still in the application context. +// +// If an empty packet is requested we send one from here and call the +// completion function. This should not cause an intr on the D12. +// +// CONTEXT: +// Called from an application thread + +static void usbs_d12_api_start_tx_ep(usbs_tx_endpoint *ep) +{ + tx_endpoint *epx = (tx_endpoint*) ep; + + if (ep->halted) { + if (ep->buffer_size != 0) + usbs_d12_ep_tx_complete(epx, -EAGAIN); + } + else if (ep->buffer_size == 0) { + usbs_d12_lock(); + + d12_write_endp_buf(D12_BASE_ADDR, TX_ENDP_INDEX[epx->endp], 0, 0); + usbs_d12_ep_tx_complete(epx, 0); + + usbs_d12_unlock(); + } + else { + TRACE_D12("EP%d: Starting Tx, %p, %d\n", epx->endp, ep->buffer, + ep->buffer_size); + usbs_d12_lock(); + + epx->tx_empty = true; + epx->transmitted = 0; + usbs_d12_ep_tx(epx); + + usbs_d12_unlock(); + } +} + +// -------------------------------------------------------------------------- +// Halts/unhalts one of the generic endpoints. + +static void +usbs_d12_api_stall_tx_ep(usbs_tx_endpoint *ep, cyg_bool halt) +{ + usbs_d12_lock(); + usbs_d12_stall_tx_ep((tx_endpoint*) ep, halt); + usbs_d12_unlock(); +} + +#endif // defined(_TX_ENDP1) || defined(_TX_EP2) + +// -------------------------------------------------------------------------- +// DSR +// -------------------------------------------------------------------------- + +// The DSR for the D12 chip. This is normally called in the DSR context when +// the D12 has raised its interrupt flag indicating that it needs to be +// serviced. The interrupt register contains bit flags that are OR'ed togther +// indicating what items need to be serviced. There are flags for the +// following: +// - The endpoints (one bit for each) +// - Bus Reset +// - Suspend Change +// - DMA (terminal count) +// +// Care must be taken in that the D12's interrupt output is level-sensitive +// (in that the interrupt sources are OR'ed together and not all cleared +// atomically in a single operation). Platforms (such as the PC) may be +// expecting edge-triggered interrupts, so we must work around that. +// So, we loop on the interrupt register. Even though, in each loop, we +// perform all of the required operations to clear the interrupts, a new +// one may have arrived before we finished clearing the previous ones. +// So we read the intr reg again. Once the intr reg gives a zero reading +// we know that the D12 has dropped its IRQ line. +// +// Note, if we're configured to use a thread, this routine is called from +// within a thread context (not a DSR context). +// + +static void +usbs_d12_dsr(cyg_vector_t vector, cyg_ucount32 count, + cyg_addrword_t data) +{ + uint16 status; + bool suspended; + + CYG_ASSERT(vector == CYGNUM_DEVS_USB_D12_INT, + "DSR should only be invoked for D12 interrupts"); + + while ((status = d12_read_intr_reg(D12_BASE_ADDR)) != 0) { + TRACE_D12("Intr Status: 0x%04X\n", (unsigned) status); + + if (status & D12_INTR_BUS_RESET) { + TRACE_D12("\n>>> Bus Reset <<<\n"); + usbs_d12_reset(); + } + else { + + // ----- Suspend Change ----- + + suspended = (bool) (ep0.common.state & USBS_STATE_SUSPENDED); + + if (status & D12_INTR_SUSPEND_CHANGE) { + if (!suspended && (status & ~D12_INTR_SUSPEND_CHANGE) == 0) + usbs_d12_suspend(true); + } + else if (suspended) + usbs_d12_suspend(false); + + // ----- Bulk Endpoints ----- + +#ifdef _TX_EP2 + if (status & D12_INTR_TX_ENDP2) + usbs_d12_ep_tx_intr(&tx_ep2); +#endif + +#ifdef _RX_EP2 + if (status & D12_INTR_RX_ENDP2) + usbs_d12_ep_rx_intr(&rx_ep2); +#endif + + // ----- Interrupt Endpoints ----- + +#ifdef _TX_EP1 + if (status & D12_INTR_TX_ENDP1) + usbs_d12_ep_tx_intr(&tx_ep1); +#endif + +#ifdef _RX_EP1 + if (status & D12_INTR_RX_ENDP1) + usbs_d12_ep_rx_intr(&rx_ep1); +#endif + + // ----- Control Endpoint ----- + + if (status & D12_INTR_TX_CTRL_ENDP) + usbs_d12_ep0_tx_intr(); + + if (status & D12_INTR_RX_CTRL_ENDP) + usbs_d12_ep0_rx_intr(); + } + } + + cyg_drv_interrupt_unmask(vector); +} + +// -------------------------------------------------------------------------- +// Interrupt +// -------------------------------------------------------------------------- + +// Here, the ISR does nothing but schedule the DSR to run. The ISR's/DSR's +// are serialized. The CPU won't process another ISR until after the DSR +// completes. + +static uint32 +usbs_d12_isr(cyg_vector_t vector, cyg_addrword_t data) +{ + CYG_ASSERT(CYGNUM_DEVS_USB_D12_INT == vector, + "usbs_isr: Incorrect interrupt"); + + // Prevent another interrupt until DSR completes + cyg_drv_interrupt_mask(vector); + cyg_drv_interrupt_acknowledge(vector); + + return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; +} + +// -------------------------------------------------------------------------- +// Polling +// -------------------------------------------------------------------------- + +static void +usbs_d12_poll(usbs_control_endpoint *endp) +{ + CYG_ASSERT(endp == &ep0.common, "usbs_poll: wrong endpoint"); + + usbs_d12_lock(); + usbs_d12_dsr(CYGNUM_DEVS_USB_D12_INT, 0, 0); + usbs_d12_unlock(); +} + +// -------------------------------------------------------------------------- +// Thread Processing +// -------------------------------------------------------------------------- + +// The user can opt to configure the driver to service the D12 using a high +// priority thread. The thread's priority MUST be greater than the priority +// of any application thread making calls into the driver. +// When we use a thread, the DSR simply signals a semaphore tio wake the +// thread up. The thread, in turn, calls the the routine to service the D12, +// now in a thread context. This allows for greater debug options, including +// tracing. + +#ifdef CYGPKG_DEVS_USB_D12_THREAD + +static byte usbs_d12_thread_stack[CYGNUM_DEVS_USB_D12_THREAD_STACK_SIZE]; +static cyg_thread usbs_d12_thread; +static cyg_handle_t usbs_d12_thread_handle; +static cyg_sem_t usbs_d12_sem; + +static void +usbs_d12_thread_dsr(cyg_vector_t vector, cyg_ucount32 count, + cyg_addrword_t data) +{ + cyg_semaphore_post(&usbs_d12_sem); + + CYG_UNUSED_PARAM(cyg_vector_t, vector); + CYG_UNUSED_PARAM(cyg_ucount32, count); + CYG_UNUSED_PARAM(cyg_addrword_t, data); +} + + +static void +usbs_d12_thread_fn(cyg_addrword_t param) +{ + while (1) { + cyg_semaphore_wait(&usbs_d12_sem); + usbs_d12_poll(&ep0.common); + } + + CYG_UNUSED_PARAM(cyg_addrword_t, param); +} + + +static void +usbs_d12_thread_init(void) +{ + cyg_semaphore_init(&usbs_d12_sem, 0); + + cyg_thread_create(CYGNUM_DEVS_USB_D12_THREAD_PRIORITY, + &usbs_d12_thread_fn, 0, "D12 USB Driver Thread", + usbs_d12_thread_stack, + CYGNUM_DEVS_USB_D12_THREAD_STACK_SIZE, + &usbs_d12_thread_handle, &usbs_d12_thread); + cyg_thread_resume(usbs_d12_thread_handle); +} + +#endif // CYGPKG_DEVS_USB_D12_THREAD + +// -------------------------------------------------------------------------- +// Start/Reset +// -------------------------------------------------------------------------- + +// Chip initialization and handler for a USB Bus Reset. This gets called at +// system startup and after a USB Bus Reset. It puts the chip into the +// default state, with USB Address 0, connected to the bus (i.e. +// "SoftConnect" asserted). Interrupts to the main endpoint are turned on +// via the DMA register. + +static void +usbs_d12_reset(void) +{ + int old_state = ep0.common.state; + ep0.common.state = USBS_STATE_DEFAULT; + + if (ep0.common.state_change_fn) { + (*ep0.common.state_change_fn)(&ep0.common, ep0.common.state_change_data, + USBS_STATE_CHANGE_RESET, old_state); + } + + d12_set_addr_enable(D12_BASE_ADDR, 0, true); + d12_set_endp_enable(D12_BASE_ADDR, true); + d12_set_dma(D12_BASE_ADDR, D12_DMA_MAIN_ENDP_INTR_ENABLE); + d12_set_mode(D12_BASE_ADDR, D12_MODE_CFG_DFLT | D12_MODE_CFG_SOFT_CONNECT, + D12_MODE_CLK_DFLT); + + // If any endpoints were going, signal the end of transfers + +#if defined(_TX_EP2) + usbs_d12_ep_tx_complete(&tx_ep2, -EPIPE); +#endif + +#if defined(_RX_EP2) + usbs_d12_ep_rx_complete(&rx_ep2, -EPIPE); +#endif + +#if defined(_TX_EP1) + usbs_d12_ep_tx_complete(&tx_ep1, -EPIPE); +#endif + +#if defined(_RX_EP1) + usbs_d12_ep_rx_complete(&rx_ep1, -EPIPE); +#endif +} + +// -------------------------------------------------------------------------- +// The start function is called indirectly by the application when +// initialization is complete. By this time, the enumeration data has been +// assigned to the control endpoint and we're ready to connect to the host. +// Within the reset function the D12's SoftConnect line is asserted which +// allows the host (hub) to see us on the USB bus. If connected, the host +// should start the enumeration process. +// + +static void usbs_d12_start(usbs_control_endpoint *endpoint) +{ +#if defined(_TRACE) && !defined(_TRACE_STDOUT) + TRACE_OPEN(TRACE_SINK); +#endif + + CYG_ASSERT(endpoint == &ep0.common, "ep0 start: wrong endpoint"); + TRACE_D12("USBS D12: Starting.\n"); + + d12_clear_all_intr(D12_BASE_ADDR); + usbs_d12_reset(); +} + +// -------------------------------------------------------------------------- +// Initialization +// -------------------------------------------------------------------------- + +// This routine is called early in the program's startup, possibly before +// main (from within a C++ object initialization). We want to put this chip +// and driver in a neutral, but ready, state until the application gets +// control, initializes itself and calls the usb start function. +// +// The D12 has a "Soft Connect" feature to tristate the USB bus, making it +// appear that the USB device is not connected to the bus. We initially +// keep seperated from the bus to allow for initialization. + +void +usbs_d12_init(void) +{ + cyg_DSR_t *pdsr; + + d12_set_mode(D12_BASE_ADDR, D12_MODE_CFG_DFLT & ~D12_MODE_CFG_SOFT_CONNECT, + D12_MODE_CLK_DFLT); + + d12_set_addr_enable(D12_BASE_ADDR, 0, false); + d12_set_endp_enable(D12_BASE_ADDR, false); + + // ----- Clear the endpoints ----- + +#if defined(_TX_EP2) + usbs_d12_clear_tx_ep(&tx_ep2); +#endif + +#if defined(_RX_EP2) + usbs_d12_clear_rx_ep(&rx_ep2); +#endif + +#if defined(_TX_EP1) + usbs_d12_clear_tx_ep(&tx_ep1); +#endif + +#if defined(_RX_EP1) + usbs_d12_clear_rx_ep(&rx_ep1); +#endif + + // ----- Start the thread (if we're using it) ----- + +#ifdef CYGPKG_DEVS_USB_D12_THREAD + usbs_d12_thread_init(); + pdsr = &usbs_d12_thread_dsr; +#else + pdsr = &usbs_d12_dsr; +#endif + + // ----- Attach the ISR ----- + + cyg_drv_interrupt_create(CYGNUM_DEVS_USB_D12_INT, + 0, 0, &usbs_d12_isr, pdsr, + &usbs_d12_intr_handle, &usbs_d12_intr_data); + + cyg_drv_interrupt_attach(usbs_d12_intr_handle); + cyg_drv_interrupt_unmask(CYGNUM_DEVS_USB_D12_INT); +} + +// ---------------------------------------------------------------------------- +// Testing support. + +usbs_testing_endpoint usbs_testing_endpoints[] = { + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL, + endpoint_number : 0, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, + endpoint : (void*) &ep0.common, +#ifdef CYGVAR_DEVS_USB_D12_EP0_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "0c", +#else + devtab_entry : (const char*) 0, +#endif + min_size : 1, + max_size : CYGNUM_DEVS_USB_D12_EP0_TXBUFSIZE, + max_in_padding : 0, + alignment : 0 + }, + + /* +#ifdef _TX_EP1 + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT, + endpoint_number : 1, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, + endpoint : (void*) &tx_ep1.common, +# ifdef CYGVAR_DEVS_USB_D12_TX_EP2_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "1w", +# else + devtab_entry : (const char*) 0, +# endif + min_size : 0, + max_size : 0x0FFFF, // Driver limitation, only a single + // buffer descriptor is used + max_in_padding : 0, + alignment : HAL_DCACHE_LINE_SIZE + }, +#endif + +#ifdef _RX_EP1 + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT, + endpoint_number : 1, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT, + endpoint : (void*) &rx_ep1.common, +# ifdef CYGVAR_DEVS_USB_D12_RX_EP2_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "1r", +# else + devtab_entry : (const char*) 0, +# endif + min_size : 1, + max_size : 0x0FFFF, // Driver limitation + max_in_padding : 0, + alignment : HAL_DCACHE_LINE_SIZE + }, +#endif + */ + +#ifdef _TX_EP2 + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_BULK, + endpoint_number : 2, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN, + endpoint : (void*) &tx_ep2.common, +# ifdef CYGVAR_DEVS_USB_D12_TX_EP2_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "2w", +# else + devtab_entry : (const char*) 0, +# endif + min_size : 0, + max_size : 0x1000, // 4k for testing + max_in_padding : 0, + alignment : HAL_DCACHE_LINE_SIZE + }, +#endif + +#ifdef _RX_EP2 + { + endpoint_type : USB_ENDPOINT_DESCRIPTOR_ATTR_BULK, + endpoint_number : 2, + endpoint_direction : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT, + endpoint : (void*) &rx_ep2.common, +# ifdef CYGVAR_DEVS_USB_D12_RX_EP2_DEVTAB_ENTRY + devtab_entry : CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "2r", +# else + devtab_entry : (const char*) 0, +# endif + min_size : 1, + max_size : 0x1000, // 4k for testing + max_in_padding : 0, + alignment : HAL_DCACHE_LINE_SIZE + }, +#endif + + USBS_TESTING_ENDPOINTS_TERMINATOR +}; + diff --git a/packages/devs/usb/d12/v2_0/src/usbs_d12_data.cxx b/packages/devs/usb/d12/v2_0/src/usbs_d12_data.cxx new file mode 100644 index 00000000..391e3cb4 --- /dev/null +++ b/packages/devs/usb/d12/v2_0/src/usbs_d12_data.cxx @@ -0,0 +1,230 @@ +//========================================================================== +// +// usbs_d12_data.cxx +// +// Static data for the D12 USB device 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) 2006 eCosCentric Ltd +// +// 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): fmp +// Contributors: fmp +// Date: 2004-05-27 +// +// This file contains various objects that should go into extras.o +// rather than libtarget.a, e.g. devtab entries that would normally +// be eliminated by the selective linking. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Initialization. The goal here is to call usbs_d12_init() +// early on during system startup, to take care of things like +// registering interrupt handlers etc. which are best done +// during system init. +// +// If the endpoint 0 devtab entry is available then its init() +// function can be used to take care of this. However the devtab +// entries are optional so an alternative mechanism must be +// provided. Unfortunately although it is possible to give +// a C function the constructor attribute, it cannot be given +// an initpri attribute. Instead it is necessary to define a +// dummy C++ class. + +extern "C" void usbs_d12_init(void); + +#ifndef CYGVAR_DEVS_USB_D12_EP0_DEVTAB_ENTRY +class usbs_d12_initialization { +public: + usbs_d12_initialization() { + usbs_d12_init(); + } +}; + +static usbs_d12_initialization usbs_d12_init_object + CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO); +#endif + +// ---------------------------------------------------------------------------- +// The devtab entries. Each of these is optional, many applications +// will want to use the lower-level API rather than go via +// open/read/write/ioctl. + +#ifdef CYGVAR_DEVS_USB_D12_EP0_DEVTAB_ENTRY + +// For endpoint 0 the only legal operations are get_config() and +// set_config(), and these are provided by the common package. + +static bool +usbs_d12_devtab_ep0_init(struct cyg_devtab_entry* tab) +{ + CYG_UNUSED_PARAM(struct cyg_devtab_entry*, tab); + usbs_d12_init(); + return true; +} + +static +CHAR_DEVIO_TABLE(usbs_d12_ep0_devtab_functions, + &cyg_devio_cwrite, + &cyg_devio_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +static CHAR_DEVTAB_ENTRY(usbs_d12_ep0_devtab_entry, + CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "0c", + 0, + &usbs_d12_ep0_devtab_functions, + &usbs_d12_devtab_ep0_init, + 0, + (void*) &usbs_d12_ep0); +#endif + +// ---------------------------------------------------------------------------- +// Common routines for ep1 and ep2. + +#if defined(CYGVAR_DEVS_USB_D12_TX_EP1_DEVTAB_ENTRY) || \ + defined(CYGVAR_DEVS_USB_D12_RX_EP1_DEVTAB_ENTRY) || \ + defined(CYGVAR_DEVS_USB_D12_TX_EP2_DEVTAB_ENTRY) || \ + defined(CYGVAR_DEVS_USB_D12_RX_EP2_DEVTAB_ENTRY) + +static bool +usbs_d12_devtab_dummy_init(struct cyg_devtab_entry* tab) +{ + CYG_UNUSED_PARAM(struct cyg_devtab_entry*, tab); + return true; +} +#endif + +// ---------------------------------------------------------------------------- +// tx (in) ep1 devtab entry. This can only be used for slave->host, +// so only the cwrite() function makes sense. + +#ifdef CYGVAR_DEVS_USB_D12_TX_EP1_DEVTAB_ENTRY + +static +CHAR_DEVIO_TABLE(usbs_d12_tx_ep1_devtab_functions, + &usbs_devtab_cwrite, + &cyg_devio_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +static +CHAR_DEVTAB_ENTRY(usbs_d12_tx_ep1_devtab_entry, + CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "1w", + 0, + &usbs_d12_tx_ep1_devtab_functions, + &usbs_d12_devtab_dummy_init, + 0, + (void*) &usbs_d12_tx_ep1); +#endif + +// ---------------------------------------------------------------------------- +// rx (out) ep1 devtab entry. This can only be used for host->slave, +// so only the cread() function makes sense. + +#ifdef CYGVAR_DEVS_USB_D12_RX_EP1_DEVTAB_ENTRY + +static +CHAR_DEVIO_TABLE(usbs_d12_rx_ep1_devtab_functions, + &cyg_devio_cwrite, + &usbs_devtab_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +static +CHAR_DEVTAB_ENTRY(usbs_d12_rx_ep1_devtab_entry, + CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "1r", + 0, + &usbs_d12_rx_ep1_devtab_functions, + &usbs_d12_devtab_dummy_init, + 0, + (void*) &usbs_d12_rx_ep1); +#endif + + +// ---------------------------------------------------------------------------- +// tx (in) ep2 devtab entry. This can only be used for slave->host, so only the +// cwrite() function makes sense. + +#ifdef CYGVAR_DEVS_USB_D12_TX_EP2_DEVTAB_ENTRY + +static +CHAR_DEVIO_TABLE(usbs_d12_tx_ep2_devtab_functions, + &usbs_devtab_cwrite, + &cyg_devio_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +static +CHAR_DEVTAB_ENTRY(usbs_d12_tx_ep2_devtab_entry, + CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "2w", + 0, + &usbs_d12_tx_ep2_devtab_functions, + &usbs_d12_devtab_dummy_init, + 0, + (void*) &usbs_d12_tx_ep2); +#endif + +// ---------------------------------------------------------------------------- +// rx (out) ep2 devtab entry. This can only be used for host->slave, +// so only the cread() function makes sense. + +#ifdef CYGVAR_DEVS_USB_D12_RX_EP2_DEVTAB_ENTRY + +static +CHAR_DEVIO_TABLE(usbs_d12_rx_ep2_devtab_functions, + &cyg_devio_cwrite, + &usbs_devtab_cread, + &cyg_devio_select, + &usbs_devtab_get_config, + &usbs_devtab_set_config); + +static +CHAR_DEVTAB_ENTRY(usbs_d12_rx_ep2_devtab_entry, + CYGDAT_DEVS_USB_D12_DEVTAB_BASENAME "2r", + 0, + &usbs_d12_rx_ep2_devtab_functions, + &usbs_d12_devtab_dummy_init, + 0, + (void*) &usbs_d12_rx_ep2); +#endif diff --git a/packages/devs/usb/i386/SoRoD12/v2_0/ChangeLog b/packages/devs/usb/i386/SoRoD12/v2_0/ChangeLog new file mode 100644 index 00000000..e5bd83a0 --- /dev/null +++ b/packages/devs/usb/i386/SoRoD12/v2_0/ChangeLog @@ -0,0 +1,36 @@ +2006-06-06 Frank Pagliughi + + * First version of the USB device driver using the philips D12 + for i386 targets. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric Ltd +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/devs/usb/i386/SoRoD12/v2_0/cdl/usbs_i386_sorod12.cdl b/packages/devs/usb/i386/SoRoD12/v2_0/cdl/usbs_i386_sorod12.cdl new file mode 100644 index 00000000..6fdff518 --- /dev/null +++ b/packages/devs/usb/i386/SoRoD12/v2_0/cdl/usbs_i386_sorod12.cdl @@ -0,0 +1,91 @@ +# ==================================================================== +# +# usbs_i386_sorod12.cdl +# +# Hardware specific parts for the SoRo D12 PC 104 USB card. +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2003, 2004, 2006 eCosCentric Limited +## Copyright (C) 2006 eCosCentric Ltd +## +## 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): Frank M. Pagliughi (fmp), SoRo Systems, Inc., asl +# Contributors: +# Date: 2006-04-27 +# +#####DESCRIPTIONEND#### +# ==================================================================== + +cdl_package CYGPKG_DEVS_USB_I386_SOROD12 { + display "Hardware specific part for SoRo D12 USB Device Driver" + include_dir "cyg/io/usb" + parent CYGPKG_DEVS_USB_D12 + + requires { CYGIMP_DEVS_USB_D12_HW_ACCESS_HEADER == + "" } + + cdl_option CYGSEM_DEVS_USB_I386_SOROD12_IO_MAPPED { + display "I/O mapped." + flavor bool + default_value 1 + description " + The PDIUSBD12 can be mapped into the processor's I/O space or memory + space. If this is set the driver accesses the chip through HAL_READ + and HAL_WRITE macros, otherwise it uses direct memory access." + } + + cdl_option CYGNUM_DEVS_USB_I386_SOROD12_BASEADDR { + display "Base Address of D12 chip" + flavor data + no_define + legal_values 1 to 0xFF8 + default_value 544 + active_if CYGFUN_DEVS_USB_D12_EP0 + requires { CYGNUM_DEVS_USB_D12_BASEADDR == + CYGNUM_DEVS_USB_I386_SOROD12_BASEADDR } + description " + The base memory or I/O address where the USB chip resides." + } + + cdl_option CYGNUM_DEVS_USB_I386_SORODD12_IRQ { + display "IRQ for the D12 chip" + flavor data + no_define + legal_values { 3 5 7 } + default_value 5 + active_if CYGFUN_DEVS_USB_D12_EP0 + requires { CYGNUM_DEVS_USB_D12_IRQ == + CYGNUM_DEVS_USB_I386_SORODD12_IRQ } + description " + The IRQ assigned to the D12 chip." + } +} diff --git a/packages/devs/usb/i386/SoRoD12/v2_0/include/usbs_i386_sorod12.inl b/packages/devs/usb/i386/SoRoD12/v2_0/include/usbs_i386_sorod12.inl new file mode 100644 index 00000000..dd8e93df --- /dev/null +++ b/packages/devs/usb/i386/SoRoD12/v2_0/include/usbs_i386_sorod12.inl @@ -0,0 +1,128 @@ +#ifndef USBS_I386_SORO12_INL +#define USBS_I386_SORO12_INL +//========================================================================== +// +// usbS_i386_sorod12.inl +// +// Hardware specific parts for the SoRo D12 PC 104 USB card. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006, eCosCentric +// +// 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): Frank M. Pagliughi (fmp), ASL +// Date: 2004-05-22 +// +// This code is a hardware specific device driver for the SoRo Systems +// USB-D12-104, a PC/104 (ISA) Full-Speed USB slave board, which turns +// a PC/104 stack into a USB slave device. The board contains a +// Philips PDIUSBD12 Peripheral Controller Chip mapped into the PC's +// I/O space, with jumper-selectable I/O base address, IRQ, and DMA +// settings. The eCos config tool is used to adjust settings for this +// driver to match the physical jumper settings. The chip could run in +// polled mode without an IRQ, but this wouldn't be a great idea other +// than maybe a debug environment. + +// ------------------------------------------------------------------------ +// Data-Only I/O +// ------------------------------------------------------------------------ +// + +#include + +// These routines read or write 8 bit values to the data area. + +static inline byte d12_read_data_byte(d12_addr_type base_addr) +{ + #if defined(CYGSEM_DEVS_USB_I386_SOROD12_IO_MAPPED) + byte val; + HAL_READ_UINT8((unsigned) base_addr, val); + return val; + #else + return *base_addr; + #endif +} + +static inline void d12_write_data_byte(d12_addr_type base_addr, byte val) +{ + #if defined(CYGSEM_DEVS_USB_I386_SOROD12_IO_MAPPED) + HAL_WRITE_UINT8((unsigned) base_addr, val); + #else + *base_addr = val; + #endif +} + +// This routine writes a command to the device. + +static inline void d12_write_cmd(d12_addr_type base_addr, byte cmd) +{ + #if defined(CYGSEM_DEVS_USB_I386_SOROD12_IO_MAPPED) + HAL_WRITE_UINT8((unsigned) base_addr+1, cmd); + #else + *(base_addr+1) = cmd; + #endif +} + +// ------------------------------------------------------------------------ +// Reads 'n' bytes from the data address of the D12 and places them into +// the buf[] array. Buf can be NULL, in which case the specified number of +// bytes are read and discarded. + +static uint8 d12_read_data(d12_addr_type base_addr, byte *buf, uint8 n) +{ + uint8 i; + + if (buf) { + for (i=0; i + + * lpc2xxx: driver for on-chip RTC unit + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== + + diff --git a/packages/devs/wallclock/arm/lpc2xxx/v2_0/cdl/lpc2xxx_wallclock.cdl b/packages/devs/wallclock/arm/lpc2xxx/v2_0/cdl/lpc2xxx_wallclock.cdl new file mode 100644 index 00000000..ff7dfbae --- /dev/null +++ b/packages/devs/wallclock/arm/lpc2xxx/v2_0/cdl/lpc2xxx_wallclock.cdl @@ -0,0 +1,86 @@ +# ==================================================================== +# +# lpc2xxx_wallclock.cdl +# +# eCos configuration data for LPC2xxx internal RTC +# +# ==================================================================== +#####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 +## Copyright (C) 2004 eCosCentric Ltd +## +## 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): Hans Rosenfeld +# Contributors: jskov +# Date: 2007-06-19 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVICES_WALLCLOCK_ARM_LPC2XXX { + display "LPC2xxx Real-time clock" + description "RTC driver for the LPC2xxx controller" + + parent CYGPKG_IO_WALLCLOCK + active_if CYGPKG_IO_WALLCLOCK + active_if CYGPKG_HAL_ARM_LPC2XXX + + requires { CYGHWR_HAL_ARM_LPC2XXX_IDLE_PWRSAVE == 0 } + compile lpc2xxx_wallclock.cxx + + implements CYGINT_WALLCLOCK_HW_IMPLEMENTATIONS + active_if CYGIMP_WALLCLOCK_HARDWARE + implements CYGINT_WALLCLOCK_SET_GET_MODE_SUPPORTED + + cdl_option CYGIMP_WALLCLOCK_HARDWARE { + parent CYGPKG_IO_WALLCLOCK_IMPLEMENTATION + display "Hardware wallclock" + default_value 1 + implements CYGINT_WALLCLOCK_IMPLEMENTATIONS + } + + cdl_option CYGNUM_HAL_ARM_LPC2XXX_RTCDEV_PREINT { + display "RTC prescaler integer portion" + flavor data + calculated { ((CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED / + CYGNUM_HAL_ARM_LPC2XXX_VPBDIV) / 32768) - 1 } + } + + cdl_option CYGNUM_HAL_ARM_LPC2XXX_RTCDEV_PREFRAC { + display "RTC prescaler fractional portion" + flavor data + calculated { ((CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED / + CYGNUM_HAL_ARM_LPC2XXX_VPBDIV) - + ((CYGNUM_HAL_ARM_LPC2XXX_RTCDEV_PREINT + 1) * 32768)) } + } +} diff --git a/packages/devs/wallclock/arm/lpc2xxx/v2_0/src/lpc2xxx_wallclock.cxx b/packages/devs/wallclock/arm/lpc2xxx/v2_0/src/lpc2xxx_wallclock.cxx new file mode 100644 index 00000000..fee97476 --- /dev/null +++ b/packages/devs/wallclock/arm/lpc2xxx/v2_0/src/lpc2xxx_wallclock.cxx @@ -0,0 +1,161 @@ +//========================================================================== +// +// lpc2xxx_wallclock.cxx +// +// Wallclock implementation for LPC2xxx +// +//========================================================================== +//####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 +// Copyright (C) 2004 eCosCentric Ltd +// +// 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): Hans Rosenfeld +// Contributors: +// Date: 2007-06-19 +// Purpose: Wallclock driver for LPC2xxx +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +#include +#include +#include + +#include +#include + +/* + * I don't like to write LOTS OF CAPITALIZED TEXT. + * This code is intended for LPC2xxx processors _only_, so there is nothing + * wrong with accessing this device directly without using the HAL macros. + */ + +struct time { + volatile cyg_uint32 sec; + volatile cyg_uint32 min; + volatile cyg_uint32 hour; + volatile cyg_uint32 dom; + volatile cyg_uint32 dow; + volatile cyg_uint32 doy; + volatile cyg_uint32 month; + volatile cyg_uint32 year; +}; + +struct rtcdev { + volatile cyg_uint32 ilr; + volatile cyg_uint32 ctc; + volatile cyg_uint32 ccr; + volatile cyg_uint32 ciir; + volatile cyg_uint32 amr; + volatile cyg_uint32 ctime[3]; + struct time time; + cyg_uint32 dummy[8]; + struct time alarm; + volatile cyg_uint32 preint; + volatile cyg_uint32 prefrac; +}; + +static struct rtcdev * const rtc = + (struct rtcdev *) CYGARC_HAL_LPC2XXX_REG_RTC_BASE; + +void +Cyg_WallClock::init_hw_seconds(void) +{ + /* halt clock, disable interrupts, disable alarm */ + rtc->ccr = 0x2; + rtc->ciir = 0x0; + rtc->amr = 0xf; + + /* initialize prescaler */ + rtc->preint = CYGNUM_HAL_ARM_LPC2XXX_RTCDEV_PREINT; + rtc->prefrac = CYGNUM_HAL_ARM_LPC2XXX_RTCDEV_PREFRAC; + +#ifndef CYGSEM_WALLCLOCK_SET_GET_MODE + /* reset time to the Unix Epoch */ + rtc->time.year = 1970; + rtc->time.month = 1; + rtc->time.dom = 1; + rtc->time.doy = 1; + rtc->time.dow = 4; + rtc->time.hour = 0; + rtc->time.min = 0; + rtc->time.sec = 0; +#endif + + /* reset alarm */ + rtc->alarm.year = rtc->alarm.month = rtc->alarm.dom = rtc->alarm.doy = + rtc->alarm.dow = rtc->alarm.hour = rtc->alarm.min = + rtc->alarm.sec = 0; + + /* start clock */ + rtc->ccr = 0x1; +} + +cyg_uint32 +Cyg_WallClock::get_hw_seconds(void) +{ + return _simple_mktime(rtc->time.year, + rtc->time.month, + rtc->time.dom, + rtc->time.hour, + rtc->time.min, + rtc->time.sec); +} + +#ifdef CYGSEM_WALLCLOCK_SET_GET_MODE +void +Cyg_WallClock::set_hw_seconds(cyg_uint32 secs) +{ + cyg_uint32 year, month, dom, hour, min, sec; + + /* halt clock, reset counter */ + rtc->ccr = 0x2; + + /* set time */ + _simple_mkdate(secs, &year, &month, &dom, &hour, &min, &sec); + rtc->time.year = year; + rtc->time.month = month; + rtc->time.dom = dom; + rtc->time.hour = hour; + rtc->time.min = min; + rtc->time.sec = sec; + + /* restart clock */ + rtc->ccr = 0x1; +} +#endif diff --git a/packages/devs/watchdog/arm/at91wdtc/v2_0/ChangeLog b/packages/devs/watchdog/arm/at91wdtc/v2_0/ChangeLog new file mode 100644 index 00000000..9b8a505e --- /dev/null +++ b/packages/devs/watchdog/arm/at91wdtc/v2_0/ChangeLog @@ -0,0 +1,39 @@ +2006-02-18 Andrew Lunn + + * Added watchdog driver for ARM AT91 devices which have the + Watchdog Timer Controller as opposed to the older devices which + have the Watchdog Timer Interface. + +//####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 Nick Garnett +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### diff --git a/packages/devs/watchdog/arm/at91wdtc/v2_0/cdl/watchdog_at91wdtc.cdl b/packages/devs/watchdog/arm/at91wdtc/v2_0/cdl/watchdog_at91wdtc.cdl new file mode 100644 index 00000000..d5edb7f1 --- /dev/null +++ b/packages/devs/watchdog/arm/at91wdtc/v2_0/cdl/watchdog_at91wdtc.cdl @@ -0,0 +1,146 @@ +# ==================================================================== +# +# watchdog_at91wdtc.cdl +# +# eCos watchdog for ARM AT91 WDTC driver configuration data +# +# ==================================================================== +#####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 Nick Garnett +## Copyright (C) 2006 Andrew Lunn (andrew.lunn@ascom.ch> +## +## 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): tkoeller +# Contributors: tkoeller, nickg, asl +# Date: 2006-02-18 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVICES_WATCHDOG_ARM_AT91WDTC { + parent CYGPKG_IO_WATCHDOG + active_if CYGPKG_IO_WATCHDOG + display "ARM AT91 WDTC watchdog driver" + requires CYGPKG_HAL_ARM_AT91 + requires CYGPKG_KERNEL + hardware + define_header devs_watchdog_arm_at91wdtc.h + compile watchdog_at91wdtc.cxx + implements CYGINT_WATCHDOG_HW_IMPLEMENTATIONS + active_if CYGIMP_WATCHDOG_HARDWARE + description " + This package uses the watchdog device integrated + in the AT91 to execute a predefined action if the + application fails to call the reset function for + longer than a given timeout interval. This package + currently only supports the AT91SAM7S device which + use the Watchdog Timer Controller." + + cdl_option CYGIMP_WATCHDOG_HARDWARE { + parent CYGPKG_IO_WATCHDOG_IMPLEMENTATION + display "Hardware watchdog" + calculated 1 + implements CYGINT_WATCHDOG_IMPLEMENTATIONS + } + + cdl_option CYGNUM_DEVS_WATCHDOG_ARM_AT91WDTC_DESIRED_TIMEOUT_MS { + display "Desired timeout value" + flavor data + default_value 1000 + description " + This parameter controls the watchdog timeout interval. + Note that you may not get the exact value requested + here, the timeout interval may have to be adjusted + because of hardware limitations. The actual timeout + used will be the smallest possible value that is not + less than this parameter. Since the timeout is derived + from the LC based slow clock don't expect great accuracy. + On my board a 1000ms timeout actually goes off after 550ms!" + } + + cdl_option CYGNUM_DEVS_WATCHDOG_ARM_AT91WDTC_TIMEOUT_VALUE { + display "Calculated timeout value" + flavor data + calculated { (CYGNUM_HAL_ARM_AT91_SLOW_CLOCK / 128) * + (CYGNUM_DEVS_WATCHDOG_ARM_AT91WDTC_DESIRED_TIMEOUT_MS / 1000) + } + legal_values { 0 to 4096 } + description " + This is the calculated value that will be placed into + watchdog counter timer." + } + + cdl_option CYGSEM_DEVS_WATCHDOG_ARM_AT91WDTC_RESET { + display "Generate reset on watchdog expiration" + flavor bool + default_value 1 + implements CYGINT_WATCHDOG_RESETS_ON_TIMEOUT + description " + Enabling this option changes the watchdog operation mode + to generate a system reset upon expiration instead of + invoking an application-defined action." + } + + cdl_component CYGPKG_DEVICES_WATCHDOG_ARM_AT91WDTC_OPTIONS { + display "AT91 watchdog 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_DEVICES_WATCHDOG_ARM_AT91WDTC_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the watchdog device. These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_DEVICES_WATCHDOG_ARM_AT91WDTC_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the watchdog device. These flags are removed from + the set of global flags if present." + } + } +} + +# EOF watchdog_at91WDTC.cdl diff --git a/packages/devs/watchdog/arm/at91wdtc/v2_0/src/watchdog_at91wdtc.cxx b/packages/devs/watchdog/arm/at91wdtc/v2_0/src/watchdog_at91wdtc.cxx new file mode 100644 index 00000000..21cf62d7 --- /dev/null +++ b/packages/devs/watchdog/arm/at91wdtc/v2_0/src/watchdog_at91wdtc.cxx @@ -0,0 +1,198 @@ +//========================================================================== +// +// devs/watchdog/arm/at91/watchdog_at91wdtc.cxx +// +// Watchdog implementation for ARM AT91 CPUs using the WDTC +// +//========================================================================== +//####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 Nick Garnett +// copyright (C) 2006 Andrew Lunn +// +// 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): tkoeller +// Contributors: tkoeller, nickg, asl +// Date: 2006-02-18 +// Purpose: Watchdog class implementation +// Description: Contains an implementation of the Watchdog class for use +// with the ATMEL AT91 watchdog timer controller. +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#if !defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) +#include +#include +#endif + +//========================================================================== + +#if defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) + +#define MRVAL (AT91_WDTC_WDMR_RSTEN | AT91_WDTC_WDMR_DBGHLT) + +void +Cyg_Watchdog::init_hw(void) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARGVOID(); + resolution = CYGNUM_DEVS_WATCHDOG_ARM_AT91WDTC_DESIRED_TIMEOUT_MS * 1000000; + CYG_REPORT_RETURN(); +} + +#else /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */ + +//========================================================================== + +#define MRVAL (AT91_WDTC_WDMR_FIEN | AT91_WDTC_WDMR_DBGHLT) +#define INT_PRIO 7 + +//========================================================================== + +static Cyg_Watchdog *wd; + +//========================================================================== + +static cyg_uint32 +isr(cyg_vector vector, CYG_ADDRWORD data) +{ + cyg_uint32 sr; + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2XV(vector, data); + + // Read the status register to clear the interrupt + HAL_READ_UINT32(AT91_WDTC + AT91_WDTC_WDSR, sr); + + wd->trigger(); + Cyg_Interrupt::acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WDTC); + CYG_REPORT_RETVAL(Cyg_Interrupt::HANDLED); + return Cyg_Interrupt::HANDLED; +} + +//========================================================================== + +static CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_DRIVERS) + Cyg_Interrupt wdint( + CYGNUM_HAL_INTERRUPT_WDTC, + INT_PRIO, + 0, + isr, + NULL + ); + +//========================================================================== + +void +Cyg_Watchdog::init_hw(void) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARGVOID(); + + wd = this; + + wdint.attach(); + wdint.acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WDTC); + wdint.unmask_interrupt(CYGNUM_HAL_INTERRUPT_WDTC); + resolution = CYGNUM_DEVS_WATCHDOG_ARM_AT91WDTC_DESIRED_TIMEOUT_MS * 1000000; + CYG_REPORT_RETURN(); +} + +#endif /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */ + +//========================================================================== +/* + * Reset watchdog timer. This needs to be called regularly to prevent + * the watchdog from firing. + */ + +void +Cyg_Watchdog::reset(void) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARGVOID(); + + /* Write magic code to reset the watchdog. */ + HAL_WRITE_UINT32(AT91_WDTC + AT91_WDTC_WDCR, + AT91_WDTC_WDCR_RELOAD | AT91_WDTC_WDCR_KEY); + + CYG_REPORT_RETURN(); +} + +//========================================================================== +/* + * Start watchdog to generate a hardware reset + * or interrupt when expiring. + */ + +void +Cyg_Watchdog::start(void) +{ + cyg_uint32 val, val1; + + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARGVOID(); + + val = (MRVAL | CYGNUM_DEVS_WATCHDOG_ARM_AT91WDTC_TIMEOUT_VALUE | + (CYGNUM_DEVS_WATCHDOG_ARM_AT91WDTC_TIMEOUT_VALUE << + AT91_WDTC_WDMR_WDD_SHIFT)); + + HAL_WRITE_UINT32(AT91_WDTC + AT91_WDTC_WDMR, val); + HAL_READ_UINT32(AT91_WDTC + AT91_WDTC_WDMR, val1); + + // If this assert goes if it probably means something else has + // already programmed the watchdog. The mode register is only + // writeable once and once it is set it can only be reset by a + // processor reset. + CYG_ASSERT(val == val1, "Unable to configure watchdog"); + + CYG_REPORT_RETURN(); +} + +//========================================================================== +// End of watchdog_at91.cxx diff --git a/packages/fs/ram/v2_0/tests/ramfs3.c b/packages/fs/ram/v2_0/tests/ramfs3.c new file mode 100644 index 00000000..ca8a6ef7 --- /dev/null +++ b/packages/fs/ram/v2_0/tests/ramfs3.c @@ -0,0 +1,185 @@ +//========================================================================== +// +// ramfs3.c +// +// Test fileio system, especially lseek calls. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 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. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, asl, Paluch Sebastian +// Contributors: nickg +// Date: 2006-10-05 +// Purpose: Test fileio system +// Description: This test uses the testfs to check out the initialization +// and basic operation of the fileio system +// +// +// +// +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include +#include +#include + +#include + +#include +#include // HAL polled output +//========================================================================== + +#define SHOW_RESULT( _fn, _res ) \ +diag_printf("FAIL: " #_fn "() returned %ld %s\n", \ + (unsigned long)_res, _res<0?strerror(errno):""); + +//========================================================================== + +cyg_uint8 buf[256]; +cyg_uint8 buf1[256]; + +//========================================================================== +// main + +int main( int argc, char **argv ) +{ + int err; + FILE *stream; + long pos; + unsigned int i; + char header[3]; + + CYG_TEST_INIT(); + + // -------------------------------------------------------------- + + CYG_TEST_INFO("mount /"); + err = mount( "", "/", "ramfs" ); + + if( err < 0 ) SHOW_RESULT( mount, err ); + + CYG_TEST_INFO("creating /fseek"); + stream = fopen("/fseek","w+"); + if (!stream) { + SHOW_RESULT( fopen, NULL); + CYG_TEST_FAIL_FINISH("done");\ + } + + for (i = 0; i < sizeof(buf); i++) { + buf[i] = i % 256; + } + + CYG_TEST_INFO("writing test pattern"); + err=fwrite(buf,sizeof(buf), 1, stream); + if ( err < 0 ) SHOW_RESULT( fwrite, err ); + + pos = ftell(stream); + if (pos < 0) SHOW_RESULT( ftell, pos ); + if (pos != sizeof(buf)) + diag_printf(": ftell is not telling the truth."); + + CYG_TEST_INFO("fseek()ing to 85"); + err = fseek(stream, 85, SEEK_SET); + if ( err < 0 ) SHOW_RESULT( fseek, err ); + + pos = ftell(stream); + if (pos < 0) SHOW_RESULT( ftell, pos ); + if (pos != 85) CYG_TEST_FAIL("ftell is not telling the truth"); + + err = fread(header,3,1,stream); + if ( err < 0 ) SHOW_RESULT( fwrite, err ); + if ((header[0] != 85) || + (header[1] != 86) || + (header[2] != 87)) + CYG_TEST_FAIL("Read returned false data"); + + pos = ftell(stream); + if (pos < 0) SHOW_RESULT( ftell, pos ); + if (pos != 88) CYG_TEST_FAIL("ftell is not telling the truth"); + + for (i = 88; i < 161; i++) { + buf[i] = 0x42; + } + + CYG_TEST_INFO("writing"); + err = fwrite(buf+88, 73, 1, stream); + if ( err < 0 ) SHOW_RESULT( fwrite, err ); + + pos = ftell(stream); + if (pos < 0) SHOW_RESULT( ftell, pos ); + if (pos != 161) CYG_TEST_FAIL("ftell is not telling the truth"); + + CYG_TEST_INFO("closing file"); + err = fclose(stream); + if (err != 0) SHOW_RESULT( fclose, err ); + + CYG_TEST_INFO("open file /fseek"); + stream = fopen("/fseek", "r+"); + if (!stream) { + SHOW_RESULT( fopen, NULL); + CYG_TEST_FAIL_FINISH("done");\ + } + + CYG_TEST_INFO("Seeking to beginning of file"); + err = fseek(stream, 0, SEEK_SET); + if ( err < 0 ) SHOW_RESULT( fseek, err ); + + CYG_TEST_INFO("Reading buf1"); + err = fread(buf1,sizeof(buf1),1, stream); + if (err != 1) SHOW_RESULT( fread, err ); + + CYG_TEST_INFO("Comparing contents"); + if (memcmp(buf, buf1, sizeof(buf1))) + CYG_TEST_FAIL("File contents inconsistent"); + + CYG_TEST_INFO("closing file"); + err = fclose(stream); + if (err != 0) SHOW_RESULT( fclose, err ); + + CYG_TEST_INFO("umount /"); + err = umount( "/" ); + if( err < 0 ) SHOW_RESULT( umount, err ); + + CYG_TEST_PASS_FINISH("ramfs3"); +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/ChangeLog b/packages/hal/arm/at91/at91sam7s/v2_0/ChangeLog new file mode 100644 index 00000000..e210a34c --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/ChangeLog @@ -0,0 +1,160 @@ +2008-05-11 James G. Smith + + * cdl/hal_arm_at91sam7s.cdl: CDL for crystal vs clock signal. + * include/hal_platform_setup.h: Rework flash wait states to remove + redundant code when running at > 60MHz. Support clock signal input + when starting the main clock. + +2008-04-30 John Eigelaar + + * include/pkgconf/mlt_arm_at91sam7x512_rom.{h|ldi}: Added the + memory layout files to support the at91sam7x512 + * cdl/hal_arm_at91s.cdl: Added the configuration options to + support the at91sam7x512 + +2008-04-23 Andrew Lunn + + * include/hal_platform_setup.h: Fix setting the flash wait states + when the clock is running faster than 60MHz. r0 was undefined + causing a data abort. + +2007-03-26 Andrew Lunn + + * cdl/hal_arm_at91sam7s.cdl: SAM7X and SAM7XC have a CAN bus + controller. + +2007-01-17 John Eigelaar + + * include/plf_io.h + * src/at91sam7s_misc.c + Added code to initialise the platform ethernet hardware if need be + +2007-01-02 Uwe Kindler + + * cdl/hal_arm_at91sam7s.cdl Moved HAL_PLATFORM_XXX defines and + definition of platform header file (CYGBLD_HAL_PLATFORM_H) from + package CYGPKG_HAL_ARM_AT91SAM7 into board specific packages. + +2006-06-01 Andrew Lunn + + * cdl/hal_arm_at91sam7s.cdl: Implement the SPI bus 1 interface for + the SAM7X and SAM7XC. + +2006-06-01 John Eigelaar + + * include/plf_io.h: Add SPI DMA registers. + +2006-05-20 John Eigelaar + + include/pkgconf/mlt_arm_at91sam7x128_rom.{h|ldi} + include/pkgconf/mlt_arm_at91sam7x256_rom.{h|ldi}: Linker files + for AT91SAM7X processor. + +2006-05-17 Andrew Lunn + + * src/at91sam7s_misc.c: Use the AT91 generic PIO manipulation + macros. Move the LED function out into the board specific HAL + package. + +2006-04-07 Andrew Lunn + + * cdl/hal_arm_at91sam7s.cdl: + * include/pkgconf/mlt_arm_at91sam7s32_rom.ldi: + * include/pkgconf/mlt_arm_at91sam7s64_rom.ldi: + * include/pkgconf/mlt_arm_at91sam7s128_rom.ldi: + * include/pkgconf/mlt_arm_at91sam7s267_rom.ldi: + Allow CDL to control where in flash the image is placed. + +2006-03-23 Andrew Lunn + + * cdl/hal_arm_at91sam7s.cdl: Implement the USB interface when chip + has the device. + +2006-03-10 Oliver Munz + + * hal_arm_at91sam7s.cdl: Change the PLL-defaults so that 96MHz is + generated so that the USB does work. + +2006-03-10 Andrew Lunn + Oliver Munz + + * cdl/hal_arm_at91sam7s.cdl: Set the debug UART as the default + channel and fix some dodge spelling. + * src/at91sam7s_misc.c (hal_plf_hardware_init): Enable the Debug UART + pins for output and control by the device. + * include/plf_io.h: Define USART2 to be the debug UART. + +2006-03-01 Andrew Lunn + + * cdl/hal_arm_at91sam7s.cdl: Change the crystal frequency. The + numbers printed on top of the crystal are misleading. It has a + 18.432MHz crystal, not 20MHz. This error when combined with the + previous fix to the PLL made the serial baud rate wrong. Change + the multiplier and divisor to achieve about the same CPU clock, + which should be USB compatible. + * src/at91sam7s_misc.c (hal_at91_us_baud): Need the same PLL fix + when calculating the baud rate dynamically. + * include/plf_io.h: Add the Programmable Clock Output registers. + +2006-02-28 Oliver Munz + + * include/hal_platform_setup.h: Fix the PLL multiplier settings + +2006-02-25 Andrew Lunn + + * misc/redboot_R[AO]M.ecm: Disable FIS and fconfig, enable + loading directly into flash with the load command. + +2006-01-01 Oliver Munz + Andrew Lunn + + * cdl/hal_arm_at91sam7s.cdl: + * include/hal_platform_ints.h: + * include/hal_platform_setup.h: + * include/plf_io.h: + * include/pkgconf/mlt_arm_at91sam7s256_rom.h: + * include/pkgconf/mlt_arm_at91sam7s256_rom.ldi: + * include/pkgconf/mlt_arm_at91sam7s128_rom.h: + * include/pkgconf/mlt_arm_at91sam7s128_rom.ldi: + * include/pkgconf/mlt_arm_at91sam7s64_rom.h: + * include/pkgconf/mlt_arm_at91sam7s64_rom.ldi: + * include/pkgconf/mlt_arm_at91sam7s32_rom.h: + * include/pkgconf/mlt_arm_at91sam7s32_rom.ldi: + * src/at91sam7s_misc.c: + * misc/redboot_ROM.ecm: + * misc/redboot_RAM.ecm: + * ChangeLog: First import of a hal for the AT91SAM7S family. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric Ltd +// Copyright (C) 2006 Andrew Lunn +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/cdl/hal_arm_at91sam7s.cdl b/packages/hal/arm/at91/at91sam7s/v2_0/cdl/hal_arm_at91sam7s.cdl new file mode 100644 index 00000000..6a46d1b6 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/cdl/hal_arm_at91sam7s.cdl @@ -0,0 +1,465 @@ +# ==================================================================== +# +# hal_arm_at91_sam7s.cdl +# +# ARM AT91 SAM7 HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2003 Nick Garnett +## Copyright (C) 2005 eCosCentric Ltd +## Copyright (C) 2005 Andrew Lunn +## +## 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): gthomas +# Contributors: gthomas, tkoeller, nickg, Oliver Munz, asl +# Date: 2005-06-20 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_AT91SAM7 { + display "Atmel AT91SAM7 HAL" + parent CYGPKG_HAL_ARM + define_header hal_arm_at91sam7.h + include_dir cyg/hal + hardware + description " + The AT91SAM7 HAL package provides the support needed to run + eCos on an Atmel AT91SAM7 based board." + + compile at91sam7s_misc.c + + requires { CYGHWR_HAL_ARM_AT91_FIQ } + requires { CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s32" implies + CYGPKG_IO_SERIAL_ARM_AT91_SERIAL0 == 0 } + + implements CYGINT_HAL_ARM_AT91_SERIAL_DBG_HW + implements CYGINT_HAL_ARM_AT91_PIT_HW + implements CYGINT_HAL_ARM_AT91_SYS_INTERRUPT + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " + puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H " + puts $::cdl_system_header "#define CYGBLD_HAL_ARM_VAR_IO_H" + } + + cdl_option CYGHWR_HAL_ARM_AT91SAM7 { + display "AT91SAM7 variant used" + flavor data + default_value {"at91sam7s256"} + legal_values {"at91sam7s32" "at91sam7s321" "at91sam7s64" + "at91sam7s128" "at91sam7s256" + "at91sam7x128" "at91sam7x256" "at91sam7x512" + "at91sam7xc128" "at91sam7xc256" } + description " + The AT91SAM7 microcontroller family has several variants, + the main differences being the amount of on-chip SRAM, + FLASH, peripherals and their layout. This option allows the + platform HALs to select the specific microcontroller + being used." + } + + cdl_option CYGHWR_HAL_ARM_AT91SAM7S { + display "SAM7S device" + calculated { CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s256" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s128" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s64" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s32" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s321" } + description " + Is the AT91SAM7 device a member of the AT91SAM7S family?" + } + + cdl_option CYGHWR_HAL_ARM_AT91SAM7X { + display "SAM7X device" + calculated { CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7x512" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7x256" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7x128" } + description " + Is the AT91SAM7 device a member of the AT91SAM7X family?" + } + + cdl_option CYGHWR_HAL_ARM_AT91SAM7XC { + display "SAM7XC device" + calculated { CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7xc256" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7xc128" } + description " + Is the AT91SAM7 device a member of the AT91SAM7XC family?" + } + + cdl_option CYGBLD_HAL_ARM_AT91SAM7_USB { + display "USB device" + active_if {!( "at91sam7s32" == CYGHWR_HAL_ARM_AT91SAM7S) || + CYGHWR_HAL_ARM_AT91SAM7X || + CYGHWR_HAL_ARM_AT91SAM7XC } + implements CYGINT_DEVS_USB_AT91_HAS_USB + default_value 1 + no_define + description " + All but the AT91SAM7S32 has the USB device" + } + + cdl_option CYGBLD_HAL_ARM_AT91SAM7_SPI1 { + display "Second SPI bus controller" + active_if { CYGHWR_HAL_ARM_AT91SAM7X || + CYGHWR_HAL_ARM_AT91SAM7XC } + implements CYGINT_DEVS_SPI_ARM_AT91_HAS_BUS1 + default_value 1 + no_define + description " + The SAM7X and SAM7XC have the second SPI bus controller" + } + + cdl_option CYGBLD_HAL_ARM_AT91SAM7_CAN0 { + display "CAN bus controller" + active_if { CYGHWR_HAL_ARM_AT91SAM7X || + CYGHWR_HAL_ARM_AT91SAM7XC } + implements CYGINT_DEVS_CAN_AT91SAM7_CAN0 + default_value 1 + no_define + description " + The SAM7X and SAM7XC have the CAN controller" + } + + cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants" + flavor none + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + default_value 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + default_value 100 + } + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + legal_values 1 to 0xffff + calculated ((CYGNUM_HAL_RTC_NUMERATOR * CYGNUM_HAL_ARM_AT91_CLOCK_SPEED/16) / CYGNUM_HAL_RTC_DENOMINATOR / 1000000000) + description " + CYGNUM_HAL_RTC_PERIOD : (CYGNUM_HAL_RTC_NUMERATOR * CYGNUM_HAL_ARM_AT91_CLOCK_SPEED/16) / CYGNUM_HAL_RTC_DENOMINATOR / 1000000000 " + } + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + default_value {"ROM"} + legal_values {"RAM" "ROM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + When targeting the AT91SAM7 eval boards it is possible to build + the system for either RAM bootstrap or ROM bootstrap(s). Select + 'ram' when building programs to load into RAM using on board + debug software such as Angel or eCos GDB stubs. Select 'rom' + when building a stand-alone application which will be put + into ROM" + } + + cdl_option CYGNUM_HAL_ARM_AT91_IMAGE_ADDRESS { + display "Address in flash the image should live" + active_if { CYG_HAL_STARTUP == "ROM" } + flavor data + default_value 0x00100000 + description " + This optionspecifies where in flash the image + lives. By default it is at the bottom of the flash, + but for example redboot may be at the bottom and an + application lives higher up, which is acheived by + setting the address here." + } + + # Real-time clock/counter specifics + cdl_option CYGNUM_HAL_ARM_AT91_CLOCK_SPEED { + display "CPU clock speed" + flavor data + calculated { CYGNUM_HAL_ARM_AT91_CLOCK_OSC_MAIN * + CYGNUM_HAL_ARM_AT91_PLL_MULTIPLIER / + CYGNUM_HAL_ARM_AT91_PLL_DIVIDER / 2} + legal_values { 0 to 220000000 } + description " + The master clock-frequency has to be 48MHz, 96MHz or + 192MHz for the USB to work correctly. The clock setup uses + PLL clock divided by two" + } + + cdl_option CYGNUM_HAL_ARM_AT91_CLOCK_OSC_MAIN { + display "Main oscillator frequency" + flavor data + legal_values { 3000000 to 20000000} + default_value { 18432000 } + description " + The frequency of the clock input, be it a crystal or a clock + signal" + } + + cdl_option CYGNUM_HAL_ARM_AT91_CLOCK_TYPE { + display "Type of main frequency input" + flavor data + default_value { "CRYSTAL" } + legal_values { "CRYSTAL" "EXTCLOCK" } + description " + Whether a crystal or a XIN input clock is clocking the device." + } + + cdl_option CYGNUM_HAL_ARM_AT91_PLL_DIVIDER { + display "Divider for PLL clock" + flavor data + legal_values { 0 to 255 } + default_value 24 + description " + The X-tal clock is divided by this value when generating the + PLL clock" + } + + cdl_option CYGNUM_HAL_ARM_AT91_PLL_MULTIPLIER { + display "Multiplier for PLL clock" + flavor data + legal_values { 0 to 2047 } + default_value 125 + description " + The X-tal clock is multiplied by this value when generating + the PLL clock." + } + + cdl_option CYGNUM_HAL_ARM_AT91_SLOW_CLOCK { + display "Slow clock frequency" + flavor data + default_value { 32768 } + description " + The slow clock is an LC oscillator which runs all the + time. The accuracy of this clock is not very high and + is temperature dependent." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + default_value 3 + description " + The AT91SAM7S development boards has two Serial port connectors. + these correspond to USART0 and the Debug Serial port. The chip + has a third serial port which does not have a 9pin D + connector, but is accessible via the patch panel pins." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 2 + description " + The AT91SAM7S has three serial ports. This option + chooses which port will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 2 + description " + The AT91SAM7S board has three USART serial ports. This option + chooses which port will be used for diagnostic output." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 38400 + description " + This option selects the baud rate used for the diagnostic port." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "GDB serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 38400 + description " + This option controls the baud rate used for the GDB connection." + } + + cdl_option CYGBLD_HAL_ARM_AT91_BAUD_DYNAMIC { + display "Dynamic calculation of baud rate" + default_value 0 + description " + The AT91SAM7S has a flexible clock generation mechanism + where the main clock used to drive peripherals can be + changed during run time. Such changes affect the serial port + baud rate generators. Enabling this option includes code + which calculates the baud rate setting dynamically from the + current clock settings. Without this option a static + calculation is performed which assumes the clock frequency + has not been changed." + } + + cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM" } + description " + Enable this option if this program is to be used as a ROM monitor, + i.e. applications will be loaded into RAM on the board, and this + ROM monitor may process exceptions or interrupts generated from the + application. This enables features such as utilizing a separate + interrupt stack when exceptions are generated." + } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM monitor. + This support changes various eCos semantics such as the encoding + of diagnostic output, or the overriding of hardware interrupt + vectors. + Firstly there is \"Generic\" support which prevents the HAL + from overriding the hardware vectors that it does not use, to + instead allow an installed ROM monitor to handle them. This is + the most basic support which is likely to be common to most + implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included in + the ROM monitor or boot ROM." + } + + cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { + display "Redboot HAL options" + flavor none + no_define + parent CYGPKG_REDBOOT + active_if CYGPKG_REDBOOT + description " + This option lists the target's requirements for a valid Redboot + configuration." + + cdl_option CYGBLD_BUILD_REDBOOT_BIN { + display "Build Redboot ROM binary image" + active_if CYGBLD_BUILD_REDBOOT + default_value 1 + no_define + description "This option enables the conversion of the Redboot ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + /bin/redboot.bin : /bin/redboot.elf + $(OBJCOPY) --strip-debug $< $(@:.bin=.img) + $(OBJCOPY) -O srec $< $(@:.bin=.srec) + $(OBJCOPY) -O binary $< $@ + } + } + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + description " + Global build options including control over + compiler flags, linker flags and choice of toolchain." + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "arm-elf" } + description " + This option specifies the command prefix used when + invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + description " + This option controls the global compiler flags which are used to + compile all packages by default. Individual packages may define + options which override these global flags." + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -Wl,--gc-sections -Wl,-static -g -nostdlib" } + description " + This option controls the global linker flags. Individual + packages may define options which override these global flags." + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { (CYG_HAL_STARTUP == "RAM") ? \ + "arm_" . CYGHWR_HAL_ARM_AT91SAM7 . "_ram" : + "arm_" . CYGHWR_HAL_ARM_AT91SAM7 . "_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { (CYG_HAL_STARTUP == "RAM") ? \ + "" : + "" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { (CYG_HAL_STARTUP == "RAM") ? \ + "" : + "" } + } + } +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/hal_platform_ints.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/hal_platform_ints.h new file mode 100644 index 00000000..e16fb135 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/hal_platform_ints.h @@ -0,0 +1,123 @@ +#ifndef CYGONCE_HAL_PLATFORM_INTS_H +#define CYGONCE_HAL_PLATFORM_INTS_H +//========================================================================== +// +// hal_platform_ints.h +// +// HAL Interrupt and clock assignments for AT91SAM7 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): gthomas +// Contributors: gthomas, Oliver Munz, Andrew Lunn, John Eigelaar +// Date: 2001-07-12 +// Purpose: Define Interrupt support +// Description: The interrupt specifics for the AT91SAM7 platform are +// defined here. +// +// Usage: #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#define CYGNUM_HAL_INTERRUPT_FIQ 0 + +#define CYGNUM_HAL_INTERRUPT_SYS 1 +#define CYGNUM_HAL_INTERRUPT_PIOA 2 + +#ifdef CYGHWR_HAL_ARM_AT91SAM7X +#define CYGNUM_HAL_INTERRUPT_PIOB 3 +#define CYGNUM_HAL_INTERRUPT_SPI 4 +#define CYGNUM_HAL_INTERRUPT_SPI1 5 +#endif +#ifdef CYGHWR_HAL_ARM_AT91SAM7S +#define CYGNUM_HAL_INTERRUPT_ADC 4 +#define CYGNUM_HAL_INTERRUPT_SPI 5 +#endif + +#define CYGNUM_HAL_INTERRUPT_USART0 6 +#define CYGNUM_HAL_INTERRUPT_USART1 7 +#define CYGNUM_HAL_INTERRUPT_SSC 8 +#define CYGNUM_HAL_INTERRUPT_TWI 9 +#define CYGNUM_HAL_INTERRUPT_PWMC 10 +#define CYGNUM_HAL_INTERRUPT_UDP 11 +#define CYGNUM_HAL_INTERRUPT_TC0 12 +#define CYGNUM_HAL_INTERRUPT_TC1 13 +#define CYGNUM_HAL_INTERRUPT_TC2 14 + +#ifdef CYGHWR_HAL_ARM_AT91SAM7X +#define CYGNUM_HAL_INTERRUPT_CAN 15 +#define CYGNUM_HAL_INTERRUPT_EMAC 16 +#define CYGNUM_HAL_INTERRUPT_ADC 17 +#endif + +#define CYGNUM_HAL_INTERRUPT_IRQ0 30 +#define CYGNUM_HAL_INTERRUPT_IRQ1 31 + +// Interrupts which are multiplexed on to the System Interrupt +#define CYGNUM_HAL_INTERRUPT_PITC 32 +#define CYGNUM_HAL_INTERRUPT_RTTC 33 +#define CYGNUM_HAL_INTERRUPT_PMC 34 +#define CYGNUM_HAL_INTERRUPT_MC 35 +#define CYGNUM_HAL_INTERRUPT_WDTC 36 +#define CYGNUM_HAL_INTERRUPT_RSTC 37 +#define CYGNUM_HAL_INTERRUPT_DBG 38 + +#define CYGNUM_HAL_ISR_MIN 0 +#define CYGNUM_HAL_ISR_MAX 38 + +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_ISR_MAX + 1) + +// The vector used by the Real time clock +#ifdef CYGBLD_HAL_ARM_AT91_TIMER_TC +#define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_TC0 +#endif +#ifdef CYGBLD_HAL_ARM_AT91_TIMER_PIT +#define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_PITC +#endif + +//---------------------------------------------------------------------------- +// Reset. +__externC void hal_at91_reset_cpu(void); +#define HAL_PLATFORM_RESET() hal_at91_reset_cpu() + +#define HAL_PLATFORM_RESET_ENTRY 0x0000000 + +#endif // CYGONCE_HAL_PLATFORM_INTS_H diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/hal_platform_setup.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/hal_platform_setup.h new file mode 100644 index 00000000..9ca7751a --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/hal_platform_setup.h @@ -0,0 +1,155 @@ +#ifndef CYGONCE_HAL_PLATFORM_SETUP_H +#define CYGONCE_HAL_PLATFORM_SETUP_H + +/*============================================================================= +// +// hal_platform_setup.h +// +// Platform specific support for HAL +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd +// Copy + +// 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): gthomas +// Contributors:gthomas, asl +// Date: 2006-02-18 +// Purpose: AT91SAM7S platform specific support routines +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include +#include + +// Macro to initialise the Memory Controller + .macro _flash_init +__flash_init__: + ldr r0,=AT91_MC +#if CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 60000000 + // When the clock is running faster than 60MHz we need two wait states + ldr r1,=(AT91_MC_FMR_2FWS) +#else +# if CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 30000000 + // When the clock is running faster than 30MHz we need a wait state + ldr r1,=(AT91_MC_FMR_1FWS) +# else + // We have a slow clock, no extra wait states are needed + ldr r1,=AT91_MC_FMR_0FWS +# endif +#endif + str r1,[r0,#AT91_MC_FMR] + .endm + +// Macro to start the main clock. + .macro _main_clock_init +__main_clock_init__: + ldr r0,=AT91_PMC + // Swap to the slow clock, just to be sure. + ldr r1,=(AT91_PMC_MCKR_PRES_CLK|AT91_PMC_MCKR_SLOW_CLK) + str r1,[r0,#AT91_PMC_MCKR] + // startup time +#if defined(CYGNUM_HAL_ARM_AT91_CLOCK_TYPE_EXTCLOCK) + ldr r1,=(AT91_PMC_MOR_OSCBYPASS) +#else + ldr r1,=(AT91_PMC_MOR_OSCCOUNT(6)|AT91_PMC_MOR_MOSCEN) +#endif + str r1,[r0,#AT91_PMC_MOR] + + // Wait for oscilator start timeout +wait_pmc_sr_1: + ldr r1,[r0,#AT91_PMC_SR] + ands r1,r1,#AT91_PMC_SR_MOSCS + beq wait_pmc_sr_1 + + // Set the PLL multiplier and divider. 16 slow clocks go by + // before the LOCK bit is set. */ + ldr r1,=((AT91_PMC_PLLR_DIV(CYGNUM_HAL_ARM_AT91_PLL_DIVIDER))|(AT91_PMC_PLLR_PLLCOUNT(16))|(AT91_PMC_PLLR_MUL(CYGNUM_HAL_ARM_AT91_PLL_MULTIPLIER-1))) + str r1,[r0,#AT91_PMC_PLLR] + + // Wait for PLL locked indication +wait_pmc_sr_2: + ldr r1,[r0,#AT91_PMC_SR] + ands r1,r1,#AT91_PMC_SR_LOCK + beq wait_pmc_sr_2 + + // Enable the PLL clock and set the prescale to 2 */ + ldr r1,=(AT91_PMC_MCKR_PRES_CLK_2|AT91_PMC_MCKR_PLL_CLK) + str r1,[r0,#AT91_PMC_MCKR] + + // Wait for the MCLK ready indication +wait_pmc_sr_3: + ldr r1,[r0,#AT91_PMC_SR] + ands r1,r1,#AT91_PMC_SR_MCKRDY + beq wait_pmc_sr_3 + .endm + +// Remap the flash from address 0x0 and place RAM there instead. + .macro _remap_flash +__remap_flash: + ldr r0,=0x000004 // Use the underfined instruction exception + ldr r1,=0x200004 + ldr r2,[r0] // Save away copies so we can restore them + ldr r3,[r1] + ldr r4,=0xffffff + eor r4,r3,r4 // XOR the contents of 0x20004 + str r4,[r1] // and write it + ldr r5,[r0] // Read from low memory + cmp r5,r4 + beq remap_done + ldr r0,=AT91_MC // Need to do a remap + ldr r5,=1 + str r5,[r0,#AT91_MC_RCR] +remap_done: + str r3,[r1] // restore the value we changed + .endm + +#if defined(CYG_HAL_STARTUP_ROM) + .macro _setup + _flash_init + _main_clock_init + _remap_flash + .endm + +#define PLATFORM_SETUP1 _setup +#else +#define PLATFORM_SETUP1 +#endif + +//----------------------------------------------------------------------------- +// end of hal_platform_setup.h +#endif // CYGONCE_HAL_PLATFORM_SETUP_H diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s128_rom.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s128_rom.h new file mode 100644 index 00000000..54893cd7 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s128_rom.h @@ -0,0 +1,25 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x00200000) +#define CYGMEM_REGION_ram_SIZE (0x08000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x00100000) +#define CYGMEM_REGION_rom_SIZE (0x20000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__reserved_bootmon) []; +#endif +#define CYGMEM_SECTION_reserved_bootmon (CYG_LABEL_NAME (__reserved_bootmon)) +#define CYGMEM_SECTION_reserved_bootmon_SIZE (0x01000) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x00204000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s128_rom.ldi b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s128_rom.ldi new file mode 100644 index 00000000..788ffce2 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s128_rom.ldi @@ -0,0 +1,30 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include +#include + +MEMORY +{ + ram : ORIGIN = 0x00200000, LENGTH = 0x08000 + rom : ORIGIN = 0x00100000, LENGTH = 0x20000 +} + +SECTIONS +{ + SECTIONS_BEGIN + CYG_LABEL_DEFN(__reserved_bootmon) = 0x00000000; . = CYG_LABEL_DEFN(__reserved_bootmon) + 0x01000; + SECTION_rom_vectors (rom, CYGNUM_HAL_ARM_AT91_IMAGE_ADDRESS, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x00200040, LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s256_rom.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s256_rom.h new file mode 100644 index 00000000..9d43fb67 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s256_rom.h @@ -0,0 +1,25 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x00200000) +#define CYGMEM_REGION_ram_SIZE (0x10000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x00100000) +#define CYGMEM_REGION_rom_SIZE (0x40000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__reserved_bootmon) []; +#endif +#define CYGMEM_SECTION_reserved_bootmon (CYG_LABEL_NAME (__reserved_bootmon)) +#define CYGMEM_SECTION_reserved_bootmon_SIZE (0x01000) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x00210000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s256_rom.ldi b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s256_rom.ldi new file mode 100644 index 00000000..84c790cd --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s256_rom.ldi @@ -0,0 +1,30 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include +#include + +MEMORY +{ + ram : ORIGIN = 0x00200000, LENGTH = 0x10000 + rom : ORIGIN = 0x00100000, LENGTH = 0x40000 +} + +SECTIONS +{ + SECTIONS_BEGIN + CYG_LABEL_DEFN(__reserved_bootmon) = 0x00000000; . = CYG_LABEL_DEFN(__reserved_bootmon) + 0x01000; + SECTION_rom_vectors (rom, CYGNUM_HAL_ARM_AT91_IMAGE_ADDRESS, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x00200040, LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s32_rom.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s32_rom.h new file mode 100644 index 00000000..61ffc48a --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s32_rom.h @@ -0,0 +1,25 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x00200000) +#define CYGMEM_REGION_ram_SIZE (0x02000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x00100000) +#define CYGMEM_REGION_rom_SIZE (0x08000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__reserved_bootmon) []; +#endif +#define CYGMEM_SECTION_reserved_bootmon (CYG_LABEL_NAME (__reserved_bootmon)) +#define CYGMEM_SECTION_reserved_bootmon_SIZE (0x01000) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x00202000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s32_rom.ldi b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s32_rom.ldi new file mode 100644 index 00000000..4724f597 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s32_rom.ldi @@ -0,0 +1,30 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include +#include + +MEMORY +{ + ram : ORIGIN = 0x00200000, LENGTH = 0x02000 + rom : ORIGIN = 0x00100000, LENGTH = 0x08000 +} + +SECTIONS +{ + SECTIONS_BEGIN + CYG_LABEL_DEFN(__reserved_bootmon) = 0x00000000; . = CYG_LABEL_DEFN(__reserved_bootmon) + 0x01000; + SECTION_rom_vectors (rom, CYGNUM_HAL_ARM_AT91_IMAGE_ADDRESS, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x00200040, LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s64_rom.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s64_rom.h new file mode 100644 index 00000000..9e3d25c9 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s64_rom.h @@ -0,0 +1,25 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x00200000) +#define CYGMEM_REGION_ram_SIZE (0x04000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x00100000) +#define CYGMEM_REGION_rom_SIZE (0x10000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__reserved_bootmon) []; +#endif +#define CYGMEM_SECTION_reserved_bootmon (CYG_LABEL_NAME (__reserved_bootmon)) +#define CYGMEM_SECTION_reserved_bootmon_SIZE (0x01000) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x00204000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s64_rom.ldi b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s64_rom.ldi new file mode 100644 index 00000000..ab345647 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7s64_rom.ldi @@ -0,0 +1,30 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include +#include + +MEMORY +{ + ram : ORIGIN = 0x00200000, LENGTH = 0x04000 + rom : ORIGIN = 0x00100000, LENGTH = 0x10000 +} + +SECTIONS +{ + SECTIONS_BEGIN + CYG_LABEL_DEFN(__reserved_bootmon) = 0x00000000; . = CYG_LABEL_DEFN(__reserved_bootmon) + 0x01000; + SECTION_rom_vectors (rom, CYGNUM_HAL_ARM_AT91_IMAGE_ADDRESS, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x00200040, LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x128_rom.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x128_rom.h new file mode 100644 index 00000000..54893cd7 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x128_rom.h @@ -0,0 +1,25 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x00200000) +#define CYGMEM_REGION_ram_SIZE (0x08000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x00100000) +#define CYGMEM_REGION_rom_SIZE (0x20000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__reserved_bootmon) []; +#endif +#define CYGMEM_SECTION_reserved_bootmon (CYG_LABEL_NAME (__reserved_bootmon)) +#define CYGMEM_SECTION_reserved_bootmon_SIZE (0x01000) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x00204000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x128_rom.ldi b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x128_rom.ldi new file mode 100644 index 00000000..788ffce2 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x128_rom.ldi @@ -0,0 +1,30 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include +#include + +MEMORY +{ + ram : ORIGIN = 0x00200000, LENGTH = 0x08000 + rom : ORIGIN = 0x00100000, LENGTH = 0x20000 +} + +SECTIONS +{ + SECTIONS_BEGIN + CYG_LABEL_DEFN(__reserved_bootmon) = 0x00000000; . = CYG_LABEL_DEFN(__reserved_bootmon) + 0x01000; + SECTION_rom_vectors (rom, CYGNUM_HAL_ARM_AT91_IMAGE_ADDRESS, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x00200040, LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x256_rom.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x256_rom.h new file mode 100644 index 00000000..9d43fb67 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x256_rom.h @@ -0,0 +1,25 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x00200000) +#define CYGMEM_REGION_ram_SIZE (0x10000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x00100000) +#define CYGMEM_REGION_rom_SIZE (0x40000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__reserved_bootmon) []; +#endif +#define CYGMEM_SECTION_reserved_bootmon (CYG_LABEL_NAME (__reserved_bootmon)) +#define CYGMEM_SECTION_reserved_bootmon_SIZE (0x01000) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x00210000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x256_rom.ldi b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x256_rom.ldi new file mode 100644 index 00000000..84c790cd --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x256_rom.ldi @@ -0,0 +1,30 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include +#include + +MEMORY +{ + ram : ORIGIN = 0x00200000, LENGTH = 0x10000 + rom : ORIGIN = 0x00100000, LENGTH = 0x40000 +} + +SECTIONS +{ + SECTIONS_BEGIN + CYG_LABEL_DEFN(__reserved_bootmon) = 0x00000000; . = CYG_LABEL_DEFN(__reserved_bootmon) + 0x01000; + SECTION_rom_vectors (rom, CYGNUM_HAL_ARM_AT91_IMAGE_ADDRESS, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x00200040, LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x512_rom.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x512_rom.h new file mode 100644 index 00000000..8ef949ee --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x512_rom.h @@ -0,0 +1,25 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x00200000) +#define CYGMEM_REGION_ram_SIZE (0x20000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x00100000) +#define CYGMEM_REGION_rom_SIZE (0x80000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__reserved_bootmon) []; +#endif +#define CYGMEM_SECTION_reserved_bootmon (CYG_LABEL_NAME (__reserved_bootmon)) +#define CYGMEM_SECTION_reserved_bootmon_SIZE (0x01000) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x00220000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x512_rom.ldi b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x512_rom.ldi new file mode 100644 index 00000000..2ac2c002 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/pkgconf/mlt_arm_at91sam7x512_rom.ldi @@ -0,0 +1,30 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include +#include + +MEMORY +{ + ram : ORIGIN = 0x00200000, LENGTH = 0x20000 + rom : ORIGIN = 0x00100000, LENGTH = 0x80000 +} + +SECTIONS +{ + SECTIONS_BEGIN + CYG_LABEL_DEFN(__reserved_bootmon) = 0x00000000; . = CYG_LABEL_DEFN(__reserved_bootmon) + 0x01000; + SECTION_rom_vectors (rom, CYGNUM_HAL_ARM_AT91_IMAGE_ADDRESS, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (ram, 0x00200040, LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/include/plf_io.h b/packages/hal/arm/at91/at91sam7s/v2_0/include/plf_io.h new file mode 100644 index 00000000..48f3c07c --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/include/plf_io.h @@ -0,0 +1,205 @@ +#ifndef CYGONCE_HAL_PLF_IO_H +#define CYGONCE_HAL_PLF_IO_H +//============================================================================= +// +// plf_io.h +// +// AT91SAM7S board specific registers +// +//============================================================================= +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): tkoeller +// Contributors: andrew lunn, Oliver Munz +// Date: 2005-12-31 +// Purpose: Atmel AT91SAM7S board specific registers +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= +#include + +#define CYGARC_PHYSICAL_ADDRESS(_x_) + +//SPI - Serial Peripheral Interface +#define AT91_SPI0 0xFFFE0000 + +#ifdef CYGHWR_HAL_ARM_AT91SAM7X +#define AT91_SPI1 0xFFFE4000 +#endif + +#define AT91_SPI AT91_SPI0 + +//Extra SPI control bits +#define AT91_SPI_MR_MODFDIS (1<<4) + +// DMA registers +#define AT91_SPI_RPR 0x100 // Receive Pointer Register +#define AT91_SPI_RCR 0x104 // Receive Counter Register +#define AT91_SPI_TPR 0x108 // Transmit Pointer Register +#define AT91_SPI_TCR 0x10C // Transmit Counter Register +#define AT91_SPI_NRPR 0x110 // Next Receive Pointer Register +#define AT91_SPI_NRCR 0x114 // Next Receive Counter Register +#define AT91_SPI_NTPR 0x118 // Next Transmit Pointer Register +#define AT91_SPI_NTCR 0x11C // Next Trsnsmit Counter Register +#define AT91_SPI_PTCR 0x120 // PDC Transfer Control Register +#define AT91_SPI_PTSR 0x124 // PDC Transfer Status Register + +// Peripheral Input/Output Controllers +#define AT91_PIOA 0xFFFFF400 +#ifdef CYGHWR_HAL_ARM_AT91SAM7X +#define AT91_PIOB 0xFFFFF600 +#endif + +#define AT91_WSTC 0xFFFFFD40 + +// USART + +#define AT91_USART0 0xFFFC0000 +#define AT91_USART1 0xFFFC4000 + +// Define USART2 to be the debug UART. It is similar enough to a USART +// that both the hal_diag and interrupt driven driver will work. +// However trying to change parity, start/stop bits etc will not work. +#define CYGNUM_HAL_INTERRUPT_USART2 CYGNUM_HAL_INTERRUPT_DBG +#define AT91_USART2 AT91_DBG + +#ifndef __ASSEMBLER__ +#ifdef CYGBLD_HAL_ARM_AT91_BAUD_DYNAMIC +extern cyg_uint32 hal_at91_us_baud(cyg_uint32 baud); +#define AT91_US_BAUD(baud) hal_at91_us_baud(baud) +#endif +#endif // __ASSEMBLER__ + +#define AT91_US_RPR 0x100 // Receive Pointer Register +#define AT91_US_RCR 0x104 // Receive Counter Register +#define AT91_US_TPR 0x108 // Transmit Pointer Register +#define AT91_US_TCR 0x10C // Transmit Counter Register +#define AT91_US_NRPR 0x110 // Next Receive Pointer Register +#define AT91_US_NRCR 0x114 // Next Receive Counter Register +#define AT91_US_NTPR 0x118 // Next Transmit Pointer Register +#define AT91_US_NTCR 0x11C // Next Trsnsmit Counter Register +#define AT91_US_PTCR 0x120 // PDC Transfer Control Register +#define AT91_US_PTSR 0x124 // PDC Transfer Status Register + +// PIO - Programmable I/O + +#define AT91_PIO AT91_PIOA + +// AIC - Advanced Interrupt Controller + +#define AT91_AIC 0xFFFFF000 + +// TC - Timer Counter + +#define AT91_TC 0xFFFA0000 + +// Power Management Controller + +#define AT91_PMC 0xFFFFFC00 + +#define AT91_PMC_MOR 0x20 // Main Oscillator Register +#define AT91_PMC_MOR_MOSCEN (1 << 0) // Main Oscillator Enable +#define AT91_PMC_MOR_OSCBYPASS (1 << 1) // Main Oscillator Bypass +#define AT91_PMC_MOR_OSCCOUNT(x) (x << 8) // Slow clocks ticks +#define AT91_PMC_MCFR 0x24 // Main Clock Frequency Register +#define AT91_PMC_PLLR 0x2c // PLL Register +#define AT91_PMC_PLLR_DIV(x) ((x) << 0) // PLL Devide +#define AT91_PMC_PLLR_PLLCOUNT(x) ((x) << 8) // PLL Count +#define AT91_PMC_PLLR_MUL(x) ((x) << 16) // PLL Devide +#define AT91_PMC_PLLR_OUT_0 (0 << 14) +#define AT91_PMC_PLLR_OUT_1 (1 << 14) +#define AT91_PMC_PLLR_OUT_2 (2 << 14) +#define AT91_PMC_PLLR_OUT_3 (3 << 14) +#define AT91_PMC_PLLR_USBDIV_0 (0 << 28) // USB clock is PLL clock / 1 +#define AT91_PMC_PLLR_USBDIV_1 (1 << 28) // USB clock is PLL clock / 2 +#define AT91_PMC_PLLR_USBDIV_2 (2 << 28) // USB clock is PLL clock / 4 +#define AT91_PMC_MCKR 0x30 // Master Clock Register +#define AT91_PMC_MCKR_SLOW_CLK (0 << 0) // Slow clock selected +#define AT91_PMC_MCKR_MAIN_CLK (1 << 0) // Main clock selected +#define AT91_PMC_MCKR_PLL_CLK (3 << 0) // PLL clock selected +#define AT91_PMC_MCKR_PRES_CLK (0 << 2) // divide by 1 +#define AT91_PMC_MCKR_PRES_CLK_2 (1 << 2) // divide by 2 +#define AT91_PMC_MCKR_PRES_CLK_4 (2 << 2) // divide by 4 +#define AT91_PMC_MCKR_PRES_CLK_8 (3 << 2) // divide by 8 +#define AT91_PMC_MCKR_PRES_CLK_16 (4 << 2) // divide by 16 +#define AT91_PMC_MCKR_PRES_CLK_32 (5 << 2) // divide by 32 +#define AT91_PMC_MCKR_PRES_CLK_64 (6 << 2) // divide by 64 +#define AT91_PMC_PCKR0 0x40 // Programmable Clock Register 0 +#define AT91_PMC_PCKR1 0x44 // Programmable Clock Register 1 +#define AT91_PMC_PCKR2 0x48 // Programmable Clock Register 2 +#define AT91_PMC_IER 0x60 // Interrupt Enable Register +#define AT91_PMC_IDR 0x64 // Interrupt Disable Register +#define AT91_PMC_SR 0x68 // Status Register +#define AT91_PMC_SR_MOSCS (1 << 0) // Main oscillator stable +#define AT91_PMC_SR_LOCK (1 << 2) // PLL Locked +#define AT91_PMC_SR_MCKRDY (1 << 3) // MCK is ready to be enabled +#define AT91_PMC_SR_PCK0RDY (1 << 8) // Pad clock 0 is ready to be enabled +#define AT91_PMC_SR_PCK1RDY (1 << 9) // Pad clock 1 is ready to be enabled +#define AT91_PMC_SR_PCK2RDY (1 << 10) // Pad clock 2 is ready to be enabled +#define AT91_PMC_SR_PCK3RDY (1 << 11) // Pad clock 3 is ready to be enabled +#define AT91_PMC_IMR 0x6c // Interrupt Mask Register + +#ifdef CYGHWR_HAL_ARM_AT91SAM7X + +// EMAC - Ethernet Medium Access Controller + +#define AT91_EMAC 0xFFFDC000 + +// CAN - Controller Area Network + +#define AT91_CAN 0xFFFD0000 + +#endif + +//---------------------------------------------------------------------- +// The platform needs this initialization during the +// hal_hardware_init() function in the varient HAL. +#ifndef __ASSEMBLER__ +extern void hal_plf_hardware_init(void); +#define HAL_PLF_HARDWARE_INIT() \ + hal_plf_hardware_init() + +#ifdef CYGHWR_HAL_ARM_AT91SAM7X +extern void hal_plf_eth_init(void); +#define HAL_PLF_ETH_INIT() \ + hal_plf_eth_init() +#endif + +#endif //__ASSEMBLER__ + + +#endif //CYGONCE_HAL_PLF_IO_H + diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/misc/redboot_RAM.ecm b/packages/hal/arm/at91/at91sam7s/v2_0/misc/redboot_RAM.ecm new file mode 100644 index 00000000..b7f956e9 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/misc/redboot_RAM.ecm @@ -0,0 +1,82 @@ +cdl_savefile_version 1; +cdl_savefile_command cdl_savefile_version {}; +cdl_savefile_command cdl_savefile_command {}; +cdl_savefile_command cdl_configuration { description hardware template package }; +cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value }; + +cdl_configuration eCos { + description "" ; + hardware at91sam7s ; + template redboot ; + package -hardware CYGPKG_HAL_ARM current ; + package -hardware CYGPKG_HAL_ARM_AT91 current ; + package -hardware CYGPKG_DEVS_FLASH_AT91 current ; + package -template CYGPKG_HAL current ; + package -template CYGPKG_INFRA current ; + package -template CYGPKG_REDBOOT current ; + package CYGPKG_IO_FLASH current ; +}; + +cdl_option CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE { + user_value 6144 +}; + +cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM { + inferred_value 0 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS { + inferred_value 1 +}; + +cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + inferred_value 0 0 +}; + +cdl_component CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +cdl_option CYGOPT_REDBOOT_FIS { + user_value 0 +}; + +cdl_component CYGSEM_REDBOOT_FLASH_CONFIG { + user_value 0 +}; + +cdl_option CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG { + user_value 0 +}; + +cdl_option CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK { + user_value -16 +}; + + +cdl_option CYGBLD_BUILD_REDBOOT_WITH_EXEC { + user_value 0 +}; + +cdl_option CYGBLD_DEV_FLASH_AT91_LOCKING { + user_value 0 +}; + +cdl_option CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK { + user_value -24 +}; + +cdl_option CYGBLD_REDBOOT_MIN_IMAGE_SIZE { + user_value 0x15000 +}; + +cdl_option CYGBLD_REDBOOT_LOAD_INTO_FLASH { + user_value 1 +}; \ No newline at end of file diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/misc/redboot_ROM.ecm b/packages/hal/arm/at91/at91sam7s/v2_0/misc/redboot_ROM.ecm new file mode 100644 index 00000000..e18ee4b1 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/misc/redboot_ROM.ecm @@ -0,0 +1,90 @@ +cdl_savefile_version 1; +cdl_savefile_command cdl_savefile_version {}; +cdl_savefile_command cdl_savefile_command {}; +cdl_savefile_command cdl_configuration { description hardware template package }; +cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value }; + +cdl_configuration eCos { + description "" ; + hardware at91sam7s ; + template redboot ; + package -hardware CYGPKG_HAL_ARM current ; + package -hardware CYGPKG_HAL_ARM_AT91 current ; + package -hardware CYGPKG_DEVS_FLASH_AT91 current ; + package -template CYGPKG_HAL current ; + package -template CYGPKG_INFRA current ; + package -template CYGPKG_REDBOOT current ; + package CYGPKG_IO_FLASH current ; +}; + +cdl_option CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE { + user_value 6144 +}; + +cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM { + inferred_value 0 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS { + inferred_value 1 +}; + +cdl_option CYGSEM_HAL_ROM_MONITOR { + inferred_value 1 +}; + +cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + inferred_value 0 0 +}; + +cdl_component CYG_HAL_STARTUP { + user_value ROM +}; + +cdl_component CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +cdl_option CYGOPT_REDBOOT_FIS { + user_value 0 +}; + +cdl_component CYGSEM_REDBOOT_FLASH_CONFIG { + user_value 0 +}; + +cdl_option CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG { + user_value 0 +}; + +cdl_option CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK { + user_value -16 +}; + + +cdl_option CYGBLD_BUILD_REDBOOT_WITH_EXEC { + user_value 0 +}; + +cdl_option CYGBLD_DEV_FLASH_AT91_LOCKING { + user_value 0 +}; + +cdl_option CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK { + user_value -24 +}; + +cdl_option CYGBLD_REDBOOT_MIN_IMAGE_SIZE { + user_value 0x15000 +}; + +cdl_option CYGBLD_REDBOOT_LOAD_INTO_FLASH { + user_value 1 +}; \ No newline at end of file diff --git a/packages/hal/arm/at91/at91sam7s/v2_0/src/at91sam7s_misc.c b/packages/hal/arm/at91/at91sam7s/v2_0/src/at91sam7s_misc.c new file mode 100644 index 00000000..89596f36 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7s/v2_0/src/at91sam7s_misc.c @@ -0,0 +1,177 @@ +/*========================================================================== +// +// at91sam7s_misc.c +// +// HAL misc board support code for Atmel AT91sam7s +// +//========================================================================== +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// Copyright (C) 2006 Andrew Lunn +// +// 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): gthomas +// Contributors: gthomas, jskov, nickg, tkoeller, Oliver Munz, Andrew Lunn +// Date: 2001-07-12 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include +#include + +#include // base types +#include // tracing macros +#include // assertion macros + +#include // IO macros +#include // Register state info +#include +#include // necessary? +#include +#include // calling interface +#include // helper functions +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT +#include // HAL ISR support +#endif + +extern void hal_at91_led(int val); + +void +hal_at91_set_leds (int val) +{ + hal_at91_led(val); +} + +// ------------------------------------------------------------------------- +// Hardware init + +void hal_plf_hardware_init (void) +{ + /* Enable the Serial devices to driver the serial port pins */ + HAL_ARM_AT91_PIO_CFG(AT91_USART_RXD0); + HAL_ARM_AT91_PIO_CFG(AT91_USART_TXD0); + HAL_ARM_AT91_PIO_CFG(AT91_DBG_DTXD); + HAL_ARM_AT91_PIO_CFG(AT91_DBG_DRXD); + +#if !defined(CYGHWR_HAL_ARM_AT91SAM7S_at91sam7s32) + /* Enable the Serial devices to driver the serial port pins */ + HAL_ARM_AT91_PIO_CFG(AT91_USART_RXD1); + HAL_ARM_AT91_PIO_CFG(AT91_USART_TXD1); +#endif + + /* Setup the Reset controller. Allow user resets */ + HAL_WRITE_UINT32(AT91_RST+AT91_RST_RMR, + AT91_RST_RMR_URSTEN | + 10 << 8 | + AT91_RST_RMR_KEY); + +#ifdef CYGBLD_HAL_ARM_AT91_SERIAL_UART + /* Enable peripheral clocks for USART 0 and 1 if they are to be used */ + HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, + AT91_PMC_PCER_US0 | + AT91_PMC_PCER_US1); +#endif + +#ifdef CYGBLD_HAL_ARM_AT91_TIMER_TC + /* Enable peripheral clocks for TC 0 and 1 if they are to be used */ + HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, + AT91_PMC_PCER_TC0 | + AT91_PMC_PCER_TC2); +#endif + +#ifndef CYGPKG_IO_WATCHDOG + /* Disable the watchdog. The eCos philosophy is that the watchdog is + disabled unless the watchdog driver is used to enable it. + Whoever if we disable it here we cannot re-enable it in the + watchdog driver, hence the conditional compilation. */ + HAL_WRITE_UINT32(AT91_WDTC + AT91_WDTC_WDMR, AT91_WDTC_WDMR_DIS); +#endif + +/* Perform some platform specific bits to get the Ethernet hardware + setup. Specifically if a specific phy is used and does not start in + the correct mode a function needs to be supplied as part of the plf + to do the necessary initializations. +*/ +#ifdef CYGPKG_DEVS_ETH_ARM_AT91 +#ifdef HAL_PLF_ETH_INIT + HAL_PLF_ETH_INIT(); +#endif +#endif +} + +// Calculate the baud value to be programmed into the serial port baud +// rate generators. This function will determine what the clock speed +// is that is driving the generator so it can be used in situations +// when the application dynamically changes the clock speed. +cyg_uint32 +hal_at91_us_baud(cyg_uint32 baud_rate) +{ + cyg_uint32 val, pll; + cyg_uint32 main_clock = 0; + cyg_uint32 baud_value = 0; + + HAL_READ_UINT32((AT91_PMC+AT91_PMC_MCKR), val); + switch (val & 0x03) { + /* Slow clock */ + case AT91_PMC_MCKR_SLOW_CLK: + main_clock = CYGNUM_HAL_ARM_AT91_SLOW_CLOCK; + break; + + /* Main clock */ + case AT91_PMC_MCKR_MAIN_CLK: + main_clock = CYGNUM_HAL_ARM_AT91_CLOCK_OSC_MAIN; + break; + /* PLL */ + case AT91_PMC_MCKR_PLL_CLK: + HAL_READ_UINT32((AT91_PMC+AT91_PMC_PLLR), pll); + main_clock = CYGNUM_HAL_ARM_AT91_CLOCK_OSC_MAIN * + (((pll & 0x7FF0000) >> 16) + 1) / (pll & 0xFF); + break; + } + + // Process prescale + val = (val & 0x1C) >> 2; + main_clock = main_clock >> val; + + /* Define the baud rate divisor register, (round) */ + baud_value = (main_clock/(8*baud_rate)+1)/2; + + return baud_value; +} + +//-------------------------------------------------------------------------- +// EOF at91sam7s_misc.c diff --git a/packages/hal/arm/at91/at91sam7sek/v2_0/ChangeLog b/packages/hal/arm/at91/at91sam7sek/v2_0/ChangeLog new file mode 100644 index 00000000..174ab05a --- /dev/null +++ b/packages/hal/arm/at91/at91sam7sek/v2_0/ChangeLog @@ -0,0 +1,47 @@ +2007-10-16 Andrew Lunn + + * src/at91sam7sek_misc.c (hal_at91_led): Fix off by one error on + GPIO lines for LEDs. Reported by Rasmus Stougaard + + +2007-01-02 Uwe Kindler + + * cdl/hal_arm_at91sam7s.cdl Moved HAL_PLATFORM_XXX defines and + definition of platform header file (CYGBLD_HAL_PLATFORM_H) from + package CYGPKG_HAL_ARM_AT91SAM7 into board specific packages. + +2006-05-20 Andrew Lunn + + * AT91SAM7X-EK development board package + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 Andrew Lunn +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/arm/at91/at91sam7sek/v2_0/cdl/hal_arm_at91sam7sek.cdl b/packages/hal/arm/at91/at91sam7sek/v2_0/cdl/hal_arm_at91sam7sek.cdl new file mode 100644 index 00000000..3e1469cb --- /dev/null +++ b/packages/hal/arm/at91/at91sam7sek/v2_0/cdl/hal_arm_at91sam7sek.cdl @@ -0,0 +1,74 @@ +# ==================================================================== +# +# hal_arm_at91_sam7sek.cdl +# +# ARM AT91 SAM7S EK development board package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## Copyright (C) 2006 Andrew Lunn +## +## 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): andrew lunn +# Contributors: +# Date: 2006-05-20 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_AT91SAM7SEK { + display "Atmel AT91SAM7S EK development board" + parent CYGPKG_HAL_ARM_AT91SAM7 + define_header hal_arm_at91sam7sek.h + include_dir cyg/hal + hardware + description " + The AT91SAM7SEK HAL package provides the support needed to run + eCos on an Atmel AT91SAM7S-EK development board." + + compile at91sam7sek_misc.c + + requires { CYGHWR_HAL_ARM_AT91 == "AT91SAM7S" } + requires { CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s256" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s128" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s64" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s32" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7s321" } + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "/***** proc output start *****/" + puts $::cdl_header "#include " + puts $::cdl_header "#define HAL_PLATFORM_CPU \"ARM7TDMI\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"Atmel (AT91SAM7S-EK)\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + puts $::cdl_header "/****** proc output end ******/" + } +} diff --git a/packages/hal/arm/at91/at91sam7sek/v2_0/src/at91sam7sek_misc.c b/packages/hal/arm/at91/at91sam7sek/v2_0/src/at91sam7sek_misc.c new file mode 100644 index 00000000..dcd42a0e --- /dev/null +++ b/packages/hal/arm/at91/at91sam7sek/v2_0/src/at91sam7sek_misc.c @@ -0,0 +1,77 @@ +/*========================================================================== +// +// at91sam7sek_misc.c +// +// HAL misc board support code for Atmel AT91sam7s EK board +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 Andrew Lunn +// +// 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): andrew lunn +// Contributors: Oliver Munz, Andrew Lunn +// Date: 2006-06-20 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include +#include + +#include // IO macros + +// The development board has four LEDs +void +hal_at91_led (int val) +{ + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PA0, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PA1, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PA2, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PA3, AT91_PIN_OUT); + + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PA0, AT91_PIN_PULLUP_DISABLE); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PA1, AT91_PIN_PULLUP_DISABLE); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PA2, AT91_PIN_PULLUP_DISABLE); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PA3, AT91_PIN_PULLUP_DISABLE); + + // Set the bits. The logic is inverted + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PA0, !(val & 1)); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PA1, !(val & 2)); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PA2, !(val & 4)); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PA3, !(val & 8)); +} + +//-------------------------------------------------------------------------- +// EOF at91sam7sek_misc.c diff --git a/packages/hal/arm/at91/at91sam7xek/v2_0/ChangeLog b/packages/hal/arm/at91/at91sam7xek/v2_0/ChangeLog new file mode 100644 index 00000000..4bc1e011 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7xek/v2_0/ChangeLog @@ -0,0 +1,54 @@ +2008-04-30 John Eigelaar + + * cdl/hal_arm_at91sam7xek.cdl: Added configuration options in + order to support the at91sam7x512 + * src/at91sam7xek_misc.c: Fix a typo in the phy initialisation code. + Pin 18 was being setup to drive the powerdown pin of the phy but + pin 19 was driven low instead. + +2007-01-17 John Eigelaar + + * Added hal_plf_eth_init() in order to initialise the Davicom + 9161A PHY properly on the Evaluation board + +2007-01-02 Uwe Kindler + + * cdl/hal_arm_at91sam7s.cdl Moved HAL_PLATFORM_XXX defines and + definition of platform header file (CYGBLD_HAL_PLATFORM_H) from + package CYGPKG_HAL_ARM_AT91SAM7 into board specific packages. + +2006-05-20 Andrew Lunn + + * AT91SAM7X-EK development board package + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 Andrew Lunn +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/arm/at91/at91sam7xek/v2_0/cdl/hal_arm_at91sam7xek.cdl b/packages/hal/arm/at91/at91sam7xek/v2_0/cdl/hal_arm_at91sam7xek.cdl new file mode 100644 index 00000000..d25f1678 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7xek/v2_0/cdl/hal_arm_at91sam7xek.cdl @@ -0,0 +1,75 @@ +# ==================================================================== +# +# hal_arm_at91_sam7xek.cdl +# +# ARM AT91 SAM7X EK development board package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## Copyright (C) 2006 Andrew Lunn +## +## 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): andrew lunn +# Contributors: +# Date: 2006-05-20 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_AT91SAM7XEK { + display "Atmel AT91SAM7X EK development board" + parent CYGPKG_HAL_ARM_AT91SAM7 + define_header hal_arm_at91sam7xek.h + include_dir cyg/hal + hardware + description " + The AT91SAM7XEK HAL package provides the support needed to run + eCos on an Atmel AT91SAM7X-EK development board." + + compile at91sam7xek_misc.c + + requires { CYGHWR_HAL_ARM_AT91 == "AT91SAM7S" } + requires { CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7x256" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7x128" || + CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7x512" } + + requires { is_active(CYGPKG_DEVS_ETH_PHY) implies + (1 == CYGHWR_DEVS_ETH_PHY_DM9161A) } + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "/***** proc output start *****/" + puts $::cdl_header "#include " + puts $::cdl_header "#define HAL_PLATFORM_CPU \"ARM7TDMI\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"Atmel (AT91SAM7X-EK)\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + puts $::cdl_header "/****** proc output end ******/" + } +} diff --git a/packages/hal/arm/at91/at91sam7xek/v2_0/src/at91sam7xek_misc.c b/packages/hal/arm/at91/at91sam7xek/v2_0/src/at91sam7xek_misc.c new file mode 100644 index 00000000..ba5b2764 --- /dev/null +++ b/packages/hal/arm/at91/at91sam7xek/v2_0/src/at91sam7xek_misc.c @@ -0,0 +1,113 @@ +/*========================================================================== +// +// at91sam7xek_misc.c +// +// HAL misc board support code for Atmel AT91SAM7X EK board +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 Andrew Lunn +// +// 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): andrew lunn +// Contributors: Andrew Lunn, John Eigelaar +// Date: 2006-06-20 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include +#include + +#include // IO macros + +// The development board has four LEDs +void +hal_at91_led (int val) +{ + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB19, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB20, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB21, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB22, AT91_PIN_OUT); + + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB19, AT91_PIN_PULLUP_DISABLE); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB20, AT91_PIN_PULLUP_DISABLE); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB21, AT91_PIN_PULLUP_DISABLE); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB22, AT91_PIN_PULLUP_DISABLE); + + // Set the bits. The logic is inverted + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PB19, !(val & 1)); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PB20, !(val & 2)); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PB21, !(val & 4)); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PB22, !(val & 8)); +} + +void hal_plf_eth_init(void) +{ + cyg_uint32 stat; + + /* Enable the PIOB Clock */ + HAL_WRITE_UINT32(AT91_PMC + AT91_PMC_PCER, AT91_PMC_PCER_PIOB); + + /* RXDV / Testmode select */ + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB15, AT91_PIN_IN); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB15, AT91_PIN_PULLUP_DISABLE); + + //TODO: The errata reports that the RMII mode for the SAM7X does not work. + // It would probably still be a good idea to use the RMII/MII CDL + // configuration to select the appropriate mode here + /* COL / !MII select */ + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB16, AT91_PIN_IN); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB16, AT91_PIN_PULLUP_DISABLE); + + /* TXCLK / ISOLATE */ + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB0, AT91_PIN_IN); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB0, AT91_PIN_PULLUP_DISABLE); + + /* Power Down Mode */ + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB18, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PB18,0); + + /* All the lines setup correctly. Now do a external reset and let the phy + start up in the correct mode */ + HAL_WRITE_UINT32(AT91_RST+AT91_RST_RMR,AT91_RST_RMR_KEY|(1<<0x8)); + HAL_WRITE_UINT32(AT91_RST+AT91_RST_RCR,AT91_RST_RCR_KEY|AT91_RST_RCR_EXTRST); + + do { + HAL_READ_UINT32(AT91_RST+AT91_RST_RSR,stat); + } while (!(stat&AT91_RST_RSR_NRST_SET)); +} + +//-------------------------------------------------------------------------- +// EOF at91sam7sek_misc.c diff --git a/packages/hal/arm/at91/sam7ex256/v2_0/ChangeLog b/packages/hal/arm/at91/sam7ex256/v2_0/ChangeLog new file mode 100644 index 00000000..77cf90f4 --- /dev/null +++ b/packages/hal/arm/at91/sam7ex256/v2_0/ChangeLog @@ -0,0 +1,50 @@ +2007-04-10 Uwe Kindler + + * cdl/hal_arm_sam7ex256.cdl Removed "implements + CYGINT_DEVS_CAN_AT91SAM7_CAN0" because this interface is already + implemented by package CYGPKG_HAL_ARM_AT91SAM7 + +2007-04-06 Uwe Kindler + + * src/sam7ex256_misc.c Added hal_plf_eth_init() in order to initialise + the Micrel KS8721 PHY properly on the Olimex board + +2007-08-01 Uwe Kindler + + * src/sam7ex256_misc.c Use the backlight of the lcd as a simple 1-bit LED + +2006-12-30 Uwe Kindler + + * SAM7-EX256 development board package + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 Andrew Lunn +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/arm/at91/sam7ex256/v2_0/cdl/hal_arm_sam7ex256.cdl b/packages/hal/arm/at91/sam7ex256/v2_0/cdl/hal_arm_sam7ex256.cdl new file mode 100644 index 00000000..4717f55d --- /dev/null +++ b/packages/hal/arm/at91/sam7ex256/v2_0/cdl/hal_arm_sam7ex256.cdl @@ -0,0 +1,74 @@ +# ==================================================================== +# +# hal_arm_sam7ex256.cdl +# +# Olimex SAM7-EX256 development board package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## Copyright (C) 2006 Andrew Lunn +## +## 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: 2006-12-30 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_SAM7EX256 { + display "Olimex SAM7-EX256 development board" + parent CYGPKG_HAL_ARM_AT91SAM7 + define_header hal_arm_sam7ex256.h + include_dir cyg/hal + hardware + description " + The SAM7EX256 HAL package provides the support needed to run + eCos on an Olimex SAM7-EX256 development board." + + compile sam7ex256_misc.c + + requires { CYGHWR_HAL_ARM_AT91 == "AT91SAM7S" } + requires { CYGHWR_HAL_ARM_AT91SAM7 == "at91sam7x256" } + + requires { is_active(CYGPKG_DEVS_ETH_PHY) implies + (1 == CYGHWR_DEVS_ETH_PHY_KS8721) } + + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "/***** proc output start *****/" + puts $::cdl_header "#include " + puts $::cdl_header "#define HAL_PLATFORM_CPU \"ARM7TDMI\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"Olimex SAM7-EX256\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + puts $::cdl_header "/****** proc output end ******/" + } +} diff --git a/packages/hal/arm/at91/sam7ex256/v2_0/src/sam7ex256_misc.c b/packages/hal/arm/at91/sam7ex256/v2_0/src/sam7ex256_misc.c new file mode 100644 index 00000000..27f88894 --- /dev/null +++ b/packages/hal/arm/at91/sam7ex256/v2_0/src/sam7ex256_misc.c @@ -0,0 +1,111 @@ +/*========================================================================== +// +// sam7ex256_misc.c +// +// HAL misc board support code for Olimex SAM7-EX256 board +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 Andrew Lunn +// +// 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: Andrew Lunn, John Eigelaar +// Date: 2006-12-30 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include +#include + +#include // IO macros + +// +// The development board does not contain any leds but a nokia 320 x 320 +// pixel lcd. We use the backlight of the lcd as a simple 1-bit LED +// +void hal_at91_led (int val) +{ + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB20, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PB20, (val & 1)); +} + +// +// Initialisation of Micrel KS8721 ethernet phy +// +void hal_plf_eth_init(void) +{ + cyg_uint32 stat; + + // Enable the PIOB Clock + HAL_WRITE_UINT32(AT91_PMC + AT91_PMC_PCER, AT91_PMC_PCER_PIOB); + + // PU = Enables PCS_LPBK mode at power-up / reset. + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB15, AT91_PIN_IN); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB15, AT91_PIN_PULLUP_DISABLE); + + // PU = Enables ISOLATE mode at power-up /reset. + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB7, AT91_PIN_IN); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB7, AT91_PIN_PULLUP_DISABLE); + + // PU = Enables RMII mode at power-up / reset + // TODO: The errata reports that the RMII mode for the SAM7X does not work. + // It would probably still be a good idea to use the RMII/MII CDL + // configuration to select the appropriate mode here + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB16, AT91_PIN_IN); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB16, AT91_PIN_PULLUP_DISABLE); + + // PU = Enable RMII_BTB mode at power-up / reset. + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB4, AT91_PIN_IN); + HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PB4, AT91_PIN_PULLUP_DISABLE); + + // Power Down Mode = 1 = normal operation + HAL_ARM_AT91_GPIO_CFG_DIRECTION(AT91_GPIO_PB18, AT91_PIN_OUT); + HAL_ARM_AT91_GPIO_PUT(AT91_GPIO_PB18, 1); + + // All the lines setup correctly. Now do a external reset and let the phy + // start up in the correct mode + HAL_WRITE_UINT32(AT91_RST+AT91_RST_RMR,AT91_RST_RMR_KEY|(1<<0x8)); + HAL_WRITE_UINT32(AT91_RST+AT91_RST_RCR,AT91_RST_RCR_KEY|AT91_RST_RCR_EXTRST); + + do + { + HAL_READ_UINT32(AT91_RST+AT91_RST_RSR,stat); + } while (!(stat & AT91_RST_RSR_NRST_SET)); +} + + +//-------------------------------------------------------------------------- +// EOF sam7ex256_misc.c diff --git a/packages/hal/arm/at91/var/v2_0/src/hal_diag_dbg.c b/packages/hal/arm/at91/var/v2_0/src/hal_diag_dbg.c new file mode 100644 index 00000000..831a5f68 --- /dev/null +++ b/packages/hal/arm/at91/var/v2_0/src/hal_diag_dbg.c @@ -0,0 +1,348 @@ +/*============================================================================= +// +// hal_diag_dbg.c +// +// HAL diagnostic output code using the debug serial port +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): jskov +// Contributors:jskov, gthomas +// Date: 2001-07-12 +// Purpose: HAL diagnostic output +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + + +#include +#include + +#include CYGBLD_HAL_PLATFORM_H + +#include // base types + +#include // SAVE/RESTORE GP macros +#include // IO macros +#include // interface API +#include // HAL_ENABLE/MASK/UNMASK_INTERRUPTS +#include // Helper functions +#include // CYG_ISR_HANDLED +#include + +#include // Device registers + +#include "hal_diag_dcc.h" // DCC initialization file +//----------------------------------------------------------------------------- +typedef struct { + cyg_uint8* base; + cyg_int32 msec_timeout; + int isr_vector; + cyg_uint32 baud_rate; +} channel_data_t; + +//----------------------------------------------------------------------------- + +static void +cyg_hal_plf_serial_dbg_init_channel(void* __ch_data) +{ + cyg_uint8 *base = ((channel_data_t*)__ch_data)->base; + + cyg_uint32 baud_value = 0; + cyg_uint32 baud_rate = ((channel_data_t*)__ch_data)->baud_rate; + + /* Enable pins to be driven by peripheral, using peripheral A. */ + HAL_WRITE_UINT32((AT91_PIO+AT91_PIO_ASR), + (AT91_PIO_PSR_DRXD | + AT91_PIO_PSR_DTXD)); + + /* Disables the PIO from controlling the corresponding pin + (enables peripheral control of the pin). */ + HAL_WRITE_UINT32((AT91_PIO+AT91_PIO_PDR), + (AT91_PIO_PSR_DRXD | + AT91_PIO_PSR_DTXD)); + + /* Disable interrupt */ + HAL_WRITE_UINT32((base+AT91_DBG_IDR), 0xFFFFFFFF); + + /* Reset receiver and transmitter */ + HAL_WRITE_UINT32((base+AT91_DBG_CR), + (AT91_DBG_CR_RSTRX | AT91_DBG_CR_RSTTX | + AT91_DBG_CR_RXDIS | AT91_DBG_CR_TXDIS)); + + baud_value = AT91_US_BAUD(baud_rate); + + HAL_WRITE_UINT32((base+AT91_DBG_BRGR), baud_value); + + /* Define the USART mode */ + /* (USART) Normal, 1 stop bit, No Parity, Character Length: 8 bits, Clock */ + HAL_WRITE_UINT32(base+AT91_DBG_MR, + (AT91_DBG_MR_CHMODE_NORMAL | + AT91_DBG_MR_PAR_NONE)); + + /* Enable Transmitter */ + HAL_WRITE_UINT32((base+AT91_DBG_CR), AT91_DBG_CR_TXEN); + + /* Enable Receiver */ + HAL_WRITE_UINT32((base+AT91_DBG_CR), AT91_DBG_CR_RXEN); +} + +void +cyg_hal_plf_serial_dbg_putc(void* __ch_data, char c) +{ + cyg_uint8 * base = ((channel_data_t*)__ch_data)->base; + cyg_uint32 status; + CYGARC_HAL_SAVE_GP(); + + // Wait for Tx FIFO not full + do + { + HAL_READ_UINT32((base+AT91_DBG_CSR), status); + } + while (!(status & AT91_DBG_CSR_TXRDY)) ; + + //UART TX data register + HAL_WRITE_UINT8((base+AT91_DBG_THR), c); + + CYGARC_HAL_RESTORE_GP(); +} + +static cyg_bool +cyg_hal_plf_serial_dbg_getc_nonblock(void* __ch_data, cyg_uint8* ch) +{ + cyg_uint8 * base = ((channel_data_t*)__ch_data)->base; + cyg_uint32 status; + + HAL_READ_UINT32((base+AT91_DBG_CSR), status); + if (status & AT91_DBG_CSR_RXRDY) + { + HAL_READ_UINT8((base+AT91_DBG_RHR), *ch); + return true; + } + return false; +} + +cyg_uint8 +cyg_hal_plf_serial_dbg_getc(void* __ch_data) +{ + cyg_uint8 ch; + CYGARC_HAL_SAVE_GP(); + + while (!cyg_hal_plf_serial_dbg_getc_nonblock(__ch_data, &ch)); + + CYGARC_HAL_RESTORE_GP(); + return ch; +} + +static void +cyg_hal_plf_serial_dbg_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while (__len-- > 0) + cyg_hal_plf_serial_dbg_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_serial_dbg_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while (__len-- > 0) + *__buf++ = cyg_hal_plf_serial_dbg_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +cyg_bool +cyg_hal_plf_serial_dbg_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_bool res; + CYGARC_HAL_SAVE_GP(); + + delay_count = chan->msec_timeout * 10; // delay in .1 ms steps + + for (;;) { + res = cyg_hal_plf_serial_dbg_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static int +cyg_hal_plf_serial_dbg_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + int ret = 0; + va_list ap; + + CYGARC_HAL_SAVE_GP(); + va_start(ap, __func); + + switch (__func) { + case __COMMCTL_GETBAUD: + ret = chan->baud_rate; + break; + case __COMMCTL_SETBAUD: + chan->baud_rate = va_arg(ap, cyg_int32); + // Should we verify this value here? + cyg_hal_plf_serial_dbg_init_channel(chan); + ret = 0; + break; + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + HAL_INTERRUPT_UNMASK(chan->isr_vector); + HAL_WRITE_UINT32((chan->base+AT91_DBG_IER), AT91_DBG_CSR_RXRDY); + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + HAL_WRITE_UINT32((chan->base+AT91_DBG_IDR), AT91_DBG_CSR_RXRDY); + HAL_INTERRUPT_MASK(chan->isr_vector); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = chan->isr_vector; + break; + case __COMMCTL_SET_TIMEOUT: + ret = chan->msec_timeout; + chan->msec_timeout = va_arg(ap, cyg_uint32); + default: + break; + } + CYGARC_HAL_RESTORE_GP(); + return ret; +} + +static int +cyg_hal_plf_serial_dbg_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + int res = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint32 status; + cyg_uint32 c; + cyg_uint8 ch; + CYGARC_HAL_SAVE_GP(); + + *__ctrlc = 0; + HAL_READ_UINT32(chan->base+AT91_DBG_CSR, status); + if ( (status & AT91_DBG_CSR_RXRDY) != 0 ) { + + HAL_READ_UINT32(chan->base+AT91_DBG_RHR, c); + ch = (cyg_uint8)(c & 0xff); + if( cyg_hal_is_break( &ch , 1 ) ) + *__ctrlc = 1; + + res = CYG_ISR_HANDLED; + } + + HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector); + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static channel_data_t at91_ser_channels[1] = { + { (cyg_uint8*)AT91_DBG, 1000, CYGNUM_HAL_INTERRUPT_DBG, + CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD} +}; + +static void +cyg_hal_plf_serial_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur; + + cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Init channels + cyg_hal_plf_serial_dbg_init_channel(&at91_ser_channels[0]); + + // Setup procs in the vector table + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &at91_ser_channels[0]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_dbg_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_dbg_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_dbg_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_dbg_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_dbg_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_dbg_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_dbg_getc_timeout); + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + + initialized = 1; + + cyg_hal_plf_serial_init(); + +#ifdef CYGBLD_HAL_ARM_AT91_DCC + cyg_hal_plf_dcc_init(CYGBLD_HAL_ARM_AT91_DCC_CHANNEL); +#endif +} + +void +hal_diag_led(int mask) +{ + hal_at91_set_leds(mask); +} + +//----------------------------------------------------------------------------- +// End of hal_diag_dbg.c diff --git a/packages/hal/arm/at91/var/v2_0/src/hal_diag_dcc.c b/packages/hal/arm/at91/var/v2_0/src/hal_diag_dcc.c new file mode 100644 index 00000000..a3a021e3 --- /dev/null +++ b/packages/hal/arm/at91/var/v2_0/src/hal_diag_dcc.c @@ -0,0 +1,211 @@ +/*============================================================================= +// +// hal_diag_dcc.c +// +// HAL diagnostic output via the DCC interface. +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 FSF +// +// 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): Andrew Lunn +// Contributors:jskov, gthomas +// Date: 2008-06-15 +// Purpose: HAL diagnostic output via DCC. +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include +#include CYGBLD_HAL_PLATFORM_H + +#include // base types + +#include // SAVE/RESTORE GP macros +#include // IO macros +#include // interface API +#include // HAL_ENABLE/MASK/UNMASK_INTERRUPTS +#include // Helper functions +#include + +#define DCC_TX_BUSY 2 +#define DCC_RX_READY 1 + +//----------------------------------------------------------------------------- + +static void +cyg_hal_plf_dcc_putc(void * __ch_data, char ch) +{ + unsigned int status; + CYG_UNUSED_PARAM(void *, __ch_data); + + CYGARC_HAL_SAVE_GP(); + + do { + __asm__ volatile ( "mrc p14,0, %0, c0, c0\n" : "=r" (status)); + } while ( status & DCC_TX_BUSY ); + __asm__( "mcr p14,0, %0, c1, c0\n" : : "r" (ch)); + + CYGARC_HAL_RESTORE_GP(); +} + +static cyg_bool +cyg_hal_plf_dcc_getc_nonblock(cyg_uint8* ch) +{ + cyg_uint32 status; + cyg_uint32 c; + + __asm__( "mrc p14,0, %0, c0, c0\n" : "=r" (status)); + + if (status & DCC_RX_READY) { + __asm__( "mrc p14,0, %0, c1, c0\n" : "=r" (c)); + *ch = (char )c; + return true; + } else + return false; +} + +static cyg_uint8 +cyg_hal_plf_dcc_getc(void* __ch_data) +{ + cyg_uint8 ch; + CYG_UNUSED_PARAM(void *, __ch_data); + CYGARC_HAL_SAVE_GP(); + + while(!cyg_hal_plf_dcc_getc_nonblock(&ch)); + + CYGARC_HAL_RESTORE_GP(); + return ch; +} + +static void +cyg_hal_plf_dcc_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYG_UNUSED_PARAM(void *, __ch_data); + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_dcc_putc(NULL, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_dcc_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYG_UNUSED_PARAM(void *, __ch_data); + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_dcc_getc(NULL); + + CYGARC_HAL_RESTORE_GP(); +} + +static cyg_bool +cyg_hal_plf_dcc_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + cyg_bool res; + CYG_UNUSED_PARAM(void *, __ch_data); + + CYGARC_HAL_SAVE_GP(); + + delay_count = 100010; // delay in .1 ms steps + + for(;;) { + res = cyg_hal_plf_dcc_getc_nonblock(ch); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static int +cyg_hal_plf_dcc_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + CYG_UNUSED_PARAM(void *, __ch_data); + CYG_UNUSED_PARAM(__comm_control_cmd_t, __func); + + return 0; +} + +static void +cyg_hal_plf_dcc_register(const int channel) +{ + hal_virtual_comm_table_t* comm; + int cur; + + cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + // Setup procs in the vector table + + CYGACC_CALL_IF_SET_CONSOLE_COMM(channel); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, NULL); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_dcc_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_dcc_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_dcc_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_dcc_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_dcc_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, NULL); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_dcc_getc_timeout); + + // Restore to original console. + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +void +cyg_hal_plf_dcc_init(const int channel) +{ + static int initialized = 0; + + if (initialized) + return; + + initialized = 1; + + cyg_hal_plf_dcc_register(channel); +} + +//----------------------------------------------------------------------------- +// End of hal_diag_dcc.c diff --git a/packages/hal/arm/at91/var/v2_0/src/hal_diag_dcc.h b/packages/hal/arm/at91/var/v2_0/src/hal_diag_dcc.h new file mode 100644 index 00000000..ecffd101 --- /dev/null +++ b/packages/hal/arm/at91/var/v2_0/src/hal_diag_dcc.h @@ -0,0 +1,60 @@ +#ifndef CYGONCE_HAL_DIAG_DCC_H +#define CYGONCE_HAL_DIAG_DCC_H + +//============================================================================= +// +// hal_diag_dcc.h +// +// HAL Support for Kernel Diagnostic Routines via DCC +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2008 FSF. +// +// 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): asl +// Contributors: +// Date: 2008-06-15 +// Purpose: HAL Support for Kernel Diagnostic Routines via DCC. +// Description: Diagnostic routines for use during kernel development. +// Usage: #include "hal_diag_dcc.h" +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +externC void cyg_hal_plf_dcc_init(const int channel); + +#endif + diff --git a/packages/hal/arm/at91/var/v2_0/src/timer_pit.c b/packages/hal/arm/at91/var/v2_0/src/timer_pit.c new file mode 100644 index 00000000..1de14df7 --- /dev/null +++ b/packages/hal/arm/at91/var/v2_0/src/timer_pit.c @@ -0,0 +1,151 @@ +/*========================================================================== +// +// timer_pit.c +// +// HAL timer code using the Periodic Interval Timer +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): asl, Oliver Munz +// Contributors: asl, Oliver Munz +// Date: 2006-02-12 +// Purpose: Clock support using the PIT +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include + +#include // base types +#include // assertion macros + +#include // IO macros +#include +// ------------------------------------------------------------------------- +// Use system clock +void +hal_clock_initialize(cyg_uint32 period) +{ + cyg_uint32 sr; + + CYG_ASSERT(CYGNUM_HAL_INTERRUPT_RTC == CYGNUM_HAL_INTERRUPT_PITC, + "Invalid timer interrupt"); + + /* Set Period Interval timer and enable interrupt */ + HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR), + (period - 1) | + AT91_PITC_PIMR_PITEN | + AT91_PITC_PIMR_PITIEN); + + // Read the status register to clear any pending interrupt + HAL_READ_UINT32(AT91_PITC + AT91_PITC_PISR, sr); +} + +// This routine is called during a clock interrupt. +void +hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) +{ + cyg_uint32 reg; + cyg_uint32 pimr; + + CYG_ASSERT(period < AT91_PITC_VALUE_MASK, "Invalid HAL clock configuration"); + + // Check that the PIT has the right period. + HAL_READ_UINT32((AT91_PITC + AT91_PITC_PIMR), pimr); + if ((pimr & AT91_PITC_VALUE_MASK) != (period - 1)) { + HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR), + (period - 1) | + AT91_PITC_PIMR_PITEN | + AT91_PITC_PIMR_PITIEN); + } + + /* Read the value register so that we clear the interrupt */ + HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIVR, reg); +} + +// Read the current value of the clock, returning the number of hardware +// "ticks" that have occurred (i.e. how far away the current value is from +// the start) +void +hal_clock_read(cyg_uint32 *pvalue) +{ + cyg_uint32 ir; + cyg_uint32 pimr; + + // Check that the PIT is running. If not start it. + HAL_READ_UINT32((AT91_PITC + AT91_PITC_PIMR),pimr); + if (!(pimr & AT91_PITC_PIMR_PITEN)) { + HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR), + AT91_PITC_VALUE_MASK | AT91_PITC_PIMR_PITEN); + } + + HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIIR, ir); + *pvalue = ir & AT91_PITC_VALUE_MASK; +} + +// ------------------------------------------------------------------------- +// +// Delay for some number of micro-seconds +// PIT is clocked at MCLK / 16 +// +void hal_delay_us(cyg_int32 usecs) +{ + cyg_int64 ticks; + cyg_uint32 val1, val2; + cyg_uint32 piv; + + // Calculate how many PIT ticks the required number of microseconds + // equate to. We do this calculation in 64 bit arithmetic to avoid + // overflow. + ticks = (((cyg_uint64)usecs) * + ((cyg_uint64)CYGNUM_HAL_ARM_AT91_CLOCK_SPEED))/16/1000000LL; + + // Calculate the wrap around period. + HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIMR, piv); + piv = (piv & AT91_PITC_VALUE_MASK) - 1; + + hal_clock_read(&val1); + while (ticks > 0) { + hal_clock_read(&val2); + if (val2 < val1) + ticks -= ((piv + val2) - val1); //overflow occurred + else + ticks -= (val2 - val1); + val1 = val2; + } +} + +// timer_pit.c diff --git a/packages/hal/arm/at91/var/v2_0/src/timer_tc.c b/packages/hal/arm/at91/var/v2_0/src/timer_tc.c new file mode 100644 index 00000000..ecd29bef --- /dev/null +++ b/packages/hal/arm/at91/var/v2_0/src/timer_tc.c @@ -0,0 +1,160 @@ +/*========================================================================== +// +// timer_tc.c +// +// HAL timer code using the Timer Counter +// +//========================================================================== +//####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 Nick Garnett +// +// 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): gthomas +// Contributors: gthomas, jskov, nickg, tkoeller +// Date: 2001-07-12 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include + +#include // base types +#include // assertion macros + +#include // IO macros +#include // Register state info +#include // necessary? + +// ------------------------------------------------------------------------- +// Clock support + +static cyg_uint32 _period; + +void hal_clock_initialize(cyg_uint32 period) +{ + CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0; + + CYG_ASSERT(period < 0x10000, "Invalid clock period"); + + // Disable counter + HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_CLKDIS); + + // Set registers + HAL_WRITE_UINT32(timer+AT91_TC_CMR, AT91_TC_CMR_CPCTRG | // Reset counter on CPC + AT91_TC_CMR_CLKS_MCK32); // 1 MHz + HAL_WRITE_UINT32(timer+AT91_TC_RC, period); + + // Start timer + HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN); + + // Enable timer 0 interrupt + HAL_WRITE_UINT32(timer+AT91_TC_IER, AT91_TC_IER_CPC); +} + +void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) +{ + CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0; + cyg_uint32 sr; + + CYG_ASSERT(period < 0x10000, "Invalid clock period"); + + HAL_READ_UINT32(timer+AT91_TC_SR, sr); // Clear interrupt + + if (period != _period) { + hal_clock_initialize(period); + } + _period = period; + +} + +void hal_clock_read(cyg_uint32 *pvalue) +{ + CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0; + cyg_uint32 val; + + HAL_READ_UINT32(timer+AT91_TC_CV, val); + *pvalue = val; +} + +// ------------------------------------------------------------------------- +// +// Delay for some number of micro-seconds +// Use timer #2 in MCLOCK/32 mode. +// +void hal_delay_us(cyg_int32 usecs) +{ + cyg_uint32 stat; + cyg_uint64 ticks; +#if defined(CYGHWR_HAL_ARM_AT91_JTST) + // TC2 is reserved for AD/DA. Use TC1 instead. + CYG_ADDRESS timer = AT91_TC+AT91_TC_TC1; +#else + CYG_ADDRESS timer = AT91_TC+AT91_TC_TC2; +#endif + // Calculate how many timer ticks the required number of + // microseconds equate to. We do this calculation in 64 bit + // arithmetic to avoid overflow. + ticks = (((cyg_uint64)usecs) * + ((cyg_uint64)CYGNUM_HAL_ARM_AT91_CLOCK_SPEED))/32000000LL; + + // CYG_ASSERT(ticks < (1 << 16), "Timer overflow"); + + if (ticks > (1 << 16)) + ticks = (1 << 16) - 1; + + if (ticks == 0) + return; + + // Disable counter + HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_CLKDIS); + + // Set registers + HAL_WRITE_UINT32(timer+AT91_TC_CMR, AT91_TC_CMR_CLKS_MCK32); // 1MHz + HAL_WRITE_UINT32(timer+AT91_TC_RA, 0); + HAL_WRITE_UINT32(timer+AT91_TC_RC, ticks); + + // Clear status flags + HAL_READ_UINT32(timer+AT91_TC_SR, stat); + + // Start timer + HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN); + + // Wait for the compare + do { + HAL_READ_UINT32(timer+AT91_TC_SR, stat); + } while ((stat & AT91_TC_SR_CPC) == 0); +} + +// timer_tc.c diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/ChangeLog b/packages/hal/arm/lpc24xx/ea2468/v2_0/ChangeLog new file mode 100755 index 00000000..f195cc6c --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/ChangeLog @@ -0,0 +1,48 @@ +2008-07-21 Uwe Kindler + + * src/ea2468_misc.c: Added hal_lpc_can_init() to initialize CAN + channels + * include/plf_io.h: Added HAL_LPC2XXX_INIT_CAN() macro for CAN channel + initialisation + +2008-07-06 Uwe Kindler + + * Initial release of Embedded Artists LPC2468 OEM board package + * cdl/hal_arm_lpc2xxx_ea2468.cdl + * include/plf_io.h + * include/hal_platform_setup.h + * src/ea2468_misc + +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2008 eCosCentric Ltd. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== + diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/cdl/hal_arm_lpc24xx_ea2468.cdl b/packages/hal/arm/lpc24xx/ea2468/v2_0/cdl/hal_arm_lpc24xx_ea2468.cdl new file mode 100755 index 00000000..97e28c3b --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/cdl/hal_arm_lpc24xx_ea2468.cdl @@ -0,0 +1,317 @@ +# ==================================================================== +# +# hal_arm_lpc24xx_ea2468.cdl +# +# Embedded Artists LPC2468 OEM Board HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2008 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: Uwe Kindler +# Date: 2008-07-06 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_LPC24XX_EA2468 { + display "Embedded Artists LPC2468 OEM Board board HAL" + parent CYGPKG_HAL_ARM_LPC24XX + define_header hal_arm_lpc24xx_ea2468.h + include_dir cyg/hal + hardware + implements CYGINT_DEVS_CAN_LPC2XXX_CAN0 + implements CYGINT_DEVS_CAN_LPC2XXX_CAN1 + implements CYGINT_IO_SERIAL_LPC24XX_UART0 + implements CYGINT_IO_SERIAL_LPC24XX_UART1 + description " + The LPC2468 OEM HAL package provides the support needed to run + eCos on Embedded Artists LPC2468 OEM 16/32 boards." + + compile ea2468_misc.c + + requires { CYGHWR_HAL_ARM_LPC24XX == "LPC2468" } + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " + puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H " + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "#define HAL_PLATFORM_CPU \"ARM7TDMI-S\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"Embedded Artists LPC2468 OEM Board\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + } + + cdl_option CYGNUM_HAL_ARM_LPC24XX_XTAL_FREQ { + display "CPU xtal frequency" + parent CYGNUM_HAL_ARM_LPC24XX_CLOCKING + flavor data + default_value {12000000} + } + + cdl_option CYGNUM_HAL_ARM_LPC24XX_MAX_CLOCK_SPEED { + display "Max. CPU clock speed" + parent CYGNUM_HAL_ARM_LPC24XX_CLOCKING + flavor data + calculated {57600000} + requires CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED <= 57600000 + description " + Due to a silicon errata, the highest internal core + clock frequency (at the time of writing this document) + is 57.6 MHz. This corresponds to an internal PLL + frequency of 288 MHz that is divided by 6 to get a 48 + MHz clock for the core and the USB interface." + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + default_value {"ROM"} + legal_values {"RAM" "ROM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + Choose RAM or ROM startup type. Typically ROM startup is used for + building RedBoot. RedBoot runs from internal on chip flash of + LPC24xx. Use RAM startup for building eCos applications. + RedBoot manages the external on board flash devices. It copies + the eCos application image from FLASH to on board SDRAM + and then starts the eCos application." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 2 + description " + Channel 0: UART0, Channel 1: UART1" + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT { + display "Default console channel." + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + calculated 0 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The LPC2468 OEM board has two serial channels. The first + channel, UART0, ist routed to an USB-to-serial bridge and + the second channel, UART1, is available on the Sub-D9 + RS232 connector. This option chooses which channel will be + used to connect to a host running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "GDB serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 38400 + description " + This option controls the baud rate used for the GDB + connection." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The LPC2468 OEM board has two serial ports. This option + chooses which port will be used for diagnostic output." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 38400 + description " + This option selects the baud rate used for the diagnostic port." + } + + cdl_option CYGHWR_HAL_ARM_LPC24XX_EA2468_DATA_BUS_WIDTH { + display "Data bus width" + flavor data + default_value { 16 } + legal_values { 16 32 } + description " + The LPC2468 OEM board is sold in two different data bus + versions - a 16-bit version and a 32-bit version." + } + + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + description " + Global build options including control over compiler flags, + linker flags and choice of toolchain." + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "arm-elf" } + description " + This option specifies the command prefix used when + invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -mno-short-load-words -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + description " + This option controls the global compiler flags which + are used to compile all packages by default. Individual + packages may define options which override these global + flags." + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -mno-short-load-words -Wl,--gc-sections -Wl,-static -g -nostdlib" } + description " + This option controls the global linker flags. Individual + packages may define options which override these global + flags." + } + } + + cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM"} + description " + Enable this option if this program is to be used as a + ROM monitor, i.e. applications will be loaded into RAM on + the board, and this ROM monitor may process exceptions or + interrupts generated from the application. This enables + features such as utilizing a separate interrupt stack when + exceptions are generated." + } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM + monitor. This support changes various eCos semantics such + as the encoding of diagnostic output, or the overriding of + hardware interrupt vectors. + Firstly there is \"Generic\" support which prevents the + HAL from overriding the hardware vectors that it does not + use, to instead allow an installed ROM monitor to handle + them. This is the most basic support which is likely to be + common to most implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included + in the ROM monitor or boot ROM." + } + + cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { + display "Redboot HAL options" + flavor none + no_define + parent CYGPKG_REDBOOT + active_if CYGPKG_REDBOOT + description " + This option lists the target's requirements for a valid + Redboot configuration." + + cdl_option CYGBLD_BUILD_REDBOOT_BIN { + display "Build Redboot ROM binary image" + active_if CYGBLD_BUILD_REDBOOT + requires { !CYGBLD_BUILD_REDBOOT_WITH_EXEC } + default_value 1 + no_define + description " + This option enables the conversion of the Redboot ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + /bin/redboot.bin : /bin/redboot.elf + $(OBJCOPY) --strip-debug $< $(@:.bin=.img) + $(OBJCOPY) -O srec $< $(@:.bin=.srec) + $(OBJCOPY) -O ihex $< $(@:.bin=.hex) + $(OBJCOPY) -O binary $< $@ + } + + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { (CYG_HAL_STARTUP == "RAM") ? "arm_lpc24xx_ea2468_ram" : + "arm_lpc24xx_ea2468_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { (CYG_HAL_STARTUP == "RAM") ? + "" : + "" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { (CYG_HAL_STARTUP == "RAM") ? + "" : + "" } + } + } +} diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/include/hal_platform_setup.h b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/hal_platform_setup.h new file mode 100755 index 00000000..0e773ec0 --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/hal_platform_setup.h @@ -0,0 +1,122 @@ +#ifndef CYGONCE_HAL_PLATFORM_SETUP_H +#define CYGONCE_HAL_PLATFORM_SETUP_H +/*============================================================================= +// +// hal_platform_setup.h +// +// Platform specific support for HAL (assembly code) +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 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: Uwe Kindler +// Date: 2008-06-05 +// Purpose: EA LPC2468 OEM platform specific support routines +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ +#include +#include + + +// +// The minimum initialisation code - we simply setup a valid C stack in +// internal SRAM and do any further initialisation in C code +// +#if defined(CYG_HAL_STARTUP_ROM) +.macro _setup + // + // While setting the stack pointer please note that the + // Flash programming routines use a + // section of the on-chip SRAM. In-System Programming (ISP) uses + // the top 256 bytes and In-Application Programming (IAP) uses the + // top 128 bytes of the on-chip SRAM. The application stack should + // not overlap this area. + // + ldr r2,=0x4000ffff // ram end + sub sp,r2,#0xff + + // + // now map the vector table to internal flash - normally this should be + // the default value after boot - but we go the save way here and force + // the mapping to internal flash (the value for + // CYGARC_HAL_LPC24XX_REG_MEMMAP is 1) + // + ldr r0,=CYGARC_HAL_LPC24XX_REG_SCB_BASE + mov r1,#1 + str r1, [r0,#CYGARC_HAL_LPC24XX_REG_MEMMAP] + + // + // Now its is save to copy the first 64 bytes of flash to RAM + // + mov r0,#0 + mov r1,#0x40000000 + mov r2,#0x40 +1: + ldr r3,[r0,#4]! + str r3,[r1,#4]! + cmps r0,r2 + bne 1b + + // + // Now we can map the vector table to internal SRAM because the SRAM no + // contains a copy of the vector table from flash (the value for + // CYGARC_HAL_LPC24XX_REG_MEMMAP is 2 = SRAM) + // + ldr r0,=CYGARC_HAL_LPC24XX_REG_SCB_BASE + mov r1,#2 // User RAM Mode. Interrupt + // vectors are re-mapped to Static RAM. + str r1, [r0,#CYGARC_HAL_LPC24XX_REG_MEMMAP] + + // + // now we have a valid stack and we can jump into the beautiful + // world of C and do any further initialisation in C code + // + bl hal_plf_startup +.endm +#define CYGSEM_HAL_ROM_RESET_USES_JUMP +#else +.macro _setup +.endm +#endif + +#define PLATFORM_SETUP1 _setup + +//----------------------------------------------------------------------------- +// end of hal_platform_setup.h +#endif // CYGONCE_HAL_PLATFORM_SETUP_H diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_ram.h b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_ram.h new file mode 100755 index 00000000..59ec54e5 --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_ram.h @@ -0,0 +1,21 @@ +#ifndef __ASSEMBLER__ +#include +#include + +#endif + +#define CYGMEM_REGION_sram (0x40000000) +#define CYGMEM_REGION_sram_SIZE (0x00010000) +#define CYGMEM_REGION_sram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) + +#define CYGMEM_REGION_ram (0xA0000000) +#define CYGMEM_REGION_ram_SIZE (0x02000000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) + +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif + +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0xA2000000 - (size_t) CYG_LABEL_NAME (__heap1)) + diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_ram.ldi b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_ram.ldi new file mode 100755 index 00000000..13074de7 --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_ram.ldi @@ -0,0 +1,26 @@ +#include +#include + +MEMORY +{ + sram : ORIGIN = 0x40000000, LENGTH = 0x10000 + ram : ORIGIN = 0xA0000000, LENGTH = 0x2000000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_fixed_vectors (sram, 0x40000400, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0xA0010000, LMA_EQ_VMA) + SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} + diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_rom.h b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_rom.h new file mode 100755 index 00000000..b087b734 --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_rom.h @@ -0,0 +1,28 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_sram (0x40000000) +#define CYGMEM_REGION_sram_SIZE (0x00010000) +#define CYGMEM_REGION_sram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) + +#define CYGMEM_REGION_ram (0xA0000000) +#define CYGMEM_REGION_ram_SIZE (0x02000000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) + +#define CYGMEM_REGION_rom (0x00000000) +#define CYGMEM_REGION_rom_SIZE (0x00080000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) + + +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0xA2000000 - (size_t) CYG_LABEL_NAME (__heap1)) + diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_rom.ldi b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_rom.ldi new file mode 100755 index 00000000..ce376fd7 --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/pkgconf/mlt_arm_lpc24xx_ea2468_rom.ldi @@ -0,0 +1,27 @@ +#include +#include + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 0x80000 + sram : ORIGIN = 0x40000000, LENGTH = 0x10000 + ram : ORIGIN = 0xA0000000, LENGTH = 0x2000000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_rom_vectors (rom, 0x00000000, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (sram, 0x40000400, LMA_EQ_VMA) + SECTION_data (ram, 0xA0000000, FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} + diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/include/plf_io.h b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/plf_io.h new file mode 100755 index 00000000..635ef5a5 --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/include/plf_io.h @@ -0,0 +1,78 @@ +#ifndef CYGONCE_HAL_PLF_IO_H +#define CYGONCE_HAL_PLF_IO_H +//============================================================================= +// +// plf_io.h +// +// Embedded Artists LPC2468 OEM board specific registers +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 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: 2008-07-06 +// Purpose: EA LPC2468 oem board specific registers +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= +// On-chip device base addresses + + +//---------------------------------------------------------------------- +// The platform needs this initialization during the +// hal_hardware_init() function in the varient HAL. +#ifndef __ASSEMBLER__ +extern void hal_plf_hardware_init(void); +#define HAL_PLF_HARDWARE_INIT() \ + hal_plf_hardware_init() + +//----------------------------------------------------------------------------- +// LPX24xx variant specific initialisation of CAN channels +// This function configures the pin functions for CAN use +//----------------------------------------------------------------------------- +#ifdef CYGPKG_DEVS_CAN_LPC2XXX +externC void hal_lpc_can_init(cyg_uint8 can_chan_no); +#define HAL_LPC2XXX_INIT_CAN(_can_chan_no_) hal_lpc_can_init(_can_chan_no_) +#endif // CYGPKG_DEVS_CAN_LPC2XXX + +#endif //__ASSEMBLER__ + +//----------------------------------------------------------------------------- +// end of plf_io.h +#endif // CYGONCE_HAL_PLF_IO_H + diff --git a/packages/hal/arm/lpc24xx/ea2468/v2_0/src/ea2468_misc.c b/packages/hal/arm/lpc24xx/ea2468/v2_0/src/ea2468_misc.c new file mode 100755 index 00000000..bdfbc4cd --- /dev/null +++ b/packages/hal/arm/lpc24xx/ea2468/v2_0/src/ea2468_misc.c @@ -0,0 +1,465 @@ +/*========================================================================== +// +// ea2468_misc.c +// +// HAL misc board support code for EA LPC2468 OEM board +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 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: Uwe Kindler +// Date: 2008-06-15 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include +#include +#include +#include // IO macros + +#include // base types +#include // assertion macros +#include +#include +#include + +#include +#include + +#ifdef CYGPKG_REDBOOT +#include +#endif + + +//=========================================================================== +// DEFINES +//=========================================================================== +#define SCB_BASE CYGARC_HAL_LPC24XX_REG_SCB_BASE +#define EMC_BASE CYGARC_HAL_LPC24XX_REG_EMC_BASE +#define PIN_BASE CYGARC_HAL_LPC24XX_REG_PIN_BASE +#define IO_BASE CYGARC_HAL_LPC24XX_REG_IO_BASE +#define FIO_BASE CYGARC_HAL_LPC24XX_REG_FIO_BASE +#define SDRAM_BASE 0xA0000000 + +extern void cyg_hal_plf_serial_init(void); + + +//=========================================================================== +// Initialize communication channels +//=========================================================================== +void cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + initialized = 1; + + cyg_hal_plf_serial_init(); +} + + +//=========================================================================== +// Finalize hardware initialisation of platform +//=========================================================================== +void hal_plf_hardware_init(void) +{ + +} + + +//=========================================================================== +// hal_gpio_init +//=========================================================================== +void hal_gpio_init(void) +{ + // + // Enable UART0 pins + // + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL0, 0x00000050); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL1, 0); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL2, 0); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL3, 0); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL4, 0); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL5, 0); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL6, 0); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL7, 0x30003fff); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL8, 0); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL9, 0); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL10,0); + + HAL_WRITE_UINT32(IO_BASE + CYGARC_HAL_LPC24XX_REG_IO0DIR, 0); + HAL_WRITE_UINT32(IO_BASE + CYGARC_HAL_LPC24XX_REG_IO1DIR, 0); + HAL_WRITE_UINT32(IO_BASE + CYGARC_HAL_LPC24XX_REG_IO0SET, 0xffffffff); + HAL_WRITE_UINT32(IO_BASE + CYGARC_HAL_LPC24XX_REG_IO1SET, 0xffffffff); + + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO0DIR, 0); + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO1DIR, 0); + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO2DIR, 0); + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO3DIR, 0); + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO4DIR, 0); + + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO0SET, 0xffffffff); + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO1SET, 0xffffffff); + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO2SET, 0xffffffff); + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO3SET, 0xffffffff); + HAL_WRITE_UINT32(FIO_BASE + CYGARC_HAL_LPC24XX_REG_FIO4SET, 0xffffffff); +} + + +//=========================================================================== +// hal_pll_init - initialize pll and all clocks +//=========================================================================== +void hal_pll_init(void) +{ + cyg_uint32 regval; + + HAL_READ_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLSTAT, regval); + if (regval & CYGARC_HAL_LPC24XX_REG_PLLSTAT_PLLC) + { + // + // Enable PLL, disconnected + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLCON, + CYGARC_HAL_LPC24XX_REG_PLLCON_PLLE); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0xaa); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0x55); + } + + // + // Disable PLL, disconnected + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLCON, 0x00); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0xaa); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0x55); + + // + // Enables main oscillator and wait until it is usable + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_SCS, + CYGARC_HAL_LPC24XX_REG_SCS_OSCEN); + do + { + HAL_READ_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_SCS, regval); + } while (!(regval & CYGARC_HAL_LPC24XX_REG_SCS_OSCSTAT)); + + // + // select main OSC, 12MHz, as the PLL clock source + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_CLKSRCSEL, + CYGARC_HAL_LPC24XX_REG_CLKSRCSEL_MAIN); + + // + // Configure PLL multiplier and pre divider according to + // configuration values + // + regval = ((CYGNUM_HAL_ARM_LPC24XX_PLL_MUL - 1) | + (CYGNUM_HAL_ARM_LPC24XX_PLL_DIV - 1) << 16); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLCFG, regval); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0xaa); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0x55); + + // + // Enable PLL, disconnected + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLCON, + CYGARC_HAL_LPC24XX_REG_PLLCON_PLLE); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0xaa); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0x55); + + // + // Set CPU clock divider + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_CCLKCFG, + CYGNUM_HAL_ARM_LPC24XX_CPU_CLK_DIV - 1); + + // + // Set USB clock divider + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_CCLKCFG, + CYGNUM_HAL_ARM_LPC24XX_USB_CLK_DIV - 1); + + // + // Check lock bit status + // + do + { + HAL_READ_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLSTAT, regval); + } while(!(regval & CYGARC_HAL_LPC24XX_REG_PLLSTAT_PLOCK)); + + // + // Enable PLL and connect + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLCON, + CYGARC_HAL_LPC24XX_REG_PLLCON_PLLE | + CYGARC_HAL_LPC24XX_REG_PLLCON_PLLC); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0xaa); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLFEED, 0x55); + + // + // Check connect bit status + // + do + { + HAL_READ_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PLLSTAT, regval); + } while(!(regval & CYGARC_HAL_LPC24XX_REG_PLLSTAT_PLLC)); + + // + // entry for JTAG debugger- enable this while loop as a stop for + // the JTAG debugger - the JTAG debugger only works after the PLL is + // initialized properly + // + /*while (1) + { + }*/ +} + + +//=========================================================================== +// hal_mem_init - initialize external memory interface +//=========================================================================== +void hal_mem_init(void) +{ + volatile unsigned int i; + volatile unsigned int dummy; + volatile cyg_uint32 regval; + + // + // Enable external memory interface + // + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMC_CTRL, + CYGARC_HAL_LPC24XX_REG_EMC_CTRL_EN); + HAL_READ_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCONP, regval); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCONP, + regval | CYGARC_HAL_LPC24XX_REG_PCONP_EMC); + + // + // Setup pin functions + // + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL4, 0x50000000); +#if defined(CYGHWR_HAL_ARM_LPC24XX_EA2468_DATA_BUS_WIDTH_32) + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL5, 0x55010115); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL7, 0x55555555); +#else + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL5, 0x05050555); +#endif + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL6, 0x55555555); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL8, 0x55555555); + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL9, 0x50555555); + +#if defined(CYGHWR_HAL_ARM_LPC24XX_EA2468_DATA_BUS_WIDTH_32) + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RP, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RAS, 3); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_SREX, 5); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_APR, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_DAL, 5); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_WR, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RC, 5); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RFC, 5); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_XSR, 5); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RRD, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_MRD, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RDCFG, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RASCAS0, + 0x00000202); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_CONFIG0, + 0x00005480); +#else + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RP, 2); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RAS, 3); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_SREX, 7); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_APR, 2); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_DAL, 5); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_WR, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RC, 5); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RFC, 5); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_XSR, 7); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RRD, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_MRD, 2); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RDCFG, 1); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_RASCAS0, + 0x00000303); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_CONFIG0, + 0x00000680); +#endif + + // + // Wait 100 ms and then send command: NOP + // + HAL_DELAY_US(100000); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_CONTROL, + 0x00000183); + + // + // wait 200 ms and then send command: PRECHARGE-ALL, shortest + // possible refresh period + // + HAL_DELAY_US(200000); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_CONTROL, + 0x00000103); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_REFRESH, + 0x00000002); + + // + // wait 128 ABH clock cycles + // + for(i = 0; i < 64; i++) + { + asm volatile(" nop"); + } + + // + // Set correct refresh period and the send command MODE + // + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_REFRESH, 28); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_CONTROL, + 0x00000083); + + // + // Set mode register in SDRAM + // +#if defined(CYGHWR_HAL_ARM_LPC24XX_EA2468_DATA_BUS_WIDTH_32) + dummy = *((volatile unsigned int*)(SDRAM_BASE | (0x22 << 11))); +#else + dummy = *((volatile unsigned int*)(SDRAM_BASE | (0x33 << 12))); +#endif + + // + //Send command: NORMAL, enable buffer and wait for 1 second + // + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_CONTROL, + 0x00000000); + HAL_READ_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_CONFIG0, regval); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCD_CONFIG0, + regval | 0x00080000); + HAL_DELAY_US(1000); + + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITW_EN0, 0x2); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITO_EN0, 0x2); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITRD0, 0x1f); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITPAGE0, 0x1f); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITWR0, 0x1f); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITTURN0, 0xf); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_CONFIG0, + 0x00000081); + + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITW_EN1, 0x2); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITO_EN1, 0x2); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITRD1, 0x8); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITPAGE1, 0x1f); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITWR1, 0x8); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_WAITTURN1, 0xf); + HAL_WRITE_UINT32(EMC_BASE + CYGARC_HAL_LPC24XX_REG_EMCS_CONFIG1, + 0x00000080); +} + + +//=========================================================================== +// hal_plf_startup +//=========================================================================== +void hal_plf_startup(void) +{ + hal_pll_init(); + + // + // Set clock speed of all peripherals to reset value (CPU speed / 4) + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCLKSEL0, 0x00000000); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCLKSEL1, 0x00000000); + + // + // Setup memory acceleration module + // + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_MAMCR, 0); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_MAMTIM, 4); + + hal_gpio_init(); + HAL_DELAY_US(20000); + hal_mem_init(); +} + + +//=========================================================================== +// hal_lpc2xxx_set_leds +//=========================================================================== +void hal_lpc24xx_set_leds (int mask) +{ + // + // implement function for setting diagnostic leds + // +} + + +#ifdef CYGPKG_DEVS_CAN_LPC2XXX +//=========================================================================== +// Configure CAN pins +//=========================================================================== +void hal_lpc_can_init(cyg_uint8 can_chan_no) +{ + CYG_ASSERT(can_chan_no < 2, "CAN channel number out of bounds"); + + cyg_uint32 pinsel0_val; + cyg_uint32 pconp_val; + HAL_READ_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL0, pinsel0_val); + HAL_READ_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCONP, pconp_val); + switch (can_chan_no) + { + case 0: + CYGARC_HAL_LPC24XX_SET_PIN_FUN(pinsel0_val, 0, 1); + CYGARC_HAL_LPC24XX_SET_PIN_FUN(pinsel0_val, 1, 1); + pconp_val |= CYGARC_HAL_LPC24XX_REG_PCONP_CAN1; + break; + + case 1: + CYGARC_HAL_LPC24XX_SET_PIN_FUN(pinsel0_val, 4, 2); + CYGARC_HAL_LPC24XX_SET_PIN_FUN(pinsel0_val, 5, 2); + pconp_val |= CYGARC_HAL_LPC24XX_REG_PCONP_CAN2; + break; + } + HAL_WRITE_UINT32(PIN_BASE + CYGARC_HAL_LPC24XX_REG_PINSEL0, pinsel0_val); + HAL_WRITE_UINT32(SCB_BASE + CYGARC_HAL_LPC24XX_REG_PCONP, pconp_val); +} +#endif // #ifdef CYGPKG_DEVS_CAN_LPC2XXX + +//-------------------------------------------------------------------------- +// EOF ea2468_misc.c diff --git a/packages/hal/arm/lpc24xx/var/v2_0/ChangeLog b/packages/hal/arm/lpc24xx/var/v2_0/ChangeLog new file mode 100755 index 00000000..7e2d817c --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/ChangeLog @@ -0,0 +1,60 @@ +2008-07-21 Uwe Kindler + + * src/lpc2xxx_misc.c: Added hal_lpc_can_init() to initialize CAN + channels + * cdl/hal_arm_lpc24xx.cdl: Added a number of CYGHWR_HAL_ARM_LPC2XXX_xxx + options for device driver compatibility reasons. Some LPC2xxx device + drivers rely on these definitions. Moved some configuration options + to make configuration more intuitive in configuration tool. Added + CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK option for configuration of CAN + peripheral clock. + * include/var_io.h: Added macro CYGARC_HAL_LPC24XX_SET_PIN_FUN() + * src/lpc2xxx_misc.c: Added function hal_lpc_set_pclk() to set + peripheral clocks easily. Initialize peripheral clocks in + hal_hardware_init() according to configuration. + +2008-07-06 Uwe Kindler + + * Initial release of LPC24xx variant support (based on LPX2xxx variant) + * src/hal_diag.c: + * src/lpc2xxx_misc.c: + * include/plf_stub.h: + * include/var_io.h: + * include/var_arch.h: + * include/hal_var_ints.h: + * include/hal_diag.h: + * include/hal_cache.h: + * cdl/hal_arm_lpc24xx.cdl: New port - based on LPX2xxx variant. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2004 eCosCentric Limited +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/arm/lpc24xx/var/v2_0/cdl/hal_arm_lpc24xx.cdl b/packages/hal/arm/lpc24xx/var/v2_0/cdl/hal_arm_lpc24xx.cdl new file mode 100755 index 00000000..297027f0 --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/cdl/hal_arm_lpc24xx.cdl @@ -0,0 +1,326 @@ +# ==================================================================== +# +# hal_arm_lpc24xx.cdl +# +# NXP LPC24XX HAL package configuration data +# +# ==================================================================== +#####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 Nick Garnett +## Copyright (C) 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: gthomas, tkoeller, tdrury, nickg +# Date: 2008-07-05 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_LPC24XX { + display "NXP LPC24XX variant HAL" + parent CYGPKG_HAL_ARM + define_header hal_arm_lpc24xx.h + include_dir cyg/hal + hardware + description " + The LPC24XX HAL package provides the support needed to run + eCos on NXP LPC24XX based targets." + + compile hal_diag.c lpc24xx_misc.c + + implements CYGINT_HAL_DEBUG_GDB_STUBS + implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + implements CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT + implements CYGINT_HAL_ARM_ARCH_ARM7 + implements CYGINT_HAL_ARM_THUMB_ARCH + + # Let the architectural HAL see this variant's files + define_proc { + puts $::cdl_header "#define CYGBLD_HAL_VAR_INTS_H " + puts $::cdl_system_header "#define CYGBLD_HAL_ARM_VAR_IO_H" + puts $::cdl_system_header "#define CYGBLD_HAL_ARM_VAR_ARCH_H" + } + + cdl_component CYGHWR_HAL_ARM_LPC24XX { + display "LPC24XX variant used" + flavor data + default_value { "LPC246x" } + legal_values { "LPC246x" "LPC2458" "LPC2460" "LPC2468" "LPC2470" + "LPC2478"} + description " + The LPC24XX microcontroller family has several variants, + the main differences being the amount of on-chip RAM, + flash and peripherals. This option allows the platform + HALs to select the specific microcontroller being used." + + cdl_option CYGHWR_HAL_ARM_LPC24XX_FAMILY { + display "LPC24XX variant family" + flavor data + calculated { + is_substr(CYGHWR_HAL_ARM_LPC24XX, "LPC246") ? + "LPC246X" : "LPC24XX" + } + description " + This specifies the family that the processor + belongs to. This is useful as it defines certain common + characteristics which affect which features should be + available in the HAL." + } + } + + # This is going to get really messy before long as the number of parts + # explodes. Its useful to know the actual part in use, but its just as + # useful to know which family it belongs to. LPC210x shouldn't really + # be in the list of devices, but will probably break something if removed. + cdl_component CYGHWR_HAL_ARM_LPC2XXX { + display "LPC2XXX variant used" + flavor data + calculated CYGHWR_HAL_ARM_LPC24XX + description " + This option is only here for compatibility reasons because some of + the LPC2XXX device drivers rely on these definitions. If this + is defined here, the LPC24XX variant can use the LPC2XXX device + drivers for on-chip peripherals." + + cdl_option CYGHWR_HAL_ARM_LPC2XXX_FAMILY { + display "LPC2XXX variant family" + flavor data + calculated CYGHWR_HAL_ARM_LPC24XX_FAMILY + description " + This option is only here for compatibility reasons + because some of the LPC2XXX device drivers rely on + these definitions. If this is defined here, the + LPC24XX variant can use the LPC2XXX device drivers + for on-chip peripherals." + } + + cdl_option CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION { + display "LPC2XXX variant version" + flavor data + calculated { + is_substr(CYGHWR_HAL_ARM_LPC2XXX, "LPC21") ? 1 : + is_substr(CYGHWR_HAL_ARM_LPC2XXX, "LPC22") ? 2 : + is_substr(CYGHWR_HAL_ARM_LPC2XXX, "LPC24") ? 4 : 0 + } + description " + This specifies the variant version that the processor + belongs to. Some common characteristics may be + different in newer LPC2xxx versions. I.e. the LPC24xx variants + are significant different from former LPC2xxx variants." + } + } + + # Important! Be very careful changing this value. That will always + # enter the LPC24XX bootloader after reset and consequently will + # never run your code. You must know what you are doing. Look at + # arch. vectors.S for details. + cdl_option CYGNUM_HAL_ARM_VECTOR_0x14 { + display "ARM vector at 0x14" + flavor data + default_value 0xB4405F62 + legal_values 0 to 0xFFFFFFFF + description " + In order to detect if a valid program is present, every + user program must have a program signature. This signature + is a word-wide number that is stored in the unused + location in the ARM7 vector table at 0x00000014. The + program signature is the two's compliment of the checksum + of the ARM vector table." + } + + cdl_component CYGNUM_HAL_ARM_LPC24XX_CLOCKING { + display "Clocking" + flavor none + + cdl_option CYGNUM_HAL_ARM_LPC24XX_PLL_MUL { + display "PLL multiplier" + flavor data + legal_values 6 to 32767 + default_value { 12 } + } + + cdl_option CYGNUM_HAL_ARM_LPC24XX_PLL_DIV { + display "PLL divider" + flavor data + legal_values 1 to 32 + default_value { 1 } + } + + cdl_option CYGNUM_HAL_ARM_LPC24XX_PLL_OUTPUT { + display "PLL output (MHz)" + flavor data + legal_values 275000000 to 290000000 + calculated { 2 * CYGNUM_HAL_ARM_LPC24XX_PLL_MUL * + CYGNUM_HAL_ARM_LPC24XX_XTAL_FREQ / + CYGNUM_HAL_ARM_LPC24XX_PLL_DIV} + description " + Normally the PLL output must be in the range of 275 MHz to + 550 MHz Because of a chip errata the maximum output of the CCO + within the PLL block is limited to 290 MHz." + } + + cdl_component CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED { + display "CPU clock speed" + flavor data + calculated { 2 * CYGNUM_HAL_ARM_LPC24XX_PLL_MUL * + CYGNUM_HAL_ARM_LPC24XX_XTAL_FREQ / + CYGNUM_HAL_ARM_LPC24XX_PLL_DIV / + CYGNUM_HAL_ARM_LPC24XX_CPU_CLK_DIV} + description " + The core CPU clock speed is the PLL output divided by the + CPU clock divider" + + cdl_option CYGNUM_HAL_ARM_LPC24XX_CPU_CLK_DIV { + display "CPU clock divider" + flavor data + legal_values 6 to 256 + default_value { 6 } + description " + The CPU clock divider controls the division of the PLL + output before it is used by the CPU. When the PLL is + bypassed, the division may be by 1. When the PLL is + running, the output must be divided in order to bring the + CPU clock frequency (CCLK) within operating limits. An 8 + bit divider allows a range of options, including slowing + CPU operation to a low rate for temporary power savings + without turning off the PLL. Only even values + (2, 4, 6, ..., 256) are supported and can be used. + Warning: Using an odd value (1, 3, 5, ..., 255) when + setting this option may result in incorrect operation of + the device." + } + } + + + cdl_component CYGNUM_HAL_ARM_LPC24XX_USB_CLOCK_SPEED { + display "USB clock speed" + flavor data + calculated { 2 * CYGNUM_HAL_ARM_LPC24XX_PLL_MUL * + CYGNUM_HAL_ARM_LPC24XX_XTAL_FREQ / + CYGNUM_HAL_ARM_LPC24XX_PLL_DIV / + CYGNUM_HAL_ARM_LPC24XX_USB_CLK_DIV} + description " + The USB clock speed is the PLL output divided by the + USB clock divider" + + cdl_option CYGNUM_HAL_ARM_LPC24XX_USB_CLK_DIV { + display "USB clock divider" + flavor data + legal_values 1 to 8 + default_value { 6 } + description " + This divider controls the division of the PLL output before + it is used by the USB block. If the PLL is bypassed, the + division may be by 1. In that case, the PLL input frequency + must be 48 MHz, with a 500 ppm tolerance. When the PLL is + running, the output must be divided in order to bring the + USB clock frequency to 48 MHz with a 50% duty cycle. A + 4-bit divider allows obtaining the correct USB clock from + any even multiple of 48 MHz (i.e. any mutliple of 96 MHz) + within the PLL operating range." + } + } + + cdl_component CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK { + display "CAN clock speed" + flavor data + calculated { CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / + CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV} + description " + The CAN clock speed is the CPU clock output divided by the + CAN clock divider" + + cdl_option CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV { + display "CAN clock divider" + flavor data + legal_values { 1 2 4 6 } + default_value { 1 } + description " + This divider selects the peripheral clock for both CAN + channels. The divider divides the CPU clock to get the + clock for the CAN peripherals." + } + } + } + + cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants" + flavor none + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + default_value 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + default_value 100 + } + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + default_value { ((CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED) / + CYGNUM_HAL_RTC_DENOMINATOR) } + } + } + + cdl_option CYGHWR_HAL_ARM_LPC24XX_IDLE_PWRSAVE { + display "Stop clock in idle loop to save power" + flavor bool + default_value { is_active(CYGPKG_REDBOOT) ? 0 : 1 } + description " + Select this option when it is desired to save power by + stopping the processor clock in the idle loop. This is + controlled by the PCON register. Generally this is a good + thing, but it may be necessary to disable this when + debugging via JTAG, as stopping the clock can prevent the + debugger getting control of the system." + } + + cdl_option CYGNUM_HAL_KERNEL_COUNTERS_CLOCK_ISR_DEFAULT_PRIORITY { + display "Default priority for system clock interrupts" + flavor data + legal_values { 0 to 15 } + default_value 15 + description " + There are 16 priority levels, corresponding to the values 0 through + 15 decimal, of which 15 is the lowest priority. The reset value of + these interrupt priority registers defaults all interrupts to the + lowest priority, allowing a single write to elevate the priority + of an individual interrupt." + } + +} diff --git a/packages/hal/arm/lpc24xx/var/v2_0/include/hal_cache.h b/packages/hal/arm/lpc24xx/var/v2_0/include/hal_cache.h new file mode 100755 index 00000000..4d341616 --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/include/hal_cache.h @@ -0,0 +1,108 @@ +#ifndef CYGONCE_HAL_CACHE_H +#define CYGONCE_HAL_CACHE_H + +//============================================================================= +// +// hal_cache.h +// +// HAL cache control API +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 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): jani +// Contributors: +// Date: 2004-09-08 +// Purpose: Cache control API +// Description: The macros defined here provide the HAL APIs for handling +// cache control operations. +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +//----------------------------------------------------------------------------- +// Global control of data cache + +// Enable the data cache +#define HAL_DCACHE_ENABLE() + +// Disable the data cache +#define HAL_DCACHE_DISABLE() + +// Invalidate the entire cache +#define HAL_DCACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_DCACHE_SYNC() + +// Purge contents of data cache +#define HAL_DCACHE_PURGE_ALL() + +// Query the state of the data cache (does not affect the caching) +#define HAL_DCACHE_IS_ENABLED(_state_) \ + CYG_MACRO_START \ + (_state_) = 0; \ + CYG_MACRO_END + +//----------------------------------------------------------------------------- +// Global control of Instruction cache + +// Enable the instruction cache +#define HAL_ICACHE_ENABLE() + +// Disable the instruction cache +#define HAL_ICACHE_DISABLE() + +// Invalidate the entire cache +#define HAL_ICACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_ICACHE_SYNC() + +// Query the state of the instruction cache (does not affect the caching) +#define HAL_ICACHE_IS_ENABLED(_state_) \ + CYG_MACRO_START \ + (_state_) = 0; \ + CYG_MACRO_END + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_CACHE_H +// End of hal_cache.h diff --git a/packages/hal/arm/lpc24xx/var/v2_0/include/hal_diag.h b/packages/hal/arm/lpc24xx/var/v2_0/include/hal_diag.h new file mode 100755 index 00000000..cd33054a --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/include/hal_diag.h @@ -0,0 +1,77 @@ +#ifndef CYGONCE_HAL_DIAG_H +#define CYGONCE_HAL_DIAG_H +//============================================================================= +// +// hal_diag.h +// +// HAL Support for Kernel Diagnostic Routines +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 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): jskov +// Contributors:jskov, gthomas, tkoeller +// Date: 2001-07-12 +// Purpose: HAL Support for Kernel Diagnostic Routines +// Description: Diagnostic routines for use during kernel development. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +#include + +#include + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + +//----------------------------------------------------------------------------- +// LED +externC void hal_diag_led(int mask); +externC void hal_lpc24xx_set_leds(int mask); + +//----------------------------------------------------------------------------- +// delay + +externC void hal_delay_us(cyg_int32 usecs); +#define HAL_DELAY_US(n) hal_delay_us(n); + +//----------------------------------------------------------------------------- +// end of hal_diag.h +#endif // CYGONCE_HAL_DIAG_H diff --git a/packages/hal/arm/lpc24xx/var/v2_0/include/hal_var_ints.h b/packages/hal/arm/lpc24xx/var/v2_0/include/hal_var_ints.h new file mode 100755 index 00000000..b9ded611 --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/include/hal_var_ints.h @@ -0,0 +1,116 @@ +#ifndef CYGONCE_HAL_VAR_INTS_H +#define CYGONCE_HAL_VAR_INTS_H +//========================================================================== +// +// hal_var_ints.h +// +// HAL Interrupt and clock support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 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: 2008-07-05 +// Purpose: Define Interrupt support +// Description: The interrupt details for the LPC24XX are defined here. +// Usage: +// #include +// #include CYGBLD_HAL_VARIANT_H +// #include CYGBLD_HAL_VAR_INTS_H +// +// ... +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#define CYGNUM_HAL_INTERRUPT_WD 0 +#define CYGNUM_HAL_INTERRUPT_SOFT 1 +#define CYGNUM_HAL_INTERRUPT_DCC_RX 2 +#define CYGNUM_HAL_INTERRUPT_DCC_TX 3 +#define CYGNUM_HAL_INTERRUPT_TIMER0 4 +#define CYGNUM_HAL_INTERRUPT_TIMER1 5 +#define CYGNUM_HAL_INTERRUPT_UART0 6 +#define CYGNUM_HAL_INTERRUPT_UART1 7 +#define CYGNUM_HAL_INTERRUPT_PWM0 8 +#define CYGNUM_HAL_INTERRUPT_I2C 9 +#define CYGNUM_HAL_INTERRUPT_SPI0 10 +#define CYGNUM_HAL_INTERRUPT_SPI1 11 +#define CYGNUM_HAL_INTERRUPT_PLL 12 +#define CYGNUM_HAL_INTERRUPT_RTCDEV 13 // actual RTC device not the + // eCos 'real time clock' + // interrupt. The latter is on + // TIMER0. +#define CYGNUM_HAL_INTERRUPT_EINT0 14 +#define CYGNUM_HAL_INTERRUPT_EINT1 15 +#define CYGNUM_HAL_INTERRUPT_EINT2 16 +#define CYGNUM_HAL_INTERRUPT_EINT3 17 +#define CYGNUM_HAL_INTERRUPT_AD 18 +#define CYGNUM_HAL_INTERRUPT_I2C1 19 +#define CYGNUM_HAL_INTERRUPT_BOD 20 +#define CYGNUM_HAL_INTERRUPT_ETH 21 +#define CYGNUM_HAL_INTERRUPT_USB 22 +#define CYGNUM_HAL_INTERRUPT_CAN 23 +#define CYGNUM_HAL_INTERRUPT_SD_MMC 24 +#define CYGNUM_HAL_INTERRUPT_DMA 25 +#define CYGNUM_HAL_INTERRUPT_TIMER2 26 +#define CYGNUM_HAL_INTERRUPT_TIMER3 27 +#define CYGNUM_HAL_INTERRUPT_UART2 28 +#define CYGNUM_HAL_INTERRUPT_UART3 29 +#define CYGNUM_HAL_INTERRUPT_I2C2 30 +#define CYGNUM_HAL_INTERRUPT_I2S 31 + + +#define CYGNUM_HAL_ISR_MIN 0 +#define CYGNUM_HAL_ISR_MAX (31) + +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_ISR_MAX+1) + +/* use non-vectored interrupts in kernel tests intr0/kintr0 */ +#define HAL_INTR_TEST_PRIO_A 16 +#define HAL_INTR_TEST_PRIO_B 16 +#define HAL_INTR_TEST_PRIO_C 16 + +//The vector used by the Real time clock +#define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_TIMER0 + +// Other entries here moved to variant specific include file +// This is included here to avoid breaking anything +#include + +//--------------------------------------------------------------------------- +#endif // CYGONCE_HAL_VAR_INTS_H diff --git a/packages/hal/arm/lpc24xx/var/v2_0/include/lpc24xx_misc.h b/packages/hal/arm/lpc24xx/var/v2_0/include/lpc24xx_misc.h new file mode 100755 index 00000000..ebd3f200 --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/include/lpc24xx_misc.h @@ -0,0 +1,117 @@ +#ifndef CYGONCE_HAL_ARM_LPC24XX_VAR_LPC24XX_MISC_H +#define CYGONCE_HAL_ARM_LPC24XX_VAR_LPC24XX_MISC_H +//============================================================================= +// +// lpc24xx_misc.h +// +// HAL misc variant support code for NCP LPC24xx header file +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 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): andyj +// Contributors: jani +// Date: 2006-02-04 +// Purpose: LPC2XXX specific miscellaneous support header file +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +//----------------------------------------------------------------------------- +// Functions to obtain the current processor clock settings +//----------------------------------------------------------------------------- +externC cyg_uint32 hal_lpc_get_pclk(cyg_uint32 peripheral_id); + +// +// Identifiers for peripheral clock. Use these identifiers with the function +// hal_get_pclk() +// +#define CYNUM_HAL_LPC24XX_PCLK_WDT 0 +#define CYNUM_HAL_LPC24XX_PCLK_TIMER0 1 +#define CYNUM_HAL_LPC24XX_PCLK_TIMER1 2 +#define CYNUM_HAL_LPC24XX_PCLK_UART0 3 +#define CYNUM_HAL_LPC24XX_PCLK_UART1 4 +#define CYNUM_HAL_LPC24XX_PCLK_PWM0 5 +#define CYNUM_HAL_LPC24XX_PCLK_PWM1 6 +#define CYNUM_HAL_LPC24XX_PCLK_I2C0 7 +#define CYNUM_HAL_LPC24XX_PCLK_SPI 8 +#define CYNUM_HAL_LPC24XX_PCLK_RTC 9 +#define CYNUM_HAL_LPC24XX_PCLK_SSP1 10 +#define CYNUM_HAL_LPC24XX_PCLK_DAC 11 +#define CYNUM_HAL_LPC24XX_PCLK_ADC 12 +#define CYNUM_HAL_LPC24XX_PCLK_CAN1 13 +#define CYNUM_HAL_LPC24XX_PCLK_CAN2 14 +#define CYNUM_HAL_LPC24XX_PCLK_ACF 15 +#define CYNUM_HAL_LPC24XX_PCLK_BATRAM 16 +#define CYNUM_HAL_LPC24XX_PCLK_GPIO 17 +#define CYNUM_HAL_LPC24XX_PCLK_PCB 18 +#define CYNUM_HAL_LPC24XX_PCLK_I2C1 19 +#define CYNUM_HAL_LPC24XX_PCLK_SSP0 21 +#define CYNUM_HAL_LPC24XX_PCLK_TIMER2 22 +#define CYNUM_HAL_LPC24XX_PCLK_TIMER3 23 +#define CYNUM_HAL_LPC24XX_PCLK_UART2 24 +#define CYNUM_HAL_LPC24XX_PCLK_UART3 25 +#define CYNUM_HAL_LPC24XX_PCLK_I2C2 26 +#define CYNUM_HAL_LPC24XX_PCLK_I2S 27 +#define CYNUM_HAL_LPC24XX_PCLK_MCI 28 +#define CYNUM_HAL_LPC24XX_PCLK_SYSCON 30 + + +//----------------------------------------------------------------------------- +// Macros to derive the baudrate divider values for the internal UARTs +// The LPC24xx family supports differents baudrate clocks for each single +// UART. So we need a way to calculate the baudrate for each single UART +// Now we rely on the fact that we use the same baurate clock for all +// UARTs and we query only UART0 +//----------------------------------------------------------------------------- +#define CYG_HAL_ARM_LPC24XX_PCLK(_pclkid_) hal_lpc_get_pclk(_pclkid_) +#define CYG_HAL_ARM_LPC2XXX_BAUD_GENERATOR(baud) \ + (CYG_HAL_ARM_LPC24XX_PCLK(CYNUM_HAL_LPC24XX_PCLK_UART0)/((baud)*16)) +#define CYG_HAL_ARM_LPC24XX_BAUD_GENERATOR(_pclkid_, baud) \ + (CYG_HAL_ARM_LPC24XX_PCLK(_pclkid_)/((baud)*16)) + + +//----------------------------------------------------------------------------- +// LPX24xx platform reset (watchdog resets the board) +//----------------------------------------------------------------------------- +externC void hal_lpc_watchdog_reset(void); + +#define HAL_PLATFORM_RESET() hal_lpc_watchdog_reset() +#define HAL_PLATFORM_RESET_ENTRY 0 + +//----------------------------------------------------------------------------- +// end of lpc24xx_misc.h +#endif // CYGONCE_HAL_ARM_LPC24XX_VAR_LPC24XX_MISC_H diff --git a/packages/hal/arm/lpc24xx/var/v2_0/include/plf_stub.h b/packages/hal/arm/lpc24xx/var/v2_0/include/plf_stub.h new file mode 100755 index 00000000..328d6f33 --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/include/plf_stub.h @@ -0,0 +1,84 @@ +#ifndef CYGONCE_HAL_PLF_STUB_H +#define CYGONCE_HAL_PLF_STUB_H + +//============================================================================= +// +// plf_stub.h +// +// Platform header for GDB stub support. +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 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): jani +// Contributors:jskov, gthomas +// Date: 2004-10-5 +// Purpose: Platform HAL stub support for LPC2XXX based boards. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include CYGBLD_HAL_PLATFORM_H + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include // CYG_UNUSED_PARAM + +#include // architecture stub support + +//---------------------------------------------------------------------------- +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. + +externC void cyg_hal_plf_comms_init(void); + +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() + +#define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) +#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 +#define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT + +//---------------------------------------------------------------------------- +// Stub initializer. +#define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_PLF_STUB_H +// End of plf_stub.h diff --git a/packages/hal/arm/lpc24xx/var/v2_0/include/var_arch.h b/packages/hal/arm/lpc24xx/var/v2_0/include/var_arch.h new file mode 100755 index 00000000..efd02ef7 --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/include/var_arch.h @@ -0,0 +1,79 @@ +#ifndef CYGONCE_HAL_VAR_ARCH_H +#define CYGONCE_HAL_VAR_ARCH_H +//============================================================================= +// +// var_arch.h +// +// LPC24XX variant architecture overrides +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Jonathan Larmour +// Copyright (C) 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: jlarmour,Daniel Neri +// Date: 2008-07-06 +// Purpose: LPC24XX variant architecture overrides +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +//-------------------------------------------------------------------------- +// Idle thread code. +// This macro is called in the idle thread loop, and gives the HAL the +// chance to insert code. Typical idle thread behaviour might be to halt the +// processor. These implementations halt the system core clock. + +#ifdef CYGHWR_HAL_ARM_LPC24XX_IDLE_PWRSAVE +#ifndef HAL_IDLE_THREAD_ACTION + +#define HAL_IDLE_THREAD_ACTION(_count_) \ +CYG_MACRO_START \ +HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + \ + CYGARC_HAL_LPC24XX_REG_PCON, \ + CYGARC_HAL_LPC24XX_REG_PCON_IDL); \ +CYG_MACRO_END + +#endif // HAL_IDLE_THREAD_ACTION +#endif // CYGHWR_HAL_ARM_LPC24XX_IDLE_MODE + +//----------------------------------------------------------------------------- +// end of var_arch.h +#endif // CYGONCE_HAL_VAR_ARCH_H diff --git a/packages/hal/arm/lpc24xx/var/v2_0/include/var_io.h b/packages/hal/arm/lpc24xx/var/v2_0/include/var_io.h new file mode 100755 index 00000000..6654ba39 --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/include/var_io.h @@ -0,0 +1,840 @@ +#ifndef CYGONCE_HAL_VAR_IO_H +#define CYGONCE_HAL_VAR_IO_H +//============================================================================= +// +// var_io.h +// +// Variant specific registers +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 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: 2008-07-05 +// Purpose: NXP LPC24xx variant specific registers +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include // variant chip model selection. +#include + +//============================================================================= +// Watchdog (WD) +#define CYGARC_HAL_LPC24XX_REG_WD_BASE 0xE0000000 + +// Registers are offsets from base of this subsystem +#define CYGARC_HAL_LPC24XX_REG_WDMOD 0x0000 +#define CYGARC_HAL_LPC24XX_REG_WDMOD_WDEN (1<<0) +#define CYGARC_HAL_LPC24XX_REG_WDMOD_WDRESET (1<<1) +#define CYGARC_HAL_LPC24XX_REG_WDMOD_WDTOF (1<<2) +#define CYGARC_HAL_LPC24XX_REG_WDMOD_WDINT (1<<3) +#define CYGARC_HAL_LPC24XX_REG_WDTC 0x0004 +#define CYGARC_HAL_LPC24XX_REG_WDFEED 0x0008 +#define CYGARC_HAL_LPC24XX_REG_WDFEED_MAGIC1 0xAA +#define CYGARC_HAL_LPC24XX_REG_WDFEED_MAGIC2 0x55 +#define CYGARC_HAL_LPC24XX_REG_WDTV 0x000C + + +//============================================================================= +// Timers (Tx) + +#define CYGARC_HAL_LPC24XX_REG_TIMER0_BASE 0xE0004000 +#define CYGARC_HAL_LPC24XX_REG_TIMER1_BASE 0xE0008000 +#define CYGARC_HAL_LPC24XX_REG_TIMER2_BASE 0xE0070000 +#define CYGARC_HAL_LPC24XX_REG_TIMER3_BASE 0xE0074000 + +// Registers are offsets from base for each timer +#define CYGARC_HAL_LPC24XX_REG_TxIR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_TxIR_MR0 (1<<0) +#define CYGARC_HAL_LPC24XX_REG_TxIR_MR1 (1<<1) +#define CYGARC_HAL_LPC24XX_REG_TxIR_MR2 (1<<2) +#define CYGARC_HAL_LPC24XX_REG_TxIR_MR3 (1<<3) +#define CYGARC_HAL_LPC24XX_REG_TxIR_CR0 (1<<4) +#define CYGARC_HAL_LPC24XX_REG_TxIR_CR1 (1<<5) +#define CYGARC_HAL_LPC24XX_REG_TxIR_CR2 (1<<6) +#define CYGARC_HAL_LPC24XX_REG_TxIR_CR3 (1<<7) +#define CYGARC_HAL_LPC24XX_REG_TxTCR 0x0004 +#define CYGARC_HAL_LPC24XX_REG_TxTCR_CTR_ENABLE (1<<0) +#define CYGARC_HAL_LPC24XX_REG_TxTCR_CTR_RESET (1<<1) +#define CYGARC_HAL_LPC24XX_REG_TxTC 0x0008 +#define CYGARC_HAL_LPC24XX_REG_TxPR 0x000C +#define CYGARC_HAL_LPC24XX_REG_TxPC 0x0010 +#define CYGARC_HAL_LPC24XX_REG_TxMCR 0x0014 +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_INT (1<<0) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_RESET (1<<1) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_STOP (1<<2) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR1_INT (1<<3) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR1_RESET (1<<4) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR1_STOP (1<<5) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR2_INT (1<<6) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR2_RESET (1<<7) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR2_STOP (1<<8) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR3_INT (1<<9) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR3_RESET (1<<10) +#define CYGARC_HAL_LPC24XX_REG_TxMCR_MR3_STOP (1<<11) +#define CYGARC_HAL_LPC24XX_REG_TxMR0 0x0018 +#define CYGARC_HAL_LPC24XX_REG_TxMR1 0x001C +#define CYGARC_HAL_LPC24XX_REG_TxMR2 0x0020 +#define CYGARC_HAL_LPC24XX_REG_TxMR3 0x0024 +#define CYGARC_HAL_LPC24XX_REG_TxCCR 0x0028 +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR0_RISE (1<<0) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR0_FALL (1<<1) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR0 (1<<2) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR1_RISE (1<<3) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR1_FALL (1<<4) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR1 (1<<5) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR2_RISE (1<<6) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR2_FALL (1<<7) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR2 (1<<8) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR3_RISE (1<<9) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR3_FALL (1<<10) +#define CYGARC_HAL_LPC24XX_REG_TxCCR_INT_CR3 (1<<11) +#define CYGARC_HAL_LPC24XX_REG_TxCR0 0x002C +#define CYGARC_HAL_LPC24XX_REG_TxCR1 0x0030 +#define CYGARC_HAL_LPC24XX_REG_TxCR2 0x0034 +#define CYGARC_HAL_LPC24XX_REG_TxCR3 0x0038 +#define CYGARC_HAL_LPC24XX_REG_TxEMR 0x003C +#define CYGARC_HAL_LPC24XX_REG_TxEMR_EM0 (1<<0) +#define CYGARC_HAL_LPC24XX_REG_TxEMR_EM1 (1<<1) +#define CYGARC_HAL_LPC24XX_REG_TxEMR_EM2 (1<<2) +#define CYGARC_HAL_LPC24XX_REG_TxEMR_EM3 (1<<3) + +//============================================================================= +// UARTs (Ux) + +#define CYGARC_HAL_LPC24XX_REG_UART0_BASE 0xE000C000 +#define CYGARC_HAL_LPC24XX_REG_UART1_BASE 0xE0010000 +#define CYGARC_HAL_LPC24XX_REG_UART2_BASE 0xE0078000 +#define CYGARC_HAL_LPC24XX_REG_UART3_BASE 0xE007C000 + +// Registers are offsets from base for each UART +#define CYGARC_HAL_LPC24XX_REG_UxRBR 0x0000 // DLAB=0 read +#define CYGARC_HAL_LPC24XX_REG_UxTHR 0x0000 // DLAB=0 write +#define CYGARC_HAL_LPC24XX_REG_UxDLL 0x0000 // DLAB=1 r/w +#define CYGARC_HAL_LPC24XX_REG_UxIER 0x0004 // DLAB=0 +#define CYGARC_HAL_LPC24XX_REG_UxIER_RXDATA_INT (1<<0) +#define CYGARC_HAL_LPC24XX_REG_UxIER_THRE_INT (1<<1) +#define CYGARC_HAL_LPC24XX_REG_UxIER_RXLS_INT (1<<2) +#define CYGARC_HAL_LPC24XX_REG_U1IER_RXMS_INT (1<<3) // U1 only +#define CYGARC_HAL_LPC24XX_REG_UxDLM 0x0004 // DLAB=1 + +#define CYGARC_HAL_LPC24XX_REG_UxIIR 0x0008 // read +#define CYGARC_HAL_LPC24XX_REG_UxIIR_IIR0 (1<<0) +#define CYGARC_HAL_LPC24XX_REG_UxIIR_IIR1 (1<<1) +#define CYGARC_HAL_LPC24XX_REG_UxIIR_IIR2 (1<<2) +#define CYGARC_HAL_LPC24XX_REG_UxIIR_IIR3 (1<<3) +#define CYGARC_HAL_LPC24XX_REG_UxIIR_FIFOS (0xB0) + +#define CYGARC_HAL_LPC24XX_REG_UxFCR 0x0008 // write +#define CYGARC_HAL_LPC24XX_REG_UxFCR_FIFO_ENA (1<<0) +#define CYGARC_HAL_LPC24XX_REG_UxFCR_RX_FIFO_RESET (1<<1) +#define CYGARC_HAL_LPC24XX_REG_UxFCR_TX_FIFO_RESET (1<<2) +#define CYGARC_HAL_LPC24XX_REG_UxFCR_RX_TRIGGER_0 (0x00) +#define CYGARC_HAL_LPC24XX_REG_UxFCR_RX_TRIGGER_1 (0x40) +#define CYGARC_HAL_LPC24XX_REG_UxFCR_RX_TRIGGER_2 (0x80) +#define CYGARC_HAL_LPC24XX_REG_UxFCR_RX_TRIGGER_3 (0xB0) + +#define CYGARC_HAL_LPC24XX_REG_UxLCR 0x000C +#define CYGARC_HAL_LPC24XX_REG_UxLCR_WORD_LENGTH_5 (0x00) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_WORD_LENGTH_6 (0x01) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_WORD_LENGTH_7 (0x02) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_WORD_LENGTH_8 (0x03) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_STOP_1 (0x00) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_STOP_2 (0x04) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_PARITY_ENA (0x08) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_PARITY_ODD (0x00) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_PARITY_EVEN (0x10) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_PARITY_ONE (0x20) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_PARITY_ZERO (0x30) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_BREAK_ENA (0x40) +#define CYGARC_HAL_LPC24XX_REG_UxLCR_DLAB (0x80) + + +// Modem Control Register is UART1 only +#define CYGARC_HAL_LPC24XX_REG_U1MCR 0x0010 +#define CYGARC_HAL_LPC24XX_REG_U1MCR_DTR (1<<0) +#define CYGARC_HAL_LPC24XX_REG_U1MCR_RTS (1<<1) +#define CYGARC_HAL_LPC24XX_REG_U1MCR_LOOPBACK (1<<4) + +#define CYGARC_HAL_LPC24XX_REG_UxLSR 0x0014 +#define CYGARC_HAL_LPC24XX_REG_UxLSR_RDR (1<<0) +#define CYGARC_HAL_LPC24XX_REG_UxLSR_OE (1<<1) +#define CYGARC_HAL_LPC24XX_REG_UxLSR_PE (1<<2) +#define CYGARC_HAL_LPC24XX_REG_UxLSR_FE (1<<3) +#define CYGARC_HAL_LPC24XX_REG_UxLSR_BI (1<<4) +#define CYGARC_HAL_LPC24XX_REG_UxLSR_THRE (1<<5) +#define CYGARC_HAL_LPC24XX_REG_UxLSR_TEMT (1<<6) +#define CYGARC_HAL_LPC24XX_REG_UxLSR_RX_FIFO_ERR (1<<7) + +// Modem Status Register is UART1 only +#define CYGARC_HAL_LPC24XX_REG_U1MSR 0x0018 +#define CYGARC_HAL_LPC24XX_REG_U1MSR_DCTS (1<<0) +#define CYGARC_HAL_LPC24XX_REG_U1MSR_DDSR (1<<1) +#define CYGARC_HAL_LPC24XX_REG_U1MSR_RI_FALL (1<<2) +#define CYGARC_HAL_LPC24XX_REG_U1MSR_DDCD (1<<3) +#define CYGARC_HAL_LPC24XX_REG_U1MSR_CTS (1<<4) +#define CYGARC_HAL_LPC24XX_REG_U1MSR_DSR (1<<5) +#define CYGARC_HAL_LPC24XX_REG_U1MSR_RI (1<<6) +#define CYGARC_HAL_LPC24XX_REG_U1MSR_DCD (1<<7) + +#define CYGARC_HAL_LPC24XX_REG_UxSCR 0x001C +#define CYGARC_HAL_LPC24XX_REG_UxACR 0x0020 +#define CYGARC_HAL_LPC24XX_REG_U3ICR 0x0024 +#define CYGARC_HAL_LPC24XX_REG_UxFDR 0x0028 +#define CYCARC_HAL_LPC24XX_REG_UxTER 0x0030 + + +//============================================================================= +// Pulse Width Modulator (PWM) + +#define CYGARC_HAL_LPC24XX_REG_PWM0_BASE 0xE0014000 +#define CYGARC_HAL_LPC24XX_REG_PWM1_BASE 0xE0018000 + + +// Registers are offsets from base of this subsystem +#define CYGARC_HAL_LPC24XX_REG_PWMIR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_PWMIR_MR0_INT (1<<0) +#define CYGARC_HAL_LPC24XX_REG_PWMIR_MR1_INT (1<<1) +#define CYGARC_HAL_LPC24XX_REG_PWMIR_MR2_INT (1<<2) +#define CYGARC_HAL_LPC24XX_REG_PWMIR_MR3_INT (1<<3) +#define CYGARC_HAL_LPC24XX_REG_PWMIR_MR4_INT (1<<8) +#define CYGARC_HAL_LPC24XX_REG_PWMIR_MR5_INT (1<<9) +#define CYGARC_HAL_LPC24XX_REG_PWMIR_MR6_INT (1<<10) +#define CYGARC_HAL_LPC24XX_REG_PWMTCR 0x0004 +#define CYGARC_HAL_LPC24XX_REG_PWMTCR_CTR_ENA (1<<0) +#define CYGARC_HAL_LPC24XX_REG_PWMTCR_CTR_RESET (1<<1) +#define CYGARC_HAL_LPC24XX_REG_PWMTCR_PWM_ENA (1<<3) +#define CYGARC_HAL_LPC24XX_REG_PWMTC 0x0008 +#define CYGARC_HAL_LPC24XX_REG_PWMPR 0x000C +#define CYGARC_HAL_LPC24XX_REG_PWMPC 0x0010 +#define CYGARC_HAL_LPC24XX_REG_PWMMCR 0x0014 +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR0_INT (1<<0) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR0_RESET (1<<1) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR0_STOP (1<<2) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR1_INT (1<<3) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR1_RESET (1<<4) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR1_STOP (1<<5) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR2_INT (1<<6) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR2_RESET (1<<7) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR2_STOP (1<<8) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR3_INT (1<<9) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR3_RESET (1<<10) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR3_STOP (1<<11) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR4_INT (1<<12) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR4_RESET (1<<13) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR4_STOP (1<<14) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR5_INT (1<<15) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR5_RESET (1<<16) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR5_STOP (1<<17) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR6_INT (1<<18) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR6_RESET (1<<19) +#define CYGARC_HAL_LPC24XX_REG_PWMMCR_MR6_STOP (1<<20) +#define CYGARC_HAL_LPC24XX_REG_PWMMR0 0x0018 +#define CYGARC_HAL_LPC24XX_REG_PWMMR1 0x001C +#define CYGARC_HAL_LPC24XX_REG_PWMMR2 0x0020 +#define CYGARC_HAL_LPC24XX_REG_PWMMR3 0x0024 +#define CYGARC_HAL_LPC24XX_REG_PWMMR4 0x0040 +#define CYGARC_HAL_LPC24XX_REG_PWMMR5 0x0044 +#define CYGARC_HAL_LPC24XX_REG_PWMMR6 0x0048 +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR 0x004C +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_SEL1 (1<<1) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_SEL2 (1<<2) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_SEL3 (1<<3) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_SEL4 (1<<4) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_SEL5 (1<<5) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_SEL6 (1<<6) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_ENA1 (1<<9) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_ENA2 (1<<10) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_ENA3 (1<<11) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_ENA4 (1<<12) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_ENA5 (1<<13) +#define CYGARC_HAL_LPC24XX_REG_PWMMPCR_ENA6 (1<<14) +#define CYGARC_HAL_LPC24XX_REG_PWMLER 0x0050 +#define CYGARC_HAL_LPC24XX_REG_PWMLER_M0_ENA (1<<0) +#define CYGARC_HAL_LPC24XX_REG_PWMLER_M1_ENA (1<<1) +#define CYGARC_HAL_LPC24XX_REG_PWMLER_M2_ENA (1<<2) +#define CYGARC_HAL_LPC24XX_REG_PWMLER_M3_ENA (1<<3) +#define CYGARC_HAL_LPC24XX_REG_PWMLER_M4_ENA (1<<4) +#define CYGARC_HAL_LPC24XX_REG_PWMLER_M5_ENA (1<<5) +#define CYGARC_HAL_LPC24XX_REG_PWMLER_M6_ENA (1<<6) + +#define CYGARC_HAL_LPC24XX_REG_PWMCTCR 0x0070 + +//============================================================================= +// I2C (I2) + +#define CYGARC_HAL_LPC24XX_REG_I2C0_BASE 0xE001C000 +#define CYGARC_HAL_LPC24XX_REG_I2C1_BASE 0xE005C000 +#define CYGARC_HAL_LPC24XX_REG_I2C2_BASE 0xE0080000 + + +// Registers are offsets from base of this subsystem +#define CYGARC_HAL_LPC24XX_REG_I2CONSET 0x0000 +#define CYGARC_HAL_LPC24XX_REG_I2CONSET_AA (1<<2) +#define CYGARC_HAL_LPC24XX_REG_I2CONSET_SI (1<<3) +#define CYGARC_HAL_LPC24XX_REG_I2CONSET_STO (1<<4) +#define CYGARC_HAL_LPC24XX_REG_I2CONSET_STA (1<<5) +#define CYGARC_HAL_LPC24XX_REG_I2CONSET_I2EN (1<<6) +#define CYGARC_HAL_LPC24XX_REG_I2STAT 0x0004 +#define CYGARC_HAL_LPC24XX_REG_I2STAT_SHIFT 3 +#define CYGARC_HAL_LPC24XX_REG_I2DAT 0x0008 +#define CYGARC_HAL_LPC24XX_REG_I2ADR 0x000C +#define CYGARC_HAL_LPC24XX_REG_I2ADR_GC (1<<0) +#define CYGARC_HAL_LPC24XX_REG_I2SCLH 0x0010 +#define CYGARC_HAL_LPC24XX_REG_I2SCLL 0x0014 +#define CYGARC_HAL_LPC24XX_REG_I2CONCLR 0x0018 +#define CYGARC_HAL_LPC24XX_REG_I2CONCLR_AAC (1<<2) +#define CYGARC_HAL_LPC24XX_REG_I2CONCLR_SIC (1<<3) +#define CYGARC_HAL_LPC24XX_REG_I2CONCLR_STAC (1<<5) +#define CYGARC_HAL_LPC24XX_REG_I2CONCLR_I2ENC (1<<6) + +//============================================================================= +// SPI (S) + +#define CYGARC_HAL_LPC24XX_REG_SPI0_BASE 0xE0020000 +#define CYGARC_HAL_LPC24XX_REG_SPI1_BASE 0xE0030000 + +// Registers are offsets from base of this subsystem +#define CYGARC_HAL_LPC24XX_REG_SPI_SPCR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_SPI_SPCR_CPHA (1<<3) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPCR_CPOL (1<<4) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPCR_MSTR (1<<5) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPCR_LSBF (1<<6) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPCR_SPIE (1<<7) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPSR 0x0004 +#define CYGARC_HAL_LPC24XX_REG_SPI_SPSR_ABRT (1<<3) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPSR_MODF (1<<4) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPSR_ROVR (1<<5) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPSR_WCOL (1<<6) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPSR_SPIF (1<<7) +#define CYGARC_HAL_LPC24XX_REG_SPI_SPDR 0x0008 +#define CYGARC_HAL_LPC24XX_REG_SPI_SPCCR 0x000C +#define CYGARC_HAL_LPC24XX_REG_SPI_SPINT 0x001C + + +//============================================================================= +// RTC + +#define CYGARC_HAL_LPC24XX_REG_RTC_BASE 0xE0024000 + +// Registers are offsets from base of this subsystem + +#define CYGARC_HAL_LPC24XX_REG_RTC_ILR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_RTC_ILR_CIF (1<<0) +#define CYGARC_HAL_LPC24XX_REG_RTC_ILR_ALF (1<<1) +#define CYGARC_HAL_LPC24XX_REG_RTC_CTC 0x0004 +#define CYGARC_HAL_LPC24XX_REG_RTC_CCR 0x0008 +#define CYGARC_HAL_LPC24XX_REG_RTC_CCR_CLKEN (1<<0) +#define CYGARC_HAL_LPC24XX_REG_RTC_CCR_CTCRST (1<<1) +#define CYGARC_HAL_LPC24XX_REG_RTC_CIIR 0x000C +#define CYGARC_HAL_LPC24XX_REG_RTC_AMR 0x0010 +#define CYGARC_HAL_LPC24XX_REG_RTC_CTIME0 0x0014 +#define CYGARC_HAL_LPC24XX_REG_RTC_CTIME1 0x0018 +#define CYGARC_HAL_LPC24XX_REG_RTC_CTIME2 0x001C +#define CYGARC_HAL_LPC24XX_REG_RTC_SEC 0x0020 +#define CYGARC_HAL_LPC24XX_REG_RTC_MIN 0x0024 +#define CYGARC_HAL_LPC24XX_REG_RTC_HOUR 0x0028 +#define CYGARC_HAL_LPC24XX_REG_RTC_DOM 0x002C +#define CYGARC_HAL_LPC24XX_REG_RTC_DOW 0x0030 +#define CYGARC_HAL_LPC24XX_REG_RTC_DOY 0x0034 +#define CYGARC_HAL_LPC24XX_REG_RTC_MONTH 0x0038 +#define CYGARC_HAL_LPC24XX_REG_RTC_YEAR 0x003C +#define CYGARC_HAL_LPC24XX_REG_RTC_ALSEC 0x0060 +#define CYGARC_HAL_LPC24XX_REG_RTC_ALMIN 0x0064 +#define CYGARC_HAL_LPC24XX_REG_RTC_ALHOUR 0x0068 +#define CYGARC_HAL_LPC24XX_REG_RTC_ALDOM 0x006C +#define CYGARC_HAL_LPC24XX_REG_RTC_ALDOW 0x0070 +#define CYGARC_HAL_LPC24XX_REG_RTC_ALDOY 0x0074 +#define CYGARC_HAL_LPC24XX_REG_RTC_ALMON 0x0078 +#define CYGARC_HAL_LPC24XX_REG_RTC_ALYEAR 0x007C +#define CYGARC_HAL_LPC24XX_REG_RTC_PREINT 0x0080 +#define CYGARC_HAL_LPC24XX_REG_RTC_PREFRAC 0x0084 + +//============================================================================= +// GPIO (IO) + +#define CYGARC_HAL_LPC24XX_REG_IO_BASE 0xE0028000 +#define CYGARC_HAL_LPC24XX_REG_FIO_BASE 0x3FFFC000 + +// Registers are offsets from base of this subsystem +#define CYGARC_HAL_LPC24XX_REG_IO0PIN 0x000 +#define CYGARC_HAL_LPC24XX_REG_IO0SET 0x004 +#define CYGARC_HAL_LPC24XX_REG_IO0DIR 0x008 +#define CYGARC_HAL_LPC24XX_REG_IO0CLR 0x00C + +#define CYGARC_HAL_LPC24XX_REG_IO1PIN 0x010 +#define CYGARC_HAL_LPC24XX_REG_IO1SET 0x014 +#define CYGARC_HAL_LPC24XX_REG_IO1DIR 0x018 +#define CYGARC_HAL_LPC24XX_REG_IO1CLR 0x01C + +#define CYGARC_HAL_LPC24XX_REG_FIO0DIR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_FIO1DIR 0x0020 +#define CYGARC_HAL_LPC24XX_REG_FIO2DIR 0x0040 +#define CYGARC_HAL_LPC24XX_REG_FIO3DIR 0x0050 +#define CYGARC_HAL_LPC24XX_REG_FIO4DIR 0x0080 + +#define CYGARC_HAL_LPC24XX_REG_FIO0SET 0x0018 +#define CYGARC_HAL_LPC24XX_REG_FIO1SET 0x0038 +#define CYGARC_HAL_LPC24XX_REG_FIO2SET 0x0058 +#define CYGARC_HAL_LPC24XX_REG_FIO3SET 0x0078 +#define CYGARC_HAL_LPC24XX_REG_FIO4SET 0x0098 + +#define CYGARC_HAL_LPC24XX_REG_FIO0CLR 0x001C +#define CYGARC_HAL_LPC24XX_REG_FIO1CLR 0x003C +#define CYGARC_HAL_LPC24XX_REG_FIO2CLR 0x005C +#define CYGARC_HAL_LPC24XX_REG_FIO3CLR 0x007C +#define CYGARC_HAL_LPC24XX_REG_FIO4CLR 0x009C + +#define CYGARC_HAL_LPC24XX_REG_FIO0PIN 0x0014 +#define CYGARC_HAL_LPC24XX_REG_FIO1PIN 0x0034 +#define CYGARC_HAL_LPC24XX_REG_FIO2PIN 0x0054 +#define CYGARC_HAL_LPC24XX_REG_FIO3PIN 0x0074 +#define CYGARC_HAL_LPC24XX_REG_FIO4PIN 0x0094 + +#define CYGARC_HAL_LPC24XX_REG_FIO0MASK 0x0010 +#define CYGARC_HAL_LPC24XX_REG_FIO1MASK 0x0030 +#define CYGARC_HAL_LPC24XX_REG_FIO2MASK 0x0050 +#define CYGARC_HAL_LPC24XX_REG_FIO3MASK 0x0070 +#define CYGARC_HAL_LPC24XX_REG_FIO4MASK 0x0090 + + + +//============================================================================= +// Pin Connect Block (PIN) + +#define CYGARC_HAL_LPC24XX_REG_PIN_BASE 0xE002C000 + +#define CYGARC_HAL_LPC24XX_REG_PINSEL0 0x000 +#define CYGARC_HAL_LPC24XX_REG_PINSEL1 0x004 +#define CYGARC_HAL_LPC24XX_REG_PINSEL2 0x008 +#define CYGARC_HAL_LPC24XX_REG_PINSEL3 0x00C +#define CYGARC_HAL_LPC24XX_REG_PINSEL4 0x010 +#define CYGARC_HAL_LPC24XX_REG_PINSEL5 0x014 +#define CYGARC_HAL_LPC24XX_REG_PINSEL6 0x018 +#define CYGARC_HAL_LPC24XX_REG_PINSEL7 0x01C +#define CYGARC_HAL_LPC24XX_REG_PINSEL8 0x020 +#define CYGARC_HAL_LPC24XX_REG_PINSEL9 0x024 +#define CYGARC_HAL_LPC24XX_REG_PINSEL10 0x028 +#define CYGARC_HAL_LPC24XX_REG_PINSEL11 0x02C + +#define CYGARC_HAL_LPC24XX_REG_PINMODE0 0x040 +#define CYGARC_HAL_LPC24XX_REG_PINMODE1 0x044 +#define CYGARC_HAL_LPC24XX_REG_PINMODE2 0x048 +#define CYGARC_HAL_LPC24XX_REG_PINMODE3 0x04C +#define CYGARC_HAL_LPC24XX_REG_PINMODE4 0x050 +#define CYGARC_HAL_LPC24XX_REG_PINMODE5 0x054 +#define CYGARC_HAL_LPC24XX_REG_PINMODE6 0x058 +#define CYGARC_HAL_LPC24XX_REG_PINMODE7 0x05C +#define CYGARC_HAL_LPC24XX_REG_PINMODE8 0x060 +#define CYGARC_HAL_LPC24XX_REG_PINMODE9 0x064 + +#define CYGARC_HAL_LPC24XX_SET_PIN_FUN(_regval_, _pin_, _func_) \ + (_regval_) = ((_regval_) & ~(0x3 << ((_pin_) << 1))) | ((_func_) << ((_pin_) << 1)) + + +//============================================================================= +// SSP - Synchronous Serial Port +#define CYGARC_HAL_LPC24XX_REG_SSP0_BASE 0xE0068000 +#define CYGARC_HAL_LPC24XX_REG_SSP1_BASE 0xE0030000 + +#define CYGARC_HAL_LPC24XX_REG_SSP_CR0 0x0000 +#define CYGARC_HAL_LPC24XX_REG_SSP_CR1 0x0004 +#define CYGARC_HAL_LPC24XX_REG_SSP_DR 0x0008 +#define CYGARC_HAL_LPC24XX_REG_SSP_SR 0x000C +#define CYGARC_HAL_LPC24XX_REG_SSP_CPSR 0x0010 +#define CYGARC_HAL_LPC24XX_REG_SSP_IMSC 0x0014 +#define CYGARC_HAL_LPC24XX_REG_SSP_RIS 0x0018 +#define CYGARC_HAL_LPC24XX_REG_SSP_MIS 0x001C +#define CYGARC_HAL_LPC24XX_REG_SSP_ICR 0x0020 +#define CYGARC_HAL_LPC24XX_REG_SSP_DMACR 0x0024 + + +//============================================================================= +// ADC (AD) + +#define CYGARC_HAL_LPC24XX_REG_AD_BASE 0xE0034000 + +// Registers are offsets from base of this subsystem +#define CYGARC_HAL_LPC24XX_REG_ADCR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_ADCR_BURST (1<<16) +#define CYGARC_HAL_LPC24XX_REG_ADCR_PDN (1<<21) +#define CYGARC_HAL_LPC24XX_REG_ADCR_EDGE (1<<27) +#define CYGARC_HAL_LPC24XX_REG_ADGDR 0x0004 +#define CYGARC_HAL_LPC24XX_REG_ADSTAT 0x0030 +#define CYGARC_HAL_LPC24XX_REG_ADINTEN 0x000C +#define CYGARC_HAL_LPC24XX_REG_ADDR0 0x0010 +#define CYGARC_HAL_LPC24XX_REG_ADDR1 0x0018 +#define CYGARC_HAL_LPC24XX_REG_ADDR2 0x0018 +#define CYGARC_HAL_LPC24XX_REG_ADDR3 0x001C +#define CYGARC_HAL_LPC24XX_REG_ADDR4 0x0020 +#define CYGARC_HAL_LPC24XX_REG_ADDR5 0x0024 +#define CYGARC_HAL_LPC24XX_REG_ADDR6 0x0028 +#define CYGARC_HAL_LPC24XX_REG_ADDR7 0x002C + + +//============================================================================= +// CAN +#define CYGARC_HAL_LPC24XX_REG_CAN_ACCFILT_RAM 0xE0038000 +#define CYGARC_HAL_LPC24XX_REG_CAN_ACCFILT_BASE 0xE003C000 +#define CYGARC_HAL_LPC24XX_REG_CAN_ACCFILT_AFMR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_CAN_ACCFILT_SFF_sa 0x0004 +#define CYGARC_HAL_LPC24XX_REG_CAN_ACCFILT_SFF_GRP_sa 0x0008 +#define CYGARC_HAL_LPC24XX_REG_CAN_ACCFILT_EFF_sa 0x000C +#define CYGARC_HAL_LPC24XX_REG_CAN_ACCFILT_EFF_GRP_sa 0x0010 +#define CYGARC_HAL_LPC24XX_REG_CAN_ACCFILT_END 0x0014 + +#define CYGARC_HAL_LPC24XX_REG_CAN_COMMON_BASE 0xE0040000 +#define CYGARC_HAL_LPC24XX_REG_CAN_TxSR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_CAN_RxSR 0x0004 +#define CYGARC_HAL_LPC24XX_REG_CAN_MSR 0x0008 + +#define CYGARC_HAL_LPC24XX_REG_CAN0_BASE 0xE0044000 +#define CYGARC_HAL_LPC24XX_REG_CAN1_BASE 0xE0048000 +#define CYCARC_HAL_LPC24XX_REG_CANx_MOD 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_CMR 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_GSR 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_ICR 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_IER 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_BTR 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_EWL 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_SR 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_RFS 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_RID 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_RDA 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_RDB 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_RFI1 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TID1 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TDA1 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TDB1 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_RFI2 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TID2 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TDA2 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TDB2 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_RFI3 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TID3 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TDA3 0x0000 +#define CYCARC_HAL_LPC24XX_REG_CANx_TDB3 0x0000 + + +//============================================================================= +// DAC +#define CYGARC_HAL_LPC24XX_REG_DAC_BASE 0xE006C000 + + +//============================================================================= +// Battery RAM +#define CYGARC_HAL_LPC24XX_REG_BATTERY_RAM 0xE0084000 + + +//============================================================================= +// I2S +#define CYGARC_HAL_LPC24XX_REG_I2S_BASE 0xE0088000 + +#define CYGARC_HAL_LPC24XX_REG_I2S_DAO 0x0000 +#define CYGARC_HAL_LPC24XX_REG_I2S_DAI 0x0004 +#define CYGARC_HAL_LPC24XX_REG_I2S_TXFIFO 0x0008 +#define CYGARC_HAL_LPC24XX_REG_I2S_RXFIFO 0x000C +#define CYGARC_HAL_LPC24XX_REG_I2S_STATE 0x0010 +#define CYGARC_HAL_LPC24XX_REG_I2S_DMA1 0x0014 +#define CYGARC_HAL_LPC24XX_REG_I2S_DMA2 0x0018 +#define CYGARC_HAL_LPC24XX_REG_I2S_IRQ 0x001C +#define CYGARC_HAL_LPC24XX_REG_I2S_TXRATE 0x0020 +#define CYGARC_HAL_LPC24XX_REG_I2S_RXRATE 0x0024 + + + +//============================================================================= +// SD/MMC Card Interface +#define CYGARC_HAL_LPC24XX_REG_SD_MMC_BASE 0xE008C000 + + +//============================================================================= +// System Control Block + +#define CYGARC_HAL_LPC24XX_REG_SCB_BASE 0xE01FC000 + +// Registers are offsets from base of this subsystem + +// Memory accelerator module +#define CYGARC_HAL_LPC24XX_REG_MAMCR 0x0000 +#define CYGARC_HAL_LPC24XX_REG_MAMCR_DISABLED 0x00 +#define CYGARC_HAL_LPC24XX_REG_MAMCR_PARTIAL 0x01 +#define CYGARC_HAL_LPC24XX_REG_MAMCR_FULL 0x02 +#define CYGARC_HAL_LPC24XX_REG_MAMTIM 0x0004 + +// Memory mapping control +#define CYGARC_HAL_LPC24XX_REG_MEMMAP 0x0040 + +// PLL +#define CYGARC_HAL_LPC24XX_REG_PLLCON 0x0080 +#define CYGARC_HAL_LPC24XX_REG_PLLCON_PLLE (1<<0) +#define CYGARC_HAL_LPC24XX_REG_PLLCON_PLLC (1<<1) +#define CYGARC_HAL_LPC24XX_REG_PLLCFG 0x0084 +#define CYGARC_HAL_LPC24XX_REG_PLLSTAT 0x0088 +#define CYGARC_HAL_LPC24XX_REG_PLLSTAT_PLLE (1<<24) +#define CYGARC_HAL_LPC24XX_REG_PLLSTAT_PLLC (1<<25) +#define CYGARC_HAL_LPC24XX_REG_PLLSTAT_PLOCK (1<<26) +#define CYGARC_HAL_LPC24XX_REG_PLLFEED 0x008C + +// Power Control +#define CYGARC_HAL_LPC24XX_REG_PCON 0x00C0 +#define CYGARC_HAL_LPC24XX_REG_PCON_IDL (1<<0) +#define CYGARC_HAL_LPC24XX_REG_PCON_PD (1<<1) +#define CYGARC_HAL_LPC24XX_REG_PCONP 0x00C4 +#define CYGARC_HAL_LPC24XX_REG_PCONP_TIM0 (1<<1) +#define CYGARC_HAL_LPC24XX_REG_PCONP_TIM1 (1<<2) +#define CYGARC_HAL_LPC24XX_REG_PCONP_URT0 (1<<3) +#define CYGARC_HAL_LPC24XX_REG_PCONP_URT1 (1<<4) +#define CYGARC_HAL_LPC24XX_REG_PCONP_PWM0 (1<<5) +#define CYGARC_HAL_LPC24XX_REG_PCONP_PWM1 (1<<6) +#define CYGARC_HAL_LPC24XX_REG_PCONP_I2C0 (1<<7) +#define CYGARC_HAL_LPC24XX_REG_PCONP_SPI (1<<8) +#define CYGARC_HAL_LPC24XX_REG_PCONP_RTC (1<<9) +#define CYGARC_HAL_LPC24XX_REG_PCONP_SSP1 (1<<10) +#define CYGARC_HAL_LPC24XX_REG_PCONP_EMC (1<<11) +#define CYGARC_HAL_LPC24XX_REG_PCONP_AD (1<<12) +#define CYGARC_HAL_LPC24XX_REG_PCONP_CAN1 (1<<13) +#define CYGARC_HAL_LPC24XX_REG_PCONP_CAN2 (1<<14) +#define CYGARC_HAL_LPC24XX_REG_PCONP_I2C1 (1<<19) +#define CYGARC_HAL_LPC24XX_REG_PCONP_LCD (1<<20) +#define CYGARC_HAL_LPC24XX_REG_PCONP_SSP0 (1<<21) +#define CYGARC_HAL_LPC24XX_REG_PCONP_TIM2 (1<<22) +#define CYGARC_HAL_LPC24XX_REG_PCONP_TIM3 (1<<23) +#define CYGARC_HAL_LPC24XX_REG_PCONP_URT2 (1<<24) +#define CYGARC_HAL_LPC24XX_REG_PCONP_URT3 (1<<25) +#define CYGARC_HAL_LPC24XX_REG_PCONP_I2C2 (1<<26) +#define CYGARC_HAL_LPC24XX_REG_PCONP_I2S (1<<27) +#define CYGARC_HAL_LPC24XX_REG_PCONP_SD (1<<28) +#define CYGARC_HAL_LPC24XX_REG_PCONP_DMA (1<<29) +#define CYGARC_HAL_LPC24XX_REG_PCONP_ENET (1<<30) +#define CYGARC_HAL_LPC24XX_REG_PCONP_USB (1<<31) + +// External interrupt inputs +#define CYGARC_HAL_LPC24XX_REG_EXTINT 0x0140 +#define CYGARC_HAL_LPC24XX_REG_EXTMODE 0x0148 +#define CYGARC_HAL_LPC24XX_REG_EXTPOLAR 0x014C + +#define CYGARC_HAL_LPC24XX_REG_EXTxxx_INT0 (1<<0) +#define CYGARC_HAL_LPC24XX_REG_EXTxxx_INT1 (1<<1) +#define CYGARC_HAL_LPC24XX_REG_EXTxxx_INT2 (1<<2) +#define CYGARC_HAL_LPC24XX_REG_EXTxxx_INT3 (1<<3) + +// Reset source identification register +#define CYGARC_HAL_LPC24XX_REG_RSID 0x0180 +#define CYGARC_HAL_LPC24XX_REG_RSID_POR (1<<0) +#define CYGARC_HAL_LPC24XX_REG_RSID_EXTR (1<<1) +#define CYGARC_HAL_LPC24XX_REG_RSID_WDTR (1<<2) +#define CYGARC_HAL_LPC24XX_REG_RSID_BODR (1<<3) + +// System control and status register +#define CYGARC_HAL_LPC24XX_REG_SCS 0x01A0 +#define CYGARC_HAL_LPC24XX_REG_SCS_OSCEN 0x20 +#define CYGARC_HAL_LPC24XX_REG_SCS_OSCSTAT 0x40 + +// Clock source selection register +#define CYGARC_HAL_LPC24XX_REG_CLKSRCSEL 0x010C +#define CYGARC_HAL_LPC24XX_REG_CLKSRCSEL_IRC 0x00 +#define CYGARC_HAL_LPC24XX_REG_CLKSRCSEL_MAIN 0x01 +#define CYGARC_HAL_LPC24XX_REG_CLKSRCSEL_RTC 0x10 + +#define CYGARC_HAL_LPC24XX_REG_CCLKCFG 0x0104 +#define CYGARC_HAL_LPC24XX_REG_USBCLKCFG 0x0108 +#define CYGARC_HAL_LPC24XX_REG_IRCTRIM 0x01A4 +#define CYGARC_HAL_LPC24XX_REG_PCLKSEL0 0x01A8 +#define CYGARC_HAL_LPC24XX_REG_PCLKSEL1 0x01AC +#define CYGARC_HAL_LPC24XX_REG_INTWAKE 0x0144 + + +//============================================================================= +// External Memory Controller +#define CYGARC_HAL_LPC24XX_REG_EMC_BASE 0xFFE08000 + +#define CYGARC_HAL_LPC24XX_REG_EMC_CTRL 0x0000 +#define CYGARC_HAL_LPC24XX_REG_EMC_CTRL_EN (1 << 0) +#define CYGARC_HAL_LPC24XX_REG_EMC_CTRL_ADDRMIRR (1 << 1) +#define CYGARC_HAL_LPC24XX_REG_EMC_CTRL_LOWPOW (1 << 2) +#define CYGARC_HAL_LPC24XX_REG_EMC_STATUS 0x0004 +#define CYGARC_HAL_LPC24XX_REG_EMC_CONFIG 0x0008 +#define CYGARC_HAL_LPC24XX_REG_EMCD_CONTROL 0x0020 +#define CYGARC_HAL_LPC24XX_REG_EMCD_REFRESH 0x0024 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RDCFG 0x0028 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RP 0x0030 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RAS 0x0034 +#define CYGARC_HAL_LPC24XX_REG_EMCD_SREX 0x0038 +#define CYGARC_HAL_LPC24XX_REG_EMCD_APR 0x003C +#define CYGARC_HAL_LPC24XX_REG_EMCD_DAL 0x0040 +#define CYGARC_HAL_LPC24XX_REG_EMCD_WR 0x0044 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RC 0x0048 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RFC 0x004C +#define CYGARC_HAL_LPC24XX_REG_EMCD_XSR 0x0050 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RRD 0x0054 +#define CYGARC_HAL_LPC24XX_REG_EMCD_MRD 0x0058 +#define CYGARC_HAL_LPC24XX_REG_EMCS_EXT_WAIT 0x0080 + +#define CYGARC_HAL_LPC24XX_REG_EMCD_CONFIG0 0x0100 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RASCAS0 0x0104 +#define CYGARC_HAL_LPC24XX_REG_EMCD_CONFIG1 0x0120 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RASCAS1 0x0124 +#define CYGARC_HAL_LPC24XX_REG_EMCD_CONFIG2 0x0140 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RASCAS2 0x0144 +#define CYGARC_HAL_LPC24XX_REG_EMCD_CONFIG3 0x0160 +#define CYGARC_HAL_LPC24XX_REG_EMCD_RASCAS3 0x0164 + +#define CYGARC_HAL_LPC24XX_REG_EMCS_CONFIG0 0x0200 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITW_EN0 0x0204 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITO_EN0 0x0208 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITRD0 0x020C +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITPAGE0 0x0210 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITWR0 0x0214 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITTURN0 0x0218 + +#define CYGARC_HAL_LPC24XX_REG_EMCS_CONFIG1 0x0220 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITW_EN1 0x0224 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITO_EN1 0x0228 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITRD1 0x022C +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITPAGE1 0x0230 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITWR1 0x0234 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITTURN1 0x0238 + +#define CYGARC_HAL_LPC24XX_REG_EMCS_CONFIG2 0x0240 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITW_EN2 0x0244 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITO_EN2 0x0248 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITRD2 0x024C +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITPAGE2 0x0250 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITWR2 0x0254 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITTURN2 0x0258 + +#define CYGARC_HAL_LPC24XX_REG_EMCS_CONFIG3 0x0260 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITW_EN3 0x0264 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITO_EN3 0x0268 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITRD3 0x026C +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITPAGE3 0x0270 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITWR3 0x0274 +#define CYGARC_HAL_LPC24XX_REG_EMCS_WAITTURN3 0x0278 + + +//============================================================================= +// Vectored Interrupt Controller (VIC) + +#define CYGARC_HAL_LPC24XX_REG_VIC_BASE 0xFFFFF000 + +// Registers are offsets from base of this subsystem + +#define CYGARC_HAL_LPC24XX_REG_VICIRQSTAT 0x000 +#define CYGARC_HAL_LPC24XX_REG_VICFIQSTAT 0x004 +#define CYGARC_HAL_LPC24XX_REG_VICRAWINTR 0x008 +#define CYGARC_HAL_LPC24XX_REG_VICINTSELECT 0x00C +#define CYGARC_HAL_LPC24XX_REG_VICINTENABLE 0x010 +#define CYGARC_HAL_LPC24XX_REG_VICINTENCLEAR 0x014 +#define CYGARC_HAL_LPC24XX_REG_VICSOFTINT 0x018 +#define CYGARC_HAL_LPC24XX_REG_VICSOFTINTCLEAR 0x01C +#define CYGARC_HAL_LPC24XX_REG_VICPROTECTION 0x020 +#define CYGARC_HAL_LPC24XX_REG_VICSWPRIOMASK 0x020 + +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR0 0x100 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR1 0x104 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR2 0x108 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR3 0x10C +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR4 0x110 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR5 0x114 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR6 0x118 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR7 0x11C +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR8 0x120 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR9 0x124 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR10 0x128 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR11 0x12C +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR12 0x130 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR13 0x134 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR14 0x138 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR15 0x13C +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR16 0x140 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR17 0x144 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR18 0x148 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR19 0x14C +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR20 0x150 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR21 0x154 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR22 0x158 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR23 0x15C +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR24 0x160 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR25 0x164 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR26 0x168 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR27 0x16C +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR28 0x170 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR29 0x174 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR30 0x178 +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR31 0x17C + +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO0 0x200 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO1 0x204 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO2 0x208 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO3 0x20C +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO4 0x210 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO5 0x214 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO6 0x218 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO7 0x21C +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO8 0x220 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO9 0x224 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO10 0x228 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO11 0x22C +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO12 0x230 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO13 0x234 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO14 0x238 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO15 0x23C +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO16 0x240 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO17 0x244 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO18 0x248 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO19 0x24C +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO20 0x250 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO21 0x254 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO22 0x258 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO23 0x25C +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO24 0x260 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO25 0x264 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO26 0x268 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO27 0x26C +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO28 0x270 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO29 0x274 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO30 0x278 +#define CYGARC_HAL_LPC24XX_REG_VICVECTPRIO31 0x27C + + +#define CYGARC_HAL_LPC24XX_REG_VICVECTADDR 0xF00 + +//----------------------------------------------------------------------------- +// end of var_io.h +#endif // CYGONCE_HAL_VAR_IO_H diff --git a/packages/hal/arm/lpc24xx/var/v2_0/src/hal_diag.c b/packages/hal/arm/lpc24xx/var/v2_0/src/hal_diag.c new file mode 100755 index 00000000..3ac58158 --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/src/hal_diag.c @@ -0,0 +1,390 @@ +/*============================================================================= +// +// hal_diag.c +// +// HAL diagnostic output code +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 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): jani +// Contributors:jskov, gthomas +// Date: 2001-07-12 +// Purpose: HAL diagnostic output +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include +#include CYGBLD_HAL_PLATFORM_H + +#include // base types + +#include // SAVE/RESTORE GP macros +#include // IO macros +#include // interface API +#include // HAL_ENABLE/MASK/UNMASK_INTERRUPTS +#include // Helper functions +#include // CYG_ISR_HANDLED +#include + +#include // USART registers +#include // peripheral identifiers + + +//=========================================================================== +// DATA TYPES +//===========================================================================- +typedef struct +{ + cyg_uint8* base; + cyg_int32 msec_timeout; + int isr_vector; + int baud_rate; + cyg_uint8 periph_id; +} channel_data_t; + + +// +// Diagnostic serial channel data +// +static channel_data_t lpc2xxx_ser_channels[2] = +{ + { (cyg_uint8*)CYGARC_HAL_LPC24XX_REG_UART0_BASE, + 1000, + CYGNUM_HAL_INTERRUPT_UART0, + CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD, + CYNUM_HAL_LPC24XX_PCLK_UART0}, + + { (cyg_uint8*)CYGARC_HAL_LPC24XX_REG_UART1_BASE, + 1000, + CYGNUM_HAL_INTERRUPT_UART1, + CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD, + CYNUM_HAL_LPC24XX_PCLK_UART1} +}; + + +//=========================================================================== +// Initialize diagnostic serial channel +//=========================================================================== +static void cyg_hal_plf_serial_init_channel(void* __ch_data) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8* base = chan->base; + cyg_uint16 divider = CYG_HAL_ARM_LPC24XX_BAUD_GENERATOR(chan->periph_id, + chan->baud_rate); + // Set baudrate + HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxLCR, + CYGARC_HAL_LPC24XX_REG_UxLCR_DLAB); + HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxDLM, divider >> 8); + HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxDLL, divider & 0xFF); + + // 8-1-no parity. + HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxLCR, + CYGARC_HAL_LPC24XX_REG_UxLCR_WORD_LENGTH_8 | + CYGARC_HAL_LPC24XX_REG_UxLCR_STOP_1); + + // Reset and enable FIFO + HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxFCR, + CYGARC_HAL_LPC24XX_REG_UxFCR_FIFO_ENA | + CYGARC_HAL_LPC24XX_REG_UxFCR_RX_FIFO_RESET | + CYGARC_HAL_LPC24XX_REG_UxFCR_TX_FIFO_RESET); +} + + +//=========================================================================== +// Write single character +//=========================================================================== +void cyg_hal_plf_serial_putc(void *__ch_data, char c) +{ + cyg_uint8* base = ((channel_data_t*)__ch_data)->base; + cyg_uint8 stat; + CYGARC_HAL_SAVE_GP(); + + do { + HAL_READ_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxLSR, stat); + } while ((stat & CYGARC_HAL_LPC24XX_REG_UxLSR_THRE) == 0); + + HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxTHR, c); + + CYGARC_HAL_RESTORE_GP(); +} + + +//=========================================================================== +// Read single character non blocking +//=========================================================================== +static cyg_bool cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8* base = chan->base; + cyg_uint8 stat; + + HAL_READ_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxLSR, stat); + if ((stat & CYGARC_HAL_LPC24XX_REG_UxLSR_RDR) == 0) + return false; + + HAL_READ_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxRBR, *ch); + + return true; +} + + +//=========================================================================== +// Read single character blocking +//=========================================================================== +cyg_uint8 cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8 ch; + CYGARC_HAL_SAVE_GP(); + + while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)); + + CYGARC_HAL_RESTORE_GP(); + return ch; +} + + +//=========================================================================== +// Write data buffer via serial line +//=========================================================================== +static void cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + + +//=========================================================================== +// Read data buffer +//=========================================================================== +static void cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + + +//=========================================================================== +// Read single character with timeout +//=========================================================================== +cyg_bool cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_bool res; + CYGARC_HAL_SAVE_GP(); + + delay_count = chan->msec_timeout * 10; // delay in .1 ms steps + + for(;;) { + res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + + +//=========================================================================== +// Control serial channel configuration +//=========================================================================== +static int cyg_hal_plf_serial_control(void *__ch_data, + __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8* base = ((channel_data_t*)__ch_data)->base; + int ret = 0; + va_list ap; + + CYGARC_HAL_SAVE_GP(); + va_start(ap, __func); + + switch (__func) { + case __COMMCTL_GETBAUD: + ret = chan->baud_rate; + break; + case __COMMCTL_SETBAUD: + chan->baud_rate = va_arg(ap, cyg_int32); + // Should we verify this value here? + cyg_hal_plf_serial_init_channel(chan); + ret = 0; + break; + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector); + HAL_INTERRUPT_UNMASK(chan->isr_vector); + HAL_WRITE_UINT32(base+CYGARC_HAL_LPC24XX_REG_UxIER, + CYGARC_HAL_LPC24XX_REG_UxIER_RXDATA_INT); + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + HAL_INTERRUPT_MASK(chan->isr_vector); + HAL_WRITE_UINT32(base+CYGARC_HAL_LPC24XX_REG_UxIER, 0); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = chan->isr_vector; + break; + case __COMMCTL_SET_TIMEOUT: + ret = chan->msec_timeout; + chan->msec_timeout = va_arg(ap, cyg_uint32); + default: + break; + } + + va_end(ap); + CYGARC_HAL_RESTORE_GP(); + return ret; +} + + +//=========================================================================== +// Serial channel ISR +//=========================================================================== +static int cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + int res = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8 c; + cyg_uint8 iir; + + CYGARC_HAL_SAVE_GP(); + + *__ctrlc = 0; + + HAL_READ_UINT32(chan->base + CYGARC_HAL_LPC24XX_REG_UxIIR, iir); + + if((iir & (CYGARC_HAL_LPC24XX_REG_UxIIR_IIR0 | + CYGARC_HAL_LPC24XX_REG_UxIIR_IIR1 | + CYGARC_HAL_LPC24XX_REG_UxIIR_IIR2)) + == CYGARC_HAL_LPC24XX_REG_UxIIR_IIR2) + { + // Rx data available or character timeout + // Read data in order to clear interrupt + HAL_READ_UINT32(chan->base + CYGARC_HAL_LPC24XX_REG_UxRBR, c); + if( cyg_hal_is_break( &c , 1 ) ) *__ctrlc = 1; + + res = CYG_ISR_HANDLED; + } + + HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector); + + CYGARC_HAL_RESTORE_GP(); + return res; +} + + +//=========================================================================== +// Initialize serial channel +//=========================================================================== +void cyg_hal_plf_serial_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur; + + cur = + CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Init channels + cyg_hal_plf_serial_init_channel(&lpc2xxx_ser_channels[0]); +#if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1 + cyg_hal_plf_serial_init_channel(&lpc2xxx_ser_channels[1]); +#endif + + // Setup procs in the vector table + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &lpc2xxx_ser_channels[0]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + +#if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1 + // Set channel 1 + CYGACC_CALL_IF_SET_CONSOLE_COMM(1); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &lpc2xxx_ser_channels[1]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); +#endif + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + + +//=========================================================================== +// Set diagnostic led +//=========================================================================== +void hal_diag_led(int mask) +{ + hal_lpc24xx_set_leds(mask); +} + +//----------------------------------------------------------------------------- +// End of hal_diag.c diff --git a/packages/hal/arm/lpc24xx/var/v2_0/src/lpc24xx_misc.c b/packages/hal/arm/lpc24xx/var/v2_0/src/lpc24xx_misc.c new file mode 100755 index 00000000..7b7d489a --- /dev/null +++ b/packages/hal/arm/lpc24xx/var/v2_0/src/lpc24xx_misc.c @@ -0,0 +1,440 @@ +/*========================================================================== +// +// lpc24xx_misc.c +// +// HAL misc variant support code for NXP LPC24xx +// +//========================================================================== +//####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 Nick Garnett +// Copyright (C) 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: gthomas, jskov, nickg, tkoeller +// Date: 2008-07-06 +// Purpose: Prozessor support +// Description: Implementations of LPC24xx processor support +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include +#include + +#include // base types +#include // tracing macros +#include // assertion macros + +#include // IO macros +#include // Register state info +#include +#include // necessary? +#include +#include // calling interface +#include // helper functions +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT +#include // HAL ISR support +#endif +#include // platform registers + +#include // For diagnostic printing + + +//=========================================================================== +// Get peripheral clock for a certain peripheral +//=========================================================================== +cyg_uint32 hal_lpc_get_pclk(cyg_uint32 peripheral_id) +{ + static const cyg_uint8 divider_tbl[4] = + { + 4, 1, 2, 8 + }; + cyg_uint32 pclkselreg; + cyg_uint32 regval; + cyg_uint8 divider; + + // + // decide if we need PCLKSEL0 or PCLKSEL1 + // + pclkselreg = ((peripheral_id <= CYNUM_HAL_LPC24XX_PCLK_ACF) ? + CYGARC_HAL_LPC24XX_REG_PCLKSEL0 : + CYGARC_HAL_LPC24XX_REG_PCLKSEL1); + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval); + regval = (regval >> ((peripheral_id & 0xF) << 1)) & 0x03; + divider = divider_tbl[regval]; + if ((8 == divider) && (peripheral_id >= CYNUM_HAL_LPC24XX_PCLK_CAN1) + && (peripheral_id <= CYNUM_HAL_LPC24XX_PCLK_ACF)) + { + divider = 6; + } + return CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / divider; +} + + +//=========================================================================== +// Set peripheral clock +//=========================================================================== +void hal_lpc_set_pclk(cyg_uint32 peripheral_id, cyg_uint8 divider) +{ + static const cyg_uint8 clock_tbl[4] = + { + 0x01, 0x02, 0x00, 0x03 + }; + cyg_uint32 clock; + cyg_uint32 pclkselreg; + cyg_uint32 regval; + + CYG_ASSERT(divider <= 8, "Wrong peripheral clock divider value"); + // + // decide if we need PCLKSEL0 or PCLKSEL1 + // + pclkselreg = (peripheral_id <= CYNUM_HAL_LPC24XX_PCLK_ACF) ? + CYGARC_HAL_LPC24XX_REG_PCLKSEL0 : + CYGARC_HAL_LPC24XX_REG_PCLKSEL1; + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval); + divider = (6 == divider) ? 8 : divider; + clock = clock_tbl[divider >> 1]; + regval |= (clock << ((peripheral_id & 0xF) << 1)); + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + pclkselreg, regval); +} + + +//=========================================================================== +// initialize timer 0 as eCos realtime clock source +//=========================================================================== +void hal_clock_initialize(cyg_uint32 period) +{ + CYG_ADDRESS timer = CYGARC_HAL_LPC24XX_REG_TIMER0_BASE; + + period = period / (CYGNUM_HAL_ARM_LPC24XX_CLOCK_SPEED / + hal_lpc_get_pclk(CYNUM_HAL_LPC24XX_PCLK_TIMER0)); + + // + // Disable and reset counter, set prescale register to 0 and + // Set up match register + // + HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxTCR, 2); + HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxPR, 0); + HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxMR0, period); + + // + // Reset and generate interrupt on match and Enable counter + // + HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxMCR, + CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_INT | + CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_RESET); + HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTCR, 1); +} + + +//=========================================================================== +// Reset clock +//=========================================================================== +void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) +{ + static cyg_uint32 _period = 0; + CYG_ADDRESS timer = CYGARC_HAL_LPC24XX_REG_TIMER0_BASE; + + HAL_WRITE_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxIR, + CYGARC_HAL_LPC24XX_REG_TxIR_MR0); // Clear interrupt + + if (period != _period) + { + hal_clock_initialize(period); + } + _period = period; +} + + +//=========================================================================== +// Reset clock value +//=========================================================================== +void hal_clock_read(cyg_uint32 *pvalue) +{ + CYG_ADDRESS timer = CYGARC_HAL_LPC24XX_REG_TIMER0_BASE; + cyg_uint32 val; + + HAL_READ_UINT32(timer + CYGARC_HAL_LPC24XX_REG_TxTC, val); + *pvalue = val; +} + + +//=========================================================================== +// Delay for some number of micro-seconds - use TIMER1 +//=========================================================================== +void hal_delay_us(cyg_int32 usecs) +{ + CYG_ADDRESS timer = CYGARC_HAL_LPC24XX_REG_TIMER1_BASE; + cyg_uint32 stat; + cyg_uint64 ticks; + + // Calculate how many timer ticks the required number of + // microseconds equate to. We do this calculation in 64 bit + // arithmetic to avoid overflow. + ticks = (((cyg_uint64)usecs) * + ((cyg_uint64)hal_lpc_get_pclk(CYNUM_HAL_LPC24XX_PCLK_TIMER1))) / + 1000000LL; + + // Disable and reset counter + HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTCR, 2); + + // Stop on match + HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxMR0, ticks); + HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxMCR, + CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_STOP | + CYGARC_HAL_LPC24XX_REG_TxMCR_MR0_RESET); + + //set prescale register to 0 + HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxPR, 0); + + // Enable counter + HAL_WRITE_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTCR, 1); + + // Wait for the match + do { + HAL_READ_UINT32(timer+CYGARC_HAL_LPC24XX_REG_TxTC, stat); + } while (stat < ticks); +} + + +//=========================================================================== +// Perform variant setup. This optionally calls into the platform +// HAL if it has defined HAL_PLF_HARDWARE_INIT. +//=========================================================================== +void hal_hardware_init(void) +{ + cyg_uint32 i; + + // + // Setup peripheral clocks here according to configuration + // + hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_CAN1, CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV); + hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_CAN2, CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV); + hal_lpc_set_pclk(CYNUM_HAL_LPC24XX_PCLK_ACF, CYGNUM_HAL_ARM_LPC24XX_CAN_CLK_DIV); + + // + // Fill vector address registers with interrupt number. If an interrupt + // occurs we can simply read the interrupt number from the vector + // address register later + // + cyg_uint32 addr = CYGARC_HAL_LPC24XX_REG_VIC_BASE + + CYGARC_HAL_LPC24XX_REG_VICVECTADDR0; + for (i = 0; i < 32; ++i) + { + HAL_WRITE_UINT32(addr, i); + addr += 4; + } +#ifdef HAL_PLF_HARDWARE_INIT + // Perform any platform specific initializations + HAL_PLF_HARDWARE_INIT(); +#endif + + // Set up eCos/ROM interfaces + hal_if_init(); +} + + +//=========================================================================== +// This routine is called to respond to a hardware interrupt (IRQ). It +// should interrogate the hardware and return the IRQ vector number. +//=========================================================================== +int hal_IRQ_handler(void) +{ + cyg_uint32 irq_num; + + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_VIC_BASE + + CYGARC_HAL_LPC24XX_REG_VICVECTADDR, irq_num); + + return (irq_num); +} + + +//=========================================================================== +// Block the interrupt associated with the vector +//=========================================================================== +void hal_interrupt_mask(int vector) +{ + CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX && + vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector"); + + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_VIC_BASE + + CYGARC_HAL_LPC24XX_REG_VICINTENCLEAR, 1 << vector); +} + + +//=========================================================================== +// Unblock the interrupt associated with the vector +//=========================================================================== +void hal_interrupt_unmask(int vector) +{ + CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX && + vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector"); + + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_VIC_BASE + + CYGARC_HAL_LPC24XX_REG_VICINTENABLE, 1 << vector); +} + + +//=========================================================================== +// Acknowledge the interrupt associated with the vector. This +// clears the interrupt but may result in another interrupt being +// delivered +//=========================================================================== +void hal_interrupt_acknowledge(int vector) +{ + + // External interrupts have to be cleared from the EXTINT register + if (vector >= CYGNUM_HAL_INTERRUPT_EINT0 && + vector <= CYGNUM_HAL_INTERRUPT_EINT3) + { + // Map int vector to corresponding bit (0..3) + vector = 1 << (vector - CYGNUM_HAL_INTERRUPT_EINT0); + + // Clear the external interrupt + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + + CYGARC_HAL_LPC24XX_REG_EXTINT, vector); + } + + // + // Write any value to vector address register to + // acknowledge the interrupt + // + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_VIC_BASE + + CYGARC_HAL_LPC24XX_REG_VICVECTADDR, 0xFFFFFFFF); +} + + +//=========================================================================== +// This provides control over how an interrupt signal is detected. +// Options are between level or edge sensitive (level) and high/low +// level or rising/falling edge triggered (up). +//=========================================================================== +void hal_interrupt_configure(int vector, int level, int up) +{ + cyg_uint32 regval; + + // Only external interrupts are configurable + CYG_ASSERT(vector <= CYGNUM_HAL_INTERRUPT_EINT3 && + vector >= CYGNUM_HAL_INTERRUPT_EINT0 , "Invalid vector"); + + // Map int vector to corresponding bit (0..3) + vector = 1 << (vector - CYGNUM_HAL_INTERRUPT_EINT0); + + // Read current mode and update for level (0) or edge detection (1) + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + + CYGARC_HAL_LPC24XX_REG_EXTMODE, regval); + if (level) + { + regval &= ~vector; + } + else + { + regval |= vector; + } + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + + CYGARC_HAL_LPC24XX_REG_EXTMODE, regval); + + // Read current polarity and update for trigger level or edge + // level: high (1), low (0) edge: rising (1), falling (0) + HAL_READ_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + + CYGARC_HAL_LPC24XX_REG_EXTPOLAR, regval); + if (up) + { + regval |= vector; + } + else + { + regval &= ~vector; + } + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + + CYGARC_HAL_LPC24XX_REG_EXTPOLAR, regval); + + // Clear any spurious interrupt that might have been generated + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_SCB_BASE + + CYGARC_HAL_LPC24XX_REG_EXTINT, vector); +} + + +//=========================================================================== +// These selects select a priority level for the 32 vectored IRQs. +// There are 16 priority levels, corresponding to the values 0 +// through 15 decimal, of which 15 is the lowest priority. +// The reset value of these registers defaults all interrupt to the +// lowest priority, allowing a single write to elevate the priority +// of an individual interrupt. +//=========================================================================== +void hal_interrupt_set_level(int vector, int level) +{ + CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX && + vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector"); + CYG_ASSERT(level >= 0 && level <= 15, "Invalid level"); + + cyg_uint32 prioreg_addr = CYGARC_HAL_LPC24XX_REG_VIC_BASE + + CYGARC_HAL_LPC24XX_REG_VICVECTPRIO0 + + (vector << 2); + HAL_WRITE_UINT32(prioreg_addr, level & 0xF); +} + + +//=========================================================================== +// Use the watchdog to generate a reset +//=========================================================================== +void hal_lpc_watchdog_reset(void) +{ + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_WD_BASE + + CYGARC_HAL_LPC24XX_REG_WDTC, 0xFF); + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_WD_BASE + + CYGARC_HAL_LPC24XX_REG_WDMOD, + CYGARC_HAL_LPC24XX_REG_WDMOD_WDEN | + CYGARC_HAL_LPC24XX_REG_WDMOD_WDRESET); + + // feed WD with the two magic values + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_WD_BASE + + CYGARC_HAL_LPC24XX_REG_WDFEED, + CYGARC_HAL_LPC24XX_REG_WDFEED_MAGIC1); + HAL_WRITE_UINT32(CYGARC_HAL_LPC24XX_REG_WD_BASE + + CYGARC_HAL_LPC24XX_REG_WDFEED, + CYGARC_HAL_LPC24XX_REG_WDFEED_MAGIC2); + + while(1) + continue; +} + + +//-------------------------------------------------------------------------- +// EOF lpc24xx_misc.c diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/ChangeLog b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/ChangeLog new file mode 100755 index 00000000..8fd6a81f --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/ChangeLog @@ -0,0 +1,42 @@ +2008-01-04 Uwe Kindler + + * cdl/hal_arm_lpc2xxx_phycore229x.cdl + * include/plf_io.h + * include/hal_platform_setup.h + * src/phycore229x_misc: + Initial release of phyCORE-LPC229x development board package + + +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2008 eCosCentric Ltd. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== + diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/cdl/hal_arm_lpc2xxx_phycore229x.cdl b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/cdl/hal_arm_lpc2xxx_phycore229x.cdl new file mode 100755 index 00000000..920e697e --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/cdl/hal_arm_lpc2xxx_phycore229x.cdl @@ -0,0 +1,421 @@ +# ==================================================================== +# +# hal_arm_lpc2xxx_phycore229x.cdl +# +# Phytec phyCORE-LPC2292/94 HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2008 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: Uwe Kindler +# Date: 2007-11-20 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_LPC2XXX_PHYCORE229X { + display "Phytec phyCORE-LPC2292/94 development board HAL" + parent CYGPKG_HAL_ARM_LPC2XXX + define_header hal_arm_lpc2xxx_phycore229x.h + include_dir cyg/hal + hardware + implements CYGINT_DEVS_CAN_LPC2XXX_CAN0 + implements CYGINT_DEVS_CAN_LPC2XXX_CAN1 + description " + The phyCORE-229x HAL package provides the support needed to run + eCos on Phytec phyCORE-LPC2292/94 development board." + + compile phycore229x_misc.c + + requires { CYGHWR_HAL_ARM_LPC2XXX == "LPC2292" || CYGHWR_HAL_ARM_LPC2XXX == "LPC2294" } + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " + puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H " + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "#define HAL_PLATFORM_CPU \"ARM7TDMI-S\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"Phytec phyCORE-LPC2292/94\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + default_value {"ROM"} + legal_values {"RAM" "ROM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + Choose RAM or ROM startup type. Typically ROM startup is used for + building RedBoot. RedBoot runs from internal on chip flash of + LPC229x. Use RAM startup for building eCos applications. + RedBoot manages the external on board flash devices. It copies + the eCos application image from FLASH to phyCORE on board SRAM + and then starts the eCos application." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 2 + description " + Channel 0: UART0, Channel 1: UART1" + } + + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT { + display "Default console channel." + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + calculated 0 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + Phytec phyCORE-LPC2292/94 board has two serial channels. This option + chooses which channel will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The phyCORE-LPC2292/94 board has two serial ports. This option + chooses which port will be used for diagnostic output." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 38400 + description " + This option selects the baud rate used for the diagnostic port." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "GDB serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 38400 + description " + This option controls the baud rate used for the GDB + connection." + } + + cdl_component CYGHWR_HAL_ARM_PHYCORE229X_MEMCFG { + display "Memory configuration" + flavor none + description " + Configuration options for FLASH and SRAM memory of phyCORE + board." + + cdl_option CYGHWR_HAL_ARM_PHYCORE229X_FLASH { + display "Flash configuration" + flavor data + legal_values { "AM29DL800" "AM29LV800" "AM29LV160" "AM29LV320" } + default_value { "AM29LV800" } + description " + Select the type of FLASH device that is fitted on the phyCORE + board." + } + + cdl_option CYGHWR_HAL_ARM_PHYCORE229X_FLASH_DEVICE_SIZE { + display "FLASH device size" + flavor data + calculated { CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29DL800" ? + 0x100000 : + CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV800" ? + 0x100000 : + CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV160" ? + 0x200000 : + CYGHWR_HAL_ARM_PHYCORE229X_FLASH == "AM29LV320" ? + 0x400000 : 0x000 } + description " + Size of one single flash device." + } + + cdl_option CYGHWR_HAL_ARM_PHYCORE229X_FLASH_CNT { + display "Number of flash devices" + flavor data + legal_values { 0 2 4 } + default_value { 2 } + description " + This option defines the number of flash devices + fitted. The board supports two 16-bit data bus width + Flash devices in parallel connected to a 32-bit data + bus on the LPC2292/94. Flash devices are always fitted + in pairs and there is space for up to 4 devices." + } + + cdl_option CYGHWR_HAL_ARM_PHYCORE229X_FLASH_SIZE { + display "FLASH size" + flavor data + calculated { CYGHWR_HAL_ARM_PHYCORE229X_FLASH_DEVICE_SIZE * + CYGHWR_HAL_ARM_PHYCORE229X_FLASH_CNT } + description " + This option defines the size of the onboard FLASH. + The board can be fitted with 0, 2 or 4 FLASH devices of + 1MB, 2MB or 4MB." + } + + cdl_option CYGHWR_HAL_ARM_PHYCORE229X_SRAM_SIZE { + display "SRAM size" + flavor data + legal_values { 0x100000 0x200000 0x400000 0x800000 } + default_value 0x100000 + description " + This option defines the size of the onboard SRAM. + The board can be fittet with 2 or 4 SRAM devices of + 512KB, 1MB or 2MB." + } + } + + cdl_component CYGHWR_HAL_ARM_PHYCORE229X_ETH { + display "Ethernet options" + flavor none + description " + Configuration options for on board SMSC LAN91C111 ethernet + chip." + + + cdl_option CYGHWR_HAL_ARM_PHYCORE229X_ETH_EINT { + display "Ethernet controller interrupt" + flavor data + legal_values { 0 1 } + default_value { 0 } + description " + Jumper J501 selects, which of the microcontroller external + interrupts (EINT) connects with the interrupt output(LAN_IRQ) + of the Ethernet controller. This configuration option should + match the actual jumper settings. The LAN chip may use EINT0 + or EINT1." + } + + cdl_option CYGHWR_HAL_ARM_PHYCORE229X_ETH_INT_PRIO { + display "Ethernet interrupt priority" + flavor data + legal_values { 0 to 16 } + default_value { 15 } + description " + Interrupt priority of ethernet interrupt. The LPC2xxx + eCos HAL supports up to 17 interrupt levels. + Interrupt levels 0 - 15 are vectored IRQs. Vectored + IRQs have a higher priority then non vectored IRQs and + they are processed faster. Non vectored IRQs are all + chained together into one single slot and the ISR need + to find out which interrupt occured. The default value + for the ethernt interrupt is 15. This is the lowest + vectored IRQ priority. That ensures that the ethernet + interrupt is processed fast while it has still a lower + priority than any other verctored interrupt." + } + + cdl_option CYGHWR_HAL_ARM_PHYCORE229X_ETH_MEM_AREA { + display "Ethernet controller memory area" + flavor data + legal_values { 0x82000000 0x83000000 } + default_value { 0x82000000 } + description " + Access to the optional Ethernet controller can be established + via /CS2 (addr. 0x82000000) or /CS3 (addr. 0x83000000) + configurable with Jumper J502. The default configuration + allows access via /CS2." + } + } + + # Real-time clock/counter specifics + cdl_option CYGNUM_HAL_ARM_LPC2XXX_XTAL_FREQ { + display "CPU xtal frequency" + flavor data + default_value {10000000} + } + + cdl_option CYGNUM_HAL_ARM_LPC2XXX_PLL_MUL { + display "CPU PLL multiplier" + flavor data + default_value {6} + } + + cdl_option CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED { + display "CPU clock speed" + flavor data + calculated { CYGNUM_HAL_ARM_LPC2XXX_PLL_MUL * + CYGNUM_HAL_ARM_LPC2XXX_XTAL_FREQ } + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + description " + Global build options including control over compiler flags, + linker flags and choice of toolchain." + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "arm-elf" } + description " + This option specifies the command prefix used when + invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -mno-short-load-words -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + description " + This option controls the global compiler flags which + are used to compile all packages by default. Individual + packages may define options which override these global + flags." + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -mno-short-load-words -Wl,--gc-sections -Wl,-static -g -nostdlib" } + description " + This option controls the global linker flags. Individual + packages may define options which override these global + flags." + } + } + + cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM"} + description " + Enable this option if this program is to be used as a + ROM monitor, i.e. applications will be loaded into RAM on + the board, and this ROM monitor may process exceptions or + interrupts generated from the application. This enables + features such as utilizing a separate interrupt stack when + exceptions are generated." + } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM + monitor. This support changes various eCos semantics such + as the encoding of diagnostic output, or the overriding of + hardware interrupt vectors. + Firstly there is \"Generic\" support which prevents the + HAL from overriding the hardware vectors that it does not + use, to instead allow an installed ROM monitor to handle + them. This is the most basic support which is likely to be + common to most implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included + in the ROM monitor or boot ROM." + } + + cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { + display "Redboot HAL options" + flavor none + no_define + parent CYGPKG_REDBOOT + active_if CYGPKG_REDBOOT + description " + This option lists the target's requirements for a valid + Redboot configuration." + + cdl_option CYGBLD_BUILD_REDBOOT_BIN { + display "Build Redboot ROM binary image" + active_if CYGBLD_BUILD_REDBOOT + requires { !CYGBLD_BUILD_REDBOOT_WITH_EXEC } + default_value 1 + no_define + description " + This option enables the conversion of the Redboot ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + /bin/redboot.bin : /bin/redboot.elf + $(OBJCOPY) --strip-debug $< $(@:.bin=.img) + $(OBJCOPY) -O srec $< $(@:.bin=.srec) + $(OBJCOPY) -O ihex $< $(@:.bin=.hex) + $(OBJCOPY) -O binary $< $@ + } + + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { (CYG_HAL_STARTUP == "RAM") ? "arm_lpc2xxx_phycore229x_ram" : + "arm_lpc2xxx_phycore229x_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { (CYG_HAL_STARTUP == "RAM") ? "" : + "" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { (CYG_HAL_STARTUP == "RAM") ? "" : + "" } + } + } +} diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/hal_platform_setup.h b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/hal_platform_setup.h new file mode 100755 index 00000000..fa51a298 --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/hal_platform_setup.h @@ -0,0 +1,262 @@ +#ifndef CYGONCE_HAL_PLATFORM_SETUP_H +#define CYGONCE_HAL_PLATFORM_SETUP_H +/*============================================================================= +// +// hal_platform_setup.h +// +// Platform specific support for HAL (assembly code) +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 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: Uwe Kindler +// Date: 2007-12-02 +// Purpose: phyCORE-LPC229x platform specific support routines +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ +#include +#include + +//===========================================================================*/ + +#define LINES (0xFE<<16) +#define LINE (1<<16) +.macro _line_init + // set to GPIO + ldr r0,=CYGARC_HAL_LPC2XXX_REG_PIN_BASE + ldr r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PINSEL2] + bic r1, r1, #8 + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PINSEL2] + // set to output + ldr r0,=CYGARC_HAL_LPC2XXX_REG_IO_BASE + ldr r1,[r0,#CYGARC_HAL_LPC2XXX_REG_IO1DIR] + orr r1,r1,#LINE + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_IO1DIR] + // turn ON + ldr r1,[r0,#CYGARC_HAL_LPC2XXX_REG_IO1PIN] + bic r1,r1,#LINES + orr r1,r1,#LINE + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_IO1PIN] +.endm + +//---------------------------------------------------------------------------- +// The phyCORE Carrier Board HD200 offers a programmable LED at +// D3 for user implementations. This LED can be connected to port pin +// P0.8 (TxD1) of the phyCORE-LPC2292/94 which is available via +// signal GPIO0 (JP17 = closed). A low-level at port pin P0.8 causes the +// LED to illuminate, LED D3 remains off when writing a high-level to +// P0.8. +// +.macro _led_init + ldr r0,=CYGARC_HAL_LPC2XXX_REG_IO_BASE + ldr r1,=(1<<8) // GPIO0 pins 8 is LED output + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_IO0DIR] +.endm + +.macro _led x + ldr r0,=CYGARC_HAL_LPC2XXX_REG_IO_BASE + ldr r1,=(1<<8) + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_IO0CLR] + ldr r1,=((\x & 1)<<8) + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_IO0SET] +.endm +#define CYGHWR_LED_MACRO _led \x + + +//---------------------------------------------------------------------------- +// PLL initialisation +// +.macro _pll_init + ldr r0,=CYGARC_HAL_LPC2XXX_REG_SCB_BASE + + mov r2,#0xAA + mov r3,#0x55 + + mov r1,#(0x20 | (CYGNUM_HAL_ARM_LPC2XXX_PLL_MUL - 1)) + // load the PLL configuration register + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PLLCFG] + + mov r1,#1 + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PLLCON] // enable PLL + + // perform validation sequence 0XAA followed by 0x55 + str r2,[r0,#CYGARC_HAL_LPC2XXX_REG_PLLFEED] + str r3,[r0,#CYGARC_HAL_LPC2XXX_REG_PLLFEED] + +1: + ldr r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PLLSTAT] // wait for it to lock + ands r1,r1,#(1<<10) + beq 1b + + mov r1,#3 // connect PLL + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PLLCON] + + // perform validation sequence 0XAA followed by 0x55 + str r2,[r0,#CYGARC_HAL_LPC2XXX_REG_PLLFEED] + str r3,[r0,#CYGARC_HAL_LPC2XXX_REG_PLLFEED] +.endm + + +//---------------------------------------------------------------------------- +// External memory and bus initialisation +// +.macro _mem_init + // + // first map the vector table to internal flash - normally this should be + // the default value after boot - but we go the safe way here and force + // the mapping to internal flash (the value for + // CYGARC_HAL_LPC2XXX_REG_MEMMAP is 1) + // + ldr r0,=CYGARC_HAL_LPC2XXX_REG_SCB_BASE + mov r1,#1 + str r1, [r0,#CYGARC_HAL_LPC2XXX_REG_MEMMAP] + + // + // Now its is save to copy the first 64 bytes of flash to RAM + // + mov r0,#0 + mov r1,#0x40000000 + mov r2,#0x40 +1: + ldr r3,[r0,#4]! + str r3,[r1,#4]! + cmps r0,r2 + bne 1b + + // + // Now we can map the vector table to internal SRAM because the SRAM no + // contains a copy of the vector tablefrom flash (the value for + // CYGARC_HAL_LPC2XXX_REG_MEMMAP is 2 = SRAM) + // + ldr r0,=CYGARC_HAL_LPC2XXX_REG_SCB_BASE + // User RAM Mode. Interrupt vectors are re-mapped to Static RAM. + mov r1,#2 + str r1, [r0,#CYGARC_HAL_LPC2XXX_REG_MEMMAP] + // 4 processor clocks fetch cycle + mov r1,#4 + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_MAMTIM] // flash timings + mov r1,#2 + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_MAMCR] // enable full MAM + + // + // Set-up external memory - the main task here is to setup the + // wait states for the external memory properly + // + // Bank Configuration Registers 0-3 (BCFG0-3) + // [0..3] IDCY: Min. number of idle Cycles <0-15> + // [4] Reserved + // [5..9] WST1: Wait States 1 <0-31> + // [10] RBLE: Read Byte Lane Enable + // [11..15] WST2: Wait States 2 <0-31> + // [16..23] Reserved + // [26] WP: Write Protect + // [27] BM: Burst ROM + // [28..29] MW: Memory Width <0=8-bit,1=16-bit,2=32-bit,3=Reserved> + // [30..31] Reserved + // + + // enable external parallel bus signals + ldr r0,=CYGARC_HAL_LPC2XXX_REG_PIN_BASE + // A0..1 enabled, CS0..3, OE, WE, BLS0..3, D0..31, A2..23, JTAG Pins + ldr r1,=0x0FE149E4 + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PINSEL2] + + // setup external FLASH wait states + ldr r0,=CYGARC_HAL_LPC2XXX_REG_BCFG0 + ldr r1,=0x20003CE3 + str r1, [r0] + + // setup external SRAM wait states + ldr r0,=CYGARC_HAL_LPC2XXX_REG_BCFG1 + ldr r1,=0x020002483 + str r1, [r0] + + // setup Ethernet chip wait states for /CS2 and /CS3 + ldr r0,=CYGARC_HAL_LPC2XXX_REG_BCFG2 + ldr r1,=0x020000C23 + str r1, [r0] + ldr r0,=CYGARC_HAL_LPC2XXX_REG_BCFG3 + ldr r1,=0x020000C23 + str r1, [r0] +.endm + +.macro _gpio_init + // enable RX and TX on UART0 and UART1 + ldr r0,=CYGARC_HAL_LPC2XXX_REG_PIN_BASE + ldr r1,=0x00050005 + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PINSEL0] + + // set pin function to EINT0 + ldr r0,=CYGARC_HAL_LPC2XXX_REG_PIN_BASE + ldr r1,=0x00000001 + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_PINSEL1] +.endm + +.macro _block + ldr r0,=CYGARC_HAL_LPC2XXX_REG_IO_BASE + ldr r1,=(1<<8) + str r1,[r0,#CYGARC_HAL_LPC2XXX_REG_IO0CLR] +2: + nop + b 2 +.endm +#define PLATFORM_BLOCK _block +//===========================================================================*/ + +#if defined(CYG_HAL_STARTUP_ROM) +.macro _setup + _line_init + _led_init + _led 1 + _pll_init + _mem_init + _gpio_init +.endm +#define CYGSEM_HAL_ROM_RESET_USES_JUMP +#else + .macro _setup + + .endm +#endif + +#define PLATFORM_SETUP1 _setup + +//----------------------------------------------------------------------------- +// end of hal_platform_setup.h +#endif // CYGONCE_HAL_PLATFORM_SETUP_H diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_ram.h b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_ram.h new file mode 100755 index 00000000..80ab082e --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_ram.h @@ -0,0 +1,21 @@ +#ifndef __ASSEMBLER__ +#include +#include + +#endif + +#define CYGMEM_REGION_sram (0x40000000) +#define CYGMEM_REGION_sram_SIZE (0x00004000) +#define CYGMEM_REGION_sram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) + +#define CYGMEM_REGION_ram (0x81000000) +#define CYGMEM_REGION_ram_SIZE (0x00100000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) + +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif + +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x81100000 - (size_t) CYG_LABEL_NAME (__heap1)) + diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_ram.ldi b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_ram.ldi new file mode 100755 index 00000000..6b02bdb9 --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_ram.ldi @@ -0,0 +1,26 @@ +#include +#include + +MEMORY +{ + sram : ORIGIN = 0x40000000, LENGTH = 0x4000 + ram : ORIGIN = 0x81000000, LENGTH = CYGHWR_HAL_ARM_PHYCORE229X_SRAM_SIZE +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_fixed_vectors (sram, 0x40000400, LMA_EQ_VMA) + SECTION_rom_vectors (ram, 0x81010000, LMA_EQ_VMA) + SECTION_text (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fini (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} + diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_rom.h b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_rom.h new file mode 100755 index 00000000..cd634ad0 --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_rom.h @@ -0,0 +1,31 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_sram (0x40000000) +#define CYGMEM_REGION_sram_SIZE (0x00004000) +#define CYGMEM_REGION_sram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) + +#define CYGMEM_REGION_ram (0x81000000) +#define CYGMEM_REGION_ram_SIZE (CYGHWR_HAL_ARM_PHYCORE229X_SRAM_SIZE) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) + +#define CYGMEM_REGION_rom (0x00000000) +#define CYGMEM_REGION_rom_SIZE (0x00040000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) + +#define CYGMEM_REGION_flash (0x80000000) +#define CYGMEM_REGION_flash_SIZE (CYGHWR_HAL_ARM_PHYCORE229X_FLASH_SIZE) +#define CYGMEM_REGION_flash_ATTR (CYGMEM_REGION_ATTR_R) + +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x81000000 + CYGHWR_HAL_ARM_PHYCORE229X_SRAM_SIZE - (size_t) CYG_LABEL_NAME (__heap1)) + diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_rom.ldi b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_rom.ldi new file mode 100755 index 00000000..2128c6e6 --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/pkgconf/mlt_arm_lpc2xxx_phycore229x_rom.ldi @@ -0,0 +1,27 @@ +#include +#include + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 0x40000 + sram : ORIGIN = 0x40000000, LENGTH = 0x4000 + ram : ORIGIN = 0x81000000, LENGTH = CYGHWR_HAL_ARM_PHYCORE229X_SRAM_SIZE +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_rom_vectors (rom, 0x00000000, LMA_EQ_VMA) + SECTION_text (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (sram, 0x40000400, LMA_EQ_VMA) + SECTION_data (ram, 0x81000000, FOLLOWING (.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} + diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/plf_io.h b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/plf_io.h new file mode 100755 index 00000000..6bd9c7b4 --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/include/plf_io.h @@ -0,0 +1,68 @@ +#ifndef CYGONCE_HAL_PLF_IO_H +#define CYGONCE_HAL_PLF_IO_H +//============================================================================= +// +// plf_io.h +// +// Phytec phyCORE-LPC2292/94 board specific registers +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 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: Sergei Gavrikov +// Date: 2007-11-20 +// Purpose: Phytec phyCORE-LPC2292/94 board specific registers +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= +// On-chip device base addresses + + +//---------------------------------------------------------------------- +// The platform needs this initialization during the +// hal_hardware_init() function in the varient HAL. +#ifndef __ASSEMBLER__ +extern void hal_plf_hardware_init(void); +#define HAL_PLF_HARDWARE_INIT() \ + hal_plf_hardware_init() +#endif //__ASSEMBLER__ + +//----------------------------------------------------------------------------- +// end of plf_io.h +#endif // CYGONCE_HAL_PLF_IO_H + diff --git a/packages/hal/arm/lpc2xxx/phycore229x/v2_0/src/phycore229x_misc.c b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/src/phycore229x_misc.c new file mode 100755 index 00000000..57eab936 --- /dev/null +++ b/packages/hal/arm/lpc2xxx/phycore229x/v2_0/src/phycore229x_misc.c @@ -0,0 +1,138 @@ +/*========================================================================== +// +// phycore_misc.c +// +// HAL misc board support code for Phytec phyCORE-LPC2292/94 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2008 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: Uwe Kindler +// Date: 2007-11-20 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ +#include +#include +#include // IO macros + +#include // base types +#include +#include +#include + +#include +#include + +#ifdef CYGPKG_REDBOOT +#include +#endif + +extern void cyg_hal_plf_serial_init(void); + +void cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + initialized = 1; + + cyg_hal_plf_serial_init(); +} + +//-------------------------------------------------------------------------- +// hal_plf_hardware_init +// +void hal_plf_hardware_init(void) +{ +#if defined(CYG_HAL_STARTUP_ROM) && defined(CYGPKG_DEVS_ETH_ARM_PHYCORE229X) + cyg_uint32 regval; + + // + // Configures the LAN IRQ + // The interrupt is being used as active high edge triggered. + // IMPORTANT: We execute this step only for ROM startup. If this is done + // for RAM startup then wrong values are stored in EXTMODE and EXTPOLAR + // register because of a bug in LPC229x hardware. + // + HAL_INTERRUPT_CONFIGURE(CYGHWR_HAL_ARM_PHYCORE229X_ETH_EINT + // the configured external interrupt + CYGNUM_HAL_INTERRUPT_EINT0, // the first external interrupt + 0, // level = 0 - edge triggered + 1); // up = 1 - rising edge + + // + // Set pin function of P0.16 to EINT0 or P0.14 to EINT1 for ethernet interrupt + // +#if CYGHWR_HAL_ARM_PHYCORE229X_ETH_EINT == 0 + HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_PIN_BASE + + CYGARC_HAL_LPC2XXX_REG_PINSEL1, regval); + regval |= 0x01; + HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_PIN_BASE + + CYGARC_HAL_LPC2XXX_REG_PINSEL1, regval); +#elif CYGHWR_HAL_ARM_PHYCORE229X_ETH_EINT == 1 + HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_PIN_BASE + + CYGARC_HAL_LPC2XXX_REG_PINSEL0, regval); + regval |= (0x10 << 28); + HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_PIN_BASE + + CYGARC_HAL_LPC2XXX_REG_PINSEL0, regval); +#else +#error "Invalid CYGHWR_HAL_ARM_PHYCORE229X_ETH_EINT value" +#endif +#endif // #if defined(CYG_HAL_STARTUP_ROM) && defined(CYGPKG_DEVS_ETH_ARM_PHYCORE229X) +} + +//-------------------------------------------------------------------------- +// hal_lpc2xxx_set_leds +// +void hal_lpc2xxx_set_leds (int mask) +{ + // + // implement function for setting diagnostic leds + // +} + +//-------------------------------------------------------------------------- +// EOF phycore_misc.c + + + + + + + diff --git a/packages/hal/arm/lpc2xxx/var/v2_0/include/lpc2xxx_misc.h b/packages/hal/arm/lpc2xxx/var/v2_0/include/lpc2xxx_misc.h new file mode 100644 index 00000000..4c93848a --- /dev/null +++ b/packages/hal/arm/lpc2xxx/var/v2_0/include/lpc2xxx_misc.h @@ -0,0 +1,79 @@ +#ifndef CYGONCE_HAL_ARM_LPC2XXX_VAR_LPC2XXX_MISC_H +#define CYGONCE_HAL_ARM_LPC2XXX_VAR_LPC2XXX_MISC_H +//============================================================================= +// +// lpc2xxx_misc.h +// +// HAL misc variant support code for Philips LPC2xxx header file +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 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): andyj +// Contributors: jani +// Date: 2006-02-04 +// Purpose: LPC2XXX specific miscellaneous support header file +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +//----------------------------------------------------------------------------- +// Macros to derive the baudrate divider values for the internal UARTs +//----------------------------------------------------------------------------- +#define CYG_HAL_ARM_LPC2XXX_BAUD_GENERATOR(baud) \ + (CYGNUM_HAL_ARM_LPC2XXX_PCLK/((baud)*16)) + +//----------------------------------------------------------------------------- +// LPX2xxx varaint specific initialisatio of CAN channels +// This function configures the pin functions for CAN use +//----------------------------------------------------------------------------- +#ifdef CYGPKG_DEVS_CAN_LPC2XXX +externC void hal_lpc_can_init(cyg_uint8 can_chan_no); +#define HAL_LPC2XXX_INIT_CAN(_can_chan_no_) hal_lpc_can_init(_can_chan_no_) +#define CYGNUM_HAL_ARM_LPC2XXX_CAN_CLK CYGNUM_HAL_ARM_LPC2XXX_PCLK +#endif // CYGPKG_DEVS_CAN_LPC2XXX + +//----------------------------------------------------------------------------- +// LPX2xxx watchdog support +//----------------------------------------------------------------------------- +externC void hal_lpc_watchdog_reset(void); + +#define HAL_PLATFORM_RESET() hal_lpc_watchdog_reset() +#define HAL_PLATFORM_RESET_ENTRY 0 + +//----------------------------------------------------------------------------- +// end of lpc2xxx_misc.h +#endif // CYGONCE_HAL_ARM_LPC2XXX_VAR_LPC2XXX_MISC_H diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/ChangeLog b/packages/hal/arm/mac7100/mac7100evb/v2_0/ChangeLog new file mode 100644 index 00000000..15782d04 --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/ChangeLog @@ -0,0 +1,46 @@ +2006-06-08 Ilija Koco + + * cdl/hal_arm_mac7100_mac7100evb.cdl: + * include/plf_io.h: + * include/hal_platform_ints.h: + * include/hal_platform_setup.h: + * include/mac7100evb_misc.h: + * include/pkgconf/mlt_arm_mac7100_mac7100evb_rom.ldi: + * include/pkgconf/mlt_arm_mac7100_mac7100evb_rom.h: + * src/mac7100evb_misc.c: + New HAL added to support the Freescale MAC7100 board. + Adapted from MACE1 + + +//=========================================================================== +//####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 Nick Garnett +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/cdl/hal_arm_mac7100_mac7100evb.cdl b/packages/hal/arm/mac7100/mac7100evb/v2_0/cdl/hal_arm_mac7100_mac7100evb.cdl new file mode 100644 index 00000000..7a42964c --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/cdl/hal_arm_mac7100_mac7100evb.cdl @@ -0,0 +1,377 @@ + +# ==================================================================== +# +# hal_arm_mac7100_mac7100evb.cdl +# +# ARM MAC7100 MAC7100EVB HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2003 Nick Garnett +## Copyright (C) 2006 eCosCentric Ltd +## +## 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): Ilija Koco +# Contributors: +# Date: 2006-06-07 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_MAC7100_MAC7100EVB { + display "MAC7100EVB evaluation board HAL" + parent CYGPKG_HAL_ARM_MAC7100 + define_header hal_arm_mac7100_mac7100evb.h + include_dir cyg/hal + hardware + description " + The MAC7100EVB HAL package provides the support needed to run + eCos on the Freescale MAC7100EVB eval board." + + compile mac7100evb_misc.c + + requires { CYGHWR_HAL_ARM_MAC7100 == "MAC7111" } + requires { CYGNUM_PIT_CHAN_CLOCK_PRIORITY == + CYGNUM_KERNEL_COUNTERS_CLOCK_ISR_PRIORITY } + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " + puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H " + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "#define HAL_PLATFORM_CPU \"ARM7TDMI\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"Freescale MAC7100/MAC7100EVB\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + } + + cdl_component CYG_PIT_CLOCKS { + display "Real time clock configuration." + flavor none + description " + Periodic Interrupt Timer Module - PIT comprise of 11 timer + channels. RTI channel (PIT0) as well as PIT1 .. PIT4 can + generate interrupts and are eligible for the real time + clock." + + cdl_option CYGNUM_PIT_CHAN_CLOCK { + display "System CLOCK device" + flavor data + legal_values 0 to 4 + default_value 3 + requires {CYGNUM_PIT_CHAN_CLOCK != CYGNUM_PIT_CHAN_US} + description " + RTI (PIT0) and PIT1 .. PIT4 can be used for real time + clock. RTI is clocked by oscillator clock while + channels 1 to 4 by 1/2 system clock frequency. + Selection of RTI vs PIT1 .. PIT4 affects Real-time + clock period (see Real-time clock constants). NOTE: + Real time clock channel must not be the same as US + delay channel. + " + } + + cdl_option CYGNUM_PIT_CHAN_CLOCK_PRIORITY { + display "System clock's INTC priority" + flavor data + legal_values 0 to 15 + default_value 12 + description " + INTC has 16 interrupt levels: 0 (lowest) to 15 (highest). + " + } + + cdl_option CYGNUM_PIT_CHAN_US { + display "PIT channel for us delay" + flavor data + legal_values 0 to 4 + default_value 0 + requires {CYGNUM_PIT_CHAN_CLOCK != CYGNUM_PIT_CHAN_US} + description " + RTI is clocked by oscillator while channels PIT1 + .. PIT4 by half system clock frequency, hence RTI + should allow for larger maximal period. NOTE: US + delay channel must not be the same as real time clock + channel. + " + } + } + + cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants" + flavor none + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + default_value 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + default_value 100 + } + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + default_value (CYGNUM_PIT_CHAN_CLOCK !=0 ? \ + (CYGNUM_HAL_ARM_MAC7100_CLOCK_SPEED / 2 / CYGNUM_HAL_RTC_DENOMINATOR - 1) : \ + (CYGNUM_HAL_ARM_MAC7100_Q_FREQ / CYGNUM_HAL_RTC_DENOMINATOR - 1)) + } + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + calculated {"ROM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + Current MAC7100EVB port supports only ROM startup type." + } + + # Real-time clock/counter specifics + + cdl_component CYG_HAL_MAC7100_OSC { + display "System Clocks Module" + flavor none + + cdl_option CYGNUM_HAL_ARM_MAC7100_F_OSC { + display "FOSC - Oscillator clock" + flavor data + default_value 8000000 + } + + cdl_option CYGNUM_HAL_ARM_MAC7100_FDIV { + display "FDIV - Frequency divider for PLL" + flavor booldata + legal_values 0 to 16 + default_value 2 + description " + If enabled (FDIV != 0), + you set divider for PLL. + Then REFDV is calculated as REFDV=FDIV-1; + If disabled (FDIV == 0), + REFDV is calculated from FOSC so that referent frequency + for PLL is 500kHz. + SYNR is then derived from desired CPU clock, FOSC and REFDV. + " + } + } + + cdl_option CYGNUM_HAL_ARM_MAC7100_CLOCK_SPEED { + display "CPU clock - PLL frequency" + flavor data + default_value 48000000 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + legal_values 0 1 2 + default_value 2 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The MAC7100 MAC7100EVB board has two serial ports. This option + chooses which port will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The MAC7100 MAC7100EVB board has two serial ports. This option + chooses which port will be used for diagnostic output." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + flavor data + legal_values 9600 19200 38400 + default_value 38400 + description " + This option selects the baud rate used for the diagnostic port." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "GDB serial port baud rate" + flavor data + legal_values 9600 19200 38400 + default_value 38400 + description " + This option controls the baud rate used for the GDB connection." + } + + cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM" || + CYG_HAL_STARTUP == "ROMRAM" } + description " + Enable this option if this program is to be used as a ROM monitor, + i.e. applications will be loaded into RAM on the board, and this + ROM monitor may process exceptions or interrupts generated from the + application. This enables features such as utilizing a separate + interrupt stack when exceptions are generated." + } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM monitor. + This support changes various eCos semantics such as the encoding + of diagnostic output, or the overriding of hardware interrupt + vectors. + Firstly there is \"Generic\" support which prevents the HAL + from overriding the hardware vectors that it does not use, to + instead allow an installed ROM monitor to handle them. This is + the most basic support which is likely to be common to most + implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included in + the ROM monitor or boot ROM." + } + + cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { + display "Redboot HAL options" + flavor none + no_define + parent CYGPKG_REDBOOT + active_if CYGPKG_REDBOOT + description " + This option lists the target's requirements for a valid Redboot + configuration." + + cdl_option CYGBLD_BUILD_REDBOOT_BIN { + display "Build Redboot ROM binary image" + active_if CYGBLD_BUILD_REDBOOT + default_value 1 + no_define + description "This option enables the conversion of the Redboot ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + /bin/redboot.bin : /bin/redboot.elf + $(OBJCOPY) --strip-debug $< $(@:.bin=.img) + $(OBJCOPY) -O srec $< $(@:.bin=.srec) + $(OBJCOPY) -O binary $< $@ + } + + } + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + description " + Global build options including control over + compiler flags, linker flags and choice of toolchain." + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "arm-elf" } + description " + This option specifies the command prefix used when + invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -mbig-endian -mno-short-load-words -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -gdwarf-2 -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + description " + This option controls the global compiler flags which + are used to compile all packages by + default. Individual packages may define options which + override these global flags." + + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -mbig-endian -mno-short-load-words -Wl,--gc-sections -Wl,-static -gdwarf-2 -nostdlib" } + description " + This option controls the global linker flags. Individual + packages may define options which override these global flags." + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { (CYG_HAL_STARTUP == "RAM") ? "arm_mac7100_mac7100evb_ram" : + (CYG_HAL_STARTUP == "ROMRAM") ? "arm_mac7100_mac7100evb_romram" : + "arm_mac7100_mac7100evb_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { (CYG_HAL_STARTUP == "RAM") ? "" : + (CYG_HAL_STARTUP == "ROMRAM") ? "" : + "" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { (CYG_HAL_STARTUP == "RAM") ? "" : + (CYG_HAL_STARTUP == "ROMRAM") ? "" : + "" } + } + } +} diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/include/hal_platform_ints.h b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/hal_platform_ints.h new file mode 100644 index 00000000..e987a26c --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/hal_platform_ints.h @@ -0,0 +1,144 @@ +#ifndef CYGONCE_HAL_PLATFORM_INTS_H +#define CYGONCE_HAL_PLATFORM_INTS_H +//========================================================================== +// +// hal_platform_ints.h +// +// HAL Interrupt and clock assignments for MAC7100EVB +// +//========================================================================== +//####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 Nick Garnett +// Copyright (C) 2996 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-06-07 +// Purpose: Define Interrupt support +// Description: The interrupt specifics for the MAC7100EVB board/platform +// are defined here. +// +// Usage: #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#define CYGNUM_HAL_ISR_MIN 0 +#define CYGNUM_HAL_ISR_MAX 63 +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_ISR_MAX + 1) + +// INTC levels + +#define MAC7100_EDMA0_LEVEL (0) +#define MAC7100_EDMA1_LEVEL (0) +#define MAC7100_EDMA2_LEVEL (0) +#define MAC7100_EDMA3_LEVEL (0) +#define MAC7100_EDMA4_LEVEL (0) +#define MAC7100_EDMA5_LEVEL (0) +#define MAC7100_EDMA6_LEVEL (0) +#define MAC7100_EDMA7_LEVEL (0) +#define MAC7100_EDMA8_LEVEL (0) +#define MAC7100_EDMA9_LEVEL (0) +#define MAC7100_EDMA10_LEVEL (0) +#define MAC7100_EDMA11_LEVEL (0) +#define MAC7100_EDMA12_LEVEL (0) +#define MAC7100_EDMA13_LEVEL (0) +#define MAC7100_EDMA14_LEVEL (0) +#define MAC7100_EDMA15_LEVEL (0) +#define MAC7100_EDMA_Error_LEVEL (0) +#define MAC7100_MCM_SWT_LEVEL (0) +#define MAC7100_CRG_LEVEL (0) +#define MAC7100_PIT1_LEVEL (9) +#define MAC7100_PIT2_LEVEL (9) +#define MAC7100_PIT3_LEVEL (10) +#define MAC7100_PIT4_RTI_LEVEL (9) +#define MAC7100_VREG_LEVEL (4) +#define MAC7100_CAN_A_MB_LEVEL (4) +#define MAC7100_CAN_A_MB14_LEVEL (4) +#define MAC7100_CAN_A_Error_LEVEL (4) +#define MAC7100_CAN_B_MB_LEVEL (4) +#define MAC7100_CAN_B_MB14_LEVEL (4) +#define MAC7100_CAN_B_Error_LEVEL (4) +#define MAC7100_CAN_C_MB_LEVEL (4) +#define MAC7100_CAN_C_MB14_LEVEL (4) +#define MAC7100_CAN_C_Error_LEVEL (4) +#define MAC7100_CAN_D_MB_LEVEL (4) +#define MAC7100_CAN_D_MB14_LEVEL (4) +#define MAC7100_CAN_D_Error_LEVEL (4) +#define MAC7100_I2C_LEVEL (4) +#define MAC7100_DSPI_A_LEVEL (5) +#define MAC7100_DSPI_B_LEVEL (5) +#define MAC7100_ESCI_A_LEVEL (8) +#define MAC7100_ESCI_B_LEVEL (8) +#define MAC7100_ESCI_C_LEVEL (8) +#define MAC7100_ESCI_D_LEVEL (8) +#define MAC7100_EMIOS0_LEVEL (7) +#define MAC7100_EMIOS1_LEVEL (7) +#define MAC7100_EMIOS2_LEVEL (7) +#define MAC7100_EMIOS3_LEVEL (7) +#define MAC7100_EMIOS4_LEVEL (7) +#define MAC7100_EMIOS5_LEVEL (7) +#define MAC7100_EMIOS6_LEVEL (7) +#define MAC7100_EMIOS7_LEVEL (7) +#define MAC7100_EMIOS8_LEVEL (7) +#define MAC7100_EMIOS9_LEVEL (7) +#define MAC7100_EMIOS10_LEVEL (7) +#define MAC7100_EMIOS11_LEVEL (7) +#define MAC7100_EMIOS12_LEVEL (7) +#define MAC7100_EMIOS13_LEVEL (7) +#define MAC7100_EMIOS14_LEVEL (7) +#define MAC7100_EMIOS15_LEVEL (7) +#define MAC7100_ATD_LEVEL (11) +#define MAC7100_CFM_LEVEL (7) +#define MAC7100_PIM_LEVEL (11) +#define MAC7100_IRQ_LEVEL (12) +#define MAC7100_XIRQ_LEVEL (12) + +// The vector used by the Real time clock +#if CYGNUM_PIT_CHAN_CLOCK==0 +#define CYGNUM_HAL_INTERRUPT_RTC MAC7100_PIT4_RTI_IV +#else +#define CYGNUM_HAL_INTERRUPT_RTC (MAC7100_PIT1_IV+CYGNUM_PIT_CHAN_CLOCK-1) +#endif + +//---------------------------------------------------------------------------- +// Reset. +__externC void hal_mac7100_reset_cpu(void); +#define HAL_PLATFORM_RESET() hal_mac7100_reset_cpu() + +#define HAL_PLATFORM_RESET_ENTRY 0x01000000 + +#endif // CYGONCE_HAL_PLATFORM_INTS_H diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/include/hal_platform_setup.h b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/hal_platform_setup.h new file mode 100644 index 00000000..c2c0c768 --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/hal_platform_setup.h @@ -0,0 +1,133 @@ +#ifndef CYGONCE_HAL_PLATFORM_SETUP_H +#define CYGONCE_HAL_PLATFORM_SETUP_H + +//============================================================================= +// +// hal_platform_setup.h +// +// Platform specific support for HAL (assembly code) +// +//============================================================================= +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-06-07 +// Purpose: MAC7100EVB platform specific support routines +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include +#include +//=========================================================================== + + .macro _led y + ldr r0,=MAC7100_PIM_PORTDATA(MAC7100_PORT_F_OFFSET) + ldrh r1,[r0] + and r1,r1,#0x00ff + orr r1,r1,#(((~\y)&0xff)<<8) + strh r1,[r0] + .endm + + +// Initialize LED PORT +// Set appropriate peripheral pins + .macro _led_init + _led 0 // Set initial LED state. + mov r1, #MAC7100_PIM_DDR // Pin setting: Output+Low + ldr r0,=MAC7100_PIM_CONFIG(MAC7100_PORT_F_OFFSET, 8) // LED pin cfg + strh r1,[r0],#2 // LED: LSB ... + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 // LED: ... MSB + .endm + + +// Clock initilalization + .macro _pclock_init + _mac7100_setpll + .endm + +// Memory re-mapping + .macro _memory_remap + _mac7100_remap_single_chip + .endm + + +// Initialize paralel port + .macro _pio_init + .endm + + +#define CYGHWR_LED_MACRO _led \x + +//=========================================================================== + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + + .macro _setup + ldr r0,=VAE_MAC7100_FlashSecurity + _led_init + _memory_remap + _pclock_init + _pio_init + .endm + +#define CYGSEM_HAL_ROM_RESET_USES_JUMP + +#else + + .macro _setup + _led_init + _led 16 + _pclock_init + _pio_init + .endm + +#endif + +#define PLATFORM_SETUP1 _setup + +//----------------------------------------------------------------------------- +// end of hal_platform_setup.h +#endif // CYGONCE_HAL_PLATFORM_SETUP_H diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/include/mac7100evb_misc.h b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/mac7100evb_misc.h new file mode 100644 index 00000000..65f008a9 --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/mac7100evb_misc.h @@ -0,0 +1,67 @@ +#ifndef CYGONCE_HAL_MAC7100EVB_MISC_H +#define CYGONCE_HAL_MAC7100EVB_MISC_H +//============================================================================= +// +// mac7100evb_misc.h +// +// MAC7100EVB board specific functions +// +//============================================================================= +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-05-07 +// Purpose: MAC7100EVB board specific registers +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +void hal_mac7100evb_set_leds(int); +void hal_mac7100evb_led_on(int); +void hal_mac7100evb_led_off(int); +int hal_mac7100evb_get_leds(void); + +#define HAL_MAC7100_SET_LEDS(x) hal_mac7100evb_set_leds(x) +#define HAL_MAC7100_LED_ON(x) hal_mac7100evb_led_on(x) +#define HAL_MAC7100_LED_OFF(x) hal_mac7100evb_led_off(x) +#define HAL_MAC7100_GET_LEDS(x) hal_mac7100evb_get_leds(x) + +//----------------------------------------------------------------------------- +// end of mac7100evb_misc.h +#endif // CYGONCE_HAL_MAC7100EVB_MISC_H diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/include/pkgconf/mlt_arm_mac7100_mac7100evb_rom.h b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/pkgconf/mlt_arm_mac7100_mac7100evb_rom.h new file mode 100644 index 00000000..7cc23f8a --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/pkgconf/mlt_arm_mac7100_mac7100evb_rom.h @@ -0,0 +1,24 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +// Initially RAM is at 0x40000000 but we ramap to 0x0 +#define CYGMEM_REGION_ram (0x00000000) +#define CYGMEM_REGION_ram_SIZE (0x00008000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x20000000) +#define CYGMEM_REGION_rom_SIZE (0x80000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE \ + ((CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE) - \ + (size_t) CYG_LABEL_NAME (__heap1)) + diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/include/pkgconf/mlt_arm_mac7100_mac7100evb_rom.ldi b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/pkgconf/mlt_arm_mac7100_mac7100evb_rom.ldi new file mode 100644 index 00000000..2abf974d --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/pkgconf/mlt_arm_mac7100_mac7100evb_rom.ldi @@ -0,0 +1,39 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include + +MEMORY +{ + ram : ORIGIN = 0x00000000, LENGTH = 0x8000 + rom : ORIGIN = 0x20000000, LENGTH = 0x80000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_rom_vectors (rom, 0x20000000, LMA_EQ_VMA) + +// MAC7100 Flash Security +// Following section is manually added to address MAC7100 flash security area +// It should actually be something like this +// SECTION_sgfm_config (rom, 0x20000400, LMA_EQ_VMA) + + .mac7100_flash_security 0x20000400 : { KEEP (*(.mac7100_flash_security))} > rom + +// END MAC7100 Flash Security + + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + + SECTION_fixed_vectors (ram, 0x00000020, LMA_EQ_VMA) + SECTION_data (ram, ALIGN(0x4), FOLLOWING(.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/include/plf_io.h b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/plf_io.h new file mode 100644 index 00000000..134abca2 --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/include/plf_io.h @@ -0,0 +1,60 @@ +#ifndef CYGONCE_HAL_PLF_IO_H +#define CYGONCE_HAL_PLF_IO_H +//============================================================================= +// +// plf_io.h +// +// MAC7100EVB board specific registers +// +//============================================================================= +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-06-07 +// Purpose: MAC7100EVB board specific registers +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= +// On-chip device base addresses + +#define CYGARC_PHYSICAL_ADDRESS(_x_) + +#endif // CYGONCE_HAL_PLF_IO_H +//----------------------------------------------------------------------------- +// end of plf_io.h diff --git a/packages/hal/arm/mac7100/mac7100evb/v2_0/src/mac7100evb_misc.c b/packages/hal/arm/mac7100/mac7100evb/v2_0/src/mac7100evb_misc.c new file mode 100644 index 00000000..969f6905 --- /dev/null +++ b/packages/hal/arm/mac7100/mac7100evb/v2_0/src/mac7100evb_misc.c @@ -0,0 +1,102 @@ +//========================================================================== +// +// mac7100evb_misc.c +// +// HAL misc board support code for MAC7100EVB board +// +//========================================================================== +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-06-07 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include + +#include // base types +#include // low level i/o +#include // common registers +#include // platform registers +#include // mac7100evb misc functions + +void +hal_mac7100evb_set_leds(int val) +{ + HAL_WRITE_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_F_OFFSET), + ~((val<<8)&0xff00)); // turn all LEDs off +} + +void +hal_mac7100evb_led_on(int val) +{ + cyg_uint16 leds; + + // read old LED state + HAL_READ_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_F_OFFSET), leds); + leds&=~(1<<(8+val)); + // Write new state + HAL_WRITE_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_F_OFFSET), leds); +} + +void +hal_mac7100evb_led_off(int val) +{ + cyg_uint16 leds; + + // read old LED state + HAL_READ_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_F_OFFSET), leds); + leds|=1<<(8+val); + // Write new state + HAL_WRITE_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_F_OFFSET), leds); +} + +int +hal_mac7100evb_get_leds(void) +{ + cyg_uint16 leds = 0; + + // read old LED state + HAL_READ_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_F_OFFSET), leds); + return ~(leds>>8&0xFF); +} + +//-------------------------------------------------------------------------- +// EOF mac7100evb_misc.c diff --git a/packages/hal/arm/mac7100/mace1/v2_0/ChangeLog b/packages/hal/arm/mac7100/mace1/v2_0/ChangeLog new file mode 100644 index 00000000..1829bb07 --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/ChangeLog @@ -0,0 +1,52 @@ +2006-06-08 Ilija Koco + + * include/hal_platform_setup.h: PLL clock and memory remap + moved to hal_var_setup.h + * include/mace1_misc.h: LED macros added + +2006-05-24 Ilija Koco + + * cdl/hal_arm_mac7100_mace1.cdl: + * include/plf_io.h: + * include/hal_platform_ints.h: + * include/hal_platform_setup.h: + * include/mace1_misc.h: + * include/pkgconf/mlt_arm_mac7100_mace1_rom.ldi: + * include/pkgconf/mlt_arm_mac7100_mace1_rom.h: + * src/mace1_misc.c: + New HAL added to support the SIvA MACE1 board. Adapted from the + EB55 by Nick Garnett + + +//=========================================================================== +//####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 Nick Garnett +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/arm/mac7100/mace1/v2_0/cdl/hal_arm_mac7100_mace1.cdl b/packages/hal/arm/mac7100/mace1/v2_0/cdl/hal_arm_mac7100_mace1.cdl new file mode 100644 index 00000000..5d88d715 --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/cdl/hal_arm_mac7100_mace1.cdl @@ -0,0 +1,377 @@ + +# ==================================================================== +# +# hal_arm_mac7100_mace1.cdl +# +# ARM MAC7100 MACE1 HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2003 Nick Garnett +## Copyright (C) 2006 eCosCentric Ltd +## +## 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): Ilija Koco +# Contributors: +# Date: 2006-04-12 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_MAC7100_MACE1 { + display "MACE1 - MAC7100 eval board HAL" + parent CYGPKG_HAL_ARM_MAC7100 + define_header hal_arm_mac7100_mace1.h + include_dir cyg/hal + hardware + description " + The MACE1 HAL package provides the support needed to run + eCos on an MACE1 - MAC7100 eval board." + + compile mace1_misc.c + + requires { CYGHWR_HAL_ARM_MAC7100 == "MAC7121" } + requires { CYGNUM_PIT_CHAN_CLOCK_PRIORITY == + CYGNUM_KERNEL_COUNTERS_CLOCK_ISR_PRIORITY } + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " + puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H " + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "#define HAL_PLATFORM_CPU \"ARM7TDMI\"" + puts $::cdl_header "#define HAL_PLATFORM_BOARD \"Freescale MAC7100/MACE1\"" + puts $::cdl_header "#define HAL_PLATFORM_EXTRA \"\"" + } + + cdl_component CYG_PIT_CLOCKS { + display "Real time clock configuration." + flavor none + description " + Periodic Interrupt Timer Module - PIT comprizes 11 timer + channels. RTI channel (PIT0) as well as PIT1 .. PIT4 can + generate interrupts and are eligible for the real time + clock. " + + cdl_option CYGNUM_PIT_CHAN_CLOCK { + display "System CLOCK device" + flavor data + legal_values 0 to 4 + default_value 3 + requires {CYGNUM_PIT_CHAN_CLOCK != CYGNUM_PIT_CHAN_US} + description " + RTI (PIT0) and PIT1 .. PIT4 can be used for ral time + clock. RTI is clocked by oscillator clock while + channels 1 to 4 by 1/2 system clock frequency. + Selection of RTI vs PIT1 .. PIT4 affects Real-time + clock period (see Real-time clock constants). NOTE: + Real time clock channel must not be the same as US + delay channel. + " + } + + cdl_option CYGNUM_PIT_CHAN_CLOCK_PRIORITY { + display "System clock's INTC priority" + flavor data + legal_values 0 to 15 + default_value 12 + description " + INTC has 16 interrupt levels: 0 (lowest) to 15 (highest). + " + } + + cdl_option CYGNUM_PIT_CHAN_US { + display "PIT channel for us delay" + flavor data + legal_values 0 to 4 + default_value 0 + requires {CYGNUM_PIT_CHAN_CLOCK != CYGNUM_PIT_CHAN_US} + description " + RTI is clocked by oscillator while channels PIT1 + .. PIT4 by half system clock frequency, hence RTI + should allow for larger maximal period. NOTE: US + delay channel must not be the same as real time clock + channel. + " + } + } + + cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants" + flavor none + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + default_value 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + default_value 100 + } + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + default_value (CYGNUM_PIT_CHAN_CLOCK !=0 ? \ + (CYGNUM_HAL_ARM_MAC7100_CLOCK_SPEED / 2 / CYGNUM_HAL_RTC_DENOMINATOR - 1) : \ + (CYGNUM_HAL_ARM_MAC7100_Q_FREQ / CYGNUM_HAL_RTC_DENOMINATOR - 1)) + } + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + calculated {"ROM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + Current MACE1 port supports only ROM startup type." + } + + # Real-time clock/counter specifics + + cdl_component CYG_HAL_MAC7100_OSC { + display "System Clocks Module" + flavor none + + cdl_option CYGNUM_HAL_ARM_MAC7100_F_OSC { + display "FOSC - Oscillator clock" + flavor data + default_value 8000000 + } + + cdl_option CYGNUM_HAL_ARM_MAC7100_FDIV { + display "FDIV - Frequency divider for PLL" + flavor booldata + legal_values 0 to 16 + default_value 2 + description " + If enabled (FDIV != 0), + you set divider for PLL. + Then REFDV is calculated as REFDV=FDIV-1; + If disabled (FDIV == 0), + REFDV is calculated from FOSC so that referent frequency + for PLL is 500kHz. + SYNR is then derived from desired CPU clock, FOSC and REFDV. + " + } + } + + cdl_option CYGNUM_HAL_ARM_MAC7100_CLOCK_SPEED { + display "CPU clock - PLL frequency" + flavor data + default_value 48000000 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + legal_values 0 1 2 + default_value 2 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The MAC7100 MACE1 board has two serial ports. This option + chooses which port will be used to connect to a host + running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The MAC7100 MACE1 board has two serial ports. This option + chooses which port will be used for diagnostic output." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + flavor data + legal_values 9600 19200 38400 + default_value 38400 + description " + This option selects the baud rate used for the diagnostic port." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "GDB serial port baud rate" + flavor data + legal_values 9600 19200 38400 + default_value 38400 + description " + This option controls the baud rate used for the GDB connection." + } + + cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM" || + CYG_HAL_STARTUP == "ROMRAM" } + description " + Enable this option if this program is to be used as a ROM monitor, + i.e. applications will be loaded into RAM on the board, and this + ROM monitor may process exceptions or interrupts generated from the + application. This enables features such as utilizing a separate + interrupt stack when exceptions are generated." + } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for different varieties of ROM monitor. + This support changes various eCos semantics such as the encoding + of diagnostic output, or the overriding of hardware interrupt + vectors. + Firstly there is \"Generic\" support which prevents the HAL + from overriding the hardware vectors that it does not use, to + instead allow an installed ROM monitor to handle them. This is + the most basic support which is likely to be common to most + implementations of ROM monitor. + \"GDB_stubs\" provides support when GDB stubs are included in + the ROM monitor or boot ROM." + } + + cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { + display "Redboot HAL options" + flavor none + no_define + parent CYGPKG_REDBOOT + active_if CYGPKG_REDBOOT + description " + This option lists the target's requirements for a valid Redboot + configuration." + + cdl_option CYGBLD_BUILD_REDBOOT_BIN { + display "Build Redboot ROM binary image" + active_if CYGBLD_BUILD_REDBOOT + default_value 1 + no_define + description "This option enables the conversion of the Redboot ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + /bin/redboot.bin : /bin/redboot.elf + $(OBJCOPY) --strip-debug $< $(@:.bin=.img) + $(OBJCOPY) -O srec $< $(@:.bin=.srec) + $(OBJCOPY) -O binary $< $@ + } + + } + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + description " + Global build options including control over + compiler flags, linker flags and choice of toolchain." + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "arm-elf" } + description " + This option specifies the command prefix used when + invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -mbig-endian -mno-short-load-words -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -gdwarf-2 -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + description " + This option controls the global compiler flags which + are used to compile all packages by + default. Individual packages may define options which + override these global flags." + + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { (CYGHWR_THUMB ? "-mthumb " : "") . (CYGBLD_ARM_ENABLE_THUMB_INTERWORK ? "-mthumb-interwork " : "") . "-mcpu=arm7tdmi -mbig-endian -mno-short-load-words -Wl,--gc-sections -Wl,-static -gdwarf-2 -nostdlib" } + description " + This option controls the global linker flags. Individual + packages may define options which override these global flags." + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { (CYG_HAL_STARTUP == "RAM") ? "arm_mac7100_mace1_ram" : + (CYG_HAL_STARTUP == "ROMRAM") ? "arm_mac7100_mace1_romram" : + "arm_mac7100_mace1_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { (CYG_HAL_STARTUP == "RAM") ? "" : + (CYG_HAL_STARTUP == "ROMRAM") ? "" : + "" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { (CYG_HAL_STARTUP == "RAM") ? "" : + (CYG_HAL_STARTUP == "ROMRAM") ? "" : + "" } + } + } +} diff --git a/packages/hal/arm/mac7100/mace1/v2_0/include/hal_platform_ints.h b/packages/hal/arm/mac7100/mace1/v2_0/include/hal_platform_ints.h new file mode 100644 index 00000000..30e9069e --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/include/hal_platform_ints.h @@ -0,0 +1,144 @@ +#ifndef CYGONCE_HAL_PLATFORM_INTS_H +#define CYGONCE_HAL_PLATFORM_INTS_H +//========================================================================== +// +// hal_platform_ints.h +// +// HAL Interrupt and clock assignments for MAC7100/MACE1 +// +//========================================================================== +//####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 Nick Garnett +// Copyright (C) 2996 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-04-13 +// Purpose: Define Interrupt support +// Description: The interrupt specifics for the MAC7100/MACE1 board/platform +// are defined here. +// +// Usage: #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#define CYGNUM_HAL_ISR_MIN 0 +#define CYGNUM_HAL_ISR_MAX 63 +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_ISR_MAX + 1) + +// INTC levels + +#define MAC7100_EDMA0_LEVEL (0) +#define MAC7100_EDMA1_LEVEL (0) +#define MAC7100_EDMA2_LEVEL (0) +#define MAC7100_EDMA3_LEVEL (0) +#define MAC7100_EDMA4_LEVEL (0) +#define MAC7100_EDMA5_LEVEL (0) +#define MAC7100_EDMA6_LEVEL (0) +#define MAC7100_EDMA7_LEVEL (0) +#define MAC7100_EDMA8_LEVEL (0) +#define MAC7100_EDMA9_LEVEL (0) +#define MAC7100_EDMA10_LEVEL (0) +#define MAC7100_EDMA11_LEVEL (0) +#define MAC7100_EDMA12_LEVEL (0) +#define MAC7100_EDMA13_LEVEL (0) +#define MAC7100_EDMA14_LEVEL (0) +#define MAC7100_EDMA15_LEVEL (0) +#define MAC7100_EDMA_Error_LEVEL (0) +#define MAC7100_MCM_SWT_LEVEL (0) +#define MAC7100_CRG_LEVEL (0) +#define MAC7100_PIT1_LEVEL (9) +#define MAC7100_PIT2_LEVEL (9) +#define MAC7100_PIT3_LEVEL (10) +#define MAC7100_PIT4_RTI_LEVEL (9) +#define MAC7100_VREG_LEVEL (4) +#define MAC7100_CAN_A_MB_LEVEL (4) +#define MAC7100_CAN_A_MB14_LEVEL (4) +#define MAC7100_CAN_A_Error_LEVEL (4) +#define MAC7100_CAN_B_MB_LEVEL (4) +#define MAC7100_CAN_B_MB14_LEVEL (4) +#define MAC7100_CAN_B_Error_LEVEL (4) +#define MAC7100_CAN_C_MB_LEVEL (4) +#define MAC7100_CAN_C_MB14_LEVEL (4) +#define MAC7100_CAN_C_Error_LEVEL (4) +#define MAC7100_CAN_D_MB_LEVEL (4) +#define MAC7100_CAN_D_MB14_LEVEL (4) +#define MAC7100_CAN_D_Error_LEVEL (4) +#define MAC7100_I2C_LEVEL (4) +#define MAC7100_DSPI_A_LEVEL (5) +#define MAC7100_DSPI_B_LEVEL (5) +#define MAC7100_ESCI_A_LEVEL (8) +#define MAC7100_ESCI_B_LEVEL (8) +#define MAC7100_ESCI_C_LEVEL (8) +#define MAC7100_ESCI_D_LEVEL (8) +#define MAC7100_EMIOS0_LEVEL (7) +#define MAC7100_EMIOS1_LEVEL (7) +#define MAC7100_EMIOS2_LEVEL (7) +#define MAC7100_EMIOS3_LEVEL (7) +#define MAC7100_EMIOS4_LEVEL (7) +#define MAC7100_EMIOS5_LEVEL (7) +#define MAC7100_EMIOS6_LEVEL (7) +#define MAC7100_EMIOS7_LEVEL (7) +#define MAC7100_EMIOS8_LEVEL (7) +#define MAC7100_EMIOS9_LEVEL (7) +#define MAC7100_EMIOS10_LEVEL (7) +#define MAC7100_EMIOS11_LEVEL (7) +#define MAC7100_EMIOS12_LEVEL (7) +#define MAC7100_EMIOS13_LEVEL (7) +#define MAC7100_EMIOS14_LEVEL (7) +#define MAC7100_EMIOS15_LEVEL (7) +#define MAC7100_ATD_LEVEL (11) +#define MAC7100_CFM_LEVEL (7) +#define MAC7100_PIM_LEVEL (11) +#define MAC7100_IRQ_LEVEL (12) +#define MAC7100_XIRQ_LEVEL (12) + +// The vector used by the Real time clock +#if CYGNUM_PIT_CHAN_CLOCK==0 +#define CYGNUM_HAL_INTERRUPT_RTC MAC7100_PIT4_RTI_IV +#else +#define CYGNUM_HAL_INTERRUPT_RTC (MAC7100_PIT1_IV+CYGNUM_PIT_CHAN_CLOCK-1) +#endif + +//---------------------------------------------------------------------------- +// Reset. +__externC void hal_mac7100_reset_cpu(void); +#define HAL_PLATFORM_RESET() hal_mac7100_reset_cpu() + +#define HAL_PLATFORM_RESET_ENTRY 0x01000000 + +#endif // CYGONCE_HAL_PLATFORM_INTS_H diff --git a/packages/hal/arm/mac7100/mace1/v2_0/include/hal_platform_setup.h b/packages/hal/arm/mac7100/mace1/v2_0/include/hal_platform_setup.h new file mode 100644 index 00000000..fd62e62b --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/include/hal_platform_setup.h @@ -0,0 +1,133 @@ +#ifndef CYGONCE_HAL_PLATFORM_SETUP_H +#define CYGONCE_HAL_PLATFORM_SETUP_H + +//============================================================================= +// +// hal_platform_setup.h +// +// Platform specific support for HAL (assembly code) +// +//============================================================================= +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-03-12 +// Purpose: MAC7100/MACE1 platform specific support routines +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include +#include +//=========================================================================== + + .macro _led y + ldr r0,=MAC7100_PIM_PORTDATA(MAC7100_PORT_A_OFFSET) + ldrh r1,[r0] + and r1,r1,#0x00ff + add r1,r1,#(\y<<8) + strh r1,[r0] + .endm + + +// Initialize LED PORT +// Set appropriate peripheral pins + .macro _led_init + mov r1, #MAC7100_PIM_DDR // Pin setting: Output+Low + ldr r0,=MAC7100_PIM_CONFIG(MAC7100_PORT_A_OFFSET, 8) // LED pin cfg + strh r1,[r0],#2 // LED: LSB ... + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 + strh r1,[r0],#2 // LED: MSB ... + _led 0 // Set initial LED state. + .endm + + +// Clock initilalization + .macro _pclock_init + _mac7100_setpll + .endm + +// Memory re-mapping + .macro _memory_remap + _mac7100_remap_single_chip + .endm + + +// Initialize paralel port + .macro _pio_init + .endm + + +#define CYGHWR_LED_MACRO _led \x + +//=========================================================================== + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + + .macro _setup + ldr r0,=VAE_MAC7100_FlashSecurity + _led_init + _memory_remap + _pclock_init + _pio_init + .endm + +#define CYGSEM_HAL_ROM_RESET_USES_JUMP + +#else + + .macro _setup + _led_init + _led 16 + _pclock_init + _pio_init + .endm + +#endif + +#define PLATFORM_SETUP1 _setup + +//----------------------------------------------------------------------------- +// end of hal_platform_setup.h +#endif // CYGONCE_HAL_PLATFORM_SETUP_H diff --git a/packages/hal/arm/mac7100/mace1/v2_0/include/mace1_misc.h b/packages/hal/arm/mac7100/mace1/v2_0/include/mace1_misc.h new file mode 100644 index 00000000..260bdcc7 --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/include/mace1_misc.h @@ -0,0 +1,68 @@ +#ifndef CYGONCE_HAL_MACE1_MISC_H +#define CYGONCE_HAL_MACE1_MISC_H +//============================================================================= +// +// mace1_misc.h +// +// MACE1 board specific functions +// +//============================================================================= +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-02-03 +// Purpose: MACE1 board specific registers +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +void hal_mace1_set_leds(int); +void hal_mace1_led_on(int); +void hal_mace1_led_off(int); +int hal_mace1_get_leds(void); + +#define HAL_MAC7100_SET_LEDS(x) hal_mace1_set_leds(x) +#define HAL_MAC7100_LED_ON(x) hal_mace1_led_on(x) +#define HAL_MAC7100_LED_OFF(x) hal_mace1_led_off(x) +#define HAL_MAC7100_GET_LEDS(x) hal_mace1_get_leds(x) + + +//----------------------------------------------------------------------------- +// end of mace1_misc.h +#endif // CYGONCE_HAL_MACE1_MISC_H diff --git a/packages/hal/arm/mac7100/mace1/v2_0/include/pkgconf/mlt_arm_mac7100_mace1_rom.h b/packages/hal/arm/mac7100/mace1/v2_0/include/pkgconf/mlt_arm_mac7100_mace1_rom.h new file mode 100644 index 00000000..7cc23f8a --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/include/pkgconf/mlt_arm_mac7100_mace1_rom.h @@ -0,0 +1,24 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +// Initially RAM is at 0x40000000 but we ramap to 0x0 +#define CYGMEM_REGION_ram (0x00000000) +#define CYGMEM_REGION_ram_SIZE (0x00008000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#define CYGMEM_REGION_rom (0x20000000) +#define CYGMEM_REGION_rom_SIZE (0x80000) +#define CYGMEM_REGION_rom_ATTR (CYGMEM_REGION_ATTR_R) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE \ + ((CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE) - \ + (size_t) CYG_LABEL_NAME (__heap1)) + diff --git a/packages/hal/arm/mac7100/mace1/v2_0/include/pkgconf/mlt_arm_mac7100_mace1_rom.ldi b/packages/hal/arm/mac7100/mace1/v2_0/include/pkgconf/mlt_arm_mac7100_mace1_rom.ldi new file mode 100644 index 00000000..2abf974d --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/include/pkgconf/mlt_arm_mac7100_mace1_rom.ldi @@ -0,0 +1,39 @@ +// eCos memory layout - Wed Apr 11 13:49:55 2001 + +// This is a generated file - do not edit + +#include + +MEMORY +{ + ram : ORIGIN = 0x00000000, LENGTH = 0x8000 + rom : ORIGIN = 0x20000000, LENGTH = 0x80000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_rom_vectors (rom, 0x20000000, LMA_EQ_VMA) + +// MAC7100 Flash Security +// Following section is manually added to address MAC7100 flash security area +// It should actually be something like this +// SECTION_sgfm_config (rom, 0x20000400, LMA_EQ_VMA) + + .mac7100_flash_security 0x20000400 : { KEEP (*(.mac7100_flash_security))} > rom + +// END MAC7100 Flash Security + + SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (rom, ALIGN (0x4), LMA_EQ_VMA) + + SECTION_fixed_vectors (ram, 0x00000020, LMA_EQ_VMA) + SECTION_data (ram, ALIGN(0x4), FOLLOWING(.gcc_except_table)) + SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff --git a/packages/hal/arm/mac7100/mace1/v2_0/include/plf_io.h b/packages/hal/arm/mac7100/mace1/v2_0/include/plf_io.h new file mode 100644 index 00000000..98f8e08b --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/include/plf_io.h @@ -0,0 +1,60 @@ +#ifndef CYGONCE_HAL_PLF_IO_H +#define CYGONCE_HAL_PLF_IO_H +//============================================================================= +// +// plf_io.h +// +// MACE1 board specific registers +// +//============================================================================= +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-02-03 +// Purpose: MACE1 board specific registers +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= +// On-chip device base addresses + +#define CYGARC_PHYSICAL_ADDRESS(_x_) + +#endif // CYGONCE_HAL_PLF_IO_H +//----------------------------------------------------------------------------- +// end of plf_io.h diff --git a/packages/hal/arm/mac7100/mace1/v2_0/src/mace1_misc.c b/packages/hal/arm/mac7100/mace1/v2_0/src/mace1_misc.c new file mode 100644 index 00000000..7e827bae --- /dev/null +++ b/packages/hal/arm/mac7100/mace1/v2_0/src/mace1_misc.c @@ -0,0 +1,102 @@ +//========================================================================== +// +// mace1_misc.c +// +// HAL misc board support code for MACE1 board +// +//========================================================================== +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-04-12 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include + +#include // base types +#include // low level i/o +#include // common registers +#include // platform registers +#include // mace1 misc functions + +void +hal_mace1_set_leds(int val) +{ + HAL_WRITE_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_A_OFFSET), + ((val<<8)&0xff00)); // turn all LEDs off +} + +void +hal_mace1_led_on(int val) +{ + cyg_uint16 leds; + + // read old LED state + HAL_READ_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_A_OFFSET), leds); + leds|=1<<(8+val); + // Write new state + HAL_WRITE_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_A_OFFSET), leds); +} + +void +hal_mace1_led_off(int val) +{ + cyg_uint16 leds; + + // read old LED state + HAL_READ_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_A_OFFSET), leds); + leds&=~(1<<(8+val)); + // Write new state + HAL_WRITE_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_A_OFFSET), leds); +} + +int +hal_mace1_get_leds(void) +{ + cyg_uint16 leds = 0; + + // read old LED state + HAL_READ_UINT16(MAC7100_PIM_PORTDATA(MAC7100_PORT_A_OFFSET), leds); + return (leds>>8)&0xFF; +} + +//-------------------------------------------------------------------------- +// EOF mace1_misc.c diff --git a/packages/hal/arm/mac7100/var/v2_0/ChangeLog b/packages/hal/arm/mac7100/var/v2_0/ChangeLog new file mode 100644 index 00000000..07e06e03 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/ChangeLog @@ -0,0 +1,61 @@ +2007-01-10 Ilija Koco + + * hal_arm_mac7100.cdl: added property + "requires CYGPKG_IO_SERIAL_FREESCALE_ESCI_H" + +2006-08-08 Ilija Koco + + * var_io.h: Freescale eSCI platform dependent clock related macros + moved here from ser_esci.h + +2006-06-08 Ilija Koco + + * hal_var_setup.h: (new) Assembly macros shared between targets. + * cdl/hal_arm_mac7100.cdl: some defaults changed in favour of + MAC7100EVB + +2006-05-24 Ilija Koco + + * cdl/hal_arm_mac7100.cdl: + * include/hal_cache.h: + * include/hal_diag.h: + * include/mac7100_misc.h: + * include/plf_stub.h: unchanged from AT91 + * include/var_arch.h: + * include/var_io.h: + * src/flash_security.S: + * src/hal_diag.c: + * src/mac7100_misc.c + New variant port - based on at91 variant by Gary Thomas + +//=========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/arm/mac7100/var/v2_0/cdl/hal_arm_mac7100.cdl b/packages/hal/arm/mac7100/var/v2_0/cdl/hal_arm_mac7100.cdl new file mode 100644 index 00000000..f7eb6f86 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/cdl/hal_arm_mac7100.cdl @@ -0,0 +1,128 @@ +# ==================================================================== +# +# hal_arm_mac7100.cdl +# +# Freescale MAC7100 HAL package configuration data +# +# ==================================================================== +#####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 Nick Garnett +## Copyright (C) 2006 eCosCentric Ltd +## +## 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): Ilija Koco +# Contributors: +# Date: 2006-02-03 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_ARM_MAC7100 { + display "Freescale MAC7100 variant HAL" + parent CYGPKG_HAL_ARM + define_header hal_arm_mac7100.h + include_dir cyg/hal + hardware + description " + The MAC7100 HAL package provides the support needed to run + eCos on Freescale MAC7100 based targets." + + compile flash_security.S hal_diag.c mac7100_misc.c + + implements CYGINT_HAL_DEBUG_GDB_STUBS + implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + implements CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT + implements CYGINT_HAL_ARM_ARCH_ARM7 + implements CYGINT_HAL_ARM_THUMB_ARCH + implements CYGINT_HAL_ARM_BIGENDIAN + + requires CYGHWR_HAL_ARM_BIGENDIAN == 1 + + requires CYGPKG_IO_SERIAL_FREESCALE_ESCI_H + + # Let the architectural HAL see this variant's files + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_ARM_VAR_IO_H" + puts $::cdl_system_header "#define CYGBLD_HAL_ARM_VAR_ARCH_H" + } + + cdl_option CYGHWR_HAL_ARM_MAC7100 { + display "MAC7100 variant used" + flavor data + default_value {"MAC7111"} + legal_values {"MAC7111" "MAC7121" "MAC7116" } + description " + The MAC7100 microcontroller family has several variants, + the main differences being the amount of on-chip SRAM, + peripherals and their layout. This option allows the + platform HALs to select the specific microcontroller being + used." + } + + cdl_option CYGHWR_HAL_ARM_MAC7100_FIQ { + display "handle FIQ as an IRQ" + flavor bool + default_value 0 + description " + Enable this option if you need to handle FIQ interrupts in the + normal way, i.e. a FIQ interrupt will be treated as a normal IRQ + using the highest priority + " + } + + cdl_option CYGHWR_HAL_ARM_MAC7100_INTC_FIQDEF { + display "Set FIQDEF" + flavor data + default_value CYGHWR_HAL_ARM_MAC7100_FIQ ? 14 : 16 + legal_values 0 to 32 + description " + Set maximum level that shall be routed to IRQ. + " + } + + cdl_option CYGHWR_HAL_ARM_MAC7100_INTC_EMASK { + display "enable INTC to automatically handle CLMASK" + flavor data + default_value 0x20 + legal_values 0x00 0x20 + description " + Enable this option if you need INTC to automatically mask + lower level IRQ. + + - 0x00 - disable + - 0x20 - enable + + " + } +} diff --git a/packages/hal/arm/mac7100/var/v2_0/include/hal_cache.h b/packages/hal/arm/mac7100/var/v2_0/include/hal_cache.h new file mode 100644 index 00000000..3f0c0c7d --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/include/hal_cache.h @@ -0,0 +1,189 @@ +#ifndef CYGONCE_HAL_CACHE_H +#define CYGONCE_HAL_CACHE_H + +//============================================================================= +// +// hal_cache.h +// +// HAL cache control API +// +//============================================================================= +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, gthomas +// Contributors: nickg, gthomas +// Date: 1998-09-28 +// Purpose: Cache control API +// Description: The macros defined here provide the HAL APIs for handling +// cache control operations. +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +//----------------------------------------------------------------------------- +// Cache dimensions + +// Data cache +//#define HAL_DCACHE_SIZE 0 // Size of data cache in bytes +//#define HAL_DCACHE_LINE_SIZE 0 // Size of a data cache line +//#define HAL_DCACHE_WAYS 0 // Associativity of the cache + +// Instruction cache +//#define HAL_ICACHE_SIZE 0 // Size of cache in bytes +//#define HAL_ICACHE_LINE_SIZE 0 // Size of a cache line +//#define HAL_ICACHE_WAYS 0 // Associativity of the cache + +//#define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS)) +//#define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS)) + +//----------------------------------------------------------------------------- +// Global control of data cache + +// Enable the data cache +#define HAL_DCACHE_ENABLE() + +// Disable the data cache +#define HAL_DCACHE_DISABLE() + +// Invalidate the entire cache +#define HAL_DCACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_DCACHE_SYNC() + +// Purge contents of data cache +#define HAL_DCACHE_PURGE_ALL() + +// Query the state of the data cache (does not affect the caching) +#define HAL_DCACHE_IS_ENABLED(_state_) \ + CYG_MACRO_START \ + (_state_) = 0; \ + CYG_MACRO_END + +// Set the data cache refill burst size +//#define HAL_DCACHE_BURST_SIZE(_size_) + +// Set the data cache write mode +//#define HAL_DCACHE_WRITE_MODE( _mode_ ) + +//#define HAL_DCACHE_WRITETHRU_MODE 0 +//#define HAL_DCACHE_WRITEBACK_MODE 1 + +// Load the contents of the given address range into the data cache +// and then lock the cache so that it stays there. +//#define HAL_DCACHE_LOCK(_base_, _size_) + +// Undo a previous lock operation +//#define HAL_DCACHE_UNLOCK(_base_, _size_) + +// Unlock entire cache +//#define HAL_DCACHE_UNLOCK_ALL() + +//----------------------------------------------------------------------------- +// Data cache line control + +// Allocate cache lines for the given address range without reading its +// contents from memory. +//#define HAL_DCACHE_ALLOCATE( _base_ , _size_ ) + +// Write dirty cache lines to memory and invalidate the cache entries +// for the given address range. +//#define HAL_DCACHE_FLUSH( _base_ , _size_ ) + +// Invalidate cache lines in the given range without writing to memory. +//#define HAL_DCACHE_INVALIDATE( _base_ , _size_ ) + +// Write dirty cache lines to memory for the given address range. +//#define HAL_DCACHE_STORE( _base_ , _size_ ) + +// Preread the given range into the cache with the intention of reading +// from it later. +//#define HAL_DCACHE_READ_HINT( _base_ , _size_ ) + +// Preread the given range into the cache with the intention of writing +// to it later. +//#define HAL_DCACHE_WRITE_HINT( _base_ , _size_ ) + +// Allocate and zero the cache lines associated with the given range. +//#define HAL_DCACHE_ZERO( _base_ , _size_ ) + +//----------------------------------------------------------------------------- +// Global control of Instruction cache + +// Enable the instruction cache +#define HAL_ICACHE_ENABLE() + +// Disable the instruction cache +#define HAL_ICACHE_DISABLE() + +// Invalidate the entire cache +#define HAL_ICACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_ICACHE_SYNC() + +// Query the state of the instruction cache (does not affect the caching) +#define HAL_ICACHE_IS_ENABLED(_state_) \ + CYG_MACRO_START \ + (_state_) = 0; \ + CYG_MACRO_END + +// Set the instruction cache refill burst size +//#define HAL_ICACHE_BURST_SIZE(_size_) + +// Load the contents of the given address range into the instruction cache +// and then lock the cache so that it stays there. +//#define HAL_ICACHE_LOCK(_base_, _size_) + +// Undo a previous lock operation +//#define HAL_ICACHE_UNLOCK(_base_, _size_) + +// Unlock entire cache +//#define HAL_ICACHE_UNLOCK_ALL() + +//----------------------------------------------------------------------------- +// Instruction cache line control + +// Invalidate cache lines in the given range without writing to memory. +//#define HAL_ICACHE_INVALIDATE( _base_ , _size_ ) + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_CACHE_H +// End of hal_cache.h diff --git a/packages/hal/arm/mac7100/var/v2_0/include/hal_diag.h b/packages/hal/arm/mac7100/var/v2_0/include/hal_diag.h new file mode 100644 index 00000000..f3a49223 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/include/hal_diag.h @@ -0,0 +1,81 @@ +#ifndef CYGONCE_HAL_DIAG_H +#define CYGONCE_HAL_DIAG_H + +//============================================================================= +// +// hal_diag.h +// +// HAL Support for Kernel Diagnostic Routines +// +//============================================================================= +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov, gthomas, tkoeller, ilijak +// Date: 2001-07-12 +// Purpose: HAL Support for Kernel Diagnostic Routines +// Description: Diagnostic routines for use during kernel development. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +#include + +#include + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + +//----------------------------------------------------------------------------- +// LED +externC void hal_diag_led(int mask); + +//----------------------------------------------------------------------------- +// delay + +externC void hal_delay_us(cyg_int32 usecs); +#define HAL_DELAY_US(n) hal_delay_us(n); + +//----------------------------------------------------------------------------- +// reset + +extern void hal_mac7100_reset_cpu(void); + +//----------------------------------------------------------------------------- +// end of hal_diag.h +#endif // CYGONCE_HAL_DIAG_H diff --git a/packages/hal/arm/mac7100/var/v2_0/include/hal_var_setup.h b/packages/hal/arm/mac7100/var/v2_0/include/hal_var_setup.h new file mode 100644 index 00000000..7ac79f11 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/include/hal_var_setup.h @@ -0,0 +1,140 @@ +#ifndef CYGONCE_HAL_VAR_SETUP_H +#define CYGONCE_HAL_VAR_SETUP_H + +//============================================================================= +// +// hal_var_setup.h +// +// Variant specific support for HAL (assembly code) +// +//============================================================================= +//####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 Nick Garnett +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-06-05 +// Purpose: MAC7100 variant specific support routines +// Description: +// Usage: in include following: +// #include +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +// Clock initilalization +// Initialize PLL +#if defined(CYGNUM_HAL_ARM_MAC7100_FDIV) // Divider set by user. +# define MAC7100_CRG_REFDV_VAL (CYGNUM_HAL_ARM_MAC7100_FDIV-1) +#else // Divider calculated. + //NOTE: works for f_osc <= 8MHz +# define MAC7100_CRG_REFDV_VAL (((CYGNUM_HAL_ARM_MAC7100_F_OSC/500000) - 1) & 0x0F) // 15 (1) +#endif +#define MAC7100_CRG_SYNR_VAL (CYGNUM_HAL_ARM_MAC7100_CLOCK_SPEED / 2 / \ + (CYGNUM_HAL_ARM_MAC7100_F_OSC / (MAC7100_CRG_REFDV_VAL+1))-1) // 47 (5) + +#define MAC7100_CRG_PLLCTL_VAL \ + (MAC7100_CRG_CME|MAC7100_CRG_PLLON|MAC7100_CRG_AUTO| \ + MAC7100_CRG_ACQ|MAC7100_CRG_SCME) +#define MAC7100_CRG_CLKSEL_VAL (MAC7100_CRG_PLLSEL) + + .macro _mac7100_setpll + ldr r2,=MAC7100_CRG_BASE + mov r3,#0 + // Disable clock interrupts + strb r3,[r2,#(MAC7100_CRG_CRGINT-MAC7100_CRG_BASE)] + // DeSelect PLL clock + mov r3,#MAC7100_CRG_REFDV_VAL + // Reference Divider reg. + strb r3,[r2,#(MAC7100_CRG_REFDV-MAC7100_CRG_BASE)] + mov r3,#MAC7100_CRG_SYNR_VAL + // Synthesizer register + strb r3,[r2,#(MAC7100_CRG_SYNR-MAC7100_CRG_BASE)] + mov r3,#MAC7100_CRG_PLLCTL_VAL + // PLL control register + strb r3,[r2,#(MAC7100_CRG_PLLCTL-MAC7100_CRG_BASE)] + // Wait PLL lock <-----------------------------------< +1: ldrb r3,[r2,#(MAC7100_CRG_CRGFLG-MAC7100_CRG_BASE)] + tst r3,#MAC7100_CRG_LOCK + bne 2f // PLL locked, GO ON ---------->> + b 1b // Still waiting for PLL lock ------------> +2: mov r3,#MAC7100_CRG_CLKSEL_VAL // <<-------<< + // Select PLL clock + strb r3,[r2,#(MAC7100_CRG_CLKSEL-MAC7100_CRG_BASE)] + mov r3,#0 + strb r3,[r2,#(MAC7100_CRG_BDMCTL-MAC7100_CRG_BASE)] // Set CRG BDMCTL + mov r3,r3 + .endm + +// Memory re-mapping for single chip configuration +// Re-map internal memory so that vectors can reside in RAM. +// RAM base 0x00000000 (as well as 0x40000000) +// Flash base 0x20000000 + .macro _mac7100_remap_single_chip + _led 1 + ldr r1, _mac7100_teleport + ldr r0, [r1] //AAMR Register + + mvn r4, #0xf0000000 // 1.Copy telepoter to RAM + ldr r2, _mac7100_teleport+4 // TelePorter + ldr r3, _mac7100_teleport+8 // TelePort (TelePorter end) + and r2,r2,r4 + and r3,r3,r4 + mov r4, #0x40000000 // RAM address +1: // Copy teleporter: // copying teleporter <---< + ldr r5,[r2],#4 + str r5,[r4],#4 + cmp r2,r3 + bne 1b // Copy teleporter --------> + ldr r3,_mac7100_teleport+12 + mov pc,#0x40000000 // 2.Jump to _mac7100_teleporter in RAM +_mac7100_teleporter: + bic r0,r0,#0x000000ff // 3.Re-map memory + orr r0,r0,#0x8b // Flash -> 0x20000000 + str r0,[r1] // RAM -> 0x00000000 and 0x40000000 + mov pc,r3 // 4.Teleport back to Flash +_mac7100_teleport: + .long MAC7100_MCM_AAMR + .long _mac7100_teleporter + .long _mac7100_teleport + .long _mac7100_teleport_return +_mac7100_teleport_return: + .endm + +// End memory re-mapping for single chip configuration + +//----------------------------------------------------------------------------- +// end of hal_var_setup.h +#endif // CYGONCE_HAL_VAR_SETUP_H diff --git a/packages/hal/arm/mac7100/var/v2_0/include/mac7100_misc.h b/packages/hal/arm/mac7100/var/v2_0/include/mac7100_misc.h new file mode 100644 index 00000000..1fb44736 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/include/mac7100_misc.h @@ -0,0 +1,63 @@ +#ifndef CYGONCE_HAL_MAC7100_MISC_H +#define CYGONCE_HAL_MAC7100_MISC_H +//============================================================================= +// +// mac7100_misc.h +// +// Variant specific functions +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-02-03 +// Purpose: MAC7100 specific hal functions +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +// ********************************************************************* +// +// ESCI Module +// +// ********************************************************************* + +externC void hal_mac7100_esci_pins(cyg_uint32 i_esci); + +#endif // CYGONCE_HAL_MAC7100_MISC_H +// end of mac7100_misc.h diff --git a/packages/hal/arm/mac7100/var/v2_0/include/plf_stub.h b/packages/hal/arm/mac7100/var/v2_0/include/plf_stub.h new file mode 100644 index 00000000..97d4d1da --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/include/plf_stub.h @@ -0,0 +1,83 @@ +#ifndef CYGONCE_HAL_PLF_STUB_H +#define CYGONCE_HAL_PLF_STUB_H + +//============================================================================= +// +// plf_stub.h +// +// Platform header for GDB stub support. +// +//============================================================================= +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov, gthomas +// Date: 2001-07-12 +// Purpose: Platform HAL stub support for MAC7100 based boards. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include CYGBLD_HAL_PLATFORM_H + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include // CYG_UNUSED_PARAM + +#include // architecture stub support + +//---------------------------------------------------------------------------- +// Define some platform specific communication details. This is mostly +// handled by hal_if now, but we need to make sure the comms tables are +// properly initialized. + +externC void cyg_hal_plf_comms_init(void); + +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() + +#define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int, (baud)) +#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 +#define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT + +//---------------------------------------------------------------------------- +// Stub initializer. +#define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_PLF_STUB_H +// End of plf_stub.h diff --git a/packages/hal/arm/mac7100/var/v2_0/include/var_arch.h b/packages/hal/arm/mac7100/var/v2_0/include/var_arch.h new file mode 100644 index 00000000..c5ea1ec3 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/include/var_arch.h @@ -0,0 +1,70 @@ +#ifndef CYGONCE_HAL_VAR_ARCH_H +#define CYGONCE_HAL_VAR_ARCH_H +//============================================================================= +// +// var_arch.h +// +// MAC7100 variant architecture overrides +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Jonathan Larmour +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-02-03 +// Purpose: MAC7100 variant architecture overrides +// Description: +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include + +//-------------------------------------------------------------------------- +// Idle thread code. +// This macro is called in the idle thread loop, and gives the HAL the +// chance to insert code. Typical idle thread behaviour might be to halt the +// processor. These implementations halt the system core clock. + +#ifndef HAL_IDLE_THREAD_ACTION + +// No idle action + +#endif + +#endif // CYGONCE_HAL_VAR_ARCH_H +//----------------------------------------------------------------------------- +// end of var_arch.h diff --git a/packages/hal/arm/mac7100/var/v2_0/include/var_io.h b/packages/hal/arm/mac7100/var/v2_0/include/var_io.h new file mode 100644 index 00000000..ca588cc4 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/include/var_io.h @@ -0,0 +1,470 @@ +#ifndef CYGONCE_HAL_VAR_IO_H +#define CYGONCE_HAL_VAR_IO_H +//============================================================================= +// +// var_io.h +// +// Variant specific registers +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-02-03 +// Purpose: MAC7100 variant specific registers +// Description: based on freescale's mac7100.h +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +#if !defined HAL_IO_MACROS_NO_ADDRESS_MUNGING +#define HAL_IO_MACROS_NO_ADDRESS_MUNGING 1 +#endif // HAL_IO_MACROS_NO_ADDRESS_MUNGING + +// ********************************************************************* +// +// INTC Module +// +// ********************************************************************* + +// Interrupt Controller Definitions +#define MAC7100_INTC_BASE (0xFC048000) + +#define MAC7100_IPRH_OFFSET (0x0000) +#define MAC7100_IPRL_OFFSET (0x0004) +#define MAC7100_IMRH_OFFSET (0x0008) +#define MAC7100_IMRL_OFFSET (0x000C) +#define MAC7100_INTFRCH_OFFSET (0x0010) +#define MAC7100_INTFRCL_OFFSET (0x0014) +#define MAC7100_ICONFIG_OFFSET (0x001B) +#define MAC7100_SIMR_OFFSET (0x001C) +#define MAC7100_CIMR_OFFSET (0x001D) +#define MAC7100_CLMASK_OFFSET (0x001E) // CLMASK - Current Level Mask Register +#define MAC7100_SLMASK_OFFSET (0x001F) // SLMASK - Saved Level Mask Register +#define MAC7100_ICR_OFFSET (0x0040) +#define MAC7100_IRQIACK_OFFSET (0x00EC) +#define MAC7100_FIQIACK_OFFSET (0x00F0) + +#define MAC7100_INTC_IPRH(intc_base) (intc_base + MAC7100_IPRH_OFFSET) +#define MAC7100_INTC_IPRL(intc_base) (intc_base + MAC7100_IPRL_OFFSET) +#define MAC7100_INTC_IMRH(intc_base) (intc_base + MAC7100_IMRH_OFFSET) +#define MAC7100_INTC_IMRL(intc_base) (intc_base + MAC7100_IMRL_OFFSET) +#define MAC7100_INTC_INTFRC(intc_base) (intc_base + MAC7100_INTFRCH_OFFSET) +#define MAC7100_INTC_INTFRCH(intc_base) (intc_base + MAC7100_INTFRCH_OFFSET) +#define MAC7100_INTC_INTFRCL(intc_base) (intc_base + MAC7100_INTFRCL_OFFSET) +#define MAC7100_INTC_ICONFIG(intc_base) (intc_base + MAC7100_ICONFIG_OFFSET) +#define MAC7100_INTC_IRQIACK(intc_base) (intc_base + MAC7100_IRQIACK_OFFSET) +#define MAC7100_INTC_FIQIACK(intc_base) (intc_base + MAC7100_FIQIACK_OFFSET) +#define MAC7100_INTC_ICR(intc_base,src) (intc_base + MAC7100_ICR_OFFSET + src) +#define MAC7100_INTC_SIMR(intc_base) (intc_base + MAC7100_SIMR_OFFSET) +#define MAC7100_INTC_CIMR(intc_base) (intc_base + MAC7100_CIMR_OFFSET) +#define MAC7100_INTC_CLMASK(intc_base) (intc_base + MAC7100_CLMASK_OFFSET) +#define MAC7100_INTC_SLMASK(intc_base) (intc_base + MAC7100_SLMASK_OFFSET) + +#define MAC7100_INTC_INT_LEVEL(lev) (lev) + +// hardware interrupt source vector numbers +#define MAC7100_EDMA0_IV (0) +#define MAC7100_EDMA1_IV (1) +#define MAC7100_EDMA2_IV (2) +#define MAC7100_EDMA3_IV (3) +#define MAC7100_EDMA4_IV (4) +#define MAC7100_EDMA5_IV (5) +#define MAC7100_EDMA6_IV (6) +#define MAC7100_EDMA7_IV (7) +#define MAC7100_EDMA8_IV (8) +#define MAC7100_EDMA9_IV (9) +#define MAC7100_EDMA10_IV (10) +#define MAC7100_EDMA11_IV (11) +#define MAC7100_EDMA12_IV (12) +#define MAC7100_EDMA13_IV (13) +#define MAC7100_EDMA14_IV (14) +#define MAC7100_EDMA15_IV (15) +#define MAC7100_EDMA_Error_IV (16) +#define MAC7100_MCM_SWT_IV (17) +#define MAC7100_CRG_IV (18) +#define MAC7100_PIT1_IV (19) +#define MAC7100_PIT2_IV (20) +#define MAC7100_PIT3_IV (21) +#define MAC7100_PIT4_RTI_IV (22) +#define MAC7100_VREG_IV (23) +#define MAC7100_CAN_A_MB_IV (24) +#define MAC7100_CAN_A_MB14_IV (25) +#define MAC7100_CAN_A_Error_IV (26) +#define MAC7100_CAN_B_MB_IV (27) +#define MAC7100_CAN_B_MB14_IV (28) +#define MAC7100_CAN_B_Error_IV (29) +#define MAC7100_CAN_C_MB_IV (30) +#define MAC7100_CAN_C_MB14_IV (31) +#define MAC7100_CAN_C_Error_IV (32) +#define MAC7100_CAN_D_MB_IV (33) +#define MAC7100_CAN_D_MB14_IV (34) +#define MAC7100_CAN_D_Error_IV (35) +#define MAC7100_I2C_IV (36) +#define MAC7100_DSPI_A_IV (37) +#define MAC7100_DSPI_B_IV (38) +#define MAC7100_ESCI_A_IV (39) +#define MAC7100_ESCI_B_IV (40) +#define MAC7100_ESCI_C_IV (41) +#define MAC7100_ESCI_D_IV (42) +#define MAC7100_EMIOS0_IV (43) +#define MAC7100_EMIOS1_IV (44) +#define MAC7100_EMIOS2_IV (45) +#define MAC7100_EMIOS3_IV (46) +#define MAC7100_EMIOS4_IV (47) +#define MAC7100_EMIOS5_IV (48) +#define MAC7100_EMIOS6_IV (49) +#define MAC7100_EMIOS7_IV (50) +#define MAC7100_EMIOS8_IV (51) +#define MAC7100_EMIOS9_IV (52) +#define MAC7100_EMIOS10_IV (53) +#define MAC7100_EMIOS11_IV (54) +#define MAC7100_EMIOS12_IV (55) +#define MAC7100_EMIOS13_IV (56) +#define MAC7100_EMIOS14_IV (57) +#define MAC7100_EMIOS15_IV (58) +#define MAC7100_ATD_IV (59) +#define MAC7100_CFM_IV (60) +#define MAC7100_PIM_IV (61) +#define MAC7100_IRQ_IV (62) +#define MAC7100_XIRQ_IV (63) + +#define MAC7100_IRQ_SPURIOUS (-1) + +// ******************************************************************* +// +// eSCI Module +// Note: eSCI definitions are in cyg/devs/ser_esci.h +// ******************************************************************* +#define CYGADDR_IO_SERIAL_FREESCALE_ESCI_A_BASE 0xFC0C4000 +#define CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_VECTOR MAC7100_ESCI_A_IV + +#define CYGADDR_IO_SERIAL_FREESCALE_ESCI_B_BASE 0xFC0C8000 +#define CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_VECTOR MAC7100_ESCI_B_IV + +#define CYGADDR_IO_SERIAL_FREESCALE_ESCI_C_BASE 0xFC0CC000 +#define CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_VECTOR MAC7100_ESCI_C_IV + +#define CYGADDR_IO_SERIAL_FREESCALE_ESCI_D_BASE 0xFC0D0000 +#define CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_VECTOR MAC7100_ESCI_D_IV + +#define CYGNUM_DEV_SER_FREESCALE_ESCI_SYSTEM_CLOCK \ + (CYGNUM_HAL_ARM_MAC7100_CLOCK_SPEED/2) +#define FREESCALE_ESCI_BAUD(baud_rate) \ + ((CYGNUM_DEV_SER_FREESCALE_ESCI_SYSTEM_CLOCK)/(baud_rate*16)) + + +// ********************************************************************* +// +// PIT Module +// +// ********************************************************************* + +// Periodic Interrupt Timer Module Definitions + +#define MAC7100_PIT_BASE (0xFC08C000) +#define MAC7100_TLVAL0_OFFSET (0x0000) +#define MAC7100_TVAL0_OFFSET (0x0080) + +#define MAC7100_PIT_TLVAL(pit_base,chan) \ + (pit_base + MAC7100_TLVAL0_OFFSET + (4 * chan)) +#define MAC7100_PIT_TVAL(pit_base,chan) \ + (pit_base + MAC7100_TVAL0_OFFSET + (4 * chan)) + +#define MAC7100_PITFLG_OFFSET (0x0100) +#define MAC7100_PITINTEN_OFFSET (0x0104) +#define MAC7100_PITINTSEL_OFFSET (0x0108) +#define MAC7100_PITEN_OFFSET (0x010C) +#define MAC7100_PITCTRL_OFFSET (0x0110) + +#define MAC7100_PIT_FLAG_RTIF (0x00000001) +#define MAC7100_PIT_FLAG_TIF(chan) (0x00000001 << chan) +#define MAC7100_PIT_INTSEL_ISEL(chan) (0x00000001 << chan) +#define MAC7100_PIT_INTEN_RTIE (0x00000001) +#define MAC7100_PIT_INTEN_TIE(chan) (0x00000001 << chan) + +#define MAC7100_PIT_EN_RTIEN (0x00000001) +#define MAC7100_PIT_EN_PEN(chan) (0x00000001 << chan) + +#define MAC7100_PIT_FLG(pit_base) (pit_base + MAC7100_PITFLG_OFFSET) +#define MAC7100_PIT_INTEN(pit_base) (pit_base + MAC7100_PITINTEN_OFFSET) +#define MAC7100_PIT_INTSEL(pit_base) (pit_base + MAC7100_PITINTSEL_OFFSET) +#define MAC7100_PIT_EN(pit_base) (pit_base + MAC7100_PITEN_OFFSET) + +#define MAC7100_PIT_CTRL(pit_base) (pit_base + MAC7100_PITCTRL_OFFSET) +#define MAC7100_PIT_MDIS (0x01000000) + + +// ********************************************************************* +// +// PIM Module +// +// *********************************************************************/ + +#define MAC7100_PIM_BASE (0xFC0E8000) + +#define MAC7100_PORT_A_OFFSET (0x000) +#define MAC7100_PORT_B_OFFSET (0x040) +#define MAC7100_PORT_C_OFFSET (0x080) +#define MAC7100_PORT_D_OFFSET (0x0C0) +#define MAC7100_PORT_E_OFFSET (0x100) +#define MAC7100_PORT_F_OFFSET (0x140) +#define MAC7100_PORT_G_OFFSET (0x180) +#define MAC7100_PORT_H_OFFSET (0x1C0) +#define MAC7100_PORT_I_OFFSET (0x200) + +// PORT Pin Configuration Registers +#define MAC7100_PIM_CONFIG(port,pin) (MAC7100_PIM_BASE+port+((pin)*2)) +// Port Wide Interrupt Flag Register +#define MAC7100_PIM_PORTIFR(port) (MAC7100_PIM_BASE+port+0x20) +// Port Wide Data Read/Write Register +#define MAC7100_PIM_PORTDATA(port) (MAC7100_PIM_BASE+port+0x24) +// Port Wide Input Register +#define MAC7100_PIM_PORTIR(port) (MAC7100_PIM_BASE+port+0x26) +// Port Pin Data Registers +#define MAC7100_PIM_DATA(port,pin) (MAC7100_PIM_BASE+port+0x28+pin) + +// Global Interrupt Status Register +#define MAC7100_PIM_GLBLINT (MAC7100_PIM_BASE+0x03C0) +// PIM Configuration Register +#define MAC7100_PIM_PIMCONFIG (MAC7100_PIM_BASE+0x03C2) +// TDI Pin Configuration Register +#define MAC7100_PIM_CONFIG_TDI (MAC7100_PIM_BASE+0x03C4) +// TDO Pin Configuration Register +#define MAC7100_PIM_CONFIG_TDO (MAC7100_PIM_BASE+0x03C6) +// TMS Pin Configuration Register +#define MAC7100_PIM_CONFIG_TMS (MAC7100_PIM_BASE+0x03C8) +// TCK Pin Configuration Register +#define MAC7100_PIM_CONFIG_TCK (MAC7100_PIM_BASE+0x03CA) +// TA Pin Configuration Register +#define MAC7100_PIM_CONFIG_TA (MAC7100_PIM_BASE+0x03CC) + +// Bit definitions and macros for PIM_PA_CONFIGn +// Pin Interrupt Flag Register +#define MAC7100_PIM_PIFR (0x0001) +// Pin Interrupt Enable Register +#define MAC7100_PIM_PIER (0x0002) +// Pull-up/down Enable Register +#define MAC7100_PIM_PULL(x) (((x)&0x0003)<<2) +// Reduced Drive Strength Register +#define MAC7100_PIM_RDR (0x0010) +// Open Drain Enable Register +#define MAC7100_PIM_ODER (0x0020) +// Data Direction Register +#define MAC7100_PIM_DDR (0x0040) +#define MAC7100_PIM_MODE (0x0080) +#define MAC7100_PIM_MODE_PERIPHERAL MAC7100_PIM_MODE + +// Bit definitions and macros for PIM_GLBLINT +// Interrupt Pending +#define MAC7100_PIM_INT_PENDING(x) (((x)&0x01FF)<<0) + +// Bit definitions and macros for PIM_PIMCONFIG +// Clock Enable for the EIM module +#define MAC7100_PIM_PORTHSEL (0x0001) +// Port H Select +#define MAC7100_PIM_EIMCLKEN (0x0002) + +#define MAC7100_PIM_PORT32IR(port32ir) (MAC7100_PIM_BASE+0x03E0+port32ir) + +#define MAC7100_PIM_PORT32IR_AB (0x00) +#define MAC7100_PIM_PORT32IR_CD (0x04) +#define MAC7100_PIM_PORT32IR_EF (0x08) +#define MAC7100_PIM_PORT32IR_GH (0x0C) +#define MAC7100_PIM_PORT32IR_BC (0x10) +#define MAC7100_PIM_PORT32IR_DE (0x14) +#define MAC7100_PIM_PORT32IR_FG (0x18) +#define MAC7100_PIM_PORT32IR_HI (0x1C) + + +// ******************************************************************** +// +// CRG Module +// +// ******************************************************************** + +// Register read/write macros +#define MAC7100_CRG_BASE 0xFC088000 // SYNR - Synthesizer Register +#define MAC7100_CRG_SYNR 0xFC088000 // SYNR - Synthesizer Register +#define MAC7100_CRG_REFDV 0xFC088001 // REFDV - Reference Divider Register +#define MAC7100_CRG_CTFLG 0xFC088002 // CTFLG - Test Flags Register (reserved) +#define MAC7100_CRG_CRGFLG 0xFC088003 // CRGFLG - Flags Register +#define MAC7100_CRG_CRGINT 0xFC088004 // CRGINT - Interrupt Enable Register +#define MAC7100_CRG_CLKSEL 0xFC088005 // CLKSEL - Clock Select Register +#define MAC7100_CRG_PLLCTL 0xFC088006 // PLLCTL - PLL Control Register +#define MAC7100_CRG_SDMCTL 0xFC088007 // SDMCTL - STOP/DOZE Control Register +#define MAC7100_CRG_BDMCTL 0xFC088008 // BDMCTL - BDM Control Register +#define MAC7100_CRG_FORBYP 0xFC088009 // FORBYP - Force and Bypass Test +#define MAC7100_CRG_CTCTL 0xFC08800A // CTCTL - Test Control Register (resvd) + +// Bit definitions and macros for CRG_SYNR +#define MAC7100_CRG_SYN(x) (((x)&0x3F)<<0) // Synthesizer Count value + +// Bit definitions and macros for CRG_REFDV +#define MAC7100_CRG_REFD(x) (((x)&0x0F)<<0) //Reference divider + +// Bit definitions and macros for CRG_CRGFLG +#define MAC7100_CRG_SCM (0x01) //Self Clock Mode Status +#define MAC7100_CRG_SCMIF (0x02) //Self Clock Mode Interrupt Flag +#define MAC7100_CRG_TRACK (0x04) //Track Status +#define MAC7100_CRG_LOCK (0x08) //Lock Status +#define MAC7100_CRG_LOCKIF (0x10) //PLL Lock Interrupt Flag +#define MAC7100_CRG_LVRF (0x20) //Low Voltage Reset Flag +#define MAC7100_CRG_PORF (0x40) //Power on Reset Flag +#define MAC7100_CRG_STPEF (0x80) //Stop Entry Flag + +// Bit definitions and macros for CRG_CRGINT +#define MAC7100_CRG_SCMIE (0x02) //Self Clock Mode Interrupt Enable +#define MAC7100_CRG_LOCKIE (0x10) //Lock Interrupt Enable + +// Bit definitions and macros for CRG_CLKSEL +#define MAC7100_CRG_SWTDOZE (0x01) //SWT stops in Doze Mode +#define MAC7100_CRG_RTIDOZE (0x02) /* RTI stops in Doze Mode */ +#define MAC7100_CRG_PLLDOZE (0x08) /* PLL stops in Doze Mode */ +#define MAC7100_CRG_DOZE_ROA (0x10) /* Reduced Osc Amp in Doze Mode */ +#define MAC7100_CRG_PSTP (0x40) /* Pseudo Stop */ +#define MAC7100_CRG_PLLSEL (0x80) /* PLL Select */ + +// Bit definitions and macros for CRG_PLLCTL +#define MAC7100_CRG_SCME (0x01) //Self Clock Mode Enable +#define MAC7100_CRG_PWE (0x02) //SWT Enable during Pseudo Stop +#define MAC7100_CRG_PRE (0x04) //RTI Enable during Pseudo Stop +#define MAC7100_CRG_FSTWKP (0x08) //Fast Wake-up from Full Stop Bit +#define MAC7100_CRG_ACQ (0x10) //Acquisition +#define MAC7100_CRG_AUTO (0x20) //Automatic Bandwidth Control +#define MAC7100_CRG_PLLON (0x40) //Phase Lock Loop On +#define MAC7100_CRG_CME (0x80) //Clock Monitor Enable + +// Bit definitions and macros for CRG_SDMCTL +#define MAC7100_CRG_STOP (0x01) //STOP mode +#define MAC7100_CRG_DOZE (0x02) //DOZE mode + +// Bit definitions and macros for CRG_BDMCTL +#define MAC7100_CRG_RSBCK (0x40) //SWT & RTI stop in Active BDM mode + + +// ********************************************************************* +// +// MCM Module +// +// ********************************************************************* + +// Register read/write macros +#define MAC7100_MCM_PCT 0xFC040000 // +#define MAC7100_MCM_REV 0xFC040002 // +#define MAC7100_MCM_AMC 0xFC040004 // +#define MAC7100_MCM_ASC 0xFC040006 // +#define MAC7100_MCM_IMC 0xFC040008 // +// MRSR - Miscellaneous Reset Status Register +#define MAC7100_MCM_MRSR 0xFC04000F +// MWCR - Miscellaneous Wakeup Control Register +#define MAC7100_MCM_MWCR 0xFC040013 +// MSWTCR - Miscellaneous Software Watchdog Timer Control Register +#define MAC7100_MCM_MSWTCR 0xFC040016 +// MSWTSR - Miscellaneous Software Watchdog Timer Service Register +#define MAC7100_MCM_MSWTSR 0xFC04001B +// MSWTIR - Miscellaneous Software Watchdog Timer Interrupt Register +#define MAC7100_MCM_MSWTIR 0xFC04001F +// AAMR - AXBS Address Map Register +#define MAC7100_MCM_AAMR 0xFC040020 +// CFADR - Core Fault Address Register +#define MAC7100_MCM_CFADR 0xFC040070 +// CFLOC - Core Fault Location Register +#define MAC7100_MCM_CFLOC 0xFC040076 +// CFATR - Core Fault Attributes Register +#define MAC7100_MCM_CFATR 0xFC040077 +// CFDTR - Core Fault Data Register +#define MAC7100_MCM_CFDTR 0xFC04007C + +// Bit definitions and macros for MCM_AMC + +// AXBS Master Configuration +#define MAC7100_MCM_AXMC(x) (((x)&0x00FF)<<0) + +// Bit definitions and macros for MCM_ASC +// AXBS Slave Configuration +#define MAC7100_MCM_AXSC(x) (((x)&0x00FF)<<0) +#define MAC7100_MCM_DP64 (0x8000) // 64-bit Datapath + +// Bit definitions and macros for MCM_MRSR +#define MAC7100_MCM_SWTR (0x20) // Watchdog Timer Reset +#define MAC7100_MCM_DIR (0x40) // Device Input Reset +#define MAC7100_MCM_POR (0x80) // Power-On Reset + +// Bit definitions and macros for MCM_MWCR +#define MAC7100_MCM_PRILVL(x) (((x)&0x0F)<<0) // Interrupt Priority Level +#define MAC7100_MCM_ENBWCR (0x80) // Enable WCR + +// Bit definitions and macros for MCM_MSWTCR +#define MAC7100_MCM_SWT(x) (((x)&0x001F)<<0) // Watchdog Time-Out Period +#define MAC7100_MCM_SWRI(x) (((x)&0x0003)<<5) // Watchdog Reset/Interrupt +#define MAC7100_MCM_SWE (0x0080) // Watchdog Enable +#define MAC7100_MCM_SWRWH (0x0100) // Watchdog Run While Halted +#define MAC7100_MCM_SWCIN16 (0x0200) // Force SWT CarryIn16 +#define MAC7100_MCM_RO (0x8000) // Read-Only + +// Bit definitions and macros for MCM_MSWTIR +#define MAC7100_MCM_SWTIC (0x01) // Watchdog Interrupt Flag + +// Bit definitions and macros for MCM_AAMR + + +// Address 0 Slave Number +#define MAC7100_MCM_ASLAVE(adr_reg,sl_n) (((sl_n)&0x00000007)<<(adr_reg*4) +// Enable Address Region 0 +#define MAC7100_MCM_EA(adr_reg) (0x00000008<<(adr_reg*4)) + +// Bit definitions and macros for MCM_CFLOC +#define MAC7100_MCM_LOCALERR (0x80) // Bus Error Indicator + +// Bit definitions and macros for MCM_CFATR +// Protection fault type +#define MAC7100_MCM_PROTECTION(x) (((x)&0x0F)<<0) +// 8-16-32-64-bit core access +#define MAC7100_MCM_SIZE(x) (((x)&0x07)<<4) +// Core read/write access +#define MAC7100_MCM_WRITE (0x80) + +//============================================================================= +// FIQ interrupt vector which is shared by all HAL variants. + +#define CYGNUM_HAL_INTERRUPT_FIQ 0 +#endif // CYGONCE_HAL_VAR_IO_H +//----------------------------------------------------------------------------- +// end of var_io.h diff --git a/packages/hal/arm/mac7100/var/v2_0/src/flash_security.S b/packages/hal/arm/mac7100/var/v2_0/src/flash_security.S new file mode 100644 index 00000000..d64acd66 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/src/flash_security.S @@ -0,0 +1,77 @@ +/*========================================================================== +// +// flash_security.S +// +// MAC7100 Flash security area +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-04-11 +// Purpose: HAL board support +// Description: MAC7100 Flash security area. +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +///////////////////////////////////////////////////////////////////////////// +// This section contains Common Flash Module (CFM) configuration field +// For detail description see Common Flash Module (CFM) chapter +// @ MAC7100 Microcontroller Familly Reference Manual +// +// Deafault factorry setting: +// 0xffffffff for All words except Flash Security Word +// 0xfffffffe for Flash Security Word +///////////////////////////////////////////////////////////////////////////// + + .section ".mac7100_flash_security", "a" + .code 32 + .global VAE_MAC7100_FlashSecurity +VAE_MAC7100_FlashSecurity: + .long 0xffffffff // Backdoor Comparison Key bit 63-32 + .long 0xffffffff // Backdoor Comparison key bit 31-0 + .long 0xffffffff // Program FLASH protection Bytes + .long 0xffffffff // Program FLASH SUPV Access Bytes + .long 0xffffffff // Program FLASH DATA Access Bytes + .long 0xfffffffe // Flash Security Word + .long 0xffffffff // Data FLASH protection, SUPV access, DATA access + + .long 0xe0f00420 // Just a placeholder (round to 0x420) + .end + +//-------------------------------------------------------------------------- +// EOF flash_security.S diff --git a/packages/hal/arm/mac7100/var/v2_0/src/hal_diag.c b/packages/hal/arm/mac7100/var/v2_0/src/hal_diag.c new file mode 100644 index 00000000..bc1d576c --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/src/hal_diag.c @@ -0,0 +1,385 @@ +/*============================================================================= +// +// hal_diag.c +// +// HAL diagnostic output code +// +//============================================================================= +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Ilija Koco +// Contributors: +// Date: 2006-04-15 +// Purpose: HAL diagnostic output +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + */ + +#include +#include CYGBLD_HAL_PLATFORM_H + +#include // base types + +#include // SAVE/RESTORE GP macros +#include // IO macros +#include // interface API +#include // HAL_ENABLE/MASK/UNMASK_INTERRUPTS +#include // Helper functions +#include // CYG_ISR_HANDLED +#include + +#include // +#include // ESCI registers + +//----------------------------------------------------------------------------- +typedef struct { + void *base; + cyg_int32 msec_timeout; + int isr_vector; + int isr_level; + int baud_rate; +} channel_data_t; + + + +//----------------------------------------------------------------------------- + +void +cyg_hal_plf_serial_putc(void *__ch_data, char c); + + +static void +cyg_hal_plf_serial_init_channel(void* __ch_data) +{ + + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8 *esci_base = chan->base; + + + // Reset device + // 8-1-no parity. + + HAL_WRITE_UINT8(FREESCALE_ESCI_CR3(esci_base), 0); + HAL_WRITE_UINT16(FREESCALE_ESCI_LINCTRL(esci_base), 0); + HAL_WRITE_UINT16(FREESCALE_ESCI_BD(esci_base), + FREESCALE_ESCI_BAUD(chan->baud_rate)); + + // Enable RX and TX + HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), (FREESCALE_ESCI_CR12_TE | + FREESCALE_ESCI_CR12_RE)); +} + +void +cyg_hal_plf_serial_putc(void* __ch_data, char ch_out) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + CYG_ADDRESS esci_base = (CYG_ADDRESS) chan->base; + cyg_uint16 esci_sr; + + CYGARC_HAL_SAVE_GP(); + + do { + HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr); + } while (!(esci_sr & FREESCALE_ESCI_SR_TDRE)); + + HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_TDRE); + HAL_WRITE_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_out); + + CYGARC_HAL_RESTORE_GP(); +} + +static cyg_bool +cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* p_ch_in) +{ + channel_data_t* chan = (channel_data_t*)__ch_data; + CYG_ADDRESS esci_base = (CYG_ADDRESS) chan->base; + cyg_uint16 esci_sr; + cyg_uint8 ch_in; + + HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr); + if (!(esci_sr & FREESCALE_ESCI_SR_RDRF)) + return false; + + HAL_READ_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_in); + HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_RDRF); + *p_ch_in = ch_in; + + return true; +} + +cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8 ch; + CYGARC_HAL_SAVE_GP(); + + while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)); + + CYGARC_HAL_RESTORE_GP(); + return ch; +} + +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +cyg_bool +cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* p_ch_in) +{ + int delay_count; + cyg_bool res; + CYGARC_HAL_SAVE_GP(); + + // delay in .1 ms steps + delay_count = ((channel_data_t*)__ch_data)->msec_timeout * 10; + + for(;;) { + res = cyg_hal_plf_serial_getc_nonblock(__ch_data, p_ch_in); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + channel_data_t* chan = (channel_data_t*)__ch_data; + cyg_uint8* base = ((channel_data_t*)__ch_data)->base; + cyg_uint16 ser_port_reg; + int ret = 0; + va_list ap; + + CYGARC_HAL_SAVE_GP(); + va_start(ap, __func); + + switch (__func) { + case __COMMCTL_GETBAUD: + ret = chan->baud_rate; + break; + case __COMMCTL_SETBAUD: + chan->baud_rate = va_arg(ap, cyg_int32); + // Should we verify this value here? + cyg_hal_plf_serial_init_channel(chan); + ret = 0; + break; + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector); + HAL_INTERRUPT_UNMASK(chan->isr_vector); + + HAL_READ_UINT16(FREESCALE_ESCI_CR12(base), ser_port_reg); + ser_port_reg |= FREESCALE_ESCI_CR12_RIE; + HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(base), ser_port_reg); + + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + HAL_INTERRUPT_MASK(chan->isr_vector); + + HAL_READ_UINT16(FREESCALE_ESCI_CR12(base), ser_port_reg); + ser_port_reg &= ~(cyg_uint16)FREESCALE_ESCI_CR12_RIE; + HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(base), ser_port_reg); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = chan->isr_vector; + break; + case __COMMCTL_SET_TIMEOUT: + ret = chan->msec_timeout; + chan->msec_timeout = va_arg(ap, cyg_uint32); + default: + break; + } + + va_end(ap); + CYGARC_HAL_RESTORE_GP(); + return ret; +} + +static int +cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + + channel_data_t* chan = (channel_data_t*)__ch_data; + CYG_ADDRESS esci_base = (CYG_ADDRESS) chan->base; + cyg_uint16 esci_sr; + int res = 0; + cyg_uint8 ch_in; + CYGARC_HAL_SAVE_GP(); + + *__ctrlc = 0; + + HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr); + if (esci_sr & FREESCALE_ESCI_SR_RDRF){ + HAL_READ_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_in); + if( cyg_hal_is_break( &ch_in , 1 ) ) + *__ctrlc = 1; + + res = CYG_ISR_HANDLED; + HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_RDRF); + } + + HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector); + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static channel_data_t mac7100_ser_channels[4] = { + { (cyg_uint16*)FREESCALE_ESCI_A_BASE, 1000, MAC7100_ESCI_A_IV, + MAC7100_ESCI_A_LEVEL, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD}, + { (cyg_uint16*)FREESCALE_ESCI_B_BASE, 1000, MAC7100_ESCI_B_IV, + MAC7100_ESCI_B_LEVEL, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD}, + { (cyg_uint16*)FREESCALE_ESCI_C_BASE, 1000, MAC7100_ESCI_C_IV, + MAC7100_ESCI_C_LEVEL, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD}, + { (cyg_uint16*)FREESCALE_ESCI_D_BASE, 1000, MAC7100_ESCI_D_IV, + MAC7100_ESCI_D_LEVEL, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD}, +}; + +static void +cyg_hal_plf_serial_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur; + + cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Init channels + cyg_hal_plf_serial_init_channel(&mac7100_ser_channels[0]); +#if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1 + cyg_hal_plf_serial_init_channel(&mac7100_ser_channels[1]); +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 2 + cyg_hal_plf_serial_init_channel(&mac7100_ser_channels[2]); +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 3 + cyg_hal_plf_serial_init_channel(&mac7100_ser_channels[3]); +#endif + // Setup procs in the vector table + + // Set channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &mac7100_ser_channels[0]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + +#if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1 + // Set channel 1 + CYGACC_CALL_IF_SET_CONSOLE_COMM(1); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &mac7100_ser_channels[1]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 2 + CYGACC_CALL_IF_SET_CONSOLE_COMM(2); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &mac7100_ser_channels[2]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); +#endif +#if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 3 + CYGACC_CALL_IF_SET_CONSOLE_COMM(3); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &mac7100_ser_channels[3]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); +#endif + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + initialized = 1; + cyg_hal_plf_serial_init(); +} + +//----------------------------------------------------------------------------- +// End of hal_diag.c diff --git a/packages/hal/arm/mac7100/var/v2_0/src/mac7100_misc.c b/packages/hal/arm/mac7100/var/v2_0/src/mac7100_misc.c new file mode 100644 index 00000000..faf17921 --- /dev/null +++ b/packages/hal/arm/mac7100/var/v2_0/src/mac7100_misc.c @@ -0,0 +1,341 @@ +/*========================================================================== +// +// mac7100_misc.c +// +// HAL misc board support code for Freescale MAC7100 +// +//========================================================================== +//####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 Nick Garnett +// Copyright (c) 2006 eCosCentric Ltd +// +// 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): Ilija Koco +// Contributors: +// Date: 2006-04-12 +// Purpose: HAL board support +// Description: Implementations of HAL board interfaces +// +//####DESCRIPTIONEND#### +// +//======================================================================== +*/ + +#include + +#include // base types +#include // tracing macros +#include // assertion macros + +#include // IO macros +#include // Register state info +#include +#include // necessary? +#include +#include // calling interface +#include // helper functions +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT +#include // HAL ISR support +#endif +#include // platform registers +#include // ESCI registers +#include + +// ------------------------------------------------------------------------- +// Clock support + +static cyg_uint32 _period; + +void hal_clock_initialize(cyg_uint32 period) +{ + CYG_ADDRESS pit_base = MAC7100_PIT_BASE; + cyg_uint32 pit_en; + + CYG_ASSERT(period < 0x10000, "Invalid clock period"); + + // Disable counter + HAL_READ_UINT32(MAC7100_PIT_EN(pit_base), pit_en); + pit_en &= ~MAC7100_PIT_EN_PEN(CYGNUM_PIT_CHAN_CLOCK); + HAL_WRITE_UINT32(MAC7100_PIT_EN(pit_base), pit_en); + + // Set registers + _period=period; + HAL_WRITE_UINT32(MAC7100_PIT_TLVAL(pit_base, CYGNUM_PIT_CHAN_CLOCK), + period); + + // Start timer + pit_en |= MAC7100_PIT_EN_PEN(CYGNUM_PIT_CHAN_CLOCK); + HAL_WRITE_UINT32(MAC7100_PIT_EN(pit_base), pit_en); + + // Enable timer interrupt + HAL_READ_UINT32(MAC7100_PIT_INTEN(pit_base), pit_en); + pit_en |= MAC7100_PIT_EN_PEN(CYGNUM_PIT_CHAN_CLOCK); + HAL_WRITE_UINT32(MAC7100_PIT_INTEN(pit_base), pit_en); + + HAL_READ_UINT32(MAC7100_PIT_INTSEL(pit_base), pit_en); + pit_en |= MAC7100_PIT_EN_PEN(CYGNUM_PIT_CHAN_CLOCK); + HAL_WRITE_UINT32(MAC7100_PIT_INTSEL(pit_base), pit_en); +} + +void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) +{ + HAL_WRITE_UINT32(MAC7100_PIT_FLG(MAC7100_PIT_BASE), + MAC7100_PIT_FLAG_TIF(CYGNUM_PIT_CHAN_CLOCK)); +} + + +void hal_clock_read(cyg_uint32 *pvalue) +{ + cyg_uint32 val; + + HAL_READ_UINT32(MAC7100_PIT_TLVAL(MAC7100_PIT_BASE,CYGNUM_PIT_CHAN_CLOCK), + val); + *pvalue = _period-val; +} + +// ------------------------------------------------------------------------- +// +// Delay for some number of micro-seconds +// + +#if CYGNUM_PIT_CHAN_US!=0 +#define CYGNUM_1_US (CYGNUM_HAL_ARM_MAC7100_CLOCK_SPEED/2000000) +#else +#define CYGNUM_1_US (CYGNUM_HAL_ARM_MAC7100_F_OSC/1000000) +#endif + +void hal_delay_us(cyg_int32 usecs) +{ + CYG_ADDRESS pit_base = MAC7100_PIT_BASE; + cyg_uint32 pit_en; + + + // Clear flag + HAL_WRITE_UINT32(MAC7100_PIT_FLG(pit_base), + MAC7100_PIT_FLAG_TIF(CYGNUM_PIT_CHAN_US)); + + // Set timer + HAL_WRITE_UINT32(MAC7100_PIT_TLVAL(pit_base, CYGNUM_PIT_CHAN_US), + usecs*CYGNUM_1_US-1); + HAL_READ_UINT32(MAC7100_PIT_EN(pit_base), pit_en); + pit_en |= MAC7100_PIT_EN_PEN(CYGNUM_PIT_CHAN_US); + HAL_WRITE_UINT32(MAC7100_PIT_EN(pit_base), pit_en); + + do { + HAL_READ_UINT32(MAC7100_PIT_FLG(pit_base), pit_en); + }while (!(pit_en & MAC7100_PIT_FLAG_TIF(CYGNUM_PIT_CHAN_US))); + + // Disable counter + HAL_READ_UINT32(MAC7100_PIT_EN(pit_base), pit_en); + pit_en &= ~MAC7100_PIT_EN_PEN(CYGNUM_PIT_CHAN_US); + HAL_WRITE_UINT32(MAC7100_PIT_EN(pit_base), pit_en); +} + + +// ------------------------------------------------------------------------- +// Hardware init + +void hal_intc_init(void); +void hal_pit_init(void); +static void hal_mac7100_esci_pins(cyg_uint32); +void hal_hardware_init(void) +{ + // Reset all interrupts + // + + // Flush internal priority level stack + // + + // Set up eCos/ROM interfaces +#if (defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_A) || \ + (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 0) + hal_mac7100_esci_pins(FREESCALE_ESCI_A_I); +#endif +#if (defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_B) || \ + (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1) + hal_mac7100_esci_pins(FREESCALE_ESCI_B_I); +#endif +#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_C + hal_mac7100_esci_pins(FREESCALE_ESCI_C_I); +#endif +#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_D + hal_mac7100_esci_pins(FREESCALE_ESCI_D_I); +#endif + + hal_intc_init(); // Initialize interrupt controller + hal_pit_init(); // Initilaize CLOCK for channels 1..10 + hal_if_init(); +} + +void hal_pit_init(void) +{ + cyg_uint32 pit_ctrl; + + CYG_ADDRESS pit_base=MAC7100_PIT_BASE; + + HAL_READ_UINT32(MAC7100_PIT_CTRL(pit_base), pit_ctrl); + pit_ctrl &= ~MAC7100_PIT_MDIS; + HAL_WRITE_UINT32(MAC7100_PIT_CTRL(pit_base), pit_ctrl); +} + + +// ------------------------------------------------------------------------- +// This routine is called to respond to a hardware interrupt (IRQ). It +// should interrogate the hardware and return the IRQ vector number. + +typedef struct ClSlMask_T { + cyg_uint8 ClMask; + cyg_uint8 SlMask; +} ClSlMask_T; + +static ClSlMask_T ClSlMasks[CYGNUM_HAL_ISR_COUNT]; + +void hal_intc_init(void) +{ + cyg_uint8 iconfig; + CYG_ADDRESS intc_base=MAC7100_INTC_BASE; + + iconfig = (CYGHWR_HAL_ARM_MAC7100_INTC_FIQDEF | + CYGHWR_HAL_ARM_MAC7100_INTC_EMASK); + HAL_WRITE_UINT8(MAC7100_INTC_ICONFIG(intc_base), iconfig); +} + +int hal_IRQ_handler(void) +{ + CYG_ADDRESS intc_base=MAC7100_INTC_BASE; + cyg_int8 irq_num; + ClSlMask_T clslmask; + + HAL_READ_UINT8(MAC7100_INTC_CLMASK(intc_base), clslmask.ClMask); + HAL_READ_UINT8(MAC7100_INTC_SLMASK(intc_base), clslmask.SlMask); +#ifdef CYGHWR_HAL_ARM_MAC7100_FIQ + HAL_READ_UINT8(MAC7100_FIQIACK(intc_base), irq_num); + if((irq_num-=CYGNUM_HAL_ISR_COUNT)<0){ +#endif //CYGHWR_HAL_ARM_MAC7100_FIQ + HAL_READ_UINT8(MAC7100_INTC_IRQIACK(intc_base), irq_num); + if((irq_num-=CYGNUM_HAL_ISR_COUNT)<0){ + irq_num=CYGNUM_HAL_INTERRUPT_NONE; + }else{ + ClSlMasks[irq_num]=clslmask; + } + return irq_num; +#ifdef CYGHWR_HAL_ARM_MAC7100_FIQ + } +#endif // CYGHWR_HAL_ARM_MAC7100_FIQ +} + +// ------------------------------------------------------------------------- +// Interrupt control +// + +void hal_interrupt_mask(int vector) +{ + CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX && + vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector"); + + HAL_WRITE_UINT8(MAC7100_INTC_SIMR(MAC7100_INTC_BASE), vector); +} + +void hal_interrupt_unmask(int vector) +{ + CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX && + vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector"); + + HAL_WRITE_UINT8(MAC7100_INTC_CIMR(MAC7100_INTC_BASE), vector); +} + +void hal_interrupt_acknowledge(int vector) +{ + // ?? No check for valid vector here! Spurious interrupts + // ?? must be acknowledged, too. + + if(vector>=0) + HAL_WRITE_UINT8(MAC7100_INTC_CLMASK(MAC7100_INTC_BASE), + ClSlMasks[vector].ClMask); +} + +void hal_interrupt_configure(int vector, int level, int up) +{ + // TO DO +} + +void hal_interrupt_set_level(int vector, int level) +{ + CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX && + vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector"); + CYG_ASSERT(level >=0 level <= 15, "Invalid level"); + + HAL_WRITE_UINT8(MAC7100_INTC_ICR(MAC7100_INTC_BASE,vector), + MAC7100_INTC_INT_LEVEL(level)); +} + +void hal_show_IRQ(int vector, int data, int handler) +{ +// UNDEFINED(__FUNCTION__); // FIXME +} + + +void hal_mac7100_reset_cpu(void) +{ + // TO DO use watchdog to reset cpu +} + +// Set ESCI channel pins in perpheral mode + +void +hal_mac7100_esci_pins(cyg_uint32 i_esci){ + cyg_uint16 *p_pim_config=0; + + switch(i_esci){ + case FREESCALE_ESCI_A_I: + p_pim_config= + (cyg_uint16 *)MAC7100_PIM_CONFIG(MAC7100_PORT_G_OFFSET,2); + break; + case FREESCALE_ESCI_B_I: + p_pim_config=(cyg_uint16 *)MAC7100_PIM_CONFIG(MAC7100_PORT_G_OFFSET,0); + break; + case FREESCALE_ESCI_C_I: + p_pim_config= + (cyg_uint16 *)MAC7100_PIM_CONFIG(MAC7100_PORT_G_OFFSET,14); + break; + case FREESCALE_ESCI_D_I: + p_pim_config= + (cyg_uint16 *)MAC7100_PIM_CONFIG(MAC7100_PORT_G_OFFSET,15); + break; + } + HAL_WRITE_UINT16(p_pim_config++, MAC7100_PIM_MODE_PERIPHERAL); + HAL_WRITE_UINT16(p_pim_config, MAC7100_PIM_MODE_PERIPHERAL); +} + + +//-------------------------------------------------------------------------- +// EOF mac7100_misc.c diff --git a/packages/hal/coldfire/arch/v2_0/ChangeLog b/packages/hal/coldfire/arch/v2_0/ChangeLog new file mode 100644 index 00000000..fb043657 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/ChangeLog @@ -0,0 +1,55 @@ +2005-06-24 Enrico Piria + + * src/coldfire.ld: + * src/coldfire_stub.c: + * src/context.S: + * src/hal_misc.c: + * src/hal_mk_defs.c: + * src/hal_startup.c: + * src/vectors.S: + * include/arch.inc: + * include/basetype.h: + * include/coldfire_regs.h: + * include/coldfire_stub.h: + * include/hal_arch.h: + * include/hal_cache.h: + * include/hal_intr.h: + * include/hal_io.h: + * include/hal_startup.h: + * cdl/hal_coldfire.cdl: + * doc/readme.txt: + Rework of the original ColdFire architecture HAL contributed by + Wade Jensen. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/coldfire/arch/v2_0/cdl/hal_coldfire.cdl b/packages/hal/coldfire/arch/v2_0/cdl/hal_coldfire.cdl new file mode 100644 index 00000000..544ad317 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/cdl/hal_coldfire.cdl @@ -0,0 +1,106 @@ +# ==================================================================== +# +# hal_coldfire.cdl +# +# ColdFire architecture HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2006 eCosCentric Ltd. +## +## 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): Enrico Piria +## Contributors: Wade Jensen +## Date: 2005-25-06 +## +######DESCRIPTIONEND#### +##======================================================================== + +cdl_package CYGPKG_HAL_COLDFIRE { + display "ColdFire architecture" + parent CYGPKG_HAL + hardware + include_dir cyg/hal + define_header hal_coldfire.h + description " + The ColdFire architecture HAL package provides generic + support for this processor architecture. It is also + necessary to select a specific target platform HAL + package." + + cdl_interface CYGINT_HAL_COLDFIRE_VARIANT { + display "Number of variant implementations in this configuration" + no_define + requires 1 == CYGINT_HAL_COLDFIRE_VARIANT + } + + compile hal_startup.c hal_misc.c coldfire_stub.c vectors.S context.S + + # The "-o file" is a workaround for CR100958 - without it the + # output file would end up in the source directory under CygWin. + # n.b. grep does not behave itself under win32 + make -priority 1 { + /include/cyg/hal/cf_offsets.inc : /src/hal_mk_defs.c + $(CC) $(ACTUAL_CFLAGS) $(INCLUDE_PATH) -Wp,-MD,cf_offsets.tmp -o hal_mk_defs.tmp -S $< + fgrep .equ hal_mk_defs.tmp | sed s/#// > $@ + @echo $@ ": \\" > $(notdir $@).deps + @tail -n +2 cf_offsets.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm cf_offsets.tmp hal_mk_defs.tmp + } + + make { + /lib/vectors.o : /src/vectors.S + $(CC) -Wp,-MD,vectors.tmp $(INCLUDE_PATH) $(ACTUAL_CFLAGS) -c -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail -n +2 vectors.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm vectors.tmp + } + + make { + /lib/target.ld: /src/coldfire.ld + $(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(ACTUAL_CFLAGS) -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail -n +2 target.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm target.tmp + } + + cdl_option CYGBLD_LINKER_SCRIPT { + display "Linker script" + flavor data + no_define + calculated { "src/coldfire.ld" } + } + +} diff --git a/packages/hal/coldfire/arch/v2_0/doc/readme.txt b/packages/hal/coldfire/arch/v2_0/doc/readme.txt new file mode 100644 index 00000000..67976d4d --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/doc/readme.txt @@ -0,0 +1,70 @@ +SOME NOTES ON THE USAGE OF THE HAL FOR COLDFIRE + +This HAL was obtained by rewriting the original port of eCos to ColdFire done +by Wade Jensen. The following guidelines give you hints about using this +software. + +* Use at least GCC version 3.4.1. This version has an improved support for + ColdFire processors. However, this compiler might not be able to build the + "cxxsupp.cxx" test in the "infra" package. + +* The version of the binutils I used is 2.15.90.0.1.1. + +* The version of newlib I used is 1.13.0. + +* The version of the BDM tools I used is 1.3.0. + +* If you want to debug code by means of the serial connection to eCos, don't +use a version of GDB with BDM support compiled into. There is some kind of +interaction between BDM and serial targets that prevents the latter from +functioning correctly. Do not even use a clean GDB 6.3 distribution to debug +through the serial cable. The downloading of code to the target is broken in +that version. Instead, use a version of GDB grabbed from CVS repository. I +used a version downloaded after June 13, 2005, and the bug had been corrected. + +* Currently (version 6.3), GDB doesn't support the ColdFire MAC unit. Thus, it +is not possible to show the MAC registers, via the "info registers" command, +when debugging an eCos application through a serial connection. The BDM addon +to GDB doesn't suffer from a similar limitation. However, there is a little +hack in order to show and modify the MAC registers even with a serial +connection. When a breakpoint is hit, the GDB module of eCos stores the +current register values in a structure of type HAL_SavedRegisters, pointed to +by the _hal_registers variable. If you included the GDB stub in your +application, it is then possible to display the MAC registers (and all of the +others) by issuing at the GDB prompt the following command: + +print *(struct HAL_SavedRegisters *)_hal_registers + +In case you are using a GDB stub burned in ROM to debug an application in RAM, +you first have to determine where the GDB stub stores the _hal_registers +variable in its own private region of RAM: use the tool m68k-elf-objdump to +find that. For example, if the address of the _hal_registers variable used by +the GDB stub is 0x1e88, then you should use the following command to display +the registers of the application being debugged: + +print *(struct HAL_SavedRegisters *)*0x1e88 + +It is also possible to modify the value of the MAC registers, by updating the +relative field of the HAL_SavedRegisters structure. Don't try to modify the +other registers because the modifications will be discarded when the +application is restarted: use the usual GDB commands instead. Finally, the +correct value of the PC register is the one shown by the "info registers" +command. + +* I added at the architecture level only the features that I could directly +test. When I developed the architecture HAL, I had a ColdFire MCF5272 at +hands, which has a MAC unit. That's why in the architecture HAL there is +currently only support for the MAC unit, and no support for the EMAC and +floating point units. However, I tried to write the HAL in the most generic +fashion I could imagine, in order to make it easy to add new architectural +features and new processor variants. + +* If you want to burn an eCos image into the flash ROM, you cannot rely on the +ROM monitor provided with the board, but you have to use the BDM interface. +If you work under Windows, you can use the free CFFlasher utility, available +on the Freescale Semiconductor web site. The BDM tools also contain a +text-mode utility to do that, but I have not tested it. + + +Enrico Piria (epiria AT fastwebnet DOT it) +November 16, 2005 diff --git a/packages/hal/coldfire/arch/v2_0/include/arch.inc b/packages/hal/coldfire/arch/v2_0/include/arch.inc new file mode 100644 index 00000000..641c7e00 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/arch.inc @@ -0,0 +1,257 @@ +#ifndef CYGONCE_HAL_ARCH_INC +#define CYGONCE_HAL_ARCH_INC +|============================================================================= +| +| arch.inc +| +| ColdFire architecture assembler header file +| +|============================================================================= +|###ECOSGPLCOPYRIGHTBEGIN#### +| ------------------------------------------- +| This file is part of eCos, the Embedded Configurable Operating System. +| Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +| Copyright (C) 2006 eCosCentric Ltd. +| +| 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): Enrico Piria +| Contributors: +| Date: 2005-25-06 +| Purpose: MCF5272 variant definitions. +| Description: This file contains macro definitions used in the +| architecture HAL assembler file. +| +|####DESCRIPTIONEND#### +|========================================================================== + + +#define FUNC_START(name) \ + .text; \ + .balign 4; \ + .type name,@function; \ + .globl name; \ +name: + + +| ---------------------------------------------------------------------------- +| Macros to deal with the interrupt priority level in the status register. + + .macro hal_cpu_int_disable + move.w #0x2700,%sr + .endm + + + .macro hal_cpu_int_enable work + move.w %sr,\work + and.l #0xf8ff,\work + move.w \work,%sr + .endm + + + .macro hal_cpu_int_merge from work + move.w %sr,\work + and.l #0xf8ff,\work + and.l #0x0700,\from + or.l \from,\work + move.w \work,%sr + .endm + +| ---------------------------------------------------------------------------- +| Macro to find the value the SP register had before an exception. + + .macro find_original_sp out + move.b CYGARC_CF_FMTVECWORD(%sp),\out + lsr.l #4,\out + and.l #0x00000003,\out + add.l #CYGARC_CF_EXCEPTION_SIZE,\out + add.l %sp,\out + .endm + + +| ---------------------------------------------------------------------------- +| Macros used to save and restore MAC registers during interrupts/exceptions. + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + .macro save_mac_registers work + | Store MACSR register + move.l %macsr,\work + move.l \work,CYGARC_CFREG_MACSR(%sp) + + | Switch to integer mode. This allows to save the contents of ACC + | without rounding + and.l #0x000000df,\work + move.l \work,%macsr + + | Store ACC register + move.l %acc,\work + move.l \work,CYGARC_CFREG_MACC(%sp) + + | Store MASK register + move.l %mask,\work + move.l \work,CYGARC_CFREG_MASK(%sp) + .endm + + + .macro restore_mac_registers work + | Load MACSR register + move.l CYGARC_CFREG_MACSR(%sp),\work + move.l \work,%macsr + + | Load ACC register + move.l CYGARC_CFREG_MACC(%sp),\work + move.l \work,%acc + + | Load MASK register + move.l CYGARC_CFREG_MASK(%sp),\work + move.l \work,%mask + .endm +#endif + + +| ---------------------------------------------------------------------------- +| Macros used to save registers in interrupt handlers. During an interrupt, +| we save registers %d0-%d1 and %a0-%a1 because of the GNU C calling +| conventions. During the handler we also need register %d2. + +#ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + .macro int_pres_regs + lea.l -CYGARC_CF_EXCEPTION_DECREMENT(%sp),%sp + movem.l %d0-%d2,CYGARC_CFREG_DREGS(%sp) + movem.l %a0-%a1,CYGARC_CFREG_AREGS(%sp) + .endm + + + .macro int_rest_regs + movem.l CYGARC_CFREG_AREGS(%sp),%a0-%a1 + movem.l CYGARC_CFREG_DREGS(%sp),%d0-%d2 + lea.l CYGARC_CF_EXCEPTION_DECREMENT(%sp),%sp + .endm + +#else /* CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT */ + + .macro int_pres_regs + lea.l -CYGARC_CF_EXCEPTION_DECREMENT(%sp),%sp + movem.l %d0-%d7,CYGARC_CFREG_DREGS(%sp) + movem.l %a0-%a6,CYGARC_CFREG_AREGS(%sp) + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + save_mac_registers %d0 +#endif + + | Save old SP (before interrupt) + find_original_sp %d0 + move.l %d0,CYGARC_CFREG_SP(%sp) + .endm + + + .macro int_rest_regs + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + restore_mac_registers %d0 +#endif + + movem.l CYGARC_CFREG_AREGS(%sp),%a0-%a6 + movem.l CYGARC_CFREG_DREGS(%sp),%d0-%d7 + lea.l CYGARC_CF_EXCEPTION_DECREMENT(%sp),%sp + .endm + +#endif /* CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT */ + + +| ---------------------------------------------------------------------------- +| Macros used to save/restore registers during context switches. +| We don't save registers %d0-%d1 and %a0-%a1 because of the GNU C calling +| conventions: these macros are used in a routine called by C code. + +#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM + + .macro ctx_save_registers + lea -CYGARC_CF_CONTEXT_SIZE(%sp),%sp + movem.l %d2-%d7,CYGARC_CFREG_D2(%sp) + movem.l %a2-%a6,CYGARC_CFREG_A2(%sp) +#ifdef CYGHWR_HAL_COLDFIRE_MAC + save_mac_registers %d0 +#endif + | Save SR and interrupt level + move.w %sr,%d0 + move.w %d0,CYGARC_CF_SR(%sp) + .endm + + + .macro ctx_restore_registers + | Restore SR and interrupt level + move.w CYGARC_CF_SR(%sp),%d0 + move.w %d0,%sr + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + restore_mac_registers %d0 +#endif + movem.l CYGARC_CFREG_D2(%sp),%d2-%d7 + movem.l CYGARC_CFREG_A2(%sp), %a2-%a6 + lea CYGARC_CF_CONTEXT_SIZE(%sp),%sp + .endm + +#else /* CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM */ + + .macro ctx_save_registers + | Save all of the registers + lea -CYGARC_CF_CONTEXT_SIZE(%sp),%sp + movem.l %d0-%d7,CYGARC_CFREG_DREGS(%sp) + movem.l %a0-%a7,CYGARC_CFREG_AREGS(%sp) +#ifdef CYGHWR_HAL_COLDFIRE_MAC + save_mac_registers %d0 +#endif + + | Save pc (useful during debugging with GDB) + lea (%pc),%a0 + move.l %a0,CYGARC_CFREG_PC(%sp) + + | Save SR and interrupt level + move.w %sr,%d0 + move.w %d0,CYGARC_CF_SR(%sp) + .endm + + + .macro ctx_restore_registers + | Restore SR and interrupt level + move.w CYGARC_CF_SR(%sp),%d0 + move.w %d0,%sr + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + restore_mac_registers %d0 +#endif + movem.l CYGARC_CFREG_DREGS(%sp),%d0-%d7 + movem.l CYGARC_CFREG_AREGS(%sp),%a0-%a6 + lea CYGARC_CF_CONTEXT_SIZE(%sp),%sp + .endm +#endif /* CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM */ + +| ---------------------------------------------------------------------------- +| End of arch.inc +#endif /* ifndef CYGONCE_HAL_ARCH_INC */ diff --git a/packages/hal/coldfire/arch/v2_0/include/basetype.h b/packages/hal/coldfire/arch/v2_0/include/basetype.h new file mode 100644 index 00000000..27db5c63 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/basetype.h @@ -0,0 +1,79 @@ +#ifndef CYGONCE_HAL_BASETYPE_H +#define CYGONCE_HAL_BASETYPE_H + +//============================================================================= +// +// basetype.h +// +// Standard types for this architecture +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Provide ColdFire-specific type definitions. +// Usage: Included by "cyg_type.h", do not use directly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +// Include variant specific types +#include + + +// --------------------------------------------------------------------------- +// Characterize the architecture + +#define CYG_BYTEORDER CYG_MSBFIRST // Big endian + +// The ColdFire architecture uses the default definitions of the base types, +// so we do not need to define any here. + +// --------------------------------------------------------------------------- +// Override the alignment definitions from cyg_type.h + +#ifndef CYGARC_ALIGNMENT +#define CYGARC_ALIGNMENT 4 +#endif + +// The corresponding power of two alignment +#ifndef CYGARC_P2ALIGNMENT +#define CYGARC_P2ALIGNMENT 2 +#endif + +// --------------------------------------------------------------------------- +// End of basetype.h +#endif // CYGONCE_HAL_BASETYPE_H diff --git a/packages/hal/coldfire/arch/v2_0/include/coldfire_regs.h b/packages/hal/coldfire/arch/v2_0/include/coldfire_regs.h new file mode 100644 index 00000000..cc9af48a --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/coldfire_regs.h @@ -0,0 +1,65 @@ +#ifndef CYGONCE_HAL_CF_REGS_H +#define CYGONCE_HAL_CF_REGS_H + +//========================================================================== +// +// coldfire_regs.h +// +// ColdFire CPU definitions +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Provide ColdFire register definitions. +// Usage: #include +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include + +#include + + +// Macro to embed movec instructions in C code +#define CYGARC_MOVEC(_value_, _reg_) \ + asm volatile("movec %0,%1" : : "d" (_value_), "i" (_reg_)) + + +// --------------------------------------------------------------------------- +// End of coldfire_regs.h +#endif // ifdef CYGONCE_HAL_CF_REGS_H diff --git a/packages/hal/coldfire/arch/v2_0/include/coldfire_stub.h b/packages/hal/coldfire/arch/v2_0/include/coldfire_stub.h new file mode 100644 index 00000000..51bc7b20 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/coldfire_stub.h @@ -0,0 +1,135 @@ +#ifndef CYGONCE_HAL_COLDFIRE_STUB_H +#define CYGONCE_HAL_COLDFIRE_STUB_H + +//======================================================================== +// +// coldfire_stub.h +// +// ColdFire-specific definitions for generic stub +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: +// Description: ColdFire-specific definitions for generic stub. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#ifdef __cplusplus +extern "C" { +#endif + +#define NUMREGS 18 + +// ColdFire stub has special needs for register handling because flating point +// registers are bigger than the rest. Special put_register and get_register +// are provided. +#define CYGARC_STUB_REGISTER_ACCESS_DEFINED 1 + +#define REGSIZE( _x_ ) (4) + +typedef unsigned long target_register_t; + +enum regnames { + D0, D1, D2, D3, D4, D5, D6, D7, + A0, A1, A2, A3, A4, A5, A6, A7, + SR, PC, +}; + +#define SP A7 + +typedef enum regnames regnames_t; + +// Given a trap value TRAP, return the corresponding signal +extern int __computeSignal(unsigned int trap_number); + +// Return the ColdFire trap number corresponding to the last-taken trap +extern int __get_trap_number(void); + +// Return the currently-saved value corresponding to register REG +extern target_register_t get_register(regnames_t reg); + +// Store VALUE in the register corresponding to WHICH +extern void put_register(regnames_t which, target_register_t value); + +// Read the contents of register WHICH into VALUE as raw bytes +extern int get_register_as_bytes(regnames_t which, char *value); + +// Write the contents of register WHICH into VALUE as raw bytes +extern int put_register_as_bytes(regnames_t which, char *value); + +// Set the currently-saved pc register value to PC. This also updates NPC +// as needed. +extern void set_pc(target_register_t pc); + +// Set things up so that the next user resume will execute one instruction. +// This may be done by setting breakpoints or setting a single step flag +// in the saved user registers, for example. +extern void __single_step(void); + +// Clear the single-step state +extern void __clear_single_step(void); + +// If the breakpoint we hit is in the breakpoint() instruction, return a +// non-zero value +extern int __is_breakpoint_function(void); + +// Skip the current instruction +extern void __skipinst(void); + +extern void __install_breakpoints(void); + +extern void __clear_breakpoints(void); + +// We have to rewind the PC in case of a breakpoint. +#define HAL_STUB_PLATFORM_STUBS_FIXUP() \ +CYG_MACRO_START \ + if (CYGNUM_HAL_VECTOR_DEBUGTRAP == __get_trap_number()) \ + { \ + CYG_ADDRESS pc = get_register(PC) - HAL_BREAKINST_SIZE; \ + put_register(PC, pc); \ + } \ +CYG_MACRO_END + +#ifdef __cplusplus +} // extern "C" +#endif + +// --------------------------------------------------------------------------- +// End of coldfire_stub.h +#endif // ifndef CYGONCE_HAL_COLDFIRE_STUB_H diff --git a/packages/hal/coldfire/arch/v2_0/include/hal_arch.h b/packages/hal/coldfire/arch/v2_0/include/hal_arch.h new file mode 100644 index 00000000..b86976bb --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/hal_arch.h @@ -0,0 +1,473 @@ +#ifndef CYGONCE_HAL_ARCH_H +#define CYGONCE_HAL_ARCH_H + +//============================================================================= +// +// hal_arch.h +// +// Architecture specific abstractions +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: +// Description: Definitions for the ColdFire architecture HAL. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include + +// Include some variant specific architectural defines +#include + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#include +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +// ---------------------------------------------------------------------------- +// Macros to deal with exception stack frame fields + +// The ColdFire family of processors has a simplified exception stack +// frame that looks like the following: +// +// 8 +----------------+----------------+ +// | Program Counter | +// 4 +----------------+----------------+ +// |Fmt/FS/Vector/FS| SR | +// SP --> 0 +----------------+----------------+ +// The stack self-aligns to a 4-byte boundary at an exception, with +// the Fmt/FS/Vector/FS field indicating the size of the adjustment +// (SP += 0,1,2,3 bytes). + +// Define the Fmt/FS/Vector/FS word. +// Bits 31-28 are the format word which tells the +// RTI instruction how to align the stack. +#define HAL_CF_EXCEPTION_FORMAT_MSK ((CYG_WORD16)0xF000) +// Bits 25-18 are the vector number of the exception. +#define HAL_CF_EXCEPTION_VECTOR_MSK ((CYG_WORD16)0x03FC) +// Bits 27-26, and 17-16 are the fault status used +// for bus and address errors. +#define HAL_CF_EXCEPTION_FS32_MSK ((CYG_WORD16)0x0C00) +#define HAL_CF_EXCEPTION_FS10_MSK ((CYG_WORD16)0x0003) + +// Macros to access fields in the format vector word. + +#define HAL_CF_EXCEPTION_FORMAT(_fmt_vec_word_) \ + ((((CYG_WORD16)(_fmt_vec_word_)) & HAL_CF_EXCEPTION_FORMAT_MSK) >> 12) + +#define HAL_CF_EXCEPTION_VECTOR(_fmt_vec_word_) \ + ((((CYG_WORD16)(_fmt_vec_word_)) & HAL_CF_EXCEPTION_VECTOR_MSK) >> 2) + +#define HAL_CF_EXCEPTION_FS(_fmt_vec_word_) \ + (((((CYG_WORD16)(_fmt_vec_word_)) & HAL_CF_EXCEPTION_FS32_MSK) >> 8) \ + | (((CYG_WORD16)(_fmt_vec_word_)) & HAL_CF_EXCEPTION_FS10_MSK)) + +// ---------------------------------------------------------------------------- +// HAL_SavedRegisters -- Saved by a context switch or by an exception/interrupt + +typedef struct +{ + // These are common to all saved states and are in the order + // stored and loaded by the movem instruction. + + // Data regs D0-D7 + CYG_WORD32 d[8]; + + // Address regs A0-A7 + CYG_ADDRESS a[8]; + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + // MAC registers + CYG_WORD32 macc; + CYG_WORD32 macsr; + CYG_WORD32 mask; +#endif + + // On exception/interrupt PC, SR and exception are pushed on the + // stack automatically, so there is no need to allocate the entire + // structure. + + // 16-bit format/vector word + CYG_WORD16 fmt_vec_word; + + // Status register + CYG_WORD16 sr; + + // Program counter + CYG_ADDRESS pc; + +} __attribute__ ((aligned, packed)) HAL_SavedRegisters; + +#ifndef HAL_THREAD_SWITCH_CONTEXT + +// *************************************************************************** +// HAL_THREAD_SWITCH_CONTEXT +// +// This macro saves the state of the currently running thread and writes +// its stack pointer to *(_fspptr_). +// It then switches to the thread context that *(_tspptr_) points to. +// +// INPUT: +// _fspptr_: A pointer to the location to save the current thread's stack +// pointer to. +// +// _tspptr_: A pointer to the location containing the stack pointer of +// the thread context to switch to. +// +// OUTPUT: +// *(_fspptr_): Contains the stack pointer of the previous thread's context. +// +// *************************************************************************** + +externC void hal_thread_switch_context( CYG_ADDRESS to, CYG_ADDRESS from ); +externC void hal_thread_load_context( CYG_ADDRESS to ) + CYGBLD_ATTRIB_NORET; + +#define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_) \ + hal_thread_switch_context((CYG_ADDRESS)_tspptr_,(CYG_ADDRESS)_fspptr_); +#endif // HAL_THREAD_SWITCH_CONTEXT + +#ifndef HAL_THREAD_LOAD_CONTEXT + +// *************************************************************************** +// hal_thread_load_context +// +// This routine loads the thread context that *(_tspptr_) points to. +// This routine does not return. +// +// INPUT: +// _tspptr_: A pointer to the location containing the stack pointer of +// the thread context to switch to. +// +// *************************************************************************** + +#define HAL_THREAD_LOAD_CONTEXT(_tspptr_) \ + hal_thread_load_context( (CYG_ADDRESS)_tspptr_ ); +#endif // HAL_THREAD_LOAD_CONTEXT + + +#ifndef HAL_THREAD_INIT_CONTEXT + +// *************************************************************************** +// HAL_THREAD_INIT_CONTEXT -- Context Initialization +// +// Initialize the context of a thread. +// +// INPUT: +// _sparg_: The name of the variable containing the current sp. This +// will be written with the new sp. +// +// _thread_: The thread object address, passed as argument to entry +// point. +// +// _entry_: The thread's entry point address. +// +// _id_: A bit pattern used in initializing registers, for debugging. +// +// OUTPUT: +// _sparg_: Updated with the value of the new sp. +// +// *************************************************************************** + +#define HAL_THREAD_INIT_CONTEXT(_sparg_, _thread_, _entry_, _id_) \ + CYG_MACRO_START \ + CYG_WORD32 * _sp_ = ((CYG_WORD32*)((CYG_WORD32)(_sparg_) & ~15)); \ + HAL_SavedRegisters * _regs_; \ + int _i_; \ + \ + /* Thread's parameter. */ \ + *(--_sp_) = (CYG_WORD32)(_thread_); \ + /* Fake thread's return addr. Needed because thread is a function */ \ + /* and parameters to functions are always follwed by the return */ \ + /* address on the stack. */ \ + *(--_sp_) = (CYG_WORD32)(0xDEADC0DE); \ + /* Thread's return addr. (used by hal_thread_load_context) */ \ + *(--_sp_) = (CYG_WORD32)(_entry_); \ + \ + _regs_ = (HAL_SavedRegisters *) \ + ((CYG_WORD32)_sp_ - sizeof(HAL_SavedRegisters)); \ + \ + for (_i_=0; _i_ < 8; _i_++) \ + _regs_->a[_i_] = _regs_->d[_i_] = (_id_); \ + /* A6, initial frame pointer should be null */ \ + _regs_->a[6] = (CYG_ADDRESS)0; \ + \ + /* Thread's starting SR. All interrupts enabled. */ \ + _regs_->sr = 0x3000; \ + \ + /* Thread's starting PC */ \ + _regs_->pc = (CYG_ADDRESS)(_entry_); \ + \ + (_sparg_) = (CYG_ADDRESS)_regs_; \ + CYG_MACRO_END +#endif // HAL_THREAD_INIT_CONTEXT + +// ---------------------------------------------------------------------------- +// Bit manipulation routines. + +externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask); +externC cyg_uint32 hal_msbit_index(cyg_uint32 mask); + +#define HAL_LSBIT_INDEX(index, mask) (index) = hal_lsbit_index(mask); + +#define HAL_MSBIT_INDEX(index, mask) (index) = hal_msbit_index(mask); + +// ---------------------------------------------------------------------------- +// Idle thread code. +// This macro is called in the idle thread loop, and gives the HAL the +// chance to insert code. Typical idle thread behaviour might be to halt the +// processor. + +externC void hal_idle_thread_action(cyg_uint32 loop_count); + +#define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_) + +// ---------------------------------------------------------------------------- +// Execution reorder barrier. +// When optimizing the compiler can reorder code. In multithreaded systems +// where the order of actions is vital, this can sometimes cause problems. +// This macro may be inserted into places where reordering should not happen. + +#define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" ) + +// ---------------------------------------------------------------------------- +// Breakpoint support +// HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen +// if executed. +// HAL_BREAKINST is the value of the breakpoint instruction and +// HAL_BREAKINST_SIZE is its size in bytes. + +// The host side of GDB debugger uses trap #15 to install breakpoints. + +#define CYGNUM_HAL_VECTOR_DEBUGTRAP 47 + +#define HAL_BREAKPOINT(_label_) \ +asm volatile (" .globl " #_label_ ";" \ + #_label_":" \ + " trap #15" \ + ); + +#define HAL_BREAKINST 0x4E4F + +#define HAL_BREAKINST_SIZE 2 + + +// ---------------------------------------------------------------------------- +// Thread register state manipulation for GDB support. + +typedef struct { + cyg_uint32 d[8]; + cyg_uint32 a[8]; + cyg_uint32 pc; + cyg_uint32 sr; +} GDB_Registers; + +// Translate a stack pointer as saved by the thread context macros above into +// a pointer to a HAL_SavedRegisters structure. +#define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ ) \ + (_regs_) = (HAL_SavedRegisters *)(_sp_) + + +// Copy a set of registers from a HAL_SavedRegisters structure into a +// GDB ordered array. +#define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ ) \ + CYG_MACRO_START \ + union __gdbreguniontype { \ + __typeof__(_aregval_) _aregval2_; \ + GDB_Registers *_gdbr; \ + } __gdbregunion; \ + __gdbregunion._aregval2_ = (_aregval_); \ + GDB_Registers *_gdb_ = __gdbregunion._gdbr; \ + int _i_; \ + \ + for( _i_ = 0; _i_ < 8; _i_++ ) \ + { \ + _gdb_->d[_i_] = (_regs_)->d[_i_]; \ + _gdb_->a[_i_] = (_regs_)->a[_i_]; \ + } \ + \ + _gdb_->pc = (_regs_)->pc; \ + _gdb_->sr = (cyg_uint32) ((_regs_)->sr); \ + CYG_MACRO_END + +// Copy a GDB ordered array into a HAL_SavedRegisters structure. +#define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ ) \ + CYG_MACRO_START \ + union __gdbreguniontype { \ + __typeof__(_aregval_) _aregval2_; \ + GDB_Registers *_gdbr; \ + } __gdbregunion; \ + __gdbregunion._aregval2_ = (_aregval_); \ + GDB_Registers *_gdb_ = __gdbregunion._gdbr; \ + int _i_; \ + \ + for( _i_ = 0; _i_ < 8; _i_++ ) \ + { \ + (_regs_)->d[_i_] = _gdb_->d[_i_]; \ + (_regs_)->a[_i_] = _gdb_->a[_i_]; \ + } \ + \ + (_regs_)->pc = _gdb_->pc; \ + (_regs_)->sr = (CYG_WORD16)(_gdb_->sr); \ + CYG_MACRO_END + + +#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ + defined(CYGPKG_HAL_EXCEPTIONS) + +// ---------------------------------------------------------------------------- +// Exception handling function. +// This function is defined by the kernel according to this prototype. It is +// invoked from the HAL to deal with any CPU exceptions that the HAL does +// not want to deal with itself. It usually invokes the kernel's exception +// delivery mechanism. + +externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data ); + +#endif // defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) + +// ---------------------------------------------------------------------------- +// Minimal and sensible stack sizes: the intention is that applications +// will use these to provide a stack size in the first instance prior to +// proper analysis. Idle thread stack should be this big. + +// THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES. +// THEY ARE HOWEVER ENOUGH TO START PROGRAMMING. +// YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES! + +// This is not a config option because it should not be adjusted except +// under "enough rope" sort of disclaimers. + +// Stack frame overhead per call: 6 data registers, 5 address registers, +// frame pointer, and return address. We can't guess the local variables so +// just assume that using all of the registers averages out. + +#define CYGNUM_HAL_STACK_FRAME_SIZE ((6 + 5 + 1 + 1) * 4) + +// Stack needed for a context switch. +// All registers + pc + sr + vector. + +#ifndef CYGNUM_HAL_STACK_CONTEXT_SIZE +#define CYGNUM_HAL_STACK_CONTEXT_SIZE ((8+8+1)*4 + (1+1)*2) +#endif // CYGNUM_HAL_STACK_CONTEXT_SIZE + +// Interrupt (rounded up) + call to ISR, interrupt_end() and the DSR. + +#define CYGNUM_HAL_STACK_INTERRUPT_SIZE \ + ((CYGNUM_HAL_STACK_CONTEXT_SIZE) + (2*CYGNUM_HAL_STACK_FRAME_SIZE)) + +// We define a minimum stack size as the minimum any thread could ever +// legitimately get away with. We can throw asserts if users ask for less +// than this. Allow enough for four interrupt sources - clock, serial, +// nic, and one other. + +// No separate interrupt stack exists. Make sure all threads contain +// a stack sufficiently large. + +#define CYGNUM_HAL_STACK_SIZE_MINIMUM \ + ((4*CYGNUM_HAL_STACK_INTERRUPT_SIZE) \ + + (16*CYGNUM_HAL_STACK_FRAME_SIZE)) + +// Now make a reasonable choice for a typical thread size. Pluck figures +// from thin air and say 30 call frames with an average of 16 words of +// automatic variables per call frame. + +#define CYGNUM_HAL_STACK_SIZE_TYPICAL \ + (CYGNUM_HAL_STACK_SIZE_MINIMUM + \ + (30 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4)))) + +// ------------------------------------------------------------------------- +// Macros for switching context between two eCos instances (jump from +// code in ROM to code in RAM or vice versa). + +#define CYGARC_HAL_SAVE_GP() +#define CYGARC_HAL_RESTORE_GP() + +// ------------------------------------------------------------------------- +// hal_setjmp/hal_longjmp + + +// We must save all of the registers that are preserved across routine +// calls. The assembly code assumes that this structure is defined in the +// following format. Any changes to this structure will result in changes to +// the assembly code!! + +typedef struct { + // D registers + cyg_uint32 d2; + cyg_uint32 d3; + cyg_uint32 d4; + cyg_uint32 d5; + cyg_uint32 d6; + cyg_uint32 d7; + + // A registers + cyg_uint32 a2; + cyg_uint32 a3; + cyg_uint32 a4; + cyg_uint32 a5; + cyg_uint32 a6; + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + // MAC registers + cyg_uint32 macc; + cyg_uint32 macsr; + cyg_uint32 mask; +#endif + + // SP and PC + cyg_uint32 sp; + cyg_uint32 pc; +} hal_jmp_buf_t; + +// This type is used by normal routines to pass the address of the structure +// into our routines without having to explicitly take the address +// of the structure. + +typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)]; + +// Define the generic setjmp and longjmp routines +externC int hal_setjmp(hal_jmp_buf env); +externC void hal_longjmp(hal_jmp_buf env, int val); +#define hal_setjmp(_env) hal_setjmp(_env) +#define hal_longjmp(_env, _val) hal_longjmp(_env, _val) + +// --------------------------------------------------------------------------- +// End of hal_arch.h +#endif // CYGONCE_HAL_ARCH_H diff --git a/packages/hal/coldfire/arch/v2_0/include/hal_cache.h b/packages/hal/coldfire/arch/v2_0/include/hal_cache.h new file mode 100644 index 00000000..579af191 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/hal_cache.h @@ -0,0 +1,60 @@ +#ifndef CYGONCE_HAL_CACHE_H +#define CYGONCE_HAL_CACHE_H + +//============================================================================= +// +// hal_cache.h +// +// HAL cache control API +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Provide ColdFire-specific cache control definitions. +// Usage: #include +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include + +#include + +// --------------------------------------------------------------------------- +// End of hal_cache.h +#endif // ifndef CYGONCE_HAL_CACHE_H diff --git a/packages/hal/coldfire/arch/v2_0/include/hal_intr.h b/packages/hal/coldfire/arch/v2_0/include/hal_intr.h new file mode 100644 index 00000000..600b509d --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/hal_intr.h @@ -0,0 +1,344 @@ +#ifndef CYGONCE_HAL_HAL_INTR_H +#define CYGONCE_HAL_HAL_INTR_H + +//========================================================================== +// +// hal_intr.h +// +// ColdFire interrupt/exception support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Provide ColdFire-specific interrupt and exception +// definitions. +// Usage: #include +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include +#include + +#include + +#include // CYG_FAIL + +// ------------------------------------------------------------------------- +// ColdFire exception vectors. These correspond to VSRs and are the values +// to use for HAL_VSR_GET/SET. + +#define CYGNUM_HAL_VECTOR_RESETSP 0 +#define CYGNUM_HAL_VECTOR_RESETPC 1 +#define CYGNUM_HAL_VECTOR_BUSERR 2 +#define CYGNUM_HAL_VECTOR_ADDRERR 3 +#define CYGNUM_HAL_VECTOR_ILLINST 4 +#define CYGNUM_HAL_VECTOR_ZERODIV 5 + +// Exception vectors 6-7 are reserved + +#define CYGNUM_HAL_VECTOR_PRIVVIOLATION 8 +#define CYGNUM_HAL_VECTOR_TRACE 9 +#define CYGNUM_HAL_VECTOR_L1010 10 +#define CYGNUM_HAL_VECTOR_L1111 11 +#define CYGNUM_HAL_VECTOR_DEBUG12 12 +#define CYGNUM_HAL_VECTOR_DEBUG13 13 +#define CYGNUM_HAL_VECTOR_FORMAT 14 +#define CYGNUM_HAL_VECTOR_UNINITINT 15 + +// Exception vectors 16-23 are reserved + +#define CYGNUM_HAL_VECTOR_SPURINT 24 + +#define CYGNUM_HAL_VECTOR_AUTOVEC1 25 +#define CYGNUM_HAL_VECTOR_AUTOVEC2 26 +#define CYGNUM_HAL_VECTOR_AUTOVEC3 27 +#define CYGNUM_HAL_VECTOR_AUTOVEC4 28 +#define CYGNUM_HAL_VECTOR_AUTOVEC5 29 +#define CYGNUM_HAL_VECTOR_AUTOVEC6 30 +#define CYGNUM_HAL_VECTOR_AUTOVEC7 31 +#define CYGNUM_HAL_NUMAUTOVEC 7 + +#define CYGNUM_HAL_VECTOR_TRAPFIRST 32 +#define CYGNUM_HAL_VECTOR_TRAPLAST 47 +#define CYGNUM_HAL_NUMTRAPS 16 + +#define CYGNUM_HAL_VECTOR_FP_BRANCH 48 +#define CYGNUM_HAL_VECTOR_FP_INEXACT 49 +#define CYGNUM_HAL_VECTOR_FP_ZERODIV 50 +#define CYGNUM_HAL_VECTOR_FP_UNDERFLOW 51 +#define CYGNUM_HAL_VECTOR_FP_OPERAND 52 +#define CYGNUM_HAL_VECTOR_FP_OVERFLOW 53 +#define CYGNUM_HAL_VECTOR_FP_NAN 54 +#define CYGNUM_HAL_VECTOR_FP_DENORM 55 + +// Exception vectors 56-60 are reserved + +#define CYGNUM_HAL_VECTOR_UNSUPINST 61 + +// Exception vectors 62-63 are reserved + +#define CYGNUM_HAL_VECTOR_USERINTRFIRST 64 +#define CYGNUM_HAL_VECTOR_USERINTRLAST 255 +#define CYGNUM_HAL_NUMUSERINTR 192 + +// ------------------------------------------------------------------------- +// Interrupt and exception vector table definitions. + +#define CYGNUM_HAL_VSR_MIN 0 +#define CYGNUM_HAL_VSR_MAX 255 +#define CYGNUM_HAL_VSR_COUNT (CYGNUM_HAL_VSR_MAX - CYGNUM_HAL_VSR_MIN + 1) + +// To simplify things in interrupt handling code, we don't take into account +// autovectored, spurious and uninitialized interrupts. + +#ifndef CYGNUM_HAL_ISR_RANGE_DEFINED +#define CYGNUM_HAL_ISR_MIN CYGNUM_HAL_VECTOR_USERINTRFIRST +#define CYGNUM_HAL_ISR_MAX CYGNUM_HAL_VECTOR_USERINTRLAST +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_ISR_MAX - CYGNUM_HAL_ISR_MIN + 1) +#endif + +#ifndef CYGNUM_HAL_EXCEPTION_RANGE_DEFINED +#define CYGNUM_HAL_EXCEPTION_MIN CYGNUM_HAL_VECTOR_BUSERR +#define CYGNUM_HAL_EXCEPTION_MAX CYGNUM_HAL_VECTOR_UNSUPINST +#define CYGNUM_HAL_EXCEPTION_COUNT (CYGNUM_HAL_EXCEPTION_MAX -\ + CYGNUM_HAL_EXCEPTION_MIN + 1) +#endif + +// ------------------------------------------------------------------------- +// Equivalence between ColdFire exception names and target independent +// exception names. +// These are the values used when passed out to an +// external exception handler using cyg_hal_deliver_exception(). + +#define CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION CYGNUM_HAL_VECTOR_ILLINST +#define CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO CYGNUM_HAL_VECTOR_ZERODIV +#define CYGNUM_HAL_EXCEPTION_DATA_ACCESS CYGNUM_HAL_VECTOR_BUSERR +#define CYGNUM_HAL_EXCEPTION_CODE_ACCESS CYGNUM_HAL_VECTOR_BUSERR + +// ------------------------------------------------------------------------- +// Spurious interrupt definition. + +#ifndef CYGNUM_HAL_SPURIOUS_INTERRUPT +#define CYGNUM_HAL_SPURIOUS_INTERRUPT CYGNUM_HAL_VECTOR_SPURINT +#endif + +// ------------------------------------------------------------------------- +// Static data used by HAL. + +// ISR tables +externC volatile CYG_ADDRESS cyg_hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; +externC volatile CYG_ADDRWORD cyg_hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; +externC volatile CYG_ADDRESS cyg_hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; + +// VSR table +externC volatile CYG_ADDRESS cyg_hal_vsr_table[CYGNUM_HAL_VSR_COUNT]; + +// ROM VSR table +externC CYG_ADDRESS rom_vsr_table[CYGNUM_HAL_VSR_COUNT]; + +// ------------------------------------------------------------------------- +// Interrupt stack definitions. + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + +externC void hal_interrupt_stack_call_pending_DSRs(void); +#define HAL_INTERRUPT_STACK_CALL_PENDING_DSRS() \ + hal_interrupt_stack_call_pending_DSRs() + +#endif + +// A separate stack always exist to allow the processor to initialize itself. +// It depends on CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK macro +// definition if this stack is used for interrupts too. + +#define HAL_INTERRUPT_STACK_BASE cyg_interrupt_stack_base +#define HAL_INTERRUPT_STACK_TOP cyg_interrupt_stack + +externC char HAL_INTERRUPT_STACK_BASE[]; +externC char HAL_INTERRUPT_STACK_TOP[]; + +// -------------------------------------------------------------------------- +// Translate a vector number into an ISR table index. + +#ifndef HAL_TRANSLATE_VECTOR +#define HAL_TRANSLATE_VECTOR(_vector_,_index_) (_index_) = (_vector_- CYGNUM_HAL_ISR_MIN) +#endif + +// ------------------------------------------------------------------------- +// Interrupt state storage. + +typedef cyg_uint16 CYG_INTERRUPT_STATE; + +// -------------------------------------------------------------------------- +// Interrupt and VSR attachment macros. + +externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); + +externC void hal_default_exception_handler(CYG_WORD vector, + HAL_SavedRegisters *regs); + +#define HAL_INTERRUPT_IN_USE( _vector_, _state_) \ +CYG_MACRO_START \ + cyg_uint32 _index_; \ + HAL_TRANSLATE_VECTOR ((_vector_), _index_); \ + \ + if (cyg_hal_interrupt_handlers[_index_] \ + == (CYG_ADDRESS) &hal_default_isr) \ + (_state_) = 0; \ + else \ + (_state_) = 1; \ +CYG_MACRO_END + +#define HAL_INTERRUPT_ATTACH( _vector_, _isr_, _data_, _object_ ) \ +CYG_MACRO_START \ + cyg_uint32 _index_; \ + HAL_TRANSLATE_VECTOR((_vector_), _index_); \ + \ + if (cyg_hal_interrupt_handlers[_index_] \ + == (CYG_ADDRESS) &hal_default_isr) \ + { \ + cyg_hal_interrupt_handlers[_index_] = (CYG_ADDRESS)(_isr_); \ + cyg_hal_interrupt_data[_index_] = (CYG_ADDRWORD)(_data_); \ + cyg_hal_interrupt_objects[_index_] = (CYG_ADDRESS)(_object_); \ + } \ +CYG_MACRO_END + +#define HAL_INTERRUPT_DETACH( _vector_, _isr_ ) \ +CYG_MACRO_START \ + cyg_uint32 _index_; \ + HAL_INTERRUPT_MASK(_vector_); \ + HAL_TRANSLATE_VECTOR((_vector_), _index_); \ + if (cyg_hal_interrupt_handlers[_index_] \ + == (CYG_ADDRESS)(_isr_)) \ + { \ + cyg_hal_interrupt_handlers[_index_] = \ + (CYG_ADDRESS)&hal_default_isr; \ + cyg_hal_interrupt_data[_index_] = 0; \ + cyg_hal_interrupt_objects[_index_] = 0; \ + } \ +CYG_MACRO_END + +#define HAL_VSR_GET( _vector_, _pvsr_ ) \ + *((CYG_ADDRESS *)(_pvsr_)) = cyg_hal_vsr_table[(_vector_)]; + + +#define HAL_VSR_SET( _vector_, _vsr_, _poldvsr_ ) \ +CYG_MACRO_START \ + if( (_poldvsr_) != NULL ) \ + *(CYG_ADDRESS *)(_poldvsr_) = cyg_hal_vsr_table[(_vector_)]; \ + cyg_hal_vsr_table[(_vector_)] = (CYG_ADDRESS)(_vsr_); \ +CYG_MACRO_END + + +// This is an ugly name, but what it means is: grab the VSR back to eCos +// internal handling, or if you like, the default handler. But if +// cooperating with a ROM monitor, the default behaviour is to pass most +// exceptions to it. This macro undoes that so that eCos handles the +// exception. So use it with care. + +#define HAL_VSR_SET_TO_ECOS_HANDLER( _vector_, _poldvsr_ ) \ + CYG_MACRO_START \ + if( (void*)_poldvsr_ != (void*)NULL ) \ + *(CYG_ADDRESS *)_poldvsr_ = cyg_hal_vsr_table[_vector_]; \ + cyg_hal_vsr_table[_vector_] = rom_vsr_table[_vector_]; \ + CYG_MACRO_END + +// ------------------------------------------------------------------------- +// Interrupt control macros. + +// The following interrupt control macros are the default for the ColdFire +// architecture. Some processor variants will override these definitions in +// their var_intr.h file. + +#ifndef HAL_CF_SET_SR +#define HAL_CF_SET_SR(__newsr__) \ + CYG_MACRO_START \ + asm volatile ("move.w %0,%%sr\n" \ + : \ + : "d" ((CYG_INTERRUPT_STATE)(__newsr__))); \ + CYG_MACRO_END +#endif // HAL_CF_SET_SR + +#ifndef HAL_ENABLE_INTERRUPTS +#define HAL_ENABLE_INTERRUPTS() \ + CYG_MACRO_START \ + CYG_INTERRUPT_STATE _msk_; \ + HAL_QUERY_INTERRUPTS(_msk_); \ + HAL_CF_SET_SR((_msk_ & (CYG_INTERRUPT_STATE)0xf8ff)); \ + CYG_MACRO_END +#endif // HAL_ENABLE_INTERRUPTS + +#ifndef HAL_DISABLE_INTERRUPTS +#define HAL_DISABLE_INTERRUPTS(_old_) \ + CYG_MACRO_START \ + HAL_QUERY_INTERRUPTS(_old_); \ + HAL_CF_SET_SR((_old_ | (CYG_INTERRUPT_STATE)0x0700)); \ + CYG_MACRO_END +#endif //HAL_DISABLE_INTERRUPTS + +#ifndef HAL_RESTORE_INTERRUPTS +#define HAL_RESTORE_INTERRUPTS(_prev_) \ + CYG_MACRO_START \ + CYG_INTERRUPT_STATE _msk_; \ + HAL_QUERY_INTERRUPTS(_msk_); \ + _msk_ &= (CYG_INTERRUPT_STATE)0xf8ff; \ + _msk_ |= (((CYG_INTERRUPT_STATE)(_prev_)) \ + & (CYG_INTERRUPT_STATE)0x0700); \ + asm volatile ("move.w %0,%%sr\n" \ + : \ + : "d" (_msk_)); \ + CYG_MACRO_END +#endif // HAL_RESTORE_INTERRUPTS + +// Use the extra assignment to avoid warnings. +// The compiler should optimize it out. +#ifndef HAL_QUERY_INTERRUPTS +#define HAL_QUERY_INTERRUPTS(__oldmask__) \ + CYG_MACRO_START \ + CYG_INTERRUPT_STATE _omsk_ = (CYG_INTERRUPT_STATE)(__oldmask__); \ + asm volatile ("move.w %%sr,%0\n" \ + : "=d" (_omsk_) \ + : ); \ + (__oldmask__) = (__typeof__(__oldmask__))_omsk_; \ + CYG_MACRO_END +#endif // HAL_QUERY_INTERRUPTS + +// --------------------------------------------------------------------------- +// End of hal_intr.h +#endif // ifndef CYGONCE_HAL_HAL_INTR_H diff --git a/packages/hal/coldfire/arch/v2_0/include/hal_io.h b/packages/hal/coldfire/arch/v2_0/include/hal_io.h new file mode 100644 index 00000000..ceae9500 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/hal_io.h @@ -0,0 +1,154 @@ +#ifndef CYGONCE_HAL_HAL_IO_H +#define CYGONCE_HAL_HAL_IO_H + +//============================================================================= +// +// hal_io.h +// +// HAL device IO register support +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Provide ColdFire-specific IO register definitions. +// Usage: #include +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include + +// --------------------------------------------------------------------------- +// IO Register address. +// This type is for recording the address of an IO register. + +typedef volatile CYG_ADDRWORD HAL_IO_REGISTER; + +// --------------------------------------------------------------------------- +// BYTE Register access. +// Individual and vectorized access to 8 bit registers. + +#define HAL_READ_UINT8( _register_, _value_ ) \ + CYG_MACRO_START \ + ((_value_) = *((volatile CYG_BYTE *)(_register_))); \ + CYG_MACRO_END + +#define HAL_WRITE_UINT8( _register_, _value_ ) \ + CYG_MACRO_START \ + (*((volatile CYG_BYTE *)(_register_)) = (_value_)); \ + CYG_MACRO_END + +#define HAL_READ_UINT8_VECTOR( _register_, _buf_, _count_, _step_ ) \ + CYG_MACRO_START \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) { \ + (_buf_)[_i_] = ((volatile CYG_BYTE *)(_register_))[_j_]; \ + } \ + CYG_MACRO_END + +#define HAL_WRITE_UINT8_VECTOR( _register_, _buf_, _count_, _step_ ) \ + CYG_MACRO_START \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) { \ + ((volatile CYG_BYTE *)(_register_))[_j_] = (_buf_)[_i_]; \ + } \ + CYG_MACRO_END + + +// --------------------------------------------------------------------------- +// 16 bit access. +// Individual and vectorized access to 16 bit registers. + +#define HAL_READ_UINT16( _register_, _value_ ) \ + CYG_MACRO_START \ + ((_value_) = *((volatile CYG_WORD16 *)(_register_))); \ + CYG_MACRO_END + +#define HAL_WRITE_UINT16( _register_, _value_ ) \ + CYG_MACRO_START \ + (*((volatile CYG_WORD16 *)(_register_)) = (_value_)); \ + CYG_MACRO_END + +#define HAL_READ_UINT16_VECTOR( _register_, _buf_, _count_, _step_ ) \ + CYG_MACRO_START \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) { \ + (_buf_)[_i_] = ((volatile CYG_WORD16 *)(_register_))[_j_]; \ + } \ + CYG_MACRO_END + +#define HAL_WRITE_UINT16_VECTOR( _register_, _buf_, _count_, _step_ ) \ + CYG_MACRO_START \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) { \ + ((volatile CYG_WORD16 *)(_register_))[_j_] = (_buf_)[_i_]; \ + } \ + CYG_MACRO_END + +// --------------------------------------------------------------------------- +// 32 bit access. +// Individual and vectorized access to 32 bit registers. + +#define HAL_READ_UINT32( _register_, _value_ ) \ + CYG_MACRO_START \ + ((_value_) = *((volatile CYG_WORD32 *)(_register_))); \ + CYG_MACRO_END + +#define HAL_WRITE_UINT32( _register_, _value_ ) \ + CYG_MACRO_START \ + (*((volatile CYG_WORD32 *)(_register_)) = (_value_)); \ + CYG_MACRO_END + +#define HAL_READ_UINT32_VECTOR( _register_, _buf_, _count_, _step_ ) \ + CYG_MACRO_START \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) { \ + (_buf_)[_i_] = ((volatile CYG_WORD32 *)(_register_))[_j_]; \ + } \ + CYG_MACRO_END + +#define HAL_WRITE_UINT32_VECTOR( _register_, _buf_, _count_, _step_ ) \ + CYG_MACRO_START \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) { \ + ((volatile CYG_WORD32 *)(_register_))[_j_] = (_buf_)[_i_]; \ + } \ + CYG_MACRO_END + +// --------------------------------------------------------------------------- +// End of hal_io.h +#endif // ifndef CYGONCE_HAL_HAL_IO_H diff --git a/packages/hal/coldfire/arch/v2_0/include/hal_startup.h b/packages/hal/coldfire/arch/v2_0/include/hal_startup.h new file mode 100644 index 00000000..b9b0c21b --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/include/hal_startup.h @@ -0,0 +1,64 @@ +#ifndef CYGONCE_HAL_STARTUP_H +#define CYGONCE_HAL_STARTUP_H + +//============================================================================= +// +// hal_startup.h +// +// HAL startup definitions for the ColdFire architecture +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright eCosCentric Ltd. +// +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Provide ColdFire-specific startup definitions. +// Usage: #include +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include + +// Include the variant-specific startup header +#include + +externC void hal_reset(void) __attribute__ ((section (".boot"))); + +// --------------------------------------------------------------------------- +// End of hal_startup.h +#endif // CYGONCE_HAL_STARTUP_H diff --git a/packages/hal/coldfire/arch/v2_0/src/coldfire.ld b/packages/hal/coldfire/arch/v2_0/src/coldfire.ld new file mode 100644 index 00000000..68b202ee --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/src/coldfire.ld @@ -0,0 +1,265 @@ +//========================================================================== +// +// coldfire.ld +// +// Linker script +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Coldfire-specific linker script definitions. +// +//####DESCRIPTIONEND#### +//======================================================================== + +STARTUP(vectors.o) +ENTRY(_start) +#ifdef EXTRAS +INPUT(extras.o) +#endif +#if (__GNUC__ >= 3) +GROUP(libtarget.a libgcc.a libsupc++.a) +#else +GROUP(libtarget.a libgcc.a) +#endif + +#define ALIGN_LMA 4 +#define FOLLOWING(_section_) AT ((LOADADDR (_section_) + SIZEOF (_section_) + ALIGN_LMA - 1) & ~ (ALIGN_LMA - 1)) +#define LMA_EQ_VMA +#define FORCE_OUTPUT . = . + +#define SECTIONS_BEGIN + +#define SECTION_boot(_region_, _vma_, _lma_) \ + .boot _vma_ : _lma_ \ + { \ + FORCE_OUTPUT; \ + *(.boot*) \ + . = ALIGN(4); \ + } \ + > _region_ + +#define SECTION_text(_region_, _vma_, _lma_) \ + .text _vma_ : _lma_ \ + { \ + _stext = .; \ + *(.text*) *(.gnu.warning) *(.gnu.linkonce*) *(.init) \ + . = ALIGN(4); \ + } \ + > _region_ \ + _etext = .; PROVIDE (etext = .); + +#define SECTION_fini(_region_, _vma_, _lma_) \ + .fini _vma_ : _lma_ \ + { \ + FORCE_OUTPUT; \ + *(.fini) \ + . = ALIGN(4); \ + } \ + > _region_ + +#define SECTION_rodata1(_region_, _vma_, _lma_) \ + .rodata1 _vma_ : _lma_ \ + { \ + FORCE_OUTPUT; \ + *(.rodata1*) \ + . = ALIGN(4); \ + } \ + > _region_ + +#define SECTION_rodata(_region_, _vma_, _lma_) \ + .rodata _vma_ : _lma_ \ + { \ + FORCE_OUTPUT; \ + *(.rodata*) \ + . = ALIGN(4); \ + } \ + > _region_ + +#define SECTION_fixup(_region_, _vma_, _lma_) \ + .fixup _vma_ : _lma_ \ + { \ + __FIXUP_START__ = ABSOLUTE(.); \ + *(.fixup) \ + . = ALIGN(4); \ + __FIXUP_END__ = ABSOLUTE(.); \ + } \ + > _region_ + +#define SECTION_gcc_except_table(_region_, _vma_, _lma_) \ + .gcc_except_table _vma_ : _lma_ \ + { \ + __EXCEPT_START__ = ABSOLUTE(.); \ + *(.gcc_except_table) \ + . = ALIGN(4); \ + __EXCEPT_END__ = ABSOLUTE(.); \ + } \ + > _region_ + +#define SECTION_data(_region_, _vma_, _lma_) \ + .data _vma_ : _lma_ \ + { \ + __ram_data_start = ABSOLUTE(.); \ + *(.data*) \ + __GOT1_START__ = ABSOLUTE(.); \ + *(.got1) \ + __GOT1_END__ = ABSOLUTE(.); \ + . = ALIGN (4); \ + /* Put .ctors and .dtors next to the .got2 section, so that */ \ + /* the pointers get relocated with -mrelocatable. */ \ + __CTOR_LIST__ = ABSOLUTE(.); \ + KEEP(*(SORT(.ctors*))); \ + __CTOR_END__ = ABSOLUTE(.); \ + __DTOR_LIST__ = ABSOLUTE(.); \ + KEEP(*(SORT(.dtors*))) \ + __DTOR_END__ = ABSOLUTE(.); \ + . = ALIGN(4); \ + KEEP(*( SORT (.ecos.table.*))); \ + . = ALIGN (4); \ + *( .2ram.*) ; \ + __GOT2_START__ = ABSOLUTE(.); \ + *(.got2) \ + __GOT2_END__ = ABSOLUTE(.); \ + __GOT_START = ABSOLUTE(.); \ + _GLOBAL_OFFSET_TABLE_ = ABSOLUTE(. + 32768); \ + _SDA_BASE_ = ABSOLUTE(.); \ + *(.got.plt) *(.got) \ + __GOT_END__ = ABSOLUTE(.); \ + *(.dynamic) \ + *(.eh_frame) \ + /* We want the small data sections together, so single-instruction */ \ + /* offsets can access them all, and initialized data all before */ \ + /* uninitialized, so we can shorten the on-disk segment size. */ \ + __SDATA_START__ = ABSOLUTE(.); \ + *(.sdata) *(.sdata.*) \ + __SDATA2_START__ = ABSOLUTE(.); \ + *(.sdata2*) \ + . = ALIGN(4); \ + __ram_data_end = ABSOLUTE(.); \ + __ram_data_size = ABSOLUTE (.) - ABSOLUTE(__ram_data_start); \ + } \ + > _region_ \ + __rom_data_start = LOADADDR(.data); \ + __rom_data_size = SIZEOF(.data); \ + __rom_data_end = __rom_data_start + __rom_data_size; + +#define SECTION_bss(_region_, _vma_, _lma_) \ + .bss _vma_ : _lma_ \ + { \ + __bss_start = ABSOLUTE (.); \ + FORCE_OUTPUT; \ + *(.dynbss*) *(.bss*) *(COMMON) *(.sbss*) *(.scommon*) \ + . = ALIGN(4); \ + __bss_end = ABSOLUTE (.); \ + __bss_size = ABSOLUTE (.) - ABSOLUTE(__bss_start); \ + } \ + > _region_ + +#define SECTION_stab \ + .stab 0 (NOLOAD) : \ + { \ + *(.stab) \ + } + +#define SECTION_stabstr \ + .stabstr 0 (NOLOAD) : \ + { \ + *(.stabstr) \ + } + +#define SECTION_comment \ + .comment 0 (NOLOAD) : \ + { \ + *(.comment) \ + } + +#define SECTION_uninvar(_region_, _vma_, _lma_) \ + .uninvar _vma_ : _lma_ \ + { \ + __uninvar_start = ABSOLUTE (.); \ + FORCE_OUTPUT; \ + *(.uninvar); \ + . = ALIGN(4); \ + __uninvar_end = ABSOLUTE (.); \ + __uninvar_size = ABSOLUTE (.) - ABSOLUTE(__uninvar_start); \ + } \ + > _region_ + +#define SECTION_romvec(_region_, _vma_, _lma_) \ + .romvec _vma_ : _lma_ \ + { \ + __romvec_start = ABSOLUTE (.); \ + FORCE_OUTPUT; \ + KEEP(*(.romvec)); \ + . = ALIGN(4); \ + __romvec_end = ABSOLUTE (.); \ + __romvec_size = ABSOLUTE (.) - ABSOLUTE(__romvec_start); \ + } \ + > _region_ + +#define SECTION_ramvec(_region_, _vma_, _lma_) \ + .ramvec _vma_ : _lma_ \ + { \ + __ramvec_start = ABSOLUTE (.); \ + FORCE_OUTPUT; \ + KEEP(*(.ramvec)); \ + . = ALIGN(4); \ + __ramvec_end = ABSOLUTE (.); \ + __ramvec_size = ABSOLUTE (.) - ABSOLUTE(__ramvec_start); \ + } \ + > _region_ + +#define SECTION_virtual_vec_table(_region_, _vma_, _lma_) \ + .virtual_vec_table _vma_ : _lma_ \ + { \ + __virtual_vec_table_start = ABSOLUTE (.); \ + . += 0x100; \ + __virtual_vec_table_end = ABSOLUTE (.); \ + __virtual_vec_table_size = ABSOLUTE (.) - ABSOLUTE(__virtual_vec_table_start); \ + } \ + > _region_ + +#define SECTIONS_END \ + SECTION_stab \ + SECTION_stabstr \ + SECTION_comment \ + . = ALIGN(0x4); _end = .; PROVIDE (end = .); + +#include +#include CYGHWR_MEMORY_LAYOUT_LDI + +hal_virtual_vector_table = __virtual_vec_table_start; diff --git a/packages/hal/coldfire/arch/v2_0/src/coldfire_stub.c b/packages/hal/coldfire/arch/v2_0/src/coldfire_stub.c new file mode 100644 index 00000000..27d8239a --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/src/coldfire_stub.c @@ -0,0 +1,268 @@ +//======================================================================== +// +// coldfire_stub.c +// +// Helper functions for stub +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Helper functions for stub, generic to all ColdFire +// processors. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include // memcpy, memset + +#include + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#include + +#include +#include +#include + +#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT +#include // dbg_currthread_id +#endif + +// Given a trap value TRAP, return the corresponding signal. +int __computeSignal (unsigned int trap_number) +{ + switch (trap_number) + { + + case CYGNUM_HAL_VECTOR_BUSERR: + case CYGNUM_HAL_VECTOR_ADDRERR: + return SIGBUS; + + case CYGNUM_HAL_VECTOR_ILLINST: + case CYGNUM_HAL_VECTOR_UNSUPINST: + return SIGILL; + + case CYGNUM_HAL_VECTOR_ZERODIV: + case CYGNUM_HAL_VECTOR_FP_BRANCH: + case CYGNUM_HAL_VECTOR_FP_INEXACT: + case CYGNUM_HAL_VECTOR_FP_ZERODIV: + case CYGNUM_HAL_VECTOR_FP_UNDERFLOW: + case CYGNUM_HAL_VECTOR_FP_OPERAND: + case CYGNUM_HAL_VECTOR_FP_OVERFLOW: + case CYGNUM_HAL_VECTOR_FP_NAN: + case CYGNUM_HAL_VECTOR_FP_DENORM: + // Although not quite accurate, use this signal also for + // integer division. + return SIGFPE; + + case CYGNUM_HAL_VECTOR_PRIVVIOLATION: + return SIGILL; + case CYGNUM_HAL_VECTOR_TRACE: + // Instruction trace + return SIGTRAP; + + case CYGNUM_HAL_VECTOR_L1010: + case CYGNUM_HAL_VECTOR_L1111: + case CYGNUM_HAL_VECTOR_UNINITINT: + case CYGNUM_HAL_VECTOR_SPURINT: + return SIGTRAP; + + case CYGNUM_HAL_VECTOR_TRAPFIRST ... CYGNUM_HAL_VECTOR_TRAPLAST: + return SIGTRAP; + + case CYGNUM_HAL_VECTOR_AUTOVEC1 ... CYGNUM_HAL_VECTOR_AUTOVEC7: + case CYGNUM_HAL_VECTOR_USERINTRFIRST ... CYGNUM_HAL_VECTOR_USERINTRLAST: + // External interrupt + return SIGINT; + + default: + return SIGTERM; + } +} + + +// Return the trap number corresponding to the last-taken trap. +int __get_trap_number (void) +{ + // The vector is not not part of the GDB register set so get it + // directly from the saved context. + return HAL_CF_EXCEPTION_VECTOR(_hal_registers->fmt_vec_word); +} + + +// Set the currently-saved pc register value to PC. +void set_pc (target_register_t pc) +{ + put_register (PC, pc); +} + + +// Return the offset of a register in the GDB_Registers structure. +static int reg_offset(regnames_t reg) +{ + switch(reg) + { + case D0 ... A7: + return reg * 4; + + case SR: + return offsetof(GDB_Registers, sr); + + default: + case PC: + return offsetof(GDB_Registers, pc); + } +} + + +// Return the currently-saved value corresponding to register REG of +// the exception context. +target_register_t get_register(regnames_t reg) +{ + target_register_t val; + int offset = reg_offset(reg); + + if (REGSIZE(reg) > sizeof(target_register_t)) + return -1; + + val = _registers[offset/sizeof(target_register_t)]; + + return val; +} + + +// Store VALUE in the register corresponding to WHICH in the exception +// context. +void put_register(regnames_t which, target_register_t value) +{ + int offset = reg_offset(which); + + if (REGSIZE(which) > sizeof(target_register_t)) + return; + + _registers[offset/sizeof(target_register_t)] = value; +} + + +// Write the contents of register WHICH into VALUE as raw bytes. This +// is only used for registers larger than sizeof(target_register_t). +// Return non-zero if it is a valid register. +int get_register_as_bytes(regnames_t which, char *value) +{ + int offset = reg_offset(which); + + memcpy (value, (char *)_registers + offset, REGSIZE(which)); + return 1; +} + + +// Alter the contents of saved register WHICH to contain VALUE. This +// is only used for registers larger than sizeof(target_register_t). +// Return non-zero if it is a valid register. +int put_register_as_bytes(regnames_t which, char *value) +{ + int offset = reg_offset(which); + + memcpy ((char *)_registers + offset, value, REGSIZE(which)); + return 1; +} + + +// --------------------------------------------------------------------- +// Single-step support + +// Set things up so that the next user resume will execute one instruction. +// This may be done by setting breakpoints or setting a single step flag +// in the saved user registers, for example. + +#define SR_TRACE 0x8000 + +void __single_step(void) +{ + target_register_t sr = get_register (SR); + + // Set trace flag in the exception context. + sr |= SR_TRACE; + + put_register (SR, sr); +} + + +// Clear the single-step state. +void __clear_single_step(void) +{ + target_register_t sr = get_register (SR); + + // Clear single-step flag in the exception context. + sr &= ~SR_TRACE; + + put_register (SR, sr); +} + + +void __install_breakpoints(void) +{ + // NOP since single-step HW exceptions are used instead of + // breakpoints. +} + + +void __clear_breakpoints(void) +{ + // NOP since single-step HW exceptions are used instead of + // breakpoints. +} + + +// If the breakpoint we hit is in the breakpoint() instruction, return a +// non-zero value. +int __is_breakpoint_function(void) +{ + return (get_register(PC) == (target_register_t) &CYG_LABEL_NAME(_breakinst)); +} + + +// Skip the current instruction. Since this is only called by the +// stub when the PC points to a breakpoint or trap instruction, +// we can safely just skip 2. +void __skipinst(void) +{ + put_register (PC, get_register (PC) + HAL_BREAKINST_SIZE); +} + +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS diff --git a/packages/hal/coldfire/arch/v2_0/src/context.S b/packages/hal/coldfire/arch/v2_0/src/context.S new file mode 100644 index 00000000..8fee00c2 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/src/context.S @@ -0,0 +1,249 @@ +|============================================================================= +| +| context.S +| +| ColdFire architecture context switch code +| +|============================================================================= +|###ECOSGPLCOPYRIGHTBEGIN#### +| ------------------------------------------- +| This file is part of eCos, the Embedded Configurable Operating System. +| Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +| Copyright (C) 2006 eCosCentric Ltd. +| +| 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): Enrico Piria +| Contributors: +| Date: 2005-25-06 +| Purpose: This file contains implementations of the thread context +| switch routines. It also contains the longjmp() and setjmp() +| routines. +| +|####DESCRIPTIONEND#### +|======================================================================== + + +#include +#include +#include + + +| ---------------------------------------------------------------------------- +| hal_thread_switch_context - Switch between two threads +| +| externC void hal_thread_switch_context(CYG_ADDRESS to, CYG_ADDRESS from) +| +| INPUT: +| 0(%sp) : return address +| 4(%sp) : to - address of sp of next thread to execute +| 8(%sp) : from - address of sp save location of current thread +| +| OUTPUT: +| None +| +| RETURN VALUE: +| None +| +| d0, d1, a0, a1 are ours to abuse. Other registers are not touched. + +FUNC_START(hal_thread_switch_context) + + ctx_save_registers + + | Read to and from parameters from the stack + move.l CYGARC_CF_CONTEXT_SIZE+4(%sp),%a0 + move.l CYGARC_CF_CONTEXT_SIZE+8(%sp),%a1 + + | Store this thread's current stack pointer to *from + move.l %sp,(%a1) + + | Load the stack pointer for the next thread from *to + move.l (%a0),%sp + + ctx_restore_registers + + | Return to caller + rts + + +| ---------------------------------------------------------------------------- +| hal_thread_load_context - Load thread context +| +| externC void hal_thread_load_context(CYG_ADDRESS to) +| +| INPUT: +| 4(%sp) : to - address of sp of next thread to execute +| +| OUTPUT: +| None +| +| RETURN VALUE: +| None +| +| d0, d1, a0, a1 are ours to abuse. + +FUNC_START(hal_thread_load_context) + + | Read the to parameter from the stack and switch to that stack + | pointer + move.l 4(%sp),%a0 + move.l (%a0),%sp + + | Load all of the preserved registers from the stack + movem.l CYGARC_CFREG_DREGS(%sp),%d0-%d7 + movem.l CYGARC_CFREG_AREGS(%sp),%a0-%a6 + + | Starting SR + move.w CYGARC_CF_SR(%sp), %d0 + move.w %d0,%sr + + | Deallocate context frame + lea CYGARC_CF_CONTEXT_SIZE(%sp),%sp + + | Return + rts + + +| ---------------------------------------------------------------------------- +| The following routines are based on the hal_jmp_buf structure layout, defined +| in hal_arch.h + +| ---------------------------------------------------------------------------- +| hal_setjmp - setjmp for the ColdFire architecture +| +| externC int hal_setjmp(hal_jmp_buf env) +| +| INPUT: +| 0(%sp) : return address +| 4(%sp) : env - address of a hal_jmp_buf structure +| +| OUTPUT: +| None +| +| RETURN VALUE: +| This routine always returns zero in d0.l. +| +| d0, d1, a0, a1 are ours to abuse. + +FUNC_START(hal_setjmp) + + | Get a pointer to the register buffer + move.l 4(%sp),%a0 + + | Store all of the preserved registers + movem.l %d2-%d7,CYGARC_JMPBUF_REG_D2(%a0) + movem.l %a2-%a6,CYGARC_JMPBUF_REG_A2(%a0) + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + | Store MAC registers + + | Store MACSR register + move.l %macsr,%d0 + move.l %d0,CYGARC_JMPBUF_REG_MACSR(%a0) + + | Switch to integer mode. This allows to save the contents of ACC + | without rounding + and.l #0x000000df,%d0 + move.l %d0,%macsr + + | Store ACC register + move.l %acc,%d0 + move.l %d0,CYGARC_JMPBUF_REG_MACC(%a0) + + | Store MASK register + move.l %mask,%d0 + move.l %d0,CYGARC_JMPBUF_REG_MASK(%a0) +#endif + + | Store the stack pointer + move.l %sp,CYGARC_JMPBUF_REG_SP(%a0) + + | Store the return address into the structure + move.l (%sp),CYGARC_JMPBUF_REG_PC(%a0) + + | Load a zero return value + clr.l %d0 + + | Return + rts + + +| ---------------------------------------------------------------------------- +| hal_longjmp - longjmp for the ColdFire architecture +| +| externC void hal_longjmp(hal_jmp_buf env, int val) +| +| INPUT: +| 0(%sp): return address +| 4(%sp): env - address of a hal_jmp_buf structure +| 8(%sp): val - the non-zero value to return +| +| OUTPUT: +| None +| +| RETURN VALUE: +| This routine always returns the value from the val parameter in d0.l +| and to the location of the PC in the env structure. + +FUNC_START(hal_longjmp) + + | Load the return value parameter + move.l 8(%sp),%d0 + + | Get a pointer to the buffer to read our state from + move.l 4(%sp),%a0 + + | Load all of the preserved registers + movem.l CYGARC_JMPBUF_REG_D2(%a0),%d2-%d7 + movem.l CYGARC_JMPBUF_REG_A2(%a0),%a2-%a6 + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + | Load MAC registers + + | Load MACSR register + move.l CYGARC_JMPBUF_REG_MACSR(%a0),%d1 + move.l %d1,%macsr + + | Load ACC register + move.l CYGARC_JMPBUF_REG_MACC(%a0),%d1 + move.l %d1,%acc + + | Load MASK register + move.l CYGARC_JMPBUF_REG_MASK(%a0),%d1 + move.l %d1,%mask +#endif + + | Load the stack pointer + move.l CYGARC_JMPBUF_REG_SP(%a0),%sp + + | Load return address and store it on stack + move.l CYGARC_JMPBUF_REG_PC(%a0),(%sp) + + | Return to caller + rts diff --git a/packages/hal/coldfire/arch/v2_0/src/hal_misc.c b/packages/hal/coldfire/arch/v2_0/src/hal_misc.c new file mode 100644 index 00000000..0a1f6d77 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/src/hal_misc.c @@ -0,0 +1,198 @@ +//========================================================================== +// +// hal_misc.c +// +// HAL miscellaneous functions +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Miscellaneous routine and variable definitions. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include + +#include +#include // tracing macros +#include // assertion macros +#include // diag_printf + +#include // HAL header + +#include // VSR/ISR defines + +// ------------------------------------------------------------------------- +// ISR table + +volatile CYG_ADDRESS cyg_hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; +volatile CYG_ADDRWORD cyg_hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; +volatile CYG_ADDRESS cyg_hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; + +// ------------------------------------------------------------------------- +// VSR table + +externC void __handle_exception(void); + +externC HAL_SavedRegisters * _hal_registers; + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +externC void* volatile __mem_fault_handler; +#endif + +// Defined in variant HAL +externC void hal_interrupt_update_level(void); + +// -------------------------------------------------------------------------- +// Default exception handler. + +void hal_exception_handler(CYG_WORD vector, HAL_SavedRegisters *regs) +{ + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + + // If we caught an exception inside the stubs, see if we were expecting it + // and if so jump to the saved address. + if (__mem_fault_handler) { + regs->pc = (CYG_ADDRWORD)__mem_fault_handler; + // Caught an exception inside stubs + return; + } + + // Set the pointer to the registers of the current exception + // context. At entry the GDB stub will expand the + // HAL_SavedRegisters structure into a (bigger) register array. + _hal_registers = regs; + + __handle_exception(); + +#elif defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ + defined(CYGPKG_HAL_EXCEPTIONS) + + // We should decode the vector and pass a more appropriate + // value as the second argument. For now we simply pass a + // pointer to the saved registers. We should also divert + // breakpoint and other debug vectors into the debug stubs. + + cyg_hal_deliver_exception(vector, (CYG_ADDRWORD)regs); + +#else + + CYG_FAIL("Exception!!!"); + +#endif + + return; +} + +// -------------------------------------------------------------------------- +// Default ISR handler. + +cyg_uint32 hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + CYG_FAIL("Unexpected ISR"); + return 0; +} + +// -------------------------------------------------------------------------- +// Default spurious interrupt handler. This routine is called with all +// interrupts disabled. + +#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS + +void hal_spurious_interrupt(HAL_SavedRegisters *regs) CYGBLD_ATTRIB_WEAK; + +void hal_spurious_interrupt(HAL_SavedRegisters *regs) +{ + CYG_FAIL("Spurious interrupt!!"); +} + +#endif + +// -------------------------------------------------------------------------- +// Idle thread action. + +void hal_idle_thread_action(cyg_uint32 count) +{ +} + +// ----------------------------------------------------------------------- +// Determine the index of the ls bit of the supplied mask. + +cyg_uint32 hal_lsbit_index(cyg_uint32 mask) +{ + cyg_uint32 n = mask; + + static const signed char tab[64] = + { -1, 0, 1, 12, 2, 6, 0, 13, 3, 0, 7, 0, 0, 0, 0, 14, 10, + 4, 0, 0, 8, 0, 0, 25, 0, 0, 0, 0, 0, 21, 27 , 15, 31, 11, + 5, 0, 0, 0, 0, 0, 9, 0, 0, 24, 0, 0 , 20, 26, 30, 0, 0, 0, + 0, 23, 0, 19, 29, 0, 22, 18, 28, 17, 16, 0 + }; + + n &= ~(n-1UL); + n = (n<<16)-n; + n = (n<<6)+n; + n = (n<<4)+n; + + return tab[n>>26]; +} + +// ----------------------------------------------------------------------- +// Determine the index of the ms bit of the supplied mask. + +cyg_uint32 hal_msbit_index(cyg_uint32 mask) +{ + cyg_uint32 x = mask; + cyg_uint32 w; + + // Phase 1: make word with all ones from that one to the right + x |= x >> 16; + x |= x >> 8; + x |= x >> 4; + x |= x >> 2; + x |= x >> 1; + + // Phase 2: calculate number of "1" bits in the word + w = (x & 0x55555555) + ((x >> 1) & 0x55555555); + w = (w & 0x33333333) + ((w >> 2) & 0x33333333); + w = w + (w >> 4); + w = (w & 0x000F000F) + ((w >> 8) & 0x000F000F); + return (cyg_uint32)((w + (w >> 16)) & 0xFF) - 1; + +} diff --git a/packages/hal/coldfire/arch/v2_0/src/hal_mk_defs.c b/packages/hal/coldfire/arch/v2_0/src/hal_mk_defs.c new file mode 100644 index 00000000..d7ab069e --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/src/hal_mk_defs.c @@ -0,0 +1,125 @@ +//========================================================================== +// +// hal_mk_defs.c +// +// HAL "make defs" program +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 Gary Thomas +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: gthomas, jskov +// Date: 2005-25-06 +// Purpose: ColdFire architecture dependent definition generator +// Description: This file contains code that can be compiled by the target +// compiler and used to generate machine specific definitions +// suitable for use in assembly code. +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include // HAL header +#include // HAL header +#ifdef CYGPKG_KERNEL +# include +# include +#endif + +// This program is used to generate definitions needed by +// assembly language modules. +// +// This technique was first used in the OSF Mach kernel code: +// generate asm statements containing #defines, +// compile this file to assembler, and then extract the +// #defines from the assembly-language output. + +#define DEFINE(sym, val) \ + asm volatile("\n\t.equ\t" #sym ",%0" : : "i" (val)) + +int +main(void) +{ + // Exception/interrupt/context save buffer + DEFINE(CYGARC_CFREG_AREGS, offsetof(HAL_SavedRegisters, a[0])); + DEFINE(CYGARC_CFREG_DREGS, offsetof(HAL_SavedRegisters, d[0])); + DEFINE(CYGARC_CFREG_A0, offsetof(HAL_SavedRegisters, a[0])); + DEFINE(CYGARC_CFREG_A1, offsetof(HAL_SavedRegisters, a[1])); + DEFINE(CYGARC_CFREG_A2, offsetof(HAL_SavedRegisters, a[2])); + DEFINE(CYGARC_CFREG_A6, offsetof(HAL_SavedRegisters, a[6])); + DEFINE(CYGARC_CFREG_D0, offsetof(HAL_SavedRegisters, d[0])); + DEFINE(CYGARC_CFREG_D1, offsetof(HAL_SavedRegisters, d[1])); + DEFINE(CYGARC_CFREG_D2, offsetof(HAL_SavedRegisters, d[2])); + DEFINE(CYGARC_CFREG_PC, offsetof(HAL_SavedRegisters, pc)); + DEFINE(CYGARC_CFREG_SP, offsetof(HAL_SavedRegisters, a[7])); + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + DEFINE(CYGARC_CFREG_MACC, offsetof(HAL_SavedRegisters, macc)); + DEFINE(CYGARC_CFREG_MACSR, offsetof(HAL_SavedRegisters, macsr)); + DEFINE(CYGARC_CFREG_MASK, offsetof(HAL_SavedRegisters, mask)); +#endif + + DEFINE(CYGARC_CF_CONTEXT_SIZE, sizeof(HAL_SavedRegisters)); + + // Below only saved on exceptions/interrupts + DEFINE(CYGARC_CF_FMTVECWORD, offsetof(HAL_SavedRegisters, fmt_vec_word)); + DEFINE(CYGARC_CF_SR, offsetof(HAL_SavedRegisters, sr)); + DEFINE(CYGARC_CF_EXCEPTION_SIZE, sizeof(HAL_SavedRegisters)); + DEFINE(CYGARC_CF_EXCEPTION_DECREMENT, offsetof(HAL_SavedRegisters, fmt_vec_word)); + + // Some other exception related definitions + DEFINE(CYGNUM_HAL_ISR_MIN, CYGNUM_HAL_ISR_MIN); + DEFINE(CYGNUM_HAL_ISR_COUNT, CYGNUM_HAL_ISR_COUNT); + DEFINE(CYGNUM_HAL_SPURIOUS_INTERRUPT, CYGNUM_HAL_SPURIOUS_INTERRUPT); + DEFINE(CYGNUM_HAL_VECTOR_DEBUGTRAP, CYGNUM_HAL_VECTOR_DEBUGTRAP); + + // setjmp/longjmp related definitions + DEFINE(CYGARC_JMPBUF_REG_D2, offsetof(hal_jmp_buf_t, d2)); + DEFINE(CYGARC_JMPBUF_REG_A2, offsetof(hal_jmp_buf_t, a2)); + DEFINE(CYGARC_JMPBUF_REG_SP, offsetof(hal_jmp_buf_t, sp)); + DEFINE(CYGARC_JMPBUF_REG_PC, offsetof(hal_jmp_buf_t, pc)); + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + DEFINE(CYGARC_JMPBUF_REG_MACC, offsetof(hal_jmp_buf_t, macc)); + DEFINE(CYGARC_JMPBUF_REG_MACSR, offsetof(hal_jmp_buf_t, macsr)); + DEFINE(CYGARC_JMPBUF_REG_MASK, offsetof(hal_jmp_buf_t, mask)); +#endif + + return 0; +} + +// ------------------------------------------------------------------------- +// EOF hal_mk_defs.c diff --git a/packages/hal/coldfire/arch/v2_0/src/hal_startup.c b/packages/hal/coldfire/arch/v2_0/src/hal_startup.c new file mode 100644 index 00000000..69800971 --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/src/hal_startup.c @@ -0,0 +1,252 @@ +//========================================================================== +// +// hal_startup.c +// +// ColdFire architecture HAL startup code +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Architecture startup code. +// Description: This module contains code that sets up the hardware and the +// memory sections. All the code must be contained in the +// section called ".boot", in order for the ROMRAM startup +// to work properly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include +#include CYGHWR_MEMORY_LAYOUT_H +#include // hal_if_init +#include // Interrupt definitions +#include // initialize_stub + +externC void cyg_start(void); +externC void hal_ctrlc_isr_init(void); + +static void hal_vsr_init(void) __attribute__ ((section (".boot"))); +static void hal_isr_init(void) __attribute__ ((section (".boot"))); +static void hal_init_ram_sections(void) __attribute__ ((section (".boot"))); +static void cyg_hal_invoke_constructors(void) __attribute__ ((section (".boot"))); + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + +externC unsigned char __romram_copy_source[]; +externC unsigned char __romram_copy_dest[]; +externC unsigned char __romram_copy_length[]; + +#endif + + +// ------------------------------------------------------------------------- +// Reset vector routine. + +void hal_reset(void) +{ + // Do any variant-specific reset initialization + var_reset(); + + // Do any platform-specific reset initialization + plf_reset(); + + // Initialize the RAM sections that the rest of the C code requires + hal_init_ram_sections(); + + // All program sections are now in place + + // Make sure that every instruction above this one has been output by + // the compiler + HAL_REORDER_BARRIER(); + + // Now it is safe to use a stack in RAM + asm volatile ("lea cyg_interrupt_stack, %sp"); + + // It is now safe to call C functions which may rely on initialized + // data + hal_vsr_init(); + hal_isr_init(); + + // Initialize variant HAL private data + var_init_data(); + + // Initialize platform HAL private data + plf_init_data(); + + // Initialize the virtual vector table + hal_if_init(); + + // Call C++ constructors + cyg_hal_invoke_constructors(); + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + initialize_stub(); +#endif + + // Init Ctrl-C debug ISR +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + hal_ctrlc_isr_init(); +#endif + + // Call cyg_start. This routine should not return. + cyg_start(); +} + + +// ------------------------------------------------------------------------- +// Initialize the vector table. + +static void hal_vsr_init(void) +{ + unsigned int i; + + // If we are starting up from ROM, or we are starting in + // RAM and NOT using a ROM monitor, initialize the VSR and ISR tables. +#if defined(CYG_HAL_STARTUP_ROM) || \ + defined(CYG_HAL_STARTUP_ROMRAM) || \ + (defined(CYG_HAL_STARTUP_RAM) && \ + !defined(CYGSEM_HAL_USE_ROM_MONITOR)) + + // Initialize the HAL's vector table with the ROM vector table + for (i = 0; i < CYGNUM_HAL_VSR_COUNT; i++) + cyg_hal_vsr_table[i] = rom_vsr_table[i]; + +#elif defined(CYG_HAL_STARTUP_RAM) && defined(CYGSEM_HAL_USE_ROM_MONITOR) + + // We only take control of the interrupt vectors, + // the rest are left to the ROM for now. + cyg_hal_vsr_table[CYGNUM_HAL_VECTOR_UNINITINT] = + rom_vsr_table[CYGNUM_HAL_VECTOR_UNINITINT]; + + cyg_hal_vsr_table[CYGNUM_HAL_VECTOR_SPURINT] = + rom_vsr_table[CYGNUM_HAL_VECTOR_SPURINT]; + + for(i = 0; i < CYGNUM_HAL_NUMAUTOVEC; i++) + cyg_hal_vsr_table[CYGNUM_HAL_VECTOR_AUTOVEC1 + i] = + rom_vsr_table[CYGNUM_HAL_VECTOR_AUTOVEC1 + i]; + + for(i = 0; i < CYGNUM_HAL_NUMUSERINTR; i++) + cyg_hal_vsr_table[CYGNUM_HAL_VECTOR_USERINTRFIRST + i] = + rom_vsr_table[CYGNUM_HAL_VECTOR_USERINTRFIRST + i]; + +#endif +} + + +// ------------------------------------------------------------------------- +// Initialize the ISRs. + +static void hal_isr_init(void) +{ + int i; + + // Initialize all ISR entries to default + for (i = 0; i < CYGNUM_HAL_ISR_COUNT; i++) + { + cyg_hal_interrupt_handlers[i] = (CYG_ADDRESS) &hal_default_isr; + cyg_hal_interrupt_data[i] = (CYG_ADDRWORD) 0; + cyg_hal_interrupt_objects[i] = (CYG_ADDRESS) 0; + } +} + + +// ------------------------------------------------------------------------- +// Initialize the RAM sections +// For an efficient copy, we suppose that the sections are aligned at a +// 4-byte boundary and are a multiple of 4 bytes. Linker scripts should +// guarantee this. + +static void hal_init_ram_sections(void) +{ + cyg_uint32 *m; + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + { + // Initialize the RAM data section from the ROM image of the data + // section. + cyg_uint32 *p = (cyg_uint32 *) __romram_copy_dest; + cyg_uint32 *q = (cyg_uint32 *) __romram_copy_source; + cyg_uint32 length = 0; + + while (length < (cyg_uint32) __romram_copy_length) + { + *p++ = *q++; + length += 4; + } + } +#endif + + // Initialize the bss sections to zero + m = (cyg_uint32 *) __bss_start; + while (m != (cyg_uint32 *) __bss_end) + *m++ = 0x0; +} + + +// ------------------------------------------------------------------------- +// Call static constructors. + +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG +cyg_bool cyg_hal_stop_constructors; +#endif + +typedef void (*pfunc) (void); +extern pfunc __CTOR_LIST__[]; +extern pfunc __CTOR_END__[]; + +static void cyg_hal_invoke_constructors(void) +{ +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG + static pfunc *p = &__CTOR_END__[-1]; + + cyg_hal_stop_constructors = 0; + for (; p >= __CTOR_LIST__; p--) { + (*p) (); + if (cyg_hal_stop_constructors) { + p--; + break; + } + } +#else + pfunc *p; + + for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--) + (*p) (); +#endif +} diff --git a/packages/hal/coldfire/arch/v2_0/src/vectors.S b/packages/hal/coldfire/arch/v2_0/src/vectors.S new file mode 100644 index 00000000..eedacadf --- /dev/null +++ b/packages/hal/coldfire/arch/v2_0/src/vectors.S @@ -0,0 +1,646 @@ +|========================================================================== +| +| vectors.S +| +| ColdFire exception vectors +| +|========================================================================== +|###ECOSGPLCOPYRIGHTBEGIN#### +| ------------------------------------------- +| This file is part of eCos, the Embedded Configurable Operating System. +| Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +| Copyright (C) 2006 eCosCentric Ltd. +| +| 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): Enrico Piria +| Contributors: Wade Jensen +| Date: 2005-25-06 +| Purpose: ColdFire exception vectors +| Description: This file contains the first level default VSRs +| that save and restore state for both exceptions and +| interrupts. +| +|####DESCRIPTIONEND#### +|========================================================================== + +#include +#include +#include +#include +#include + +#ifdef CYGPKG_KERNEL +#include +#endif + +| ---------------------------------------------------------------------------- +| Hardware reset vector + + .section ".boot","x" + .balign 4 + .globl cyg_hal_reset_vsr +cyg_hal_reset_vsr: + + | Define the entry point for the linker. + .globl _start +_start: + + | Make sure that all interrupts are masked. + hal_cpu_int_disable + + | Initial setup. Just do the minimum to be able to perform + | initialization in C. + + | Initialize CPU variant + hal_cpu_init + + | Platform specific hardware initialization. + | This may include memory controller initialization. + hal_hardware_init + + | Setup boot stack + hal_boot_stack_init + + | Set up the initial frame pointer. + lea 0,%fp + link %fp,#0 + + | Call the C routine to complete the reset process. + .extern hal_reset + jsr hal_reset + + | If we return, stop. +9: + stop #0x2000 + bra 9b + + +| ---------------------------------------------------------------------------- +| Default exception vector handler +| +| The default handler for all machine exceptions. We save the +| machine state and call the default C exception handler. This routine passes a +| pointer to the saved state to the C exception handler. The stack pointer in +| the saved state points to the the sp before the exception. +| The format/vector word in the exception stack contains the vector +| number. + +| void hal_exception_handler(CYG_WORD vector, HAL_SavedRegisters *regs); + + .text + .balign 4 + .globl cyg_hal_default_exception_vsr +cyg_hal_default_exception_vsr: + + | Disable all interrupts + hal_cpu_int_disable + + | Preserve the entire state. + | Allocate space for all registers (including the stack pointer). + | Write all registers to the stack space. + lea.l -CYGARC_CF_EXCEPTION_DECREMENT(%sp),%sp + movem.l %d0-%d7,CYGARC_CFREG_DREGS(%sp) + movem.l %a0-%a6,CYGARC_CFREG_AREGS(%sp) + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + save_mac_registers %d0 +#endif + + | Write the original stack pointer value to the stack. + | The format/vector word, sr, and pc are already on the stack. + find_original_sp %d0 + move.l %d0,CYGARC_CFREG_SP(%sp) + + | Calculate the vector number. The format/vector word on the stack + | contains the vector number. + move.w CYGARC_CF_FMTVECWORD(%sp),%d0 + and.l #0x000003fc,%d0 + lsr.l #2,%d0 + + | Pass a pointer to the saved state to the exception handler. + pea.l (%sp) + + | Push the vector number parameter. + move.l %d0,-(%sp) + + | Call the default exception handler. This routine may modify + | the exception context. + .extern hal_exception_handler + jsr hal_exception_handler + + | Remove the vector number and the state pointer from the stack. + addq.l #2*4,%sp + + | Get a pointer to the location following the exception context. + find_original_sp %d0 + + | Restore all of the registers that we do not need in the following + | code. We will copy all registers that are not restored here + | to the new stack before restoring them. + +#ifdef CYGHWR_HAL_COLDFIRE_MAC + restore_mac_registers %d0 +#endif + + movem.l CYGARC_CFREG_D2(%sp),%d2-%d7 + movem.l CYGARC_CFREG_A1(%sp),%a1-%a6 + + | Load the address of the new SP. + move.l CYGARC_CFREG_SP(%sp),%d1 + + | We now have: + | d0.l : original stack pointer + | d1.l : final stack pointer + + | ColdFire programmer's manual doesn't tell if rte instruction expects + | the stack frame to be aligned at 32-bit boundaries. + | So, we align the new stack value, and adjust the format field + | accordingly. At the end of rte instruction the stack will thus point + | to the desired location. + + | Compare the new stack address to the end of the exception context. + | This will tell us the order that we need to copy the exception + | stack and the remaining registers from the old exception context to + | the new one. The order is important because the stack frames might + | overlap. + cmp.l %d0,%d1 + + | If the new SP and the old one coincide. + beq 2f + + | If the new SP is at a higher address than the old one. + bgt 1f + + | The new SP is at a lower address than the old one. Copy from the + | lowest address to the highest address. + + | Align stack at longword boundary + move.l %d1,%d0 + and.l #0xfffffffc,%d0 + move.l %d0,%a0 + + | Allocate new frame + sub.l #CYGARC_CF_CONTEXT_SIZE,%a0 + + | Copy D0, D1, A0, FVW, SR, and PC from the old stack to the new stack. + | Note that we copy in ascending order. + + | Copy D0, D1, A0 + move.l CYGARC_CFREG_D0(%sp),CYGARC_CFREG_D0(%a0) + move.l CYGARC_CFREG_D1(%sp),CYGARC_CFREG_D1(%a0) + move.l CYGARC_CFREG_A0(%sp),CYGARC_CFREG_A0(%a0) + + | Based on target SP address, construct new format field + and.l #0x00000003,%d1 + or.l #0x4,%d1 + lsl.l #8,%d1 + lsl.l #4,%d1 + + | Load old format field + move.w CYGARC_CF_FMTVECWORD(%sp),%d0 + + | Clear old format field + and.l #0x0fff,%d0 + + | Write the new one + or.l %d1,%d0 + move.w %d0,CYGARC_CF_FMTVECWORD(%a0) + + | Copy SR and PC + move.w CYGARC_CF_SR(%sp),CYGARC_CF_SR(%a0) + move.l CYGARC_CFREG_PC(%sp),CYGARC_CFREG_PC(%a0) + + | A0 points to the top of the new stack + move.l %a0,%sp + + | Restore remaining registers and exit + jmp 2f + +1: + + | The new SP is at a higher address than the old one. Copy from the + | highest address to the lowest address. + + | Align stack at longword boundary + move.l %d1,%d0 + and.l #0xfffffffc,%d0 + move.l %d0,%a0 + + | Allocate new frame + sub.l #CYGARC_CF_CONTEXT_SIZE,%a0 + + | Copy D0, D1, A0, FVW, SR, and PC from the old stack to the new stack. + | Note that we copy in descending order. + + | Copy PC and SR + move.l CYGARC_CFREG_PC(%sp),CYGARC_CFREG_PC(%a0) + move.w CYGARC_CF_SR(%sp),CYGARC_CF_SR(%a0) + + | Based on target SP address, construct new format field + and.l #0x00000003,%d1 + or.l #0x4,%d1 + lsl.l #8,%d1 + lsl.l #4,%d1 + + | Load old format field + move.w CYGARC_CF_FMTVECWORD(%sp),%d0 + + | Clear old format field + and.l #0x0fff,%d0 + + | Write the new one + or.l %d1,%d0 + move.w %d0,CYGARC_CF_FMTVECWORD(%a0) + + | Copy A0, D1, D0 + move.l CYGARC_CFREG_A0(%sp),CYGARC_CFREG_A0(%a0) + move.l CYGARC_CFREG_D1(%sp),CYGARC_CFREG_D1(%a0) + move.l CYGARC_CFREG_D0(%sp),CYGARC_CFREG_D0(%a0) + + | A0 points to the top of the new stack + move.l %a0,%sp + +2: + | Restore remaining registers + move.l CYGARC_CFREG_D0(%sp),%d0 + move.l CYGARC_CFREG_D1(%sp),%d1 + move.l CYGARC_CFREG_A0(%sp),%a0 + add.l #CYGARC_CF_EXCEPTION_DECREMENT,%sp + + | Return from exception + rte + + +| ---------------------------------------------------------------------------- +| Spurious interrupt vector handler +| +| Used for spurious and uninitialized interrupts. +| It is unknown at which priority spurious interrupts are generated. So, the +| safest thing to do is to disable all interrupts while processing spurious +| ones. + + .text + .balign 4 + .globl cyg_hal_default_spurious_vsr +cyg_hal_default_spurious_vsr: + +#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS + + | Disable all interrupts. On the first instruction, interrupt sampling + | is always disabled. + hal_cpu_int_disable + + | Preserve all registers that this handler needs to preserve. + | The C code will preserve all other registers. + int_pres_regs + + | Pass a pointer to the saved state to the interrupt handler. + pea.l (%sp) + + | Call spurious interrupt handler + .extern hal_spurious_interrupt + jsr hal_spurious_interrupt + + | Remove the arguments from the stack. + addq.l #4,%sp + + | Restore the preserved registers for the current thread. + int_rest_regs + +#endif /* ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS */ + + | Just return from interrupt. + rte + + +| ---------------------------------------------------------------------------- +| User interrupt vector handler +| +| Control is transferred here from a user interrupt vector (#64-255). +| Before branching to common code, load a value to translate the +| vector table offset to the ISR table offset. + + .text + .balign 4 + .globl cyg_hal_default_interrupt_vsr +cyg_hal_default_interrupt_vsr: + + | Disable all interrupts. On the first instruction, interrupt sampling + | is always disabled. + hal_cpu_int_disable + + | Preserve all registers that this handler needs to preserve. + | The C code will preserve all other registers. + int_pres_regs + + | It is safe to use breakpoints below this point. + .globl _cyg_hal_default_interrupt_vsr_bp_safe +_cyg_hal_default_interrupt_vsr_bp_safe: + + | Adding this value to the vector table offset will result in the + | corresponding offset into the ISR table. + move.l #(-CYGNUM_HAL_ISR_MIN)*4,%d2 + + | d2.l: Contains a value to translate the vector table offset to + | the ISR table offset. + + | Calculate the vector offset. The format/vector word on the stack + | contains the vector number. Mask off all unused bits. The bit + | position of the vector number field makes it automatically multiplied + | by four. + move.w CYGARC_CF_FMTVECWORD(%sp),%d1 + and.l #0x000003fc,%d1 + + | Calculate the ISR table offset. Add the vector table offset to the + | translation value. + add.l %d1,%d2 + + | Calculate the vector number using the vector table offset. + asr.l #2,%d1 + + | d2.l: Contains the offset into the ISR table. + | d1.l: Contains the vector number. + +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + + | If we are supporting Ctrl-C interrupts from GDB, we must squirrel + | away a pointer to the saved interrupt state here so that we can + | plant a breakpoint at some later time. + + .extern hal_saved_interrupt_state + move.l %sp,(hal_saved_interrupt_state) + +#endif + +#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT + + | Lock the scheduler if we are using the kernel. + .extern cyg_scheduler_sched_lock + addq.l #1,cyg_scheduler_sched_lock + +#endif /* CYGFUN_HAL_COMMON_KERNEL_SUPPORT */ + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + + | a0 = sp. We'll need it later + move.l %sp,%a0 + + cmp.l #__interrupt_stack_base,%sp + + | If sp < base : not on istack + blt 1f + + cmp.l #__interrupt_stack,%sp + + | If sp <= top : already on istack + ble 2f + +1: + | Switch to istack + lea __interrupt_stack,%sp + +2: + | Save old SP on istack + pea (%a0) + +#endif + +#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR) + + .extern cyg_instrument + + | Save d1 + move.l %d1,-(%sp) + + | arg2 = 0 + move.l #0,-(%sp) + + | arg1 = vector number + move.l %d1,-(%sp) + + | type = INTR,RAISE + move.l #0x0301,-(%sp) + + | Call instrumentation + jsr cyg_instrument + + | Remove args from stack + add.l #12,%sp + + | Restore %d1 + move.l (%sp)+,%d1 + +#endif + + +#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING + + | If interrupt nesting is enabled, we have to determine the IPL of the + | current interrupt. We inline the following macro, which is defined + | by ColdFire variants. The vector number of the current interrupt + | is passed in d0, and the return value is in d0. + | Registers a0-a1/d0-d1 are for use by the macro, other registers + | must be saved explicitly before being used. + + | Save %d1 + move.l %d1,-(%sp) + + | Pass d1 as argument to macro + move.l %d1,%d0 + + | Retrieve IPL, which will be contained in d0 + hal_variant_retrieve_ipl + + | Shift IPL up to the same position occupied in sr + lsl.l #8,%d0 + + | Transform d0 in a mask to be applied to sr + or.l #0xfffff0ff,%d0 + + | Update sr. Use d1 as working register + move.w %sr,%d1 + and.l %d0,%d1 + move.w %d1,%sr + + | Restore d1 + move.l (%sp)+,%d1 + +#endif + + | We need to call the following routines. The isr address, data, and + | intr are all from the ISR table. The interrupt_end routine is + | only called if we are using the kernel. regs points to the saved + | registers on the stack. isr_ret is the return value from the ISR. + | vector is the vector number. + + | static cyg_uint32 isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) + + | externC void interrupt_end(cyg_uint32 isr_ret, Cyg_Interrupt *intr, + | HAL_SavedRegisters *regs) + + + | Push the data value from the table. + .extern cyg_hal_interrupt_data + lea cyg_hal_interrupt_data,%a0 + move.l (%a0,%d2.l),-(%sp) + + | Get the address of the ISR from the table. + .extern cyg_hal_interrupt_handlers + lea cyg_hal_interrupt_handlers,%a0 + move.l (%a0,%d2.l),%a0 + + | Push the vector number parameter. + move.l %d1,-(%sp) + + | Call the ISR. + jsr (%a0) + + | Remove the isr parameters from the stack. + addq.l #4*2,%sp + + | d0.l now contains the return value from the ISR. + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + + | If we are returning from the last nested interrupt, move back + | to the thread stack. interrupt_end() must be called on the + | thread stack since it potentially causes a context switch. + | Since we have arranged for the top of stack location to + | contain the sp we need to go back to here, just pop it off + | and put it in SP. + + move.l (%sp),%sp | sp = *sp + +#endif + +#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT + + | We only need to call interrupt_end() when there is a kernel + | present to do any tidying up. To keep the following code simple, + | we enable all interrupts before calling DSRs only if a common + | interrupt stack is in use. + + | Push the regs pointer. + pea (%sp) + + | Push the intr object pointer from the table. + .extern cyg_hal_interrupt_objects + lea cyg_hal_interrupt_objects,%a0 + move.l (%a0,%d2.l),-(%sp) + + | Push ISR return value + move.l %d0,-(%sp) + + | Even when this is not the last nested interrupt, we must call + | interrupt_end() to post the DSR and decrement the scheduler + | lock. + + | Call the interrupt_end C routine. + .extern interrupt_end + jsr interrupt_end + + | Remove the isr_ret, intr, and regs parameters from the stack. + lea (4*3)(%sp),%sp + +#endif /* ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT */ + + | Restore the preserved registers for the current thread. + int_rest_regs + + | Restore the SR and PC. + rte + + +| ---------------------------------------------------------------------------- +| Execute pending DSRs on the interrupt stack with interrupts enabled. +| Note: this can only be called from code running on a thread stack + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK + + .extern cyg_interrupt_call_pending_DSRs + +FUNC_START(hal_interrupt_stack_call_pending_DSRs) + | Change to interrupt stack, save state and set up stack for + | calls to C code. + | By virtue of GNU C calling conventions, we are free to use registers + | %d0-%d1 and %a0-%a1 without saving them. + + | a0 = sp + move.l %sp, %a0 + + | Switch to istack + lea __interrupt_stack,%sp + + | Save old SP on istack + pea (%a0) + + | Save sr + move.w %sr,%d0 + move.l %d0,-(%sp) + + | Enable interrupts + hal_cpu_int_enable %d0 + + | Call into kernel which will execute DSRs + jsr cyg_interrupt_call_pending_DSRs + + move.l (%sp)+,%d0 + + | Restore previous interrupt state + hal_cpu_int_merge %d0,%d1 + + | Restore sp + move.l (%sp),%sp + + | return to caller + rts + +#endif + + +| ---------------------------------------------------------------------------- +| Interrupt and reset stack +| +| WARNING: Do not put this in any memory section that gets initialized. +| Doing so may cause the C code to initialize its own stack. + + .section ".uninvar","aw",@nobits + + .balign 16 + .global cyg_interrupt_stack_base +cyg_interrupt_stack_base: +__interrupt_stack_base: + .skip CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE + .balign 16 + .global cyg_interrupt_stack +cyg_interrupt_stack: +__interrupt_stack: + .skip 0x10 + diff --git a/packages/hal/coldfire/m5272c3/v2_0/ChangeLog b/packages/hal/coldfire/m5272c3/v2_0/ChangeLog new file mode 100644 index 00000000..3a39b6c3 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/ChangeLog @@ -0,0 +1,53 @@ +2006-05-09 Andrew Lunn + + * include/pkgconf/mlt_coldfire_m5272c3_*.h: Added CYGMEM_REGION_RAM* + so that the test cases compile. + +2005-06-24 Enrico Piria + + * src/plf_mk_defs.c: + * src/plf_startup.c: + * include/hal_memmap.h: + * include/platform.inc: + * include/plf_intr.h: + * include/plf_serial.h: + * include/plf_startup.h: + * include/plf_stub.h: + * include/pkgconf/mlt_coldfire_m5272c3_ram.h: + * include/pkgconf/mlt_coldfire_m5272c3_ram.ldi: + * include/pkgconf/mlt_coldfire_m5272c3_rom.h: + * include/pkgconf/mlt_coldfire_m5272c3_rom.ldi: + * cdl/hal_coldfire_m5272c3.cdl: + Rework of the original M5272C3 platform HAL contributed by Wade Jensen. + +//=========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/coldfire/m5272c3/v2_0/cdl/hal_coldfire_m5272c3.cdl b/packages/hal/coldfire/m5272c3/v2_0/cdl/hal_coldfire_m5272c3.cdl new file mode 100644 index 00000000..5d6e9f62 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/cdl/hal_coldfire_m5272c3.cdl @@ -0,0 +1,358 @@ +# ==================================================================== +# +# hal_coldfire_m5272c3.cdl +# +# Freescale M5272C3 evaluation board HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2006 eCosCentric Ltd. +## +## 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): Enrico Piria +## Contributors: Wade Jensen +## Date: 2005-25-06 +## +######DESCRIPTIONEND#### +##======================================================================== + +cdl_package CYGPKG_HAL_COLDFIRE_M5272C3 { + display "Freescale M5272C3 evaluation board" + parent CYGPKG_HAL_COLDFIRE_MCF5272 + define_header hal_coldfire_m5272c3.h + include_dir cyg/hal + + description "The Freescale M5272C3 evaluation board platform HAL + package should be used when targeting the actual hardware for + the Freescale M5272C3 evaluation board platform." + + compile plf_startup.c + + implements CYGINT_HAL_DEBUG_GDB_STUBS + implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " + puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H " + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_system_header "#define HAL_PLATFORM_BOARD \"Freescale M5272C3\"" + puts $::cdl_system_header "#define HAL_PLATFORM_EXTRA \"\"" + } + + # The "-o file" is a workaround for CR100958 - without it the + # output file would end up in the source directory under CygWin. + # n.b. grep does not behave itself under win32 + make -priority 1 { + /include/cyg/hal/plf_offsets.inc : /src/plf_mk_defs.c + $(CC) $(ACTUAL_CFLAGS) $(INCLUDE_PATH) -Wp,-MD,plf_offsets.tmp -o plf_mk_defs.tmp -S $< + fgrep .equ plf_mk_defs.tmp | sed s/#// > $@ + @echo $@ ": \\" > $(notdir $@).deps + @tail -n +2 plf_offsets.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm plf_offsets.tmp plf_mk_defs.tmp + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + legal_values {"RAM" "ROM" "ROMRAM"} + default_value {"RAM"} + no_define + define -file system.h CYG_HAL_STARTUP + + description " + This option is used to control where the application program will + run, either from RAM or ROM (flash) memory. ROM based applications + must be self contained, while RAM applications will typically assume + the existence of a debug environment, such as GDB stubs. + ROMRAM bootstrap is similar to ROM bootstrap, but everything + is copied to RAM before execution starts, thus improving performace, + but at the cost of an increased RAM footprint." + } + + cdl_option CYGHWR_HAL_ROM_LMA { + display "Load address for ROM image" + active_if { CYG_HAL_STARTUP == "ROM" || CYG_HAL_STARTUP == "ROMRAM" } + flavor data + legal_values 0xFFE00000 0xFFF00000 + default_value 0xFFF00000 + + description "This option lets you decide in which half of flash + memory to download the ROM image. As a safety measure, + the default is to use the upper half (starting at + 0xFFF00000), thus preserving the ROM monitor shipped with + the board. This option is meaningful only when ROM or + ROMRAM startup is choosed." + } + + cdl_option CYGHWR_HAL_SYSTEM_CLOCK_MHZ { + display "System clock speed in MHz" + flavor data + legal_values 66 48 + default_value 66 + + description "This option identifies the system clock that the + processor uses. This value is used to set clock dividers + for some devices." + } + + cdl_option CYGHWR_EXT_SRAM_INSTALLED { + display "External 512Kb SRAM module" + flavor bool + default_value 0 + + description "If this option is enabled, chip-select module 2 is + configured to access the optional external 512Kb SRAM module." + } + + cdl_option CYGHWR_INSTALLED_SDRAM_SIZE { + display "Megabytes of SDRAM installed" + flavor data + legal_values 16 4 + default_value 16 + + description "This option selects the size of the SDRAM installed. + Note that the linker scripts have been written for a board with + 16 Mb of RAM. If you modify this option, you will have to change + them by hand." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 2 + description " + Port 0 is the terminal serial port; port 1 is the auxiliary + serial port." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + This option chooses which port will be used to connect to a host + via the GDB remote protocol." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "Debug serial port baud rate" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 19200 + description " + This option controls the baud rate used for the GDB connection." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + This option chooses which port will be used for diagnostic output." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + active_if CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 19200 + + description "This option selects the baud rate used for the + diagnostic port. Note: this should match the value chosen + for the GDB port if the diagnostic and GDB port are the + same." + } + + # Real-time clock/counter specifics + cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants." + flavor none + + description "Set the periodic timer on the MCF5272 to 10 ms or + 10000000 ns." + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + default_value 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + default_value 100 + } + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + default_value 4125 + description " + The default value is calculated as: + 10 ms / ((1 / (66 MHz)) * 16 * 10)." + } + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + + description "Global build options including control over compiler + flags, linker flags and choice of toolchain." + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "m68k-elf" } + + description "This option specifies the command prefix used + when invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { "-m5206e -malign-int -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -finit-priority" } + description "This option controls the global compiler flags + which are used to compile all packages by default. + Individual packages may define options which + override these global flags." + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { "-m5206e -g -nostdlib -Wl,--gc-sections -Wl,-static" } + + description "This option controls the global linker flags. + Individual packages may define options which + override these global flags." + } + + cdl_option CYGBLD_BUILD_GDB_STUBS { + display "Build GDB stub ROM image" + default_value 0 + requires { CYG_HAL_STARTUP == "ROM" || CYG_HAL_STARTUP == "ROMRAM" } + requires CYGSEM_HAL_ROM_MONITOR + requires CYGBLD_BUILD_COMMON_GDB_STUBS + requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + requires CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM + no_define + + description "This option enables the building of the GDB + stubs for the board. The common HAL controls + take care of most of the build process, but the + final conversion from ELF image to binary data is + handled by the platform CDL, allowing relocation + of the data if necessary." + + make -priority 320 { + /bin/gdb_module.srec : /bin/gdb_module.img + $(OBJCOPY) -S -O srec $< $@ + } + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { (CYG_HAL_STARTUP == "RAM") ? "coldfire_m5272c3_ram" : \ + (CYG_HAL_STARTUP == "ROMRAM") ? "coldfire_m5272c3_romram" : \ + "coldfire_m5272c3_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { (CYG_HAL_STARTUP == "RAM") ? "" : \ + (CYG_HAL_STARTUP == "ROMRAM") ? "" : \ + "" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { (CYG_HAL_STARTUP == "RAM") ? "" : \ + (CYG_HAL_STARTUP == "ROMRAM") ? "" : \ + "" } + } + } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "GDB_stubs" : 0 } + requires { CYG_HAL_STARTUP == "RAM" } + parent CYGPKG_HAL_ROM_MONITOR + + description "Support can be enabled for boot ROMs or ROM + monitors which contain GDB stubs. This support + changes various eCos semantics such as the encoding of + diagnostic output, and the overriding of hardware + interrupt vectors." + } + + cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM" || CYG_HAL_STARTUP == "ROMRAM" } + + description "Enable this option if this program is to be used as + a ROM monitor, i.e. applications will be loaded into + RAM on the board, and this ROM monitor may process + exceptions or interrupts generated from the + application. This enables features such as utilizing + a separate interrupt stack when exceptions are + generated." + } +} diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/hal_memmap.h b/packages/hal/coldfire/m5272c3/v2_0/include/hal_memmap.h new file mode 100644 index 00000000..e959eea3 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/hal_memmap.h @@ -0,0 +1,73 @@ +#ifndef CYGONCE_HAL_MEMMAP_H +#define CYGONCE_HAL_MEMMAP_H + +//============================================================================= +// +// hal_memmap.h +// +// Platform specific memory section definitions +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Memory section definitions specific to the M5272C3 board +// Usage: Included via CYGHWR_MEMORY_LAYOUT_H +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include + +// WARNING: DO NOT CHANGE THE TYPE OF THESE LABELS. THE LINKER DEFINES +// THESE AND WE WANT TO USE THE VARIABLE ADDRESSES NOT THE VARIABLES +// THEMSELVES. + +#define SECTION_DEC(_name_) \ + externC unsigned char __ ## _name_ ## _start[]; \ + externC unsigned char __ ## _name_ ## _end[]; \ + externC unsigned char __ ## _name_ ## _size[]; + +SECTION_DEC(bss) +SECTION_DEC(ram_data) +SECTION_DEC(rom_data) +SECTION_DEC(uninvar) +SECTION_DEC(romvec) +SECTION_DEC(ramvec) + +// --------------------------------------------------------------------------- +// End of hal_memmap.h +#endif // CYGONCE_HAL_MEMMAP_H diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_ram.h b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_ram.h new file mode 100644 index 00000000..3a5de18a --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_ram.h @@ -0,0 +1,84 @@ +#ifndef CYGONCE_MLT_COLDFIRE_RAM_H +#define CYGONCE_MLT_COLDFIRE_RAM_H + +//============================================================================= +// +// mlt_coldfire_m5272c3_ram.h +// +// Platform specific memory section definitions for RAM startup +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Memory section definitions specific to the M5272C3 board, +// used for RAM startup configuration. +// +//####DESCRIPTIONEND#### +//======================================================================== + +// eCos memory layout + +#include + +#define CYGMEM_REGION_sdram (0x00000000) +#define CYGMEM_REGION_sdram_SIZE (0x01000000) + +#define CYGMEM_REGION_devs (0x10000000) +#define CYGMEM_REGION_devs_SIZE (0x00001800) + +#define CYGMEM_REGION_sram (0x20000000) +#define CYGMEM_REGION_sram_SIZE (0x00001000) + +#define CYGMEM_REGION_ext_sram (0x30000000) +#define CYGMEM_REGION_ext_sram_SIZE (0x00080000) + +#define CYGMEM_REGION_flash (0xFFE00000) +#define CYGMEM_REGION_flash_SIZE (0x00200000) + +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x01000000 - (size_t) CYG_LABEL_NAME (__heap1)) +externC unsigned char CYG_LABEL_NAME (__heap1) []; + +// These symbols are required by the test cases. Normally the memory tool would generate them, +// but this file was been generated by hand and so is a little +// different to normal. +#define CYGMEM_REGION_ram CYGMEM_REGION_sdram +#define CYGMEM_REGION_ram_SIZE CYGMEM_REGION_sdram_SIZE + +// --------------------------------------------------------------------------- +// End of mlt_coldfire_m5272c3_ram.h +#endif // CYGONCE_MLT_COLDFIRE_RAM_H diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_ram.ldi b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_ram.ldi new file mode 100644 index 00000000..2f8ac671 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_ram.ldi @@ -0,0 +1,85 @@ +//=========================================================================== +// +// mlt_coldfire_m5272c3_ram.ldi +// +// RAM startup linker control script +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Linker script specific to the M5272C3 board, used for +// RAM startup. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include + +MEMORY +{ + sdram : ORIGIN = 0x00000000, LENGTH = 0x01000000 + devs : ORIGIN = 0x10000000, LENGTH = 0x00001800 + sram : ORIGIN = 0x20000000, LENGTH = 0x00001000 + ext_sram : ORIGIN = 0x30000000, LENGTH = 0x00080000 + flash : ORIGIN = 0xFFE00000, LENGTH = 0x00200000 +} + +SECTIONS +{ + SECTIONS_BEGIN + + SECTION_ramvec (sdram, 0x00000000 (NOLOAD), LMA_EQ_VMA) + SECTION_virtual_vec_table (sdram, ALIGN(0x4) (NOLOAD), LMA_EQ_VMA) + + // Reserve some space to the ROM monitor + SECTION_romvec (sdram, 0x00020000, LMA_EQ_VMA) + SECTION_boot (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_text (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_fini (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_rodata1 (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_rodata (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_fixup (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_data (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_bss (sdram, ALIGN(0x4) (NOLOAD), LMA_EQ_VMA) + SECTION_uninvar (sdram, ALIGN(0x4) (NOLOAD), LMA_EQ_VMA) + + // The heap starts here. + CYG_LABEL_DEFN(__heap1) = ALIGN (0x4); + + SECTIONS_END +} diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_rom.h b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_rom.h new file mode 100644 index 00000000..5adc7d83 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_rom.h @@ -0,0 +1,84 @@ +#ifndef CYGONCE_MLT_COLDFIRE_ROM_H +#define CYGONCE_MLT_COLDFIRE_ROM_H + +//============================================================================= +// +// mlt_coldfire_m5272c3_rom.h +// +// Platform specific memory section definitions for ROM startup +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Memory section definitions specific to the M5272C3 board, +// used for ROM startup configuration. +// +//####DESCRIPTIONEND#### +//======================================================================== + +// eCos memory layout + +#include + +#define CYGMEM_REGION_sdram (0x00000000) +#define CYGMEM_REGION_sdram_SIZE (0x01000000) + +#define CYGMEM_REGION_devs (0x10000000) +#define CYGMEM_REGION_devs_SIZE (0x00001800) + +#define CYGMEM_REGION_sram (0x20000000) +#define CYGMEM_REGION_sram_SIZE (0x00001000) + +#define CYGMEM_REGION_ext_sram (0x30000000) +#define CYGMEM_REGION_ext_sram_SIZE (0x00080000) + +#define CYGMEM_REGION_flash (0xFFE00000) +#define CYGMEM_REGION_flash_SIZE (0x00200000) + +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x01000000 - (size_t) CYG_LABEL_NAME (__heap1)) +externC unsigned char CYG_LABEL_NAME (__heap1) []; + +// These symbols are required by the test cases. Normally the memory tool would generate them, +// but this file was been generated by hand and so is a little +// different to normal. +#define CYGMEM_REGION_ram CYGMEM_REGION_sdram +#define CYGMEM_REGION_ram_SIZE CYGMEM_REGION_sdram_SIZE + +// --------------------------------------------------------------------------- +// End of mlt_coldfire_m5272c3_rom.h +#endif // CYGONCE_MLT_COLDFIRE_ROM_H diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_rom.ldi b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_rom.ldi new file mode 100644 index 00000000..3f32d969 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_rom.ldi @@ -0,0 +1,94 @@ +//=========================================================================== +// +// mlt_coldfire_m5272c3_rom.ldi +// +// ROM startup linker control script +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Linker script specific to the M5272C3 board, used for +// ROM startup. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include CYGBLD_HAL_PLATFORM_H + +MEMORY +{ + sdram : ORIGIN = 0x00000000, LENGTH = 0x01000000 + devs : ORIGIN = 0x10000000, LENGTH = 0x00001800 + sram : ORIGIN = 0x20000000, LENGTH = 0x00001000 + ext_sram : ORIGIN = 0x30000000, LENGTH = 0x00080000 + flash : ORIGIN = 0xFFE00000, LENGTH = 0x00200000 +} + +SECTIONS +{ + SECTIONS_BEGIN + +#if (CYGHWR_HAL_ROM_LMA == 0xFFF00000) + SECTION_romvec (flash, 0xFFF00000, LMA_EQ_VMA) +#else + SECTION_romvec (flash, 0xFFE00000, LMA_EQ_VMA) +#endif + + SECTION_boot (flash, ALIGN (0x4), LMA_EQ_VMA) + SECTION_text (flash, ALIGN (0x4),LMA_EQ_VMA) + SECTION_fini (flash, ALIGN (0x4),LMA_EQ_VMA) + SECTION_rodata1 (flash, ALIGN (0x4),LMA_EQ_VMA) + SECTION_rodata (flash, ALIGN (0x4),LMA_EQ_VMA) + SECTION_fixup (flash, ALIGN (0x4),LMA_EQ_VMA) + SECTION_gcc_except_table (flash, ALIGN (0x4),LMA_EQ_VMA) + + SECTION_ramvec (sdram, 0x00000000 (NOLOAD), LMA_EQ_VMA) + SECTION_virtual_vec_table (sdram, ALIGN (0x4) (NOLOAD), LMA_EQ_VMA) + SECTION_data (sdram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (sdram, ALIGN (0x4) (NOLOAD), LMA_EQ_VMA) + SECTION_uninvar (sdram, ALIGN (0x4) (NOLOAD), LMA_EQ_VMA) + + // The heap starts here. + CYG_LABEL_DEFN(__heap1) = ALIGN (0x4); + + CYG_LABEL_DEFN(__romram_copy_source) = LOADADDR(.data); + CYG_LABEL_DEFN(__romram_copy_dest) = ADDR(.data); + CYG_LABEL_DEFN(__romram_copy_length) = SIZEOF(.data); + + SECTIONS_END +} diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_romram.h b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_romram.h new file mode 100644 index 00000000..11ab83f4 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_romram.h @@ -0,0 +1,84 @@ +#ifndef CYGONCE_MLT_COLDFIRE_ROMRAM_H +#define CYGONCE_MLT_COLDFIRE_ROMRAM_H + +//============================================================================= +// +// mlt_coldfire_m5272c3_romram.h +// +// Platform specific memory section definitions for ROMRAM startup +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Memory section definitions specific to the M5272C3 board, +// used for ROMRAM startup configuration. +// +//####DESCRIPTIONEND#### +//======================================================================== + +// eCos memory layout + +#include + +#define CYGMEM_REGION_sdram (0x00000000) +#define CYGMEM_REGION_sdram_SIZE (0x01000000) + +#define CYGMEM_REGION_devs (0x10000000) +#define CYGMEM_REGION_devs_SIZE (0x00001800) + +#define CYGMEM_REGION_sram (0x20000000) +#define CYGMEM_REGION_sram_SIZE (0x00001000) + +#define CYGMEM_REGION_ext_sram (0x30000000) +#define CYGMEM_REGION_ext_sram_SIZE (0x00080000) + +#define CYGMEM_REGION_flash (0xFFE00000) +#define CYGMEM_REGION_flash_SIZE (0x00200000) + +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x01000000 - (size_t) CYG_LABEL_NAME (__heap1)) +externC unsigned char CYG_LABEL_NAME (__heap1) []; + +// These symbols are required by the test cases. Normally the memory tool would generate them, +// but this file was been generated by hand and so is a little +// different to normal. +#define CYGMEM_REGION_ram CYGMEM_REGION_sdram +#define CYGMEM_REGION_ram_SIZE CYGMEM_REGION_sdram_SIZE + +// --------------------------------------------------------------------------- +// End of mlt_coldfire_m5272c3_romram.h +#endif // CYGONCE_MLT_COLDFIRE_ROMRAM_H diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_romram.ldi b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_romram.ldi new file mode 100644 index 00000000..33791b2e --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/pkgconf/mlt_coldfire_m5272c3_romram.ldi @@ -0,0 +1,95 @@ +//=========================================================================== +// +// mlt_coldfire_m5272c3_romram.ldi +// +// ROMRAM startup linker control script +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Linker script specific to the M5272C3 board, used for +// ROMRAM startup. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include CYGBLD_HAL_PLATFORM_H + +MEMORY +{ + sdram : ORIGIN = 0x00000000, LENGTH = 0x01000000 + devs : ORIGIN = 0x10000000, LENGTH = 0x00001800 + sram : ORIGIN = 0x20000000, LENGTH = 0x00001000 + ext_sram : ORIGIN = 0x30000000, LENGTH = 0x00080000 + flash : ORIGIN = 0xFFE00000, LENGTH = 0x00200000 +} + +SECTIONS +{ + SECTIONS_BEGIN + +#if (CYGHWR_HAL_ROM_LMA == 0xFFF00000) + SECTION_romvec (flash, 0xFFF00000, LMA_EQ_VMA) +#else + SECTION_romvec (flash, 0xFFE00000, LMA_EQ_VMA) +#endif + + SECTION_boot (flash, ALIGN(0x4), FOLLOWING(.romvec)) + + SECTION_ramvec (sdram, 0x00000000 (NOLOAD), LMA_EQ_VMA) + SECTION_virtual_vec_table (sdram, ALIGN (0x4) (NOLOAD), LMA_EQ_VMA) + + SECTION_text (sdram, ALIGN (0x4),FOLLOWING(.boot)) + SECTION_fini (sdram, ALIGN (0x4),FOLLOWING(.text)) + SECTION_rodata1 (sdram, ALIGN (0x4),FOLLOWING(.fini)) + SECTION_rodata (sdram, ALIGN (0x4),FOLLOWING(.rodata1)) + SECTION_fixup (sdram, ALIGN (0x4),FOLLOWING(.rodata)) + SECTION_gcc_except_table (sdram, ALIGN (0x4),FOLLOWING(.fixup)) + SECTION_data (sdram, ALIGN (0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (sdram, ALIGN (0x4) (NOLOAD), LMA_EQ_VMA) + SECTION_uninvar (sdram, ALIGN (0x4) (NOLOAD), LMA_EQ_VMA) + + // The heap starts here. + CYG_LABEL_DEFN(__heap1) = ALIGN (0x4); + + CYG_LABEL_DEFN(__romram_copy_source) = LOADADDR(.text); + CYG_LABEL_DEFN(__romram_copy_dest) = ADDR(.text); + CYG_LABEL_DEFN(__romram_copy_length) = SIZEOF(.text) + SIZEOF(.fini) + SIZEOF(.rodata1) + SIZEOF(.rodata) + SIZEOF(.fixup) + SIZEOF(.gcc_except_table) + SIZEOF(.data); + + SECTIONS_END +} diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/platform.inc b/packages/hal/coldfire/m5272c3/v2_0/include/platform.inc new file mode 100644 index 00000000..518a18e4 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/platform.inc @@ -0,0 +1,76 @@ +#ifndef CYGONCE_HAL_PLATFORM_INC +#define CYGONCE_HAL_PLATFORM_INC + +|============================================================================= +| +| platform.inc +| +| M5272C3 board assembler header file +| +|============================================================================= +|###ECOSGPLCOPYRIGHTBEGIN#### +| ------------------------------------------- +| This file is part of eCos, the Embedded Configurable Operating System. +| Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +| Copyright (C) 2006 eCosCentric Ltd. +| +| 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): Enrico Piria +| Contributors: +| Date: 2005-25-06 +| Purpose: Assembler macro definitions specific to the M5272C3 board. +| Usage: Included by "variant.inc". Do not use directly. +| +|####DESCRIPTIONEND#### +|======================================================================== + +#include + +|------------------------------------------------------------------------------- +| Platform initialization macros + + .macro hal_hardware_init + | Initialize RAMBAR: locate SRAM and validate it. + move.l #CYGMEM_REGION_sram,%d0 + add.l #0x21,%d0 + movec %d0,%rambar0 + .endm + + + | Setup stack for startup routines. Use SRAM module. + .macro hal_boot_stack_init + | Point Stack Pointer into SRAM temporarily. + move.l #CYGMEM_REGION_sram,%d0 + add.l #CYGMEM_REGION_sram_SIZE,%d0 + move.l %d0,%sp + .endm + +|----------------------------------------------------------------------------- +| End of platform.inc +#endif // CYGONCE_HAL_PLATFORM_INC diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/plf_intr.h b/packages/hal/coldfire/m5272c3/v2_0/include/plf_intr.h new file mode 100644 index 00000000..f3174f72 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/plf_intr.h @@ -0,0 +1,73 @@ +#ifndef CYGONCE_HAL_PLF_INTR_H +#define CYGONCE_HAL_PLF_INTR_H + +//========================================================================== +// +// plf_intr.h +// +// Platform specific interrupt and clock support +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Interrupt and clock definitions specific to the M5272C3 board. +// Usage: Included via "var_intr.h". Do not use directly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include + +// --------------------------------------------------------------------------- +// Reset + +#ifndef CYGHWR_HAL_RESET_DEFINED + +externC void cyg_hal_reset_vsr( void ); + +#define CYGHWR_HAL_RESET_DEFINED +#define HAL_PLATFORM_RESET() cyg_hal_reset_vsr() + +#define HAL_PLATFORM_RESET_ENTRY &cyg_hal_reset_vsr + +#endif // CYGHWR_HAL_RESET_DEFINED + +// --------------------------------------------------------------------------- +// End of plf_intr.h +#endif // CYGONCE_HAL_PLF_INTR_H diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/plf_serial.h b/packages/hal/coldfire/m5272c3/v2_0/include/plf_serial.h new file mode 100644 index 00000000..7448f807 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/plf_serial.h @@ -0,0 +1,98 @@ +#ifndef CYGONCE_PLF_SERIAL_H +#define CYGONCE_PLF_SERIAL_H + +//============================================================================= +// +// plf_serial.h +// +// Platform specific definitions for diagnstic ouput via serial port +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Definitions for diagnostic output via serial port +// Usage: #include +// +//####DESCRIPTIONEND#### +//======================================================================== + +#define MCF5272_UART_UMR_8BNP (0x13) +#define MCF5272_UART_UMR_1S (0x07) + +#define MCF5272_UART_USR_RRDY (1<<0) +#define MCF5272_UART_USR_FFUL (1<<1) +#define MCF5272_UART_USR_TXRDY (1<<2) +#define MCF5272_UART_USR_TXEMP (1<<3) +#define MCF5272_UART_USR_OE (1<<4) +#define MCF5272_UART_USR_PE (1<<5) +#define MCF5272_UART_USR_FE (1<<6) +#define MCF5272_UART_USR_RB (1<<7) + +#define MCF5272_UART_UCSR_CLKIN (0xDD) + +#define MCF5272_UART_UCR_RMR (0x01<<4) +#define MCF5272_UART_UCR_RRX (0x02<<4) +#define MCF5272_UART_UCR_RTX (0x03<<4) +#define MCF5272_UART_UCR_RES (0x04<<4) +#define MCF5272_UART_UCR_RBC (0x05<<4) +#define MCF5272_UART_UCR_TXEN (1<<2) +#define MCF5272_UART_UCR_TXDE (1<<3) +#define MCF5272_UART_UCR_RXEN (1<<0) +#define MCF5272_UART_UCR_RXDE (1<<1) + +#define MCF5272_UART_UCR_TXRXEN \ + (MCF5272_UART_UCR_TXEN | \ + MCF5272_UART_UCR_RXEN) + +#define MCF5272_UART_UIMR_FFULL (0x02) + +#define MCF5272_UART_UTF_TXB (0x1F) + +#define MCF5272_UART_UOP0_RTS (0x01) +#define MCF5272_UART_UOP1_RTS (0x01) + +#define MCF5272_GPIO_PBCNT_URT0_EN (0x00000155) +#define MCF5272_GPIO_PBCNT_URT0_DE (0x00000000) +#define MCF5272_GPIO_PBCNT_URT0_MSK (0x000003FF) + +#define MCF5272_GPIO_PDCNT_URT1_EN (0x000002AA) +#define MCF5272_GPIO_PDCNT_URT1_DE (0x00000000) +#define MCF5272_GPIO_PDCNT_URT1_MSK (0x000003FF) + +// --------------------------------------------------------------------------- +// End of plf_serial.h +#endif // CYGONCE_PLF_SERIAL_H diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/plf_startup.h b/packages/hal/coldfire/m5272c3/v2_0/include/plf_startup.h new file mode 100644 index 00000000..75585178 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/plf_startup.h @@ -0,0 +1,61 @@ +#ifndef CYGONCE_PLF_STARTUP_H +#define CYGONCE_PLF_STARTUP_H + +//============================================================================= +// +// plf_startup.h +// +// M5272C3 platform startup header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: M5272C3 platform startup header. +// Usage: Included via "var_startup.h". Do not use directly. +// +//####DESCRIPTIONEND#### +//========================================================================== + +// Platform specific reset vector initialization routine +externC void plf_reset(void) __attribute__ ((section (".boot"))); + +// Platform specific data initialization routine +externC void plf_init_data(void) __attribute__ ((section (".boot"))); + +// --------------------------------------------------------------------------- +// End of plf_startup.h +#endif // CYGONCE_PLF_STARTUP_H diff --git a/packages/hal/coldfire/m5272c3/v2_0/include/plf_stub.h b/packages/hal/coldfire/m5272c3/v2_0/include/plf_stub.h new file mode 100644 index 00000000..bdbfad5e --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/include/plf_stub.h @@ -0,0 +1,79 @@ +#ifndef CYGONCE_HAL_PLF_STUB_H +#define CYGONCE_HAL_PLF_STUB_H + +//======================================================================== +// +// plf_stub.h +// +// Platform specific definitions for generic stub +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: GDB stub definitions specific to the M5272C3 board. +// Usage: #include +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include // CYG_UNUSED_PARAM + +#include // architecture stub support + + +externC void cyg_hal_plf_comms_init(void); + +#define HAL_STUB_PLATFORM_INIT_SERIAL() cyg_hal_plf_comms_init() + +#define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int,(baud)) +#define HAL_STUB_PLATFORM_INTERRUPTIBLE 0 +#define HAL_STUB_PLATFORM_INIT_BREAK_IRQ() CYG_EMPTY_STATEMENT + +// --------------------------------------------------------------------------- +// Stub initializer + +#define HAL_STUB_PLATFORM_INIT() CYG_EMPTY_STATEMENT + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +// --------------------------------------------------------------------------- +// End of plf_stub.h +#endif // CYGONCE_HAL_PLF_STUB_H diff --git a/packages/hal/coldfire/m5272c3/v2_0/src/plf_mk_defs.c b/packages/hal/coldfire/m5272c3/v2_0/src/plf_mk_defs.c new file mode 100644 index 00000000..0689ac0d --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/src/plf_mk_defs.c @@ -0,0 +1,85 @@ +//========================================================================== +// +// plf_mk_defs.c +// +// "make defs" program for M5272C3 platform +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 Gary Thomas +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: gthomas, jskov +// Date: 2005-25-06 +// Purpose: Definition generator for M5272C3 board. +// Description: This file contains code that can be compiled by the target +// compiler and used to generate machine specific definitions +// suitable for use in assembly code. +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include CYGHWR_MEMORY_LAYOUT_H + +// This program is used to generate definitions needed by +// assembly language modules. +// +// This technique was first used in the OSF Mach kernel code: +// generate asm statements containing #defines, +// compile this file to assembler, and then extract the +// #defines from the assembly-language output. + +#define DEFINE(sym, val) \ + asm volatile("\n\t.equ\t" #sym ",%0" : : "i" (val)) + +int +main(void) +{ + // Memory layout values + DEFINE(CYGMEM_REGION_sdram, CYGMEM_REGION_sdram); + DEFINE(CYGMEM_REGION_sdram_SIZE, CYGMEM_REGION_sdram_SIZE); + DEFINE(CYGMEM_REGION_devs, CYGMEM_REGION_devs); + DEFINE(CYGMEM_REGION_devs_SIZE, CYGMEM_REGION_devs_SIZE); + DEFINE(CYGMEM_REGION_sram, CYGMEM_REGION_sram); + DEFINE(CYGMEM_REGION_sram_SIZE, CYGMEM_REGION_sram_SIZE); + DEFINE(CYGMEM_REGION_flash, CYGMEM_REGION_flash); + DEFINE(CYGMEM_REGION_flash_SIZE, CYGMEM_REGION_flash_SIZE); + + return 0; +} + +// ------------------------------------------------------------------------- +// EOF hal_mk_defs.c diff --git a/packages/hal/coldfire/m5272c3/v2_0/src/plf_startup.c b/packages/hal/coldfire/m5272c3/v2_0/src/plf_startup.c new file mode 100644 index 00000000..d3e72e16 --- /dev/null +++ b/packages/hal/coldfire/m5272c3/v2_0/src/plf_startup.c @@ -0,0 +1,255 @@ +//========================================================================== +// +// plf_startup.c +// +// M5272C3 platform HAL startup code +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Platform startup code. +// Description: This module contains code that sets up the platform specific +// hardware and data. All the code must be contained in the +// section called ".boot", in order for the ROMRAM startup +// to work properly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include +#include +#include CYGHWR_MEMORY_LAYOUT_H +#include +#include +#include + +static void plf_init_sim(void) __attribute__ ((section (".boot"))); +static void plf_init_intc(void) __attribute__ ((section (".boot"))); +static void plf_init_cs(void) __attribute__ ((section (".boot"))); +static void plf_init_sdramc(void) __attribute__ ((section (".boot"))); +static void plf_init_cache_acr(void) __attribute__ ((section (".boot"))); + + +// Platform-specific reset vector initialization routine +void plf_reset(void) +{ + plf_init_sim(); + plf_init_intc(); + plf_init_cs(); + plf_init_sdramc(); + + // Call a routine to set up the cache and ACRs for this specific + // platform. + plf_init_cache_acr(); +} + + +// Initialize the cache and access control registers. +// The reset procedure already invalidated the cache and ACRs. +// This routine only needs to enable the ACRs that it will use. +static void plf_init_cache_acr(void) +{ + // Enable the instruction cache with the following options: + // Enable CPUSHL invalidation. + // No freeze. + // Invalidate all cache lines (flush). + // No external arbiter control. + // Disable non-cacheable instruction bursting. + // Default memory is cacheable. + // Enable buffered writes. + // Read and write access permitted by default. + // Instruction fetch size is cache line. + +#ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP + CYGARC_MOVEC((CYG_WORD32) 0x81000102, CYGARC_REG_CACR); +#endif + + // Leave the access control registers disabled. +} + + +// Initialize SIM module and system configuration registers +void plf_init_sim(void) +{ + // Set up the mapping of our internal registers. The LSB indicates that + // the register contents are valid. + CYGARC_MOVEC((CYG_WORD32)(CYGMEM_REGION_devs | 1), CYGARC_REG_MBAR); + + // Initialize System Config Register + // Setup Watch Dog Timeout + HAL_WRITE_UINT16(&MCF5272_DEVS->cfg.scr, MCF5272_SIM_SCR_HWWD_1024); + + // Initialize System Protection Register + // Enable all bus error exceptions + HAL_WRITE_UINT16(&MCF5272_DEVS->cfg.spr, + (0 | MCF5272_SIM_SPR_ADC | MCF5272_SIM_SPR_ADCEN + | MCF5272_SIM_SPR_WPV | MCF5272_SIM_SPR_WPVEN + | MCF5272_SIM_SPR_SMV | MCF5272_SIM_SPR_SMVEN + | MCF5272_SIM_SPR_SBE | MCF5272_SIM_SPR_SBEEN + | MCF5272_SIM_SPR_HWT | MCF5272_SIM_SPR_HWTEN + | MCF5272_SIM_SPR_RPV | MCF5272_SIM_SPR_RPVEN + | MCF5272_SIM_SPR_EXT | MCF5272_SIM_SPR_EXTEN + | MCF5272_SIM_SPR_SUV | MCF5272_SIM_SPR_SUVEN + )) ; +} + + +// Initialize interrupt controller +void plf_init_intc(void) +{ + int i; + + // Initialize the vector base register in the interrupt controller. + HAL_WRITE_UINT8(&MCF5272_DEVS->intc.ipvr, HAL_PROG_INT_VEC_BASE); + + // Initialize the interrupt control register. + // Disable all interrupts by setting all priorities to zero. + for (i = 0; i < 4; i++) + { + HAL_WRITE_UINT32(&MCF5272_DEVS->intc.icr[i], 0x88888888); + } + + // Initialize the processor's vector base register (align to 1M boundary). + CYGARC_MOVEC((CYG_WORD32) __ramvec_start & 0xFFF00000, CYGARC_REG_VBR); +} + + +// Initialize chip-select modules +void plf_init_cs(void) +{ + // ChipSelect 0 - 2MB FLASH + // At startup, CS0 is configured so that addresses starting at 0xXXX00000 + // are aliased to 0x00000000, so, in ROM startup configuration, code can + // be placed starting at VMA address 0xFFE00000. When we are here, + // the PC points to addresses in 0xFFE00000 space, and we can safely + // reconfigure CS0 to respond uniquely to those addresses. + HAL_WRITE_UINT32(&MCF5272_DEVS->cs[0].csbr, (0 + | MCF5272_CS_BR_BASE(CYGMEM_REGION_flash) + | MCF5272_CS_BR_SRAM + | MCF5272_CS_BR_PS_16 + | MCF5272_CS_BR_EN)); + + HAL_WRITE_UINT32(&MCF5272_DEVS->cs[0].csor, + (0 | MCF5272_CS_OR_MASK_2M + | MCF5272_CS_OR_WS(5))); + +#ifdef CYGHWR_EXT_SRAM_INSTALLED + // Chip Select 2 - 512KB SRAM + HAL_WRITE_UINT32(&MCF5272_DEVS->cs[2].csbr, (0 + | MCF5272_CS_BR_BASE(CYGMEM_REGION_ext_sram) + | MCF5272_CS_BR_SRAM + | MCF5272_CS_BR_PS_32 + | MCF5272_CS_BR_EN)); + + HAL_WRITE_UINT32(&MCF5272_DEVS->cs[2].csor, (0 + | MCF5272_CS_OR_MASK_512K + | MCF5272_CS_OR_WS(0))); +#endif // CYGHWR_EXT_SRAM_INSTALLED + + // ChipSelect 7 - 16MB SDRAM + HAL_WRITE_UINT32(&MCF5272_DEVS->cs[7].csbr, (0 + | MCF5272_CS_BR_BASE(CYGMEM_REGION_sdram) + | MCF5272_CS_BR_SDRAM + | MCF5272_CS_BR_PS_LINE + | MCF5272_CS_BR_EN)); + + HAL_WRITE_UINT32(&MCF5272_DEVS->cs[7].csor, (0 +#if (CYGHWR_INSTALLED_SDRAM_SIZE == 4) + | MCF5272_CS_OR_MASK_4M +#else + | MCF5272_CS_OR_MASK_16M +#endif + | MCF5272_CS_OR_WS(0x1F))); +} + + +// Initialize SDRAM controller +void plf_init_sdramc(void) +{ + cyg_uint16 sdcr; + + + HAL_READ_UINT16(&MCF5272_DEVS->sdramc.sdcr, sdcr); + + // Do not initialize SDRAM if it is already active + if (!(sdcr & MCF5272_SDRAMC_SDCCR_ACT)) + { +#if (CYGHWR_HAL_SYSTEM_CLOCK_MHZ == 66) + HAL_WRITE_UINT16(&MCF5272_DEVS->sdramc.sdtr, (0 + | MCF5272_SDRAMC_SDCTR_RTP_66MHz + | MCF5272_SDRAMC_SDCTR_RC(0) + | MCF5272_SDRAMC_SDCTR_RP(1) + | MCF5272_SDRAMC_SDCTR_RCD(1) + | MCF5272_SDRAMC_SDCTR_CLT_2)); +#else + // Clock frequency must be 48 Mhz + HAL_WRITE_UINT16(&MCF5272_DEVS->sdramc.sdtr, (0 + | MCF5272_SDRAMC_SDCTR_RTP_48MHz + | MCF5272_SDRAMC_SDCTR_RC(0) + | MCF5272_SDRAMC_SDCTR_RP(1) + | MCF5272_SDRAMC_SDCTR_RCD(0) + | MCF5272_SDRAMC_SDCTR_CLT_2)); +#endif + + HAL_WRITE_UINT16(&MCF5272_DEVS->sdramc.sdcr, (0 + | MCF5272_SDRAMC_SDCCR_MCAS_A9 +#if (CYGHWR_INSTALLED_SDRAM_SIZE == 4) + | MCF5272_SDRAMC_SDCCR_BALOC_A21 +#else + | MCF5272_SDRAMC_SDCCR_BALOC_A22 +#endif + | MCF5272_SDRAMC_SDCCR_REG + | MCF5272_SDRAMC_SDCCR_INIT)); + + // Start SDRAM controller with a memory write + *((volatile char *) CYGMEM_REGION_sdram) = 0; + + // Wait until controller is ready + do + { + HAL_READ_UINT16(&MCF5272_DEVS->sdramc.sdcr, sdcr); + } while(!(sdcr & MCF5272_SDRAMC_SDCCR_ACT)); + } +} + + +// Platform specific data initialization routine +void plf_init_data(void) +{ + // Nothing to do +} diff --git a/packages/hal/coldfire/mcf5272/v2_0/ChangeLog b/packages/hal/coldfire/mcf5272/v2_0/ChangeLog new file mode 100644 index 00000000..854a1caa --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/ChangeLog @@ -0,0 +1,49 @@ +2005-06-24 Enrico Piria + + * src/var_misc.c: + * src/var_startup.c: + * src/hal_diag.c: + * src/variant.S: + * include/hal_diag.h: + * include/mcf5272_devs.h: + * include/var_arch.h: + * include/var_basetype.h: + * include/var_cache.h: + * include/var_intr.h: + * include/var_regs.h: + * include/var_startup.h: + * include/variant.inc: + * cdl/hal_coldfire_mcf5272.cdl: + Rework of the original MCF5272 variant HAL contributed by Wade Jensen. + +//=========================================================================== +//####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. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/coldfire/mcf5272/v2_0/cdl/hal_coldfire_mcf5272.cdl b/packages/hal/coldfire/mcf5272/v2_0/cdl/hal_coldfire_mcf5272.cdl new file mode 100644 index 00000000..ef513c51 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/cdl/hal_coldfire_mcf5272.cdl @@ -0,0 +1,94 @@ +# ==================================================================== +# +# hal_coldfire_mcf5272.cdl +# +# MCF5272 variant architectural HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2006 eCosCentric Ltd. +## +## 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): Enrico Piria +## Contributors: Wade Jensen +## Date: 2005-25-06 +## +######DESCRIPTIONEND#### +##======================================================================== + +cdl_package CYGPKG_HAL_COLDFIRE_MCF5272 { + display "MCF5272 ColdFire variant HAL" + parent CYGPKG_HAL_COLDFIRE + requires CYGPKG_HAL_COLDFIRE + implements CYGINT_HAL_COLDFIRE_VARIANT + implements CYGARC_HAL_COLDFIRE_V2_CORE + implements CYGARC_HAL_COLDFIRE_MAC + implements CYGARC_HAL_COLDFIRE_ISA_A + hardware + include_dir cyg/hal + define_header hal_coldfire_mcf5272.h + + description "The ColdFire 5272 variant HAL package provides + generic support for the ColdFire 5272 processor. It is also + necessary to select a specific target platform HAL package." + + define_proc { + puts $::cdl_header "#include " + } + + compile var_startup.c var_misc.c variant.S + + cdl_option CYGHWR_HAL_COLDFIRE_MAC { + display "MAC support" + flavor bool + default_value 0 + description " + Enable or disable support for MAC operations. MAC registers will be + saved during context switches, during exceptions, and in the + setjmp/longjmp routines. If you don't use the MAC unit, you can + leave this option disabled." + } + + # With this calculated option, code for diagnostic/debug output is compiled + # only if it is really needed. + cdl_option CYGBLD_HAL_COLDFIRE_MCF5272_DIAG { + display "Compile HAL diagnostic output code" + flavor bool + no_define + calculated { is_active(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL) || + is_active(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL) } + compile hal_diag.c + description " + This calculated option is enabled only when code for + diagnostic/debug output is really needed." + } +} diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/hal_diag.h b/packages/hal/coldfire/mcf5272/v2_0/include/hal_diag.h new file mode 100644 index 00000000..b718371d --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/hal_diag.h @@ -0,0 +1,67 @@ +#ifndef CYGONCE_HAL_HAL_DIAG_H +#define CYGONCE_HAL_HAL_DIAG_H + +//============================================================================= +// +// hal_diag.h +// +// HAL support for kernel diagnostic routines +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Provide ColdFire-specific diagnostic system definitions. +// Usage: #include +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include + +#include + +// We suppose that CYGSEM_HAL_VIRTUAL_VECTOR_DIAG is always defined + +#include + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + +// --------------------------------------------------------------------------- +// End of hal_diag.h +#endif // CYGONCE_HAL_HAL_DIAG_H diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/mcf5272_devs.h b/packages/hal/coldfire/mcf5272/v2_0/include/mcf5272_devs.h new file mode 100644 index 00000000..c78a7bbc --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/mcf5272_devs.h @@ -0,0 +1,708 @@ +#ifndef CYGONCE_MCF5272_DEVS_H +#define CYGONCE_MCF5272_DEVS_H + +//============================================================================= +// +// mcf5272_devs.h +// +// Definitions for the MCF5272 on-chip peripherals +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria, Wade Jensen +// Contributors: +// Date: 2005-25-06 +// Purpose: Definitions for the MCF5272 on-chip peripherals. +// Usage: #include +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include + +// General configuration registers +typedef struct +{ + + // Module base address register + cyg_uint32 mbar; + + // System configuration register + cyg_uint16 scr; + + // System protection register + cyg_uint16 spr; + + // Power management register + cyg_uint32 pmr; + + // Gap + cyg_uint16 _res1; + + // Active low power register + cyg_uint16 alpr; + + // Device identification register + cyg_uint32 dir; + + // Gap + cyg_uint32 _res2[3]; + +} __attribute__ ((aligned (4), packed)) mcf5272_sim_cfg_t; + +// Configuration registers macros + +#define MCF5272_SIM_SCR_HWWD_1024 0x0003 + +#define MCF5272_SIM_SPR_ADC 0x8000 +#define MCF5272_SIM_SPR_ADCEN 0x0080 +#define MCF5272_SIM_SPR_WPV 0x4000 +#define MCF5272_SIM_SPR_WPVEN 0x0040 +#define MCF5272_SIM_SPR_SMV 0x2000 +#define MCF5272_SIM_SPR_SMVEN 0x0020 +#define MCF5272_SIM_SPR_SBE 0x1000 +#define MCF5272_SIM_SPR_SBEEN 0x0010 +#define MCF5272_SIM_SPR_HWT 0x0800 +#define MCF5272_SIM_SPR_HWTEN 0x0008 +#define MCF5272_SIM_SPR_RPV 0x0400 +#define MCF5272_SIM_SPR_RPVEN 0x0004 +#define MCF5272_SIM_SPR_EXT 0x0200 +#define MCF5272_SIM_SPR_EXTEN 0x0002 +#define MCF5272_SIM_SPR_SUV 0x0100 +#define MCF5272_SIM_SPR_SUVEN 0x0001 + +// --------------------------------------------------------------------------- + +// Interrupt controller registers +typedef struct +{ + + // Interrupt control register 1-4 + cyg_uint32 icr[4]; + + // Interrupt source register + cyg_uint32 isr; + + // Programmable interrupt transition register + cyg_uint32 pitr; + + // Programmable interrupt wakeup register + cyg_uint32 piwr; + + // Gap + cyg_uint8 _res1[3]; + + // Programmable interrupt vector register + cyg_uint8 ipvr; + +} __attribute__ ((aligned (4), packed)) mcf5272_sim_int_t; + +// Interrupt controller related macros + +#define MCF5272_SIM_PITR_INT1_POS_EDGE (0x80000000) +#define MCF5272_SIM_PITR_INT2_POS_EDGE (0x40000000) +#define MCF5272_SIM_PITR_INT3_POS_EDGE (0x20000000) +#define MCF5272_SIM_PITR_INT4_POS_EDGE (0x10000000) +#define MCF5272_SIM_PITR_INT5_POS_EDGE (0x00000040) +#define MCF5272_SIM_PITR_INT6_POS_EDGE (0x00000020) + +#define MCF5272_SIM_PIWR_INT1_WAKE (0x80000000) +#define MCF5272_SIM_PIWR_INT2_WAKE (0x40000000) +#define MCF5272_SIM_PIWR_INT3_WAKE (0x20000000) +#define MCF5272_SIM_PIWR_INT4_WAKE (0x10000000) +#define MCF5272_SIM_PIWR_TMR0_WAKE (0x08000000) +#define MCF5272_SIM_PIWR_TMR1_WAKE (0x04000000) +#define MCF5272_SIM_PIWR_TMR2_WAKE (0x02000000) +#define MCF5272_SIM_PIWR_TMR3_WAKE (0x01000000) +#define MCF5272_SIM_PIWR_UART1_WAKE (0x00800000) +#define MCF5272_SIM_PIWR_UART2_WAKE (0x00400000) +#define MCF5272_SIM_PIWR_PLIP_WAKE (0x00200000) +#define MCF5272_SIM_PIWR_PLIA_WAKE (0x00100000) +#define MCF5272_SIM_PIWR_USB0_WAKE (0x00080000) +#define MCF5272_SIM_PIWR_USB1_WAKE (0x00040000) +#define MCF5272_SIM_PIWR_USB2_WAKE (0x00020000) +#define MCF5272_SIM_PIWR_USB3_WAKE (0x00010000) +#define MCF5272_SIM_PIWR_USB4_WAKE (0x00008000) +#define MCF5272_SIM_PIWR_USB5_WAKE (0x00004000) +#define MCF5272_SIM_PIWR_USB6_WAKE (0x00002000) +#define MCF5272_SIM_PIWR_USB7_WAKE (0x00001000) +#define MCF5272_SIM_PIWR_DMA_WAKE (0x00000800) +#define MCF5272_SIM_PIWR_ERX_WAKE (0x00000400) +#define MCF5272_SIM_PIWR_ETX_WAKE (0x00000200) +#define MCF5272_SIM_PIWR_ENTC_WAKE (0x00000100) +#define MCF5272_SIM_PIWR_QSPI_WAKE (0x00000080) +#define MCF5272_SIM_PIWR_INT5_WAKE (0x00000040) +#define MCF5272_SIM_PIWR_INT6_WAKE (0x00000020) +#define MCF5272_SIM_PIWR_SWTO_WAKE (0x00000010) + +// --------------------------------------------------------------------------- + +// Chip-select module +typedef struct +{ + + // CS base register + cyg_uint32 csbr; + + // CS option register + cyg_uint32 csor; + +} __attribute__ ((aligned (4), packed)) mcf5272_sim_cs_t; + +// Chip-select modules related macros + +#define MCF5272_CS_BR_BASE(a) ((a) & 0xFFFFF000) + +#define MCF5272_CS_OR_MASK_128M (0xF8000000) +#define MCF5272_CS_OR_MASK_64M (0xFC000000) +#define MCF5272_CS_OR_MASK_32M (0xFE000000) +#define MCF5272_CS_OR_MASK_16M (0xFF000000) +#define MCF5272_CS_OR_MASK_8M (0xFF800000) +#define MCF5272_CS_OR_MASK_4M (0xFFC00000) +#define MCF5272_CS_OR_MASK_2M (0xFFE00000) +#define MCF5272_CS_OR_MASK_1M (0xFFF00000) +#define MCF5272_CS_OR_MASK_512K (0xFFF80000) +#define MCF5272_CS_OR_MASK_256K (0xFFFC0000) +#define MCF5272_CS_OR_MASK_128K (0xFFFE0000) +#define MCF5272_CS_OR_MASK_64K (0xFFFF0000) +#define MCF5272_CS_OR_MASK_32K (0xFFFF8000) +#define MCF5272_CS_OR_MASK_16K (0xFFFFC000) +#define MCF5272_CS_OR_MASK_8K (0xFFFFE000) +#define MCF5272_CS_OR_MASK_4K (0xFFFFF000) +#define MCF5272_CS_OR_WS_MASK (0x007C) +#define MCF5272_CS_OR_WS(a) (((a) & 0x1F) << 2) +#define MCF5272_CS_OR_BRST (0x0100) +#define MCF5272_CS_OR_WR_ONLY (0x0003) +#define MCF5272_CS_OR_RD_ONLY (0x0001) + +#define MCF5272_CS_BR_PS_8 (0x0100) +#define MCF5272_CS_BR_PS_16 (0x0200) +#define MCF5272_CS_BR_PS_32 (0x0000) +#define MCF5272_CS_BR_PS_LINE (0x0300) +#define MCF5272_CS_BR_ROM (0x0000) +#define MCF5272_CS_BR_SRAM (0x0000) +#define MCF5272_CS_BR_SRAM_8 (0x0C00) +#define MCF5272_CS_BR_SDRAM (0x0400) +#define MCF5272_CS_BR_ISA (0x0800) +#define MCF5272_CS_BR_SV (0x0080) +#define MCF5272_CS_BR_EN (0x0001) + +// --------------------------------------------------------------------------- + +// General purpose I/O module +typedef struct +{ + + // Port A control register + cyg_uint32 pacnt; + + // Port A data direction register + cyg_uint16 paddr; + + // Port A data register + cyg_uint16 padat; + + // Port B control register + cyg_uint32 pbcnt; + + // Port B data direction register + cyg_uint16 pbddr; + + // Port B data register + cyg_uint16 pbdat; + + // Gap + cyg_uint32 _res1; + + // Port C data direction register + cyg_uint16 pcddr; + + // Port C data register + cyg_uint16 pcdat; + + // Port D control register + cyg_uint32 pdcnt; + + // Gap + cyg_uint16 _res2; + cyg_uint16 _res3; + +} __attribute__ ((aligned (4), packed)) mcf5272_sim_gpio_t; + +// GPIO ports related macros + +#define MCF5272_GPIO_DDR_IN (0) +#define MCF5272_GPIO_DDR_OUT (1) + +#define MCF5272_GPIO_PBCNT_ETH_EN (0x55550000) +#define MCF5272_GPIO_PBCNT_ETH_DE (0x00000000) +#define MCF5272_GPIO_PBCNT_ETH_MSK (0xFFFF0000) + +#define MCF5272_GPIO_PBCNT_TA_EN (0x00000400) +#define MCF5272_GPIO_PBCNT_TA_DE (0x00000000) +#define MCF5272_GPIO_PBCNT_TA_MSK (0x00000C00) + +#define MCF5272_GPIO_PBCNT_URT0_EN (0x00000155) +#define MCF5272_GPIO_PBCNT_URT0_DE (0x00000000) +#define MCF5272_GPIO_PBCNT_URT0_MSK (0x000003FF) + +#define MCF5272_GPIO_PDCNT_INT4_EN (0x00000C00) +#define MCF5272_GPIO_PDCNT_INT4_DE (0x00000000) +#define MCF5272_GPIO_PDCNT_INT4_MSK (0x00000C00) + +#define MCF5272_GPIO_PDCNT_URT1_EN (0x000002AA) +#define MCF5272_GPIO_PDCNT_URT1_DE (0x00000000) +#define MCF5272_GPIO_PDCNT_URT1_MSK (0x000003FF) + +// --------------------------------------------------------------------------- + +// UART module +typedef struct +{ + + // UART mode register + cyg_uint8 umr; + + // Gap + cyg_uint8 _res1[3]; + + // UART status register (R) and clock-select register (W) + cyg_uint8 usr_ucsr; + + // Gap + cyg_uint8 _res2[3]; + + // UART command register + cyg_uint8 ucr; + + // Gap + cyg_uint8 _res3[3]; + + // UART receiver buffers (R) and transmitter buffers (W) + cyg_uint8 urb_utb; + + // Gap + cyg_uint8 _res4[3]; + + // UART input port change register (R) and auxiliary control register (W) + cyg_uint8 uipcr_uacr; + + // Gap + cyg_uint8 _res5[3]; + + // UART interrupt status register (R) and interrupt mask register (W) + cyg_uint8 uisr_uimr; + + // Gap + cyg_uint8 _res6[3]; + + // UART divider upper register + cyg_uint8 udu; + + // Gap + cyg_uint8 _res7[3]; + + // UART divider lower register + cyg_uint8 udl; + + // Gap + cyg_uint8 _res8[3]; + + // UART autobaud register MSB + cyg_uint8 uabu; + + // Gap + cyg_uint8 _res9[3]; + + // UART autobaud register LSB + cyg_uint8 uabl; + + // Gap + cyg_uint8 _res10[3]; + + // UART transmitter FIFO register + cyg_uint8 utf; + + // Gap + cyg_uint8 _res11[3]; + + // UART receiver FIFO register + cyg_uint8 urf; + + // Gap + cyg_uint8 _res12[3]; + + // UART fractional precision divider register + cyg_uint8 ufpd; + + // Gap + cyg_uint8 _res13[3]; + + // UART input port register + cyg_uint8 uip; + + // Gap + cyg_uint8 _res14[3]; + + // UART output port register 1 + cyg_uint8 uop1; + + // Gap + cyg_uint8 _res15[3]; + + // UART output port register 0 + cyg_uint8 uop0; + + // Gap + cyg_uint8 _res16[3]; + +} __attribute__ ((aligned (4), packed)) mcf5272_uart_t; + +// --------------------------------------------------------------------------- + +// SDRAM controller +typedef struct +{ + + // Gap + cyg_uint8 _res1[2]; + + // SDRAM configuration register + cyg_uint16 sdcr; + + // Gap + cyg_uint8 _res2[2]; + + // SDRAM timing register + cyg_uint16 sdtr; + + // Gap + cyg_uint8 _res3[120]; + +} __attribute__ ((aligned (4), packed)) mcf5272_sim_sdramctrl_t; + +// SDRAM controller related macros + +#define MCF5272_SDRAMC_SDCCR_MCAS_A7 (0x0 << 13) +#define MCF5272_SDRAMC_SDCCR_MCAS_A8 (0x1 << 13) +#define MCF5272_SDRAMC_SDCCR_MCAS_A9 (0x2 << 13) +#define MCF5272_SDRAMC_SDCCR_MCAS_A10 (0x3 << 13) +#define MCF5272_SDRAMC_SDCCR_BALOC_A19 (0x0 << 8) +#define MCF5272_SDRAMC_SDCCR_BALOC_A20 (0x1 << 8) +#define MCF5272_SDRAMC_SDCCR_BALOC_A21 (0x2 << 8) +#define MCF5272_SDRAMC_SDCCR_BALOC_A22 (0x3 << 8) +#define MCF5272_SDRAMC_SDCCR_BALOC_A23 (0x4 << 8) +#define MCF5272_SDRAMC_SDCCR_BALOC_A24 (0x5 << 8) +#define MCF5272_SDRAMC_SDCCR_BALOC_A25 (0x6 << 8) +#define MCF5272_SDRAMC_SDCCR_BALOC_A26 (0x7 << 8) +#define MCF5272_SDRAMC_SDCCR_GSL (0x00000080) +#define MCF5272_SDRAMC_SDCCR_REG (0x00000010) +#define MCF5272_SDRAMC_SDCCR_INV (0x00000008) +#define MCF5272_SDRAMC_SDCCR_SLEEP (0x00000004) +#define MCF5272_SDRAMC_SDCCR_ACT (0x00000002) +#define MCF5272_SDRAMC_SDCCR_INIT (0x00000001) + +#define MCF5272_SDRAMC_SDCTR_RTP_66MHz (0x3D << 10) +#define MCF5272_SDRAMC_SDCTR_RTP_48MHz (0x2B << 10) +#define MCF5272_SDRAMC_SDCTR_RTP_33MHz (0x1D << 10) +#define MCF5272_SDRAMC_SDCTR_RTP_25MHz (0x16 << 10) +#define MCF5272_SDRAMC_SDCTR_RC(x) ((x & 0x3) << 8) +#define MCF5272_SDRAMC_SDCTR_RP(x) ((x & 0x3) << 4) +#define MCF5272_SDRAMC_SDCTR_RCD(x) ((x & 0x3) << 2) +#define MCF5272_SDRAMC_SDCTR_CLT_2 (0x00000001) +#define MCF5272_SDRAMC_SDCTR_CLT_3 (0x00000002) +#define MCF5272_SDRAMC_SDCTR_CLT_4 (0x00000003) + +// --------------------------------------------------------------------------- + +// Timer module +typedef struct +{ + + // Timer mode register + cyg_uint16 tmr; + + // Gap + cyg_uint16 _res1; + + // Timer reference register + cyg_uint16 trr; + + // Gap + cyg_uint16 _res2; + + // Timer capture register + cyg_uint16 tcap; + + // Gap + cyg_uint16 _res3; + + // Timer counter register + cyg_uint16 tcn; + + // Gap + cyg_uint16 _res4; + + // Timer event register + cyg_uint16 ter; + + // Gap + cyg_uint16 _res5; + + // Gap + cyg_uint32 _res6[3]; + +} __attribute__ ((aligned (4), packed)) mcf5272_timer_t; + +// Related macros + +#define MCF5272_TIMER_TMR_PS (0xFF00) +#define MCF5272_TIMER_TMR_PS_BIT (8) +#define MCF5272_TIMER_TMR_CE (0x00C0) +#define MCF5272_TIMER_TMR_CE_BIT (6) +#define MCF5272_TIMER_TMR_OM (0x0020) +#define MCF5272_TIMER_TMR_OM_BIT (5) +#define MCF5272_TIMER_TMR_ORI (0x0010) +#define MCF5272_TIMER_TMR_ORI_BIT (4) +#define MCF5272_TIMER_TMR_FRR (0x0008) +#define MCF5272_TIMER_TMR_FRR_BIT (3) +#define MCF5272_TIMER_TMR_CLK (0x0006) +#define MCF5272_TIMER_TMR_CLK_BIT (1) +#define MCF5272_TIMER_TMR_RST (0x0001) +#define MCF5272_TIMER_TMR_RST_BIT (0) +#define MCF5272_TIMER_TER_REF (0x0002) +#define MCF5272_TIMER_TER_REF_BIT (1) +#define MCF5272_TIMER_TER_CAP (0x0001) +#define MCF5272_TIMER_TER_CAP_BIT (0) + +// --------------------------------------------------------------------------- + +// Watchdog timer +typedef struct +{ + + // Watchdog reset reference register + cyg_uint16 wrrr; + + // Gap + cyg_uint16 _res1; + + // Watchdog interrupt reference register + cyg_uint16 wirr; + + // Gap + cyg_uint16 _res2; + + // Watchdog counter register + cyg_uint16 wcr; + + // Gap + cyg_uint16 _res3; + + // Watchdog event register + cyg_uint16 wer; + + // Gap + cyg_uint16 _res4; + + // Gap + cyg_uint32 _res5[28]; + +} __attribute__ ((aligned (4), packed)) mcf5272_sim_wdtmr_t; + +// --------------------------------------------------------------------------- + +// Fast Ethernet Controller module +typedef struct +{ + + // Ethernet control register + cyg_uint32 ecr; + + // Ethernet interrupt event register + cyg_uint32 eir; + + // Ethernet interrupt mask register + cyg_uint32 eimr; + + // Interrupt vector status register + cyg_uint32 ivsr; + + // Receive descriptor active register + cyg_uint32 rdar; + + // Transmit descriptor active register + cyg_uint32 tdar; + + // Gap + cyg_uint8 _res2[0x0880 - 0x0858]; + + // MII management frame register + cyg_uint32 mmfr; + + // MII speed control register + cyg_uint32 mscr; + + // Gap + cyg_uint8 _res3[0x08cc - 0x0888]; + + // FIFO receive bound register + cyg_uint32 frbr; + + // FIFO receive start register + cyg_uint32 frsr; + + // Gap + cyg_uint8 _res4[0x08e4 - 0x08d4]; + + // Transmit FIFO watermark + cyg_uint32 tfwr; + + // Gap + cyg_uint8 _res5[0x08ec - 0x08e8]; + + // Transmit FIFO start register + cyg_uint32 tfsr; + + // Gap + cyg_uint8 _res6[0x0944 - 0x08f0]; + + // Receive control register + cyg_uint32 rcr; + + // Maximum frame length register + cyg_uint32 mflr; + + // Gap + cyg_uint8 _res7[0x0984 - 0x094c]; + + // Transmit control register + cyg_uint32 tcr; + + // Gap + cyg_uint8 _res8[0x0c00 - 0x0988]; + + // RAM perfect match address low register + cyg_uint32 malr; + + // RAM perfect match address high register + cyg_uint32 maur; + + // Hash table high register + cyg_uint32 htur; + + // Hash table low register + cyg_uint32 htlr; + + // Pointer to receive descriptor ring + cyg_uint32 erdsr; + + // Pointer to transmit descriptor ring + cyg_uint32 etdsr; + + // Maximum receive buffer size + cyg_uint32 emrbr; + + // Gap + cyg_uint8 _res9[0x0c40 - 0x0c1c]; + + // FIFO RAM space + cyg_uint8 efifo[0x0e00 - 0x0c40]; + + // Gap + cyg_uint8 _res10[0x1000 - 0x0e00]; + +} __attribute__ ((aligned (4), packed)) mcf5272_fec_t; + +// --------------------------------------------------------------------------- + +// On-chip peripherals: this structure defines each register's offset from the +// current value of the MBAR register. +typedef struct +{ + + // 0x0000: System Integration Module (SIM) general configuration registers + mcf5272_sim_cfg_t cfg; + + // 0x0020: SIM interrupt controller registers + mcf5272_sim_int_t intc; + + // 0x0040: SIM chip-select modules + mcf5272_sim_cs_t cs[8]; + + // 0x0080: SIM general purpose I/O control registers + mcf5272_sim_gpio_t gpio; + + // 0x00a0: QSPI module + // TODO: a specific data structure is needed + cyg_uint32 qspi[8]; + + // 0x00c0: PWM module + // TODO: a specific data structure is needed + cyg_uint32 pwm[8]; + + // 0x00e0: DMA controller + // TODO: a specific data structure is needed + cyg_uint32 dmac[8]; + + // 0x0100: UART modules + mcf5272_uart_t uart[2]; + + // 0x0180: SIM SDRAM controller + mcf5272_sim_sdramctrl_t sdramc; + + // 0x0200: timer module + mcf5272_timer_t timer[4]; + + // 0x0280: SIM watchdog timer module + mcf5272_sim_wdtmr_t wdtimer; + + // 0x0300: physical layer interface controller + // TODO: a specific data structure is needed + cyg_uint32 plic[336]; + + // 0x0840: ethernet module + mcf5272_fec_t fec; + + // 0x1000: USB module + // TODO: a specific data structure is needed + cyg_uint32 usb[512]; + +} __attribute__ ((aligned (4), packed)) mcf5272_devs_t; + +// --------------------------------------------------------------------------- +// End of mcf5272_devs.h +#endif // CYGONCE_MCF5272_DEVS_H diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/var_arch.h b/packages/hal/coldfire/mcf5272/v2_0/include/var_arch.h new file mode 100644 index 00000000..f6c33783 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/var_arch.h @@ -0,0 +1,65 @@ +#ifndef CYGONCE_HAL_VAR_ARCH_H +#define CYGONCE_HAL_VAR_ARCH_H + +//============================================================================= +// +// var_arch.h +// +// Processor variant specific definitions +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Definitions specific to the MCF5272 processor. +// Usage: Included by "hal_arch.h". Do not use directly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include +#include +#include CYGHWR_MEMORY_LAYOUT_H + + +// Declare the global pointer to the peripheral registers. +// Everyone should use the MCF5272_DEVS macro so it can be easily changed. +#define MCF5272_DEVS ((volatile mcf5272_devs_t *) CYGMEM_REGION_devs) + +// --------------------------------------------------------------------------- +// End of var_arch.h +#endif // CYGONCE_HAL_VAR_ARCH_H diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/var_basetype.h b/packages/hal/coldfire/mcf5272/v2_0/include/var_basetype.h new file mode 100644 index 00000000..15a46979 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/var_basetype.h @@ -0,0 +1,57 @@ +#ifndef CYGONCE_HAL_VAR_BASETYPE_H +#define CYGONCE_HAL_VAR_BASETYPE_H + +//============================================================================= +// +// var_basetype.h +// +// Standard types for this architecture variant +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Type definitions specific to the MCF5272 processor. +// Usage: Included by "basetype.h". Do not use directly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +// Use defaults for this architecture. + +// --------------------------------------------------------------------------- +// End of var_basetype.h +#endif // CYGONCE_HAL_VAR_BASETYPE_H diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/var_cache.h b/packages/hal/coldfire/mcf5272/v2_0/include/var_cache.h new file mode 100644 index 00000000..fcb95f07 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/var_cache.h @@ -0,0 +1,187 @@ +#ifndef CYGONCE_VAR_CACHE_H +#define CYGONCE_VAR_CACHE_H + +//============================================================================= +// +// var_cache.h +// +// Variant HAL cache control API +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Definitions specific to the MCF5272 processor cache. +// Usage: Included via "hal_cache.h". Do not use directly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include +#include + +// We currently just enable the instruction cache on startup. There is +// no data cache. + +// ---------------------------------------------------------------------------- +// Cache dimensions - these vary between the ColdFire sub-models + +// Data cache +#define HAL_DCACHE_SIZE 0 // Size of data cache in bytes + +// Size of a data cache line. Leave this value even if there is no data cache +// on 5272, otherwise some tests won't compile. +#define HAL_DCACHE_LINE_SIZE 16 + +#define HAL_DCACHE_WAYS 1 // Associativity of the cache + +// Instruction cache +#define HAL_ICACHE_SIZE 1024 // Size of cache in bytes +#define HAL_ICACHE_LINE_SIZE 16 // Size of a cache line +#define HAL_ICACHE_WAYS 1 // Associativity of the cache + +#define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS)) +#define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS)) + +// ---------------------------------------------------------------------------- +// Global control of data cache + +// Enable the data cache +#define HAL_DCACHE_ENABLE() + +// Disable the data cache +#define HAL_DCACHE_DISABLE() + +// Invalidate the entire cache +// Note: Any locked lines will not be invalidated. +#define HAL_DCACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_DCACHE_SYNC() + +// Query the state of the data cache +#define HAL_DCACHE_IS_ENABLED(_state_) + +// Set the data cache refill burst size +//#define HAL_DCACHE_BURST_SIZE(_size_) + +// Set the data cache write mode +//#define HAL_DCACHE_WRITE_MODE( _mode_ ) + +//#define HAL_DCACHE_WRITETHRU_MODE 0 +//#define HAL_DCACHE_WRITEBACK_MODE 1 + + +// Load the contents of the given address range into the data cache +// and then lock the cache so that it stays there. +#define HAL_DCACHE_LOCK(_base_, _size_) + +// Undo a previous lock operation +#define HAL_DCACHE_UNLOCK(_base_, _size_) + +// Unlock entire cache +#define HAL_DCACHE_UNLOCK_ALL() + +// ---------------------------------------------------------------------------- +// Data cache line control + +// Allocate cache lines for the given address range without reading its +// contents from memory. +//#define HAL_DCACHE_ALLOCATE( _base_ , _size_ ) + +// Write dirty cache lines to memory and invalidate the cache entries +// for the given address range. +#define HAL_DCACHE_FLUSH( _base_ , _size_ ) + +// Invalidate cache lines in the given range without writing to memory. +#define HAL_DCACHE_INVALIDATE( _base_ , _size_ ) + +// Write dirty cache lines to memory for the given address range. +#define HAL_DCACHE_STORE( _base_ , _size_ ) + +// Preread the given range into the cache with the intention of reading +// from it later. +#define HAL_DCACHE_READ_HINT( _base_ , _size_ ) + +// Preread the given range into the cache with the intention of writing +// to it later. +#define HAL_DCACHE_WRITE_HINT( _base_ , _size_ ) + +// Allocate and zero the cache lines associated with the given range. +#define HAL_DCACHE_ZERO( _base_ , _size_ ) + +// ---------------------------------------------------------------------------- +// Global control of Instruction cache + +// Enable the instruction cache +#define HAL_ICACHE_ENABLE() CYGARC_MOVEC((CYG_WORD32)0x80000102, CYGARC_REG_CACR) + +// Disable the instruction cache +#define HAL_ICACHE_DISABLE() CYGARC_MOVEC((CYG_WORD32)0x00000102, CYGARC_REG_CACR) + +// Invalidate the entire cache +#define HAL_ICACHE_INVALIDATE_ALL() CYGARC_MOVEC((CYG_WORD32)0x81000102, CYGARC_REG_CACR) + +// Synchronize the contents of the cache with memory. +#define HAL_ICACHE_SYNC() CYGARC_MOVEC((CYG_WORD32)0x81000102, CYGARC_REG_CACR) + +// Query the state of the instruction cache +//#define HAL_ICACHE_IS_ENABLED(_state_) + +// Set the instruction cache refill burst size +//#define HAL_ICACHE_BURST_SIZE(_size_) + + +// Load the contents of the given address range into the instruction cache +// and then lock the cache so that it stays there. +#define HAL_ICACHE_LOCK(_base_, _size_) + +// Undo a previous lock operation +#define HAL_ICACHE_UNLOCK(_base_, _size_) + +// Unlock entire cache +#define HAL_ICACHE_UNLOCK_ALL() + +// ---------------------------------------------------------------------------- +// Instruction cache line control + +// Invalidate cache lines in the given range without writing to memory. +//#define HAL_ICACHE_INVALIDATE( _base_ , _size_ ) + +// --------------------------------------------------------------------------- +// End of var_cache.h +#endif // ifndef CYGONCE_VAR_CACHE_H diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/var_intr.h b/packages/hal/coldfire/mcf5272/v2_0/include/var_intr.h new file mode 100644 index 00000000..39b366a1 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/var_intr.h @@ -0,0 +1,253 @@ +#ifndef CYGONCE_HAL_VAR_INTR_H +#define CYGONCE_HAL_VAR_INTR_H + +//========================================================================== +// +// var_intr.h +// +// MCF5272 processor variant interrupt, exception and clock support +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: Wade Jensen +// Date: 2005-25-06 +// Purpose: Provide interrupt, exception and clock definitions specific +// to the MCF5272 processor. +// Usage: Included via "hal_intr.h". Do not use directly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include + +// Include any platform specific interrupt definitions. +#include + +// Include for the device addresses (MCF5272_DEVS). +#include + +// Include for HAL I/O macros +#include + +// -------------------------------------------------------------------------- +// Interrupt controller management + +// This chip has a programmable interrupt vector base which is different +// from the vector base register (VBR). All interrupts from the interrupt +// controller are offset from the programmable interrupt vector register +// (PIVR). However, the only legal value is 64. + +#define HAL_PROG_INT_VEC_BASE 64 + +// Vector numbers defined by the interrupt controller. +// These are all relative to the interrupt vector base number. +#define CYGNUM_HAL_INTERRUPT_USR_SPURINT (0 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_EXTINT1 (1 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_EXTINT2 (2 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_EXTINT3 (3 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_EXTINT4 (4 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_TMR0 (5 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_TMR1 (6 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_TMR2 (7 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_TMR3 (8 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_UART1 (9 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_UART2 (10 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_PLIP (11 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_PLIA (12 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_USB0 (13 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_USB1 (14 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_USB2 (15 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_USB3 (16 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_USB4 (17 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_USB5 (18 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_USB6 (19 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_USB7 (20 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_DMA (21 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_ERX (22 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_ETX (23 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_ENTC (24 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_QSPI (25 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_EXTINT5 (26 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_EXTINT6 (27 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_SWTO (28 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_RES1 (29 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_RES2 (30 + HAL_PROG_INT_VEC_BASE) +#define CYGNUM_HAL_INTERRUPT_RES3 (31 + HAL_PROG_INT_VEC_BASE) + +// ------------------------------------------------------------------------- +// Interrupt and exception vector table definitions. We need to redifine +// CYGNUM_HAL_ISR_MIN because the first usable vector is 65 + +#define CYGNUM_HAL_ISR_RANGE_DEFINED +#define CYGNUM_HAL_ISR_MIN CYGNUM_HAL_INTERRUPT_EXTINT1 +#define CYGNUM_HAL_ISR_MAX CYGNUM_HAL_INTERRUPT_RES3 +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_ISR_MAX - CYGNUM_HAL_ISR_MIN + 1) + +// ------------------------------------------------------------------------- +// Spurious interrupt definition. The MCF5272 returns vector number 64, +// instead of 24, for spurious interrupts + +#define CYGNUM_HAL_SPURIOUS_INTERRUPT CYGNUM_HAL_INTERRUPT_USR_SPURINT + +// -------------------------------------------------------------------------- +// Interrupt controller definitions. + +// Interrupt priority tables +externC volatile cyg_uint8 cyg_hal_ILVL_table[CYGNUM_HAL_ISR_COUNT]; +externC volatile cyg_uint8 cyg_hal_IMASK_table[CYGNUM_HAL_ISR_COUNT]; + +externC void hal_interrupt_set_level(int vector, int level); +externC void hal_interrupt_mask(int vector); +externC void hal_interrupt_unmask(int vector); + +// Mask the interrupt associated with the given vector. +#define HAL_INTERRUPT_MASK( _vector_ ) \ + hal_interrupt_mask(_vector_) + +// Unmask the interrupt associated with the given vector. +#define HAL_INTERRUPT_UNMASK( _vector_ ) \ + hal_interrupt_unmask(_vector_) + +// Set the priority level of an interrupt. +#define HAL_INTERRUPT_SET_LEVEL( _vector_, _prilevel_ ) \ + hal_interrupt_set_level(_vector_, _prilevel_) + +// Acknowledge the interrupt by writing a 1 to the corresponding +// interrupt pending bit. Write 0 to all other interrupt pending bits. Leave +// all priority levels unchanged. Disable all interrupts while we access the +// hardware registers. +#define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) \ +CYG_MACRO_START \ + cyg_uint32 _vec_offset = (_vector_) - HAL_PROG_INT_VEC_BASE - 1; \ + cyg_uint32 _icr = _vec_offset / 8; \ + cyg_uint32 _icr_msk = 0x80000000 >> ((_vec_offset % 8) * 4); \ + cyg_uint32 _icr_oldval; \ + CYG_INTERRUPT_STATE _intr_state; \ + \ + HAL_DISABLE_INTERRUPTS(_intr_state); \ + HAL_READ_UINT32(&MCF5272_DEVS->intc.icr[_icr], _icr_oldval); \ + HAL_WRITE_UINT32(&MCF5272_DEVS->intc.icr[_icr], \ + _icr_oldval & (_icr_msk | 0x77777777)); \ + HAL_RESTORE_INTERRUPTS(_intr_state); \ +CYG_MACRO_END + +// Set/clear the interrupt transition register bit. Disable all +// interrupts while we access the hardware registers. +#define HAL_INTERRUPT_CONFIGURE( _vector_, _leveltriggered_, _up_ ) \ +CYG_MACRO_START \ + if (!(_leveltriggered_)) \ + { \ + cyg_uint32 _vec_offset = (_vector_) - HAL_PROG_INT_VEC_BASE - 1; \ + cyg_uint32 _itr_bit = 0x80000000 >> _vec_offset; \ + cyg_uint32 _pitr_oldval; \ + CYG_INTERRUPT_STATE _intr_state; \ + \ + HAL_DISABLE_INTERRUPTS(_intr_state); \ + HAL_READ_UINT32(&MCF5272_DEVS->intc.pitr, _pitr_oldval); \ + if (_up_) \ + { \ + HAL_WRITE_UINT32(&MCF5272_DEVS->intc.pitr, _pitr_oldval | _itr_bit); \ + } \ + else \ + { \ + HAL_WRITE_UINT32(&MCF5272_DEVS->intc.pitr, _pitr_oldval & (~_itr_bit)); \ + } \ + HAL_RESTORE_INTERRUPTS(_intr_state); \ + } \ +CYG_MACRO_END + +// -------------------------------------------------------------------------- +// Clock control + +// The MCF5272 has 4 timers, numbered 0...3. Define the timer number that we +// want to use for the OS clock. +#define CYGNUM_HAL_RTC_TIMER_NUM (3) + +// The vector used by the real-time clock +#define CYGNUM_HAL_INTERRUPT_RTC (CYGNUM_HAL_INTERRUPT_TMR3) + +// Initialize the timer to generate an interrupt every 10 ms. Use the +// system clock divided by 16 as the source. Using 10 as the prescaler +// gives a 2.4 us counter. When this counter reaches _period_, generate +// an interrupt. +#define HAL_CLOCK_INITIALIZE(_period_) \ +CYG_MACRO_START \ +HAL_WRITE_UINT16(&MCF5272_DEVS->timer[CYGNUM_HAL_RTC_TIMER_NUM].tmr, \ + 0x0000); \ +HAL_WRITE_UINT16(&MCF5272_DEVS->timer[CYGNUM_HAL_RTC_TIMER_NUM].trr, \ + (_period_)); \ +HAL_WRITE_UINT16(&MCF5272_DEVS->timer[CYGNUM_HAL_RTC_TIMER_NUM].tcn, 0); \ +HAL_WRITE_UINT16(&MCF5272_DEVS->timer[CYGNUM_HAL_RTC_TIMER_NUM].ter, 0x0003); \ +HAL_WRITE_UINT16(&MCF5272_DEVS->timer[CYGNUM_HAL_RTC_TIMER_NUM].tmr, \ + (((10)-1) << MCF5272_TIMER_TMR_PS_BIT) | \ + (0 << MCF5272_TIMER_TMR_CE_BIT) | \ + (0 << MCF5272_TIMER_TMR_OM_BIT) | \ + (1 << MCF5272_TIMER_TMR_ORI_BIT) | \ + (0 << MCF5272_TIMER_TMR_FRR_BIT) | \ + (2 << MCF5272_TIMER_TMR_CLK_BIT) | \ + (1 << MCF5272_TIMER_TMR_RST_BIT)); \ +CYG_MACRO_END + +// We must clear the bit in the timer event register before we can get +// another interrupt. +#define HAL_CLOCK_RESET( _vector_, _period_ ) \ +CYG_MACRO_START \ +HAL_WRITE_UINT16(&MCF5272_DEVS->timer[CYGNUM_HAL_RTC_TIMER_NUM].tcn, 0); \ +HAL_WRITE_UINT16(&MCF5272_DEVS->timer[CYGNUM_HAL_RTC_TIMER_NUM].ter, 0x0002); \ +CYG_MACRO_END + +// Read the current counter from the timer +#define HAL_CLOCK_READ( _pvalue_ ) \ +CYG_MACRO_START \ +HAL_READ_UINT16(&MCF5272_DEVS->timer[CYGNUM_HAL_RTC_TIMER_NUM].tcn, \ + *(_pvalue_)); \ +CYG_MACRO_END + +// Measure clock latency +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY +#define HAL_CLOCK_LATENCY( _pvalue_ ) \ +CYG_MACRO_START \ + register cyg_int32 result; \ + HAL_CLOCK_READ( &result ); \ + *_pvalue_ = result - CYGNUM_HAL_RTC_PERIOD; \ +CYG_MACRO_END +#endif + +// --------------------------------------------------------------------------- +// End of var_intr.h +#endif // ifndef CYGONCE_HAL_VAR_INTR_H diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/var_regs.h b/packages/hal/coldfire/mcf5272/v2_0/include/var_regs.h new file mode 100644 index 00000000..9233655d --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/var_regs.h @@ -0,0 +1,66 @@ +#ifndef CYGONCE_HAL_VAR_REGS_H +#define CYGONCE_HAL_VAR_REGS_H + +//========================================================================== +// +// var_regs.h +// +// ColdFire MCF5272 variant CPU definitions +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Provide register definitions for the MCF5272. +// Description: +// Usage: Included via "coldfire_regs.h". Do not use directly. +// +//####DESCRIPTIONEND#### +//========================================================================== + +// CPU space registers definitions + +#define CYGARC_REG_CACR 0x002 +#define CYGARC_REG_ACR0 0x004 +#define CYGARC_REG_ACR1 0x005 +#define CYGARC_REG_VBR 0x801 +#define CYGARC_REG_ROMBAR0 0xC00 +#define CYGARC_REG_RAMBAR0 0xC04 +#define CYGARC_REG_MBAR 0xC0F + +// --------------------------------------------------------------------------- +// End of var_regs.h +#endif // ifdef CYGONCE_HAL_VAR_REGS_H diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/var_startup.h b/packages/hal/coldfire/mcf5272/v2_0/include/var_startup.h new file mode 100644 index 00000000..a680ecb6 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/var_startup.h @@ -0,0 +1,67 @@ +#ifndef CYGONCE_VAR_STARTUP_H +#define CYGONCE_VAR_STARTUP_H + +//============================================================================= +// +// var_startup.h +// +// ColdFire MCF5272 CPU variant startup header +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: ColdFire MCF5272 CPU variant startup header. +// Description: +// Usage: Included via "hal_startup.h". Do not use directly. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include + +// Include the platform-specific startup header. +#include + +// Variant specific hardware initialization routine +externC void var_reset(void) __attribute__ ((section (".boot"))); + +// Variant specific data initialization routine +externC void var_init_data(void) __attribute__ ((section (".boot"))); + +// --------------------------------------------------------------------------- +// End of var_startup.h +#endif // CYGONCE_VAR_STARTUP_H diff --git a/packages/hal/coldfire/mcf5272/v2_0/include/variant.inc b/packages/hal/coldfire/mcf5272/v2_0/include/variant.inc new file mode 100644 index 00000000..c0b810dc --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/include/variant.inc @@ -0,0 +1,99 @@ +#ifndef CYGONCE_HAL_VARIANT_INC +#define CYGONCE_HAL_VARIANT_INC + +|========================================================================== +| +| variant.inc +| +| MCF5272 variant assembler header file +| +|========================================================================== +|###ECOSGPLCOPYRIGHTBEGIN#### +| ------------------------------------------- +| This file is part of eCos, the Embedded Configurable Operating System. +| Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +| Copyright (C) 2006 eCosCentric Ltd. +| +| 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): Enrico Piria +| Contributors: +| Date: 2005-25-06 +| Purpose: MCF5272 variant definitions. +| Description: This file contains the definitions specific to the +| CPU variant, used in the architecture HAL assembler file. +| Usage: Included by "vectors.S". Do not use directly. +| +|####DESCRIPTIONEND#### +|========================================================================== + +#include + + +| ----------------------------------------------------------------------------- +| CPU specific macros. These provide a common assembler interface to +| operations that may have CPU specific implementations on different +| variants of the architecture. + +| CPU initialization macro + .macro hal_cpu_init + + | Invalidate and disable the cache and ACRs. + move.l #0x01000000,%d0 + movec %d0,%cacr + + move.l #0x0,%d0 + movec %d0,%acr0 + movec %d0,%acr1 + .endm + + +| ---------------------------------------------------------------------------- +| This macro retrieves the IPL of the current interrupt from the +| interrupt controller register. This is needed because on inetrrupt entry +| all interrupts are disabled by writing to the status register, and thus +| loosing the current IPL. +| Input: interrupt vector number in d0 +| Output: IPL associated to interrupt in d0 + + .macro hal_variant_retrieve_ipl + + | Subtract minimum interrupt vector number + sub.l #CYGNUM_HAL_ISR_MIN,%d0 + + | Load IPL table address in a0 + lea cyg_hal_ILVL_table,%a0 + + | Retrieve IPL level for current interrupt + move.b (%a0,%d0.l),%d0 + + .endm + +| ---------------------------------------------------------------------------- +| end of variant.inc +#endif // ifndef CYGONCE_HAL_VARIANT_INC diff --git a/packages/hal/coldfire/mcf5272/v2_0/src/hal_diag.c b/packages/hal/coldfire/mcf5272/v2_0/src/hal_diag.c new file mode 100644 index 00000000..e9c9ab0c --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/src/hal_diag.c @@ -0,0 +1,416 @@ +//========================================================================== +// +// hal_diag.c +// +// HAL diagnostic I/O support routines for the MCF5272 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Code to manage the serial ports for diagnostic output. +// Description: +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#include +#include +#include // CYGNUM_HAL_INTERRUPT_UART1 +#include // __comm_control_cmd_t +#include // HAL I/O macros +#include // cyg_hal_is_break +#include // CYG_ISR_HANDLED + +#include + + +typedef struct { + CYG_ADDRWORD base; // [Pointer] to Port base address + unsigned int vector; // UART interrupt vector + CYG_WORD msec_timeout; // Timeout in msec +} channel_data_t; + +static channel_data_t ports[] = { + { + (CYG_ADDRWORD) (&((mcf5272_devs_t *) 0)->uart[0]), + CYGNUM_HAL_INTERRUPT_UART1, + 1000 + }, + + { + (CYG_ADDRWORD) (&((mcf5272_devs_t *) 0)->uart[1]), + CYGNUM_HAL_INTERRUPT_UART2, + 1000 + } +}; + + +static cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data); + +static void +cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 ch); + +static void +cyg_hal_plf_serial_init_channel(channel_data_t *port); + +static cyg_bool +cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch); + +static cyg_bool +cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch); + +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len); +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len); + +static int +cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data); +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...); + + +// ---------------------------------------------------------------------------- +// Early initialization of comm. channels. +void +cyg_hal_plf_comms_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + cyg_uint32 portcnt; + static int initialized = 0; + + if (initialized) + return; + initialized = 1; + +#if (defined(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL) && \ + CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL == 0) || \ + (defined(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL) && \ + CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 0) + + // UART0 pins are multplexed with GPIO port B. Enable them in + // port B control register. + HAL_READ_UINT32(&MCF5272_DEVS->gpio.pbcnt, portcnt); + HAL_WRITE_UINT32(&MCF5272_DEVS->gpio.pbcnt, ((portcnt & + ~(MCF5272_GPIO_PBCNT_URT0_MSK)) | + (MCF5272_GPIO_PBCNT_URT0_EN))); + + // Init channel 0 + cyg_hal_plf_serial_init_channel(&ports[0]); + + // Setup procs in the vector table for channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(0); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[0]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); +#endif + +#if (defined(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL) && \ + CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL == 1) || \ + (defined(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL) && \ + CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 1) + + // UART1 pins need to be enabled in port D control register. + HAL_READ_UINT32(&MCF5272_DEVS->gpio.pdcnt, portcnt); + HAL_WRITE_UINT32(&MCF5272_DEVS->gpio.pdcnt, ((portcnt & + ~(MCF5272_GPIO_PDCNT_URT1_MSK)) | + (MCF5272_GPIO_PDCNT_URT1_EN))); + + // Init channel 1 + cyg_hal_plf_serial_init_channel(&ports[1]); + + // Setup procs in the vector table for channel 0 + CYGACC_CALL_IF_SET_CONSOLE_COMM(1); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[1]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); +#endif + + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + + +void cyg_hal_plf_serial_init_channel(channel_data_t *port) +{ + CYG_WORD16 clk_div; + volatile mcf5272_uart_t *base = + (volatile mcf5272_uart_t *)((char *)MCF5272_DEVS + port->base); + // Initialize variable to prevent compiler warnings + unsigned int baud_rate = 1200; + + +#ifdef CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE + if( (port-&ports[0]) == CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL ) + baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD; +#endif +#ifdef CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE + if( (port-&ports[0]) == CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL ) + baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD; +#endif + + // Before we do anything else, make sure we have enabled RTS in case + // the device we are using relies on hardware flow control. + // Note that this step is our only attempt at hardware flow control. + HAL_WRITE_UINT8(&base->uop1, MCF5272_UART_UOP1_RTS); + + // Initialize UART + + // Reset Transmitter + HAL_WRITE_UINT8(&base->ucr, MCF5272_UART_UCR_RTX); + + // Reset Receiver + HAL_WRITE_UINT8(&base->ucr, MCF5272_UART_UCR_RRX); + + // Reset Mode Register + HAL_WRITE_UINT8(&base->ucr, MCF5272_UART_UCR_RMR); + + HAL_WRITE_UINT8(&base->ucr, MCF5272_UART_UCR_RES); + HAL_WRITE_UINT8(&base->ucr, MCF5272_UART_UCR_RBC); + + // Mode register 1 sets the UART to 8 data bits with no parity, and + // mode register 2 forces 1 stop bit. Also, interrupt generation + // on RxRDY signal is enabled by default. + // Reading or write to the mode register switches it from umr1 to umr2. + // To set it to umr1, we must write a reset mode register command to the + // command register. + HAL_WRITE_UINT8(&base->umr, MCF5272_UART_UMR_8BNP); + HAL_WRITE_UINT8(&base->umr, MCF5272_UART_UMR_1S); + + // Select a prescaled (by 1/16) CLKIN for the clock source + HAL_WRITE_UINT8(&base->usr_ucsr, MCF5272_UART_UCSR_CLKIN); + + // Calculate baud settings + clk_div = (CYG_WORD16) + ((CYGHWR_HAL_SYSTEM_CLOCK_MHZ*1000000)/ + (baud_rate * 32)); + HAL_WRITE_UINT8(&base->udu, clk_div >> 8); + HAL_WRITE_UINT8(&base->udl, clk_div & 0x00ff); + + // Enable the transmitter and receiver + HAL_WRITE_UINT8(&base->ucr, MCF5272_UART_UCR_TXRXEN); + + // Set interrupt priority to highest maskable level + HAL_INTERRUPT_SET_LEVEL(port->vector, 6); +} + + +cyg_uint8 cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8 ch; + + + while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)); + + return ch; +} + + +void cyg_hal_plf_serial_putc(void *__ch_data, cyg_uint8 ch) +{ + channel_data_t *port = (channel_data_t *) __ch_data; + volatile mcf5272_uart_t *base = + (volatile mcf5272_uart_t *)((char *)MCF5272_DEVS + port->base); + cyg_uint8 usr_ucsr, utf; + + + // Loop until the transmit data holding register is empty + do + { + HAL_READ_UINT8(&base->usr_ucsr, usr_ucsr); + } while (!(usr_ucsr & MCF5272_UART_USR_TXRDY)); + + // Write the character to the transmit buffer + HAL_WRITE_UINT8(&base->urb_utb, ch); + + // Loop until the transmit data FIFO and the shift register are empty + do + { + HAL_READ_UINT8(&base->utf, utf); + HAL_READ_UINT8(&base->usr_ucsr, usr_ucsr); + } while ((utf & MCF5272_UART_UTF_TXB) || + (!(usr_ucsr & MCF5272_UART_USR_TXEMP))); +} + +static void cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); +} + + +static void cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, + cyg_uint32 __len) +{ + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); +} + + +static cyg_bool cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) +{ + channel_data_t *port = (channel_data_t *) __ch_data; + volatile mcf5272_uart_t *base = + (volatile mcf5272_uart_t *)((char *)MCF5272_DEVS + port->base); + cyg_uint8 usr_ucsr; + + + // Read status + HAL_READ_UINT8(&base->usr_ucsr, usr_ucsr); + + // Check if a character is present + if (usr_ucsr & MCF5272_UART_USR_RRDY) + { + // Read character + HAL_READ_UINT8(&base->urb_utb, *ch); + return true; + } + + return false; +} + + +static cyg_bool cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + cyg_bool res; + + + delay_count = ((channel_data_t *)__ch_data)->msec_timeout; + + for(;;) { + res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + + CYGACC_CALL_IF_DELAY_US(100); + } + + return res; +} + + +static int cyg_hal_plf_serial_control(void *__ch_data, + __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + channel_data_t *port = (channel_data_t *) __ch_data; + volatile mcf5272_uart_t *base = + (volatile mcf5272_uart_t *)((char *)MCF5272_DEVS + port->base); + int ret = 0; + + + switch (__func) { + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + + HAL_WRITE_UINT8(&base->uisr_uimr, MCF5272_UART_UIMR_FFULL); + HAL_INTERRUPT_UNMASK(port->vector); + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + + HAL_INTERRUPT_MASK(port->vector); + HAL_WRITE_UINT8(&base->uisr_uimr, 0); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = port->vector; + break; + case __COMMCTL_SET_TIMEOUT: + { + va_list ap; + + va_start(ap, __func); + + ret = port->msec_timeout; + port->msec_timeout = va_arg(ap, cyg_uint32); + + va_end(ap); + } + default: + break; + } + + return ret; +} + + +static int cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + channel_data_t *port = (channel_data_t *) __ch_data; + volatile mcf5272_uart_t *base = + (volatile mcf5272_uart_t *)((char *)MCF5272_DEVS + port->base); + char c; + + + // Disable the interrupt temporarily + HAL_WRITE_UINT8(&base->uisr_uimr, 0); + + *__ctrlc = 0; + + // Read character + HAL_READ_UINT8(&base->urb_utb, c); + if( cyg_hal_is_break( &c , 1 ) ) + { + *__ctrlc = 1; + } + + // Re-enable RxRDY interrupt + HAL_WRITE_UINT8(&base->uisr_uimr, MCF5272_UART_UIMR_FFULL); + + return CYG_ISR_HANDLED; +} diff --git a/packages/hal/coldfire/mcf5272/v2_0/src/var_misc.c b/packages/hal/coldfire/mcf5272/v2_0/src/var_misc.c new file mode 100644 index 00000000..a11544f0 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/src/var_misc.c @@ -0,0 +1,161 @@ +//========================================================================== +// +// var_misc.c +// +// Miscellaneous functions specific to the processor variant +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Miscellaneous functions specific to the MCF5272 processor. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include + +#include + +#include +#include +#include + +#include CYGHWR_MEMORY_LAYOUT_H + +// ------------------------------------------------------------------------- +// VSR table + +// For the MCF5272, we can point the VBR directly to the VSR table. +// However, the table must be on a 1 MB boundary. Locate the VSR table where +// the linker tells us to. + +volatile CYG_ADDRESS cyg_hal_vsr_table[CYGNUM_HAL_VSR_COUNT] + __attribute__ ((section (".ramvec"))); + +// ------------------------------------------------------------------------- +// Function prototypes + +static void hal_update_interrupt_controller(int vector); + +// ------------------------------------------------------------------------- +// Interrupt controller management +// +// With the MCF5272 interrupt controller, it is not possible to mask an +// interrupt while retaining its associated priority. Moreover, if we enabled +// the use of interrupts with different priorities, we don't have a means to +// retrieve the priority of the current interrupt, after having raised the +// IPL to the maximum, in the first instruction of the HAL ISR handler. +// So, we use an auxiliary table (cyg_hal_ILVL_table) that records all the +// priorities set for the various interrupts. +// The purpose of the cyg_hal_IMASK_table table is to record wether an +// interrupt is currently masked (0) or not (1). + +volatile cyg_uint8 cyg_hal_ILVL_table[CYGNUM_HAL_ISR_COUNT]; +volatile cyg_uint8 cyg_hal_IMASK_table[CYGNUM_HAL_ISR_COUNT]; + + +// Update priority table and interrupt controller +void hal_interrupt_set_level(int vector, int level) +{ + cyg_uint32 index; + + CYG_ASSERT((0 <= (level) && 7 >= (level)), "Illegal level"); + CYG_ASSERT((CYGNUM_HAL_ISR_MIN <= (vector) + && CYGNUM_HAL_ISR_MAX >= (vector)), "Illegal vector"); + + HAL_TRANSLATE_VECTOR(vector, index); + cyg_hal_ILVL_table[index] = (cyg_uint8) level; + + hal_update_interrupt_controller(vector); +} + +// Update mask table and interrupt controller +void hal_interrupt_mask(int vector) +{ + cyg_uint32 index; + + CYG_ASSERT((CYGNUM_HAL_ISR_MIN <= (vector) + && CYGNUM_HAL_ISR_MAX >= (vector)), "Illegal vector"); + + HAL_TRANSLATE_VECTOR(vector, index); + cyg_hal_IMASK_table[index] = 0; + + hal_update_interrupt_controller(vector); +} + +// Update mask table and interrupt controller +void hal_interrupt_unmask(int vector) +{ + cyg_uint32 index; + + CYG_ASSERT((CYGNUM_HAL_ISR_MIN <= (vector) + && CYGNUM_HAL_ISR_MAX >= (vector)), "Illegal vector"); + + HAL_TRANSLATE_VECTOR(vector, index); + cyg_hal_IMASK_table[index] = 1; + + hal_update_interrupt_controller(vector); +} + + +// Set the priority in the interrupt control register. +// Disable all interrupts while we access the hardware registers. +static void hal_update_interrupt_controller(int vector) +{ + cyg_uint32 index; + cyg_uint8 level; + cyg_uint32 vec_offset; + cyg_uint32 icr, icr_msk_offset, icr_msk, icr_val, icr_oldval; + CYG_INTERRUPT_STATE intr_state; + + HAL_TRANSLATE_VECTOR(vector, index); + level = cyg_hal_IMASK_table[index] ? cyg_hal_ILVL_table[index] : 0; + + vec_offset = (vector) - HAL_PROG_INT_VEC_BASE - 1; + icr = vec_offset / 8; + icr_msk_offset = ((8-1)*4) - (vec_offset % 8) * 4; + icr_msk = 0x0F << (icr_msk_offset); + icr_val = (0x08 | (level & 0x07)) << icr_msk_offset; + + HAL_DISABLE_INTERRUPTS(intr_state); + HAL_READ_UINT32(&MCF5272_DEVS->intc.icr[icr], icr_oldval); + icr_val |= icr_oldval & 0x77777777 & ~icr_msk; + HAL_WRITE_UINT32(&MCF5272_DEVS->intc.icr[icr], icr_val); + HAL_RESTORE_INTERRUPTS(intr_state); +} +// ------------------------------------------------------------------------- +// End of var_misc.c diff --git a/packages/hal/coldfire/mcf5272/v2_0/src/var_startup.c b/packages/hal/coldfire/mcf5272/v2_0/src/var_startup.c new file mode 100644 index 00000000..c739eaf6 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/src/var_startup.c @@ -0,0 +1,75 @@ +//========================================================================== +// +// var_startup.c +// +// Functions for the processor variant startup +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 eCosCentric Ltd. +// +// 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): Enrico Piria +// Contributors: +// Date: 2005-25-06 +// Purpose: Functions needed for MCF5272 startup. +// Description: This module contains code that sets up the variant specific +// hardware and data. All the code must be contained in the +// section called ".boot", in order for the ROMRAM startup +// to work properly. +// +//####DESCRIPTIONEND#### +//======================================================================== + +#include +#include + + +// Variant specific initialization routine. +// This routine must be called with interrupts disabled. +void var_reset(void) +{ + // Nothing to do +} + +// Variant specific data initialization routine +void var_init_data(void) +{ + int i; + + // Initialize priority and mask tables + for(i = 0; i < CYGNUM_HAL_ISR_COUNT; i++) + { + cyg_hal_IMASK_table[i] = 0; + cyg_hal_ILVL_table[i] = 0; + } +} diff --git a/packages/hal/coldfire/mcf5272/v2_0/src/variant.S b/packages/hal/coldfire/mcf5272/v2_0/src/variant.S new file mode 100644 index 00000000..03e91db1 --- /dev/null +++ b/packages/hal/coldfire/mcf5272/v2_0/src/variant.S @@ -0,0 +1,109 @@ +|========================================================================== +| +| variant.S +| +| MCF5272 variant code +| +|========================================================================== +|###ECOSGPLCOPYRIGHTBEGIN#### +| ------------------------------------------- +| This file is part of eCos, the Embedded Configurable Operating System. +| Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +| Copyright (C) 2006 eCosCentric Ltd. +| +| 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): Enrico Piria +| Contributors: +| Date: 2005-25-06 +| Purpose: MCF5272 variant code. +| Description: This file contains the VSR table for the MCF5272, and +| other definitions used by the rest of the ColdFire HAL. +| +|####DESCRIPTIONEND#### +|========================================================================== + +#include +#include + + +| ---------------------------------------------------------------------------- +| ROM vector table + + .section ".romvec","ax" + + .extern cyg_interrupt_stack + .extern cyg_hal_reset_vsr + .extern cyg_hal_default_exception_vsr + .extern cyg_hal_default_spurious_vsr + .extern cyg_hal_default_interrupt_vsr + + .globl rom_vsr_table +rom_vsr_table: + + | 0 - Initial SSP + .long cyg_interrupt_stack + + | 1 - Initial PC + .long cyg_hal_reset_vsr + + | 2-14 - Default exception handlers + .rept 14-2+1 + .long cyg_hal_default_exception_vsr + .endr + + | 15 - Uninitialized interrupt. It should never happen, because + | we configure interrupt controller at startup. + .long cyg_hal_default_spurious_vsr + + | 16-23 - Reserved, treat as exceptions + .rept 23-16+1 + .long cyg_hal_default_exception_vsr + .endr + + | 24 - Spurious interrupt + .long cyg_hal_default_spurious_vsr + + | 25-31 - Autovectored interrupts 1-7. Not used in MCF5272. + .rept 31-25+1 + .long cyg_hal_default_interrupt_vsr + .endr + + | 32-63 - Default exception handlers + .rept 63-32+1 + .long cyg_hal_default_exception_vsr + .endr + + | 64 - User spurious interrupt. The MCF5272 interrupt controller + | returns this vector number instead of vector 24 + .long cyg_hal_default_spurious_vsr + + | 65-255 - User interrupt vectors + .rept 255-65+1 + .long cyg_hal_default_interrupt_vsr + .endr diff --git a/packages/hal/fr30/arch/v2_0/ChangeLog b/packages/hal/fr30/arch/v2_0/ChangeLog new file mode 100644 index 00000000..a6a2a7f8 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/ChangeLog @@ -0,0 +1,58 @@ +2008-07-01 Lars Poeschel + + * src/vectors.S: + * include/arch.inc: + * include/hal_arch.h: Introduced CYGPKG_HAL_FR30_LMA_OFFSET for supporting + remapping a flash chip during initialisation. + +2007-07-09 Lars Poeschel + + * src/context.S: + * src/fr30_stub.c: + * src/hal_misc.c: + * src/vectors.S: + * include/arch.inc: + * include/basetype.h: + * include/fr30.inc: + * include/fr30_stub.h: + * include/hal_arch.h: + * include/hal_cache.h: + * include/hal_intr.h: + * include/hal_io.h: + * cdl/hal_fr30.cdl: Initial fr30 ecos port + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/fr30/arch/v2_0/cdl/hal_fr30.cdl b/packages/hal/fr30/arch/v2_0/cdl/hal_fr30.cdl new file mode 100644 index 00000000..5e7f0bf8 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/cdl/hal_fr30.cdl @@ -0,0 +1,80 @@ +# ==================================================================== +# +# hal_fr30.cdl +# +# fr30 architectural HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2007 eCosCentric Ltd. +## +## 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): larsi +# Original data: +# Contributors: +# Date: 2006-05-28 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_FR30 { + display "fr30 architecture" + parent CYGPKG_HAL + hardware + include_dir cyg/hal + define_header hal_fr30.h + description " + The fr30 architecture HAL package provides generic + support for Fujitsu's fr30/fr50/fr60 processor architecture. + It is also necessary to select a specific target platform HAL + package. If you have a fr50 device, choose the MB91360 variant." + + cdl_interface CYGINT_HAL_FR30_VARIANT { + display "Number of variant implementations in this configuration" + requires 1 == CYGINT_HAL_FR30_VARIANT + } + + compile hal_misc.c context.S vectors.S fr30_stub.c + + make { + /lib/vectors.o : /src/vectors.S + $(CC) -Wp,-MD,vectors.tmp $(INCLUDE_PATH) $(CFLAGS) -c -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail -n +2 vectors.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm vectors.tmp + } +} diff --git a/packages/hal/fr30/arch/v2_0/include/arch.inc b/packages/hal/fr30/arch/v2_0/include/arch.inc new file mode 100644 index 00000000..050df2b0 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/include/arch.inc @@ -0,0 +1,200 @@ +#ifndef CYGONCE_HAL_ARCH_INC +#define CYGONCE_HAL_ARCH_INC +##============================================================================= +## +## arch.inc +## +## fr30 assembler header file +## +##============================================================================= +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2007 eCosCentric Ltd. +## +## 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): larsi +## Contributors: larsi +## Date: 2006-06-20 +## Purpose: Architecture definitions. +## Description: This file contains various definitions and macros that are +## useful for writing assembly code for the fr30 CPU family. +## Usage: +## #include +## ... +## +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#include + +#include + +##----------------------------------------------------------------------------- +## define some .equ's to access c-code #define's from assembler code +.equ CYGNUM_ASM_CALL_IF_TABLE_SIZE, CYGNUM_CALL_IF_TABLE_SIZE + +##----------------------------------------------------------------------------- +## CPU specific macros. These provide a common assembler interface to +## operations that may have CPU specific implementations on different +## variants of the architecture + +#ifndef CYGPKG_HAL_FR30_CPU_INIT_DEFINED + # Initialize CPU + .macro hal_cpu_init + .endm +#endif /* !CYGPKG_HAL_FR30_CPU_INIT_DEFINED */ + +.macro hal_cpu_int_enable + orccr #0x10 +.endm + +.macro hal_cpu_int_disable + andccr #0xef +.endm + + +# Merge the interrupt enable state of the status register in +# \sr with the current sr. + +.macro hal_cpu_int_merge sr + FIXME hal_cpu_int_merge not implemented yet +.endm + +##----------------------------------------------------------------------------- +# Default FR30 interrupt controller macros. Every FR30 has an integrated +# interrupt controller, which we use here. This should be enough if there is +# no special external interrupt controller (which I did not see yet). + +#ifndef CYGPKG_HAL_FR30_INTC_DEFINED + +#ifndef CYGPKG_HAL_FR30_INTC_INIT_DEFINED +# initialize all interrupts to disabled. This is done automatically during +# CPU reset and the macro is not used during ECOS startup. It is not +# supplied here but would be setting all ICRs to 31 (to disable the particular +# interrupt and maybe setting ILM in PS to 0. + .macro hal_intc_init + .endm +#endif + + +# Normally interrupts are decoded by hardware and can not be software decoded, +# so this is empty here. + + .macro hal_intc_decode vnum + .endm + +# Also translation interrupt number <--> vector number is done automatically +# in hardware, so the macros are not supplied here. + +#endif + +#------------------------------------------------------------------------------ +# These defines are for the ISR and VSR tables which are defined in assembler +# code. (currently in variant.S / vectors.S) and have to be the same like in +# hal_intr.h + +#define CYGNUM_HAL_VECTOR_INTRFIRST 15 +#define CYGNUM_HAL_VECTOR_INTRLAST 63 +#define CYGNUM_HAL_VECTOR_NUMINTRS (CYGNUM_HAL_VECTOR_INTRLAST-CYGNUM_HAL_VECTOR_INTRFIRST+1) + +// Common interrupt vectors +#ifndef CYGNUM_HAL_ISR_MIN +#define CYGNUM_HAL_ISR_MIN CYGNUM_HAL_VECTOR_INTRFIRST +#define CYGNUM_HAL_ISR_MAX CYGNUM_HAL_VECTOR_INTRLAST +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_VECTOR_NUMINTRS) +#endif + +// The default size of the VSR table is 256 entries. +#ifndef CYGNUM_HAL_VSR_MIN +#define CYGNUM_HAL_VSR_MIN 0 +#define CYGNUM_HAL_VSR_MAX 255 +#define CYGNUM_HAL_VSR_COUNT 256 +#endif + +#------------------------------------------------------------------------------ +# Register save and restore macros. These expect a pointer to a CPU save state +# area in the register \ptr. The GPR indicated by \reg will be saved into its +# slot in that structure. + +# TODO do this macros if needed, look at MIPS arch.inc for inspiration + + +#------------------------------------------------------------------------------ +# Stack switching macros + + + +#------------------------------------------------------------------------------ +# MEMC macros. + + +#------------------------------------------------------------------------------ +# Cache macros. + +#ifndef CYGPKG_HAL_FR30_CACHE_DEFINED + + .macro hal_cache_init + + .endm + +#endif + +#------------------------------------------------------------------------------ +# Diagnostics macros. + +#------------------------------------------------------------------------------ +# Timer initialization. + +#ifndef CYGPKG_HAL_FR30_TIMER_DEFINED + + .macro hal_timer_init + .endm + +#endif + +#------------------------------------------------------------------------------ +# Difference of the flash memory from the linkers LMA (loadmemoryaddress) after +# the new mapping in (mapping is done in hal_fr30_ram_startup_trampoline). + +#ifndef CYGPKG_HAL_FR30_LMA_OFFSET + +#define CYGPKG_HAL_FR30_LMA_OFFSET 0x0 + +#endif + + +#endif // ifndef CYGONCE_HAL_ARCH_INC +# end of arch.inc diff --git a/packages/hal/fr30/arch/v2_0/include/basetype.h b/packages/hal/fr30/arch/v2_0/include/basetype.h new file mode 100644 index 00000000..9c2d39ad --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/include/basetype.h @@ -0,0 +1,76 @@ +#ifndef CYGONCE_HAL_BASETYPE_H +#define CYGONCE_HAL_BASETYPE_H + +//============================================================================= +// +// basetype.h +// +// Standard types for this architecture. +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): larsi +// Contributors:larsi +// Date: 2006-06-15 +// Purpose: Define architecture base types. +// Usage: Included by "cyg_type.h", do not use directly +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +//----------------------------------------------------------------------------- +// Characterize the architecture + +#define CYG_BYTEORDER CYG_MSBFIRST // BIG endian + +// --------------------------------------------------------------------------- +// Override the alignment definitions from cyg_type.h + +#ifndef CYGARC_ALIGNMENT +#define CYGARC_ALIGNMENT 4 +#endif + +// The corresponding power of two alignment +#ifndef CYGARC_P2ALIGNMENT +#define CYGARC_P2ALIGNMENT 2 +#endif + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_BASETYPE_H +// End of basetype.h diff --git a/packages/hal/fr30/arch/v2_0/include/fr30.inc b/packages/hal/fr30/arch/v2_0/include/fr30.inc new file mode 100644 index 00000000..952c8816 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/include/fr30.inc @@ -0,0 +1,65 @@ +##============================================================================= +## +## fr30.inc +## +## fr30 assembler header file +## +##============================================================================= +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2007 eCosCentric Ltd. +## +## 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): larsi +## Contributors:larsi +## Date: 2006-06-15 +## Purpose: fr30 definitions. +## Description: This file contains various definitions and macros that are +## useful for writing assembly code for the fr30 +## Usage: +## #include +## ... +## +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#------------------------------------------------------------------------------ +# Exception, interrupt and thread context save area layout +# The layout of this structure is also defined in "hal_arch.h", for C +# code. Do not change this without changing that (or vice versa). + +#------------------------------------------------------------------------------ +# end of fr30.inc diff --git a/packages/hal/fr30/arch/v2_0/include/fr30_stub.h b/packages/hal/fr30/arch/v2_0/include/fr30_stub.h new file mode 100644 index 00000000..a3506c26 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/include/fr30_stub.h @@ -0,0 +1,160 @@ +//======================================================================== +// +// fr30_stub.h +// +// FR30-specific definitions for remote debugging via gdb +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): larsi +// Contributors: +// Date: 2007-07-09 +// Purpose: Fujitsu FR30-specific definitions for gdb stubs support +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#ifndef CYGONCE_HAL_FR30_STUB_H +#define CYGONCE_HAL_FR30_STUB_H + +#include +#include + +#ifdef CYGPKG_IO_SERIAL +#include +#endif + +#include + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include // CYG_UNUSED_PARAM, externC + +#define HAL_STUB_PLATFORM_INIT_SERIAL() HAL_DIAG_INIT() + +#define HAL_STUB_PLATFORM_GET_CHAR() \ +((cyg_int8)({ \ + cyg_int8 _ch_; \ + HAL_DIAG_READ_CHAR(_ch_); \ + _ch_; \ +})) + +#define HAL_STUB_PLATFORM_PUT_CHAR(c) HAL_DIAG_WRITE_CHAR((c)) + +#define HAL_STUB_PLATFORM_SET_BAUD_RATE(baud) CYG_UNUSED_PARAM(int,(baud)) + +#define HAL_STUB_PLATFORM_RESET() HAL_DIAG_INIT() + +#define HAL_STUB_PLATFORM_INIT() HAL_DIAG_INIT() + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#define FR30_GENREGS 16 +#define FR30_DEDICATEDREGS 8 +#define FR30_REGSIZE 4 /* bytes */ + +// only NUMREGS and REGSIZE are the really needed macros + +#define NUMREGS (FR30_GENREGS + FR30_DEDICATEDREGS) +#define REGSIZE( _x_ ) FR30_REGSIZE + + +typedef unsigned long target_register_t; + +enum regnames { + R0, R1, R2, R3, R4, R5, R6, R7, + R8, R9, R10, R11, R12, R13, R14, SP, + PC, PS, TBR, RP, SSP, USP, MDH, MDL +}; + +typedef enum regnames regnames_t; + +// Override generic stubs get_register() and use arch-specific version +#define CYGARC_STUB_REGISTER_ACCESS_DEFINED + +#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) +#define HAL_GET_PROFILE_INFO( _thepc_, _thesp_ ) \ + CYG_MACRO_START \ + extern HAL_SavedRegisters *hal_saved_interrupt_state; \ + if ( hal_saved_interrupt_state ) { \ + (_thepc_) = (char *)(hal_saved_interrupt_state->pc); \ + (_thesp_) = (char *)(hal_saved_interrupt_state->sp); \ + } \ + CYG_MACRO_END +#endif + +/* Given a trap value TRAP, return the corresponding signal. */ +externC int __computeSignal (unsigned int trap_number); + +/* Return the trap number corresponding to the last-taken trap. */ +externC int __get_trap_number (void); + +/* Return the currently-saved value corresponding to register REG. */ +externC target_register_t get_register (regnames_t reg); + +/* Store VALUE in the register corresponding to WHICH. */ +externC void put_register (regnames_t which, target_register_t value); + +/* Set the currently-saved pc register value to PC. This also updates NPC + as needed. */ +externC void set_pc (target_register_t pc); + +/* Set things up so that the next user resume will execute one instruction. + This may be done by setting breakpoints or setting a single step flag + in the saved user registers, for example. */ +externC void __single_step (void); + +/* Clear the single-step state. */ +externC void __clear_single_step (void); + +/* If the breakpoint we hit is in the breakpoint() instruction, return a + non-zero value. */ +externC int __is_breakpoint_function (void); + +/* Skip the current instruction. */ +externC void __skipinst (void); + +externC void __install_breakpoints (void); + +externC void __clear_breakpoints (void); + +#endif // ifndef CYGONCE_HAL_FR30_STUB_H + +// EOF fr30_stub.h diff --git a/packages/hal/fr30/arch/v2_0/include/hal_arch.h b/packages/hal/fr30/arch/v2_0/include/hal_arch.h new file mode 100644 index 00000000..e537f269 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/include/hal_arch.h @@ -0,0 +1,363 @@ +#ifndef CYGONCE_HAL_HAL_ARCH_H +#define CYGONCE_HAL_HAL_ARCH_H + +//============================================================================= +// +// hal_arch.h +// +// Architecture specific abstractions +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): larsi +// Contributors: +// Date: 2006-05-28 +// Purpose: Define architecture abstractions +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include + +#include + +#define CYG_HAL_FR30_REG CYG_ADDRWORD + +//----------------------------------------------------------------------------- +// Processor saved states. This structure is also defined in fr30.inc for +// assembly code. Do not change this without changing that (or vice versa). + +typedef struct HAL_SavedRegisters +{ + cyg_uint32 r[16]; // general purpose registers with + // r[13]: virtual accumulator (AC) + // r[14]: frame pointer (FP) + // r[15]: stack pointer (SP) r15 is not saved here! + cyg_uint32 pc; // program counter + cyg_uint32 ps; // program status (with ILM, SCR, CCR) + cyg_uint32 tbr; // table base register (not neccessary, + // as it is used system-wide not per thread) + cyg_uint32 rp; // return pointer + // ssp is used system-wide for EIT processing and does not need to be saved here + // and therefore we don't store usp, because we have it already in r15 + cyg_uint32 ssp; // system stack pointer + cyg_uint32 usp; // user stack pointer + cyg_uint32 mdh; // multiplication and division regs / + cyg_uint32 mdl; // with high and low words + + cyg_uint32 last_trap; // the last taken trap (for GDB stubs) + +} HAL_SavedRegisters; + + +//----------------------------------------------------------------------------- +// Exception handling function. +// This function is defined by the kernel according to this prototype. It is +// invoked from the HAL to deal with any CPU exceptions that the HAL does +// not want to deal with itself. It usually invokes the kernel's exception +// delivery mechanism. FIXME +// declared in src/hal_misc.c +externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data ); + +//----------------------------------------------------------------------------- +// Bit manipulation routines +// declared in src/hal_misc.c + +externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask); +externC cyg_uint32 hal_msbit_index(cyg_uint32 mask); + +#define HAL_LSBIT_INDEX(index, mask) index = hal_lsbit_index(mask); + +#define HAL_MSBIT_INDEX(index, mask) index = hal_msbit_index(mask); + +//----------------------------------------------------------------------------- +// Context Initialization +// Initialize the context of a thread. +// Arguments: +// _sparg_ name of variable containing current sp, will be written with new sp +// _thread_ thread object address, passed as argument to entry point +// _entry_ entry point address. +// _id_ bit pattern used in initializing registers, for debugging. + +#define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ ) \ + CYG_MACRO_START \ + register CYG_WORD _sp_ = ((CYG_WORD)_sparg_); \ + register HAL_SavedRegisters *_regs_; \ + int _i_; \ + _regs_ = (HAL_SavedRegisters *)(((_sp_) - sizeof(HAL_SavedRegisters)) & ~(CYGARC_ALIGNMENT - 1)); \ + for( _i_ = 0; _i_ <= 14; _i_++ ) (_regs_)->r[_i_] = (_id_)|_i_; \ + (_regs_)->r[15] = (CYG_HAL_FR30_REG)(_regs_); /* r15 = USP = top of stack*/ \ + (_regs_)->r[04] = (CYG_HAL_FR30_REG)(_thread_); /* R4 = arg1 = thread ptr */ \ + (_regs_)->pc = (CYG_WORD)(_entry_); /* PC = entry point */ \ + (_regs_)->ps = (CYG_HAL_FR30_REG)0x1f0030; /* 0x000F0030; set flags */ \ + (_regs_)->tbr = (CYG_HAL_FR30_REG)0x10ffc00; /*system standard tbr value*/ \ + (_regs_)->rp = (CYG_HAL_FR30_REG)0x0; /* return pointer = 0x0 */ \ + (_regs_)->ssp = (CYG_HAL_FR30_REG)0x0; /* R4 = arg1 = thread ptr */ \ + (_regs_)->usp = (CYG_HAL_FR30_REG)(_regs_); /* r15 = USP = top of stack*/ \ + (_regs_)->mdh = (CYG_HAL_FR30_REG)0; /* mdh = 0 */ \ + (_regs_)->mdl = (CYG_HAL_FR30_REG)0; /* mdl = 0 */ \ + (_sparg_) = (CYG_ADDRESS)_regs_; \ + CYG_MACRO_END + +//----------------------------------------------------------------------------- +// Context switch macros. +// The arguments are pointers to locations where the stack pointer +// of the current thread is to be stored, and from where the sp of the +// next thread is to be fetched. +// declared in src/hal_misc.c + +externC void hal_thread_switch_context( CYG_ADDRESS to, CYG_ADDRESS from ); +externC void hal_thread_load_context( CYG_ADDRESS to ) + __attribute__ ((noreturn)); + +#define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_) \ + hal_thread_switch_context((CYG_ADDRESS)_tspptr_,(CYG_ADDRESS)_fspptr_); + +#define HAL_THREAD_LOAD_CONTEXT(_tspptr_) \ + hal_thread_load_context( (CYG_ADDRESS)_tspptr_ ); + +//----------------------------------------------------------------------------- +// Execution reorder barrier. +// When optimizing the compiler can reorder code. In multithreaded systems +// where the order of actions is vital, this can sometimes cause problems. +// This macro may be inserted into places where reordering should not happen. + +#define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" ) + +//----------------------------------------------------------------------------- +// Breakpoint support +// HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen +// if executed. +// HAL_BREAKINST is the value of the breakpoint instruction and +// HAL_BREAKINST_SIZE is its size in bytes. + +#define HAL_BREAKPOINT(_label_) \ +CYG_MACRO_START \ + asm volatile (" .globl " #_label_ ";\n" \ + #_label_":\n" \ + "int #0x9\n" \ + ); \ +CYG_MACRO_END + +// 0x9F30 is the INTE instruction (vector no.9, TBR offset 0x3D8) +// 0x1f09 is the INT# 9 instruction (vector no.9, TBR offset 0x3D8) +#define HAL_BREAKINST 0x1f09 +#define HAL_BREAKINST_SIZE 2 +#define HAL_BREAKINST_TYPE unsigned short + +//----------------------------------------------------------------------------- +// Thread register state manipulation for GDB support. + +// Default to a 32 bit register size for GDB register dumps. +#ifndef CYG_HAL_GDB_REG +#define CYG_HAL_GDB_REG CYG_WORD32 +#endif + +// Register layout expected by GDB +typedef struct +{ + CYG_HAL_FR30_REG r[16]; // was: r[0] GPR regs + CYG_HAL_FR30_REG pc; + CYG_HAL_FR30_REG ps; + CYG_HAL_FR30_REG tbr; + CYG_HAL_FR30_REG rp; + CYG_HAL_FR30_REG ssp; + CYG_HAL_FR30_REG usp; + CYG_HAL_FR30_REG mdh; + CYG_HAL_FR30_REG mdl; +} GDB_Registers; + +// Translate a stack pointer as saved by the thread context macros above into +// a pointer to a HAL_SavedRegisters structure declared in src/fr30_stub.h + +#define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ ) \ + (_regs_) = (HAL_SavedRegisters *)(_sp_) + +// Copy a set of registers from a HAL_SavedRegisters structure into a +// GDB ordered array. +#define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ ) \ + CYG_MACRO_START \ + GDB_Registers *_gdb_ = (GDB_Registers *)(_aregval_); \ + int _i_; \ + \ + for( _i_ = 0; _i_ < 16; _i_++ ) { \ + _gdb_->r[_i_] = (_regs_)->r[_i_]; \ + } \ + \ + _gdb_->pc = (_regs_)->pc; \ + _gdb_->ps = (_regs_)->ps; \ + _gdb_->tbr = (_regs_)->tbr; \ + _gdb_->rp = (_regs_)->rp; \ + _gdb_->ssp = (_regs_)->ssp; \ + _gdb_->usp = (_regs_)->usp; \ + _gdb_->mdh = (_regs_)->mdh; \ + _gdb_->mdl = (_regs_)->mdl; \ + CYG_MACRO_END + +// Copy a set of registers from a GDB_Registers structure into a +// HAL_SavedRegisters structure. +#define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ ) \ + CYG_MACRO_START \ + GDB_Registers *_gdb_ = (GDB_Registers *)(_aregval_); \ + int _i_; \ + \ + for( _i_ = 0; _i_ < 16; _i_++ ) \ + (_regs_)->r[_i_] = _gdb_->r[_i_]; \ + \ + (_regs_)->pc = _gdb_->pc; \ + (_regs_)->ps = _gdb_->ps; \ + (_regs_)->tbr = _gdb_->tbr; \ + (_regs_)->rp = _gdb_->rp; \ + (_regs_)->ssp = _gdb_->ssp; \ + (_regs_)->usp = _gdb_->usp; \ + (_regs_)->mdh = _gdb_->mdh; \ + (_regs_)->mdl = _gdb_->mdl; \ + CYG_MACRO_END + + +// ------------------------------------------------------------------------- +// hal_setjmp/hal_longjmp + + +// We must save all of the registers that are preserved across routine +// calls. The assembly code assumes that this structure is defined in the +// following format. Any changes to this structure will result in changes to +// the assembly code!! + +typedef struct { + // registers + cyg_uint32 r8; + cyg_uint32 r9; + cyg_uint32 r10; + cyg_uint32 r11; + cyg_uint32 r14; + + // SP and PC + cyg_uint32 r15; //USP + cyg_uint32 pc; +} hal_jmp_buf_t; + +// This type is used by normal routines to pass the address of the structure +// into our routines without having to explicitly take the address +// of the structure. + +typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)]; + +// Define the generic setjmp and longjmp routines +externC int hal_setjmp(hal_jmp_buf env); +externC void hal_longjmp(hal_jmp_buf env, int val); +//----------------------------------------------------------------------------- +// Idle thread code. +// This macro is called in the idle thread loop, and gives the HAL the +// chance to insert code. Typical idle thread behaviour might be to halt the +// processor. (contains an empty function call at the moment) +// declared in src/hal_misc.c + +externC void hal_idle_thread_action(cyg_uint32 loop_count); + +#define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_) + +//----------------------------------------------------------------------------- +// Minimal and sensible stack sizes: the intention is that applications +// will use these to provide a stack size in the first instance prior to +// proper analysis. Idle thread stack should be this big. +// +// THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES. +// THEY ARE HOWEVER ENOUGH TO START PROGRAMMING. +// YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES! + +// This is not a config option because it should not be adjusted except +// under "enough rope" sort of disclaimers. + +// Stack frame overhead per call. 13 registers (which is a maximum FIXME), +// frame pointer, and return address. We can't guess the local variables so +// just assume that using all of the registers averages out. + +#define CYGNUM_HAL_STACK_FRAME_SIZE ((13 + 1 + 1) * 4) + +// Stack needed for a context switch. +// it should be sizeof(HAL_SavedRegisters) +// All registers + PC + PS + RP + MDH + MDL + +#ifndef CYGNUM_HAL_STACK_CONTEXT_SIZE +#define CYGNUM_HAL_STACK_CONTEXT_SIZE ((16+1+1+1+1+1)*4) +#endif // CYGNUM_HAL_STACK_CONTEXT_SIZE + +// Interrupt + call to ISR, interrupt_end() and the DSR + +#define CYGNUM_HAL_STACK_INTERRUPT_SIZE \ +((CYGNUM_HAL_STACK_CONTEXT_SIZE) + (4*CYGNUM_HAL_STACK_FRAME_SIZE)) + +// We define a minimum stack size as the minimum any thread could ever +// legitimately get away with. We can throw asserts if users ask for less +// than this. Allow enough for four interrupt sources - clock, serial, +// nic, and one other + +#define CYGNUM_HAL_STACK_SIZE_MINIMUM \ +((4*CYGNUM_HAL_STACK_INTERRUPT_SIZE) \ + + (16*CYGNUM_HAL_STACK_FRAME_SIZE)) + +// Now make a reasonable choice for a typical thread size. Pluck figures +// from thin air and say 30 call frames with an average of 16 words of +// automatic variables per call frame + +#define CYGNUM_HAL_STACK_SIZE_TYPICAL \ +(CYGNUM_HAL_STACK_SIZE_MINIMUM + \ + (30 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4)))) + +//-------------------------------------------------------------------------- +// Memory access macros + +#define CYGARC_CACHED_ADDRESS(x) (x) +#define CYGARC_UNCACHED_ADDRESS(x) (x) +#define CYGARC_PHYSICAL_ADDRESS(x) (x) +#define CYGARC_VIRTUAL_ADDRESS(x) (x) + +//-------------------------------------------------------------------------- +// Macros for switching context between two eCos instances (jump from +// code in ROM to code in RAM or vice versa). + +#define CYGARC_HAL_SAVE_GP() +#define CYGARC_HAL_RESTORE_GP() + +//-------------------------------------------------------------------------- +#endif // CYGONCE_HAL_HAL_ARCH_H +// End of hal_arch.h diff --git a/packages/hal/fr30/arch/v2_0/include/hal_cache.h b/packages/hal/fr30/arch/v2_0/include/hal_cache.h new file mode 100644 index 00000000..6fee45de --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/include/hal_cache.h @@ -0,0 +1,127 @@ +#ifndef CYGONCE_HAL_CACHE_H +#define CYGONCE_HAL_CACHE_H + +//============================================================================= +// +// hal_cache.h +// +// HAL cache control API +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): larsi +// Contributors: +// Date: 2007-07-09 +// Purpose: Cache control API +// Description: The macros defined here provide the HAL APIs for handling +// cache control operations. +// Usage: +// #include +// ... +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +//----------------------------------------------------------------------------- +// Cache dimensions + +// Data cache +#define HAL_DCACHE_SIZE 4096 // Size of data cache in bytes +#define HAL_DCACHE_LINE_SIZE 16 // Size of a data cache line +#define HAL_DCACHE_WAYS 2 // Associativity of the cache + +// Instruction cache +#define HAL_ICACHE_SIZE 4096 // Size of cache in bytes +#define HAL_ICACHE_LINE_SIZE 16 // Size of a cache line +#define HAL_ICACHE_WAYS 2 // Associativity of the cache + +#define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS)) +#define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS)) + +//----------------------------------------------------------------------------- +// Global control of data cache + +// Enable the data cache +#define HAL_DCACHE_ENABLE() + +// Disable the data cache +#define HAL_DCACHE_DISABLE() + +// Query the state of the data cache +#define HAL_DCACHE_IS_ENABLED(_state_) \ +CYG_MACRO_START \ +_state_ = 1; \ +CYG_MACRO_END + +// Invalidate the entire cache +#define HAL_DCACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_DCACHE_SYNC() + +//----------------------------------------------------------------------------- +// Global control of Instruction cache + +// Enable the instruction cache +#define HAL_ICACHE_ENABLE() + +// Disable the instruction cache +#define HAL_ICACHE_DISABLE() + +// Query the state of the instruction cache +#define HAL_ICACHE_IS_ENABLED(_state_) \ +CYG_MACRO_START \ +_state_ = 1; \ +CYG_MACRO_END + +// Invalidate the entire cache +#define HAL_ICACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_ICACHE_SYNC() + +//----------------------------------------------------------------------------- +// Instruction cache line control + + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_CACHE_H +// End of hal_cache.h diff --git a/packages/hal/fr30/arch/v2_0/include/hal_intr.h b/packages/hal/fr30/arch/v2_0/include/hal_intr.h new file mode 100644 index 00000000..f9e4d14b --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/include/hal_intr.h @@ -0,0 +1,431 @@ +#ifndef CYGONCE_HAL_HAL_INTR_H +#define CYGONCE_HAL_HAL_INTR_H + +//========================================================================== +// +// hal_intr.h +// +// FR30 HAL Interrupt and clock support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): larsi +// Contributors: larsi +// Date: 2006-06-09 +// Purpose: Define Interrupt support +// Description: The macros defined here provide the HAL APIs for handling +// interrupts and the clock. +// +// Usage: +// #include +// ... +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include + +#include + +#include + +//-------------------------------------------------------------------------- +// Exception vectors. +// Standard exception,interrupt and trap(EIT) vectors supported by FR30 CPUs +// These values are the ones to use for HAL_VSR_GET/SET +// The FR30 vector table lies in reversed in memory, therefore we do +// the 255-x thing here. + +#define CYGNUM_HAL_VECTOR_RESET 0 +// Values from 1 - 8 are system reserved +#define CYGNUM_HAL_VECTOR_MODE_VECTOR 1 +#define CYGNUM_HAL_VECTOR_COPR_NOT_FOUND 7 +#define CYGNUM_HAL_VECTOR_COPR_ERROR 8 +#define CYGNUM_HAL_VECTOR_BREAKPOINT 9 +#define CYGNUM_HAL_VECTOR_INTE CYGNUM_HAL_VECTOR_BREAKPOINT +// Values 10 and 11 are system reserved +#define CYGNUM_HAL_VECTOR_INSTR_BREAK_EXCEPTION 10 +#define CYGNUM_HAL_VECTOR_OPERAND_BREAK_TRAP 11 +#define CYGNUM_HAL_VECTOR_DEBUG 12 +#define CYGNUM_HAL_VECTOR_STEP_TRACE CYGNUM_HAL_VECTOR_DEBUG +// Value 13 is system reserved +#define CYGNUM_HAL_VECTOR_NMI_INTR_TOOL 13 +// Value 14 undefined instruction exception +#define CYGNUM_HAL_VECTOR_OPCODE 14 +// NMI (special non maskable interrupt) +#define CYGNUM_HAL_VECTOR_NMI 15 +// interrupts +// Note that these defines are for C code and have to be the same like those in +// arch.inc for assembler code ! +#define CYGNUM_HAL_VECTOR_INTRFIRST 15 +#define CYGNUM_HAL_VECTOR_INTRLAST 63 +#define CYGNUM_HAL_VECTOR_NUMINTRS (CYGNUM_HAL_VECTOR_INTRLAST-CYGNUM_HAL_VECTOR_INTRFIRST+1) +// Values 64 and 65 are reserved for system +// traps +#define CYGNUM_HAL_VECTOR_TRAPFIRST 80 +#define CYGNUM_HAL_VECTOR_SYSTEM_CALL CYGNUM_HAL_VECTOR_TRAPFIRST +#define CYGNUM_HAL_VECTOR_TRAPLAST 255 +#define CYGNUM_HAL_VECTOR_NUMTRAPS (CYGNUM_HAL_VECTOR_TRAPLAST-CYGNUM_HAL_VECTOR_TRAPFIRST+1) + +// The default size of the VSR table is 256 entries. +#ifndef CYGNUM_HAL_VSR_MIN +#define CYGNUM_HAL_VSR_MIN 0 +#define CYGNUM_HAL_VSR_MAX 255 +#define CYGNUM_HAL_VSR_COUNT 256 +#endif + +// For ecos fr30 interrupts are interrupts and fr30 exceptions and +// fr30 traps are both exceptions + +// Common interrupt vectors +#ifndef CYGNUM_HAL_ISR_MIN +#define CYGNUM_HAL_ISR_MIN CYGNUM_HAL_VECTOR_INTRFIRST +#define CYGNUM_HAL_ISR_MAX CYGNUM_HAL_VECTOR_INTRLAST +#define CYGNUM_HAL_ISR_COUNT (CYGNUM_HAL_VECTOR_NUMINTRS) +#endif +// Common exception vectors. (so these are fr30 exceptions and traps) +#define CYGNUM_HAL_EXCEPTION_RESET CYGNUM_HAL_VECTOR_RESET +#define CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL CYGNUM_HAL_VECTOR_COPR_NOT_FOUND +#define CYGNUM_HAL_EXCEPTION_FPU CYGNUM_HAL_VECTOR_COPR_ERROR +#define CYGNUM_HAL_EXCEPTION_TRAP CYGNUM_HAL_VECTOR_INTE +// #define CYGNUM_HAL_EXCEPTION_INTERRUPT CYGNUM_HAL_VECTOR_BREAKPOINT +// #define CYGNUM_HAL_EXCEPTION_TRAP CYGNUM_HAL_VECTOR_STEP_TRACE +#define CYGNUM_HAL_EXCEPTION_SINGLE_STEP CYGNUM_HAL_VECTOR_STEP_TRACE +#define CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION CYGNUM_HAL_VECTOR_OPCODE + +// common interrupt vectors +// I am sure more defines can be moved from variant to architecture HAL here +#define CYGNUM_HAL_INTERRUPT_NMI 15 + +// here we define exceptions and traps as the fr30 docs termini +#define CYGNUM_HAL_EXCEPTION_FR30_MIN 0 +#define CYGNUM_HAL_EXCEPTION_FR30_MAX 14 +#define CYGNUM_HAL_EXCEPTION_FR30_COUNT (CYGNUM_HAL_EXCEPTION_FR30_MAX - CYGNUM_HAL_EXCEPTION_FR30_MIN + 1) + +#define CYGNUM_HAL_TRAP_FR30_MIN 80 +#define CYGNUM_HAL_TRAP_FR30_MAX 255 +#define CYGNUM_HAL_TRAP_FR30_COUNT (CYGNUM_HAL_TRAP_FR30_MAX - CYGNUM_HAL_TRAP_FR30_MIN + 1) + +// here we define the ecos ones +// nicht mehr aktuell:(calculated from fr30 ones) FIXME maybe have to +// change to correspons to durchgaengig vector numbers. In this table +// exceptions are unterbrochen from interrupts +#define CYGNUM_HAL_EXCEPTION_MIN 0 +#define CYGNUM_HAL_EXCEPTION_MAX 255 +#define CYGNUM_HAL_EXCEPTION_COUNT \ + ( CYGNUM_HAL_EXCEPTION_MAX - CYGNUM_HAL_EXCEPTION_MIN + 1 ) + +//-------------------------------------------------------------------------- +// Interrupt levels +// Lower numbers mean stronger interrupt levels +// values 0 - 14 are system reserved and can not be set by a program +// (setting them would add 16 to the value automatically) +// value 15 is for NMI +// value 31 disables the interrupt + +#ifndef CYGHWR_HAL_INTERRUPT_LEVELS_DEFINED + +#define CYGNUM_HAL_INTERRUPT_LEVEL_0 16 +#define CYGNUM_HAL_INTERRUPT_LEVEL_1 17 +#define CYGNUM_HAL_INTERRUPT_LEVEL_2 18 +#define CYGNUM_HAL_INTERRUPT_LEVEL_3 19 +#define CYGNUM_HAL_INTERRUPT_LEVEL_4 20 +#define CYGNUM_HAL_INTERRUPT_LEVEL_5 21 +#define CYGNUM_HAL_INTERRUPT_LEVEL_6 22 +#define CYGNUM_HAL_INTERRUPT_LEVEL_7 23 +#define CYGNUM_HAL_INTERRUPT_LEVEL_8 24 +#define CYGNUM_HAL_INTERRUPT_LEVEL_9 25 +#define CYGNUM_HAL_INTERRUPT_LEVEL_10 26 +#define CYGNUM_HAL_INTERRUPT_LEVEL_11 27 +#define CYGNUM_HAL_INTERRUPT_LEVEL_12 28 +#define CYGNUM_HAL_INTERRUPT_LEVEL_13 29 +#define CYGNUM_HAL_INTERRUPT_LEVEL_14 30 +#define CYGNUM_HAL_INTERRUPT_LEVEL_15 31 +#define CYGNUM_HAL_INTERRUPT_LEVEL_DISABLE \ + CYGNUM_HAL_INTERRUPT_LEVEL_15 + +#define CYGHWR_HAL_INTERRUPT_LEVELS_DEFINED + +#endif + +//-------------------------------------------------------------------------- +// Static data used by HAL + +// ISR tables +externC volatile CYG_ADDRESS hal_interrupt_handlers[CYGNUM_HAL_ISR_COUNT]; +externC volatile CYG_ADDRWORD hal_interrupt_data[CYGNUM_HAL_ISR_COUNT]; +externC volatile CYG_ADDRESS hal_interrupt_objects[CYGNUM_HAL_ISR_COUNT]; + +// VSR table +externC volatile CYG_ADDRESS hal_vsr_table[CYGNUM_HAL_VSR_COUNT]; + +//-------------------------------------------------------------------------- +// Interrupt state storage + +typedef cyg_uint32 CYG_INTERRUPT_STATE; + +//--------------------------------------------------------------------------- +// Default ISR +externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); + +#define HAL_DEFAULT_ISR hal_default_isr + +//-------------------------------------------------------------------------- +// CPU interrupt enable/disable macros + +#define HAL_ENABLE_INTERRUPTS() \ +CYG_MACRO_START \ + asm volatile ("orccr #0x10;\n") ; \ +CYG_MACRO_END + +#define HAL_DISABLE_INTERRUPTS(_old_) \ +CYG_MACRO_START \ + register int x ; \ + asm volatile ("st r1, @-r15 ;\n" \ + "MOV PS, r1 ;\n" \ + "LDI:8 #0x10,%0 ;\n" \ + "AND r1, %0 ;\n" \ + "LSR #1,%0 ;\n" \ + "ld @r15+, r1 ;\n" \ + "ANDCCR #0xEF \n" \ + : "=r" (x) \ + ); \ + (_old_) = (x); \ +CYG_MACRO_END + +#define HAL_RESTORE_INTERRUPTS(_old_) \ +CYG_MACRO_START \ + register int x = _old_; \ + asm volatile ( "CMP #8, %0 ;\n" \ + "BEQ 0f ;\n" \ + "ANDCCR #0xEF ;\n" \ + "BRA 1f;\n" \ + "0:\n" \ + "ORCCR #0x10 ;\n" \ + "1:\n" \ + : /* No outputs */ \ + : "r"(x) \ + ); \ +CYG_MACRO_END + +// 5th bit (0x10 / #10H) is interrupt flag +// it is shifted right to be able to work with 4 bit immediate in the other macros +#define HAL_QUERY_INTERRUPTS(_old_) \ +CYG_MACRO_START \ + register int x ; \ + asm volatile ("MOV PS,__tmp_reg__ ;\n" \ + "LDI:8 #10H,%0 ;\n" \ + "AND __tmp_reg__,%0 ;\n" \ + "LSR #1,%0 ;\n" \ + : "=r" (x) \ + ); \ + (_old_) = (x); \ +CYG_MACRO_END + +//--------------------------------------------------------------------------- +// Interrupt and VSR attachment macros + + +#define HAL_INTERRUPT_IN_USE( _vector_, _state_) \ + CYG_MACRO_START \ + cyg_uint32 _index_; \ + HAL_TRANSLATE_VECTOR ((_vector_), _index_); \ + \ + if (hal_interrupt_handlers[_index_] \ + ==(CYG_ADDRESS)HAL_DEFAULT_ISR) \ + (_state_) = 0; \ + else \ + (_state_) = 1; \ + CYG_MACRO_END + +#ifndef HAL_INTERRUPT_ATTACH +externC void __default_interrupt_vsr(void); +#define HAL_INTERRUPT_ATTACH( _vector_, _isr_, _data_, _object_ ) \ + CYG_MACRO_START \ + cyg_uint32 _index_; \ + HAL_TRANSLATE_VECTOR((_vector_), _index_); \ + \ + HAL_VSR_SET( _vector_, &__default_interrupt_vsr , NULL); \ + if( hal_interrupt_handlers[_index_] == (CYG_ADDRESS)HAL_DEFAULT_ISR ) \ + { \ + hal_interrupt_handlers[_index_] = (CYG_ADDRESS)(_isr_); \ + hal_interrupt_data[_index_] = (CYG_ADDRWORD)(_data_); \ + hal_interrupt_objects[_index_] = (CYG_ADDRESS)(_object_); \ + } \ + CYG_MACRO_END +#endif /* HAL_INTERRUPT_ATTACH */ + +#define HAL_INTERRUPT_DETACH( _vector_, _isr_ ) \ + CYG_MACRO_START \ + cyg_uint32 _index_; \ + HAL_TRANSLATE_VECTOR((_vector_), _index_); \ + \ + if (hal_interrupt_handlers[_index_] \ + == (CYG_ADDRESS)(_isr_)) \ + { \ + hal_interrupt_handlers[_index_] = \ + (CYG_ADDRESS)HAL_DEFAULT_ISR; \ + hal_interrupt_data[_index_] = 0; \ + hal_interrupt_objects[_index_] = 0; \ + } \ + CYG_MACRO_END + +#define HAL_VSR_GET( _vector_, _pvsr_ ) \ + *((CYG_ADDRESS *)(_pvsr_)) = hal_vsr_table[(_vector_)]; + + +#define HAL_VSR_SET( _vector_, _vsr_, _poldvsr_ ) \ + CYG_MACRO_START \ + CYG_ADDRESS *__poldvsr = (CYG_ADDRESS *)(_poldvsr_); \ + if( __poldvsr != NULL ) \ + *__poldvsr = hal_vsr_table[(_vector_)]; \ + hal_vsr_table[(_vector_)] = (CYG_ADDRESS)(_vsr_); \ + CYG_MACRO_END + +// This is an ugly name, but what it means is: grab the VSR back to eCos +// internal handling, or if you like, the default handler. But if +// cooperating with GDB and CygMon, the default behaviour is to pass most +// exceptions to CygMon. This macro undoes that so that eCos handles the +// exception. So use it with care. + +externC void __default_exception_vsr(void); +externC void __default_interrupt_vsr(void); + +#define HAL_VSR_SET_TO_ECOS_HANDLER( _vector_, _poldvsr_ ) \ +CYG_MACRO_START \ + HAL_VSR_SET( _vector_, _vector_ > CYGNUM_HAL_EXCEPTION_MAX \ + ? (CYG_ADDRESS)__default_interrupt_vsr \ + : (CYG_ADDRESS)__default_exception_vsr, \ + _poldvsr_ ); \ +CYG_MACRO_END + +//-------------------------------------------------------------------------- +// Vector translation. +// For chained interrupts we only have a single vector though which all +// are passed. For unchained interrupts we have a vector per interrupt. + +#ifndef HAL_TRANSLATE_VECTOR + +#if defined(CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN) + +#define HAL_TRANSLATE_VECTOR(_vector_,_index_) (_index_) = 0 + +#else + +#define HAL_TRANSLATE_VECTOR(_vector_,_index_) (_index_) = (_vector_) + +#endif + +#endif + +//-------------------------------------------------------------------------- +// Clock control. +// This code uses the 16 bit reload timer 1. The defines are used to specify +// the IO adress of the registers, that are different in FR30 variants. + +#ifndef CYGHWR_HAL_CLOCK_CONTROL_DEFINED + +extern CYG_WORD32 cyg_hal_clock_period; + +#define CYGHWR_HAL_CLOCK_PERIOD_DEFINED + +#define HAL_CLOCK_INITIALIZE( _period_ ) \ +CYG_MACRO_START \ + HAL_WRITE_UINT16( CYG_HAL_FR30_RTC_TMRLR , _period_); \ + HAL_WRITE_UINT16( CYG_HAL_FR30_RTC_TMCSR , 0x081b); \ + cyg_hal_clock_period = _period_; \ +CYG_MACRO_END + +// This clears the interrupt request for reload timer 1 (RTC) +#define HAL_CLOCK_RESET( _vector_, _period_ ) \ +CYG_MACRO_START \ +asm volatile("ldi:8 #0x57, r0;\n" \ + "bandl #0xb, @r0;\n" \ + : : :"r0"); \ +CYG_MACRO_END + +#define HAL_CLOCK_READ( _pvalue_ ) \ +CYG_MACRO_START \ + CYG_FAIL("clock_read"); \ + register CYG_WORD32 result; \ + HAL_READ_UINT16( CYG_HAL_FR30_RTC_TMR, result); \ + *(_pvalue_) = cyg_hal_clock_period - result; \ +CYG_MACRO_END + +#define CYGHWR_HAL_CLOCK_CONTROL_DEFINED + +#endif + + +#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && \ + !defined(HAL_CLOCK_LATENCY) +#define HAL_CLOCK_LATENCY( _pvalue_ ) \ +CYG_MACRO_START \ + register CYG_WORD32 _cval_; \ + HAL_CLOCK_READ(&_cval_); \ + *(_pvalue_) = _cval_ - cyg_hal_clock_period; \ +CYG_MACRO_END +#endif + +//---------------------------------------------------------------------------- +// Reset +// this clears BIT4 in STCR(0x481), which should issue a reset + +#define HAL_PLATFORM_RESET() \ + asm volatile ( \ + "ldi:20 #0x481, r0;\n" \ + "bandh #1, @r0;\n" \ + : : :"r0"); + +externC void _start(void); +#define HAL_PLATFORM_RESET_ENTRY (&_start) + +//-------------------------------------------------------------------------- +// Microsecond delay +// This uses reload timer 2, because timer 0 and 1 can cause DMA transfers. +// Timer 2 is only used for delay service. We maybe support it out of the +// scheduler clock in the future. + +externC void hal_delay_us(cyg_int32 usecs); +#define HAL_DELAY_US(_millis_) hal_delay_us(_millis_); + +//--------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_HAL_INTR_H +// End of hal_intr.h diff --git a/packages/hal/fr30/arch/v2_0/include/hal_io.h b/packages/hal/fr30/arch/v2_0/include/hal_io.h new file mode 100644 index 00000000..c8480735 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/include/hal_io.h @@ -0,0 +1,160 @@ +#ifndef CYGONCE_HAL_HAL_IO_H +#define CYGONCE_HAL_HAL_IO_H + +//============================================================================= +// +// hal_io.h +// +// HAL device IO register support. +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): larsi +// Contributors: +// Date: 2007-07-09 +// Purpose: Define IO register support +// Description: The macros defined here provide the HAL APIs for handling +// device IO control registers. +// +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +#include + +#include + +//----------------------------------------------------------------------------- +// IO Register address. +// This type is for recording the address of an IO register. + +typedef volatile CYG_ADDRWORD HAL_IO_REGISTER; + +//----------------------------------------------------------------------------- +// HAL IO macros. +#ifndef HAL_IO_MACROS_DEFINED + +//----------------------------------------------------------------------------- +// BYTE Register access. +// Individual and vectorized access to 8 bit registers. + +#define HAL_READ_UINT8( _register_, _value_ ) \ + asm volatile ("ldub @%1, %0": "=r" (_value_): "r" (_register_)); +// ((_value_) = *((volatile CYG_BYTE *)(_register_))) + +#define HAL_WRITE_UINT8( _register_, _value_ ) \ + asm volatile ("stb %0, @%1": : "r" (_value_), "r" (_register_)); +// (*((volatile CYG_BYTE *)(_register_)) = (_value_)) + +#define HAL_READ_UINT8_VECTOR( _register_, _buf_, _count_, _step_ ) \ +{ \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) \ + (_buf_)[_i_] = ((volatile CYG_BYTE *)(_register_))[_j_]; \ +} + +#define HAL_WRITE_UINT8_VECTOR( _register_, _buf_, _count_, _step_ ) \ +{ \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) \ + ((volatile CYG_BYTE *)(_register_))[_j_] = (_buf_)[_i_]; \ +} + +//----------------------------------------------------------------------------- +// 16 bit access. +// Individual and vectorized access to 16 bit registers. + +#define HAL_READ_UINT16( _register_, _value_ ) \ + asm volatile ("lduh @%1, %0": "=r" (_value_): "r" (_register_)); + +#define HAL_WRITE_UINT16( _register_, _value_ ) \ + asm volatile ("sth %0, @%1": : "r" (_value_), "r" (_register_)); + +#define HAL_READ_UINT16_VECTOR( _register_, _buf_, _count_, _step_ ) \ +{ \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) \ + (_buf_)[_i_] = ((volatile CYG_WORD16 *)(_register_))[_j_]; \ +} + +#define HAL_WRITE_UINT16_VECTOR( _register_, _buf_, _count_, _step_ ) \ +{ \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) \ + ((volatile CYG_WORD16 *)(_register_))[_j_] = (_buf_)[_i_]; \ +} + +//----------------------------------------------------------------------------- +// 32 bit access. +// Individual and vectorized access to 32 bit registers. + +#define HAL_READ_UINT32( _register_, _value_ ) \ + asm volatile ("ld @%1, %0": "=r" (_value_): "r" (_register_)); + +#define HAL_WRITE_UINT32( _register_, _value_ ) \ + asm volatile ("st %0, @%1": : "r" (_value_), "r" (_register_)); + +#define HAL_READ_UINT32_VECTOR( _register_, _buf_, _count_, _step_ ) \ +{ \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) \ + (_buf_)[_i_] = ((volatile CYG_WORD32 *)(_register_))[_j_]; \ +} + +#define HAL_WRITE_UINT32_VECTOR( _register_, _buf_, _count_, _step_ ) \ +{ \ + cyg_count32 _i_,_j_; \ + for( _i_ = 0, _j_ = 0; _i_ < (_count_); _i_++, _j_ += (_step_)) \ + ((volatile CYG_WORD32 *)(_register_))[_j_] = (_buf_)[_i_]; \ +} + +#define HAL_IO_MACROS_DEFINED + +#endif + + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_HAL_IO_H +// End of hal_io.h diff --git a/packages/hal/fr30/arch/v2_0/src/context.S b/packages/hal/fr30/arch/v2_0/src/context.S new file mode 100644 index 00000000..2810bc8d --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/src/context.S @@ -0,0 +1,201 @@ +##============================================================================= +## +## context.S +## +## FR30 context switch and longjmp setjmp code +## +##============================================================================= +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2007 eCosCentric Ltd. +## +## 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): larsi +## Contributors:larsi +## Date: 2006-06-03 +## Purpose: fr30 context switch code +## Description: This file contains implementations of the thread context +## switch routines. It also contains the longjmp() and setjmp() +## routines. +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#include + +#include + +#include + +#------------------------------------------------------------------------------ +# function declaration macro + +#define FUNC_START(name) \ + .globl name; \ +name: + +#------------------------------------------------------------------------------ +# hal_thread_switch_context +# Switch thread contexts +# +# a timer interrupt should have caused this function to be called +# so interrupts are forbidden and we are in SSP mode (S flag=1) +# +# R4 and R5 contain our arguments. +# R5 is _fspptr_ (old USP), R4 is _tspptr_ (new USP). +# @(SSP) has the return address of the call to this function. +# In @(SSP,4) the PS and in @(SSP,8) the PC are saved by hardware. +# Before we RETI, we have to switch S flag in CCR to 0 +# to use SSP for returning. Interrupts have to be +# reenabled before returning, but this is done by restoring PS. + + + .globl hal_thread_switch_context +hal_thread_switch_context: + +# at first switch to USP (set bit 5 in CCR in PS) + st r0, @-r15 ; push last_trap, cannot guarantee that it is + ; the right value, but that should not matter + ; as it is only for GDB + st mdl, @-r15 + st mdh, @-r15 + + st r0, @-r15 ; store usp + + st r0, @-r15 ; store ssp + st rp, @-r15 + st tbr, @-r15 + st ps, @-r15 + st rp, @-r15 ; rp is our new pc when load_context executes + + st r15, @-r15 ; store original r15 here + + stm1 (r8, r9, r10, r11, r12, r13, r14) + stm0 (r0, r1, r2, r3 , r4 , r5 , r6 , r7) + +# we should be finished saving context here + + st r15, @r5 ; store pointer to saved context + +#------------------------------------------------------------------------------ +# hal_thread_load_context +# Load thread context +.globl hal_thread_load_context +hal_thread_load_context: + + ld @r4, r15 + + ldm0 (r0, r1, r2, r3, r4, r5, r6, r7) + ldm1 (r8, r9, r10, r11, r12, r13, r14) + ld @r15+, mdl + ld @r15+, rp + ld @r15+, ps + ld @r15+, tbr +# TODO addsp to skip stack positions + ld @r15+, mdl + ld @r15+, mdl + ld @r15+, mdl + ld @r15+, mdh + ld @r15+, mdl + addsp 4 + ret + +#------------------------------------------------------------------------------ +# HAL longjmp, setjmp implementations +# hal_setjmp saves only to callee save registers r8, r9, r10, r11, r14, r15 +# into buffer supplied in r4 +# Note: These definitions are repeated in hal_arch.h. If changes are required +# remember to update both sets. +# setjmp/longjmp for FR30. The jmpbuf looks like this: +# +# Register jmpbuf offset +# r8 0x00 +# r9 0x04 +# r10 0x08 +# r11 0x0c +# r14 (FP) 0x10 +# r15 (SP) 0x14 +# pc (rp) 0x18 + + .macro save reg + st \reg, @r4 + addn #4, r4 + .endm + + .macro restore reg + ld @r4, \reg + addn #4, r4 + .endm + + + .text + .global hal_setjmp + .type hal_setjmp,@function +hal_setjmp: + save r8 + save r9 + save r10 + save r11 + save r14 + save r15 + mov rp, r5 + st r5, @r4 + +# Return 0 to caller. + ldi:8 #0, r4 + ret + + .global hal_longjmp +hal_longjmp: + restore r8 + restore r9 + restore r10 + restore r11 + restore r14 + restore r15 + ld @r4, r4 + mov r4, rp + +# If caller attempted to return 0, return 1 instead. + + mov r5, r4 + or r4, r4 + bne 1f + ldi:8 #1, r4 +1: + ret + +#----------------------------------------------------------------------------- +# End of context.S diff --git a/packages/hal/fr30/arch/v2_0/src/fr30_stub.c b/packages/hal/fr30/arch/v2_0/src/fr30_stub.c new file mode 100644 index 00000000..4de53c53 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/src/fr30_stub.c @@ -0,0 +1,210 @@ +//======================================================================== +// +// fr30_stub.c +// +// Fujitsu FR30-specific code for remote debugging via gdb +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): larsi +// Contributors: +// Date: 2007-07-09 +// Purpose: +// Description: Helper functions for gdb stub for FR30 processors +// Usage: +// +//####DESCRIPTIONEND#### +// +//======================================================================== + +#include + +#include + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS + +#include +#include +#include +#include // assertion macros + +#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT +#include // dbg_currthread_id +#endif + +/* Given a trap value TRAP, return the corresponding signal. */ + +int __computeSignal (unsigned int trap_number) +{ + switch (trap_number) + { + + case CYGNUM_HAL_VECTOR_COPR_NOT_FOUND: + case CYGNUM_HAL_VECTOR_COPR_ERROR: + return SIGFPE; + + // step trace TRAP + case CYGNUM_HAL_VECTOR_DEBUG: + // INTE + case CYGNUM_HAL_VECTOR_BREAKPOINT: + return SIGTRAP; + /* System call instruction executed */ + case CYGNUM_HAL_VECTOR_SYSTEM_CALL ... CYGNUM_HAL_VECTOR_TRAPLAST: + return SIGSYS; + /* External interrupt */ + case CYGNUM_HAL_INTERRUPT_0 ... CYGNUM_HAL_INTERRUPT_DELAYED_IRQ: + return SIGINT; + // Illegal or reserved instruction + case CYGNUM_HAL_VECTOR_OPCODE: + return SIGILL; + + // Marks port does think to return SIGTRAP as default. + default: + return SIGTERM; + } +} + +/* Return the trap number corresponding to the last-taken trap. */ + +int __get_trap_number (void) +{ + // The vector is not not part of the GDB register set so get it + // directly from the save context. + return _hal_registers->last_trap; +} + +/* Set the currently-saved pc register value to PC. This also updates NPC + as needed. */ + +void set_pc (target_register_t pc) +{ + put_register (PC, pc); +} + +/*---------------------------------------------------------------------- + * Single-step support + */ + +/* Set things up so that the next user resume will execute one instruction. + This may be done by setting breakpoints or setting a single step flag + in the saved user registers, for example. */ + +void __single_step (void) +{ + /* Trying to use processors single stepping. + This means to set T flag in PS register. */ + put_register (PS, get_register (PS) | 0x100); +} + +/* Clear the single-step state. */ +void __clear_single_step (void) +{ + put_register (PS, get_register (PS) & ~0x100); +} + +void __install_breakpoints () +{ + /* if (instrBuffer.targetAddr != NULL) + { + instrBuffer.savedInstr = *instrBuffer.targetAddr; + *instrBuffer.targetAddr = __break_opcode (); + } */ + + /* Install the breakpoints in the breakpoint list */ + __install_breakpoint_list(); + + // No need to flush caches here; Generic stub code will handle this. +} + +void __clear_breakpoints (void) +{ + __clear_breakpoint_list(); +} + +/* If the breakpoint we hit is in the breakpoint() instruction, return a + non-zero value. */ + +int +__is_breakpoint_function () +{ + return get_register (PC) == (target_register_t)&_breakinst; +} + +/* Skip the current instruction. Since this is only called by the + stub when the PC points to a breakpoint or trap instruction, + we can safely just skip 2. */ + +void __skipinst (void) +{ + put_register (PC, get_register (PC) + 2); +} + +/* Get a register out of the GDB register structure */ +target_register_t +get_register (regnames_t reg) +{ + GDB_Registers* gdb_regs; + + gdb_regs = (GDB_Registers*)_registers; + + if (reg >= R0 && reg <= MDL) + return gdb_regs->r[reg]; + + return 0xdeadbeef; +} + +/* Put a register into the GDB register structure */ +void +put_register (regnames_t reg, target_register_t value) +{ + GDB_Registers* gdb_regs; + + gdb_regs = (GDB_Registers*)_registers; + + if (reg >= R0 && reg <= MDL) { + gdb_regs->r[reg] = value; + } else { + CYG_FAIL("Attempt to write to non-existent register "); + } +} + +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +// EOF openrisc_stub.c diff --git a/packages/hal/fr30/arch/v2_0/src/hal_misc.c b/packages/hal/fr30/arch/v2_0/src/hal_misc.c new file mode 100644 index 00000000..b2dc9c06 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/src/hal_misc.c @@ -0,0 +1,245 @@ +//========================================================================== +// +// hal_misc.c +// +// HAL miscellaneous functions +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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#### +//========================================================================== + +#include + +#include +#include // tracing macros +#include // assertion macros +#include // HAL header +#include // VSR/ISR defines +#include + +/*------------------------------------------------------------------------*/ +/* If required, define a variable to store the clock period. */ + +#ifdef CYGHWR_HAL_CLOCK_PERIOD_DEFINED + +CYG_WORD32 cyg_hal_clock_period; + +#endif + + +/***************************************************************************** +hal_default_exception_handler -- First level C exception handler + + The assembly default VSR handler calls this routine to handle the +exception. When this routine returns, the state is restored to the state +pointed to by regs. + + We declare this routine as weak so that other handlers can easily +become the default exception handler. + +INPUT: + + vector: The exception vector number. + + regs: A pointer to the saved state. + +OUTPUT: + +RETURN VALUE: + + None + +*****************************************************************************/ + +externC void +hal_default_exception_handler(CYG_WORD vector, HAL_SavedRegisters *regs) + __attribute__ ((weak)); + +void hal_default_exception_handler(CYG_WORD vector, HAL_SavedRegisters *regs) +{ + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + externC void __handle_exception(void); + externC HAL_SavedRegisters * _hal_registers; + + // Set the pointer to the registers of the current exception + // context. At entry the GDB stub will expand the + // HAL_SavedRegisters structure into a (bigger) register array. + _hal_registers = regs; + + __handle_exception(); + +#elif defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ + defined(CYGPKG_HAL_EXCEPTIONS) + + // We should decode the vector and pass a more appropriate + // value as the second argument. For now we simply pass a + // pointer to the saved registers. We should also divert + // breakpoint and other debug vectors into the debug stubs. + + cyg_hal_deliver_exception(vector, (CYG_ADDRWORD)regs); + +#else + + CYG_FAIL("Exception!!!"); + +#endif + + return; +} + +//--------------------------------------------------------------------------- +// Default arch ISR + +externC cyg_uint32 +hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + CYG_FAIL("Spurious Interrupt!!!"); + return 0; +} + +//--------------------------------------------------------------------------- +// Idle thread action + +void +hal_idle_thread_action( cyg_uint32 count ) +{ +} + +//----------------------------------------------------------------------------- +// Monitor initialization. This means to init the vsr vector table. +// TODO maybe init hal_vsr_table through defining it in assembler code + +#ifndef CYGPKG_HAL_FR30_MON_DEFINED +void hal_mon_init(void){ + int i; + /* 0 - 14 exceptions */ + for(i = 0; i < CYGNUM_HAL_VECTOR_INTRFIRST; i++){ + hal_vsr_table[i] = (CYG_ADDRESS)__default_exception_vsr; + } + /* 15 - xx interrupts */ + for( ; i < CYGNUM_HAL_VECTOR_INTRLAST; i++){ + hal_vsr_table[i] = (CYG_ADDRESS)__default_interrupt_vsr; + } + /* xx+1 - 255 exceptions (fr30 traps) */ + for( ; i < CYGNUM_HAL_VSR_MAX; i++){ + hal_vsr_table[i] = (CYG_ADDRESS)__default_exception_vsr; + } +} +#endif + +//--------------------------------------------------------------------------- +// Determine the index of the ls bit of the supplied mask. + +cyg_uint32 +hal_lsbit_index(cyg_uint32 mask) +{ + cyg_uint32 n = mask; + + static const signed char tab[64] = + { -1, 0, 1, 12, 2, 6, 0, 13, 3, 0, 7, 0, 0, 0, 0, 14, 10, + 4, 0, 0, 8, 0, 0, 25, 0, 0, 0, 0, 0, 21, 27 , 15, 31, 11, + 5, 0, 0, 0, 0, 0, 9, 0, 0, 24, 0, 0 , 20, 26, 30, 0, 0, 0, + 0, 23, 0, 19, 29, 0, 22, 18, 28, 17, 16, 0 + }; + + n &= ~(n-1UL); + n = (n<<16)-n; + n = (n<<6)+n; + n = (n<<4)+n; + + return tab[n>>26]; +} + +//--------------------------------------------------------------------------- +// Determine the index of the ms bit of the supplied mask. FIXME: since we +// have hardware support for it, use it! (bit search module) + +cyg_uint32 +hal_msbit_index(cyg_uint32 mask) +{ + cyg_uint32 x = mask; + cyg_uint32 w; + + // Phase 1: make word with all ones from that one to the right. + x |= x >> 16; + x |= x >> 8; + x |= x >> 4; + x |= x >> 2; + x |= x >> 1; + + // Phase 2: calculate number of "1" bits in the word. + w = (x & 0x55555555) + ((x >> 1) & 0x55555555); + w = (w & 0x33333333) + ((w >> 2) & 0x33333333); + w = w + (w >> 4); + w = (w & 0x000F000F) + ((w >> 8) & 0x000F000F); + return (cyg_uint32)((w + (w >> 16)) & 0xFF); + +} + +/*------------------------------------------------------------------------*/ +/* C++ support - run initial constructors */ + +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG +cyg_bool cyg_hal_stop_constructors; +#endif + +typedef void (*pfunc) (void); +extern pfunc __CTOR_LIST__[]; +extern pfunc __CTOR_END__[]; + +void + cyg_hal_invoke_constructors (void) +{ +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG + static pfunc *p = &__CTOR_END__[-1]; + + cyg_hal_stop_constructors = 0; + for (; p >= __CTOR_LIST__; p--) { + (*p) (); + if (cyg_hal_stop_constructors) { + p--; + break; + } + } +#else + pfunc *p; + for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--) { + (*p) (); + } +#endif +} + +//--------------------------------------------------------------------------- diff --git a/packages/hal/fr30/arch/v2_0/src/vectors.S b/packages/hal/fr30/arch/v2_0/src/vectors.S new file mode 100644 index 00000000..49481d14 --- /dev/null +++ b/packages/hal/fr30/arch/v2_0/src/vectors.S @@ -0,0 +1,566 @@ +##============================================================================= +## +## vectors.S +## +## fr30 startup code and exception and interrupt vectors +## +##============================================================================= +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2007 eCosCentric Ltd. +## +## 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): larsi +## Contributors:larsi +## Date: 2006-06-26 +## Purpose: fr30 exception vectors +## Description: This file defines the code placed into the exception +## vectors. It also contains the startup code and first +## level default VSRs that save and restore state for +## both exceptions and interrupts. +## +######DESCRIPTIONEND#### +## +##============================================================================= + + +#include +#include +#include CYGBLD_HAL_PLATFORM_H + +#ifdef CYGPKG_KERNEL +#include +#endif /* CYGPKG_KERNEL */ + +#include + +#============================================================================== + + .file "vectors.S" + +#============================================================================== +# Real startup code. We jump here from the various reset vectors to set up the +# world. + + .text + .globl _start + +_start: + +# disable interrupts and set priority to lowest (=disable) + andccr #0xef + stilm #0x0 + + hal_diag_init_led +#ifdef CYGPKG_HAL_FR30_FLASH_INIT_DEFINED + hal_flash_init +#endif + hal_cpu_init + +#ifdef CYGPKG_HAL_FR30_MEMC_INIT_DEFINED + hal_memc_init +#endif + + hal_intc_init + + hal_cache_init + + hal_timer_init + +# Zero the BSS. If the BSS is not a whole number of words +# long we will write up to 3 extra bytes at the end. +# (This should not be a problem usually). + ldi:32 #__bss_end - 8, r12 + ldi:32 #__bss_start - 4, r13 + eor r0, r0 ; zero r0 +2: + add #0x4, r13 + cmp r12, r13 + ble:d 2b + st r0, @r13 + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + +# In a ROM booted system, we also need to copy the data section +# out to the RAM. + + ldi:32 #__rom_data_start - 4 + CYGPKG_HAL_FR30_LMA_OFFSET, r11 + ldi:32 #__ram_data_start - 4, r9 + ldi:32 #__ram_data_end - 8, r10 +3: + add #0x4, r11 + add #0x4, r9 + ld @r11, r0 + cmp r10, r9 + ble:d 3b + st r0, @r9 + +#endif + + + # Set up the stacks + # Begin with interrupt (system) stack + + ldi:32 #__interrupt_stack, r11 + mov r11, ssp + + # and now continue with user stack + + orccr #0x20 + ldi:32 #__user_stack, r11 + mov r11, usp + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) +# If we are here, initialize the hal_vsr_table. RAM startup +# configurations can assume that Redboot has already set it up. + + .extern hal_mon_init + ldi:32 #hal_mon_init, r11 + call @r11 + +#endif + + .extern hal_variant_init + ldi:32 #hal_variant_init, r11 + call @r11 + + .extern hal_platform_init + ldi:32 #hal_platform_init, r11 + call @r11 + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + // This is here so we can debug the constructors. + .extern initialize_stub + ldi:32 #initialize_stub, r11 + call @r11 +#endif + + .extern cyg_hal_invoke_constructors + ldi:32 #cyg_hal_invoke_constructors, r11 + call @r11 + +# TODO integrate into hal_intr.h +# set irq 25 priority (for reload timer 1) + ldi:20 #0x449, r4 + ldi:8 #0x10, r5 + stb r5, @r4 + +#ifdef CYGDBG_HAL_DEBUG_GDB_INITIAL_BREAK + .extern breakpoint + call breakpoint +#endif + + + .extern cyg_start + ldi:32 #cyg_start, r11 + call @r11 + +# Hmm. Not expecting to return from cyg_start, endless nop loop +1: nop + call 1b + +#============================================================================== +# Default exception VSR + + .align 2, 0xcc + .globl __default_exception_vsr +__default_exception_vsr: + + ## We enter here with the CPU state still in the registers and: + ## @(ssp,8) PS pushed by hardware + ## @(ssp,4) PC pushed by hardware + ## @(ssp) old register r0 content pushed by trampoline + ## r0 now contains the vector number + +# at first switch to USP (set bit 5 in CCR in PS) + orccr #0x20 + + st r0, @-r15 + st mdl, @-r15 + st mdh, @-r15 + + mov r0, mdh ; save exception/interrupt number + mov r15, r0 + addn #+12, r0 + mov r0, mdl ; save r15 also in mdl + + st r0, @-r15 ; store usp + mov ssp, r0 + st r0, @-r15 ; store ssp (TODO maybe have to sub 12 before) + st rp, @-r15 + st tbr, @-r15 + addsp #-8 ; skip 2 positions for PS and PC + mov r15, r0 ; save stack position to later store PS and PC + + st mdl, @-r15 ; store original r15 here + stm1 (r8, r9, r10, r11, r12, r13, r14) + stm0 (r1, r2, r3, r4, r5, r6, r7) + + mov ssp, r14 + ld @r14, r1 ; get original r0 content + st r1, @-r15 ; and store it + + ld @(r14,4), r2 ; get hardware pushed PC + st r2, @r0 ; and store it + ld @(r14,8), r3 ; get hardware pushed PS + addn #4, r0 ; and + st r3, @r0 ; store it + +# we should be finished saving context here + +# Call exception handler + .extern hal_default_exception_handler + + ldi:32 #hal_default_exception_handler, r11 + mov r15, r5 ; pointer to saved state as second argument + call:d @r11 + mov mdh, r4 ; exception number as first argument + +__default_exception_vsr_return: + + + ## At this point, the user stack (USP) contains: + ## @(usp,0x60) trap number + ## @(usp,0x5c) mdl + ## @(usp,0x58) mdh + ## @(usp,0x54) usp + ## @(usp,0x50) ssp + ## @(usp,0x4c) rp + ## @(usp,0x48) tbr + ## @(usp,0x44) ps + ## @(usp,0x40) pc + ## @(usp,0x3c) r15 + ## @(usp,0x38) r14 + ## @(usp,0x34) r13 + ## @(usp,0x30) r12 + ## @(usp,0x2c) r11 + ## @(usp,0x28) r10 + ## @(usp,0x24) r9 + ## @(usp,0x20) r8 + ## @(usp,0x1c) r7 + ## @(usp,0x18) r6 + ## @(usp,0x14) r5 + ## @(usp,0x10) r4 + ## @(usp,0xc) r3 + ## @(usp,8) r2 + ## @(usp,4) r1 + ## @(usp) r0 + ## + ## and system stack (SSP) contains: + ## @(ssp,8) PS + ## @(ssp,4) PC + ## @(ssp) old r0 content + +# we can reuse the code from __default_interrupt_vsr + ldi:32 #hal_exception_return, r0 + jmp @r0 + +#============================================================================== +# Default interrupt VSR +# +# + + .align 2, 0xcc + .globl __default_interrupt_vsr +__default_interrupt_vsr: + + ## We enter here with the CPU state still in the registers and: + ## r0 vector number + ## @(ssp) old register r0 content pushed by trampoline + ## @(ssp,4) PS pushed by hardware + ## @(ssp,8) PC pushed by hardware + + # begin to save registers (to USP) + orccr #0x20 + + st mdl, @-r15 + st mdh, @-r15 + st rp, @-r15 + + stm1 (r8, r9, r10, r11, r12, r13) + stm0 (r1, r2, r3 , r4 , r5 , r6, r7) + + andccr #0xdf + ld @r15+, r8 ; read old r0 content from SSP + ld @r15+, r9 ; read pc pushed by hardware + ld @r15+, r10 ; read ps pushed by hardware + orccr #0x20 + + st r8, @-r15 ; push old r0 content to USP + +# we should be finished saving irq context here + +#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) +# Increment scheduler lock + .extern cyg_scheduler_sched_lock + ldi:32 #cyg_scheduler_sched_lock, r1 + ld @r1, r2 + addn #1, r2 + st r2, @r1 +#endif + +# Call hal_interrupt_handlers[vector](vector, cyg_hal_interrupt_data[vector]) + mov r0, r8 ; copy the vector + lsl #2, r8 ; multiply vector by 4 + + ldi:32 #hal_interrupt_handlers, r13 ; load handlers table + ld @(r13, r8), r1 ; current handler + ldi:32 #hal_interrupt_data, r13 ; load data table + ld @(r13, r8), r5 ; current data, second argument + call:d @r1 + mov r0, r4 ; exception number as argument + +# At this point: +# r15 = stack pointer /*(should be usable as pointer to HAL_SavedRegisters)*/ +# r4 = ISR return code (returned by call) +# r8 = ISR table offset (saved across call) +# r0 = vector number (NOT saved across call, but we don't need it) + +/* + # If we are returning from the last nested interrupt, move back + # to the thread stack. interrupt_end() must be called on the + # thread stack since it potentially causes a context switch. + + hal_from_intstack +*/ + +#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT + +# Call interrupt_end(return_value, hal_interrupt_objects[vector], regs) +# - r4 is the return value from the ISR +# - regs points to saved CPU context + + ldi:32 #hal_interrupt_objects, r13 ; load objects table + ld @(r13, r8), r5 ; current object, second argument + ldi:32 #interrupt_end, r12 + call:d @r12 + mov r15, r6 ; third argument TODO is not in + ; HAL_Saved_Registers format + +#endif + +##.globl hal_exception_return +hal_exception_return: + +# Now pull saved state from stack and return to +# what thread was originally doing. + +# at first store return values to SSP + andccr #0xdf + st r10, @-r15 ; store ps + st r9, @-r15 ; store pc + orccr #0x20 + +# and then restore normal registers from USP + ldm0 (r0, r1, r2 , r3 , r4 , r5, r6, r7) + ldm1 (r8, r9, r10, r11, r12, r13) + + ld @r15+, rp + ld @r15+, mdh + ld @r15+, mdl + + andccr #0xdf + reti + + +#============================================================================== +# Exception trampolines +# TBR table points to these short code sequences here that push the vector +# number on to the stack and then indirect via the VSR table to a handler. +# (__default_interrupt_vsr) + + .text + +# macro to create exception handler (no error code) + +.macro hal_fr30_exception_noerr idx + .globl hal_fr30_exception_noerr_\idx +hal_fr30_exception_noerr_\idx: + st r0, @-r15 + ldi:32 #hal_vsr_table + \idx * 4, r0 + ld @r0, r0 + jmp:d @r0 + ldi:8 #\idx, r0 +.endm + + # Now generate all the default exception VSR trampolines. + +# hal_fr30_exception_noerr 1 no trampoline needed for reset and mode vector + hal_fr30_exception_noerr 2 + hal_fr30_exception_noerr 3 + hal_fr30_exception_noerr 4 + hal_fr30_exception_noerr 5 + hal_fr30_exception_noerr 6 + hal_fr30_exception_noerr 7 + hal_fr30_exception_noerr 8 + hal_fr30_exception_noerr 9 + hal_fr30_exception_noerr 10 + hal_fr30_exception_noerr 11 + hal_fr30_exception_noerr 12 + hal_fr30_exception_noerr 13 + hal_fr30_exception_noerr 14 + +#============================================================================== +# IRQ handler trampolines + +# macro to create exception handler (no error code) + +.macro hal_fr30_irq_handler idx + .globl hal_fr30_irq_\idx +hal_fr30_irq_\idx: + st r0, @-r15 + ldi:32 #hal_vsr_table + \idx * 4, r0 + ld @r0, r0 + jmp:d @r0 + ldi:8 #\idx, r0 +.endm + + hal_fr30_irq_handler 15 + hal_fr30_irq_handler 16 + hal_fr30_irq_handler 17 + hal_fr30_irq_handler 18 + hal_fr30_irq_handler 19 + hal_fr30_irq_handler 20 + hal_fr30_irq_handler 21 + hal_fr30_irq_handler 22 + hal_fr30_irq_handler 23 + hal_fr30_irq_handler 24 + hal_fr30_irq_handler 25 + hal_fr30_irq_handler 26 + hal_fr30_irq_handler 27 + hal_fr30_irq_handler 28 + hal_fr30_irq_handler 29 + hal_fr30_irq_handler 30 + hal_fr30_irq_handler 31 + hal_fr30_irq_handler 32 + hal_fr30_irq_handler 33 + hal_fr30_irq_handler 34 + hal_fr30_irq_handler 35 + hal_fr30_irq_handler 36 + hal_fr30_irq_handler 37 + hal_fr30_irq_handler 38 + hal_fr30_irq_handler 39 + hal_fr30_irq_handler 40 + hal_fr30_irq_handler 41 + hal_fr30_irq_handler 42 + hal_fr30_irq_handler 43 + hal_fr30_irq_handler 44 + hal_fr30_irq_handler 45 + hal_fr30_irq_handler 46 + hal_fr30_irq_handler 47 + hal_fr30_irq_handler 48 + hal_fr30_irq_handler 49 + hal_fr30_irq_handler 50 + hal_fr30_irq_handler 51 + hal_fr30_irq_handler 52 + hal_fr30_irq_handler 53 + hal_fr30_irq_handler 54 + hal_fr30_irq_handler 55 + hal_fr30_irq_handler 56 + hal_fr30_irq_handler 57 + hal_fr30_irq_handler 58 + hal_fr30_irq_handler 59 + hal_fr30_irq_handler 60 + hal_fr30_irq_handler 61 + hal_fr30_irq_handler 62 + hal_fr30_irq_handler 63 + + + .data +// +// "Vectors" - fixed location data items +// This section contains any data which might be shared between +// an eCos application and any other environment, e.g. the debug +// ROM. +// + .section ".fixed_vectors" +// Space for the virtual vectors + .balign 4 +// Vectors used to communicate between eCos and ROM environments + .globl hal_virtual_vector_table +hal_virtual_vector_table: + .rept 64 // CYGNUM_CALL_IF_TABLE_SIZE + .long 0 + .endr + + .globl hal_vsr_table +hal_vsr_table: + .rept CYGNUM_HAL_VSR_COUNT // exceptions & interrupts + .long 0 + .endr + +#============================================================================== +# Initial and interrupt stack + + .section ".bss" + + .balign 4 + .global cyg_interrupt_stack_base +cyg_interrupt_stack_base: +__interrupt_stack_base: + .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE + .byte 0 + .endr + .balign 4 + .global cyg_interrupt_stack +cyg_interrupt_stack: +__interrupt_stack: + .long 0,0,0,0,0,0,0,0 + + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + .global __stub_stack_base +__stub_stack_base: + .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE + .byte 0 + .endr + .balign 4 + .global __stub_stack +__stub_stack: + + .long 0,0,0,0,0,0,0,0 +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + + .balign 4 +__user_stack_base: +// FIXME TODO import symbolic constant from C-code + .rept 4532 + .byte 0 + .endr + .balign 4 +__user_stack: + .long 0 + +#------------------------------------------------------------------------------ +# end of vectors.S diff --git a/packages/hal/fr30/mb91301/v2_0/ChangeLog b/packages/hal/fr30/mb91301/v2_0/ChangeLog new file mode 100644 index 00000000..99dd979b --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/ChangeLog @@ -0,0 +1,53 @@ +2008-07-01 Lars Poeschel + + * src/fr30_md91301.ld: Reworked memory layout for flash support. + * src/hal_diag.c: Little updates in serial0 configuration registers. + * src/variant.S: Made it possible for the platform to override + variants rom vectors. + * include/variant.inc: Moved macros for sdram config addresses to platform. + +2007-07-09 Lars Poeschel + + * src/fr30_md91301.ld: + * src/hal_diag.c: + * src/var_misc.c: + * include/hal_diag.h: + * include/var_arch.h: + * include/variant.inc: + * include/var_intr.h: + * cdl/hal_fr30_mb91301.cdl: Initial fr30 ecos port + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/hal/fr30/mb91301/v2_0/cdl/hal_fr30_mb91301.cdl b/packages/hal/fr30/mb91301/v2_0/cdl/hal_fr30_mb91301.cdl new file mode 100644 index 00000000..1a44bf06 --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/cdl/hal_fr30_mb91301.cdl @@ -0,0 +1,192 @@ +# ==================================================================== +# +# hal_fr30_mb91301.cdl +# +# FR30/mb91301 variant architectural HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): larsi +# Original data: bartv, nickg +# Contributors: +# Date: 2006-07-09 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_FR30_MB91301 { + display "MB91301 variant" + parent CYGPKG_HAL_FR30 + implements CYGINT_HAL_FR30_VARIANT + hardware + include_dir cyg/hal + define_header hal_fr30_mb91301.h + description " + The MB91301 architecture HAL package provides generic support + for this processor architecture. It is also necessary to + select a specific target platform HAL package." + + + define_proc { + puts $::cdl_header "#include " + } + + cdl_component CYGHWR_HAL_FR30_MB91301_SYSTEM_CLOCK_MHZ { + display "System clock speed in MHz" + flavor data + calculated { (CYGHWR_HAL_FR30_MB91301_CRYSTAL_SPEED * \ + CYGHWR_HAL_FR30_MB91301_CLKR) } + description "This is the resulting base clock speed for the board. + It is calculated + CLKR * CRYSTAL_SPEED. + This is NOT the CPU Frequency." + + cdl_option CYGHWR_HAL_FR30_MB91301_CRYSTAL_SPEED { + display "Crystal speed in Mhz" + flavor data + description "You have to enter the speed of the mounted crystal here. + The resulting base clock is calculated: + CLKR * CRYSTAL_SPEED / CLKB_DIVIDER" + legal_values 1 to 17 + default_value 15 + } + + cdl_option CYGHWR_HAL_FR30_MB91301_CLKR { + display "Main PLL multiply-by rate" + flavor data + description "Using this value you can set the resulting base clock + speed. It is calculated: + CLKR * CRYSTAL_SPEED. + DO NOT DO A SETTING HIGHER THAN 4 UNLESS YOU EXACTLY + KNOW WHAT YOU A DOING! " + legal_values 1 to 8 + default_value 4 + } + + cdl_option CYGHWR_HAL_FR30_MB91301_CLKB_DIVIDER { + display "Base clock divider" + flavor data + description "Using this value you can limit the base clock speed. + You set the divider. The resulting base clock speed + is calculated: + CLKB = system clock / divider + CPU, internal memory and internal buses use this base clock! + A value other than 1 can cause problems when using the stop + mode of the CPU. + See Fujitsu MB91301 hardware manual Chapter 5 for + constraints on setting this value!" + legal_values 1 to 16 + default_value 1 + } + + cdl_option CYGHWR_HAL_FR30_MB91301_CLKP_DIVIDER { + display "Peripheral clock divider" + flavor data + description "Using this value you can set the peripheral clock + speed. You set the divider. The resulting peripheral clock + speed is calculated: + CLKP = system clock / divider + See Fujitsu MB91301 hardware manual Chapter 5 for constraints on setting + this value!" + legal_values 1 to 16 + default_value 4 + } + + cdl_option CYGHWR_HAL_FR30_MB91301_CLKT_DIVIDER { + display "External buses clock divider" + flavor data + description "Using this value you can set the external buses clock + speed. You set the divider. The resulting external buses + clock speed is calculated: + CLKT = system clock / divider + See Fujitsu MB91301 hardware manual Chapter 5 for constraints on setting + this value!" + legal_values 1 to 16 + default_value 1 + } + + } + + + # Real-time clock/counter specifics + cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants." + flavor none + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + default_value 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + default_value 100 + } + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + default_value {(CYGHWR_HAL_FR30_MB91301_CRYSTAL_SPEED * CYGHWR_HAL_FR30_MB91301_CLKR * 1000000) / (CYGHWR_HAL_FR30_MB91301_CLKP_DIVIDER * CYGNUM_HAL_RTC_DENOMINATOR * 32)} + description " + The tick timer facility is used + to drive the eCos kernel RTC. Reload Timer 1 is used. The count + register decrements at the CLKP clock speed. We use prescaler 32. + By default we want 100 Hz." + } + } + + + compile hal_diag.c var_misc.c variant.S + + make { + /lib/target.ld: /src/fr30_mb91301.ld + $(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail -n +2 target.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm target.tmp + } + + cdl_option CYGBLD_LINKER_SCRIPT { + display "Linker script" + flavor data + no_define + calculated { "src/fr30_mb91301.ld" } + } + +} diff --git a/packages/hal/fr30/mb91301/v2_0/include/hal_diag.h b/packages/hal/fr30/mb91301/v2_0/include/hal_diag.h new file mode 100644 index 00000000..c08de032 --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/include/hal_diag.h @@ -0,0 +1,128 @@ +/*============================================================================= +// +// hal_diag.h +// +// HAL Support for Kernel Diagnostic Routines +// +//============================================================================= +//####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): larsi +// Contributors: +// Date: 2007-07-09 +// Purpose: HAL Support for Kernel Diagnostic Routines +// Description: Diagnostic routines for use during kernel development. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#ifndef CYGONCE_HAL_DIAG_H +#define CYGONCE_HAL_DIAG_H + +#include +#include + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) + +#include + +#define HAL_DIAG_INIT() hal_if_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) + + +#else // old way of doing diagnostic I/O + +/*---------------------------------------------------------------------------*/ +/* functions implemented in hal_diag.c (old way without virtual vectors) */ + +externC void hal_diag_init(void); +externC void hal_diag_write_char(char c); +externC void hal_diag_read_char(char *c); + +/*---------------------------------------------------------------------------*/ + +#define HAL_DIAG_INIT() hal_diag_init() +#define HAL_DIAG_WRITE_CHAR(_c_) hal_diag_write_char(_c_) +#define HAL_DIAG_READ_CHAR(_c_) hal_diag_read_char(&_c_) + +#endif /* CYGSEM_HAL_VIRTUAL_VECTOR_DIAG */ + +/*---------------------------------------------------------------------------*/ +// serial port0 defines +#define CYG_HAL_FR30_MB91301_SMR0 0x63 +#define CYG_HAL_FR30_MB91301_SCR0 0x62 +#define CYG_HAL_FR30_MB91301_SIDR0 0x61 +#define CYG_HAL_FR30_MB91301_SODR0 0x61 +#define CYG_HAL_FR30_MB91301_SSR0 0x60 +#define CYG_HAL_FR30_MB91301_UTIM0 0x64 +#define CYG_HAL_FR30_MB91301_UTIMR0 0x64 +#define CYG_HAL_FR30_MB91301_DRCL0 0x66 +#define CYG_HAL_FR30_MB91301_UTIMC0 0x67 + +/*---------------------------------------------------------------------------*/ +// serial port1 defines +#define CYG_HAL_FR30_MB91301_SMR1 0x6b +#define CYG_HAL_FR30_MB91301_SCR1 0x6a +#define CYG_HAL_FR30_MB91301_SIDR1 0x69 +#define CYG_HAL_FR30_MB91301_SODR1 0x69 +#define CYG_HAL_FR30_MB91301_SSR1 0x68 +#define CYG_HAL_FR30_MB91301_UTIM1 0x6c +#define CYG_HAL_FR30_MB91301_UTIMR1 0x6c +#define CYG_HAL_FR30_MB91301_DRCL1 0x6e +#define CYG_HAL_FR30_MB91301_UTIMC1 0x6f + +#define CYG_HAL_FR30_MB91301_PDRJ 0x13 +#define CYG_HAL_FR30_MB91301_DDRJ 0x403 +#define CYG_HAL_FR30_MB91301_PFRJ 0x413 + +/*---------------------------------------------------------------------------*/ +// LED +#define CYG_HAL_FR30_MB91301_PDRG 0x10 +#define CYG_HAL_FR30_MB91301_DDRG 0x400 +#define CYG_HAL_FR30_MB91301_PFRG 0x410 +// our MB91302A does not have PCRG (pull up resistor register G) +// but it is here anyway +#define CYG_HAL_FR30_MB91301_PCRG 0x420 + +// externC void hal_diag_init_led(void); +externC void hal_diag_led(cyg_uint8); + +/*---------------------------------------------------------------------------*/ +/* end of hal_diag.h */ +#endif /* CYGONCE_HAL_DIAG_H */ diff --git a/packages/hal/fr30/mb91301/v2_0/include/var_arch.h b/packages/hal/fr30/mb91301/v2_0/include/var_arch.h new file mode 100644 index 00000000..4a8285fd --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/include/var_arch.h @@ -0,0 +1,64 @@ +#ifndef CYGONCE_HAL_VAR_ARCH_H +#define CYGONCE_HAL_VAR_ARCH_H + +//========================================================================== +// +// var_arch.h +// +// Architecture specific abstractions +// +//========================================================================== +//####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): larsi +// Contributors: +// Date: 2007-07-09 +// Purpose: Define architecture abstractions +// Description: This file contains any extra or modified definitions for +// this variant of the architecture. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include + + +//-------------------------------------------------------------------------- +#endif // CYGONCE_HAL_VAR_ARCH_H +// End of var_arch.h diff --git a/packages/hal/fr30/mb91301/v2_0/include/var_intr.h b/packages/hal/fr30/mb91301/v2_0/include/var_intr.h new file mode 100644 index 00000000..81a00646 --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/include/var_intr.h @@ -0,0 +1,275 @@ +#ifndef CYGONCE_HAL_IMP_INTR_H +#define CYGONCE_HAL_IMP_INTR_H + +//========================================================================== +// +// var_intr.h +// +// MB91301 Interrupt and clock support +// +//========================================================================== +//####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): larsi +// Contributors: larsi +// Date: 2006-07-14 +// Purpose: MB91301 Interrupt support +// Description: The macros defined here provide the HAL APIs for handling +// interrupts and the clock for variants of the MB91301 +// architecture. +// +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#include + +#include + +#include + +//-------------------------------------------------------------------------- +// Interrupt vectors. + +#ifndef CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED + +#define CYGNUM_HAL_INTERRUPT_0 16 +#define CYGNUM_HAL_INTERRUPT_1 17 +#define CYGNUM_HAL_INTERRUPT_2 18 +#define CYGNUM_HAL_INTERRUPT_3 19 +#define CYGNUM_HAL_INTERRUPT_4 20 +#define CYGNUM_HAL_INTERRUPT_5 21 +#define CYGNUM_HAL_INTERRUPT_6 22 +#define CYGNUM_HAL_INTERRUPT_7 23 +#define CYGNUM_HAL_INTERRUPT_RELOAD_TIMER0 24 +#define CYGNUM_HAL_INTERRUPT_RELOAD_TIMER1 25 +#define CYGNUM_HAL_INTERRUPT_RELOAD_TIMER2 26 +#define CYGNUM_HAL_INTERRUPT_UART0_RX 27 +#define CYGNUM_HAL_INTERRUPT_UART1_RX 28 +#define CYGNUM_HAL_INTERRUPT_UART2_RX 29 +#define CYGNUM_HAL_INTERRUPT_UART0_TX 30 +#define CYGNUM_HAL_INTERRUPT_UART1_TX 31 +#define CYGNUM_HAL_INTERRUPT_UART2_TX 32 +#define CYGNUM_HAL_INTERRUPT_DMAC0 33 +#define CYGNUM_HAL_INTERRUPT_DMAC1 34 +#define CYGNUM_HAL_INTERRUPT_DMAC2 35 +#define CYGNUM_HAL_INTERRUPT_DMAC3 36 +#define CYGNUM_HAL_INTERRUPT_DMAC4 37 +#define CYGNUM_HAL_INTERRUPT_AD 38 +#define CYGNUM_HAL_INTERRUPT_PPG0 39 +#define CYGNUM_HAL_INTERRUPT_PPG1 40 +#define CYGNUM_HAL_INTERRUPT_PPG2 41 +#define CYGNUM_HAL_INTERRUPT_PPG3 42 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 43 +#define CYGNUM_HAL_INTERRUPT_UTIMER0 44 +#define CYGNUM_HAL_INTERRUPT_UTIMER1 45 +#define CYGNUM_HAL_INTERRUPT_UTIMER2 46 +#define CYGNUM_HAL_INTERRUPT_TIMEBASE_OVERFLOW 47 +#define CYGNUM_HAL_INTERRUPT_I2C0 48 +#define CYGNUM_HAL_INTERRUPT_I2C1 49 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 50 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 51 +#define CYGNUM_HAL_INTERRUPT_FREERUN_TIMER 52 +#define CYGNUM_HAL_INTERRUPT_ICU0 53 +#define CYGNUM_HAL_INTERRUPT_ICU1 54 +#define CYGNUM_HAL_INTERRUPT_ICU2 55 +#define CYGNUM_HAL_INTERRUPT_ICU3 56 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 57 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 58 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 59 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 60 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 61 +// system reserved #define CYGNUM_HAL_INTERRUPT_ 62 +#define CYGNUM_HAL_INTERRUPT_DELAYED_IRQ 63 + +// The interrupt vector used by the RTC, aka tick timer +#define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_RELOAD_TIMER1 + +#define CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED + +#endif + +//-------------------------------------------------------------------------- +// Interrupt controller access. + +// currently only external interrupts are masked using the external +// interrupt controller. This means only vectors 16 to 23 are valid. +// Other interrupts may be masked in the future +// using the mask mechanism for interrupt levels, if needed. + +#ifndef CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED + +#define CYG_HAL_FR30_MB91301_ENIR 0x41 +#define CYG_HAL_FR30_MB91301_EIRR 0x40 +#define CYG_HAL_FR30_MB91301_ELVR 0x42 +#define CYG_HAL_FR30_MB91301_ICR00 0x440 + +// Array which stores the configured priority levels for the configured +// interrupts. +// this will be useful, if we implement masking of non external interrupts +// externC volatile CYG_BYTE hal_interrupt_level[CYGNUM_HAL_ISR_COUNT]; + + +#define HAL_INTERRUPT_MASK( _vector_ ) \ +{ \ + CYG_WORD32 _ilr_; \ + if ((_vector_ >= CYGNUM_HAL_INTERRUPT_7) && \ + (_vector_ <= CYGNUM_HAL_INTERRUPT_0)){ \ + HAL_READ_UINT8( CYG_HAL_FR30_MB91301_ENIR, _ilr_ ); \ + _ilr_ &= ~(1<<((_vector_)>>4)); \ + HAL_WRITE_UINT8( CYG_HAL_FR30_MB91301_ENIR, _ilr_ ); \ + } \ + /* Handle RTC masking special */ \ + if (_vector_ == CYGNUM_HAL_INTERRUPT_RTC) \ + asm volatile("ldi:8 #0x57, r0;\n" \ + "bandl #0x7, @r0;\n" \ + : : :"r0"); \ +} + +#define HAL_INTERRUPT_UNMASK( _vector_ ) \ +{ \ + CYG_WORD32 _ilr_; \ + if ((_vector_ >= CYGNUM_HAL_INTERRUPT_7) && \ + (_vector_ <= CYGNUM_HAL_INTERRUPT_0)){ \ + HAL_READ_UINT8( CYG_HAL_FR30_MB91301_ENIR, _ilr_ ); \ + _ilr_ |= (1<<((_vector_)>>4)); \ + HAL_WRITE_UINT8( CYG_HAL_FR30_MB91301_ENIR, _ilr_ ); \ + } \ + /* Handle RTC unmasking special */ \ + if (_vector_ == CYGNUM_HAL_INTERRUPT_RTC) \ + asm volatile("ldi:8 #0x57, r0;\n" \ + "borl #0x8, @r0;\n" \ + : : :"r0"); \ +} + +#define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) \ +{ \ + CYG_WORD32 _ilr_; \ + if ((_vector_ >= CYGNUM_HAL_INTERRUPT_7) && \ + (_vector_ <= CYGNUM_HAL_INTERRUPT_0)){ \ + HAL_READ_UINT8( CYG_HAL_FR30_MB91301_EIRR, _ilr_ ); \ + _ilr_ &= ~(1<<((_vector_)>>4)); \ + HAL_WRITE_UINT8( CYG_HAL_FR30_MB91301_EIRR, _ilr_ ); \ + } \ + /* Handle RTC acknowledging special */ \ + if (_vector_ == CYGNUM_HAL_INTERRUPT_RTC) \ + asm volatile("ldi:8 #0x57, r0;\n" \ + "bandl #0xb, @r0;\n" \ + : : :"r0"); \ +} + +#define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ ) \ +{ \ + /* subtract 15 from vector */ \ + cyg_uint32 _v_ = _vector_ >> 4; \ + cyg_uint16 _val_ = 0; \ + cyg_uint16 _reg_; \ + \ + if ((_vector_ >= CYGNUM_HAL_INTERRUPT_7) && \ + (_vector_ <= CYGNUM_HAL_INTERRUPT_0)){ \ + \ + /* set bits according to requirements */ \ + if( _up_ ) _val_ |= 1; \ + if( !(_level_) ) _val_ |= 2; \ + \ + /* get old ELVR */ \ + HAL_READ_UINT16( CYG_HAL_FR30_MB91301_ELVR, _reg_ ); \ + \ + /* clear old value and set new */ \ + _reg_ &= ~(3 << _v_); \ + _reg_ |= _val_ << _v_; \ + HAL_WRITE_UINT16( CYG_HAL_FR30_MB91301_ELVR, _reg_ ); \ + } \ +} + +#define HAL_INTERRUPT_SET_LEVEL( _vector_, _level_ ) \ +{ \ + /* subtract 15 from vector */ \ + cyg_uint32 _v_ = _vector_ >> 4; \ + CYG_WORD32 _ilr_; \ +/* HAL_READ_UINT8( CYG_HAL_FR30_MB91301_ICR00 + _vector_, _ilr_ );*/ \ +/* reading before writing is only needed, if UINT8 writing is not */ \ +/* possible to IO 0x440 */ \ + _ilr_ = (_level_); \ + HAL_WRITE_UINT8( CYG_HAL_FR30_MB91301_ICR00 + _vector_, _ilr_ ); \ +/* for later use: */ \ +/* hal_interrupt_level[_vector_] = _level_; */ \ +} + +#define CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED + +#endif + +//-------------------------------------------------------------------------- +// Clock control registers + +// MB91301 series has 3 built-in timer channels. +// Timer 2 is used for delay and timer 1 for RTC/*delay*/. +// Timer 0 and 1 can activate DMA and this feature is propably needed by +// the application. Timer 0 is free to use by the application. + +#define CYG_HAL_FR30_DLY_TMCSR 0x5e +#define CYG_HAL_FR30_DLY_TMR 0x5a +#define CYG_HAL_FR30_DLY_TMRLR 0x58 +#define CYG_HAL_FR30_RTC_TMCSR 0x56 +#define CYG_HAL_FR30_RTC_TMR 0x52 +#define CYG_HAL_FR30_RTC_TMRLR 0x50 + + + +//-------------------------------------------------------------------------- +// Control-C support. + +#if defined(CYGDBG_HAL_FR30_DEBUG_GDB_CTRLC_SUPPORT) + +#define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_DUART + +externC cyg_uint32 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); + +#define HAL_CTRLC_ISR hal_ctrlc_isr + +#endif + +//-------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_IMP_INTR_H +// End of imp_intr.h diff --git a/packages/hal/fr30/mb91301/v2_0/include/variant.inc b/packages/hal/fr30/mb91301/v2_0/include/variant.inc new file mode 100644 index 00000000..8bd86850 --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/include/variant.inc @@ -0,0 +1,341 @@ +#ifndef CYGONCE_HAL_VARIANT_INC +#define CYGONCE_HAL_VARIANT_INC +##============================================================================= +## +## variant.inc +## +## MB91301 family assembler header file +## +##============================================================================= +#####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): larsi +## Contributors:larsi +## Date: 2006-07-24 +## Purpose: MB91301 family definitions. +## Description: This file contains various definitions and macros that are +## useful for writing assembly code for the TX39 CPU family. +## Usage: +## #include +## ... +## +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#include + +#include + +#include + +##----------------------------------------------------------------------------- +## Define CPU variant for architecture HAL. + +#define CYG_HAL_FR30_MB91301 + +##----------------------------------------------------------------------------- +## Indicate that the ISR tables are defined in variant.S + +#ifndef CYG_HAL_FR30_ISR_TABLES_DEFINED +#define CYG_HAL_FR30_ISR_TABLES_DEFINED +#endif + +##----------------------------------------------------------------------------- +## CPU initialisation, we set the clock to PLL 48 Mhz (12 * 4Mhz) here. +## PLL lock waiting time is implemented as a busy loop. + +#ifndef CYGPKG_HAL_FR30_CPU_INIT_DEFINED +#define CYGPKG_HAL_FR30_CPU_INIT_DEFINED +# +# busy wait loop +# pollutes r11, r12 +# +.macro wait_loop no=0x1 + ldi:20 #\no, r12 + ldi:8 #0x1, r11 +8: + sub r11, r12 + bne 8b +.endm + +##----------------------------------------------------------------------------- +## Clock Modulator control registers + + .equ FR30_MB91301_CMCR, 0x164 + .equ FR30_MB91301_CMCRH, 0x164 + .equ FR30_MB91301_CMCRL, 0x165 + .equ FR30_MB91301_CMPR, 0x166 + .equ FR30_MB91301_CMLS0, 0x168 + .equ FR30_MB91301_CMLS1, 0x16a + .equ FR30_MB91301_CMLS2, 0x16c + .equ FR30_MB91301_CMLT0, 0x170 + .equ FR30_MB91301_CMLT1, 0x172 + .equ FR30_MB91301_CMLT2, 0x174 + .equ FR30_MB91301_CMAC, 0x176 + .equ FR30_MB91301_CMACH, 0x178 + .equ FR30_MB91301_CMACL, 0x179 + .equ FR30_MB91301_CMTS, 0x17a + .equ FR30_MB91301_CMTSH, 0x17a + .equ FR30_MB91301_CMTSL, 0x17b + .equ FR30_MB91301_ICR31, 0x45f + +##----------------------------------------------------------------------------- +## Registers for Clock Generation and Reset + + .equ FR30_MB91301_RSRR, 0x480 + .equ FR30_MB91301_STCR, 0x481 + .equ FR30_MB91301_TBCR, 0x482 + .equ FR30_MB91301_CTBR, 0x483 + .equ FR30_MB91301_CLKR, 0x484 + .equ FR30_MB91301_WPR, 0x485 + .equ FR30_MB91301_DIVR0, 0x486 + .equ FR30_MB91301_DIVR1, 0x487 + +##----------------------------------------------------------------------------- +## ext bus interface registers +## part used for flash + + .equ FR30_MB91301_ASR0, 0x640 + .equ FR30_MB91301_ACR0, 0x642 + .equ FR30_MB91301_AWR0, 0x660 + .equ FR30_MB91301_CSER, 0x680 + + .equ FR30_MB91301_PDR9, 0x9 + .equ FR30_MB91301_DDR9, 0x609 + .equ FR30_MB91301_PFR9, 0x619 + .equ FR30_MB91301_PCR9, 0x629 + + .equ FR30_MB91301_PDR8, 0x8 + .equ FR30_MB91301_DDR8, 0x608 + .equ FR30_MB91301_PFR8, 0x618 + .equ FR30_MB91301_PCR8, 0x628 + +## part used for sdram + .equ FR30_MB91301_ASR6, 0x658 + .equ FR30_MB91301_ACR6, 0x65a + .equ FR30_MB91301_AWR6, 0x66c + .equ FR30_MB91301_MCRA, 0x670 + .equ FR30_MB91301_MCRB, 0x671 + .equ FR30_MB91301_RCR, 0x684 + + +##----------------------------------------------------------------------------- +## registers for serial0 and U-timer settings +## + .equ FR30_MB91301_PDRJ, 0x13 + .equ FR30_MB91301_DDRJ, 0x403 + .equ FR30_MB91301_PFRJ, 0x413 + .equ FR30_MB91301_UTIM0, 0x64 + .equ FR30_MB91301_UTIMR0, 0x64 + .equ FR30_MB91301_UTIMC0, 0x67 + .equ FR30_MB91301_DRCL, 0x66 + .equ FR30_MB91301_SMR0, 0x63 + .equ FR30_MB91301_SCR0, 0x62 + .equ FR30_MB91301_SIDR0, 0x61 + .equ FR30_MB91301_SODR0, 0x61 + .equ FR30_MB91301_SSR0, 0x60 + +##----------------------------------------------------------------------------- +## registers for clock settings +## + .equ FR30_MB91301_RTC_TMRLR, 0x50 + .equ FR30_MB91301_RTC_TMR, 0x52 + .equ FR30_MB91301_RTC_TMCSR, 0x56 + + + +##------------------------------------------------------------------------------ +## CPU initialisation macro +## This is mainly for setting clock speeds. +##------------------------------------------------------------------------------ +.macro hal_cpu_init + + ldi:8 #0x00, r0 + + ldi:20 #FR30_MB91301_CLKR, r10 ; PLLx4 and enable it, still use source + ldi:8 (CYGHWR_HAL_FR30_MB91301_CLKR - 1) * 16 + 4, r1 ; + stb r1, @r10 ; oscillation as clock source + + ldi:20 #FR30_MB91301_TBCR, r11 ; set time base counter to + ldi:8 #0x18, r1 ; about 60 ms and disable + stb r1, @r11 ; its interrupt (we poll below) + + ldi:20 #FR30_MB91301_CTBR, r12 ; and + ldi:8 #0xa5, r2 ; start + ldi:8 #0x5a, r3 ; the + stb r2, @r12 ; time base + stb r3, @r12 ; counter + + ldi:20 #FR30_MB91301_STCR, r13 ; set oscillation stabilisation time + ldi:8 #0x17, r1 ; to about 250 us + stb r1, @r13 ; + + ldi:20 #FR30_MB91301_DIVR0, r12 ; set CLKB divider + ldi:8 (CYGHWR_HAL_FR30_MB91301_CLKB_DIVIDER - 1) * 16 + (CYGHWR_HAL_FR30_MB91301_CLKP_DIVIDER - 1), r1 ; and + stb r1, @r12 ; CLKP divider + + ldi:20 #FR30_MB91301_DIVR1, r13 ; CLKT divider + ldi:8 (CYGHWR_HAL_FR30_MB91301_CLKT_DIVIDER - 1) * 16, r1 + stb r1, @r13 ; + + ldi:8 #0x80, r2 ; wait the rest +1: ; of the + ldub @r11, r3 ; time base counter time + and r2, r3 ; (we set it to + beq 1b ; 60 ms above) + + ldi:8 #0x36, r1 ; and now we are ready to + stb r1, @r10 ; switch clock to PLL + +.endm + +#endif /* !CYGPKG_HAL_FR30_CPU_INIT_DEFINED */ + +##----------------------------------------------------------------------------- +## FR30 interrupt handling. +## nothing is here because the intc is initialized correctly by hardware reset +## if something is needed it should be implemented in arch.inc with define'd +## adresses to the registers. It should be the same for all FR30s + + +##------------------------------------------------------------------------------ +## Diagnostics macros. +## Indicate that the diagnostic macros are defined in variant.S / hal_diag.c + +#ifndef CYGPKG_HAL_FR30_DIAG_DEFINED + +##----------------------------------------------------------------------------- +## registers for led settings +## + + .equ FR30_MB91301_PDRG, 0x10 + .equ FR30_MB91301_DDRG, 0x400 + .equ FR30_MB91301_PFRG, 0x410 +## our MB91301A does not have PCRG (pull up resistor register G) +## but it is here anyway + .equ FR30_MB91301_PCRG, 0x420 + + +.macro hal_diag_init_led + ldi:8 #0xff, r4 + ldi:20 #FR30_MB91301_DDRG, r5 + stb r4, @r5 + ldi:8 #0x00, r13 + ldi:20 #FR30_MB91301_PFRG, r5 + stb r13, @r5 + dmovb r13, @FR30_MB91301_PDRG +.endm + +## +## switch on led on "hardcoded" value supplied after this macro +## pollutes r13 +## +.macro hal_diag_led led=0x0 +##st r13, @-r15 + ldi:8 #\led , r13 + dmovb r13, @FR30_MB91301_PDRG +##ld @r15+, r13 +.endm + +##------------------------------------------------------------------------------ +## UARTa macros +## + +## output a value to UART a +## the value has to be in r4 +## register r1 will be polluted +.macro uarta_putc + ldi:8 #FR30_MB91301_SODR0, r1 + stb r4, @r1 +.endm + + +## wait for the data in UART a SODR0 register to be drained +## registers r1, r2, r3 will be polluted +.macro uarta_drain + ldi:8 #FR30_MB91301_SSR0, r3 ; + ldi:8 #0x08, r1 ; TDRE bit of SSR0 +1: ; + ldub @r3, r2 ; + and r1, r2 ; + beq 1b +.endm + +## receive a value from UART a +## value is returned in r4 +## register r1, r2 and r3 will be polluted +.macro uarta_getc + ldi:8 #FR30_MB91301_SSR0, r3 ; + ldi:8 #0x10, r1 ; RDRF bit of SSR0 +2: + ldub @r3, r2 ; + and r1, r2 ; + beq 2b ; wait until a byte is received + + ldi:8 #FR30_MB91301_SIDR0, r3 ; + ldub @r3, r4 ; and get the value +.endm + +#define CYGPKG_HAL_FR30_DIAG_DEFINED + +#endif + +#------------------------------------------------------------------------------ +# Timer initialization. + +#ifndef CYGPKG_HAL_FR30_TIMER_DEFINED + + .macro hal_timer_init + + # load reload value into reload register + ldi:8 #FR30_MB91301_RTC_TMRLR, r4 + ldi:20 #CYGNUM_HAL_RTC_PERIOD, r5 + sth r5, @r4 + # set parameters to TODO + ldi:8 #FR30_MB91301_RTC_TMCSR, r4 + ldi:20 #0x0813, r5 + sth r5, @r4 + .endm + +#define CYGPKG_HAL_FR30_TIMER_DEFINED + +#endif + +#------------------------------------------------------------------------------ +#endif // ifndef CYGONCE_HAL_VARIANT_INC +# end of variant.inc diff --git a/packages/hal/fr30/mb91301/v2_0/src/fr30_mb91301.ld b/packages/hal/fr30/mb91301/v2_0/src/fr30_mb91301.ld new file mode 100644 index 00000000..9f6f7278 --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/src/fr30_mb91301.ld @@ -0,0 +1,166 @@ +//============================================================================= +// +// MLT linker script for Fujitsu FR30 +// +//============================================================================= +//####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#### +//============================================================================= + +#include + +STARTUP(vectors.o) +ENTRY(_start) +#ifdef EXTRAS +INPUT(extras.o) +#endif +#if (__GNUC__ >= 3) +// GROUP(libtarget.a libgcc.a libsupc++.a) +GROUP(libtarget.a libgcc.a) +#else +GROUP(libtarget.a libgcc.a) +#endif + +#define ALIGN_LMA 4 +#define FOLLOWING(_section_) AT ((LOADADDR (_section_) + SIZEOF (_section_) + ALIGN_LMA - 1) & ~ (ALIGN_LMA - 1)) +#define LMA_EQ_VMA +#define FORCE_OUTPUT . = . + +#define SECTIONS_BEGIN \ + /* Debug information */ \ + .debug_aranges 0 : { *(.debug_aranges) } \ + .debug_pubnames 0 : { *(.debug_pubnames) } \ + .debug_info 0 : { *(.debug_info) } \ + .debug_abbrev 0 : { *(.debug_abbrev) } \ + .debug_line 0 : { *(.debug_line) } \ + .debug_frame 0 : { *(.debug_frame) } \ + .debug_str 0 : { *(.debug_str) } \ + .debug_loc 0 : { *(.debug_loc) } \ + .debug_macinfo 0 : { *(.debug_macinfo) } + +#define SECTION_fixed_vectors(_region_, _vma_, _lma_) \ + .fixed_vectors _vma_ : _lma_ \ + { FORCE_OUTPUT; KEEP (*(.fixed_vectors)) } \ + > _region_ + +#define SECTION_rom_vectors(_region_, _vma_, _lma_) \ + .rom_vectors _vma_ : _lma_ \ + { FORCE_OUTPUT; KEEP (*(.rom_vectors)) } \ + > _region_ + +#define SECTION_rom_startup(_region_, _vma_, _lma_) \ + .rom_startup_trampoline _vma_ : _lma_ \ + { FORCE_OUTPUT; KEEP(*(.rom_startup_trampoline*)) } \ + > _region_ + +#define SECTION_ram_startup(_region_, _vma_, _lma_) \ + .ram_startup_trampoline _vma_ : _lma_ \ + { __ram_trampoline_start = ABSOLUTE (.); FORCE_OUTPUT; KEEP(*(.ram_startup_trampoline*)) } \ + > _region_ \ + __rom_trampoline_start = LOADADDR (.ram_startup_trampoline); \ + __rom_trampoline_end = LOADADDR (.ram_startup_trampoline) + SIZEOF(.ram_startup_trampoline); + +#define SECTION_text(_region_, _vma_, _lma_) \ + .text _vma_ : _lma_ \ + { _stext = ABSOLUTE(.); \ + PROVIDE (__stext = ABSOLUTE(.)); \ + *(.text*) *(.gnu.warning) *(.gnu.linkonce*) *(.init) \ + *(.glue_7) *(.glue_7t) \ + } > _region_ \ + _etext = .; PROVIDE (__etext = .); + +#define SECTION_fini(_region_, _vma_, _lma_) \ + .fini _vma_ : _lma_ \ + { FORCE_OUTPUT; *(.fini) } \ + > _region_ + +#define SECTION_rodata(_region_, _vma_, _lma_) \ + .rodata _vma_ : _lma_ \ + { FORCE_OUTPUT; *(.rodata*) } \ + > _region_ + +#define SECTION_rodata1(_region_, _vma_, _lma_) \ + .rodata1 _vma_ : _lma_ \ + { FORCE_OUTPUT; *(.rodata1) } \ + > _region_ + +#define SECTION_fixup(_region_, _vma_, _lma_) \ + .fixup _vma_ : _lma_ \ + { FORCE_OUTPUT; *(.fixup) } \ + > _region_ + +#define SECTION_gcc_except_table(_region_, _vma_, _lma_) \ + .gcc_except_table _vma_ : _lma_ \ + { FORCE_OUTPUT; *(.gcc_except_table) } \ + > _region_ + +#define SECTION_sram(_region_, _vma_, _lma_) \ + .sram _vma_ : _lma_ \ + { FORCE_OUTPUT; *(.sram*) } \ + > _region_ + +#define SECTION_data(_region_, _vma_, _lma_) \ + .data _vma_ : _lma_ \ + { __ram_data_start = ABSOLUTE (.); *(.data*) *(.data1) \ + . = ALIGN (8); \ + KEEP(*( SORT (.ecos.table.*))) ; \ + . = ALIGN (8); \ + __CTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.ctors*))) __CTOR_END__ = ABSOLUTE (.); \ + __DTOR_LIST__ = ABSOLUTE (.); KEEP (*(SORT (.dtors*))) __DTOR_END__ = ABSOLUTE (.); \ + *(.sdata*) \ + *(.eh_frame) \ + . = ALIGN (8); *(.2ram.*) \ + /* Global pointer stuff */ \ + . = ALIGN(8); _gp = . + 2048; __global = _gp; \ + _GOT_START_ = ABSOLUTE (.); *(.got) _GOT_END_ = ABSOLUTE (.); \ + _GOT_PLT_START_ = ABSOLUTE (.); *(.got_plt) _GOT_PLT_END_ = ABSOLUTE (.); \ + _GOT1_START_ = ABSOLUTE (.); *(.got1) _GOT1_END_ = ABSOLUTE (.); \ + _GOT2_START_ = ABSOLUTE (.); *(.got2) _GOT2_END_ = ABSOLUTE (.); \ + _DYNAMIC_ = ABSOLUTE (.); *(.dynamic) _DYNAMIC_ = ABSOLUTE (.); \ + } \ + > _region_ \ + __rom_data_start = LOADADDR (.data); \ + __ram_data_end = .; PROVIDE (__ram_data_end = .); _edata = .; PROVIDE (edata = .); \ + __rom_data_end = LOADADDR (.data) + SIZEOF(.data); + +#define SECTION_bss(_region_, _vma_, _lma_) \ + .bss _vma_ : _lma_ \ + { __bss_start = ABSOLUTE (.); \ + *(.scommon) *(.dynbss) *(.sbss) *(.sbss.*) *(.bss*) *(.bss.*) *(COMMON) \ + __bss_end = ABSOLUTE (.); } \ + > _region_ + +#define SECTIONS_END . = ALIGN(4); _end = .; PROVIDE (end = .); + +#include +#include CYGHWR_MEMORY_LAYOUT_LDI diff --git a/packages/hal/fr30/mb91301/v2_0/src/hal_diag.c b/packages/hal/fr30/mb91301/v2_0/src/hal_diag.c new file mode 100644 index 00000000..be392e29 --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/src/hal_diag.c @@ -0,0 +1,566 @@ +/*============================================================================= +// +// hal_diag.c +// +// HAL diagnostic output code +// +//============================================================================= +//####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): larsi +// Contributors:larsi +// Date: 2006-07-26 +// Purpose: HAL diagnostic output +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include + +#include // base types +#include // tracing macros +#include // assertion macros + +#include +#include + +#include + +#include + +#include +/*---------------------------------------------------------------------------*/ + +//#define CYG_KERNEL_DIAG_LCD +#define CYG_KERNEL_DIAG_SERIAL0 // For ROM start but see immediately below: + +#if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) +#undef CYG_KERNEL_DIAG_SERIAL0 +#undef CYG_KERNEL_DIAG_LCD +#define CYG_KERNEL_DIAG_CYGMON +#define CYG_KERNEL_DIAG_GDB + +#endif + +/*---------------------------------------------------------------------------*/ + +#if defined(CYG_KERNEL_DIAG_SERIAL0) || defined(CYG_KERNEL_DIAG_CYGMON) + +/*---------------------------------------------------------------------------*/ +// LED diag function +/* +void hal_diag_init_led(){ +// we only init the first 4 leds here + asm volatile( + "ldi:8 #0xf, r4;\n" + "ldi:20 #CYG_HAL_FR30_MB91360_DDRJ, r5;\n" + "stb r4, @r5;\n" + "ldi:20 #CYG_HAL_FR30_MB91360_PFRJ, r5;\n" + "stb r4, @r5;\n" + : : :"r4", "r5" + ); +} +*/ +// static cyg_uint8 leds = 0; + +void hal_diag_init(void){ + + // PJ2(SCK0) & PJ1(SOT0) output, PJ0(SIN0) input + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_DDRJ, 0x6); + // PJ2(SCK0) & PJ1(SOT0) & PJ0(SIN0) to peripheral operation + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_PFRJ, 0x7); + + // set up U-Timer + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_UTIMC0, 0x02); + // 115200 bps + HAL_WRITE_UINT16(CYG_HAL_FR30_MB91301_UTIMR0, 0x7); + + // setup UART + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_SCR0, 0x13); + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_SMR0, 0x30); +} + + +void hal_diag_led(cyg_uint8 leds) +{ + + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_PDRG, leds); + +} + +/*---------------------------------------------------------------------------*/ + +void hal_diag_write_char_serial0( char c) +{ + cyg_uint8 ssr; + + do + { + HAL_READ_UINT8( CYG_HAL_FR30_MB91301_SSR0 , ssr ); + } while (!(ssr & BIT3)); + + HAL_WRITE_UINT8( CYG_HAL_FR30_MB91301_SODR0, c ); + +} + +void hal_diag_write_hex_serial0(unsigned int c) +{ + unsigned char chr; + int i; + + hal_diag_write_char_serial0('0'); + hal_diag_write_char_serial0('x'); + + for(i = 28; i >= 0; i = i - 4) + { + chr = (c >> i) & 0xf; + if (chr >= 10) chr = chr + 55; /* for A-F */ + else chr = chr + 48; /* for 0-9 */ + hal_diag_write_char_serial0(chr); + } + hal_diag_write_char_serial0('\n'); + hal_diag_write_char_serial0('\r'); +} + + +void hal_diag_drain(void) +{ + cyg_uint8 ssr; + + do + { + HAL_READ_UINT8( CYG_HAL_FR30_MB91301_SSR0 , ssr ); + } while (!(ssr & BIT3)); +} + +void hal_diag_read_char_serial0(char *c) +{ + cyg_uint8 ssr; + + do + { + HAL_READ_UINT8( CYG_HAL_FR30_MB91301_SSR0 , ssr ); + } while (!(ssr & BIT4)); + + HAL_READ_UINT8( CYG_HAL_FR30_MB91301_SIDR0, *c ); + +} + + +#if defined(CYG_KERNEL_DIAG_CYGMON) +void hal_diag_dumb_write_char(char c) +#else +void hal_diag_write_char(char c) +#endif +{ +#ifdef CYG_KERNEL_DIAG_GDB + static char line[100]; + static int pos = 0; +// register volatile cyg_uint16 *volatile tty_status = SERIAL1_SR; + + // No need to send CRs + if( c == '\r' ) return; + + line[pos++] = c; + + if( c == '\n' || pos == sizeof(line) ) + { + + // Disable interrupts. This prevents GDB trying to interrupt us + // while we are in the middle of sending a packet. The serial + // receive interrupt will be seen when we re-enable interrupts + // later. + CYG_INTERRUPT_STATE oldstate; + HAL_DISABLE_INTERRUPTS(oldstate); + + while(1) + { + static char hex[] = "0123456789ABCDEF"; + cyg_uint8 csum = 0; + int i; + char c1; + + hal_diag_write_char_serial0('$'); + hal_diag_write_char_serial0('O'); + csum += 'O'; + for( i = 0; i < pos; i++ ) + { + char ch = line[i]; + char h = hex[(ch>>4)&0xF]; + char l = hex[ch&0xF]; + hal_diag_write_char_serial0(h); + hal_diag_write_char_serial0(l); + csum += h; + csum += l; + } + hal_diag_write_char_serial0('#'); + hal_diag_write_char_serial0(hex[(csum>>4)&0xF]); + hal_diag_write_char_serial0(hex[csum&0xF]); + + hal_diag_read_char_serial0( &c1 ); + + if( c1 == '+' ) break; + + { + extern void cyg_hal_user_break(CYG_ADDRWORD *regs); + extern cyg_bool cyg_hal_is_break(char *buf, int size); + if( cyg_hal_is_break( &c1 , 1 ) ) + cyg_hal_user_break( NULL ); + } + + break; + } + + pos = 0; + + // Wait for all data from serial line to drain + // and clear ready-to-send indication. + hal_diag_drain_serial0(); + + // And re-enable interrupts + HAL_RESTORE_INTERRUPTS( oldstate ); + + } +#else + hal_diag_write_char_serial0(c); +#endif +} + + +void hal_diag_read_char(char *c) +{ + for(;;) + { +#if defined(CYG_KERNEL_DIAG_GDB) && defined(CYGSEM_HAL_USE_ROM_MONITOR) + + typedef void rom_read_fn(char *c); + rom_read_fn *fn = ((rom_read_fn **)0x80000100)[62]; + + fn(c); + +#else + hal_diag_read_char_serial0(c); + +#endif + +#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) + if( *c == 3 ) + { + // Ctrl-C: breakpoint. + extern void breakpoint(void); + breakpoint(); + continue; + } +#elif defined(CYGSEM_HAL_USE_ROM_MONITOR) + if( *c == 3 ) + { + // Ctrl-C: breakpoint. + +// HAL_BREAKPOINT(_breakinst); + typedef void bpt_fn(void); + bpt_fn *bfn = ((bpt_fn **)0x80000100)[61]; + + bfn(); + continue; + } +#endif + + break; + } +} + +#endif // defined(CYG_KERNEL_DIAG_SERIAL0) || defined(CYG_KERNEL_DIAG_CYGMON) + + +#if defined(CYG_KERNEL_DIAG_CYGMON) // only + +/* This code has been imported from the BSP module. The definitions have + * been left as-is, even though there was scope for doing more, to avoid + * too much drift from the original sources + */ + +struct bsp_comm_procs { + void *ch_data; + void (*__write)(void *ch_data, const char *buf, int len); + int (*__read)(void *ch_data, char *buf, int len); + void (*__putc)(void *ch_data, char ch); + int (*__getc)(void *ch_data); + int (*__control)(void *ch_data, int func, ...); +}; + +// This is pointed to by entry BSP_NOTVEC_BSP_COMM_PROCS: +typedef struct { + int version; /* version number for future expansion */ + void *__ictrl_table; + void *__exc_table; + void *__dbg_vector; + void *__kill_vector; + struct bsp_comm_procs *__console_procs; + struct bsp_comm_procs *__debug_procs; + void *__flush_dcache; + void *__flush_icache; + void *__cpu_data; + void *__board_data; + void *__sysinfo; + int (*__set_debug_comm)(int __comm_id); + int (*__set_console_comm)(int __comm_id); + int (*__set_serial_baud)(int __comm_id, int baud); + void *__dbg_data; + void (*__reset)(void); + int __console_interrupt_flag; +} bsp_shared_t; + +/* + * Core Exception vectors. + */ +#define BSP_EXC_INT 0 +#define BSP_EXC_TLBMOD 1 +#define BSP_EXC_TLBL 2 +#define BSP_EXC_TLBS 3 +#define BSP_EXC_ADEL 4 +#define BSP_EXC_ADES 5 +#define BSP_EXC_IBE 6 +#define BSP_EXC_DBE 7 +#define BSP_EXC_SYSCALL 8 +#define BSP_EXC_BREAK 9 +#define BSP_EXC_ILL 10 +#define BSP_EXC_CPU 11 +#define BSP_EXC_OV 12 +#define BSP_EXC_TRAP 13 +#define BSP_EXC_VCEI 14 +#define BSP_EXC_FPE 15 +#define BSP_EXC_RSV16 16 +#define BSP_EXC_RSV17 17 +#define BSP_EXC_RSV18 18 +#define BSP_EXC_RSV19 19 +#define BSP_EXC_RSV20 20 +#define BSP_EXC_RSV21 21 +#define BSP_EXC_RSV22 22 +#define BSP_EXC_WATCH 23 +#define BSP_EXC_RSV24 24 +#define BSP_EXC_RSV25 25 +#define BSP_EXC_RSV26 26 +#define BSP_EXC_RSV27 27 +#define BSP_EXC_RSV28 28 +#define BSP_EXC_RSV29 29 +#define BSP_EXC_RSV30 30 +#define BSP_EXC_VCED 31 +/* tx39 debug exception */ +#define BSP_EXC_DEBUG 32 +#define BSP_EXC_TLB 33 +#define BSP_EXC_NMI 34 +/* + * Hack for eCos on tx39 to set an async breakpoint. + */ +#define BSP_VEC_BP_HOOK 35 + +#define BSP_EXC_XTLB 36 +#define BSP_EXC_CACHE 37 + +#define BSP_MAX_EXCEPTIONS 38 + +/* + * Another hack for tx39 eCos compatibility. + */ +#if defined(__CPU_R3900__) +#define BSP_VEC_MT_DEBUG 15 +#else +#define BSP_VEC_MT_DEBUG 38 +#endif + +#define BSP_VEC_STUB_ENTRY 39 +#define BSP_VEC_BSPDATA 40 +#define BSP_VEC_MAGIC 41 +#define BSP_VEC_IRQ_CHECK 42 + +#define BSP_VEC_PAD 43 +#define NUM_VTAB_ENTRIES 44 + + +#define BSP_MAGIC_VAL 0x55aa4321 + +#define SYS_interrupt 1000 + +// These vectors should be called with: +// +// k0 - Exception Number + +#define CYGMON_VECTOR_TABLE_BASE 0x80000100 +#define CYGMON_VECTOR_TABLE ((CYG_ADDRESS *)CYGMON_VECTOR_TABLE_BASE) + +#if 0 // UNUSED +static int +hal_bsp_set_debug_comm(int arg) +{ + bsp_shared_t *shared; + + shared = (bsp_shared_t *) + (CYGMON_VECTOR_TABLE[ BSP_VEC_BSPDATA ]); + + if (0 != shared->__set_debug_comm) { + return (*(shared->__set_debug_comm))(arg); + } + return 0; +} + +static int +hal_bsp_set_console_comm(int arg) +{ + bsp_shared_t *shared; + + shared = (bsp_shared_t *) + (CYGMON_VECTOR_TABLE[ BSP_VEC_BSPDATA ]); + + if (0 != shared->__set_console_comm) { + return (*(shared->__set_console_comm))(arg); + } + return 0; +} +#endif // 0 UNUSED + +static void bsp_trap(int trap_num); + +static int +hal_bsp_console_write(const void *p, int len) +{ + bsp_shared_t *shared; + struct bsp_comm_procs *com; + int magic; + + /*hal_bsp_set_console_comm(0);*/ + + /* If this is not a BSP-based CygMon, return 0 */ + magic = (int)(CYGMON_VECTOR_TABLE[ BSP_VEC_MAGIC ]); + if (magic != BSP_MAGIC_VAL) + return 0; + + shared = (bsp_shared_t *) + (CYGMON_VECTOR_TABLE[ BSP_VEC_BSPDATA ]); + + com = shared->__console_procs; + + if (0 != com) { + shared->__console_interrupt_flag = 0; + com->__write(com->ch_data, p, len); + if (shared->__console_interrupt_flag) { + /* debug interrupt; stop here */ + bsp_trap(SYS_interrupt); + } + + return 1; + } + return 0; +} + +static void +bsp_trap(int trap_num) +{ + asm("syscall\n"); +} + + +static void +hal_dumb_serial_write(const char *p, int len) +{ + int i; + for ( i = 0 ; i < len; i++ ) { + hal_diag_dumb_write_char(p[i]); + } +} +/* +void hal_diag_write_char(char c) +{ + static char line[100]; + static int pos = 0; + + // No need to send CRs + if( c == '\r' ) return; + + line[pos++] = c; + + if( c == '\n' || pos == sizeof(line) ) { + CYG_INTERRUPT_STATE old; + + // Disable interrupts. This prevents GDB trying to interrupt us + // while we are in the middle of sending a packet. The serial + // receive interrupt will be seen when we re-enable interrupts + // later. + + HAL_DISABLE_INTERRUPTS(old); + + if ( ! hal_bsp_console_write( line, pos ) ) + // then there is no function registered, just spew it out serial + hal_dumb_serial_write( line, pos ); + + pos = 0; + + // And re-enable interrupts + HAL_RESTORE_INTERRUPTS(old); + + } +}*/ + +int +hal_diag_irq_check(int vector) +{ + typedef int irq_check_fn(int irq_nr); + irq_check_fn *fn = (irq_check_fn *)(CYGMON_VECTOR_TABLE[ BSP_VEC_IRQ_CHECK ]); + int magic; + + + /* If this is not a BSP-based CygMon, return 0 */ + magic = (int)(CYGMON_VECTOR_TABLE[ BSP_VEC_MAGIC ]); + if (magic != BSP_MAGIC_VAL) + return 0; + +#if defined(CYGPKG_HAL_MIPS_TX3904) + /* convert vector to BSP irq number */ + if (vector == 16) + vector = 2; + else + vector += 3; +#endif + + return fn(vector); +} + +#endif // defined(CYG_KERNEL_DIAG_CYGMON) *only* + + +/*---------------------------------------------------------------------------*/ +/* End of hal_diag.c */ diff --git a/packages/hal/fr30/mb91301/v2_0/src/var_misc.c b/packages/hal/fr30/mb91301/v2_0/src/var_misc.c new file mode 100644 index 00000000..10f0aed6 --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/src/var_misc.c @@ -0,0 +1,125 @@ +//========================================================================== +// +// var_misc.c +// +// HAL implementation miscellaneous 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): larsi +// Contributors: +// Date: 2007-07-09 +// Purpose: HAL miscellaneous functions +// Description: This file contains miscellaneous functions provided by the +// HAL. +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include + +#include // Base types +#include // tracing macros +#include // assertion macros + +#include + +#include +/*------------------------------------------------------------------------*/ +// Array which stores the configured priority levels for the configured +// interrupts. + +/* this may be useful later when interrupt masking of internal interrupt + sources is implemented + +volatile CYG_BYTE hal_interrupt_level[CYGNUM_HAL_ISR_COUNT]; +*/ +/*------------------------------------------------------------------------*/ + +void hal_variant_init(void) +{ +} + +//-------------------------------------------------------------------------- +// Microsecond delay +// This uses reload timer 2, because timer 0 and 1 can cause DMA transfers +// and may be used by the application. +// Timer is initialized with 32 prescaler. If we need more precise delay +// this has to change. + +void hal_delay_us(cyg_int32 n){ +#define TIMER_TIME CYGHWR_HAL_FR30_MB91301_SYSTEM_CLOCK_MHZ * 1000000 / CYGHWR_HAL_FR30_MB91301_CLKP_DIVIDER / 32 + + unsigned int calc(unsigned long long n){ + return n * TIMER_TIME / 1000000; + } + + cyg_uint16 timer_status; + + n = 21;//calc(n); + // stop eventually running counter and initialize + HAL_WRITE_UINT16(CYG_HAL_FR30_DLY_TMCSR, 0x812); + + HAL_WRITE_UINT16(CYG_HAL_FR30_DLY_TMRLR, 0xFFFF); + while(n > 0xffff){ + // start counting + HAL_WRITE_UINT16(CYG_HAL_FR30_DLY_TMCSR, 0x813); + n = n - 0xffff; + // look for underflow + do { + HAL_READ_UINT16(CYG_HAL_FR30_DLY_TMCSR, timer_status); + } while (!(timer_status & BIT2)); + // clear underflow bit + HAL_WRITE_UINT16(CYG_HAL_FR30_DLY_TMCSR, 0x813); + } + // clear count enable bit + HAL_WRITE_UINT16(CYG_HAL_FR30_DLY_TMCSR, 0x810); + // set new remaining count value + HAL_WRITE_UINT16(CYG_HAL_FR30_DLY_TMRLR, n); + // start counting + HAL_WRITE_UINT16(CYG_HAL_FR30_DLY_TMCSR, 0x813); + // look for underflow + do { + HAL_READ_UINT16(CYG_HAL_FR30_DLY_TMCSR, timer_status); + } while (!(timer_status & BIT2)); + // clear underflow and count enable bits + HAL_WRITE_UINT16(CYG_HAL_FR30_DLY_TMCSR, 0x810); +} + +/*------------------------------------------------------------------------*/ +/* End of var_misc.c */ diff --git a/packages/hal/fr30/mb91301/v2_0/src/variant.S b/packages/hal/fr30/mb91301/v2_0/src/variant.S new file mode 100644 index 00000000..cf81809e --- /dev/null +++ b/packages/hal/fr30/mb91301/v2_0/src/variant.S @@ -0,0 +1,198 @@ +##============================================================================= +## +## variant.S +## +## FR30 MB91301 variant code +## +##============================================================================= +#####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): larsi +## Contributors:larsi +## Date: 2006-07-22 +## Purpose: FR30 MB91301 variant code +## Description: Variant specific code for MB91301 processor family. +## +## +## +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#include +#include + +#ifdef CYGPKG_KERNEL +# include +#endif + +#include + +#============================================================================== +# Vector table for storage in flash +# base address is 0x000FFC00, which stores the vector address for number 255 +# address 0x000FFFFC is the last vector, the reset vector, which is not +# alterable. Vectors 255 to 80 are used by the INT instruction and set to 0 +# here for now ... + +#ifndef CYGPKG_HAL_FR30_ROM_VECTORS_DEFINED +#define CYGPKG_HAL_FR30_ROM_VECTORS_DEFINED + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + + .section ".rom_vectors","ax" + + .balign 4 + .global hal_fr30_vector_table +hal_fr30_vector_table: + .rept 255-80 + 1 + .long 0x0 + .endr + .rept 79-67 + 1 + .long 0x0 + .endr + + .long 0x0 + .long 0x0 + .long 0x0 +# number 63 first interrupt source + .long hal_fr30_irq_63 + .long hal_fr30_irq_62 + .long hal_fr30_irq_61 + .long hal_fr30_irq_60 + .long hal_fr30_irq_59 + .long hal_fr30_irq_58 + .long hal_fr30_irq_57 + .long hal_fr30_irq_56 + .long hal_fr30_irq_55 + .long hal_fr30_irq_54 + .long hal_fr30_irq_53 + .long hal_fr30_irq_52 + .long hal_fr30_irq_51 + .long hal_fr30_irq_50 + .long hal_fr30_irq_49 + .long hal_fr30_irq_48 + .long hal_fr30_irq_47 + .long hal_fr30_irq_46 + .long hal_fr30_irq_45 + .long hal_fr30_irq_44 + .long hal_fr30_irq_43 + .long hal_fr30_irq_42 + .long hal_fr30_irq_41 + .long hal_fr30_irq_40 + .long hal_fr30_irq_39 + .long hal_fr30_irq_38 + .long hal_fr30_irq_37 + .long hal_fr30_irq_36 + .long hal_fr30_irq_35 + .long hal_fr30_irq_34 + .long hal_fr30_irq_33 + .long hal_fr30_irq_32 + .long hal_fr30_irq_31 + .long hal_fr30_irq_30 + .long hal_fr30_irq_29 + .long hal_fr30_irq_28 + .long hal_fr30_irq_27 + .long hal_fr30_irq_26 + .long hal_fr30_irq_25 + .long hal_fr30_irq_24 + .long hal_fr30_irq_23 + .long hal_fr30_irq_22 + .long hal_fr30_irq_21 + .long hal_fr30_irq_20 + .long hal_fr30_irq_19 + .long hal_fr30_irq_18 + .long hal_fr30_irq_17 + .long hal_fr30_irq_16 + .long hal_fr30_irq_15 + .long hal_fr30_exception_noerr_14 + .long hal_fr30_exception_noerr_13 + .long hal_fr30_exception_noerr_12 + .long hal_fr30_exception_noerr_11 + .long hal_fr30_exception_noerr_10 + .long hal_fr30_exception_noerr_9 + .long hal_fr30_exception_noerr_8 + .long hal_fr30_exception_noerr_7 + .long hal_fr30_exception_noerr_6 + .long hal_fr30_exception_noerr_5 + .long hal_fr30_exception_noerr_4 + .long hal_fr30_exception_noerr_3 + .long hal_fr30_exception_noerr_2 + +# mode vector (only the first of the four byte is relevant) + .byte 0x1 + .byte 0 + .byte 0 + .byte 0 + +# reset vector + .long _start + +#endif /*CYG_HAL_STARTUP_ROM || CYG_HAL_STARTUP_ROMRAM*/ +#endif /*CYGPKG_HAL_FR30_ROM_VECTORS_DEFINED*/ + +##----------------------------------------------------------------------------- +# Interrupt vector tables. +# These tables contain the isr, data and object pointers used to deliver +# interrupts to user code. + + .extern hal_default_isr + + .data + .balign 4 + + .globl hal_interrupt_handlers +hal_interrupt_handlers: + .rept CYGNUM_HAL_ISR_COUNT + .long hal_default_isr + .endr + + .globl hal_interrupt_data +hal_interrupt_data: + .rept CYGNUM_HAL_ISR_COUNT + .long 0 + .endr + + .globl hal_interrupt_objects +hal_interrupt_objects: + .rept CYGNUM_HAL_ISR_COUNT + .long 0 + .endr + +##----------------------------------------------------------------------------- +## end of variant.S + diff --git a/packages/hal/fr30/skmb91302/v2_0/ChangeLog b/packages/hal/fr30/skmb91302/v2_0/ChangeLog new file mode 100644 index 00000000..4de285c0 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/ChangeLog @@ -0,0 +1,66 @@ +2008-07-01 Lars Poeschel + + * src/platform.S: Startup routines for remapping the flash during + startup. Defined own rom_vector table. + * src/ser.c: Little updates that could cause problems after a reset with + wrong settings in the serial configuration registers. + * include/pkgconf/mlt_fr30_skmb91302_rom.h: + * include/pkgconf/mlt_fr30_skmb91302_rom.ldi: Reworked memory layout for + flash support. + + +2007-07-09 Lars Poeschel + + * src/platform.S: + * src/plf_misc.c: + * src/plf_stub.c: + * src/ser.c: + * misc/redboot_RAM.ecm: + * misc/redboot_ROM.ecm: + * include/pkgconf/mlt_fr30_skmb91302_ram.h: + * include/pkgconf/mlt_fr30_skmb91302_ram.ldi: + * include/pkgconf/mlt_fr30_skmb91302_rom.h: + * include/pkgconf/mlt_fr30_skmb91302_rom.ldi: + * include/platform.inc: + * include/plf_cache.h: + * include/plf_intr.h: + * include/plf_io.h: + * include/plf_stub.h: + * cdl/hal_fr30_skmb91302.cdl: Initial fr30 ecos port + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== + diff --git a/packages/hal/fr30/skmb91302/v2_0/cdl/hal_fr30_skmb91302.cdl b/packages/hal/fr30/skmb91302/v2_0/cdl/hal_fr30_skmb91302.cdl new file mode 100644 index 00000000..335ab5b3 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/cdl/hal_fr30_skmb91302.cdl @@ -0,0 +1,282 @@ +# ==================================================================== +# +# hal_fr30_skmb91302.cdl +# +# Fujitsu Starterkit MB91302 board HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2007 eCosCentric Ltd +## +## 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#### +# ==================================================================== + +cdl_package CYGPKG_HAL_FR30_MB91301_SKMB91302 { + display "Fujitsu Starterkit MB91302 board" + parent CYGPKG_HAL_FR30 + requires CYGPKG_HAL_FR30_MB91301 + define_header hal_fr30_skmb91302.h + include_dir cyg/hal + + description "Fujitsu Starterkit MB91302 board platform HAL + package should be used when targeting the actual hardware for + the Fujitsu Starterkit MB91302 board platform." + + compile platform.S plf_misc.c ser.c + implements CYGINT_HAL_DEBUG_GDB_STUBS + implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + implements CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + + define_proc { + puts $::cdl_header "#include " + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " + puts $::cdl_system_header "#define CYGBLD_HAL_VARIANT_H " + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + legal_values {"RAM" "ROM" "ROMRAM"} + default_value {"ROM"} + no_define + define -file system.h CYG_HAL_STARTUP + + description "Should the system run from RAM, ROM, or copy itself from ROM + and RAM and then run in RAM?" + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 2 + description "The MB91302 board has 3 serial ports. Only the first + 2 have mounted 9 pin connectors. The 3rd is not + connected and should therefore not be used." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT { + display "Default console channel." + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + calculated 0 + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description "This option chooses which port will be used to connect + to a host running GDB." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT + description " + This option chooses which port will be used for diagnostic output." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD { + display "Diagnostic serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 57600 + description " + This option selects the baud rate used for the diagnostic port. + Note: this should match the value chosen for the GDB port if the + diagnostic and GDB port are the same." + } + + cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD { + display "GDB serial port baud rate" + flavor data + legal_values 9600 19200 38400 57600 115200 + default_value 57600 + description " + This option selects the baud rate used for the diagnostic port. + Note: this should match the value chosen for the GDB port if the + diagnostic and GDB port are the same." + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + + description "Global build options including control over compiler + flags, linker flags and choice of toolchain." + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "fr30-unknown-elf" } + description "This option specifies the command prefix used + when invoking the build tools." + + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -finit-priority -fomit-frame-pointer" } + description "This option controls the global compiler flags + which are used to compile all packages by default. + Individual packages may define options which + override these global flags." + + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { " -g -nostdlib -Wl,--gc-sections -Wl,-static" } + description "This option controls the global linker flags. + Individual packages may define options which + override these global flags." + + } + + cdl_option CYGBLD_BUILD_GDB_STUBS { + display "Build GDB stub ROM image" + default_value 0 + requires { CYG_HAL_STARTUP == "ROM" } + requires CYGSEM_HAL_ROM_MONITOR + requires CYGBLD_BUILD_COMMON_GDB_STUBS + requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM + no_define + description "This option enables the building of the GDB + stubs for the board. The common HAL controls + takes care of most of the build process, but the + final conversion from ELF image to binary data is + handled by the platform CDL, allowing relocation + of the data if necessary." + + make -priority 320 { + /bin/gdb_module.srec : /bin/gdb_module.img + $(OBJCOPY) -O srec $< $@ + } + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { CYG_HAL_STARTUP == "RAM" ? "mlt_fr30_skmb91302_ram" : \ + "mlt_fr30_skmb91302_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { CYG_HAL_STARTUP == "RAM" ? "" : \ + "" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { CYG_HAL_STARTUP == "RAM" ? "" : \ + "" } + } + } + + cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor bool + default_value { CYG_HAL_STARTUP == "RAM" ? 1 : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Allow coexistence with ROM monitor (CygMon or GDB stubs) by + only initializing interrupt vectors on startup, thus leaving + exception handling to the ROM monitor." + } + + cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM" } + + description "Enable this option if this program is to be used as + a ROM monitor, i.e. applications will be loaded into + RAM on the board, and this ROM monitor may process + exceptions or interrupts generated from the + application. This enables features such as utilizing + a separate interrupt stack when exceptions are + generated." + + } + + cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { + display "Redboot HAL options" + flavor none + no_define + parent CYGPKG_REDBOOT + active_if CYGPKG_REDBOOT + description " + This option lists the target's requirements for a valid Redboot + configuration." + + cdl_option CYGBLD_BUILD_REDBOOT_BIN { + display "Build Redboot ROM binary image" + active_if CYGBLD_BUILD_REDBOOT + default_value 1 + no_define + description "This option enables the conversion of the Redboot ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + /bin/redboot.srec : /bin/redboot.elf + $(OBJCOPY) --strip-all $< $(@:.srec=.img) + $(OBJCOPY) -O srec $< $@ + } + } + } + +} diff --git a/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_ram.h b/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_ram.h new file mode 100644 index 00000000..5a2ddb64 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_ram.h @@ -0,0 +1,17 @@ +// eCos memory layout - Fri Oct 20 05:56:24 2000 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x2000000) +#define CYGMEM_REGION_ram_SIZE (0x800000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x03F00000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_ram.ldi b/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_ram.ldi new file mode 100644 index 00000000..fb34bea6 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_ram.ldi @@ -0,0 +1,28 @@ +// eCos memory layout - Fri Oct 20 05:56:24 2000 + +// This is a generated file - do not edit + +#include + +MEMORY +{ + ram : ORIGIN = 0x3F000, LENGTH = 0x1000 + sdram : ORIGIN = 0x2000000, LENGTH = 0x800000 +} + +SECTIONS +{ + SECTIONS_BEGIN +// SECTION_rodata1 (rom, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixed_vectors (sdram, 0x2000000, LMA_EQ_VMA) + SECTION_text (sdram, 0x2008000, LMA_EQ_VMA) + SECTION_fini (sdram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_rodata (sdram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_fixup (sdram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_gcc_except_table (sdram, ALIGN (0x4), LMA_EQ_VMA) + SECTION_data (sdram, ALIGN(0x4), FOLLOWING (.gcc_except_table)) +// SECTION_data (sdram, ALIGN(0x4), LMA_EQ_VMA) + SECTION_bss (sdram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x1000); + SECTIONS_END +} diff --git a/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_rom.h b/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_rom.h new file mode 100644 index 00000000..5a2ddb64 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_rom.h @@ -0,0 +1,17 @@ +// eCos memory layout - Fri Oct 20 05:56:24 2000 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x2000000) +#define CYGMEM_REGION_ram_SIZE (0x800000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x03F00000 - (size_t) CYG_LABEL_NAME (__heap1)) diff --git a/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_rom.ldi b/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_rom.ldi new file mode 100644 index 00000000..e6e6ed05 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/pkgconf/mlt_fr30_skmb91302_rom.ldi @@ -0,0 +1,32 @@ +// eCos memory layout - Fri Oct 20 05:56:24 2000 + +// This is a generated file - do not edit + +#include + +MEMORY +{ + ram : ORIGIN = 0x18000, LENGTH = 0x1000 + rom1 : ORIGIN = 0x80000, LENGTH = 0x7fc00 // Length = 511 kB + ints : ORIGIN = 0xFFC00, LENGTH = 0x400 + rom2 : ORIGIN = 0x1100000, LENGTH = 0x700000 + sdram : ORIGIN = 0x2000000, LENGTH = 0x800000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_rom_startup(rom1, 0x80000, LMA_EQ_VMA) + SECTION_ram_startup(ram, 0x18000, FOLLOWING(.rom_startup_trampoline)) + SECTION_rom_vectors (ints, 0xffc00 , LMA_EQ_VMA) + SECTION_text (rom2, 0x1100000, AT(0x100000)) + SECTION_fini (rom2, ALIGN (0x4), FOLLOWING (.text)) + SECTION_rodata (rom2, ALIGN (0x4), FOLLOWING (.fini)) + SECTION_fixup (rom2, ALIGN (0x4), FOLLOWING (.rodata)) + SECTION_gcc_except_table (rom2, ALIGN (0x4), FOLLOWING (.fixup)) + SECTION_fixed_vectors (sdram, 0x2000000, LMA_EQ_VMA) + SECTION_data (sdram, ALIGN(0x4), FOLLOWING (.gcc_except_table)) + SECTION_bss (sdram, ALIGN (0x4), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x1000); + SECTIONS_END +} diff --git a/packages/hal/fr30/skmb91302/v2_0/include/platform.inc b/packages/hal/fr30/skmb91302/v2_0/include/platform.inc new file mode 100644 index 00000000..cdeac624 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/platform.inc @@ -0,0 +1,188 @@ +#ifndef CYGONCE_HAL_PLATFORM_INC +#define CYGONCE_HAL_PLATFORM_INC +##============================================================================= +## +## platform.inc +## +## Fujitsu Starterkit MB91302 board assembler header file +## +##============================================================================= +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2007 eCosCentric Ltd. +## +## 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): larsi +## Contributors: +## Date: 2007-07-09 +## Purpose: Fujitsu Starterkit MB91302 board definitions. +## Description: This file contains various definitions and macros that are +## useful for writing assembly code for the skmb91302 board. +## Usage: +## #include +## +## +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#include + + +##------------------------------------------------------------------------------ +## ext Bus (memory controller) initialisation macros +## +## flash part + + +#define CYGPKG_HAL_FR30_FLASH_INIT_DEFINED +## flash init is empty for this platform because it is initialized in the +## special hal_fr30_ram_startup_trampoline to map flash to 0x1000000 +.macro hal_flash_init +.endm + +## and the following macro is used in the special +## hal_fr30_ram_startup_trampoline for flash initialisation +.macro hal_flash_init_from_ram + + ldi:20 #FR30_MB91301_ASR0, r10 ; CS0 area starts at + ldi:20 0x100, r0 ; 0x01000000 + sth r0, @r10 ; + + ldi:20 #FR30_MB91301_ACR0, r11 ; configuration parameters for CS0 + ldi:20 #0x7422, r1 ; 8MB(0x0-0x7FFFFF),16bit data bus, + sth r1, @r11 ; pre-fetch off, single access, + ; write enable, big endian, + ; normal access(asynchronous), + ; WR pin enabled for write, + ; wait by RDY pin disabled + + ldi:20 #FR30_MB91301_AWR0, r12 ; first access auto-wait 3cyc + ldi:20 #0x3378, r2 ; inpage access auto-wait 3cyc + sth r2, @r12 ; read/write idle 1cyc + ; write recover 3cyc + ; async write strobe outp enabled + ; CS delay enabled + ; CS read/write setup delay 0 + ; RD/WR -> CS hold extension 0 cyc + + ldi:20 #FR30_MB91301_PFR9, r13 ; WRn, BAAE, ASXE enable + ldi:8 #0x7e, r3 ; + stb r3, @r13 ; + +## following would chip select enable +## we only use cs0 until here, which is already set by reset + +.endm + + +## sdram part + + +#define CYGPKG_HAL_FR30_MEMC_INIT_DEFINED + +.macro hal_memc_init + +## The following instruction is without function. It is only to reference +## hal_fr30_rom_startup_trampoline, because when not referenced the linker +## does not include the file platform.S in the link. If somewhen some other +## referenced code appears in platform.S the instruction here can be deleted +## (including the surrounding macro)! + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + ldi:32 #hal_fr30_rom_startup_trampoline, r10 +#endif + + ldi:20 #FR30_MB91301_ASR6, r10 ; CS6 area starts at + ldi:20 0x200, r0 ; 0x02000000 + sth r0, @r10 ; + + ldi:20 #FR30_MB91301_ACR6, r11 ; configuration parameters for CS6 + ldi:20 #0x7868, r1 ; 64MB(0x2000000-0x27FFFFF),32bit data bus, + sth r1, @r11 ; pre-fetch on, single access(no burst), + ; write enable, big endian, + ; FCRAM setting + + ldi:20 #FR30_MB91301_AWR6, r12 ; first access auto-wait 1cyc ?? + ldi:20 #0x1159, r2 ; inpage access auto-wait 1cyc ?? + sth r2, @r12 ; read/write idle 1cyc ?? + ; write recover 1cyc ?? + ; async write strobe outp enabled ?? + ; CS delay disabled ?? + ; CS read/write setup delay 0 ?? + ; RD/WR -> CS hold extension 1 cyc ?? + ; see Hardware Manual page 156ff + + ldi:20 #FR30_MB91301_MCRA, r13 ; 8 columns, single write, + ldi:8 #0x07, r3 ; 4 banks for burst write, + stb r3, @r13 ; 4 active banks + + ldi:20 #FR30_MB91301_PFR9, r10 ; enable WRn, BAAE, ASXE, + ldi:8 #0x7e, r0 ; sysclk, MCKE, MCKEE + stb r0, @r10 + + ldi:20 #FR30_MB91301_PFR8, r11 ; enable WR3XE, WR2XE, WR1XE + ldi:8 #0xe0, r1 + stb r1, @r11 + + ldi:20 #FR30_MB91301_CSER, r12 ; switch on CS6 & CS0 + ldi:8 #0x41, r2 + stb r2, @r12 + + ldi:20 #FR30_MB91301_RCR, r13 ; power on SDRAM I/F + ldi:20 #0xe247, r3 ; 0xe247 -> 0xe24f + sth r3, @r13 + ldi:20 #0xe24f, r3 + sth r3, @r13 + +.endm + +#------------------------------------------------------------------------------ +## Vector table for storage. platform.S defines a vector table and wants to +## override the one from variant.S with this define + +#define CYGPKG_HAL_FR30_ROM_VECTORS_DEFINED + +#------------------------------------------------------------------------------ +# Difference of the flash memory from the linkers LMA (loadmemoryaddress) after +# the new mapping in (mapping is done in hal_fr30_ram_startup_trampoline). + +#define CYGPKG_HAL_FR30_LMA_OFFSET 0x1000000 + + + +#------------------------------------------------------------------------------ +#endif // ifndef CYGONCE_HAL_PLATFORM_INC +# end of platform.inc diff --git a/packages/hal/fr30/skmb91302/v2_0/include/plf_cache.h b/packages/hal/fr30/skmb91302/v2_0/include/plf_cache.h new file mode 100644 index 00000000..54f058b3 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/plf_cache.h @@ -0,0 +1,74 @@ +#ifndef CYGONCE_PLF_CACHE_H +#define CYGONCE_PLF_CACHE_H + +//============================================================================= +// +// plf_cache.h +// +// HAL cache control API +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): nickg +// Contributors: +// Date: 2007-07-09 +// Purpose: Cache control API +// Description: The macros defined here provide the HAL APIs for handling +// cache control operations. +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include + +#include + +//============================================================================= + +// Nothing here at present. + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_PLF_CACHE_H +// End of plf_cache.h + diff --git a/packages/hal/fr30/skmb91302/v2_0/include/plf_intr.h b/packages/hal/fr30/skmb91302/v2_0/include/plf_intr.h new file mode 100644 index 00000000..2a614a22 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/plf_intr.h @@ -0,0 +1,73 @@ +#ifndef CYGONCE_HAL_PLF_INTR_H +#define CYGONCE_HAL_PLF_INTR_H + +//========================================================================== +// +// plf_intr.h +// +// Fujitsu Starterkit MB91302 board interrupt and clock support +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd +// +// 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): nickg +// Contributors: +// Date: 2007-07-09 +// Purpose: Define Interrupt support +// Description: The macros defined here provide the HAL APIs for handling +// interrupts and the clock for the Fujitsu Starterkit MB91302 board. +// +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#include + +//-------------------------------------------------------------------------- +// Interrupt controller stuff. + + +//-------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_PLF_INTR_H +// End of plf_intr.h diff --git a/packages/hal/fr30/skmb91302/v2_0/include/plf_io.h b/packages/hal/fr30/skmb91302/v2_0/include/plf_io.h new file mode 100644 index 00000000..12df3df6 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/plf_io.h @@ -0,0 +1,67 @@ +#ifndef CYGONCE_PLF_IO_H +#define CYGONCE_PLF_IO_H + +//============================================================================= +// +// plf_io.h +// +// Platform specific IO support +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): hmt, jskov, nickg +// Contributors: +// Date: 2007-07-09 +// Purpose: Fujitsu Starterkit MB91302 board IO support macros +// Description: +// Usage: #include +// +// Note: Based on information in +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +#include // IO macros +#include // Interrupt vectors + +//----------------------------------------------------------------------------- +// end of plf_io.h +#endif // CYGONCE_PLF_IO_H diff --git a/packages/hal/fr30/skmb91302/v2_0/include/plf_stub.h b/packages/hal/fr30/skmb91302/v2_0/include/plf_stub.h new file mode 100644 index 00000000..5256385d --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/include/plf_stub.h @@ -0,0 +1,77 @@ +#ifndef CYGONCE_HAL_PLF_STUB_H +#define CYGONCE_HAL_PLF_STUB_H + +//============================================================================= +// +// plf_stub.h +// +// Platform header for GDB stub support. +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2007 eCosCentric Ltd. +// +// 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): jskov +// Contributors: +// Date: 2007-07-09 +// Purpose: Platform HAL stub support for Fujitsu Starterkit MB91302 boards. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//============================================================================= +#include + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include // CYG_UNUSED_PARAM + +#include // architecture stub support + + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +//----------------------------------------------------------------------------- +// Syscall support. +#ifdef CYGPKG_CYGMON +// Cygmon provides syscall handling for this board +#define SIGSYSCALL SIGSYS +extern int __get_syscall_num (void); +#endif + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_PLF_STUB_H +// End of plf_stub.h diff --git a/packages/hal/fr30/skmb91302/v2_0/misc/redboot_RAM.ecm b/packages/hal/fr30/skmb91302/v2_0/misc/redboot_RAM.ecm new file mode 100644 index 00000000..92c948cb --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/misc/redboot_RAM.ecm @@ -0,0 +1,67 @@ +cdl_savefile_version 1; +cdl_savefile_command cdl_savefile_version {}; +cdl_savefile_command cdl_savefile_command {}; +cdl_savefile_command cdl_configuration { description hardware template package }; +cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value }; + +cdl_configuration eCos { + description "" ; + hardware phytec91f364g ; + template redboot ; + package -hardware CYGPKG_HAL_FR30 current ; + package -hardware CYGPKG_HAL_FR30_MB91301_SKMB91302 current ; + package -template CYGPKG_HAL current ; + package -template CYGPKG_INFRA current ; + package -template CYGPKG_REDBOOT current ; +}; + +cdl_option CYGBLD_BUILD_GDB_STUBS { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM { + inferred_value 0 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS { + inferred_value 1 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT { + inferred_value 1 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT { + inferred_value 0 +}; + +cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + inferred_value 0 0 +}; + +cdl_component CYG_HAL_STARTUP { + user_value RAM +}; + +cdl_option CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + +#cdl_option CYGSEM_REDBOOT_FLASH_CONFIG { +# user_value 1 +#}; + +cdl_option CYGSEM_REDBOOT_BSP_SYSCALLS { + user_value 1 +}; + +cdl_option CYGBLD_REDBOOT_FLASH_BOOT_OFFSET { + inferred_value 0x1C00000 +}; diff --git a/packages/hal/fr30/skmb91302/v2_0/misc/redboot_ROM.ecm b/packages/hal/fr30/skmb91302/v2_0/misc/redboot_ROM.ecm new file mode 100644 index 00000000..5f97e66f --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/misc/redboot_ROM.ecm @@ -0,0 +1,68 @@ +cdl_savefile_version 1; +cdl_savefile_command cdl_savefile_version {}; +cdl_savefile_command cdl_savefile_command {}; +cdl_savefile_command cdl_configuration { description hardware template package }; +cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value }; +cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value }; + +cdl_configuration eCos { + description "" ; + hardware phytec91f364g ; + template redboot ; + package -hardware CYGPKG_HAL_FR30 current ; + package -hardware CYGPKG_HAL_FR30_MB91301_SKMB91302 current ; + package -template CYGPKG_HAL current ; + package -template CYGPKG_INFRA current ; + package -template CYGPKG_REDBOOT current ; +}; + +cdl_option CYGBLD_BUILD_GDB_STUBS { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT { + user_value 0 +}; + +cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM { + inferred_value 0 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS { + inferred_value 1 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT { + inferred_value 1 +}; + +cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT { + inferred_value 0 +}; + +cdl_option CYGSEM_HAL_ROM_MONITOR { + user_value 1 +}; + +cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + inferred_value 0 0 +}; + +cdl_component CYG_HAL_STARTUP { + user_value ROM +}; + +cdl_option CYGBLD_BUILD_REDBOOT { + user_value 1 +}; + + +cdl_option CYGSEM_REDBOOT_BSP_SYSCALLS { + user_value 1 +}; + +cdl_option CYGBLD_REDBOOT_FLASH_BOOT_OFFSET { + inferred_value 0x1C00000 +}; diff --git a/packages/hal/fr30/skmb91302/v2_0/src/platform.S b/packages/hal/fr30/skmb91302/v2_0/src/platform.S new file mode 100644 index 00000000..ebf6c0fc --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/src/platform.S @@ -0,0 +1,234 @@ +##============================================================================= +## +## platform.S +## +## Fujitsu Starterkit MB91302 platform code +## +##============================================================================= +#####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): larsi +## Contributors: +## Date: 2007-07-09 +## Purpose: Fujitsu Starterkit MB91302 platform code +## Description: Platform specific code for Fujitsu Starterkit MB91302 board. +## +## +## +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#include +#include + +#ifdef CYGPKG_KERNEL +# include +#endif + +#include + +##----------------------------------------------------------------------------- +## platforms special entry point. +## it copies the code from hal_fr30_ram_startup_trampoline until +## hal_fr30_ram_startup_trampoline_end to ram and jumps there. The code there +## is for mapping the flash to 0x1000000 and then jumping to real entry +## (_start). + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + + .section ".rom_startup_trampoline","ax" + + .balign 4 + .global hal_fr30_rom_startup_trampoline +hal_fr30_rom_startup_trampoline: + # disable interrupts and set priority to lowest (=disable) + andccr #0xef + stilm #0x0 + + ldi:32 #__rom_trampoline_start - 4, r11 + ldi:32 #__ram_trampoline_start - 4, r13 + ldi:32 #__rom_trampoline_end - 8, r12 +1: + add #0x4, r11 + add #0x4, r13 + ld @r11, r0 + cmp r12, r11 + ble:d 1b + st r0, @r13 + +## jump to the code in ram + ldi:32 #hal_fr30_ram_startup_trampoline, r0 + jmp @r0 + +#endif + +##----------------------------------------------------------------------------- +# Platform Initialization. +# This code is copied to a location in RAM on startup and is executed there. +# It maps the the FLASH chip to 0x1000000 and sets the TBR to the new location +# of the hardware vector table (hal_fr30_vector_table). So we can reach the full +# range of the FLASH and it can be used for flashfilesystem. After that it jumps +# to the real application. + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + + .section ".ram_startup_trampoline","ax" + + .balign 4 + .global hal_fr30_ram_startup_trampoline +hal_fr30_ram_startup_trampoline: + hal_flash_init_from_ram + +## map TBR to the new location (for vector tables) + ldi:32 #0x10ffc00, r0 + mov r0, tbr + +## jump to real startup + ldi:32 #_start, r0 + jmp @r0 + +#endif + + +#============================================================================== +# Vector table for storage in flash, version for skmb91302 platform. +# it differs from variants/archs version in that uses a different reset vector +# that points to the special startup procedure that jumps to the normal entry +# (_start) later. +# base address is 0x000FFC00 and 0x10ffc00 after remapping the flash. +# This address stores the vector address for number 255 +# address 0x000FFFFC (0x10ffffc) is the last vector, the reset vector, which +# is not alterable. Vectors 255 to 80 are used by the INT instruction and set +# to 0 here for now ... + + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) + + .section ".rom_vectors","ax" + + .balign 4 + .global hal_fr30_vector_table +hal_fr30_vector_table: + .rept 255-80 + 1 + .long 0x0 + .endr + .rept 79-67 + 1 + .long 0x0 + .endr + + .long 0x0 + .long 0x0 + .long 0x0 +# number 63 first interrupt source + .long hal_fr30_irq_63 + .long hal_fr30_irq_62 + .long hal_fr30_irq_61 + .long hal_fr30_irq_60 + .long hal_fr30_irq_59 + .long hal_fr30_irq_58 + .long hal_fr30_irq_57 + .long hal_fr30_irq_56 + .long hal_fr30_irq_55 + .long hal_fr30_irq_54 + .long hal_fr30_irq_53 + .long hal_fr30_irq_52 + .long hal_fr30_irq_51 + .long hal_fr30_irq_50 + .long hal_fr30_irq_49 + .long hal_fr30_irq_48 + .long hal_fr30_irq_47 + .long hal_fr30_irq_46 + .long hal_fr30_irq_45 + .long hal_fr30_irq_44 + .long hal_fr30_irq_43 + .long hal_fr30_irq_42 + .long hal_fr30_irq_41 + .long hal_fr30_irq_40 + .long hal_fr30_irq_39 + .long hal_fr30_irq_38 + .long hal_fr30_irq_37 + .long hal_fr30_irq_36 + .long hal_fr30_irq_35 + .long hal_fr30_irq_34 + .long hal_fr30_irq_33 + .long hal_fr30_irq_32 + .long hal_fr30_irq_31 + .long hal_fr30_irq_30 + .long hal_fr30_irq_29 + .long hal_fr30_irq_28 + .long hal_fr30_irq_27 + .long hal_fr30_irq_26 + .long hal_fr30_irq_25 + .long hal_fr30_irq_24 + .long hal_fr30_irq_23 + .long hal_fr30_irq_22 + .long hal_fr30_irq_21 + .long hal_fr30_irq_20 + .long hal_fr30_irq_19 + .long hal_fr30_irq_18 + .long hal_fr30_irq_17 + .long hal_fr30_irq_16 + .long hal_fr30_irq_15 + .long hal_fr30_exception_noerr_14 + .long hal_fr30_exception_noerr_13 + .long hal_fr30_exception_noerr_12 + .long hal_fr30_exception_noerr_11 + .long hal_fr30_exception_noerr_10 + .long hal_fr30_exception_noerr_9 + .long hal_fr30_exception_noerr_8 + .long hal_fr30_exception_noerr_7 + .long hal_fr30_exception_noerr_6 + .long hal_fr30_exception_noerr_5 + .long hal_fr30_exception_noerr_4 + .long hal_fr30_exception_noerr_3 + .long hal_fr30_exception_noerr_2 + +# mode vector (only the first of the four byte is relevant) + .byte 0x1 + .byte 0 + .byte 0 + .byte 0 + +# reset vector + .long hal_fr30_rom_startup_trampoline + +#endif /*CYG_HAL_STARTUP_ROM || CYG_HAL_STARTUP_ROMRAM*/ + + +##----------------------------------------------------------------------------- +## end of platform.S diff --git a/packages/hal/fr30/skmb91302/v2_0/src/plf_misc.c b/packages/hal/fr30/skmb91302/v2_0/src/plf_misc.c new file mode 100644 index 00000000..e3812636 --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/src/plf_misc.c @@ -0,0 +1,109 @@ +//========================================================================== +// +// plf_misc.c +// +// HAL platform miscellaneous 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): nickg, larsi +// Contributors: nickg, jlarmour, dmoseley +// Date: 2007-07-09 +// Purpose: HAL miscellaneous functions +// Description: This file contains miscellaneous functions provided by the +// HAL. +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS +#include + +#include // Base types +#include // tracing macros +#include // assertion macros + +#include // architectural definitions + +#include // Interrupt handling + +#include // Cache handling + +#include + + +/*------------------------------------------------------------------------*/ + +void hal_platform_init(void) +{ +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT) + // Set up eCos/ROM interfaces + hal_if_init(); +#endif + +#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ + (defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) || \ + defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs)) + +{ + extern CYG_ADDRESS hal_virtual_vector_table[32]; + void patch_dbg_syscalls( void * ); + patch_dbg_syscalls( (void *)(&hal_virtual_vector_table[0]) ); +} +#endif + +} + +/*------------------------------------------------------------------------*/ +/* Reset support */ + + +/*------------------------------------------------------------------------*/ +/* Syscall support */ +#ifdef CYGPKG_CYGMON +// Cygmon provides syscall handling for this board +#include +int __get_syscall_num (void) +{ + return SIGSYS; +} +#endif + + +/*------------------------------------------------------------------------*/ +/* End of plf_misc.c */ diff --git a/packages/hal/fr30/skmb91302/v2_0/src/plf_stub.c b/packages/hal/fr30/skmb91302/v2_0/src/plf_stub.c new file mode 100644 index 00000000..9432168e --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/src/plf_stub.c @@ -0,0 +1,96 @@ +//============================================================================= +// +// plf_stub.c +// +// Platform specific code for GDB stub support. +// +//============================================================================= +//####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): msalter, larsi +// Contributors: +// Date: 2007-07-09 +// Purpose: Platform specific code for GDB stub support. +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include + +#include // HAL IO macros +#include // diag output. FIXME + +#include +#include + +//----------------------------------------------------------------------------- +// Stub init + +void hal_plf_stub_init(void) +{ +// extern CYG_ADDRESS hal_virtual_vector_table[64]; + extern void init_thread_syscall( void *); + extern void install_async_breakpoint(void *epc); + void (*oldvsr)(void); + extern void __default_exception_vsr(void); + + // Ensure that the breakpoint VSR points to the default VSR. This will pass + // it on to the stubs. + HAL_VSR_SET( CYGNUM_HAL_VECTOR_BREAKPOINT, __default_exception_vsr, &oldvsr ); + + // Install async breakpoint handler into vector table. + hal_virtual_vector_table[35] = (CYG_ADDRESS)install_async_breakpoint; + +#if !defined(CYGPKG_KERNEL) && defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT) + // Only include this code if we do not have a kernel. Otherwise + // the kernel supplies the functionality for the app we are linked + // with. + + // Prepare for application installation of thread info function in + // vector table. + hal_virtual_vector_table[15] = 0; + init_thread_syscall( (void *)&hal_virtual_vector_table[15] ); +#endif +} + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +//----------------------------------------------------------------------------- +// End of plf_stub.c diff --git a/packages/hal/fr30/skmb91302/v2_0/src/ser.c b/packages/hal/fr30/skmb91302/v2_0/src/ser.c new file mode 100644 index 00000000..f7fea89c --- /dev/null +++ b/packages/hal/fr30/skmb91302/v2_0/src/ser.c @@ -0,0 +1,429 @@ +//============================================================================= +// +// ser.c +// +// Simple (polling) driver for the Fujitsu MB91302 on-chip serial port +// +//============================================================================= +//####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): larsi +// Contributors: +// Date: 2007-01-10 +// Description: Simple driver for the MB91302 internal serial port +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include CYGBLD_HAL_PLATFORM_H + +#include // SAVE/RESTORE GP macros +#include // IO macros +#include // interface API +#include // HAL_ENABLE/MASK/UNMASK_INTERRUPTS +#include // Helper functions +#include // CYG_ISR_HANDLED + +// We have no control over baud rate +// #if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==57600 +// #define CYG_DEV_SERIAL_BAUD_DIVISOR BAUD_57600 +// #endif + +// #ifndef CYG_DEV_SERIAL_BAUD_DIVISOR +// #error Missing/incorrect serial baud rate defined - CDL error? +// #endif + +#define CYG_HAL_FR30_MB91301_SMR0 0x63 +#define CYG_HAL_FR30_MB91301_SCR0 0x62 +#define CYG_HAL_FR30_MB91301_SIDR0 0x61 +#define CYG_HAL_FR30_MB91301_SODR0 0x61 +#define CYG_HAL_FR30_MB91301_SSR0 0x60 +#define CYG_HAL_FR30_MB91301_UTIM0 0x64 +#define CYG_HAL_FR30_MB91301_UTIMR0 0x64 +#define CYG_HAL_FR30_MB91301_DRCL 0x66 +#define CYG_HAL_FR30_MB91301_UTIMC0 0x67 + + +#define CYG_HAL_FR30_MB91301_SER0_BASE 0x60 +#define CYG_HAL_FR30_MB91301_SER1_BASE 0x68 +#define CYG_HAL_FR30_MB91301_SER2_BASE 0x70 + +#define CYG_HAL_FR30_MB91301_SMR_OFFSET 0x03 +#define CYG_HAL_FR30_MB91301_SCR_OFFSET 0x02 +#define CYG_HAL_FR30_MB91301_SIDR_OFFSET 0x01 +#define CYG_HAL_FR30_MB91301_SODR_OFFSET 0x01 +#define CYG_HAL_FR30_MB91301_SSR_OFFSET 0x00 +#define CYG_HAL_FR30_MB91301_UTIM_OFFSET 0x04 +#define CYG_HAL_FR30_MB91301_UTIMR_OFFSET 0x04 +#define CYG_HAL_FR30_MB91301_DRCL_OFFSET 0x06 +#define CYG_HAL_FR30_MB91301_UTIMC_OFFSET 0x07 + +#define CYG_HAL_FR30_MB91301_PDRG 0x10 +#define CYG_HAL_FR30_MB91301_DDRG 0x400 +#define CYG_HAL_FR30_MB91301_PFRG 0x410 +#define CYG_HAL_FR30_MB91301_PDRJ 0x13 +#define CYG_HAL_FR30_MB91301_DDRJ 0x403 +#define CYG_HAL_FR30_MB91301_PFRJ 0x413 + + +//----------------------------------------------------------------------------- +typedef struct { + cyg_uint8 base; + cyg_int32 msec_timeout; + int isr_vector; +} channel_data_t; + +static channel_data_t channels[2] = { + { CYG_HAL_FR30_MB91301_SER0_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART0_RX}, + { CYG_HAL_FR30_MB91301_SER1_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART1_RX}/*, + { CYG_HAL_FR30_MB91301_SER2_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART2_RX}*/ +}; + +//----------------------------------------------------------------------------- +// function for calculating and setting the baudrate + +static void cyg_hal_plf_serial_set_baudrate_internal(cyg_uint8 port, int baudrate){ + + float n, nn; + int t, tt; + + n = (CYGHWR_HAL_FR30_MB91301_SYSTEM_CLOCK_MHZ * 1000000 / CYGHWR_HAL_FR30_MB91301_CLKP_DIVIDER) / (float) (32 * baudrate) - 1; + nn = (CYGHWR_HAL_FR30_MB91301_SYSTEM_CLOCK_MHZ * 1000000 / CYGHWR_HAL_FR30_MB91301_CLKP_DIVIDER) / (float) (32 * baudrate) - 1.5; + + /* rounding */ + t = n; + tt = nn; + if ( (n-t) > (1 - (n-t)) ) t++; + if ( (nn-tt) > (1 - (nn-tt)) ) tt++; + + /* check which is better t or tt */ + + /* back calculation of baudrate from t and tt */ + n = (CYGHWR_HAL_FR30_MB91301_SYSTEM_CLOCK_MHZ * 1000000 / CYGHWR_HAL_FR30_MB91301_CLKP_DIVIDER) / (float) ((2*t+2) * 16); + nn = (CYGHWR_HAL_FR30_MB91301_SYSTEM_CLOCK_MHZ * 1000000 / CYGHWR_HAL_FR30_MB91301_CLKP_DIVIDER) / (float) ((2*tt+3) * 16); + + /* taking difference between wanted baudrate and back calculated br */ + if ((baudrate - n) < 0) + n = n - baudrate; + else + n = baudrate - n; + + if ((baudrate - nn) < 0) + nn = nn - baudrate; + else + nn = baudrate - nn; + + /* and finally take the best */ + if (n < nn){ + /* UCC1 = 0 */ + HAL_WRITE_UINT16(port + CYG_HAL_FR30_MB91301_UTIMR_OFFSET, t); + HAL_WRITE_UINT8(port + CYG_HAL_FR30_MB91301_UTIMC_OFFSET, 0x02); + } else { + /* UCC1 = 1 */ + HAL_WRITE_UINT16(port + CYG_HAL_FR30_MB91301_UTIMR_OFFSET, tt); + HAL_WRITE_UINT8(port + CYG_HAL_FR30_MB91301_UTIMC_OFFSET, 0x82); + } +} + +//----------------------------------------------------------------------------- +// The minimal init, get and put functions. All by polling. + +void +cyg_hal_plf_serial_init_channel(void* __ch_data) +{ + cyg_uint8 port; + cyg_uint8 value; + + port = ((channel_data_t*)__ch_data)->base; + + // set the port direction and function registers to serial + switch (port){ + case CYG_HAL_FR30_MB91301_SER0_BASE: + HAL_READ_UINT8(CYG_HAL_FR30_MB91301_DDRJ, value); + value |= 0x6; + value &= ~0x1; + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_DDRJ, value); + HAL_READ_UINT8(CYG_HAL_FR30_MB91301_PFRJ, value); + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_PFRJ, value | 0x7); + if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT == 0){ + cyg_hal_plf_serial_set_baudrate_internal(port, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD); + } else { + cyg_hal_plf_serial_set_baudrate_internal(port, CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD); + } + break; + + case CYG_HAL_FR30_MB91301_SER1_BASE: + HAL_READ_UINT8(CYG_HAL_FR30_MB91301_DDRJ, value); + value |= 0x30; + value &= ~0x8; + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_DDRJ, value); + HAL_READ_UINT8(CYG_HAL_FR30_MB91301_PFRJ, value); + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_PFRJ, value | 0x38); + if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT == 1){ + cyg_hal_plf_serial_set_baudrate_internal(port, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD); + } else { + cyg_hal_plf_serial_set_baudrate_internal(port, CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD); + } + break; +/* + case CYG_HAL_FR30_MB91301_SER2_BASE: + HAL_READ_UINT8(CYG_HAL_FR30_MB91301_DDRG, value); + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_DDRG, value | 0x40); + HAL_READ_UINT8(CYG_HAL_FR30_MB91301_PFRG, value); + HAL_WRITE_UINT8(CYG_HAL_FR30_MB91301_PFRG, value | 0x60); + break; +*/ + } + + // set up U-Timer +/* HAL_WRITE_UINT8(port + CYG_HAL_FR30_MB91301_UTIMC_OFFSET, 0x02); + // 115200 bps + HAL_WRITE_UINT16(port + CYG_HAL_FR30_MB91301_UTIMR_OFFSET, 0x7); + + cyg_hal_plf_serial_set_baudrate_internal(port, baudrate); +*/ + // setup UART + HAL_WRITE_UINT8(port + CYG_HAL_FR30_MB91301_SCR_OFFSET, 0x13); + HAL_WRITE_UINT8(port + CYG_HAL_FR30_MB91301_SMR_OFFSET, 0x30); +} + +void +cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 __ch) +{ + cyg_uint8 ssr; + cyg_uint8 port; + + port = ((channel_data_t*)__ch_data)->base; + // wait for tx rdy + do + { + HAL_READ_UINT8(port + CYG_HAL_FR30_MB91301_SSR_OFFSET, ssr); + } while (!(ssr & BIT3)); + // Now, write it + HAL_WRITE_UINT8( port + CYG_HAL_FR30_MB91301_SODR_OFFSET, __ch ); +} + +static cyg_bool +cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) +{ + cyg_uint8 ssr; + cyg_uint8 port; + + port = ((channel_data_t*)__ch_data)->base; + HAL_READ_UINT8(port + CYG_HAL_FR30_MB91301_SSR_OFFSET, ssr); + if (!(ssr & BIT4)) + return false; + + HAL_READ_UINT8(port + CYG_HAL_FR30_MB91301_SIDR_OFFSET, *ch); +// hal_diag_led(port); + return true; +} + +cyg_uint8 +cyg_hal_plf_serial_getc(void* __ch_data) +{ + cyg_uint8 ch; + + while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)); + return ch; +} + +static void +cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len) +{ + while(__len-- > 0) + cyg_hal_plf_serial_putc(__ch_data, *__buf++); +} + +static void +cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) +{ + while(__len-- > 0) + *__buf++ = cyg_hal_plf_serial_getc(__ch_data); +} + + +cyg_bool +cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) +{ + int delay_count; + channel_data_t* chan; + cyg_bool res; + + // Some of the diagnostic print code calls through here with no idea what the ch_data is. + // Go ahead and assume it is channels[0]. + if (__ch_data == 0) + __ch_data = (void*)&channels[0]; + + chan = (channel_data_t*)__ch_data; + + delay_count = chan->msec_timeout; // delay in 1000 us steps + for(;;) { + res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); + if (res || 0 == delay_count--) + break; + CYGACC_CALL_IF_DELAY_US(1000); + } + return res; +} + +static int +cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) +{ + static int irq_state = 0; + channel_data_t* chan; + int ret = 0; + cyg_uint8 port; + cyg_uint8 value; + + // Some of the diagnostic print code calls through here with no idea what the ch_data is. + // Go ahead and assume it is channels[0]. + if (__ch_data == 0) + __ch_data = (void*)&channels[0]; + + chan = (channel_data_t*)__ch_data; + + switch (__func) { + case __COMMCTL_IRQ_ENABLE: + irq_state = 1; + port = ((channel_data_t*)__ch_data)->base; + HAL_READ_UINT8(port + CYG_HAL_FR30_MB91301_SSR_OFFSET, value); + HAL_WRITE_UINT8(port + CYG_HAL_FR30_MB91301_SSR_OFFSET, value | BIT1); + break; + case __COMMCTL_IRQ_DISABLE: + ret = irq_state; + irq_state = 0; + port = ((channel_data_t*)__ch_data)->base; + HAL_READ_UINT8(port + CYG_HAL_FR30_MB91301_SSR_OFFSET, value); + HAL_WRITE_UINT8(port + CYG_HAL_FR30_MB91301_SSR_OFFSET, value & ~BIT1); + break; + case __COMMCTL_DBG_ISR_VECTOR: + ret = chan->isr_vector; + break; + case __COMMCTL_SET_TIMEOUT: + { + va_list ap; + + va_start(ap, __func); + + ret = chan->msec_timeout; + chan->msec_timeout = va_arg(ap, cyg_uint32); + + va_end(ap); + } + break; + case __COMMCTL_SETBAUD: + { + cyg_uint32 baud_rate; + cyg_uint16 n, nn; + va_list ap; + + va_start(ap, __func); + baud_rate = va_arg(ap, cyg_uint32); + va_end(ap); + port = ((channel_data_t*)__ch_data)->base; + cyg_hal_plf_serial_set_baudrate_internal(port, baud_rate); + } + break; + + case __COMMCTL_GETBAUD: + break; + default: + break; + } + return ret; +} + +static int +cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) +{ + *__ctrlc = 0; + return 0; +} + +static void +cyg_hal_plf_serial_init(void) +{ + hal_virtual_comm_table_t* comm; + int i, cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + +#define NUM_CHANNELS CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS + for (i = 0; i < NUM_CHANNELS; i++) { + + // Disable interrupts. + HAL_INTERRUPT_MASK(channels[i].isr_vector); + + // Init channels + cyg_hal_plf_serial_init_channel((void*)&channels[i]); + // Setup procs in the vector table + + // Set COMM callbacks for channel + CYGACC_CALL_IF_SET_CONSOLE_COMM(i); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[i]); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); + CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); + CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); + } + // Restore original console + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +void +cyg_hal_plf_comms_init(void) +{ + static int initialized = 0; + + if (initialized) + return; + + initialized = 1; + cyg_hal_plf_serial_init(); + +} + +//----------------------------------------------------------------------------- +// end of ser.c + diff --git a/packages/hal/synth/arch/v2_0/tests/ftok.c b/packages/hal/synth/arch/v2_0/tests/ftok.c new file mode 100644 index 00000000..91098eb9 --- /dev/null +++ b/packages/hal/synth/arch/v2_0/tests/ftok.c @@ -0,0 +1,84 @@ +/*================================================================= +// +// cache.c +// +// SYNTH ftok test +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005 Andrew Lunn +// +// 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): asl +// Contributors: asl +// Date: 05/11/2005 +//####DESCRIPTIONEND#### +*/ + +#ifndef HOST +#include +#include + +#define printf diag_printf +#define ftok cyg_hal_sys_ftok + +#else + +#include +#include +#include +#endif + +int main(void) +{ + printf("ftok(\"/etc/passwd\",0x12)) = 0x%8x\n", + ftok("/etc/passwd",0x12)); + + printf("ftok(\"/etc/passwd\",0x72)) = 0x%8x\n", + ftok("/etc/passwd",0x72)); + + printf("ftok(\"/boot/vmlinuz\",0x72)) = 0x%8x\n", + ftok("/boot/vmlinuz",0x72)); + + printf("ftok(\"/boot/vmlinuz\",0x12)) = 0x%8x\n", + ftok("/boot/vmlinuz",0x12)); + + return 0; +} + +#ifndef HOST + +externC void +cyg_start( void ) +{ + main(); +} +#endif diff --git a/packages/io/can/v2_0/doc/can.sgml b/packages/io/can/v2_0/doc/can.sgml new file mode 100644 index 00000000..5914aaea --- /dev/null +++ b/packages/io/can/v2_0/doc/can.sgml @@ -0,0 +1,1980 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +CAN Support + + +Overview + +
+Description + + +The Controller Area Network, CAN, is a multicast shared, differential +serial bus standard especially suited for networking "intelligent" +devices as well as sensors and actuators within a system or sub-system. +The protocol was originally developed in the 1980s by Robert Bosch GmbH +aiming at automotive applications. Nowadays CAN has gained widespread use +and is used in industrial automation as well as in automotive, mobile +machines and in many embedded control applications. + + + +The CAN protocol is defined by the ISO 11898-1 standard. The physical layer +uses differential transmission on a twisted pair wire. CAN uses a +non-destructive bit-wise arbitration to control access to the bus. + + + +There is no explicit address in the messages because in CAN networks there +is no addressing of subscribers or stations, but instead, each message carries +a prioritized identifier. A transmitter sends a message to all CAN nodes +(broadcasting). The identifier may serve as an identification of the contents +of the message and also determines the priority that the message enjoys in +competition for bus access. A node decides on the basis of this identifier +received whether it should process the message or not. + + + +The CAN messages are small (at most eight data bytes) and are protected +by a checksum. Each CAN message consists of an 11 bit message ID, up to 8 +bytes of data and, a CRC checksum and a number of control bits. These +short messages ensure a robust transfer of data in electromagnetically +noisy environments. An extended version of the CAN frame supports 29 bit +message identifiers. + + + +Basically there are two different operational modes for CAN receivers - +FullCAN and BasicCAN. The difference between these two modes is the +Object Storage function. The BasicCAN architecture is quite similar to a +simple UART. A BasicCAN device has typically one transmit buffer and two +receive buffers. The CAN chip handles only the transmitting and receiving +of the data (and the error handling) and so most of the manipulation of the +data has to be done by the CPU. The CPU has to request the transmitting or +acknowledge the receiving of the data through the interrupt flags. This will +burden the CPU and take up much of the CPU time. + + + +The FullCAN architecture is more suitable for high-speed performance. It +has its own storage area on chip and works with a number of message buffers +or message boxes. The CAN controller has its own Acceptance Filtering Mask +on chip. It can thus determine which frames are to be received by examining +the identifiers. The CPU in this case will only receive the valid (wanted) +frames and hence improve the performance of the CPU. + + + +You can find more information at the +CAN in Automation website. + + +
+ +
+eCos Support for CAN + + +The eCos CAN subsystem supports the BasicCAN and FullCAN mode. The architecture +and the interface of the eCos CAN driver is quite similar to the eCos serial +driver and supports the same interface. + + + +The eCos CAN support for any given platform is spread over a number of different +packages: + + + + + + +This package, CYGPKG_IO_CAN, exports a generic +device independent CAN I/O API for accessing devices attached to a CAN +network. This API handles issues such as locking between threads. The +package does not contain any hardware-specific code. Instead it will +call into a CAN device driver to handle the hardware device +access. This package also defines the inderface that such hardware +drivers should provide. + + + + +Each CAN device will have its own device driver, which is implemented +as a separate package, for example +CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN. For devices that may +be attached to a variety of different boards the device driver will be +generic and a second platform specific package will be used to customize +it to each platform. For devices that are associated with a specific +chipset, only a single package may be present. + + + + + +Typically all appropriate packages will be loaded automatically when +you configure eCos for a given platform. If the application does not use +any of the CAN I/O facilities, directly or indirectly, then linker garbage +collection should eliminate all unnecessary code and data. All necessary +initialization should happen automatically. However the exact details may +depend on the platform, so the platform HAL documentation should be +checked for further details. + + + +There is an important exception to this: if the CAN devices are attached +to an expansion connector, such as PCI, then the platform HAL will not +know about these devices. Instead the necessary packages will need to be +added explicitly during configuration. + +
+
+ + +User API + + +The CAN driver uses the standard eCos I/O API functions. All functions +except cyg_io_lookup() require an I/O "handle". + + + +All functions return a value of the type Cyg_ErrNo. +If an error condition is detected, this value will be negative and the +absolute value indicates the actual error, as specified in +cyg/error/codes.h. The only other legal return values +will be ENOERR, -EINTR and +-EAGAIN. All other function arguments are pointers +(references). This allows the drivers to pass information efficiently, +both into and out of the driver. The most striking example of this is the +len value passed to the read and write functions. +This parameter contains the desired length of data on input to the +function and the actual transferred length on return. + + + +// Lookup a CAN device and return its handle +Cyg_ErrNo cyg_io_lookup( + const char *name, + cyg_io_handle_t *handle ) + + + +This function maps a CAN device name onto an appropriate handle. If the +named device is not in the system, then the error +-ENOENT is returned. If the device is found, then +the handle for the device is returned by way of the handle pointer +*handle. + + + +// Send a CAN message +Cyg_ErrNo cyg_io_write( + cyg_io_handle_t handle, + const void *buf, + cyg_uint32 *len ) + + + +This function sends one single CAN message (not a buffer of CAN messages) +to a device. The size of data to send is contained in +*len and the actual size sent will be returned in +the same place. + + + +// Read one CAN event from device +Cyg_ErrNo cyg_io_read( + cyg_io_handle_t handle, + void *buf, + cyg_uint32 *len ) + + + +This function receives one single CAN event from a device. The desired size +of data to receive is contained in *len and the +actual size obtained will be returned in the same place. + + + +// Read configuration of a CAN device +Cyg_ErrNo cyg_io_get_config( + cyg_io_handle_t handle, + cyg_uint32 key, + void *buf, + cyg_uint32 *len ) + + + +This function is used to obtain run-time configuration about a +device. The type of information retrieved is specified by the +key. The data will be returned in the given +buffer. The value of *len should contain the +amount of data requested, which must be at least as large as the size +appropriate to the selected key. The actual size of data retrieved is +placed in *len. The appropriate key values +are all listed in the file <cyg/io/config_keys.h>. + + + +// Change configuration of a CAN device +Cyg_ErrNo cyg_io_set_config( + cyg_io_handle_t handle, + cyg_uint32 key, + const void *buf, + cyg_uint32 *len ) + + + +This function is used to manipulate or change the run-time +configuration of a device. The type of information is specified by the +key. The data will be obtained from the given +buffer. The value of *len should contain the +amount of data provided, which must match the size appropriate to the +selected key. The appropriate key values are all listed in the file +<cyg/io/config_keys.h>. + + + + +CAN driver details + + +Allow applications and other packages to access CAN devices. + + +
+Description + + +A raw CAN driver is is provided as a standard part of the eCos system. + + + +Use the include file <cyg/io/canio.h> for this driver. + + + +The CAN driver is capable of sending single CAN messages to a device and +receiving single CAN events from a CAN device. Controls are provided to +configure the actual hardware, but there is no manipulation of the data by +this driver. + + + +There may be many instances of this driver in a given system, one for each +CAN channel. Each channel corresponds to a physical device and there will +typically be a device module created for this purpose. The device modules +themselves are configurable, allowing specification of the actual hardware +details. + +
+ +
+API Details + +
+cyg_io_write + + +cyg_io_write(handle, buf, len) + + + +To transmit a message an application must fill a cyg_can_message +buffer and call cyg_io_write(). +This function sends one single CAN message (not a buffer of CAN messages) +to a device. The size of data to send is contained in *len +and the actual size sent will be returned in the same place. A pointer to a +cyg_can_message is contained in *buf. +The driver maintains a buffer to hold the data. The size of the intermediate +buffer is configurable within the interface module. The data is not modified +at all while it is being buffered. On return, *len +contains the amount of characters actually consumed - that means +*len always contains +sizeof(cyg_can_message). + + + +It is possible to configure the write call to be blocking (default) or +non-blocking. Non-blocking mode requires both the configuration option +CYGOPT_IO_CAN_SUPPORT_NONBLOCKING to be enabled, and +the specific device to be set to non-blocking mode for writes +(see cyg_io_set_config()). In blocking mode, the +call will not return until there is space in the buffer and the content +of the CAN message has been consumed. In non-blocking mode, if there is +no space in buffer for the CAN message, -EAGAIN is +returned and the caller must try again. + + + +It is possible to configure the write call to be non-blocking with timeout. +None-blocking mode with timeout requires the configuration option +CYGOPT_IO_CAN_SUPPORT_NONBLOCKING and +CYGOPT_IO_CAN_SUPPORT_TIMEOUTS to be enabled, requires +the eCos kernel package to be included and the specific device to be set +to non-blocking mode for writes (see cyg_io_set_config() +). +In non-blocking mode with timeouts, if there is no space in buffer for the +CAN message, the driver waits a certain amount of time (the timeout time) +for space in the buffer. If there is still no space in buffer after +expiration of the timeout time, -EINTR is returned and +the caller must try again. + + + +If a message was sucessfully sent, the function returns ENOERR. + +
+ +
+CAN Messages + + +The CAN driver uses cyg_can_message structures to +pass messages between the application and the CAN driver. The type +cyg_can_message provides a device independent type of CAN message. +Before calling the write function this message should be setup properly. + + + +typedef struct can_message +{ + cyg_uint32 id; + cyg_uint8 data[8]; + cyg_can_id_type ext; + cyg_can_frame_type rtr; + cyg_uint8 dlc; +} cyg_can_message; + + + +The structure contains the following fields: + + + + + cyg_uint32 id + +Message ID. This is the ID to be transmitted with the message, or the +ID received. If the ext field is set, then +this will contain a 29 bit ID, otherwise it will contain an 11 bit ID. + + + + cyg_uint32 data + +Message data. Only the first dlc bytes of +data are valid. If the rtr field is set, +then the contents of this field are ignored. + + + + cyg_can_id_type ext + +Extended ID. If this field is CYGNUM_CAN_ID_EXT then the +id field contains a 29 bit extended ID. If it +contains CYGNUM_CAN_ID_STD then the ID is 11 bits. + + + + cyg_can_frame_type rtr + +Remote Transmission Request. If this field contains +CYGNUM_CAN_FRAME_RTR then the RTR bit on the message +will be set and the data field will be ignored. +If the field contains CYGNUM_CAN_FRAME_DATA then a +normal data frame will be send. + + + + cyg_uint8 dlc + +The length of the data carried in the message. This can range from +zero to 8. In a message with the rtr field set, +this indicates the size of data being requested. + + + + + +Example code for sending one single CAN message: + + + +cyg_can_message tx_msg; +cyg_uint32 len; +Cyg_ErrNo ret; + +tx_msg.id = 0x100; +tx_msg.ext = CYGNUM_CAN_ID_EXT; +tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; +tx_msg.dlc = 1; +tx_msg.data[0] = 0xF1; + +len = sizeof(tx_msg); +ret = cyg_io_write(hDrvCAN, &tx_msg, &len); + +
+ +
+cyg_io_read + + +cyg_io_read(handle, buf, len) + + + +To receive a message the application calls cyg_can_recv(). +This function receives one single event from a device. The desired size +of data to receive is contained in *len and the +actual size obtained will be returned in the same place. A pointer to +a cyg_can_event is contained in *buf. +No manipulation of the data is performed before being transferred. +Again, this buffering is completely configurable. On return, +*len contains sizeof(cyg_can_event). + + + +It is possible to configure the read call to be blocking (default) or +non-blocking. Non-blocking mode requires both the configuration option +CYGOPT_IO_CAN_SUPPORT_NONBLOCKING to be enabled, +and the specific device to be set to non-blocking mode for reads +(see cyg_io_set_config()). In blocking mode, +the call will not return until one single CAN event has been read. +In non-blocking mode, if there is no CAN event in buffer, the call +returns immediately with -EAGAIN and the caller must +try again. + + + +It is possible to configure the write call to be non-blocking with timeout. +None-blocking mode with timeout requires the configuration option +CYGOPT_IO_CAN_SUPPORT_NONBLOCKING and +CYGOPT_IO_CAN_SUPPORT_TIMEOUTS to be enabled, +requires the eCos kernel package to be included and the specific device +to be set to non-blocking mode for reads (see +cyg_io_set_config()). In non-blocking mode with timeouts, +if there is no CAN event in receive buffer, the driver waits a certain amount +of time (the timeout time) for a CAN event to arrive. If there is still no +CAN event in buffer after expiration of the timeout time, -EINTR +is returned and the caller must try again. + + + +If a event was sucessfully received, the function returns ENOERR. + +
+ + +
+CAN Events + + +The CAN driver uses cyg_can_event structures to +pass events from hardware device driver to the generic CAN driver. +A cyg_can_event provides a generic device +independent type for handling CAN events that may occur. + + + +typedef struct cyg_can_event_st +{ + cyg_uint32 timestamp; + cyg_can_message msg; + cyg_uint16 flags; +} cyg_can_event; + + + +The structure contains the following fields: + + + + + cyg_uint32 timestamp + +If the hardware CAN device driver supports timestamps then this field may +contain a timestamp value for an event that occured. + + + + cyg_can_message msg + +CAN message. The msg field contains a CAN message if an RX or TX event +occured. If another type of event occured, +the data field of +the msg may contain additional event +specific data. + + + + cyg_uint16 flags + +Event flags. The flags field contains 16 bits that +indicate which kind of events occured. + + + + + +The following events are supported and after receiving an event the +application should check the flag field against these values: + + + +typedef enum +{ + CYGNUM_CAN_EVENT_RX = 0x0001, // message received + CYGNUM_CAN_EVENT_TX = 0x0002, // message transmitted + CYGNUM_CAN_EVENT_WARNING_RX = 0x0004, // (TEC) reached warning level (>96) + CYGNUM_CAN_EVENT_WARNING_TX = 0x0008, // (REC) reached warning level (>96) + CYGNUM_CAN_EVENT_ERR_PASSIVE = 0x0010, // CAN "error passive" occured + CYGNUM_CAN_EVENT_BUS_OFF = 0x0020, // CAN "bus off" error occured + CYGNUM_CAN_EVENT_OVERRUN_RX = 0x0040, // overrun in RX queue or hardware + CYGNUM_CAN_EVENT_OVERRUN_TX = 0x0080, // overrun in TX queue occured + CYGNUM_CAN_EVENT_CAN_ERR = 0x0100, // a CAN bit or frame error occured + CYGNUM_CAN_EVENT_LEAVING_STANDBY = 0x0200, // CAN hardware leaves standby + CYGNUM_CAN_EVENT_ENTERING_STANDBY = 0x0400, // CAN hardware enters standby + CYGNUM_CAN_EVENT_ARBITRATION_LOST = 0x0800, // arbitration lost + CYGNUM_CAN_EVENT_FILTER_ERR = 0x1000, // CAN message filter / acceptance filter error + CYGNUM_CAN_EVENT_PHY_FAULT = 0x2000, // General failure of physical layer + CYGNUM_CAN_EVENT_PHY_H = 0x4000, // Fault on CAN-H (Low Speed CAN) + CYGNUM_CAN_EVENT_PHY_L = 0x8000, // Fault on CAN-L (Low Speed CAN) +} cyg_can_event_flags; + + + +Often the flags field will contain only one single set flag. But it is +possible that a number of flags is set and so the flag field should always +be checked by a receiver. I.e. if the CYGNUM_CAN_EVENT_RX +is set then also the CYGNUM_CAN_EVENT_OVERRUN_RX +may be set if the received message caused an RX overrun. + + + +The internal receive buffers of the CAN device driver are circular buffers. +That means that even if the buffers are completely filled new messages +will be received. In this case the newest message will always overwrite +the oldest message in receive buffer. If this happens the +CYGNUM_CAN_EVENT_OVERRUN_RX flag will be set for this +new message that caused overwriting of the old one. The +CYGNUM_CAN_EVENT_OVERRUN_RX flag will be set also if +a overrun occures in hardware message buffers of the CAN device. + + + +Example code for receiving one single CAN event: + + + +cyg_can_event rx_event; +cyg_uint32 len; +Cyg_ErrNo ret; + +len = sizeof(rx_event); +ret = cyg_io_read(hDrvCAN, &rx_event, &len); + +if (ENOERR == ret) +{ + if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + { + // handle RX event + } + + if (rx_event.flags & ~CYGNUM_CAN_EVENT_RX) + { + // handle other events + } +} +else if (-EINTR == ret) +{ + // handle timeout +} + +
+ + +
+cyg_io_get_config + + +cyg_io_get_config(handle, key, buf, len) + + + +This function is used to obtain run-time configuration about a device. +The type of information retrieved is specified by the key. +The data will be returned in the given buffer. The value of +*len should contain the amount of data requested, +which must be at least as large as the size appropriate to the selected +key. The actual size of data retrieved is placed +in *len. The appropriate key values are all listed +in the file <cyg/io/config_keys.h>. + + + +The following config keys are currently supported: + + + +CYG_IO_GET_CONFIG_READ_BLOCKING +CYG_IO_GET_CONFIG_WRITE_BLOCKING +CYG_IO_GET_CONFIG_CAN_INFO +CYG_IO_GET_CONFIG_CAN_BUFFER_INFO +CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO +CYG_IO_GET_CONFIG_CAN_TIMEOUT +CYG_IO_GET_CONFIG_CAN_HDI +CYG_IO_GET_CONFIG_CAN_STATE + +
+ +
+cyg_io_set_config + + +cyg_io_set_config(handle, key, buf, len) + + + +This function is used to manipulate or change the run-time configuration +of a device. The type of information is specified by the key. +The data will be obtained from the given buffer. The value of +*len should contain the amount of data provided, +which must match the size appropriate to the selected key. +The appropriate key values are all listed in the file +<cyg/io/config_keys.h>. + + + +The following config keys are currently supported: + + + +CYG_IO_SET_CONFIG_READ_BLOCKING +CYG_IO_SET_CONFIG_WRITE_BLOCKING +CYG_IO_SET_CONFIG_CAN_INFO +CYG_IO_SET_CONFIG_CAN_OUTPUT_DRAIN +CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH +CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH +CYG_IO_SET_CONFIG_CAN_TIMEOUT +CYG_IO_SET_CONFIG_CAN_MSGBUF +CYG_IO_SET_CONFIG_CAN_MODE +CYG_IO_SET_CONFIG_CAN_ABORT +CYG_IO_SET_CONFIG_CAN_CALLBACK + +
+
+ +
+Runtime Configuration + + +Runtime configuration is achieved by exchanging data structures with the +driver via the cyg_io_set_config() and +cyg_io_get_config() functions. + + +
+Device configuration + + +typedef struct cyg_can_info_st { + cyg_can_baud_rate_t baud; +} cyg_can_info_t; + + + +Device configuration is achieved by by exchanging +cyg_can_info_t data structures with the driver +via the cyg_io_set_config() and +cyg_io_get_config() functions using the config keys +CYG_IO_GET_CONFIG_CAN_INFO and +CYG_IO_SET_CONFIG_CAN_INFO. +The field baud contains a baud rate selection. +This must be one of the following values: + + + +CYGNUM_CAN_KBAUD_10 +CYGNUM_CAN_KBAUD_20 +CYGNUM_CAN_KBAUD_50 +CYGNUM_CAN_KBAUD_100 +CYGNUM_CAN_KBAUD_125 +CYGNUM_CAN_KBAUD_250 +CYGNUM_CAN_KBAUD_500 +CYGNUM_CAN_KBAUD_800 +CYGNUM_CAN_KBAUD_1000 + +
+ +
+Timeout configuration + + +typedef struct cyg_can_timeout_info_st +{ + cyg_uint32 rx_timeout; + cyg_uint32 tx_timeout; +} cyg_can_timeout_info_t; + + + +Timeout configuration is achieved by by exchanging +cyg_can_timeout_info_t data structures with the +driver via the cyg_io_set_config() and +cyg_io_get_config() functions using the config keys +CYG_IO_SET_CONFIG_CAN_TIMEOUT and +CYG_IO_SET_CONFIG_CAN_TIMEOUT. + + + + + cyg_uint32 rx_timeout + +Timeout for cyg_io_read calls. + + + + cyg_uint32 tx_timeout + +Timeout for cyg_io_write calls. + + + + + +Timeout runtime configuration is supported if the configuration options +CYGOPT_IO_CAN_SUPPORT_NONBLOCKING +and CYGOPT_IO_CAN_SUPPORT_TIMEOUTS are enabled. + +
+ +
+Reading buffer configuration + + +typedef struct cyg_can_buf_info_st +{ + cyg_int32 rx_bufsize; + cyg_int32 rx_count; + cyg_int32 tx_bufsize; + cyg_int32 tx_count; +} cyg_can_buf_info_t; + + + +CYG_IO_GET_CONFIG_CAN_BUFFER_INFO - This function +retrieves the current state of the software buffers in the CAN drivers. +For the transmit buffer it returns the the total number of +cyg_can_message objects in buffer and the current number of +cyg_can_message objects occupied in the buffer. +For the receive buffer it returns the total number of +cyg_can_event objects in receive buffer and the current +number of cyg_can_event objects occupied in the buffer. +It does not take into account any buffering such as FIFOs or holding +registers that the CAN hardware device itself may have. + + + + + cyg_uint32 rx_bufsize + +Total number of cyg_can_event buffers in receive queue. + + + + cyg_uint32 rx_count + +Current number of cyg_can_event buffers occupied in receive queue. + + + + cyg_uint32 tx_bufsize + +Total number of cyg_can_message buffers in transmit queue. + + + + cyg_uint32 rtx_count + +Current number of cyg_can_message buffers occupied in transmit queue. + + + +
+ + +
+Reading hardware description information + + +typedef struct cyg_can_hdi_st +{ + cyg_uint8 support_flags; + cyg_uint8 controller_type; +} cyg_can_hdi; + + + +CYG_IO_GET_CONFIG_CAN_HDI - This function retrieves +information about the used hardware. The Hardware Description Interface +provides a method to gather information about the CAN hardware and the +functionality of the driver. For this purpose the structure +cyg_can_hdi is defined. + + + + + cyg_uint8 support_flags + +Contains information about the capabilities of the used CAN hardware. + + + + cyg_uint8 controller_type + +A number that identifies the CAN controller type. + + + + + +The following flags are available in the field support_flags: + + + +| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ++-------+-------+-------+-------+-------+-------+-------+-------+ +| res | res | res |timest.|SW-Filt|FullCAN| Frametype | + + + + + Frametype + +Bit 0 and Bit 1 of the structure describe the possibilities of the CAN +controller. The following values are defined: + +CYGNUM_CAN_HDI_FRAMETYPE_STD // receives only standard frame +CYGNUM_CAN_HDI_FRAMETYPE_EXT_PASSIVE // can receive but not send extended frames +CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE // can send and receive extended frames + + + + + FullCAN + +If the Bit 2 - CYGNUM_CAN_HDI_FULLCAN - is set to one, +the CAN controller supports more than one message buffer. + + + + SW-Filter + +If Bit 3 - CYGNUM_CAN_HDI_FILT_SW - is set to one then +the CAN driver supports some kind of software message filtering. + + + + Timestamp + +If Bit 4 - CYGNUM_CAN_HDI_TIMESTAMP - is set to one then +the CAN hardware supports timestamps for CAN messages + + + +
+ +
+Reading hardware message buffer configuration + +typedef struct cyg_can_msgbox_info_st +{ + cyg_uint8 count; // number of message buffers available for this device + cyg_uint8 free; // number of free message buffers +} cyg_can_msgbuf_info; + + + +CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO - If the CAN hardware supports +more than one message buffer for reception of CAN messages (flag +CYGNUM_CAN_HDI_FULLCAN is set while reading hardware description +interface with CYG_IO_GET_CONFIG_CAN_HDI) then this function +reads the number of message buffers the CAN hardware supports and the number of +free message buffers. + + + + + cyg_uint8 count + +Counts the number of message buffers supported by the device. + + + + cyg_uint8 free + +Contains the number of free message buffers. The free message buffers are +available for setting up remote buffers (CYG_IO_SET_CONFIG_CAN_REMOTE_BUF) +and message filters (CYG_IO_SET_CONFIG_CAN_FILTER_MSG). + + + +
+ +
+Reading state of CAN hardware + + +typedef enum +{ + CYGNUM_CAN_STATE_ACTIVE, // CAN controller active, no errors + CYGNUM_CAN_STATE_STOPPED, // CAN controller in stopped mode + CYGNUM_CAN_STATE_STANDBY, // CAN controller in Sleep mode + CYGNUM_CAN_STATE_BUS_WARN, // CAN controller active, warning level is reached + CYGNUM_CAN_STATE_ERR_PASSIVE, // CAN controller went into error passive mode + CYGNUM_CAN_STATE_BUS_OFF, // CAN controller went into bus off mode + CYGNUM_CAN_STATE_PHY_FAULT, // General failure of physical layer + CYGNUM_CAN_STATE_PHY_H, // Fault on CAN-H detected (Low Speed CAN) + CYGNUM_CAN_STATE_PHY_L, // Fault on CAN-L detected (Low Speed CAN) +} cyg_can_state; + + + +CYG_IO_GET_CONFIG_CAN_STATE - This function retrieves the +present state of the CAN controller. Possible values are defined in the +cyg_can_state enumeration. + +
+ + +
+Changing mode of CAN hardware + + +CYG_IO_SET_CONFIG_CAN_MODE - This function changes +the operating mode of the CAN controller. The identifiers for the different +operating modes are defined in the cyg_can_mode enumeration. + + + +typedef enum +{ + CYGNUM_CAN_MODE_STOP, // set controller into stop mode + CYGNUM_CAN_MODE_START, // set controller into operational mode + CYGNUM_CAN_MODE_STANDBY // set controller into standby / sleep mode +} cyg_can_mode; + + + + + CYGNUM_CAN_MODE_STOP + +Set controller into stop mode + + + + CYGNUM_CAN_MODE_START + +Set controller into operational mode + + + + CYGNUM_CAN_MODE_STANDBY + +Set controller into standby / sleep mode. + + + + + +Before the hardware configuration of the device is changed, that means +if baud rate is changed or the message buffer and filter configuration +is changed, the CAN hardware should be set into stop mode and if +configuration is finished, then device should be set back into +operational mode. Before the device is set into standby mode, the +output buffers should be flushed or drained because transmission of a +CAN message may wake up the CAN hardware. If a received message wakes +up the CAN hardware from standby mode then +a CYGNUM_CAN_EVENT_LEAVING_STANDBY event will be +inserted into receive message buffer or +the CYGNUM_CAN_EVENT_LEAVING_STANDBY flag will be +set for the message that caused wake up of CAN hardware. + +
+ +
+Flush or drain buffers + + +CYG_IO_SET_CONFIG_CAN_OUTPUT_DRAIN - This function +waits for any buffered output to complete. This function only +completes when there is no more data remaining to be sent to the +device. + + + +CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH - This function +discards any buffered output for the device. + + + +CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH - This function +discards any buffered input for the device. + +
+ +
+Configuring blocking/non-blocking calls + +By default all calls to cyg_io_read() +and cyg_io_write() are blocking calls. The config +keys + + + +CYG_IO_SET_CONFIG_READ_BLOCKING +CYG_IO_SET_CONFIG_WRITE_BLOCKING + + + +enable switching between blocking and nonblocking calls separatly for +read and write calls. If blocking calls are configured then the +read/write functions return only if a message was stored into TX +buffer or a event was received from RX buffer. If non-blocking calls +are enabled and there is no space in TX buffer or RX buffer is empty +then the function returns immediately +with -EAGAIN. + + + +If non-blocking calls are enabled and additionally timeouts are +supported by driver, then the read/write functions wait until timeout +value is expired and then return with -EINTR. If +the read/write operation succeeds during the timed wait then the +functions return succesfully with +ENOERR. + + + +To query if cyg_io_read() +and cyg_io_write() are blocking or non-blocking +you can use the config keys + + + +CYG_IO_GET_CONFIG_READ_BLOCKING +CYG_IO_GET_CONFIG_WRITE_BLOCKING + +
+ +
+Message buffer management + + +Full CAN controllers often support more the one message buffer. These +message buffers are often configurable for transmission or reception +of certain CAN messages or as a remote buffers. If a CAN hardware +supports more than one message buffer then it is possible to configure +the CAN hardware to receive only CAN messages with certain identifiers +or to configure hardware support for remote buffers. If message +filtering is done by hardware, the number of received CAN messages +decreases and so also the time for processing received CAN messages +and the memory required for buffering received messages +decreases. This saves valuable memory and processing time. + + + +The eCos CAN driver supports a generic way of adding message filters +or remote buffers. By default the CAN driver is configured for +reception of any kind of CAN standard and extended +frames. Configuration of message buffers is done by +calling cyg_io_set_config() with the config key + + + +CYG_IO_SET_CONFIG_CAN_MSGBUF + + + +and by exchanging cyg_can_msgbuf_cfg data structures. + + + +typedef struct cyg_can_msgbox_cfg_st +{ + cyg_can_msgbuf_cfg_id cfg_id; // configuration id + cyg_can_msgbuf_handle handle; // handle to message buffer + cyg_can_message msg; // CAN message - for configuration of buffer +} cyg_can_msgbuf_cfg; + + + + cyg_can_msgbuf_cfg_id cfg_id + The cfg_id field +contains the configuration ID that tells the driver what to do with a +message buffer. + + + + cyg_can_msgbuf_handle handle + +Contains a reference to a certain message buffer. + + + + cyg_can_message msg + +Required for configuration of message buffer parameters. + + + + + +The following configuration identifiers are supported: + + + +CYGNUM_CAN_MSGBUF_RESET_ALL // clears alle message buffers +CYGNUM_CAN_MSGBUF_RX_FILTER_ALL // cfg driver for reception of all can messages +CYGNUM_CAN_MSGBUF_RX_FILTER_ADD // add single message filter +CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD // add new remote response buffer +CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE // stores data into existing remote buffer + + + + + CYGNUM_CAN_MSGBUF_RESET_ALL + +Clears alle message buffers - no message will be received and all remote buffers are deleted. + + + + CYGNUM_CAN_MSGBUF_RX_FILTER_ALL + +Configure driver for reception of all can messages + + + + CYGNUM_CAN_MSGBUF_RX_FILTER_ADD + +Add single message filter. + + + + CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD + +Add new remote response buffer. + + + + CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE + +Stores data into existing remote buffer (remote buffer handle required). + + + + + +Example code for resetting all message buffers: + + + +cyg_can_msgbuf_cfg msgbox_cfg; + +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)) +{ + // handle configuration error +} + +
+ + +
+Remote frame response buffer configuration + + +The remote frame is a message frame which is transmitted to request a +data frame. Some CAN hardware generates receive interrupts when a +remote transmission request arrives. Other CAN hardware, i.e. the +Motorola FlexCAN module, does not generate any receive +interrupt. These CAN hardware chips like the FlexCAN module can be +configured to transmit a data frame automatically in response to a +remote frame. In order to support any kind of CAN hardware the eCos CAN +driver provides a generic handling of remote transmission requests. + + + +The transmission of the data frame in response to a remote frame is +completely handled by the CAN driver. If the hardware driver, like +the driver for the FlexCAN module, supports hardware message buffers, +then the response frame is automatically transmitted if a remote +transmission request with a matching ID arrives. If a CAN hardware +does not provide hardware support for sending data frames in response +to a remote frame, then this need to be implemented in software by the +hardware device driver. + + + +It is always possible to add remote response buffers. It does not +matter if the driver is configured for reception of all CAN messages +or if message filtering is used. As long as there are free message +buffers available, it is possible to add remote response buffers. + + + +In order to respond to a remote frame, a remote frame response buffer +need to be initialized before a data frame can be sent in response to +a remote frame. This is achieved by by +exchanging cyg_can_remote_buf data structures with the +driver via the cyg_io_set_config() function using +the config key CYG_IO_SET_CONFIG_CAN_MSGBUF. Once +the buffer is initialized, the CAN data can be changed at any time by +the application. + + + +typedef struct cyg_can_msgbuf_cfg_st +{ + cyg_can_msgbuf_cfg_id cfg_id; // configuration id + cyg_can_msgbuf_handle handle; // handle to message buffer + cyg_can_message msg; // CAN message - for configuration of buffer +} cyg_can_remote_buf; + + + + cyg_can_msgbuf_cfg_id cfg_id + +The cfg_id field contains the configuration ID that tells the driver what to do with +a message buffer (CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD or +CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE). + + + + cyg_can_msgbuf_handle handle + +If there is no buffer initialized for this data, the value of the handle field need to be set to +CYGNUM_CAN_MSGBUF_INIT. After the call to cyg_io_set_config() +the handle field contains a valid remote buffer handle ( >= 0) or the value +CYGNUM_CAN_MSGBUF_NA ( < 0) if no free buffer is available. + + + + cyg_can_message msg + +The CAN frame that should be transmitted in response to a remote frame. + + + + + +Example code for setting up a remote response buffer: + + + +cyg_can_remote_buf rtr_buf; + +// prepare the remote response buffer +rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; +rtr_buf.handle = CYGNUM_CAN_MSGBUF_INIT; +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)) +{ + // handle configuration error +} + +if (rtr_buf.handle == CYGNUM_CAN_MSGBUF_NA) +{ + // no free message buffer available - handle this problem here +} + + +// change CAN data for a buffer that is already initialized +rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE; +rtr_buf.msg.data[0] = 0x11; + +len = sizeof(rtr_buf); +if (ENOERR != cyg_io_set_config(hDrvFlexCAN, + CYG_IO_SET_CONFIG_CAN_MSGBUF, + &rtr_buf, &len)) +{ + // handle configuration error +} + +
+ + +
+Message filter configuration + + +If message filtering is done by hardware the number of received CAN +messages decreases and so also the time for processing received CAN +messages and the memory required for buffering received messages +decreases. This saves valuable memory and processing time. The eCos +CAN driver supports a generic way of adding message filters. By +default the CAN driver is configured for reception of any kind of CAN +standard and extended frames. As soon as a message filter is added, +the CAN driver will only receive the CAN frames with the identifier of +the CAN filter. By adding a number of message filters it is possible +for the CAN hardware to receive an number of different CAN messages. + + + +Adding message filters is only possible if driver is not configured +for reception of all available CAN messages. If the driver is +configured for reception of all CAN messages then message buffers need +to be reset before adding single message filters. + + + +In order to add a message filter, a message buffer need to be +initialized. This is achieved by +exchanging cyg_can_filter data structures with the driver +via the cyg_io_set_config() function using the +config key CYG_IO_SET_CONFIG_CAN_MSGBUF. Once the +buffer is initialized, the CAN hardware can receive messages with the +identifier of the filter. + + + +typedef struct cyg_can_msgbox_cfg_st +{ + cyg_can_msgbuf_cfg_id cfg_id; + cyg_can_msgbuf_handle handle; + cyg_can_message msg; +} cyg_can_filter; + + + + + cyg_can_msgbuf_cfg_id cfg_id + +The cfg_id field contains the configuration ID that tells the driver what to do with +a message buffer. + + + + cyg_can_msgbuf_handle handle + +After the call to cyg_io_set_config() the handle field contains a valid value +( >= 0) or the value CYGNUM_CAN_MSGBUF_NA ( < 0) if no free buffer is available. + + + + cyg_can_message msg + +The fields id and ext of the msg +configure the type of message to receive by a certain message filter. + + + + + +Before adding message filters the device should be stopped and after +configuration it should be set into operational mode again. + + + +Example code for setting up a message filter: + + + +cyg_can_msgbuf_cfg msgbox_cfg; +cyg_can_filter rx_filter; + +// reset all message buffers +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)) +{ + // handle configuration error +} + +// prepare the message filter +rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD +rx_filter.msg.id = 0x800; +rx_filter.msg.ext = CYGNUM_CAN_ID_EXT; + +len = sizeof(rx_filter); +if (ENOERR != cyg_io_set_config(hDrvFlexCAN, + CYG_IO_SET_CONFIG_CAN_MSGBUF, + &rx_filter, &len)) +{ + // handle configuration error; +} +else if (CYGNUM_CAN_MSGBUF_NA == rx_filter.handle) +{ + // no free message buffer available - handle this problem here +} + +
+ + +
+Message filter deactivation + + +After startup of your device the CAN driver is configured for +reception of all available CAN messages. If you change this +configuration by adding single message filters then you can reset this +default state with the configuration ID: + + + +CYGNUM_CAN_MSGBUF_RX_FILTER_ALL + + + +This message buffer configuration id will clear all message filters +and remote buffers and prepares the CAN hardware for reception of any +kind of CAN standard and extended frames. It is not necessary to reset +the message buffer configuration before this configuration step is +executed because this should be done by device driver. + + + +Example code for deactivation of message filtering: + + + +cyg_can_filter rx_filter; + +// now setup a RX all configuration +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"); +} + +
+ +
+Configuring a callback on events + + +By default application cannot get information about an event arriving +in the RX buffer until it calls +the cyg_io_read(). Usually this leads applications +to use accessory threads to wait for new CAN events. + + + +The CDL option CYGOPT_IO_CAN_SUPPORT_CALLBACK +allows application to use a callback on event arrival. It is +configured by passing a cyg_can_callback_cfg +data structure to the driver via +the cyg_io_set_config() function using the config +key +CYG_IO_SET_CONFIG_CAN_CALLBACK. + + + +CYG_IO_SET_CONFIG_CAN_CALLBACK + + + +typedef void (*cyg_can_event_cb_t)(cyg_uint16, CYG_ADDRWORD); + +typedef struct cyg_can_callback_cfg_st +{ + cyg_can_event_cb_t callback_func; // callback function + cyg_uint16 flag_mask; // flags mask + CYG_ADDRWORD data; // data passed to callback +} cyg_can_callback_cfg; + + + + + cyg_can_event_cb_t callback_func + +Pointer to the callback function. The function will be called from DSR context so +you should be careful to only call API functions that are safe in DSR +context. The First parameter is a combination of event flags for events that have +occurred. Second parameter is a user defined data pointer or value. + + + + CYG_ADDRWORD data + +Additional user data that will be passed to callback function as a second parameter. + + + + cyg_uint16 flag_mask + +Should be set with a combination +of CYGNUM_CAN_EVENT_* flags. If one of these +events happens, the callback function will be called, with the +actually event flags passed as a parameter. To disable the callback +function from being called set flag_mask to 0. + + + + +
+ +
+
+ + +Configuration + + +The CAN subsystem has a number of configuration options. + + + + + cdl_interface CYGINT_IO_CAN_TIMESTAMP + +A hardware device driver that supports timestamps should implement this interface. + + + + cdl_option CYGOPT_IO_CAN_SUPPORT_TIMESTAMP + +If the CAN hardware driver supports some kind of timestamps then this option enables +propagation of timestamps to higher layers. This may add some extra code to hardware +drivers. + + + + cdl_option CYGOPT_IO_CAN_TX_EVENT_SUPPORT + + This option enables support for TX +events. If a CAN message is transmitted successfully a TX event will +be inserted into the receive event queue and propagated to higher +layers. If this option is enabled the RX event queue will be filled +faster. + + + + cdl_option CYGOPT_IO_CAN_SUPPORT_NONBLOCKING + + +This option enables extra code in the generic CAN driver which allows +clients to switch read() and write() call semantics from blocking to +non-blocking. + + + + cdl_option CYGOPT_IO_CAN_SUPPORT_CALLBACK + + +This option enables extra code in the generic CAN driver which allows +an application to register a callback for events. The callback function +is called from DSR context so you should be careful to only call API +functions that are safe in DSR context. + + + + cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_READ + +The initial timeout value in clock ticks for cyg_io_read() calls. + + + + cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_WRITE + The initial timeout value in clock ticks +for cyg_io_write() calls. + + + + + + + +Writing a CAN hardware device driver + + +A CAN driver is nothing more than a named entity that supports the +basic I/O functions - read, write, get config, and set config. The +device driver uses and manages interrupts from the device. While the +interface is generic and device driver independent, the actual driver +implementation is completely up to the device driver designer. + + + +That said, the reason for using a device driver is to provide access +to a CAN device from application code in as general purpose a fashion +as reasonable. Most driver writers are also concerned with making this +access as simple as possible while being as efficient as possible. + + + +Like other device drivers the CAN device driver is concerned with the +movement of information - the CAN messages. In order to make the most +efficient use of system resources, interrupts are used. This will +allow other application processing to take place while the data +transfers are under way, with interrupts used to indicate when various +events have occurred. For example, a CAN device typically generates an +interrupt after a CAN message has been sent or a CAN message has been +received by a CAN hardware message buffer. It makes sense to allow +further application processing while the data is being sent since this +can take quite a long time. The interrupt can be used to allow the +driver to send a CAN message as soon as the current one is complete, +without any active participation by the application code. + + + +The main building blocks for CAN device drivers are found in the +include files +<cyg/io/devtab.h> and <cyg/io/can.h> + + + +Like many other device drivers in eCos, CAN device drivers are described by a device +table entry, using the cyg_devtab_entry_t type. The entry should be created using +the DEVTAB_ENTRY() macro. + + + +
+How to Write a CAN Hardware Interface Driver + + +The standard CAN driver supplied with eCos is structured as a hardware +independent portion and a hardware dependent interface module. To add +support for a new CAN device, the user should be able to use the +existing hardware independent portion and just add their own interface +driver which handles the details of the actual device. The user should +have no need to change the hardware independent portion. + + + +The interfaces used by the CAN driver and CAN implementation modules +are contained in the file <cyg/io/can.h>. + + +
+DevTab Entry + + +The interface module contains the devtab entry (or entries if a single +module supports more than one interface). This entry should have the +form: + + + +DEVTAB_ENTRY(<<module_name>>, + <<device_name>>, + 0, + &can_devio, + <<module_init>>, + <<module_lookup>>, + &<<can_channel>> + ); + + + +Arguments + + module_name + The "C" label for this devtab entry + + + device_name + The "C" string for the + device. E.g. /dev/can0. + + + can_devio + The table of I/O functions. This set is defined in + the hardware independent CAN driver and should be used. + + + + module_init + The hardware module initialization function. + + + module_lookup + The device lookup function. This function + typically sets up the CAN device for actual use, turning on + interrupts, configuring the message buffers, etc. + + + can_channel + This table (defined below) contains the interface + between the interface module and the CAN driver proper. + + + + +Example devtab entry for Motorola FlexCAN device driver: + + + +DEVTAB_ENTRY(flexcan_devtab, + CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_can_devio, + flexcan_init, + flexcan_lookup, // CAN driver may need initializing + &flexcan_can0_chan + ); + +
+ + +
+CAN Channel Structure + + +Each CAN device must have a “CAN channel”. +This is a set of data which describes all operations on the device. +It also contains buffers, etc. The CAN channel is created by the macro: + + + +CAN_CHANNEL_USING_INTERRUPTS(l, funs, dev_priv, baud, + out_buf, out_buflen, + in_buf, in_buflen) + + + + Arguments + + l + The "C" label for this structure. + + + funs + The set of interface functions (see below). + + + dev_priv + A placeholder for any device specific data for + this channel. + + + baud + The initial baud rate value + (cyg_can_baud_rate_t). + + + out_buf + Pointer to the output buffer + + + out_buflen + The length of the output buffer. + + + in_buf + pointer to the input buffer. + + + in_buflen + The length of the input buffer. + + + + +Example CAN channel implementation for Motorola FlexCAN device driver: + + + +CAN_CHANNEL_USING_INTERRUPTS( + flexcan_can0_chan, + flexcan_lowlevel_funs, + flexcan_can0_info, + CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD), + flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX, + flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX +); + + + +The interface from the hardware independent driver into the hardware +interface module is contained in the funs +table. This is defined by the macro: + +
+ +
+CAN Lowlevel Functions Structure + + +CAN_LOWLEVEL_FUNS(l, putmsg, getevent, get_config, set_config, start_xmit, stop_xmit) + + + + Arguments + + l + The "C" label for this structure. + + + putmsg + + + bool (*putmsg)(can_channel *priv, cyg_can_message *pmsg, void *pdata) + + + This function sends one CAN message to the interface. It should + return true if the message is actually + consumed. It should return false if there is + no space in the interface + + + + + getevent + + + bool (*getevent)(can_channel *priv, cyg_can_event *pevent, void *pdata) + + + This function fetches one event from the interface. + + + + + get_config + + + Cyg_ErrNo (*get_config)(can_channel *priv, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) + + + This function is used to query the configuration of a CAN channel. + + + + + set_config + + + Cyg_ErrNo (*set_config)(can_channel *priv, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) + + + This function is used to change configuration of a CAN channel. + + + + + start_xmit + void (*start_xmit)(can_channel *priv) + + Enable the transmit channel and turn on transmit interrupts. + + + + + stop_xmit + + void (*stop_xmit)(can_channel *priv) + Disable the transmit channel and turn transmit interrupts off. + + + + + +Example implementation of low level function structure for Motorola FlexCAN +device driver: + + + +CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs, + flexcan_putmsg, + flexcan_getevent, + flexcan_get_config, + flexcan_set_config, + flexcan_start_xmit, + flexcan_stop_xmit + ); + +
+ +
+Callbacks + + +The device interface module can execute functions in the +hardware independent driver via chan->callbacks. +These functions are available: + + + +void (*can_init)(can_channel *chan) + + +This function is used to initialize the CAN channel. + + +void (*xmt_msg)(can_channel *chan, void *pdata) + + + +This function would be called from an interrupt handler after a +transmit interrupt indicating that additional messages may be +sent. The upper driver will call the putmsg +function as appropriate to send more data to the device. + + + +void (*rcv_event)(can_channel *chan, void *pdata) + + + +This function is used to tell the driver that a message has arrived +at the interface or that an event has occurred. This function is typically +called from the interrupt handler. + +
+ +
+
+ +
diff --git a/packages/io/can/v2_0/tests/can_filter.c b/packages/io/can/v2_0/tests/can_filter.c new file mode 100644 index 00000000..c1145f0a --- /dev/null +++ b/packages/io/can/v2_0/tests/can_filter.c @@ -0,0 +1,307 @@ +//========================================================================== +// +// can_filter.c +// +// CAN 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: 2007-03-21 +// Description: CAN hardware filter test +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + +// Package option requirements +#if defined (CYGOPT_IO_CAN_STD_CAN_ID) + + +//=========================================================================== +// 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 hCAN0; + + +//=========================================================================== +// LOCAL FUNCTIONS +//=========================================================================== +#include "can_test_aux.inl" // include CAN test auxiliary functions + + +//=========================================================================== +// Main thread +//=========================================================================== +void can0_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_event rx_event; + cyg_uint16 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(hCAN0, CYG_IO_GET_CONFIG_CAN_HDI ,&hdi, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); + } + + // + // Normally the CAN 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"); + } + + + // + // Now reset message buffer configuration - this is mandatory bevore starting + // message buffer runtime configuration + // + msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; + len = sizeof(msgbox_cfg); + if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&msgbox_cfg, &len)) + { + CYG_TEST_FAIL_FINISH("Error resetting 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(hCAN0, 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"); + } + + // + // 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; + rx_filter.msg.ext = CYGNUM_CAN_ID_STD; + + len = sizeof(rx_filter); + if (ENOERR != cyg_io_set_config(hCAN0, 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"); + } + } + + + diag_printf("\n\nNow try to send CAN messages. The device should only\n" + "receive messages identifiers in the range of 0x00 to 0x%X.\n" + "As soon as a standard message with ID 0x000 arrives, all\n" + "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(hCAN0, &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(hCAN0, &rx_event, &len)) + else + { + print_can_flags(rx_event.flags, ""); + rx_event.msg.id = 1; + } + } // while(1) + + + // + // 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(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF , &rx_filter, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); + } + + + diag_printf("\n\nAll message filters have been cleared an now the device\n" + "will receive any available CAN message identifiers.\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(hCAN0, &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(hCAN0, &rx_event, &len)) + } // while(1) + + CYG_TEST_PASS_FINISH("can_filter test OK"); +} + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) + { + CYG_TEST_FAIL_FINISH("Error opening /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 // CYGOPT_IO_CAN_STD_CAN_ID +#define N_A_MSG "Needs support for standard CAN identifiers" +#endif + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs IO/CAN and Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG); +} +#endif // N_A_MSG + +//--------------------------------------------------------------------------- +// EOF can_filter.c diff --git a/packages/io/can/v2_0/tests/can_hdi.c b/packages/io/can/v2_0/tests/can_hdi.c new file mode 100644 index 00000000..1aba3735 --- /dev/null +++ b/packages/io/can/v2_0/tests/can_hdi.c @@ -0,0 +1,235 @@ +//========================================================================== +// +// can_hdi.c +// +// CAN hardware description information 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: 2007-03-22 +// Description: CAN hardware desciption information test +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + + +//=========================================================================== +// 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 hCAN0; + + +//=========================================================================== +// LOCAL FUNCTIONS +//=========================================================================== +#include "can_test_aux.inl" // include CAN test auxiliary functions + + +//=========================================================================== +// Main thread +//=========================================================================== +void can0_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_hdi hdi; + cyg_can_msgbuf_info msgbox_info; + + + // + // Query information about hardware of CAN controller + // + len = sizeof(hdi); + if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_HDI ,&hdi, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); + } + + // + // Check type of CAN controller - type of supported CAN frames + // + diag_printf("\n\nSupported message formats:\n"); + if (hdi.support_flags & CYGNUM_CAN_HDI_FRAMETYPE_STD) + { + diag_printf(" Standard CAN (2.0A): yes\n"); + diag_printf(" Extended CAN (2.0B): no\n"); + } + else if (hdi.support_flags & CYGNUM_CAN_HDI_FRAMETYPE_EXT_PASSIVE) + { + diag_printf(" Standard CAN (2.0A): yes\n"); + diag_printf(" Extended CAN (2.0B): passive\n"); + } + else if (hdi.support_flags & CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE) + { + diag_printf(" Standard CAN (2.0A): yes\n"); + diag_printf(" Extended CAN (2.0B): yes\n"); + } + + // + // Check if this is a FullCAN controller + // + diag_printf("\nController type: "); + if (hdi.support_flags & CYGNUM_CAN_HDI_FULLCAN) + { + diag_printf("FullCAN\n"); + // + // FullCAN means the controller supports a number of message buffers. + // Now query number of available and free message buffers + // + len = sizeof(msgbox_info); + if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); + } + + diag_printf(" Message buffers: %d\n", msgbox_info.count); + diag_printf(" Message buffers free: %d\n", msgbox_info.free); + } + else + { + diag_printf("BasicCAN\n"); + } + + // + // Check if automatic baudrate detection is supported + // + if (hdi.support_flags & CYGNUM_CAN_HDI_AUTBAUD) + { + diag_printf("\nAutomatic baudrate detection: supported\n"); + } + + // + // Check if driver supports timestamps + // + if (hdi.support_flags & CYGNUM_CAN_HDI_TIMESTAMP) + { + diag_printf("Timestamps: supported\n"); + } + + diag_printf("\n\n"); + CYG_TEST_PASS_FINISH("can_hdi test OK"); +} + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) + { + CYG_TEST_FAIL_FINISH("Error opening /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 can_hdi.c diff --git a/packages/io/can/v2_0/tests/can_load.c b/packages/io/can/v2_0/tests/can_load.c new file mode 100644 index 00000000..60d5d02f --- /dev/null +++ b/packages/io/can/v2_0/tests/can_load.c @@ -0,0 +1,308 @@ +//========================================================================== +// +// can_load.c +// +// CAN 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: CAN load test +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + +// Package option requirements +#if defined(CYGOPT_IO_CAN_STD_CAN_ID) && defined(CYGOPT_IO_CAN_EXT_CAN_ID) + + +//=========================================================================== +// 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 hCAN0; + + +//=========================================================================== +// LOCAL FUNCTIONS +//=========================================================================== +#include "can_test_aux.inl" // include CAN test auxiliary functions + + +//=========================================================================== +// Main 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(hCAN0, 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(hCAN0, &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 + 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 + }; + + // + // 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.bytes[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 frames + // + else + { + tx_msg.ext = CYGNUM_CAN_ID_STD; + tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; + } + + len = sizeof(tx_msg); + if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing to /dev/can0"); + } + + cyg_thread_delay(50); + } // while (1) +} + + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) + { + CYG_TEST_FAIL_FINISH("Error opening /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 // defined(CYGOPT_IO_CAN_STD_CAN_ID) && defined(CYGOPT_IO_CAN_EXT_CAN_ID) +#define N_A_MSG "Needs support for standard and extended CAN identifiers" +#endif + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs IO/CAN and Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG); +} +#endif // N_A_MSG + +// EOF can_load.c diff --git a/packages/io/can/v2_0/tests/can_remote.c b/packages/io/can/v2_0/tests/can_remote.c new file mode 100644 index 00000000..0c223f08 --- /dev/null +++ b/packages/io/can/v2_0/tests/can_remote.c @@ -0,0 +1,312 @@ +//========================================================================== +// +// can_remote.c +// +// CAN 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: CAN load test +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + +// Package option requirements +#if defined(CYGOPT_IO_CAN_RUNTIME_MBOX_CFG) + +// Package option requirements +#if defined(CYGOPT_IO_CAN_REMOTE_BUF) + + +//=========================================================================== +// 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 hCAN0; + + +//=========================================================================== +// LOCAL FUNCTIONS +//=========================================================================== +#include "can_test_aux.inl" // include CAN test auxiliary functions + + +//=========================================================================== +// Main thread +//=========================================================================== +void can0_thread(cyg_addrword_t data) +{ + cyg_uint32 len; + cyg_can_event rx_event; + cyg_can_remote_buf rtr_buf; + cyg_can_filter rx_filter; + cyg_can_msgbuf_info msgbox_info; + cyg_can_msgbuf_cfg msgbox_cfg; + + // + // 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(hCAN0, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); + } + else + { + diag_printf("\n\n\nMessage boxes available: %d free: %d\n", + msgbox_info.count, msgbox_info.free); + } + + // + // We have not enougth free message buffers, so we clear all message buffers now + // and try again + // + if (msgbox_info.free < 2) + { + msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; + len = sizeof(msgbox_cfg); + if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF, &msgbox_cfg, &len)) + { + CYG_TEST_FAIL_FINISH("Error clearing message buffers of /dev/can0"); + } + + // + // Now query number of free message boxes again. We need 3 free message boxes. + // 2 message boxes for setup of remote response buffers and 1 message box for + // setup of receive message box for CAN identifier 0x100 + // + len = sizeof(msgbox_info); + if (ENOERR != cyg_io_get_config(hCAN0, 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 < 3) + { + CYG_TEST_FAIL_FINISH("Not enough free message buffers available for /dev/can0"); + } + else + { + rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD; + CYG_CAN_MSG_SET_STD_ID(rx_filter.msg, 0x100); + + len = sizeof(rx_filter); + if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rx_filter, &len)) + { + CYG_TEST_FAIL_FINISH("Error adding rx filter for CAN ID 0x100 for /dev/can0"); + } + } // if (msgbox_info.free < 3) + } // if (msgbox_info.free < 2) +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + // + // Setup the first remote response buffer for resception of standard + // remote frames + // + rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; + CYG_CAN_MSG_SET_PARAM(rtr_buf.msg, 0x7FF, CYGNUM_CAN_ID_STD, 1, CYGNUM_CAN_FRAME_DATA); + CYG_CAN_MSG_SET_DATA(rtr_buf.msg, 0, 0xAB); + + len = sizeof(rtr_buf); + if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); + } +#endif + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + cyg_can_remote_buf rtr_buf2; + // + // setup the second remote response buffer for reception of extended + // remote frames + // + rtr_buf2.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; + CYG_CAN_MSG_SET_PARAM(rtr_buf2.msg, 0x800, CYGNUM_CAN_ID_EXT, 4, CYGNUM_CAN_FRAME_DATA); + CYG_CAN_MSG_SET_DATA(rtr_buf2.msg, 0, 0xCD); + + len = sizeof(rtr_buf2); + if (ENOERR != cyg_io_set_config(hCAN0, 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"); + } +#endif + + diag_printf("\nTest of CAN remote response buffer configuration\n" + "If a CAN node sends a remote request with ID 0x7FF (std. ID)\n" + "or 0x800 (ext. ID) then the CAN driver should respond with\n" + "data frames.\n\n"); + diag_printf("!!! This test can be stopped by sending a data frame\n" + "with ID 0x100 !!!\n\n"); + + len = sizeof(msgbox_info); + if (ENOERR != cyg_io_get_config(hCAN0, 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(hCAN0, &rx_event, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); + } + + if (0x100 == rx_event.msg.id) + { + CYG_TEST_PASS_FINISH("can_remote test OK"); + } + else + { + print_can_flags(rx_event.flags, ""); + + if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + { + print_can_msg(&rx_event.msg, ""); + } + } + } +} + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // open CAN device driver + // + if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) + { + CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); + } + + // + // create the thread that accesses the CAN device driver + // + cyg_thread_create(4, can0_thread, + (cyg_addrword_t) 0, + "can0_thread", + (void *) can0_thread_data.stack, + 1024 * sizeof(long), + &can0_thread_data.hdl, + &can0_thread_data.obj); + + cyg_thread_resume(can0_thread_data.hdl); + + cyg_scheduler_start(); +} + +#else // CYGOPT_IO_CAN_REMOTE_BUF +#define N_A_MSG "Needs support for CAN remote response buffers" +#endif + +#else // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG +#define N_A_MSG "Needs support for CAN message buffer runtime configuration" +#endif + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs IO/CAN and Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG); +} +#endif // N_A_MSG + +// EOF can_remote.c diff --git a/packages/io/can/v2_0/tests/can_test_aux.inl b/packages/io/can/v2_0/tests/can_test_aux.inl new file mode 100644 index 00000000..2946b8fd --- /dev/null +++ b/packages/io/can/v2_0/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 diff --git a/packages/io/can/v2_0/tests/can_tx.c b/packages/io/can/v2_0/tests/can_tx.c new file mode 100644 index 00000000..ceea6efa --- /dev/null +++ b/packages/io/can/v2_0/tests/can_tx.c @@ -0,0 +1,230 @@ +//========================================================================== +// +// can_tx.c +// +// Simple CAN TX 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: 2007-01-08 +// Description: Simple write test of CAN driver +//####DESCRIPTIONEND#### + + +//=========================================================================== +// INCLUDES +//=========================================================================== +#include + +#include // test macros +#include // assertion macros +#include +#include + +// Package requirements +#if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) + +#include +#include +#include + +// Package option requirements +#if defined(CYGFUN_KERNEL_API_C) + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include + + +//=========================================================================== +// DATA TYPES +//=========================================================================== +typedef struct st_thread_data +{ + cyg_thread obj; + long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; + cyg_handle_t hdl; +} thread_data_t; + + +//=========================================================================== +// LOCAL DATA +//=========================================================================== +cyg_thread_entry_t can0_thread; +thread_data_t can0_thread_data; + + +//=========================================================================== +// LOCAL FUNCTIONS +//=========================================================================== +#include "can_test_aux.inl" // include CAN test auxiliary functions + + +//=========================================================================== +// WRITER THREAD +//=========================================================================== +void can0_thread(cyg_addrword_t data) +{ + cyg_io_handle_t hCAN0; + cyg_uint32 i; + cyg_uint32 len; + CYG_CAN_MSG_INIT(tx_msg, 0x001, CYGNUM_CAN_ID_STD, 1, CYGNUM_CAN_FRAME_DATA); + + // + // Open device and check return value + // + if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) + { + CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); + } + +#ifdef CYGOPT_IO_CAN_STD_CAN_ID + // + // Now send 1000 messages with standard identifier. + // Each message contains the message number in its identifier + // and in the first data byte + // + for (i = 0; i < 1000; ++i) + { + CYG_CAN_MSG_SET_STD_ID(tx_msg, i); + CYG_CAN_MSG_SET_DATA(tx_msg, 0, i); + len = sizeof(tx_msg); + + // + // Each message with an odd identifier should be a remote request message + // + if (i % 2) + { + CYG_CAN_MSG_SET_FRAME_TYPE(tx_msg, CYGNUM_CAN_FRAME_RTR); + } + else + { + CYG_CAN_MSG_SET_FRAME_TYPE(tx_msg, CYGNUM_CAN_FRAME_DATA); + } + + // + // Sending CAN messages is blocking so the thread waits until there is + // space in the tx queue + // + if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing to /dev/can0"); + } + } +#endif + +#ifdef CYGOPT_IO_CAN_EXT_CAN_ID + // + // Now send 1000 messages with extended identifier. + // Each message contains the message number in its identifier + // and in the first data byte + // + for (i = 0; i < 1000; ++i) + { + CYG_CAN_MSG_SET_EXT_ID(tx_msg, i + 0x800); + CYG_CAN_MSG_SET_DATA(tx_msg, 0, i); + CYG_CAN_MSG_SET_DATA_LEN(tx_msg, 8); + len = sizeof(tx_msg); + + // + // Each message with an odd identifier should be a remote request message + // + if (i % 2) + { + CYG_CAN_MSG_SET_FRAME_TYPE(tx_msg, CYGNUM_CAN_FRAME_RTR); + } + else + { + CYG_CAN_MSG_SET_FRAME_TYPE(tx_msg, CYGNUM_CAN_FRAME_DATA); + } + + // + // Sending CAN messages is blocking so the thread waits until there is + // space in the tx queue + // + if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing to /dev/can0"); + } + } +#endif + + + CYG_TEST_PASS_FINISH("CAN TX test OK"); +} + + +void +cyg_start(void) +{ + CYG_TEST_INIT(); + + // + // create the threads that access the CAN device driver + // + cyg_thread_create(4, can0_thread, + (cyg_addrword_t) 0, + "can0_thread", + (void *) can0_thread_data.stack, + 1024 * sizeof(long), + &can0_thread_data.hdl, + &can0_thread_data.obj); + + cyg_thread_resume(can0_thread_data.hdl); + + cyg_scheduler_start(); +} + +#else // CYGFUN_KERNEL_API_C +#define N_A_MSG "Needs kernel C API" +#endif + +#else // CYGPKG_IO_CAN && CYGPKG_KERNEL +#define N_A_MSG "Needs IO/CAN and Kernel" +#endif + +#ifdef N_A_MSG +void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG); +} +#endif // N_A_MSG + +// EOF can_tx.c diff --git a/packages/io/fileio/v2_0/include/fnmatch.h b/packages/io/fileio/v2_0/include/fnmatch.h new file mode 100644 index 00000000..c14318b3 --- /dev/null +++ b/packages/io/fileio/v2_0/include/fnmatch.h @@ -0,0 +1,67 @@ +#ifndef CYGONCE_FILEIO_FNMATCH_H +#define CYGONCE_FILEIO_FNMATCH_H + +//========================================================================== +// +// fnmatch.h +// +//========================================================================== +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from NetBSD, and are +// covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### + +/* $NetBSD: fnmatch.h,v 1.12 2005/02/03 04:39:32 perry Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + */ + +#include // common type definitions and support + +#define FNM_NOMATCH (1) /* Match failed. */ +#define FNM_NOSYS (2) /* Function not implemented. */ + +#define FNM_NOESCAPE (0x01) /* Disable backslash escaping. */ +#define FNM_PATHNAME (0x02) /* Slash must be matched by slash. */ +#define FNM_PERIOD (0x04) /* Period must be matched by period. */ +#define FNM_CASEFOLD (0x08) /* Pattern is matched case-insensitive */ +#define FNM_LEADING_DIR (0x10) /* Ignore / after Imatch. */ + +__externC int +fnmatch(const char *, const char *, int); + +#endif /* !CYGONCE_FILEIO_FNMATCH_H */ diff --git a/packages/io/fileio/v2_0/src/fnmatch.c b/packages/io/fileio/v2_0/src/fnmatch.c new file mode 100644 index 00000000..0c3db477 --- /dev/null +++ b/packages/io/fileio/v2_0/src/fnmatch.c @@ -0,0 +1,185 @@ +/* $NetBSD: fnmatch.c,v 1.21 2005/12/24 21:11:16 perry Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + +#include // assertion macros +#include +#include +#include + +#define EOS '\0' + +static const char *rangematch(const char *, int, int); + +static inline int +foldcase(int ch, int flags) +{ + + if ((flags & FNM_CASEFOLD) != 0 && isupper(ch)) + return (tolower(ch)); + return (ch); +} + +#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags)) + +int +fnmatch(const char *pattern, const char *string, int flags) +{ + const char *stringstart; + char c, test; + + CYG_ASSERT(pattern != NULL, "pattern NULL pointer!"); + CYG_ASSERT(string != NULL, "string NULL pointer!"); + + for (stringstart = string;;) + switch (c = FOLDCASE(*pattern++, flags)) { + case EOS: + if ((flags & FNM_LEADING_DIR) && *string == '/') + return (0); + return (*string == EOS ? 0 : FNM_NOMATCH); + case '?': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + ++string; + break; + case '*': + c = FOLDCASE(*pattern, flags); + /* Collapse multiple stars. */ + while (c == '*') + c = FOLDCASE(*++pattern, flags); + + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) { + if (flags & FNM_PATHNAME) + return ((flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH); + else + return (0); + } else if (c == '/' && flags & FNM_PATHNAME) { + if ((string = strchr(string, '/')) == NULL) + return (FNM_NOMATCH); + break; + } + + /* General case, use recursion. */ + while ((test = FOLDCASE(*string, flags)) != EOS) { + if (!fnmatch(pattern, string, + flags & ~FNM_PERIOD)) + return (0); + if (test == '/' && flags & FNM_PATHNAME) + break; + ++string; + } + return (FNM_NOMATCH); + case '[': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && flags & FNM_PATHNAME) + return (FNM_NOMATCH); + if ((pattern = + rangematch(pattern, FOLDCASE(*string, flags), + flags)) == NULL) + return (FNM_NOMATCH); + ++string; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + if ((c = FOLDCASE(*pattern++, flags)) == EOS) { + c = '\\'; + --pattern; + } + } + /* FALLTHROUGH */ + default: + if (c != FOLDCASE(*string++, flags)) + return (FNM_NOMATCH); + break; + } + /* NOTREACHED */ +} + +static const char * +rangematch(const char *pattern, int test, int flags) +{ + int negate, ok; + char c, c2; + + CYG_ASSERT(pattern != NULL, "pattern NULL pointer!"); + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^')) != 0) + ++pattern; + + for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) { + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = FOLDCASE(*pattern++, flags); + if (c == EOS) + return (NULL); + if (*pattern == '-' + && (c2 = FOLDCASE(*(pattern+1), flags)) != EOS && + c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) + c2 = FOLDCASE(*pattern++, flags); + if (c2 == EOS) + return (NULL); + if (c <= test && test <= c2) + ok = 1; + } else if (c == test) + ok = 1; + } + return (ok == negate ? NULL : pattern); +} diff --git a/packages/io/fileio/v2_0/tests/fnmatch.c b/packages/io/fileio/v2_0/tests/fnmatch.c new file mode 100644 index 00000000..75667be5 --- /dev/null +++ b/packages/io/fileio/v2_0/tests/fnmatch.c @@ -0,0 +1,152 @@ +//========================================================================== +// +// fnmatch.c +// +// Test fnmatch function +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2007 Andrew Lunn +// +// 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): asl +// Contributors: asl +// Date: 2007-01-27 +// Purpose: Test fnmatch function. +// Description: // +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#ifndef CYGPKG_FILEIO_FNMATCH +# define NA_MSG "FNMATCH function not available" +#endif + +#include + +#ifndef NA_MSG +#include +#include + +#include + +//========================================================================== +// main + +int main( int argc, char **argv ) +{ + int i; + cyg_bool failed = false; + + struct + { + const int result; + const int flags; + const char * string; + const char * pattern; + } test_case[] = { + { 0, 0, "abc", "abc" }, /* 0 */ + { FNM_NOMATCH, 0, "cba", "abc" }, + { 0, 0, "abc", "a*" }, + { FNM_NOMATCH, 0, "abc", "b*" }, + { 0, 0, "abc", "[abc]*" }, + { FNM_NOMATCH, 0, "abc", "[def]*" }, + { FNM_NOMATCH, 0, "abc", "*[def]*" }, + { 0, 0, "a/b", "a/b" }, + { FNM_NOMATCH, 0, "a/b", "a/a" }, + { FNM_NOMATCH, 0, "a/b", "b/b" }, + + { 0, 0, "a b", "a\\ b"}, /* 10 */ + { FNM_NOMATCH, FNM_NOESCAPE, "a b", "a\\ b"}, + + { 0, 0, "a/b", "a*b" }, + { 0, 0, "a/b", "a?b" }, + { 0, 0, "a/b", "a[/]b" }, + { FNM_NOMATCH, FNM_PATHNAME, "a/b", "a*b"}, + { FNM_NOMATCH, FNM_PATHNAME, "a/b", "a?b"}, + { FNM_NOMATCH, FNM_PATHNAME, "a/b", "a[/]b"}, + { 0, FNM_PATHNAME, "a/b", "a/b"}, + + { 0, 0, ".abc", "?abc" }, + { 0, 0, ".abc", "*abc" }, /* 20 */ + { 0, 0, ".abc", "[.]abc" }, + { 0, 0, ".abc", ".abc" }, + { FNM_NOMATCH, FNM_PERIOD, ".abc", "?abc" }, + { FNM_NOMATCH, FNM_PERIOD, ".abc", "*abc" }, + { 0, FNM_PERIOD, ".abc", "[.]abc" }, + { 0, FNM_PERIOD, ".abc", ".abc" }, + + { 0, 0, "/.abc", "/?abc" }, + { 0, 0, "/.abc", "/*abc" }, + { 0, 0, "/.abc", "/[.]abc" }, + { 0, 0, "/.abc", "/.abc" }, /* 30 */ + { FNM_NOMATCH, FNM_PERIOD|FNM_PATHNAME, "/.abc", "/?abc" }, + { FNM_NOMATCH, FNM_PERIOD|FNM_PATHNAME, "/.abc", "/*abc" }, + { 0, FNM_PERIOD|FNM_PATHNAME, "/.abc", "/[.]abc" }, + { 0, FNM_PERIOD|FNM_PATHNAME, "/.abc", "/.abc" } + }; + + for (i=0; i < CYG_NELEM(test_case); i++) { + if (test_case[i].result != + fnmatch(test_case[i].pattern, + test_case[i].string, + test_case[i].flags)) { + diag_printf(": test number %d failed\n", i); + failed = true; + } + } + + if (failed) { + CYG_TEST_FAIL_FINISH("fnmatch failed"); + } else { + CYG_TEST_PASS_FINISH("fnmatch passed"); + } +} + +#else + +//========================================================================== +// main + +int main( int argc, char **argv ) +{ + CYG_TEST_INIT(); + + CYG_TEST_NA(NA_MSG); +} + +#endif + +// ------------------------------------------------------------------------- +// EOF fnmatch.c diff --git a/packages/io/usb/serial/slave/v2_0/ChangeLog b/packages/io/usb/serial/slave/v2_0/ChangeLog new file mode 100644 index 00000000..ccf3798a --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/ChangeLog @@ -0,0 +1,37 @@ +2008-07-12 Frank Pagliughi + + * Generic USB Serial package created. + Some files were rearranged during the import and the Documentation + written Andrew Lunn. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2008 FSF +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/io/usb/serial/slave/v2_0/cdl/usbs_serial.cdl b/packages/io/usb/serial/slave/v2_0/cdl/usbs_serial.cdl new file mode 100644 index 00000000..de6a8e78 --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/cdl/usbs_serial.cdl @@ -0,0 +1,260 @@ +# ==================================================================== +# +# usbs_serial.cdl +# +# USB slave-side serial package. +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## +## 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): Frank M. Pagliughi (fmp), SoRo Systems, Inc. +# Contributors: +# Date: 2008-06-04 +# +#####DESCRIPTIONEND#### +# ==================================================================== + +cdl_package CYGPKG_IO_USB_SLAVE_SERIAL { + display "USB slave serial support" + include_dir "cyg/io/usb" + parent CYGPKG_IO_USB_SLAVE + requires { CYGHWR_IO_USB_SLAVE_OUT_ENDPOINTS >= 1 } + requires { CYGHWR_IO_USB_SLAVE_IN_ENDPOINTS >= 1 } + compile usbs_serial.c + implements CYGINT_IO_USB_SLAVE_CLIENTS +# doc ref/io-usb-slave-eth.html + + description " + The USB slave serial package supports the development of USB + peripherals which mimic a serial connection to the host + machine. Such a device creates a relatively simple upgrade to + USB from a legacy serial connection, especially from the + perspective of the host software and device drivers." + + cdl_option CYGDAT_IO_USB_SLAVE_CLASS_TYPE { + display "Serial USB Class" + flavor data + default_value { "ACM" } + legal_values { "ACM" "generic" } + description " + The USB serial module can enumerate as either a generic + (vendor-specific) usb device or a communications class ACM + device. The generic device requires a pair of Bulk + endpoints, while the ACM device also requires an Interrupt + IN endpoint. For a Windows host, the ACM configuration is + required to use the standard 'usbser.sys' device driver, + but for a Linux host, the generic configuration works, and + saves the additional endpoint." + } + cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_EP0 { + display "Name of EP0 structure" + flavor data + default_value { "usbs_at91_ep0" } + description " + The name of the variable that contains the endpoint 0 + structure. This should be set to the EP0 structure for + the desired USB device driver such as usbs_at91_ep0, + usbs_sa11x0_ep0, etc" + } + cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_EP0_MAX_PACKET_SIZE { + display "The size of EP0" + flavor data + default_value 8 + legal_values { 8 16 64 } + description " + The size of the EP0 hardware buffer on the specific USB + chip used." + } + cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_TX_EP_NUM { + display "Tx (USB IN) endpoint number" + flavor data + default_value 1 + description " + The endpoint that should be used for the device-side + transmitter, which is the USB IN direction." + } + cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP { + display "The Tx (USB IN) endpoint structure" + flavor data + default_value { "usbs_at91_ep1" } + description " + The endpoint structure that corresponds to the selected + Tx endpoint number. This is dependent on the USBS device + driver selected, and could be usbs_at91_ep1, + usbs_sa11x0_ep1, etc" + + } + cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_RX_EP_NUM { + display "Rx (USB OUT) endpoint number" + flavor data + default_value 2 + description " + The endpoint that should be used for the device-side + receiver, which is the USB OUT direction." + } + cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP { + display "The Rx (USB OUT) endpoint structure" + flavor data + default_value { "usbs_at91_ep2" } + description " + The endpoint structure that corresponds to the selected + Rx endpoint number. This is dependent on the USBS device + driver selected, and could be usbs_at91_ep2, + usbs_sa11x0_ep2, etc" + } + cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP_NUM { + display "Interrupt IN endpoint number" + flavor data + default_value 3 + active_if { CYGDAT_IO_USB_SLAVE_CLASS_TYPE == "ACM" } + description " + The endpoint that should be used for the ACM Interrupt IN" + } + cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_INTR_EP { + display "Interrupt IN endpoint structure" + flavor data + default_value { "usbs_at91_ep3" } + active_if { CYGDAT_IO_USB_SLAVE_CLASS_TYPE == "ACM" } + description " + The endpoint structure that corresponds to the selected ACM + Interrupt IN endpoint." + } + cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_VENDOR_ID { + display "USB Forum Vendor ID" + flavor data + default_value 0xFFFF + legal_values 1 to 0xFFFF + description " + Each USB vendor has an Vendor ID allocated to it by the + USB-IF organization. Any arbitrary value can be selected + for testing provided that it doesn't conflict with devices + on the development host, but a device should NEVER be + released publicly without a valid Vendor ID" + + } + cdl_option CYGNUM_IO_USB_SLAVE_SERIAL_PRODUCT_ID { + display "USB product ID" + flavor data + default_value 1 + legal_values 1 to 0xFFFF + description " + You are free to select an arbitrary 16-bit Product ID for + a device. The combination of Vendor ID and Product ID + uniquely identified a USB device." + } + cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_MFG_STR { + display "The Device Vendor's Name (Manufacturer String)" + flavor data + default_value { "\"eCos\"" } + description " + The standard USB enumeration allows for a + manufacturer's name which is normally reported to the + user when the device is first plugged into the host." + } + cdl_option CYGDAT_IO_USB_SLAVE_SERIAL_PRODUCT_STR { + display "The Device Product Name" + flavor data + default_value { "\"eCos USB Serial Device\"" } + description " + The standard USB enumeration allows for a product name + which is normally reported to the user when the device + is first plugged into the host." + } + + cdl_option CYGBLD_IO_USB_SLAVE_SERIAL_DEBUG { + display "Enable debug output from the driver" + default_value 0 + flavor bool + description " + The driver may produce debug output which can be + useful to work out why it is not working as expected." + } + + cdl_component CYGPKG_IO_USB_SLAVE_SERIAL_OPTIONS { + display "Build options" + flavor none + + description " + Package-specific build options including control over compiler + flags used only in building this package." + + cdl_option CYGPKG_IO_USB_SLAVE_SERIAL_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building this package. These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_IO_USB_SLAVE_SERIAL_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building this package. These flags are removed from + the set of global flags if present." + } + + + cdl_component CYGBLD_IO_USB_SLAVE_SERIAL_EXAMPLES { + display "Build example programs" + no_define + requires { CYGPKG_IO_FILEIO } + requires { CYGPKG_IO_SERIAL_DEVICES } + description " + Enabling this option will cause the example programs + to be built using the normal test case infrastructure. + They are however not test cases and should not be used + with any automatic test farm running all the + tests. Hence this option is disabled by default." + + cdl_option CYGPKG_IO_USB_SLAVE_SERIAL_TESTS { + display "USBS serial example/test programs" + no_define + flavor data + calculated { "tests/usbserial_echo.c tests/usb2serial.c" } + description " + usbserial_echo will echo charactors received + over the usb serial port back to the sender. + usb2serial acts as a bridge between a USB serial + slave and a real serial port. It is hard coded to use + /dev/ser0." + } + } + } +} \ No newline at end of file diff --git a/packages/io/usb/serial/slave/v2_0/doc/usbs_serial.sgml b/packages/io/usb/serial/slave/v2_0/doc/usbs_serial.sgml new file mode 100644 index 00000000..ef8a22ae --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/doc/usbs_serial.sgml @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eCos Support for USB Serial like Peripherals + + + + + + Introduction + + + Introduction + + eCos support for USB Serial like Peripherals + + + + Introduction + + The eCos USB-Serial package provides additional support for + USB peripherals that look like a serial port to the + host. These can follow the ACM communication device + specification or simpler devices which just have two bulk + endpoints. Microsoft Windows requires ACM mode. Linux should + operate with both modes, however ACM may cause problems since + the eCos driver does not implement all the class descriptors, + so generic mode is recommended. + + + The USB-Serial package is not tied to any specific + hardware. It requires the presence of USB hardware on the + target and a suitable device driver to make endpoints + available for this code to use. The configuration system + cannot load the eCos package automatically for specific + targets, in the way that a USB device driver or an ethernet + driver can be loaded automatically. Instead, the package has + to be added explicitly. When using the command line tools this + will involve an operation like the following: + + + $ ecosconfig add usbs_serial + + + Typically, this will automatically cause the USB device driver + to become active. + + + + + + + + + + Configuration + + + Configuration + Configuration USB Serial like Peripherals + + + Configuration + + The package requires a few basic configurations plus + optionally some additional configuration options. + + + The driver needs two or three endpoints, depending if ACM + communications or a more generic model is used. This is + configured + with CYGDAT_IO_USB_SLAVE_CLASS_TYPE which + can take the value ACM + or generic. + + + The CYGDAT_IO_USB_SLAVE_SERIAL_EP0 must be + configured with the control end point of the USB + device. CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP + must be configured with the endpoint to be used for + transmission and + CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP must be + configured with the end point used for reception. Associated + with these + are CYGNUM_IO_USB_SLAVE_SERIAL_RX_EP_NUM + and CYGNUM_IO_USB_SLAVE_SERIAL_TX_EP_NUM + which are the endpoint numbers and are used during enumeration + of the device. The TX and RX endpoints must operate in BULK + mode. + + + If operation mode ACM is selected a third endpoint is + needed. This must operate in interrupt mode and should be + configured + in CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP + and + CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP_NUM. + + + The USB serial device will make its vendor:product ID known to + the host. This should be configured + with CYGNUM_IO_USB_SLAVE_SERIAL_VENDOR_ID + and CYGNUM_IO_USB_SLAVE_SERIAL_PRODUCT_ID. NOTE: + The default configurations are not valid for products, but + should work for testing. + + + The USB enumeration also contains text strings to describe the + device. This text string can be set + with CYGDAT_IO_USB_SLAVE_SERIAL_PRODUCT_STR. + + + The last configuration option of interest + is CYGPKG_IO_USB_SLAVE_SERIAL_EXAMPLES. When + true example programs will be built when the eCos tests are + built. These are not pass/fail test like other eCos tests, but + examples of how the eCos USB serial class can be used. + + + + + + + + + + Host Configuration + + + Host Configuration + Host Configuration for USB Serial like Peripherals + + + + + Host Configuration + + Configuration for two hosts are listed here, Microsoft Windows + and Linux. It should also be possible to use the eCos USB + serial like peripheral driver with other hosts. + + Linux + + The eCos USB serial like peripheral driver can be used in + Linux in one of two ways. + + + + Using the generic usbserial kernel module passing the + vendor and product ID as module parameters. e.g. + + + modprobe usbserial vendor=0xabcd product=0x1234 + + + would load the kernel module so that it would use a + USB device abcd:1234 as a serial device. + + + + + Using the mini driver provided with eCos in the + host/linux + directory. This driver must be edited and the correct + vendor and product ID set to match the vendor and + product ID used by the device. Once compiled this + driver can be loaded with: + + + modprobe usbserial + modprobe ecos_usbserial + + + This driver is known to compile with kernel versions + 2.6.18 and probably works fine with other + kernels. However it fails to compile with kernels + after 2.6.25. + + + + Both of these methods will result in the Linux Kernel making + a new serial device available. This is typically + named /dev/ttyUSB0. + + + Microsoft Windows + + To install the device in a Microsoft Windows system make use + of the INF file + in host/windows/eCosUsbSerial.inf. Copy + this INF file and usbser.sys from your + version of Windows into an empty directory. Then plug in the + USB device. When prompted to load a driver navigate to the + INF file and select it. + + + + + + + + + + + API Function + + + usbs_serial_start + usbs_serial_init + usbs_serial_start + usbs_serial_wait_until_configured + usbs_serial_is_configured + usbs_serial_start_tx + usbs_serial_wait_for_tx + usbs_serial_tx + usbs_serial_start_rx + usbs_serial_wait_for_rx + usbs_serial_rx + usbs_serial_state_change_handler + + eCos USB Serial like Peripherals API + + + + + + +#include <cyg/io/usb/usbs_serial.h> + + + void + usbs_serial_start + + void + + + void + usbs_serial_init + + usbs_serial * ser + usbs_tx_endpoint * tx_ep + usbs_rx_endpoint * rx_ep + + + void + usbs_serial_wait_until_configured + + void> + + + cyg_bool + usbs_serial_is_configured + + void + + + void + usbs_serial_start_tx + + usbs_serial * ser + const void *buf + int * n + + + int + usbs_serial_wait_for_tx + + usbs_serial * ser + + + void + usbs_serial_start_rx + + usbs_serial * ser + const void *buf + int * n + + + int + usbs_serial_wait_for_rx + + usbs_serial * ser + + + int + usbs_serial_rx + + usbs_serial * ser + const void *buf + int * n + + + void + usbs_serial_state_change_handler + + usbs_control_endpoint * ep + void * data + usbs_state_change change + int prev_state + + + + + + Description + + For examples of how to use this API see the + files .../tests/usbserial_echo.c + and .../tests/usb2serial.c + + + + The first function that needs calling + is usbs_serial_start(). This will initialise + the eCos USB slave layer, creating all the enumeration data and + then let the host know that the device exists. + + + Once the USB subsystem has been started it is necessary to wait + for the host to configure the device using the + function usbs_serial_wait_until_configured(). The + host will assign the device an ID and then load the appropriate + device driver in the host in order to make use the device. + + + Once the device is configured it is then possible to make use of + it, i.e. send and receive data. This transfer of data can be + accomplished either asynchronously or synchronously. It is also + possible to mix asynchronously and synchronously between + receiving and sending data. + + + To perform asynchronous operations the + functions usbs_serial_start_rx() + and usbs_serial_start_tx() is used to + start the operation. These functions start the necessary + actions and then return immediately. At a later time the + functions usbs_serial_wait_for_tx() + or usbs_serial_wait_for_rx() should be + called. These will, if necessary, block and then return the + status and any data for the previously started asynchronous + call. + + + To perform synchronous operations the + functions usbs_serial_rx() + and usbs_serial_tx() are used. These + functions will block until the requested action is complete. + + + + + + diff --git a/packages/io/usb/serial/slave/v2_0/host/linux/.cvsignore b/packages/io/usb/serial/slave/v2_0/host/linux/.cvsignore new file mode 100644 index 00000000..88c404ab --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/host/linux/.cvsignore @@ -0,0 +1,3 @@ +.ecos_usbserial.o.d +.tmp_versions +*.ko \ No newline at end of file diff --git a/packages/io/usb/serial/slave/v2_0/host/linux/Makefile b/packages/io/usb/serial/slave/v2_0/host/linux/Makefile new file mode 100644 index 00000000..e3f4d0b4 --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/host/linux/Makefile @@ -0,0 +1,11 @@ +# Makefile for ecos_usbserial Linux kernel module + +ifneq ($(KERNELRELEASE),) + obj-m := ecos_usbserial.o +else + KDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) +default: + $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules +endif + diff --git a/packages/io/usb/serial/slave/v2_0/host/linux/ecos_usbserial.c b/packages/io/usb/serial/slave/v2_0/host/linux/ecos_usbserial.c new file mode 100644 index 00000000..11708973 --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/host/linux/ecos_usbserial.c @@ -0,0 +1,111 @@ +//========================================================================== +// +// ecos_usbserial.c +// +// Kernel driver for the eCos USB serial driver +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// +// 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): Frank M. Pagliughi (fmp), SoRo Systems, Inc. +// Contributors: +// Date: 2008-06-02 +// Description: Kernel driver for the eCos USB serial driver +// +//####DESCRIPTIONEND#### +//=========================================================================== + +#include +#include +#include +#include +#include +#include + +#define VENDOR_ID 0xFFFF +#define PRODUCT_ID 1 + +static struct usb_device_id id_table[] = { + { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver ecos_usbserial_driver = { + .name = "ecos_usbserial", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table +}; + +static struct usb_serial_driver ecos_usbserial_device = { + .driver = { + .owner = THIS_MODULE, + .name = "ecos_usbserial", + }, + .id_table = id_table, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1 +}; + +static int __init ecos_usbserial_init(void) +{ + int retval; + + retval = usb_serial_register(&ecos_usbserial_device); + if (retval) + return retval; + + retval = usb_register(&ecos_usbserial_driver); + if (retval) { + usb_serial_deregister(&ecos_usbserial_device); + return retval; + } + + return 0; +} + +static void __exit ecos_usbserial_exit(void) +{ + usb_deregister(&ecos_usbserial_driver); + usb_serial_deregister(&ecos_usbserial_device); +} + +module_init(ecos_usbserial_init); +module_exit(ecos_usbserial_exit); + +MODULE_LICENSE("GPL"); + diff --git a/packages/io/usb/serial/slave/v2_0/host/windows/eCosUsbSerial.inf b/packages/io/usb/serial/slave/v2_0/host/windows/eCosUsbSerial.inf new file mode 100644 index 00000000..f96e1160 --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/host/windows/eCosUsbSerial.inf @@ -0,0 +1,49 @@ +; eCos USB Serial INF file for Windows +; This can be used for any USB device that emulates a serial port connection. +; Simply set the VID & PID numbers in this file to the proper values for the +; device, copy this file and the 'usbser.sys' file from your version of Windows +; into the same directory, and load these when prompted by the Windows device +; manager. + +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Provider=eCosUsbSerial +DriverVer=06/02/2008,0.0.0.1 + +[DestinationDirs] +DefaultDestDir=12 ; %windir$\System32\drivers + +[Manufacturer] +eCosUsbSerial=eCosDevices + +[eCosDevices] +"eCosUsbSerial"=InstalleCosUsbSerial,USB\VID_FFFF&PID_0001 + +[InstalleCosUsbSerial] +CopyFiles=CopyeCosUsbFiles +AddReg=eCosUsbReg + +[CopyeCosUsbFiles] +usbser.sys ; The standard Windows USB serial driver + +[eCosUsbReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[InstalleCosUsbSerial.Services] +AddService = usbser,2,eCosUsbSerialService + +[eCosUsbSerialService] +DisplayName = ECOS_USB_SERIAL_NAME +ServiceType = 1 ; driver +StartType = 3 ; on-demand or manual +ErrorControl = 1 ; report errors +ServiceBinary = %12%\usbser.sys ; Driver path: %windir%\System32\drivers +LoadOrderGroup = Base + +[Strings] +ECOS_USB_SERIAL_NAME = "eCos USB Serial Driver" + diff --git a/packages/io/usb/serial/slave/v2_0/include/usbs_serial.h b/packages/io/usb/serial/slave/v2_0/include/usbs_serial.h new file mode 100644 index 00000000..9e7f84ce --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/include/usbs_serial.h @@ -0,0 +1,184 @@ +#ifndef CYGONCE_USBS_SERIAL_H +#define CYGONCE_USBS_SERIAL_H +//========================================================================== +// +// include/usbs_serial.h +// +// Description of the USB slave-side serial device support +// +//========================================================================== +//####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): Frank M. Pagliughi (fmp), SoRo Systems, Inc. +// Contributors: +// Date: 2008-06-02 +// Purpose: +// Description: USB slave-side serial support +// +// +//####DESCRIPTIONEND#### +//========================================================================== + +#ifdef __cplusplus +extern "C" { +#endif + +// +// The primary purpose of the USB slave-side serial code is to provide a +// simple USB connection to the host, especially for embedded systems that +// are upgrading from RS-232 serial connections. The host would see the +// device as if through a serial port, and thus the host software would +// remain unchanged. It would also eliminate the need for a new device +// driver on the host. +// +// On this side (the eCos USB slave side), the application sees the host +// through a normal USB slave connection with two Bulk endpoints - one in +// the IN direction and one in the OUT direction. This module provides the +// necessary USB descriptors to enumerate the device for a single serial +// port, but then the application is free to communicate with the host +// using any desired API: +// - The standard eCos USB slave API +// - The low-level File I/O layer (if USB devtab entries configured) +// - The C stdio functions (again, if USB devtab entries configured) +// - The USB serial API defined here. +// +// The USB serial API is a thin layer over the standard eCos USB functions +// to provide common synchronous and asynchronous transfers over the assigned +// Bulk endpoints. +// + +#include +#include + +// ---------------------------------------------------------------------------- +// The ACM class requests +// + +#define USBS_SERIAL_SEND_ENCAPSULATED_COMMAND 0x00 +#define USBS_SERIAL_GET_ENCAPSULATED_RESPONSE 0x01 +#define USBS_SERIAL_SET_COMM_FEATURE 0x02 +#define USBS_SERIAL_GET_COMM_FEATURE 0x03 +#define USBS_SERIAL_CLEAR_COMM_FEATURE 0x04 + +#define USBS_SERIAL_SET_LINE_CODING 0x20 +#define USBS_SERIAL_GET_LINE_CODING 0x21 +#define USBS_SERIAL_SET_CONTROL_LINE_STATE 0x22 +#define USBS_SERIAL_SEND_BREAK 0x23 + +// ---------------------------------------------------------------------------- +// Data structure to manage the pair of USB endpoints that comprise a single +// serial port connection. Each "port" requires one Bulk IN endpoint and one +// Bulk OUT endpoint. + +typedef struct usbs_serial { + // The communication endpoints. For the first (default) channel, these + // are normally set by the configuration, but can be changed by the + // application, if desired. + usbs_tx_endpoint* tx_ep; + usbs_rx_endpoint* rx_ep; + + // The signal that a transmit operation is complete, and it's result. + cyg_sem_t tx_ready; + int tx_result; + + // The signal that a receive operation is complete, and it's result. + cyg_sem_t rx_ready; + int rx_result; + +} usbs_serial; + +// The package contains one USB serial device. +extern usbs_serial usbs_ser0; + +// It's assumed that there's a single USB slave chip in the system, with a +// single control endpoint 0. The actual variable is contained in the device +// driver, but the USB serial code keeps a pointer to it for driver +// independence. The application might find it useful for overriding low-level +// code or callbacks. +extern usbs_control_endpoint* usbs_serial_ep0; + +// ---------------------------------------------------------------------------- +// A C interface to the serial USB code. +// The application can use this interface, the standard (low-level) USB slave +// API, the standard Unix-like I/O API, or C stdio API. + +// Initialize support for a particular USB serial "port" +// This associates a usbs_serial structure with specific endpoints and +// initializes the structure for communications. +void usbs_serial_init(usbs_serial*, usbs_tx_endpoint*, usbs_rx_endpoint*); + +// Block the calling thread until the host configures the USB device. +void usbs_serial_wait_until_configured(void); + +// Determines if the USB subsystem is configured +cyg_bool usbs_serial_is_configured(void); + +// Start an asynchronous transmit of a single buffer. +void usbs_serial_start_tx(usbs_serial*, const void* buf, int n); + +// Block the calling thread until the transmit completes. +// Returns the result code for the transfer +int usbs_serial_wait_for_tx(usbs_serial*); + +// Blocking, synchronous transmit of a single buffer. +int usbs_serial_tx(usbs_serial*, const void* buf, int n); + +// Start an asynchronous receive of a buffer. +void usbs_serial_start_rx(usbs_serial*, void* buf, int n); + +// Block the calling thread until the receive completes. +// Returns the result code for the transfer +int usbs_serial_wait_for_rx(usbs_serial*); + +// Blocking, synchronous receive of a single buffer. +int usbs_serial_rx(usbs_serial*, void* buf, int n); + +// The default USB-serial state change handler paces the functions +// usbs_serial_wait_until_configured() and usbs_serial_is_configured(). +// The application can override the state chain handler, but chain to +// this function to keep the full USB-serial system working. +void usbs_serial_state_change_handler(usbs_control_endpoint*, void*, + usbs_state_change, int); + +// Starts the USB subsystem +void usbs_serial_start(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // CYGONCE_USBS_SERIAL_H + diff --git a/packages/io/usb/serial/slave/v2_0/src/usbs_serial.c b/packages/io/usb/serial/slave/v2_0/src/usbs_serial.c new file mode 100644 index 00000000..52b464d9 --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/src/usbs_serial.c @@ -0,0 +1,545 @@ +//========================================================================== +// +// usbs_serial.c +// +// Support for slave-side USB serial devices. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// +// 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): Frank M. Pagliughi (fmp), SoRo Systems, Inc. +// Date: 2008-06-02 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(CYGBLD_IO_USB_SLAVE_SERIAL_DEBUG) +#define DBG diag_printf +#else +#define DBG (1) ? (void)0 : diag_printf +#endif + +#define EP0_MAX_PACKET_SIZE CYGNUM_IO_USB_SLAVE_SERIAL_EP0_MAX_PACKET_SIZE + +extern usbs_control_endpoint CYGDAT_IO_USB_SLAVE_SERIAL_EP0; +extern usbs_tx_endpoint CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP; +extern usbs_rx_endpoint CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP; + +#define TX_EP_NUM CYGNUM_IO_USB_SLAVE_SERIAL_TX_EP_NUM +#define RX_EP_NUM CYGNUM_IO_USB_SLAVE_SERIAL_RX_EP_NUM +#define INTR_EP_NUM CYGNUM_IO_USB_SLAVE_SERIAL_INTR_EP_NUM +#define EP0 (&CYGDAT_IO_USB_SLAVE_SERIAL_EP0) +#define TX_EP (&CYGDAT_IO_USB_SLAVE_SERIAL_TX_EP) +#define RX_EP (&CYGDAT_IO_USB_SLAVE_SERIAL_RX_EP) +#define INTR_EP (&CYGDAT_IO_USB_SLAVE_SERIAL_INTR_EP) + + +#define VENDOR_ID CYGNUM_IO_USB_SLAVE_SERIAL_VENDOR_ID +#define PRODUCT_ID CYGNUM_IO_USB_SLAVE_SERIAL_PRODUCT_ID + +#define USB_MAX_STR_LEN 256 + +#define LO_BYTE_16(word16) ((cyg_uint8) ((word16) & 0xFF)) +#define HI_BYTE_16(word16) ((cyg_uint8) (((word16) >> 8) & 0xFF)) + +#define BYTE0_32(word32) ((cyg_uint8) ((word32) & 0xFF)) +#define BYTE1_32(word32) ((cyg_uint8) (((word32) >> 8) & 0xFF)) +#define BYTE2_32(word32) ((cyg_uint8) (((word32) >> 16) & 0xFF)) +#define BYTE3_32(word32) ((cyg_uint8) (((word32) >> 24) & 0xFF)) + + +#define MFG_STR_INDEX '\x01' +#define PRODUCT_STR_INDEX '\x02' + +#define USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH(interfaces, endpoints) \ + (USB_CONFIGURATION_DESCRIPTOR_LENGTH + \ + ((interfaces) * USB_INTERFACE_DESCRIPTOR_LENGTH) + \ + ((endpoints) * USB_ENDPOINT_DESCRIPTOR_LENGTH)) + + +#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM + #define USBS_SERIAL_DEVICE_CLASS 2 + #define USBS_SERIAL_NUM_IFACE 2 + #define USBS_SERIAL_NUM_ENDP 3 + #define USBS_SERIAL_DATA_IFACE_CLASS 0x0A // Data +#else + #define USBS_SERIAL_DEVICE_CLASS 0 + #define USBS_SERIAL_NUM_IFACE 1 + #define USBS_SERIAL_NUM_ENDP 2 + #define USBS_SERIAL_DATA_IFACE_CLASS 0xFF // Vendor +#endif + +// ----- Configuration Descriptor ----- + +static const usb_configuration_descriptor usb_configuration = { + length: sizeof(usb_configuration_descriptor), + type: USB_CONFIGURATION_DESCRIPTOR_TYPE, + total_length_lo: + USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_LO(USBS_SERIAL_NUM_IFACE, + USBS_SERIAL_NUM_ENDP), + total_length_hi: + USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH_HI(USBS_SERIAL_NUM_IFACE, + USBS_SERIAL_NUM_ENDP), + number_interfaces: USBS_SERIAL_NUM_IFACE, + configuration_id: 1, + configuration_str: 0, + attributes: (USB_CONFIGURATION_DESCRIPTOR_ATTR_REQUIRED | + USB_CONFIGURATION_DESCRIPTOR_ATTR_SELF_POWERED), + max_power: 50 +}; + +// ----- Interface Descriptor ----- + +static const usb_interface_descriptor usb_interface[] = { + +#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM + { + length: sizeof(usb_interface_descriptor), + type: USB_INTERFACE_DESCRIPTOR_TYPE, + interface_id: 0, + alternate_setting: 0, + number_endpoints: 1, + interface_class: 0x02, // Comm class + interface_subclass: 0x02, + interface_protocol: 0x01, + interface_str: 0x00 + }, + { + length: sizeof(usb_interface_descriptor), + type: USB_INTERFACE_DESCRIPTOR_TYPE, + interface_id: 1, + alternate_setting: 0, + number_endpoints: 2, + interface_class: USBS_SERIAL_DATA_IFACE_CLASS, + interface_subclass: 0x00, + interface_protocol: 0x00, + interface_str: 0x00 + } +#else + { + length: sizeof(usb_interface_descriptor), + type: USB_INTERFACE_DESCRIPTOR_TYPE, + interface_id: 0, + alternate_setting: 0, + number_endpoints: 2, + interface_class: USBS_SERIAL_DATA_IFACE_CLASS, + interface_subclass: 0x00, + interface_protocol: 0x00, + interface_str: 0x00 + } +#endif +}; + +// ----- Endpoint Descriptors ----- + +static const usb_endpoint_descriptor usb_endpoints[] = +{ +#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM + // Interrupt in endpoint + { + sizeof(usb_endpoint_descriptor), + USB_ENDPOINT_DESCRIPTOR_TYPE, + USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN | INTR_EP_NUM, + USB_ENDPOINT_DESCRIPTOR_ATTR_INTERRUPT, + 0x40, + 0, + 255 + }, +#endif + + // Tx (Bulk IN) Endpoint Descriptor + { + sizeof(usb_endpoint_descriptor), + USB_ENDPOINT_DESCRIPTOR_TYPE, + USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN | TX_EP_NUM, + USB_ENDPOINT_DESCRIPTOR_ATTR_BULK, + 0x40, + 0, + 0 + }, + + // Rx (Bulk OUT) Endpoint Descriptor + { + sizeof(usb_endpoint_descriptor), + USB_ENDPOINT_DESCRIPTOR_TYPE, + USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT | RX_EP_NUM, + USB_ENDPOINT_DESCRIPTOR_ATTR_BULK, + 0x40, + 0, + 0 + } +}; + +// ----- String Descriptors ----- + +static char mfg_str_descr[USB_MAX_STR_LEN], + product_str_descr[USB_MAX_STR_LEN]; + + +static const char* usb_strings[] = { + "\x04\x03\x09\x04", + mfg_str_descr, + product_str_descr +}; + +// ----- Enumeration Data w/ Device Descriptor ----- + +static usbs_enumeration_data usb_enum_data = { + { + length: sizeof(usb_device_descriptor), + type: USB_DEVICE_DESCRIPTOR_TYPE, + usb_spec_lo: 0x00, + usb_spec_hi: 0x02, + device_class: USBS_SERIAL_DEVICE_CLASS, + device_subclass: 0, + device_protocol: 0, + max_packet_size: EP0_MAX_PACKET_SIZE, + vendor_lo: LO_BYTE_16(VENDOR_ID), + vendor_hi: HI_BYTE_16(VENDOR_ID), + product_lo: LO_BYTE_16(PRODUCT_ID), + product_hi: HI_BYTE_16(PRODUCT_ID), + device_lo: 0x00, + device_hi: 0x00, + manufacturer_str: MFG_STR_INDEX, + product_str: PRODUCT_STR_INDEX, + serial_number_str: 0, + number_configurations: 1 + }, + + total_number_interfaces: USBS_SERIAL_NUM_IFACE, + total_number_endpoints: USBS_SERIAL_NUM_ENDP, + total_number_strings: 3, + configurations: &usb_configuration, + interfaces: usb_interface, + endpoints: usb_endpoints, + strings: (const unsigned char **) usb_strings +}; + +// -------------------------------------------------------------------------- +// USBS Serial Data +// -------------------------------------------------------------------------- + +usbs_control_endpoint* usbs_serial_ep0 = EP0; + +// Lock for the state. +cyg_mutex_t usbs_serial_lock; + +// Condition variable for state changes +cyg_cond_t usbs_serial_state_cond; + +int usbs_serial_state; + +usbs_serial usbs_ser0 = { + tx_ep: TX_EP, + rx_ep: RX_EP, + tx_result: 0, + rx_result: 0, +}; + +static void (*usbs_serial_app_state_change_fn)(struct usbs_control_endpoint*, + void*, usbs_state_change, int) += 0; + +// -------------------------------------------------------------------------- +// Create a USB String Descriptor from a C string. + +void +usbs_serial_create_str_descriptor(char descr[], const char *str) +{ + int i, n = strlen(str); + + if (n > (USB_MAX_STR_LEN/2 - 2)) + n = USB_MAX_STR_LEN/2 - 2; + + descr[0] = (cyg_uint8) (2*n + 2); + descr[1] = USB_DEVREQ_DESCRIPTOR_TYPE_STRING; + + for (i=0; icontrol_buffer; + static cyg_uint8 rsp_buf[32]; + cyg_uint32 baud = 38400; // Arbitrary, fake value to return to the host. + + DBG("USB Serial ACM Class Handler: "); + + switch (req->request) { + + case USBS_SERIAL_SET_LINE_CODING : + DBG("ACM Request: Set Line Coding\n"); + result = USBS_CONTROL_RETURN_HANDLED; + break; + + case USBS_SERIAL_GET_LINE_CODING : + DBG("ACM Request: Get Line Coding\n"); + rsp_buf[0] = BYTE0_32(baud); + rsp_buf[1] = BYTE1_32(baud); + rsp_buf[2] = BYTE2_32(baud); + rsp_buf[3] = BYTE3_32(baud); + rsp_buf[4] = 0; // One stop bit + rsp_buf[5] = 0; // No parity + rsp_buf[6] = 8; // 8 data bits + ep0->buffer = rsp_buf; + ep0->buffer_size = 7; + result = USBS_CONTROL_RETURN_HANDLED; + break; + + default : + DBG("*** Unhandled ACM Request: 0x%02X ***\n", + (unsigned) req->request); + } + + return result; +} +#endif // CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM + +// -------------------------------------------------------------------------- +// Callback for a USB state change + +void +usbs_serial_state_change_handler(usbs_control_endpoint* ep, void* data, + usbs_state_change change, int prev_state) +{ +#if defined(CYGBLD_IO_USB_SLAVE_SERIAL_DEBUG) + const char *STATE_CHG_STR[] = { "Detached", "Attached", "Powered", "Reset", + "Addressed", "Configured", "Deconfigured", + "Suspended", "Resumed" }; + + if (change > 0) { + DBG("### %d:%s ###\n", change, STATE_CHG_STR[(int) change-1]); + } +#endif + + // Called from DSR, cond broadcast should be ok without mutex lock + usbs_serial_state = usbs_serial_ep0->state; + cyg_cond_broadcast(&usbs_serial_state_cond); + + if (usbs_serial_app_state_change_fn) + (*usbs_serial_app_state_change_fn)(ep, data, change, prev_state); +} + +// -------------------------------------------------------------------------- +// Block the calling thread until the USB is configured. + +void +usbs_serial_wait_until_configured(void) +{ + cyg_mutex_lock(&usbs_serial_lock); + while (usbs_serial_state != USBS_STATE_CONFIGURED) + cyg_cond_wait(&usbs_serial_state_cond); + cyg_mutex_unlock(&usbs_serial_lock); +} + +// -------------------------------------------------------------------------- +// Determine if the device is currently configured. + +cyg_bool +usbs_serial_is_configured(void) +{ + return usbs_serial_state == USBS_STATE_CONFIGURED; +} + +// -------------------------------------------------------------------------- +// Callback for when a transmit is complete + +static void +usbs_serial_tx_complete(void *p, int result) +{ + usbs_serial* ser = (usbs_serial*) p; + ser->tx_result = result; + cyg_semaphore_post(&ser->tx_ready); +} + +// -------------------------------------------------------------------------- +// Callback for when a receive is complete + +static void +usbs_serial_rx_complete(void *p, int result) +{ + usbs_serial* ser = (usbs_serial*) p; + ser->rx_result = result; + cyg_semaphore_post(&ser->rx_ready); +} + +// -------------------------------------------------------------------------- +// Start an asynchronous transmit of a buffer. +// + +void +usbs_serial_start_tx(usbs_serial* ser, const void* buf, int n) +{ + usbs_start_tx_buffer(ser->tx_ep, (unsigned char*) buf, n, + usbs_serial_tx_complete, ser); +} + +// -------------------------------------------------------------------------- +// Block the caller until the transmit is complete + +int +usbs_serial_wait_for_tx(usbs_serial* ser) +{ + cyg_semaphore_wait(&ser->tx_ready); + return ser->tx_result; +} + +// -------------------------------------------------------------------------- +// Perform a synchronous transmit and wait for it to complete. + +int +usbs_serial_tx(usbs_serial* ser, const void* buf, int n) +{ + usbs_serial_start_tx(ser, buf, n); + return usbs_serial_wait_for_tx(ser); +} + +// -------------------------------------------------------------------------- +// Start an asynchronous receive of a buffer. + +void +usbs_serial_start_rx(usbs_serial* ser, void* buf, int n) +{ + usbs_start_rx_buffer(ser->rx_ep, (unsigned char*) buf, n, + usbs_serial_rx_complete, ser); +} + +// -------------------------------------------------------------------------- +// Block the caller until the receive is complete + +int +usbs_serial_wait_for_rx(usbs_serial* ser) +{ + cyg_semaphore_wait(&ser->rx_ready); + return ser->rx_result; +} + +// -------------------------------------------------------------------------- +// Perform a synchronous receive and wait for it to complete. + +int +usbs_serial_rx(usbs_serial* ser, void* buf, int n) +{ + usbs_serial_start_rx(ser, buf, n); + return usbs_serial_wait_for_rx(ser); +} + +// -------------------------------------------------------------------------- +// Initialize a serial port structure. + +void +usbs_serial_init(usbs_serial* ser, usbs_tx_endpoint* tx_ep, + usbs_rx_endpoint* rx_ep) +{ + ser->tx_ep = tx_ep; + ser->rx_ep = rx_ep; + + cyg_semaphore_init(&ser->tx_ready, 0); + cyg_semaphore_init(&ser->rx_ready, 0); +} + +// -------------------------------------------------------------------------- +// Start the USB subsystem + +void +usbs_serial_start(void) +{ + usbs_serial_init(&usbs_ser0, TX_EP, RX_EP); + + cyg_mutex_init(&usbs_serial_lock); + cyg_cond_init(&usbs_serial_state_cond, &usbs_serial_lock); + + // Make the mfg & product names into USB string descriptors + + usbs_serial_create_str_descriptor(mfg_str_descr, + CYGDAT_IO_USB_SLAVE_SERIAL_MFG_STR); + usbs_serial_create_str_descriptor(product_str_descr, + CYGDAT_IO_USB_SLAVE_SERIAL_PRODUCT_STR); + + // ----- Set up enumeration & USB callbacks ----- + + usbs_serial_state = usbs_serial_ep0->state; + + usbs_serial_ep0->enumeration_data = &usb_enum_data; + + if (usbs_serial_ep0->state_change_fn) + usbs_serial_app_state_change_fn = usbs_serial_ep0->state_change_fn; + + usbs_serial_ep0->state_change_fn = usbs_serial_state_change_handler; + +#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM + if (!usbs_serial_ep0->class_control_fn) + usbs_serial_ep0->class_control_fn = usbs_serial_acm_class_handler; +#endif + + // ----- Start USB subsystem ----- + + usbs_start(usbs_serial_ep0); +} diff --git a/packages/io/usb/serial/slave/v2_0/tests/usb2serial.c b/packages/io/usb/serial/slave/v2_0/tests/usb2serial.c new file mode 100644 index 00000000..78f2f223 --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/tests/usb2serial.c @@ -0,0 +1,358 @@ +//========================================================================== +// +// usb2serial.c +// +// Example application for the USB serial layer in eCos. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// +// 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): Frank M. Pagliughi (fmp), SoRo Systems, Inc. +// Contributors: +// Date: 2008-06-02 +// Description: USB serial example application. +// +//####DESCRIPTIONEND#### +//=========================================================================== + +#include +#include +#include +#include +#include + +// Replace this with any other USB driver desired. +#include +#include +#include + +#include +#include +#include +#include +#include + +// This application creates a USB-serial converter. To the host it will appear +// as a single serial USB port, such as /dev/ttyUSB0 for a Linux host. +// Any characters received from the USB host will be sent out the serial port +// and visa-verse. It creates a separate, dedicated thread for each direction. +// +// It uses the eCos USB-serial layer to enumerate with the USB host and monitor +// the connection, but then uses standard C I/O functions to perform the +// communications. +// +// The USB serial module can be configured as a generic adapter or an an ACM +// communications class device. For the latter, the application handles the +// USB communications class requests which allows it to receive requests from +// the host to set serial parameters, like the baud rate. This actually turns +// this example into a more realistic USB-serial adapter that can be configured +// dynamically by the host. +// +// The eCos library must be configured with the packages for USB slave, USB +// serial, and File I/O. It also requires the proper serial port driver for the +// target platform. +// +// This example was tested with the AT91SAM7S-EK board, but should work with any +// board that has a USB slave and serial port, and the necessary drivers. + + +// Comment this line out to remove debug output. +#define DEBUG_OUTPUT + +#if defined(DEBUG_OUTPUT) +#define DBG diag_printf +#else +#define DBG (1) ? (void)0 : diag_printf +#endif + +// Set these to the USB devtab entries for the Tx and Rx Bulk endpoints +// selected in the configuration of the USB serial subsystem. +#define USB_TX_DEV "/dev/usbs1" +#define USB_RX_DEV "/dev/usbs2" + +// Set this for any available serial port on the target. +#define SER_DEV "/dev/ser0" + +// Buffer for incoming USB bulk data. The local USB driver can probably split +// packets, but just in case, making this the page size of the host might be +// helpful. +#define BUF_SIZE 4096 +static char usb2ser_buf[BUF_SIZE]; + +// The threads +cyg_thread thread[2]; + +// Space for two 4K stacks +#define THREAD_STACK_SIZE 4096 +char stack[2][THREAD_STACK_SIZE]; + +// The handles for the threads +cyg_handle_t usb2ser_thread, + ser2usb_thread; + +// -------------------------------------------------------------------------- +// For an ACM serial device we can handle the USB class messages to deal with +// requests from the host like setting the serial parameters (baud rate, +// etc). + +#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM + +static cyg_uint8 acm_buf[32]; +static cyg_uint32 baud = 34800; + +// -------------------------------------------------------------------------- +// Handler for the completion of a SetLineCoding request from the host. +// The 'acm_buf' should contain the 7-byte request OUT packet from the +// host. This contains a request to change the serial parameters. +// In this example function, we will accept a few different baud rates. +// To keep the example relatively simple, though, we keep the other serial +// parameters to 1 stop bit, no parity, 8 data bits. + +static usbs_control_return +acm_set_line_coding(usbs_control_endpoint* ep0, int n) +{ + int err; + cyg_uint32 req_baud; + cyg_io_handle_t handle; + + // Get the requested baud rate from the received ctrl OUT packet + req_baud = ((acm_buf[3] << 24) | (acm_buf[2] << 16) | + (acm_buf[1] << 8) | acm_buf[0]); + + DBG("Set Baud: %u\n", (unsigned) baud); + + // Look up the serial handle and attempt to set the baud rate. + if (cyg_io_lookup(SER_DEV, &handle) == 0) { + cyg_serial_info_t ser_info; + cyg_uint32 len = sizeof(ser_info); + + switch (baud) { + case 9600 : ser_info.baud = CYGNUM_SERIAL_BAUD_9600; break; + case 38400 : ser_info.baud = CYGNUM_SERIAL_BAUD_38400; break; + case 115200 : ser_info.baud = CYGNUM_SERIAL_BAUD_115200; break; + default: + DBG("Unsupported baud rate\n"); + return USBS_CONTROL_RETURN_HANDLED; + } + ser_info.stop = CYGNUM_SERIAL_STOP_1; + ser_info.parity = CYGNUM_SERIAL_PARITY_NONE; + ser_info.word_length = CYGNUM_SERIAL_WORD_LENGTH_8; + ser_info.flags = 0; + + err = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, + &ser_info, &len); + if (err == 0) + baud = req_baud; + else { + DBG("Error setting serial params\n"); + } + } + else { + DBG("Error looking up serial device: %s\n", SER_DEV); + } + return USBS_CONTROL_RETURN_HANDLED; +} + +// -------------------------------------------------------------------------- +// Handler for the ACM class messages. +// +static usbs_control_return +acm_class_handler(usbs_control_endpoint* ep0, void* data) +{ + usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN; + + usb_devreq *req = (usb_devreq *) ep0->control_buffer; + + static cyg_uint8 rsp_buf[32]; + + DBG("ACM Class Handler\n"); + + switch (req->request) { + + case USBS_SERIAL_SET_LINE_CODING : + DBG("Set Line Coding\n"); + memset(acm_buf, 0, 32); + ep0->buffer = acm_buf; + ep0->buffer_size = 7; + ep0->complete_fn = acm_set_line_coding; + result = USBS_CONTROL_RETURN_HANDLED; + break; + + case USBS_SERIAL_GET_LINE_CODING : + DBG("Get Line Coding\n"); + rsp_buf[0] = baud & 0xFF; + rsp_buf[1] = (baud >> 8) & 0xFF; + rsp_buf[2] = (baud >> 16) & 0xFF; + rsp_buf[3] = (baud >> 24) & 0xFF; + rsp_buf[4] = 0; // One stop bit + rsp_buf[5] = 0; // No parity + rsp_buf[6] = 8; // 8 data bits + ep0->buffer = rsp_buf; + ep0->buffer_size = 7; + result = USBS_CONTROL_RETURN_HANDLED; + break; + + default : + DBG("*** Unhandled ACM Request: 0x%02X ***\n", + (unsigned) req->request); + } + + return result; +} + +#endif // CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM + +// -------------------------------------------------------------------------- +// Thread receives packets from the USB and sends them out the serial port +// It uses a buffered stdio input, an un-buffered low-level file output. +// This isn't terribly efficient, but rather an example of both methods. + +void usb2ser_func(cyg_addrword_t data) +{ + int c; + FILE *rxf = fopen(USB_RX_DEV, "r"); + int txh = open(SER_DEV, O_WRONLY, 0); + + DBG("Usb2Ser: Thread starting\n"); + + if (!rxf) { + DBG("Error opening USB rx port\n"); + return; + } + + if (txh < 0) { + DBG("Error opening serial tx port\n"); + return; + } + + // Give the USB receiver an adequate buffer. + setvbuf(rxf, usb2ser_buf, _IOFBF, BUF_SIZE); + + while (1) { + + // ----- Wait for the host to configure ----- + + DBG("Usb2Ser: Waiting for USB configuration\n"); + usbs_serial_wait_until_configured(); + cyg_thread_delay((cyg_tick_count_t) 10); + + // ----- While configured read data & send out serial port ----- + + DBG("Usb2Ser: USB configured\n"); + while (usbs_serial_is_configured()) { + if ((c = getc(rxf)) < 0) { + DBG("*** USB Read Error: %d ***\n", c); + } + else { + char ch = (char) c; + write(txh, &ch, 1); + } + } + } +} + +// -------------------------------------------------------------------------- +// Thread receives packets from the serial port and sends them out the USB +// It uses a buffered stdio input, an un-buffered low-level file output. +// This isn't terribly efficient, but rather an example of both methods. + +void ser2usb_func(cyg_addrword_t data) +{ + int c; + FILE *rxf = fopen(SER_DEV, "r"); + int txh = open(USB_TX_DEV, O_WRONLY, 0); + + DBG("Ser2Usb: Thread starting\n"); + + if (!rxf) { + DBG("Error opening serial rx port\n"); + return; + } + + if (txh < 0) { + DBG("Error opening USB tx port\n"); + return; + } + + while (1) { + + // ----- Wait for the host to configure ----- + + DBG("Ser2Usb: Waiting for USB configuration\n"); + usbs_serial_wait_until_configured(); + cyg_thread_delay((cyg_tick_count_t) 10); + + // ----- While configured read data & send out serial port ----- + + DBG("Ser2Usb: USB configured\n"); + while (usbs_serial_is_configured()) { + if ((c = getc(rxf)) < 0) { + DBG("*** Console Read Error: %d ***\n", c); + } + else { + char ch = (char) c; + write(txh, &ch, 1); + } + } + } +} + +// -------------------------------------------------------------------------- +// Application Startup +// -------------------------------------------------------------------------- + +void cyg_user_start(void) +{ + DBG("Entering cyg_user_start() function\n"); + +#ifdef CYGDAT_IO_USB_SLAVE_CLASS_TYPE_ACM + // Override the class handler to use ours. + usbs_serial_ep0->class_control_fn = acm_class_handler; +#endif + + cyg_thread_create(4, usb2ser_func, (cyg_addrword_t) 0, + "Usb2Serial", (void *) stack[0], THREAD_STACK_SIZE, + &usb2ser_thread, &thread[0]); + + cyg_thread_create(4, ser2usb_func, (cyg_addrword_t) 1, + "Serial2Usb", (void *) stack[1], THREAD_STACK_SIZE, + &ser2usb_thread, &thread[1]); + + // Start USB subsystem + usbs_serial_start(); + + // Start the threads running. + cyg_thread_resume(usb2ser_thread); + cyg_thread_resume(ser2usb_thread); +} + diff --git a/packages/io/usb/serial/slave/v2_0/tests/usbserial_echo.c b/packages/io/usb/serial/slave/v2_0/tests/usbserial_echo.c new file mode 100644 index 00000000..9ffab93e --- /dev/null +++ b/packages/io/usb/serial/slave/v2_0/tests/usbserial_echo.c @@ -0,0 +1,126 @@ +//========================================================================== +// +// usb_serial_echo.c +// +// Example application for the USB serial layer in eCos. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// +// 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): Frank M. Pagliughi (fmp), SoRo Systems, Inc. +// Contributors: +// Date: 2008-06-02 +// Description: USB serial example application. +// +//####DESCRIPTIONEND#### +//=========================================================================== + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DEBUG_OUTPUT + +#if defined(DEBUG_OUTPUT) +#define DBG diag_printf +#else +#define DBG (1) ? (void)0 : diag_printf +#endif + +typedef unsigned char byte; + +// -------------------------------------------------------------------------- +// Data & Callback(s) +// -------------------------------------------------------------------------- + +#define BUF_SIZE 4096 + +static byte rx_buf[2][BUF_SIZE+1], tx_buf[BUF_SIZE+1]; + +// -------------------------------------------------------------------------- +// Main Routine +// -------------------------------------------------------------------------- + +int main(void) +{ + int n; + unsigned ibuf, next_buf; + + // ----- Start USB subsystem ----- + + usbs_serial_start(); + + // ----- Get data from host and send it back ----- + + while (1) { + ibuf = 0; + + // ----- Wait for the host to configure ----- + + usbs_serial_wait_until_configured(); + cyg_thread_delay((cyg_tick_count_t) 10); + + // ----- While configured read data & print to screen ----- + + usbs_serial_start_rx(&usbs_ser0, rx_buf[ibuf], BUF_SIZE); + + while (usbs_serial_is_configured()) { + + n = usbs_serial_wait_for_rx(&usbs_ser0); + next_buf = ibuf ^ 1; + + usbs_serial_start_rx(&usbs_ser0, rx_buf[next_buf], BUF_SIZE); + + if (n < 0) { + DBG("*** I/O Error: %d ***\n", n); + } + else { + memcpy(tx_buf, rx_buf[ibuf], n); + usbs_serial_tx(&usbs_ser0, tx_buf, n); + rx_buf[ibuf][n] = '\0'; + DBG("%s", rx_buf[ibuf]); + } + + ibuf = next_buf; + } + } + + return 0; +} + diff --git a/packages/io/usb/slave/v2_0/host/bulk-boundaries.tcl b/packages/io/usb/slave/v2_0/host/bulk-boundaries.tcl new file mode 100644 index 00000000..deceb1ce --- /dev/null +++ b/packages/io/usb/slave/v2_0/host/bulk-boundaries.tcl @@ -0,0 +1,105 @@ +#=============================================================================== +# +# bulk-boundaries.tcl +# +# Support for USB testing +# +#=============================================================================== +#####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. +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +#=============================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): asl +# Date: 2006-04-21 +# Purpose: Test the bulk endpoints with different sizes of packets +# at the important boundaries. +# +#####DESCRIPTIONEND#### +#=============================================================================== + +set pktsizes { 1 2 3 4 5 7 8 9 15 16 17 31 32 33 63 64 65 127 128 129 \ + 255 256 257 511 512 513 1023 1024 1025 2047 2048 2049 \ + 4095 4096 4097 } + + if { 0 != [llength $usbtest::bulk_in_endpoints] } { + puts "Bulk IN endpoints: $usbtest::bulk_in_endpoints" + foreach ep $usbtest::bulk_in_endpoints { + puts [format " %2d: packet sizes %d to %d, padding %d" $ep \ + $usbtest::bulk_in($ep,min_size) \ + $usbtest::bulk_in($ep,max_size) \ + $usbtest::bulk_in($ep,max_in_padding)] + foreach pktsize $pktsizes { + if { $pktsize <= $usbtest::bulk_in($ep,max_size) } { + puts [format "Testing IN endpoint %d with packet size %4d" \ + $ep $pktsize] + usbtest::reset + usbtest::bulktest $ep in 5 txsize1=$pktsize format=byteseq \ + data1=42 data* $usbtest::MULTIPLIER \ + data+ $usbtest::INCREMENT + if { [usbtest::start 10] } { + puts "Passed" + } else { + puts "Failed" + foreach result $usbtest::results { + puts $result + } + } + } + } + } + } + +if { 0 != [llength $usbtest::bulk_out_endpoints] } { + puts "Bulk OUT endpoints: $usbtest::bulk_out_endpoints" + foreach ep $usbtest::bulk_out_endpoints { + puts [format " %2d: packet sizes %d to %d" $ep \ + $usbtest::bulk_out($ep,min_size) \ + $usbtest::bulk_out($ep,max_size)] + foreach pktsize $pktsizes { + if { $pktsize <= $usbtest::bulk_out($ep,max_size) } { + puts [format "Testing OUT endpoint %d with packet size %4d" \ + $ep $pktsize] + usbtest::reset + usbtest::bulktest $ep out 5 txsize1=$pktsize format=byteseq \ + data1=42 data* $usbtest::MULTIPLIER \ + data+ $usbtest::INCREMENT rxsize1=4096 + if { [usbtest::start 10] } { + puts "Passed" + } else { + puts "Failed" + foreach result $usbtest::results { + puts $result + } + } + } + } + } +} diff --git a/packages/isoinfra/v2_0/include/fnmatch.h b/packages/isoinfra/v2_0/include/fnmatch.h new file mode 100644 index 00000000..61c7a97c --- /dev/null +++ b/packages/isoinfra/v2_0/include/fnmatch.h @@ -0,0 +1,68 @@ +#ifndef CYGONCE_ISO_FNMATCH_H +#define CYGONCE_ISO_FNMATCH_H +/*======================================================================== +// +// fnmatch.h +// +// fnmatch() +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2007 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): Peter Korsgaard +// Contributors: +// Date: 2007-01-24 +// Purpose: This file provides the fnmatch() function +// required by POSIX 1003.2-1992, section B.6. +// Description: The real contents of this file get set from the +// configuration (set by the implementation) +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//====================================================================== +*/ + +/* CONFIGURATION */ + +#include /* Configuration header */ + +/* INCLUDES */ + +#ifdef CYGBLD_ISO_FNMATCH_HEADER +# include CYGBLD_ISO_FNMATCH_HEADER +#endif + +#endif /* CYGONCE_ISO_FNMATCH_H multiple inclusion protection */ + +/* EOF fnmatch.h */ diff --git a/packages/isoinfra/v2_0/include/sys/time.h b/packages/isoinfra/v2_0/include/sys/time.h new file mode 100644 index 00000000..6e547f9c --- /dev/null +++ b/packages/isoinfra/v2_0/include/sys/time.h @@ -0,0 +1,88 @@ +#ifndef CYGONCE_ISO_SYS_TIME_H +#define CYGONCE_ISO_SYS_TIME_H +/*======================================================================== +// +// sys/time.h +// +// struct timeval and gettimeofday() +// +//======================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005 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): Alexander Neundorf +// Contributors: +// Date: 2005-10-04 +// Purpose: This file provides the time macros, types and functions +// required by ISO C and POSIX 1003.1. +// Description: The real contents of this file get set from the +// configuration (set by the implementation) +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//====================================================================== +*/ + +/* CONFIGURATION */ + +#include /* Configuration header */ + +/* INCLUDES */ + +/* This is the "standard" way to get NULL and size_t from stddef.h, + * which is the canonical location of the definitions. + */ +#define __need_NULL +#define __need_size_t +#include + +#include +#ifdef CYGBLD_ISO_STRUCTTIMEVAL_HEADER +# include CYGBLD_ISO_STRUCTTIMEVAL_HEADER +#else + +/* + * Structure returned by gettimeofday(2), + * and used in other calls such as select(2). + */ +struct timeval { + time_t tv_sec; /* seconds */ + time_t tv_usec; /* and microseconds */ +}; + +#endif + + +#endif /* CYGONCE_ISO_SYS_TIME_H multiple inclusion protection */ + +/* EOF sys/time.h */ diff --git a/packages/kernel/v2_0/tests/timeslice2.c b/packages/kernel/v2_0/tests/timeslice2.c new file mode 100644 index 00000000..b71fd0f0 --- /dev/null +++ b/packages/kernel/v2_0/tests/timeslice2.c @@ -0,0 +1,307 @@ +//========================================================================== +// +// timeslice2.c +// +// Timeslice 2 test +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2006 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. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2001-06-18 +// Description: An additional timeslicing test. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#include + +#include + +#include + +#include +#include + +//========================================================================== + +#if defined(CYGSEM_KERNEL_SCHED_TIMESLICE) && \ + defined(CYGFUN_KERNEL_API_C) && \ + defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \ + defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \ + !defined(CYGDBG_INFRA_DIAG_USE_DEVICE) && \ + (CYGNUM_KERNEL_SCHED_PRIORITIES > 12) + +//========================================================================== + +#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL + +#define NTHREADS_MAX (CYGNUM_KERNEL_CPU_MAX*6) + +static int ncpus = CYGNUM_KERNEL_CPU_MAX; + +static char test_stack[STACK_SIZE]; +static cyg_thread test_thread; +static cyg_handle_t main_thread; + +static char hipri_stack[STACK_SIZE]; +static cyg_thread hipri_thread_obj; +static cyg_handle_t hipri_thread; + +static char stacks[NTHREADS_MAX][STACK_SIZE]; +static cyg_thread test_threads[NTHREADS_MAX]; +static cyg_handle_t threads[NTHREADS_MAX]; + +static volatile int failed = false; + +static volatile cyg_uint32 slicerun[NTHREADS_MAX][CYGNUM_KERNEL_CPU_MAX]; + +//========================================================================== + +void +test_thread_timeslice(CYG_ADDRESS id) +{ + for(;;) + slicerun[id][CYG_KERNEL_CPU_THIS()]++; +} + +//========================================================================== + +void run_test_timeslice(int nthread) +{ + int i,j; + cyg_uint32 cpu_total[CYGNUM_KERNEL_CPU_MAX]; + cyg_uint32 cpu_threads[CYGNUM_KERNEL_CPU_MAX]; + cyg_uint32 thread_total[NTHREADS_MAX]; + + CYG_TEST_INFO( "Timeslice2 Test: Check timeslicing works under preemption"); + + // Init flags. + for (i = 0; i < nthread; i++) + for( j = 0; j < ncpus; j++ ) + slicerun[i][j] = 0; + + // Set my priority higher than any I plan to create + cyg_thread_set_priority(cyg_thread_self(), 2); + + for (i = 0; i < nthread; i++) { + cyg_thread_create(10, // Priority - just a number + test_thread_timeslice, // entry + i, // index + "test_thread", // Name + &stacks[i][0], // Stack + STACK_SIZE, // Size + &threads[i], // Handle + &test_threads[i] // Thread data structure + ); + cyg_thread_resume( threads[i]); + } + + // Just wait a while, until the threads have all run for a bit. + cyg_thread_delay( CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS*100 ); + + // Suspend all the threads + for (i = 0; i < nthread; i++) { + cyg_thread_suspend(threads[i]); + } + + + // And check that a thread ran on each CPU, and that each thread + // ran. + + + diag_printf(" Thread "); + for( j = 0; j < ncpus; j++ ) + { + cpu_total[j] = 0; + cpu_threads[j] = 0; + // " %11d" __123456789ab" + diag_printf(" CPU %2d",j); + } + // " %11d" __123456789ab" + diag_printf(" Total\n"); + for (i = 0; i < nthread; i++) + { + thread_total[i] = 0; + diag_printf(" %2d ",i); + for( j = 0; j < ncpus; j++ ) + { + thread_total[i] += slicerun[i][j]; + cpu_total[j] += slicerun[i][j]; + if( slicerun[i][j] > 0 ) + cpu_threads[j]++; + diag_printf(" %11d",slicerun[i][j]); + } + diag_printf(" %11d\n",thread_total[i]); + if( thread_total[i] == 0 ) + failed++; + } + + diag_printf(" Total "); + for( j = 0; j < ncpus; j++ ) + diag_printf(" %11d",cpu_total[j]); + diag_printf("\n"); + diag_printf("Threads "); + for( j = 0; j < ncpus; j++ ) + { + diag_printf(" %11d",cpu_threads[j]); + if( cpu_threads[j] < 2 ) + failed++; + } + diag_printf("\n"); + + // Delete all the threads + for (i = 0; i < nthread; i++) { + cyg_thread_delete(threads[i]); + } + + CYG_TEST_INFO( "Timeslice2 Test: done"); +} + + +//========================================================================== + +void +hipri_test(CYG_ADDRESS id) +{ + while( 1 ) + { + cyg_thread_delay( CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS/2 ); + } +} + +//========================================================================== + +void +run_tests(CYG_ADDRESS id) +{ + int step; + int nthread; + + // Try to run about 10 times in total, with varying numbers of threads + // from only one extra up to the full set: + + step = (NTHREADS_MAX - (1 + CYG_KERNEL_CPU_COUNT()))/10; + if( step == 0 ) step = 1; + + for( nthread = 1 + CYG_KERNEL_CPU_COUNT() ; + nthread <= NTHREADS_MAX ; + nthread += step ) + run_test_timeslice(nthread); + + if( failed ) + CYG_TEST_FAIL_FINISH("Timeslice2 test failed\n"); + + CYG_TEST_PASS_FINISH("Timeslice2 test OK"); +} + +//========================================================================== + +void timeslice_main( void ) +{ + CYG_TEST_INIT(); + + // Work out how many CPUs we actually have. + ncpus = CYG_KERNEL_CPU_COUNT(); + + cyg_thread_create(0, // Priority - just a number + run_tests, // entry + 0, // index + "run_tests", // Name + test_stack, // Stack + STACK_SIZE, // Size + &main_thread, // Handle + &test_thread // Thread data structure + ); + cyg_thread_resume( main_thread); + + cyg_thread_create(5, // Priority - just a number + hipri_test, // entry + 0, // index + "hipri_run", // Name + hipri_stack, // Stack + STACK_SIZE, // Size + &hipri_thread, // Handle + &hipri_thread_obj // Thread data structure + ); + cyg_thread_resume( hipri_thread); + + cyg_scheduler_start(); +} + +//========================================================================== + +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG +externC void +cyg_hal_invoke_constructors(); +#endif + +externC void +cyg_start( void ) +{ +#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG + cyg_hal_invoke_constructors(); +#endif + timeslice_main(); +} + +//========================================================================== + +#else // CYGSEM_KERNEL_SCHED_TIMESLICE etc + +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_INFO("Timeslice test requires:\n" + "CYGSEM_KERNEL_SCHED_TIMESLICE &&\n" + "CYGFUN_KERNEL_API_C && \n" + "CYGSEM_KERNEL_SCHED_MLQUEUE &&\n" + "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n" + "!CYGDBG_INFRA_DIAG_USE_DEVICE &&\n" + "(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n"); + CYG_TEST_NA("Timeslice test requirements"); +} + +#endif // CYGSEM_KERNEL_SCHED_TIMESLICE etc. + +//========================================================================== +// EOF timeslice2.c diff --git a/packages/redboot/v2_0/doc/.cvsignore b/packages/redboot/v2_0/doc/.cvsignore new file mode 100644 index 00000000..8a8c3850 --- /dev/null +++ b/packages/redboot/v2_0/doc/.cvsignore @@ -0,0 +1,11 @@ +redboot-guide-a4.aux +redboot-guide-a4.log +redboot-guide-a4.out +redboot-guide-a4.pdf +redboot-guide-a4.tex +redboot-guide-letter.aux +redboot-guide-letter.log +redboot-guide-letter.out +redboot-guide-letter.pdf +redboot-guide-letter.tex +*.html \ No newline at end of file diff --git a/packages/redboot/v2_0/src/flash_load.c b/packages/redboot/v2_0/src/flash_load.c new file mode 100644 index 00000000..9082502c --- /dev/null +++ b/packages/redboot/v2_0/src/flash_load.c @@ -0,0 +1,183 @@ +//========================================================================== +// +// flash_load.c +// +// RedBoot file/image loader into flash +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric LTD +// +// 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): Oliver Munz +// Contributors: om, asl +// Date: 2006-02-21 +// Purpose: +// Description: +// +// This code is part of RedBoot (tm). +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include + +#include +#include + +static int flash_block_size; + +static cyg_uint8 * current_flash_page; + +/* Allocation of the flash-sector size RAM-buffer is done */ +static bool init_done = false; + +/* We have initialized the current page ready for writing */ +static bool flash_page_init = false; + +static cyg_uint8 *flash_buffer; + +// If the io flash code outputs when erasing/writing it will upset the +// download over the communications channel. So we install a dummy +// print function. +static int dummy_printf(const char *fmt, ...){ + return 0; +} + +// Calculate the address of the first byte in a flash block +static cyg_uint8 * flash_block_begin(cyg_uint32 addr) +{ + return (cyg_uint8 *) + ((addr / flash_block_size) * flash_block_size); +} + +// Initialize the loading process +void flash_load_start(void) +{ + flash_init(dummy_printf); + + init_done = true; + flash_page_init = false; +} + +// Write a byte into flash. We maintain a copy in RAM of the FLASH +// page we are currently "writing" into. This copy is loaded with the +// current contents of the FLASH page when the first byte is "written" +// to the page. The "writes" are then made into the RAM copy. We only +// write to FLASH when there is a "write" outside of the current page, +// or the flash_load_finish function is called. +void flash_load_write(cyg_uint8 *flash_addr, cyg_uint8 value) +{ + + cyg_uint32 retcode = FLASH_ERR_OK; + void * err_addr; + cyg_uint32 addr = (cyg_uint32)flash_addr; + cyg_uint32 offset; + + if (!flash_page_init) { + /* First Byte for the current flash block. Read the current contents */ + current_flash_page = flash_block_begin(addr); + flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr); + flash_page_init = true; + } + if (flash_block_begin(addr) != current_flash_page) { + /* We have moved into the next flash page. Write the current + page so we can move on */ + retcode = flash_erase(current_flash_page, flash_block_size, &err_addr); + if (retcode != FLASH_ERR_OK){ /* Flash ERROR */ + diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode)); + return; + } + + retcode = flash_program(current_flash_page, flash_buffer, + flash_block_size, &err_addr); + if (retcode != FLASH_ERR_OK){ + diag_printf("Error writing at %p: %s\n", + err_addr, flash_errmsg(retcode)); + return; + } + current_flash_page = flash_block_begin(addr); + flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr); + } + + offset = flash_addr - current_flash_page; + CYG_ASSERT(offset < flash_block_size, "offset not inside flash block"); + + flash_buffer[offset] = value; +} + +// Program the current page into flash. +void flash_load_finish(void) +{ + cyg_uint32 retcode = FLASH_ERR_OK; + void * err_addr; + + if (init_done && flash_page_init) { + flash_page_init = false; + + retcode = flash_erase(current_flash_page, flash_block_size, &err_addr); + if (retcode != FLASH_ERR_OK){ + diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode)); + } else { + retcode = flash_program(current_flash_page, flash_buffer, + flash_block_size, &err_addr); + if (retcode != FLASH_ERR_OK){ + diag_printf("Error writing at %p: %s\n", + err_addr, flash_errmsg(retcode)); + } + } + } + flash_init(diag_printf); +} + +// This is called during redboot start up. We allocate a buffer the +// size of the flash page. +void +flash_load_init(void) +{ + int flash_blocks; + + flash_get_block_info(&flash_block_size, &flash_blocks); + workspace_end -= flash_block_size; + + flash_buffer = workspace_end; +} + +// Register this initialization function in the table +RedBoot_init(flash_load_init, RedBoot_INIT_LAST); + + + diff --git a/packages/redboot/v2_0/src/flash_load.h b/packages/redboot/v2_0/src/flash_load.h new file mode 100644 index 00000000..8b955960 --- /dev/null +++ b/packages/redboot/v2_0/src/flash_load.h @@ -0,0 +1,67 @@ +//========================================================================== +// +// flash_load.h +// +// Interfaces to byte writing into FLASH during load +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric Ltd +// Copyright (C) 2006 Andrew Lunn +// +// 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): Oliver Munz +// Contributors: om, asl +// Date: 2005-02-21 +// Purpose: +// Description: +// +// This code is part of RedBoot (tm). +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#ifndef FLASH_LOAD_H +#define FLASH_LOAd_H + +// Prepare a write to flash. +void flash_load_start(void); + +// Finish a write to flash +void flash_load_finish(void); + +// Write a single byte. This will be buffered until either a full page +// is available or flash_write_finish is called. +void flash_load_write(cyg_uint8 *addr, cyg_uint8 value); + +#endif // FLASH_LOAD_H + diff --git a/packages/redboot/v2_0/src/gunzip.c b/packages/redboot/v2_0/src/gunzip.c new file mode 100644 index 00000000..c241433c --- /dev/null +++ b/packages/redboot/v2_0/src/gunzip.c @@ -0,0 +1,117 @@ +//========================================================================== +// +// gunzip.c +// +// RedBoot GZIP uncompress command +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005 eCosCentric Ltd +// +// 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): Peter Korsgaard +// Contributors: Peter Korsgaard +// Date: 2005-04-04 +// Purpose: +// Description: +// +// This code is part of RedBoot (tm). +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +RedBoot_cmd("gunzip", + "Uncompress GZIP compressed data", + "-s -d ", + do_gunzip + ); + +void +do_gunzip(int argc, char *argv[]) +{ + struct option_info opts[2]; + unsigned long src, dst; + bool src_set, dst_set; + _pipe_t pipe; + _pipe_t* p = &pipe; + int err; + + init_opts(&opts[0], 's', true, OPTION_ARG_TYPE_NUM, + (void *)&src, (bool *)&src_set, "source address"); + init_opts(&opts[1], 'd', true, OPTION_ARG_TYPE_NUM, + (void *)&dst, (bool *)&dst_set, "destination address"); + if (!scan_opts(argc, argv, 1, opts, 2, 0, 0, "")) { + return; + } + + // Must have src and dst + if (!src_set || !dst_set) { + // try to use load_address for src + if (dst_set + && load_address >= (CYG_ADDRESS)ram_start + && load_address < load_address_end) { + src = load_address; + diag_printf("Decompressing from %p to %p\n", + (void*)src, (void*)dst); + } + else + { + diag_printf("usage: gunzip -s -d \n"); + return; + } + } + + p->out_buf = (unsigned char*)dst; + p->out_max = p->out_size = -1; + p->in_buf = (unsigned char*)src; + p->in_avail = -1; + + err = (*_dc_init)(p); + + if (0 == err) + err = (*_dc_inflate)(p); + + // Free used resources, do final translation of error value. + err = (*_dc_close)(p, err); + + if (0 != err && p->msg) { + entry_address = (CYG_ADDRESS)NO_MEMORY; + diag_printf("Decompression error: %s\n", p->msg); + } else { + load_address = entry_address = (CYG_ADDRESS)dst; + load_address_end = (CYG_ADDRESS)p->out_buf; + diag_printf("Decompressed %lu bytes\n", + load_address_end - load_address); + } +}