aboutsummaryrefslogtreecommitdiffstats
path: root/os/ports/GCC/ARM7
diff options
context:
space:
mode:
Diffstat (limited to 'os/ports/GCC/ARM7')
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/mii.h156
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/pal_lld.c116
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/pal_lld.h245
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/port.dox73
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/sam7x_emac.c418
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/sam7x_emac.h93
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/sam7x_serial.c224
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/sam7x_serial.h86
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/vectors.s74
-rw-r--r--os/ports/GCC/ARM7/AT91SAM7X/wfi.h35
-rw-r--r--os/ports/GCC/ARM7/LPC214x/lpc214x.h523
-rw-r--r--os/ports/GCC/ARM7/LPC214x/lpc214x_serial.c268
-rw-r--r--os/ports/GCC/ARM7/LPC214x/lpc214x_serial.h102
-rw-r--r--os/ports/GCC/ARM7/LPC214x/lpc214x_ssp.c133
-rw-r--r--os/ports/GCC/ARM7/LPC214x/lpc214x_ssp.h54
-rw-r--r--os/ports/GCC/ARM7/LPC214x/pal_lld.c89
-rw-r--r--os/ports/GCC/ARM7/LPC214x/pal_lld.h252
-rw-r--r--os/ports/GCC/ARM7/LPC214x/port.dox83
-rw-r--r--os/ports/GCC/ARM7/LPC214x/vectors.s71
-rw-r--r--os/ports/GCC/ARM7/LPC214x/vic.c63
-rw-r--r--os/ports/GCC/ARM7/LPC214x/vic.h41
-rw-r--r--os/ports/GCC/ARM7/LPC214x/wfi.h35
-rw-r--r--os/ports/GCC/ARM7/chcore.c42
-rw-r--r--os/ports/GCC/ARM7/chcore.h331
-rw-r--r--os/ports/GCC/ARM7/chcore.lst48
-rw-r--r--os/ports/GCC/ARM7/chcoreasm.s234
-rw-r--r--os/ports/GCC/ARM7/chtypes.h56
-rw-r--r--os/ports/GCC/ARM7/crt0.lst218
-rw-r--r--os/ports/GCC/ARM7/crt0.s181
-rw-r--r--os/ports/GCC/ARM7/port.dox200
-rw-r--r--os/ports/GCC/ARM7/port.mk7
31 files changed, 4551 insertions, 0 deletions
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/mii.h b/os/ports/GCC/ARM7/AT91SAM7X/mii.h
new file mode 100644
index 000000000..4ec25667a
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/mii.h
@@ -0,0 +1,156 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Parts of this file are borrowed by the Linux include file linux/mii.h:
+ * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _MII_H_
+#define _MII_H_
+
+/* Generic MII registers. */
+#define MII_BMCR 0x00 /* Basic mode control register */
+#define MII_BMSR 0x01 /* Basic mode status register */
+#define MII_PHYSID1 0x02 /* PHYS ID 1 */
+#define MII_PHYSID2 0x03 /* PHYS ID 2 */
+#define MII_ADVERTISE 0x04 /* Advertisement control reg */
+#define MII_LPA 0x05 /* Link partner ability reg */
+#define MII_EXPANSION 0x06 /* Expansion register */
+#define MII_CTRL1000 0x09 /* 1000BASE-T control */
+#define MII_STAT1000 0x0a /* 1000BASE-T status */
+#define MII_ESTATUS 0x0f /* Extended Status */
+#define MII_DCOUNTER 0x12 /* Disconnect counter */
+#define MII_FCSCOUNTER 0x13 /* False carrier counter */
+#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
+#define MII_RERRCOUNTER 0x15 /* Receive error counter */
+#define MII_SREVISION 0x16 /* Silicon revision */
+#define MII_RESV1 0x17 /* Reserved... */
+#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
+#define MII_PHYADDR 0x19 /* PHY address */
+#define MII_RESV2 0x1a /* Reserved... */
+#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
+#define MII_NCONFIG 0x1c /* Network interface config */
+
+/* Basic mode control register. */
+#define BMCR_RESV 0x003f /* Unused... */
+#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
+#define BMCR_CTST 0x0080 /* Collision test */
+#define BMCR_FULLDPLX 0x0100 /* Full duplex */
+#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
+#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
+#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
+#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
+#define BMCR_RESET 0x8000 /* Reset the DP83840 */
+
+/* Basic mode status register. */
+#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
+#define BMSR_JCD 0x0002 /* Jabber detected */
+#define BMSR_LSTATUS 0x0004 /* Link status */
+#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
+#define BMSR_RFAULT 0x0010 /* Remote fault detected */
+#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
+#define BMSR_RESV 0x00c0 /* Unused... */
+#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
+#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
+#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
+#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
+#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
+#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
+
+/* Advertisement control register. */
+#define ADVERTISE_SLCT 0x001f /* Selector bits */
+#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
+#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
+#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
+#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
+#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
+#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
+#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
+#define ADVERTISE_RESV 0x1000 /* Unused... */
+#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
+#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
+#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
+
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ ADVERTISE_CSMA)
+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL)
+
+/* Link partner ability register. */
+#define LPA_SLCT 0x001f /* Same as advertise selector */
+#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
+#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
+#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
+#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
+#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
+#define LPA_PAUSE_CAP 0x0400 /* Can pause */
+#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
+#define LPA_RESV 0x1000 /* Unused... */
+#define LPA_RFAULT 0x2000 /* Link partner faulted */
+#define LPA_LPACK 0x4000 /* Link partner acked us */
+#define LPA_NPAGE 0x8000 /* Next page bit */
+
+#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
+#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+
+/* Expansion register for auto-negotiation. */
+#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
+#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
+#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
+#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
+#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
+#define EXPANSION_RESV 0xffe0 /* Unused... */
+
+#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
+#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
+
+/* N-way test register. */
+#define NWAYTEST_RESV1 0x00ff /* Unused... */
+#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
+#define NWAYTEST_RESV2 0xfe00 /* Unused... */
+
+/* 1000BASE-T Control register */
+#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
+#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
+
+/* 1000BASE-T Status register */
+#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
+#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
+#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
+#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */
+
+#define MII_DM9161_ID 0x0181b8a0
+#define MII_AM79C875_ID 0x00225540
+#define MII_MICREL_ID 0x00221610
+
+#endif /* _MII_H_ */
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/pal_lld.c b/os/ports/GCC/ARM7/AT91SAM7X/pal_lld.c
new file mode 100644
index 000000000..266bdb38d
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/pal_lld.c
@@ -0,0 +1,116 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-AT91SAM7X/pal_lld.c
+ * @brief AT91SAM7X PIO low level driver code
+ * @addtogroup AT91SAM7X_PAL
+ * @{
+ */
+
+#include <ch.h>
+#include <pal.h>
+
+/**
+ * @brief AT91SAM7X I/O ports configuration.
+ * @details PIO registers initialization.
+ *
+ * @param[in] config the AT91SAM7X ports configuration
+ */
+void _pal_lld_init(const AT91SAM7XPIOConfig *config) {
+
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA) | (1 << AT91C_ID_PIOB);
+
+ /*
+ * PIOA setup.
+ */
+ AT91C_BASE_PIOA->PIO_OER = config->P0Data.pusr; /* Pull-up as spec.*/
+ AT91C_BASE_PIOA->PIO_ODR = ~config->P0Data.pusr;
+ AT91C_BASE_PIOA->PIO_PER = 0xFFFFFFFF; /* PIO enabled.*/
+ AT91C_BASE_PIOA->PIO_ODSR = config->P0Data.odsr; /* Data as specified.*/
+ AT91C_BASE_PIOA->PIO_OER = config->P0Data.osr; /* Dir. as specified.*/
+ AT91C_BASE_PIOA->PIO_ODR = ~config->P0Data.osr;
+ AT91C_BASE_PIOA->PIO_IFDR = 0xFFFFFFFF; /* Filter disabled.*/
+ AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF; /* Int. disabled.*/
+ AT91C_BASE_PIOA->PIO_MDDR = 0xFFFFFFFF; /* Push Pull drive.*/
+ AT91C_BASE_PIOA->PIO_ASR = 0xFFFFFFFF; /* Peripheral A.*/
+ AT91C_BASE_PIOA->PIO_OWER = 0xFFFFFFFF; /* Write enabled.*/
+
+ /*
+ * PIOB setup.
+ */
+ AT91C_BASE_PIOB->PIO_OER = config->P0Data.pusr; /* Pull-up as spec.*/
+ AT91C_BASE_PIOB->PIO_ODR = ~config->P0Data.pusr;
+ AT91C_BASE_PIOB->PIO_PER = 0xFFFFFFFF; /* PIO enabled.*/
+ AT91C_BASE_PIOB->PIO_ODSR = config->P1Data.odsr; /* Data as specified.*/
+ AT91C_BASE_PIOB->PIO_OER = config->P1Data.osr; /* Dir. as specified.*/
+ AT91C_BASE_PIOB->PIO_ODR = ~config->P1Data.osr;
+ AT91C_BASE_PIOB->PIO_IFDR = 0xFFFFFFFF; /* Filter disabled.*/
+ AT91C_BASE_PIOB->PIO_IDR = 0xFFFFFFFF; /* Int. disabled.*/
+ AT91C_BASE_PIOB->PIO_MDDR = 0xFFFFFFFF; /* Push Pull drive.*/
+ AT91C_BASE_PIOB->PIO_ASR = 0xFFFFFFFF; /* Peripheral A.*/
+ AT91C_BASE_PIOB->PIO_OWER = 0xFFFFFFFF; /* Write enabled.*/
+}
+
+/**
+ * @brief Pads mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ * @note @p PAL_MODE_RESET is implemented as input with pull-up.
+ * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
+ * state.
+ * @note @p PAL_MODE_OUTPUT_OPENDRAIN also enables the pull-up resistor.
+ */
+void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ uint_fast8_t mode) {
+
+ switch (mode & PAL_MODE_MASK) {
+ case PAL_MODE_RESET:
+ case PAL_MODE_INPUT_PULLUP:
+ port->PIO_PPUER = mask;
+ port->PIO_ODR = mask;
+ break;
+ case PAL_MODE_INPUT:
+ port->PIO_PPUDR = mask;
+ port->PIO_ODR = mask;
+ break;
+ case PAL_MODE_UNCONNECTED:
+ port->PIO_SODR = mask;
+ /* Falls in */
+ case PAL_MODE_OUTPUT_PUSHPULL:
+ port->PIO_PPUDR = mask;
+ port->PIO_OER = mask;
+ port->PIO_MDDR = mask;
+ break;
+ case PAL_MODE_OUTPUT_OPENDRAIN:
+ port->PIO_PPUER = mask;
+ port->PIO_OER = mask;
+ port->PIO_MDER = mask;
+ }
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/pal_lld.h b/os/ports/GCC/ARM7/AT91SAM7X/pal_lld.h
new file mode 100644
index 000000000..b403fc2cc
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/pal_lld.h
@@ -0,0 +1,245 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-AT91SAM7X/pal_lld.h
+ * @brief AT91SAM7X PIO low level driver header
+ * @addtogroup AT91SAM7X_PAL
+ * @{
+ */
+
+#ifndef _PAL_LLD_H_
+#define _PAL_LLD_H_
+
+#include "at91lib/AT91SAM7X256.h"
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+#undef PAL_MODE_INPUT_PULLDOWN
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @brief PIO port setup info.
+ */
+typedef struct {
+ /** Initial value for ODSR register (data).*/
+ uint32_t odsr;
+ /** Initial value for OSR register (direction).*/
+ uint32_t osr;
+ /** Initial value for PUSR register (Pull-ups).*/
+ uint32_t pusr;
+} at91sam7x_pio_setup_t;
+
+/**
+ * @brief AT91SAM7X PIO static initializer.
+ * @details An instance of this structure must be passed to @p palInit() at
+ * system startup time in order to initialized the digital I/O
+ * subsystem. This represents only the initial setup, specific pads
+ * or whole ports can be reprogrammed at later time.
+ */
+typedef struct {
+ /** @brief Port 0 setup data.*/
+ at91sam7x_pio_setup_t P0Data;
+ /** @brief Port 1 setup data.*/
+ at91sam7x_pio_setup_t P1Data;
+} AT91SAM7XPIOConfig;
+
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 32
+
+/**
+ * @brief Digital I/O port sized unsigned type.
+ */
+typedef uint32_t ioportmask_t;
+
+/**
+ * @brief Port Identifier.
+ * @details This type can be a scalar or some kind of pointer, do not make
+ * any assumption about it, use the provided macros when populating
+ * variables of this type.
+ */
+typedef AT91PS_PIO ioportid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/*===========================================================================*/
+
+/**
+ * @brief PIO port A identifier.
+ */
+#define IOPORT_A AT91C_BASE_PIOA
+
+/**
+ * @brief PIO port B identifier.
+ */
+#define IOPORT_B AT91C_BASE_PIOB
+
+/*===========================================================================*/
+/* Implementation, some of the following macros could be implemented as */
+/* functions, if so please put them in a file named pal_lld.c. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level PAL subsystem initialization.
+ */
+#define pal_lld_init(config) _pal_lld_init(config)
+
+/**
+ * @brief Reads the physical I/O port states.
+ * @details This function is implemented by reading the PIO_PDSR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @return The port bits.
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_readport(port) ((port)->PIO_PDSR)
+
+/**
+ * @brief Reads the output latch.
+ * @details This function is implemented by reading the PIO_ODSR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @return The latched logical states.
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_readlatch(port) ((port)->PIO_ODSR)
+
+/**
+ * @brief Writes a bits mask on a I/O port.
+ * @details This function is implemented by writing the PIO_ODSR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @param[in] bits the bits to be written on the specified port
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_writeport(port, bits) { \
+ (port)->PIO_ODSR = (bits); \
+}
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @details This function is implemented by writing the PIO_SODR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @param[in] bits the bits to be ORed on the specified port
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_setport(port, bits) { \
+ (port)->PIO_SODR = (bits); \
+}
+
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @details This function is implemented by writing the PIO_CODR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @param[in] bits the bits to be cleared on the specified port
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_clearport(port, bits) { \
+ (port)->PIO_CODR = (bits); \
+}
+
+/**
+ * @brief Writes a group of bits.
+ * @details This function is implemented by writing the PIO_OWER, PIO_ODSR and
+ * PIO_OWDR registers, the implementation is not atomic because the
+ * multiple accesses.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] offset the group bit offset within the port
+ * @param[in] bits the bits to be written. Values exceeding the group width
+ * are masked.
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_writegroup(port, mask, offset, bits) { \
+ (port)->PIO_OWER = (mask) << (offset); \
+ (port)->PIO_ODSR = (bits) << (offset); \
+ (port)->PIO_OWDR = (mask) << (offset); \
+}
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
+ * state.
+ */
+#define pal_lld_setgroupmode(port, mask, mode) \
+ _pal_lld_setgroupmode(port, mask, mode)
+
+/**
+ * @brief Writes a logical state on an output pad.
+ *
+ * @param[in] port the port identifier
+ * @param[in] pad the pad number within the port
+ * @param[out] bit the logical value, the value must be @p 0 or @p 1
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _pal_lld_init(const AT91SAM7XPIOConfig *config);
+ void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ uint_fast8_t mode);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PAL_LLD_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/port.dox b/os/ports/GCC/ARM7/AT91SAM7X/port.dox
new file mode 100644
index 000000000..dac6ed181
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/port.dox
@@ -0,0 +1,73 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @defgroup AT91SAM7X AT91SAM7X Support
+ * @brief AT91SAM7X specific support.
+ * @details The AT91SAM7X support includes:
+ * - Buffered, interrupt driven, serial driver.
+ * - EMAC driver with MII support.
+ * - A demo supporting the kernel test suite.
+ * - A Web server demo using the uIP TCP/IP stack.
+ * .
+ * @ingroup ARM7
+ */
+
+/**
+ * @defgroup AT91SAM7X_PAL I/O Ports Support
+ * @brief I/O Ports peripherals support.
+ * @details This module supports the AT91SAM7X PIO controller. The controller
+ * supports the following features (see @ref PAL):
+ * - 32 bits wide ports.
+ * - Atomic set/reset functions.
+ * - Output latched regardless of the pad setting.
+ * - Direct read of input pads regardless of the pad setting.
+ * .
+ * <h2>Supported Setup Modes</h2>
+ * - @p PAL_MODE_RESET.
+ * - @p PAL_MODE_UNCONNECTED.
+ * - @p PAL_MODE_INPUT.
+ * - @p PAL_MODE_INPUT_PULLUP.
+ * - @p PAL_MODE_OUTPUT_PUSHPULL.
+ * - @p PAL_MODE_OUTPUT_OPENDRAIN.
+ * .
+ * Any attempt to setup an invalid mode is ignored.
+ *
+ * <h2>Suboptimal Behavior</h2>
+ * Some PIO features are less than optimal:
+ * - Pad/port toggling operations are not atomic.
+ * - Pad/group mode setup is not atomic.
+ * .
+ * @ingroup AT91SAM7X
+ */
+
+/**
+ * @defgroup AT91SAM7X_SERIAL USART Support
+ * @brief USART peripherals support.
+ * @details The serial driver supports the AT91SAM7X USART peripherals.
+ *
+ * @ingroup AT91SAM7X
+ */
+
+/**
+ * @defgroup AT91SAM7X_EMAC EMAC Support
+ * @brief EMAC peripheral support.
+ *
+ * @ingroup AT91SAM7X
+ */
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/sam7x_emac.c b/os/ports/GCC/ARM7/AT91SAM7X/sam7x_emac.c
new file mode 100644
index 000000000..b0db11dca
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/sam7x_emac.c
@@ -0,0 +1,418 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-AT91SAM7X/sam7x_emac.c
+ * @brief AT91SAM7X EMAC driver code.
+ * @addtogroup AT91SAM7X_EMAC
+ * @{
+ */
+
+#include <string.h>
+
+#include <ch.h>
+
+#include "board.h"
+#include "sam7x_emac.h"
+#include "mii.h"
+#include "at91lib/aic.h"
+
+EventSource EMACFrameTransmitted; /* A frame was transmitted. */
+EventSource EMACFrameReceived; /* A frame was received. */
+
+#ifndef __DOXYGEN__
+//static int received; /* Buffered frames counter. */
+static bool_t link_up; /* Last from EMACGetLinkStatus()*/
+
+static uint8_t default_mac[] = {0xAA, 0x55, 0x13, 0x37, 0x01, 0x10};
+
+static BufDescriptorEntry rent[EMAC_RECEIVE_BUFFERS] __attribute__((aligned(8)));
+static uint8_t rbuffers[EMAC_RECEIVE_BUFFERS * EMAC_RECEIVE_BUFFERS_SIZE] __attribute__((aligned(8)));
+static BufDescriptorEntry *rxptr;
+
+static BufDescriptorEntry tent[EMAC_TRANSMIT_BUFFERS] __attribute__((aligned(8)));
+static uint8_t tbuffers[EMAC_TRANSMIT_BUFFERS * EMAC_TRANSMIT_BUFFERS_SIZE] __attribute__((aligned(8)));
+static BufDescriptorEntry *txptr;
+#endif
+
+#define AT91C_PB15_ERXDV AT91C_PB15_ERXDV_ECRSDV
+#define EMAC_PIN_MASK (AT91C_PB0_ETXCK_EREFCK | \
+ AT91C_PB1_ETXEN | AT91C_PB2_ETX0 | \
+ AT91C_PB3_ETX1 | AT91C_PB4_ECRS | \
+ AT91C_PB5_ERX0 | AT91C_PB6_ERX1 | \
+ AT91C_PB7_ERXER | AT91C_PB8_EMDC | \
+ AT91C_PB9_EMDIO | AT91C_PB10_ETX2 | \
+ AT91C_PB11_ETX3 | AT91C_PB12_ETXER | \
+ AT91C_PB13_ERX2 | AT91C_PB14_ERX3 | \
+ AT91C_PB15_ERXDV | AT91C_PB16_ECOL | \
+ AT91C_PB17_ERXCK)
+
+#define PHY_LATCHED_PINS (AT91C_PB4_ECRS | AT91C_PB5_ERX0 | AT91C_PB6_ERX1 | \
+ AT91C_PB7_ERXER | AT91C_PB13_ERX2 | AT91C_PB14_ERX3 | \
+ AT91C_PB15_ERXDV | AT91C_PB16_ECOL | PIOB_PHY_IRQ_MASK)
+
+/*
+ * PHY utilities.
+ */
+static uint32_t phy_get(uint8_t regno) {
+
+ AT91C_BASE_EMAC->EMAC_MAN = (1 << 30) | // SOF = 01
+ (2 << 28) | // RW = 10
+ (PHY_ADDRESS << 23) |
+ (regno << 18) |
+ (2 << 16); // CODE = 10
+ while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE))
+ ;
+ return AT91C_BASE_EMAC->EMAC_MAN & 0xFFFF;
+}
+
+/*static void phy_put(uint8_t regno, uint32_t val) {
+
+ AT91C_BASE_EMAC->EMAC_MAN = (1 << 30) | // SOF = 01
+ (1 << 28) | // RW = 01
+ (PHY_ADDRESS << 23) |
+ (regno << 18) |
+ (2 << 16) | // CODE = 10
+ val;
+ while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE))
+ ;
+}*/
+
+#define RSR_BITS (AT91C_EMAC_BNA | AT91C_EMAC_REC | AT91C_EMAC_OVR)
+#define TSR_BITS (AT91C_EMAC_UBR | AT91C_EMAC_COL | AT91C_EMAC_RLES | \
+ AT91C_EMAC_BEX | AT91C_EMAC_COMP | AT91C_EMAC_UND)
+
+__attribute__((noinline))
+static void ServeInterrupt(void) {
+ uint32_t isr, rsr, tsr;
+
+ /* Fix for the EMAC errata */
+ isr = AT91C_BASE_EMAC->EMAC_ISR;
+ rsr = AT91C_BASE_EMAC->EMAC_RSR;
+ tsr = AT91C_BASE_EMAC->EMAC_TSR;
+
+ if ((isr & AT91C_EMAC_RCOMP) || (rsr & RSR_BITS)) {
+ if (rsr & AT91C_EMAC_REC) {
+// received++;
+ chSysLockFromIsr();
+ chEvtBroadcastI(&EMACFrameReceived);
+ chSysUnlockFromIsr();
+ }
+ AT91C_BASE_EMAC->EMAC_RSR = RSR_BITS;
+ }
+
+ if ((isr & AT91C_EMAC_TCOMP) || (tsr & TSR_BITS)) {
+ if (tsr & AT91C_EMAC_COMP) {
+ chSysLockFromIsr();
+ chEvtBroadcastI(&EMACFrameTransmitted);
+ chSysUnlockFromIsr();
+ }
+ AT91C_BASE_EMAC->EMAC_TSR = TSR_BITS;
+ }
+ AT91C_BASE_AIC->AIC_EOICR = 0;
+}
+
+CH_IRQ_HANDLER(EMACIrqHandler) {
+
+ CH_IRQ_PROLOGUE();
+
+ ServeInterrupt();
+
+ CH_IRQ_EPILOGUE();
+}
+
+/*
+ * EMAC subsystem initialization.
+ */
+void emac_init(int prio) {
+ int i;
+
+ /*
+ * Buffers initialization.
+ */
+// received = 0;
+ for (i = 0; i < EMAC_RECEIVE_BUFFERS; i++) {
+ rent[i].w1 = (uint32_t)&rbuffers[i * EMAC_RECEIVE_BUFFERS_SIZE];
+ rent[i].w2 = 0;
+ }
+ rent[EMAC_RECEIVE_BUFFERS - 1].w1 |= W1_R_WRAP;
+ rxptr = rent;
+ for (i = 0; i < EMAC_TRANSMIT_BUFFERS; i++) {
+ tent[i].w1 = (uint32_t)&tbuffers[i * EMAC_TRANSMIT_BUFFERS_SIZE];
+ tent[i].w2 = EMAC_TRANSMIT_BUFFERS_SIZE | W2_T_USED;
+ }
+ tent[EMAC_TRANSMIT_BUFFERS - 1].w2 |= W2_T_WRAP;
+ txptr = tent;
+
+ /*
+ * Disables the pullups on all the pins that are latched on reset by the PHY.
+ * The status latched into the PHY is:
+ * PHYADDR = 00001
+ * PCS_LPBK = 0 (disabled)
+ * ISOLATE = 0 (disabled)
+ * RMIISEL = 0 (MII mode)
+ * RMIIBTB = 0 (BTB mode disabled)
+ * SPEED = 1 (100mbps)
+ * DUPLEX = 1 (full duplex)
+ * ANEG_EN = 1 (auto negotiation enabled)
+ */
+ AT91C_BASE_PIOB->PIO_PPUDR = PHY_LATCHED_PINS;
+
+ /*
+ * PHY power control.
+ */
+ AT91C_BASE_PIOB->PIO_OER = PIOB_PHY_PD_MASK; // Becomes an output.
+ AT91C_BASE_PIOB->PIO_PPUDR = PIOB_PHY_PD_MASK; // Default pullup disabled.
+ AT91C_BASE_PIOB->PIO_SODR = PIOB_PHY_PD_MASK; // Output to high level.
+
+ /*
+ * PHY reset by pulsing the NRST pin.
+ */
+ AT91C_BASE_RSTC->RSTC_RMR = 0xA5000100;
+ AT91C_BASE_RSTC->RSTC_RCR = 0xA5000000 | AT91C_RSTC_EXTRST;
+ while (!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL))
+ ;
+
+ /*
+ * EMAC pins setup and clock enable. Note, PB18 is not included because it is
+ * used as #PD control and not as EF100.
+ */
+ AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_EMAC;
+ AT91C_BASE_PIOB->PIO_ASR = EMAC_PIN_MASK;
+ AT91C_BASE_PIOB->PIO_PDR = EMAC_PIN_MASK;
+ AT91C_BASE_PIOB->PIO_PPUDR = EMAC_PIN_MASK;
+
+ /*
+ * EMAC setup.
+ */
+ AT91C_BASE_EMAC->EMAC_NCR = 0; // Initial setting.
+ AT91C_BASE_EMAC->EMAC_NCFGR = 2 << 10; // MDC-CLK = MCK / 32
+ AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_CLKEN; // Enable EMAC in MII mode
+ AT91C_BASE_EMAC->EMAC_RBQP = (AT91_REG)rent; // RX buffers list
+ AT91C_BASE_EMAC->EMAC_TBQP = (AT91_REG)tent; // TX buffers list
+ AT91C_BASE_EMAC->EMAC_RSR = AT91C_EMAC_OVR |
+ AT91C_EMAC_REC |
+ AT91C_EMAC_BNA; // Clears RSR
+ AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_DRFCS; // Initial NCFGR settings
+ AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TE |
+ AT91C_EMAC_RE |
+ AT91C_EMAC_CLRSTAT; // Initial NCR settings
+ EMACSetAddress(default_mac);
+
+ /*
+ * PHY detection and settings.
+ */
+ AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
+ if ((phy_get(MII_PHYSID1) != (MII_MICREL_ID >> 16)) ||
+ ((phy_get(MII_PHYSID2) & 0xFFF0) != (MII_MICREL_ID & 0xFFF0)))
+ chSysHalt();
+
+ /*
+ * Waits for auto-negotiation to end and then detects the link status.
+ */
+ AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
+
+ /*
+ * Interrupt setup.
+ */
+ AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
+ AIC_ConfigureIT(AT91C_ID_EMAC,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | prio,
+ EMACIrqHandler);
+ AIC_EnableIT(AT91C_ID_EMAC);
+
+ /*
+ * Event sources setup.
+ */
+ chEvtInit(&EMACFrameTransmitted);
+ chEvtInit(&EMACFrameReceived);
+}
+
+/*
+ * Set the MAC address.
+ */
+void EMACSetAddress(const uint8_t *eaddr) {
+
+ AT91C_BASE_EMAC->EMAC_SA1L = (AT91_REG)((eaddr[3] << 24) | (eaddr[2] << 16) |
+ (eaddr[1] << 8) | eaddr[0]);
+ AT91C_BASE_EMAC->EMAC_SA1H = (AT91_REG)((eaddr[5] << 8) | eaddr[4]);
+}
+
+/*
+ * Returns TRUE if the link is active. To be invoked at regular intervals in
+ * order to monitor the link.
+ * @note It is not thread-safe.
+ */
+bool_t EMACGetLinkStatus(void) {
+ uint32_t ncfgr, bmsr, bmcr, lpa;
+
+ AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
+ (void)phy_get(MII_BMSR);
+ bmsr = phy_get(MII_BMSR);
+ if (!(bmsr & BMSR_LSTATUS)) {
+ AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
+ return link_up = FALSE;
+ }
+
+ ncfgr = AT91C_BASE_EMAC->EMAC_NCFGR & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
+ bmcr = phy_get(MII_BMCR);
+ if (bmcr & BMCR_ANENABLE) {
+ lpa = phy_get(MII_LPA);
+ if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4))
+ ncfgr |= AT91C_EMAC_SPD;
+ if (lpa & (LPA_10FULL | LPA_100FULL))
+ ncfgr |= AT91C_EMAC_FD;
+ }
+ else {
+ if (bmcr & BMCR_SPEED100)
+ ncfgr |= AT91C_EMAC_SPD;
+ if (bmcr & BMCR_FULLDPLX)
+ ncfgr |= AT91C_EMAC_FD;
+ }
+ AT91C_BASE_EMAC->EMAC_NCFGR = ncfgr;
+ AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
+ return link_up = TRUE;
+}
+
+/*
+ * Allocates and locks a buffer for a transmission operation.
+ */
+BufDescriptorEntry *EMACGetTransmitBuffer(void) {
+ BufDescriptorEntry *cptr;
+
+ if (!link_up)
+ return NULL;
+
+ chSysLock();
+ cptr = txptr;
+ if (!(cptr->w2 & W2_T_USED) ||
+ (cptr->w2 & W2_T_LOCKED)) {
+ chSysUnlock();
+ return FALSE;
+ }
+ cptr->w2 |= W2_T_LOCKED; /* Locks the buffer while copying.*/
+ if (++txptr >= &tent[EMAC_TRANSMIT_BUFFERS])
+ txptr = tent;
+ chSysUnlock();
+ return cptr;
+}
+
+/*
+ * Transmits a previously allocated buffer and then releases it.
+ */
+void EMACTransmit(BufDescriptorEntry *cptr, size_t size) {
+
+ chDbgAssert(size <= EMAC_TRANSMIT_BUFFERS_SIZE,
+ "EMACTransmit(), #1",
+ "unexpected size");
+
+ chSysLock();
+ if (cptr < &tent[EMAC_TRANSMIT_BUFFERS - 1])
+ cptr->w2 = size | W2_T_LAST_BUFFER;
+ else
+ cptr->w2 = size | W2_T_LAST_BUFFER | W2_T_WRAP;
+ AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;
+ chSysUnlock();
+}
+
+/*
+ * Reads a buffered frame.
+ * Returns TRUE if a frame was present and read else FALSE.
+ * @note It is not thread-safe.
+ */
+bool_t EMACReceive(uint8_t *buf, size_t *sizep) {
+ unsigned n;
+ size_t size;
+ uint8_t *p;
+ bool_t overflow, found;
+
+// chSysLock();
+// if (received <= 0) {
+// chSysUnlock();
+// return FALSE;
+// }
+// received--;
+// chSysUnlock();
+
+ n = EMAC_RECEIVE_BUFFERS;
+
+ /*
+ * Skips unused buffers, if any.
+ */
+skip:
+ while (n && !(rxptr->w1 & W1_R_OWNERSHIP)) {
+ if (++rxptr >= &rent[EMAC_RECEIVE_BUFFERS])
+ rxptr = rent;
+ n--;
+ }
+
+ /*
+ * Skips fragments, if any.
+ */
+ while (n && (rxptr->w1 & W1_R_OWNERSHIP) && !(rxptr->w2 & W2_R_FRAME_START)) {
+ rxptr->w1 &= ~W1_R_OWNERSHIP;
+ if (++rxptr >= &rent[EMAC_RECEIVE_BUFFERS])
+ rxptr = rent;
+ n--;
+ }
+
+restart:
+ p = buf;
+ size = 0;
+ found = overflow = FALSE;
+ while (n && !found) {
+ size_t segsize;
+
+ if (!(rxptr->w1 & W1_R_OWNERSHIP))
+ goto skip; /* Empty buffer for some reason... */
+
+ if (size && (rxptr->w2 & W2_R_FRAME_START))
+ goto restart; /* Another start buffer for some reason... */
+
+ if (rxptr->w2 & W2_R_FRAME_END) {
+ segsize = (rxptr->w2 & W2_T_LENGTH_MASK) - size;
+ if (((rxptr->w2 & W2_T_LENGTH_MASK) > *sizep) ||
+ (segsize > EMAC_RECEIVE_BUFFERS_SIZE))
+ overflow = TRUE;
+ found = TRUE;
+ }
+ else {
+ segsize = EMAC_RECEIVE_BUFFERS_SIZE;
+ if (size + segsize > *sizep)
+ overflow = TRUE;
+ }
+
+ if (!overflow) {
+ chDbgAssert(segsize <= 128, "EMACReceive(), #1", "");
+ memcpy(p, (void *)(rxptr->w1 & W1_R_ADDRESS_MASK), segsize);
+ p += segsize;
+ size += segsize;
+ }
+
+ rxptr->w1 &= ~W1_R_OWNERSHIP;
+ if (++rxptr >= &rent[EMAC_RECEIVE_BUFFERS])
+ rxptr = rent;
+ n--;
+ }
+
+ *sizep = size;
+ return found && !overflow;
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/sam7x_emac.h b/os/ports/GCC/ARM7/AT91SAM7X/sam7x_emac.h
new file mode 100644
index 000000000..d666ea6ef
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/sam7x_emac.h
@@ -0,0 +1,93 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-AT91SAM7X/sam7x_emac.h
+ * @brief AT91SAM7X EMAC driver macros and structures.
+ * @addtogroup AT91SAM7X_EMAC
+ * @{
+ */
+
+#ifndef _SAM7X_EMAC_H_
+#define _SAM7X_EMAC_H_
+
+#define PHY_ADDRESS 1
+
+#define EMAC_RECEIVE_BUFFERS 24
+#define EMAC_RECEIVE_BUFFERS_SIZE 128
+#define EMAC_TRANSMIT_BUFFERS 2
+#define EMAC_TRANSMIT_BUFFERS_SIZE 1518
+
+typedef struct {
+ uint32_t w1;
+ uint32_t w2;
+} BufDescriptorEntry;
+
+#define W1_R_OWNERSHIP 0x00000001
+#define W1_R_WRAP 0x00000002
+#define W1_R_ADDRESS_MASK 0xFFFFFFFC
+
+#define W2_R_LENGTH_MASK 0x00000FFF
+#define W2_R_FRAME_START 0x00004000
+#define W2_R_FRAME_END 0x00008000
+#define W2_R_CFI 0x00010000
+#define W2_R_VLAN_PRIO_MASK 0x000E0000
+#define W2_R_PRIO_TAG_DETECTED 0x00100000
+#define W2_R_VLAN_TAG_DETECTED 0x00200000
+#define W2_R_TYPE_ID_MATCH 0x00400000
+#define W2_R_ADDR4_MATCH 0x00800000
+#define W2_R_ADDR3_MATCH 0x01000000
+#define W2_R_ADDR2_MATCH 0x02000000
+#define W2_R_ADDR1_MATCH 0x04000000
+#define W2_R_RFU1 0x08000000
+#define W2_R_ADDR_EXT_MATCH 0x10000000
+#define W2_R_UNICAST_MATCH 0x20000000
+#define W2_R_MULTICAST_MATCH 0x40000000
+#define W2_R_BROADCAST_DETECTED 0x80000000
+
+#define W2_T_LENGTH_MASK 0x000007FF
+#define W2_T_LOCKED 0x00000800 /* Not an EMAC flag, used by the driver */
+#define W2_T_RFU1 0x00003000
+#define W2_T_LAST_BUFFER 0x00008000
+#define W2_T_NO_CRC 0x00010000
+#define W2_T_RFU2 0x07FE0000
+#define W2_T_BUFFERS_EXHAUSTED 0x08000000
+#define W2_T_TRANSMIT_UNDERRUN 0x10000000
+#define W2_T_RETRY_LIMIT_EXC 0x20000000
+#define W2_T_WRAP 0x40000000
+#define W2_T_USED 0x80000000
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void emac_init(int prio);
+ void EMACSetAddress(const uint8_t *eaddr);
+ bool_t EMACGetLinkStatus(void);
+ BufDescriptorEntry *EMACGetTransmitBuffer(void);
+ void EMACTransmit(BufDescriptorEntry *cptr, size_t size);
+ bool_t EMACReceive(uint8_t *buf, size_t *sizep);
+#ifdef __cplusplus
+}
+#endif
+
+extern EventSource EMACFrameTransmitted, EMACFrameReceived;
+
+#endif /* _SAM7X_EMAC_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/sam7x_serial.c b/os/ports/GCC/ARM7/AT91SAM7X/sam7x_serial.c
new file mode 100644
index 000000000..91aaf2f0e
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/sam7x_serial.c
@@ -0,0 +1,224 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-AT91SAM7X/sam7x_serial.c
+ * @brief AT91SAM7X Serial driver code.
+ * @addtogroup AT91SAM7X_SERIAL
+ * @{
+ */
+
+#include <ch.h>
+
+#include "board.h"
+#include "sam7x_serial.h"
+#include "at91lib/aic.h"
+
+#if USE_SAM7X_USART0 || defined(__DOXYGEN__)
+/** @brief USART0 serial driver identifier.*/
+FullDuplexDriver COM1;
+
+static uint8_t ib1[SERIAL_BUFFERS_SIZE];
+static uint8_t ob1[SERIAL_BUFFERS_SIZE];
+#endif
+
+#if USE_SAM7X_USART1 || defined(__DOXYGEN__)
+/** @brief USART1 serial driver identifier.*/
+FullDuplexDriver COM2;
+
+static uint8_t ib2[SERIAL_BUFFERS_SIZE];
+static uint8_t ob2[SERIAL_BUFFERS_SIZE];
+#endif
+
+static void SetError(AT91_REG csr, FullDuplexDriver *com) {
+ dflags_t sts = 0;
+
+ if (csr & AT91C_US_OVRE)
+ sts |= SD_OVERRUN_ERROR;
+ if (csr & AT91C_US_PARE)
+ sts |= SD_PARITY_ERROR;
+ if (csr & AT91C_US_FRAME)
+ sts |= SD_FRAMING_ERROR;
+ if (csr & AT91C_US_RXBRK)
+ sts |= SD_BREAK_DETECTED;
+ chSysLockFromIsr();
+ chFDDAddFlagsI(com, sts);
+ chSysUnlockFromIsr();
+}
+
+/** @cond never*/
+__attribute__((noinline))
+/** @endcond*/
+/**
+ * @brief Common IRQ handler.
+ * @param[in] u pointer to an USART I/O block
+ * @param[in] com communication channel associated to the USART
+ */
+static void ServeInterrupt(AT91PS_USART u, FullDuplexDriver *com) {
+
+ if (u->US_CSR & AT91C_US_RXRDY) {
+ chSysLockFromIsr();
+ chFDDIncomingDataI(com, u->US_RHR);
+ chSysUnlockFromIsr();
+ }
+ if (u->US_CSR & AT91C_US_TXRDY) {
+ chSysLockFromIsr();
+ msg_t b = chFDDRequestDataI(com);
+ chSysUnlockFromIsr();
+ if (b < Q_OK)
+ u->US_IDR = AT91C_US_TXRDY;
+ else
+ u->US_THR = b;
+ }
+ if (u->US_CSR & (AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK)) {
+ SetError(u->US_CSR, com);
+ u->US_CR = AT91C_US_RSTSTA;
+ }
+ AT91C_BASE_AIC->AIC_EOICR = 0;
+}
+
+#if USE_SAM7X_USART0 || defined(__DOXYGEN__)
+CH_IRQ_HANDLER(USART0IrqHandler) {
+
+ CH_IRQ_PROLOGUE();
+
+ ServeInterrupt(AT91C_BASE_US0, &COM1);
+
+ CH_IRQ_EPILOGUE();
+}
+
+static void OutNotify1(void) {
+
+ AT91C_BASE_US0->US_IER = AT91C_US_TXRDY;
+}
+#endif
+
+#if USE_SAM7X_USART1 || defined(__DOXYGEN__)
+CH_IRQ_HANDLER(USART1IrqHandler) {
+
+ CH_IRQ_PROLOGUE();
+
+ ServeInterrupt(AT91C_BASE_US1, &COM2);
+
+ CH_IRQ_EPILOGUE();
+}
+
+static void OutNotify2(void) {
+
+ AT91C_BASE_US1->US_IER = AT91C_US_TXRDY;
+}
+#endif
+
+/**
+ * @brief USART setup.
+ * @param[in] u pointer to an UART I/O block
+ * @param[in] speed serial port speed in bits per second
+ * @param[in] mr the value for the @p MR register
+ * @note Must be invoked with interrupts disabled.
+ * @note Does not reset the I/O queues.
+ */
+void usart_setup(AT91PS_USART u, int speed, int mr) {
+
+ /* Disables IRQ sources and stop operations.*/
+ u->US_IDR = 0xFFFFFFFF;
+ u->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA;
+
+ /* New parameters setup.*/
+ if (mr & AT91C_US_OVER)
+ u->US_BRGR = MCK / (speed * 8);
+ else
+ u->US_BRGR = MCK / (speed * 16);
+ u->US_MR = mr;
+ u->US_RTOR = 0;
+ u->US_TTGR = 0;
+
+ /* Enables operations and IRQ sources.*/
+ u->US_CR = AT91C_US_RXEN | AT91C_US_TXEN | AT91C_US_DTREN | AT91C_US_RTSEN;
+ u->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE |
+ AT91C_US_RXBRK;
+}
+
+/**
+ * @brief Serial driver initialization.
+ * @param[in] prio0 priority to be assigned to the USART1 IRQ
+ * @param[in] prio1 priority to be assigned to the USART2 IRQ
+ * @note Handshake pads are not enabled inside this function because they
+ * may have another use, enable them externally if needed.
+ * RX and TX pads are handled inside.
+ */
+void serial_init(int prio0, int prio1) {
+
+#if USE_SAM7X_USART0 || defined(__DOXYGEN__)
+ /* I/O queue setup.*/
+ chFDDInit(&COM1, ib1, sizeof ib1, NULL, ob1, sizeof ob1, OutNotify1);
+
+ /* Switches the I/O pins to the peripheral function A, disables pullups.*/
+ AT91C_BASE_PIOA->PIO_PDR = AT91C_PA0_RXD0 | AT91C_PA1_TXD0;
+ AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA0 | AT91C_PIO_PA1;
+ AT91C_BASE_PIOA->PIO_PPUDR = AT91C_PIO_PA0 | AT91C_PIO_PA1;
+
+ /* Starts the clock and clears possible sources of immediate interrupts.*/
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US0);
+ AT91C_BASE_US0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA;
+
+ /* Interrupts setup.*/
+ AIC_ConfigureIT(AT91C_ID_US0,
+ AT91C_AIC_SRCTYPE_HIGH_LEVEL | prio0,
+ USART0IrqHandler);
+ AIC_EnableIT(AT91C_ID_US0);
+
+ /* Default parameters.*/
+ usart_setup(AT91C_BASE_US0, DEFAULT_USART_BITRATE,
+ AT91C_US_USMODE_NORMAL |
+ AT91C_US_CLKS_CLOCK |
+ AT91C_US_CHRL_8_BITS |
+ AT91C_US_PAR_NONE |
+ AT91C_US_NBSTOP_1_BIT);
+#endif
+
+#if USE_SAM7X_USART1 || defined(__DOXYGEN__)
+ /* I/O queues setup.*/
+ chFDDInit(&COM2, ib2, sizeof ib2, NULL, ob2, sizeof ob2, OutNotify2);
+
+ /* Switches the I/O pins to the peripheral function A, disables pullups.*/
+ AT91C_BASE_PIOA->PIO_PDR = AT91C_PA5_RXD1 | AT91C_PA6_TXD1;
+ AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA5 | AT91C_PIO_PA6;
+ AT91C_BASE_PIOA->PIO_PPUDR = AT91C_PIO_PA5 | AT91C_PIO_PA6;
+
+ /* Starts the clock and clears possible sources of immediate interrupts.*/
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1);
+ AT91C_BASE_US1->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA;
+
+ /* Interrupts setup.*/
+ AIC_ConfigureIT(AT91C_ID_US1,
+ AT91C_AIC_SRCTYPE_HIGH_LEVEL | prio1,
+ USART1IrqHandler);
+ AIC_EnableIT(AT91C_ID_US1);
+
+ /* Default parameters.*/
+ usart_setup(AT91C_BASE_US1, DEFAULT_USART_BITRATE,
+ AT91C_US_USMODE_NORMAL |
+ AT91C_US_CLKS_CLOCK |
+ AT91C_US_CHRL_8_BITS |
+ AT91C_US_PAR_NONE |
+ AT91C_US_NBSTOP_1_BIT);
+#endif
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/sam7x_serial.h b/os/ports/GCC/ARM7/AT91SAM7X/sam7x_serial.h
new file mode 100644
index 000000000..1652ab69f
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/sam7x_serial.h
@@ -0,0 +1,86 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-AT91SAM7X/sam7x_serial.h
+ * @brief AT91SAM7X Serial driver macros and structures.
+ * @addtogroup AT91SAM7X_SERIAL
+ * @{
+ */
+
+#ifndef _SAM7X_SERIAL_H_
+#define _SAM7X_SERIAL_H_
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 128 bytes for both the transmission and receive buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 128
+#endif
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, at startup the UARTs are configured at
+ * this speed.
+ * @note It is possible to use @p SetUART() in order to change the working
+ * parameters at runtime.
+ */
+#if !defined(DEFAULT_USART_BITRATE) || defined(__DOXYGEN__)
+#define DEFAULT_USART_BITRATE 38400
+#endif
+
+/**
+ * @brief UART0 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(USE_SAM7X_USART0) || defined(__DOXYGEN__)
+#define USE_SAM7X_USART0 TRUE
+#endif
+
+/**
+ * @brief UART1 driver enable switch.
+ * @details If set to @p TRUE the support for USART2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(USE_SAM7X_USART1) || defined(__DOXYGEN__)
+#define USE_SAM7X_USART1 TRUE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void serial_init(int prio0, int prio1);
+ void usart_setup(AT91PS_USART u, int speed, int mr);
+ CH_IRQ_HANDLER(UART0IrqHandler);
+ CH_IRQ_HANDLER(UART1IrqHandler);
+#ifdef __cplusplus
+}
+#endif
+
+/** @cond never*/
+extern FullDuplexDriver COM1, COM2;
+/** @endcond*/
+
+#endif /* _SAM7X_SERIAL_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/vectors.s b/os/ports/GCC/ARM7/AT91SAM7X/vectors.s
new file mode 100644
index 000000000..29271daf1
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/vectors.s
@@ -0,0 +1,74 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+.section vectors
+.code 32
+.balign 4
+/*
+ * System entry points.
+ */
+_start:
+ ldr pc, _reset
+ ldr pc, _undefined
+ ldr pc, _swi
+ ldr pc, _prefetch
+ ldr pc, _abort
+ nop
+ ldr pc, [pc,#-0xF20] /* AIC - AIC_IVR */
+ ldr pc, [pc,#-0xF20] /* AIC - AIC_FVR */
+
+_reset:
+ .word ResetHandler /* In crt0.s */
+_undefined:
+ .word UndHandler
+_swi:
+ .word SwiHandler
+_prefetch:
+ .word PrefetchHandler
+_abort:
+ .word AbortHandler
+ .word 0
+ .word 0
+ .word 0
+
+.text
+.code 32
+.balign 4
+
+/*
+ * Default exceptions handlers. The handlers are declared weak in order to be
+ * replaced by the real handling code. Everything is defaulted to an infinite
+ * loop.
+ */
+.weak UndHandler
+UndHandler:
+
+.weak SwiHandler
+SwiHandler:
+
+.weak PrefetchHandler
+PrefetchHandler:
+
+.weak AbortHandler
+AbortHandler:
+
+.weak FiqHandler
+FiqHandler:
+
+.loop: b .loop
diff --git a/os/ports/GCC/ARM7/AT91SAM7X/wfi.h b/os/ports/GCC/ARM7/AT91SAM7X/wfi.h
new file mode 100644
index 000000000..5e2da044d
--- /dev/null
+++ b/os/ports/GCC/ARM7/AT91SAM7X/wfi.h
@@ -0,0 +1,35 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _WFI_H_
+#define _WFI_H_
+
+#include "at91lib/AT91SAM7X256.h"
+
+#ifndef port_wait_for_interrupt
+#if ENABLE_WFI_IDLE != 0
+#define port_wait_for_interrupt() { \
+ AT91C_BASE_SYS->PMC_SCDR = AT91C_PMC_PCK; \
+}
+#else
+#define port_wait_for_interrupt()
+#endif
+#endif
+
+#endif /* _WFI_H_ */
diff --git a/os/ports/GCC/ARM7/LPC214x/lpc214x.h b/os/ports/GCC/ARM7/LPC214x/lpc214x.h
new file mode 100644
index 000000000..e260da713
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/lpc214x.h
@@ -0,0 +1,523 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file lpc214x.h
+ * @brief LPC214x register definitions
+ */
+
+#ifndef _LPC214X_H_
+#define _LPC214X_H_
+
+typedef volatile unsigned char IOREG8;
+typedef volatile unsigned int IOREG32;
+
+/*
+ * System.
+ */
+#define MEMMAP (*((IOREG32 *)0xE01FC040))
+#define PCON (*((IOREG32 *)0xE01FC0C0))
+#define PCONP (*((IOREG32 *)0xE01FC0C4))
+#define VPBDIV (*((IOREG32 *)0xE01FC100))
+#define EXTINT (*((IOREG32 *)0xE01FC140))
+#define INTWAKE (*((IOREG32 *)0xE01FC144))
+#define EXTMODE (*((IOREG32 *)0xE01FC148))
+#define EXTPOLAR (*((IOREG32 *)0xE01FC14C))
+#define RSID (*((IOREG32 *)0xE01FC180))
+#define CSPR (*((IOREG32 *)0xE01FC184))
+#define SCS (*((IOREG32 *)0xE01FC1A0))
+
+#define VPD_D4 0
+#define VPD_D1 1
+#define VPD_D2 2
+#define VPD_RESERVED 3
+
+#define PCTIM0 (1 << 1)
+#define PCTIM1 (1 << 2)
+#define PCUART0 (1 << 3)
+#define PCUART1 (1 << 4)
+#define PCPWM0 (1 << 5)
+#define PCI2C0 (1 << 7)
+#define PCSPI0 (1 << 8)
+#define PCRTC (1 << 9)
+#define PCSPI1 (1 << 10)
+#define PCAD0 (1 << 12)
+#define PCI2C1 (1 << 19)
+#define PCAD1 (1 << 20)
+#define PCUSB (1 << 31)
+#define PCALL (PCTIM0 | PCTIM1 | PCUART0 | PCUART1 | \
+ PCPWM0 | PCI2C0 | PCSPI0 | PCRTC | PCSPI1 | \
+ PCAD0 | PCI2C1 | PCAD1 | PCUSB)
+
+#define EINT0 1
+#define EINT1 2
+#define EINT2 4
+#define EINT3 8
+
+#define EXTWAKE0 1
+#define EXTWAKE1 2
+#define EXTWAKE2 4
+#define EXTWAKE3 8
+#define USBWAKE 0x20
+#define BODWAKE 0x4000
+#define RTCWAKE 0x8000
+
+#define EXTMODE0 1
+#define EXTMODE1 2
+#define EXTMODE2 4
+#define EXTMODE3 8
+
+#define EXTPOLAR0 1
+#define EXTPOLAR1 2
+#define EXTPOLAR2 4
+#define EXTPOLAR3 8
+
+typedef struct {
+ IOREG32 PLL_CON;
+ IOREG32 PLL_CFG;
+ IOREG32 PLL_STAT;
+ IOREG32 PLL_FEED;
+} PLL;
+
+#define PLL0Base ((PLL *)0xE01FC080)
+#define PLL1Base ((PLL *)0xE01FC0A0)
+#define PLL0CON (PLL0Base->PLL_CON)
+#define PLL0CFG (PLL0Base->PLL_CFG)
+#define PLL0STAT (PLL0Base->PLL_STAT)
+#define PLL0FEED (PLL0Base->PLL_FEED)
+#define PLL1CON (PLL1Base->PLL_CON)
+#define PLL1CFG (PLL1Base->PLL_CFG)
+#define PLL1STAT (PLL1Base->PLL_STAT)
+#define PLL1FEED (PLL1Base->PLL_FEED)
+
+/*
+ * Pins.
+ */
+typedef struct {
+ IOREG32 PS_SEL0;
+ IOREG32 PS_SEL1;
+ IOREG32 PS_SEL2;
+} PS;
+
+#define PSBase ((PS *)0xE002C000)
+#define PINSEL0 (PSBase->PS_SEL0)
+#define PINSEL1 (PSBase->PS_SEL1)
+#define PINSEL2 (PSBase->PS_SEL2)
+
+/*
+ * VIC
+ */
+#define SOURCE_WDT 0
+#define SOURCE_ARMCore0 2
+#define SOURCE_ARMCore1 3
+#define SOURCE_Timer0 4
+#define SOURCE_Timer1 5
+#define SOURCE_UART0 6
+#define SOURCE_UART1 7
+#define SOURCE_PWM0 8
+#define SOURCE_I2C0 9
+#define SOURCE_SPI0 10
+#define SOURCE_SPI1 11
+#define SOURCE_PLL 12
+#define SOURCE_RTC 13
+#define SOURCE_EINT0 14
+#define SOURCE_EINT1 15
+#define SOURCE_EINT2 16
+#define SOURCE_EINT3 17
+#define SOURCE_ADC0 18
+#define SOURCE_I2C1 19
+#define SOURCE_BOD 20
+#define SOURCE_ADC1 21
+#define SOURCE_USB 22
+
+#define INTMASK(n) (1 << (n))
+#define ALLINTMASK (INTMASK(SOURCE_WDT) | INTMASK(SOURCE_ARMCore0) | \
+ INTMASK(SOURCE_ARMCore1) | INTMASK(SOURCE_Timer0) | \
+ INTMASK(SOURCE_Timer1) | INTMASK(SOURCE_UART0) | \
+ INTMASK(SOURCE_UART1) | INTMASK(SOURCE_PWM0) | \
+ INTMASK(SOURCE_I2C0) | INTMASK(SOURCE_SPI0) | \
+ INTMASK(SOURCE_SPI1) | INTMASK(SOURCE_PLL) | \
+ INTMASK(SOURCE_RTC) | INTMASK(SOURCE_EINT0) | \
+ INTMASK(SOURCE_EINT1) | INTMASK(SOURCE_EINT2) | \
+ INTMASK(SOURCE_EINT3) | INTMASK(SOURCE_ADC0) | \
+ INTMASK(SOURCE_I2C1) | INTMASK(SOURCE_BOD) | \
+ INTMASK(SOURCE_ADC1) | INTMASK(SOURCE_USB))
+
+typedef struct {
+ IOREG32 VIC_IRQStatus;
+ IOREG32 VIC_FIQStatus;
+ IOREG32 VIC_RawIntr;
+ IOREG32 VIC_IntSelect;
+ IOREG32 VIC_IntEnable;
+ IOREG32 VIC_IntEnClear;
+ IOREG32 VIC_SoftInt;
+ IOREG32 VIC_SoftIntClear;
+ IOREG32 VIC_Protection;
+ IOREG32 unused1[3];
+ IOREG32 VIC_VectAddr;
+ IOREG32 VIC_DefVectAddr;
+ IOREG32 unused2[50];
+ IOREG32 VIC_VectAddrs[16];
+ IOREG32 unused3[48];
+ IOREG32 VIC_VectCntls[16];
+} VIC;
+
+#define VICBase ((VIC *)0xFFFFF000)
+#define VICVectorsBase ((IOREG32 *)0xFFFFF100)
+#define VICControlsBase ((IOREG32 *)0xFFFFF200)
+
+#define VICIRQStatus (VICBase->VIC_IRQStatus)
+#define VICFIQStatus (VICBase->VIC_FIQStatus)
+#define VICRawIntr (VICBase->VIC_RawIntr)
+#define VICIntSelect (VICBase->VIC_IntSelect)
+#define VICIntEnable (VICBase->VIC_IntEnable)
+#define VICIntEnClear (VICBase->VIC_IntEnClear)
+#define VICSoftInt (VICBase->VIC_SoftInt)
+#define VICSoftIntClear (VICBase->VIC_SoftIntClear)
+#define VICProtection (VICBase->VIC_Protection)
+#define VICVectAddr (VICBase->VIC_VectAddr)
+#define VICDefVectAddr (VICBase->VIC_DefVectAddr)
+
+#define VICVectAddrs(n) (VICBase->VIC_VectAddrs[n])
+#define VICVectCntls(n) (VICBase->VIC_VectCntls[n])
+
+/*
+ * MAM.
+ */
+typedef struct {
+ IOREG32 MAM_Control;
+ IOREG32 MAM_Timing;
+} MAM;
+
+#define MAMBase ((MAM *)0xE01FC000)
+#define MAMCR (MAMBase->MAM_Control)
+#define MAMTIM (MAMBase->MAM_Timing)
+
+/*
+ * GPIO - FIO.
+ */
+typedef struct {
+ IOREG32 IO_PIN;
+ IOREG32 IO_SET;
+ IOREG32 IO_DIR;
+ IOREG32 IO_CLR;
+} GPIO;
+
+#define GPIO0Base ((GPIO *)0xE0028000)
+#define IO0PIN (GPIO0Base->IO_PIN)
+#define IO0SET (GPIO0Base->IO_SET)
+#define IO0DIR (GPIO0Base->IO_DIR)
+#define IO0CLR (GPIO0Base->IO_CLR)
+
+#define GPIO1Base ((GPIO *)0xE0028010)
+#define IO1PIN (GPIO1Base->IO_PIN)
+#define IO1SET (GPIO1Base->IO_SET)
+#define IO1DIR (GPIO1Base->IO_DIR)
+#define IO1CLR (GPIO1Base->IO_CLR)
+
+typedef struct {
+ IOREG32 FIO_DIR;
+ IOREG32 unused1;
+ IOREG32 unused2;
+ IOREG32 unused3;
+ IOREG32 FIO_MASK;
+ IOREG32 FIO_PIN;
+ IOREG32 FIO_SET;
+ IOREG32 FIO_CLR;
+} FIO;
+
+#define FIO0Base ((FIO *)0x3FFFC000)
+#define FIO0DIR (FIO0Base->FIO_DIR)
+#define FIO0MASK (FIO0Base->FIO_MASK)
+#define FIO0PIN (FIO0Base->FIO_PIN)
+#define FIO0SET (FIO0Base->FIO_SET)
+#define FIO0CLR (FIO0Base->FIO_CLR)
+
+#define FIO1Base ((FIO *)0x3FFFC020)
+#define FIO1DIR (FIO1Base->FIO_DIR)
+#define FIO1MASK (FIO1Base->FIO_MASK)
+#define FIO1PIN (FIO1Base->FIO_PIN)
+#define FIO1SET (FIO1Base->FIO_SET)
+#define FIO1CLR (FIO1Base->FIO_CLR)
+
+/*
+ * UART.
+ */
+typedef struct {
+ union {
+ IOREG32 UART_RBR;
+ IOREG32 UART_THR;
+ IOREG32 UART_DLL;
+ };
+ union {
+ IOREG32 UART_IER;
+ IOREG32 UART_DLM;
+ };
+ union {
+ IOREG32 UART_IIR;
+ IOREG32 UART_FCR;
+ };
+ IOREG32 UART_LCR;
+ IOREG32 UART_MCR; // UART1 only
+ IOREG32 UART_LSR;
+ IOREG32 unused18;
+ IOREG32 UART_SCR;
+ IOREG32 UART_ACR;
+ IOREG32 unused24;
+ IOREG32 UART_FDR;
+ IOREG32 unused2C;
+ IOREG32 UART_TER;
+} UART;
+
+#define U0Base ((UART *)0xE000C000)
+#define U0RBR (U0Base->UART_RBR)
+#define U0THR (U0Base->UART_THR)
+#define U0DLL (U0Base->UART_DLL)
+#define U0IER (U0Base->UART_IER)
+#define U0DLM (U0Base->UART_DLM)
+#define U0IIR (U0Base->UART_IIR)
+#define U0FCR (U0Base->UART_FCR)
+#define U0LCR (U0Base->UART_LCR)
+#define U0LSR (U0Base->UART_LSR)
+#define U0SCR (U0Base->UART_SCR)
+#define U0ACR (U0Base->UART_ACR)
+#define U0FDR (U0Base->UART_FDR)
+#define U0TER (U0Base->UART_TER)
+
+#define U1Base ((UART *)0xE0010000)
+#define U1RBR (U1Base->UART_RBR)
+#define U1THR (U1Base->UART_THR)
+#define U1DLL (U1Base->UART_DLL)
+#define U1IER (U1Base->UART_IER)
+#define U1DLM (U1Base->UART_DLM)
+#define U1IIR (U1Base->UART_IIR)
+#define U1FCR (U1Base->UART_FCR)
+#define U1MCR (U1Base->UART_MCR)
+#define U1LCR (U1Base->UART_LCR)
+#define U1LSR (U1Base->UART_LSR)
+#define U1SCR (U1Base->UART_SCR)
+#define U1ACR (U1Base->UART_ACR)
+#define U1FDR (U1Base->UART_FDR)
+#define U1TER (U1Base->UART_TER)
+
+#define IIR_SRC_MASK 0x0F
+#define IIR_SRC_NONE 0x01
+#define IIR_SRC_TX 0x02
+#define IIR_SRC_RX 0x04
+#define IIR_SRC_ERROR 0x06
+#define IIR_SRC_TIMEOUT 0x0C
+
+#define IER_RBR 1
+#define IER_THRE 2
+#define IER_STATUS 4
+
+#define IIR_INT_PENDING 1
+
+#define LCR_WL5 0
+#define LCR_WL6 1
+#define LCR_WL7 2
+#define LCR_WL8 3
+#define LCR_STOP1 0
+#define LCR_STOP2 4
+#define LCR_NOPARITY 0
+#define LCR_PARITYODD 0x08
+#define LCR_PARITYEVEN 0x18
+#define LCR_PARITYONE 0x28
+#define LCR_PARITYZERO 0x38
+#define LCR_BREAK_ON 0x40
+#define LCR_DLAB 0x80
+
+#define FCR_ENABLE 1
+#define FCR_RXRESET 2
+#define FCR_TXRESET 4
+#define FCR_TRIGGER0 0
+#define FCR_TRIGGER1 0x40
+#define FCR_TRIGGER2 0x80
+#define FCR_TRIGGER3 0xC0
+
+#define LSR_RBR_FULL 1
+#define LSR_OVERRUN 2
+#define LSR_PARITY 4
+#define LSR_FRAMING 8
+#define LSR_BREAK 0x10
+#define LSR_THRE 0x20
+#define LSR_TEMT 0x40
+#define LSR_RXFE 0x80
+
+#define TER_ENABLE 0x80
+
+/*
+ * SSP.
+ */
+typedef struct {
+ IOREG32 SSP_CR0;
+ IOREG32 SSP_CR1;
+ IOREG32 SSP_DR;
+ IOREG32 SSP_SR;
+ IOREG32 SSP_CPSR;
+ IOREG32 SSP_IMSC;
+ IOREG32 SSP_RIS;
+ IOREG32 SSP_MIS;
+ IOREG32 SSP_ICR;
+} SSP;
+
+#define SSPBase ((SSP *)0xE0068000)
+#define SSPCR0 (SSPBase->SSP_CR0)
+#define SSPCR1 (SSPBase->SSP_CR1)
+#define SSPDR (SSPBase->SSP_DR)
+#define SSPSR (SSPBase->SSP_SR)
+#define SSPCPSR (SSPBase->SSP_CPSR)
+#define SSPIMSC (SSPBase->SSP_IMSC)
+#define SSPRIS (SSPBase->SSP_RIS)
+#define SSPMIS (SSPBase->SSP_MIS)
+#define SSPICR (SSPBase->SSP_ICR)
+
+#define CR0_DSS4BIT 3
+#define CR0_DSS5BIT 4
+#define CR0_DSS6BIT 5
+#define CR0_DSS7BIT 6
+#define CR0_DSS8BIT 7
+#define CR0_DSS9BIT 8
+#define CR0_DSS10BIT 9
+#define CR0_DSS11BIT 0xA
+#define CR0_DSS12BIT 0xB
+#define CR0_DSS13BIT 0xC
+#define CR0_DSS14BIT 0xD
+#define CR0_DSS15BIT 0xE
+#define CR0_DSS16BIT 0xF
+#define CR0_FRFSPI 0
+#define CR0_FRFSSI 0x10
+#define CR0_FRFMW 0x20
+#define CR0_CPOL 0x40
+#define CR0_CPHA 0x80
+#define CR0_CLOCKRATE(n) ((n) << 8)
+
+#define CR1_LBM 1
+#define CR1_SSE 2
+#define CR1_MS 4
+#define CR1_SOD 8
+
+#define SR_TFE 1
+#define SR_TNF 2
+#define SR_RNE 4
+#define SR_RFF 8
+#define SR_BSY 0x10
+
+#define IMSC_ROR 1
+#define IMSC_RT 2
+#define IMSC_RX 4
+#define IMSC_TX 8
+
+#define RIS_ROR 1
+#define RIS_RT 2
+#define RIS_RX 4
+#define RIS_TX 8
+
+#define MIS_ROR 1
+#define MIS_RT 2
+#define MIS_RX 4
+#define MIS_TX 8
+
+#define ICR_ROR 1
+#define ICR_RT 2
+
+/*
+ * Timers/Counters.
+ */
+typedef struct {
+ IOREG32 TC_IR;
+ IOREG32 TC_TCR;
+ IOREG32 TC_TC;
+ IOREG32 TC_PR;
+ IOREG32 TC_PC;
+ IOREG32 TC_MCR;
+ IOREG32 TC_MR0;
+ IOREG32 TC_MR1;
+ IOREG32 TC_MR2;
+ IOREG32 TC_MR3;
+ IOREG32 TC_CCR;
+ IOREG32 TC_CR0;
+ IOREG32 TC_CR1;
+ IOREG32 TC_CR2;
+ IOREG32 TC_CR3;
+ IOREG32 TC_EMR;
+ IOREG32 TC_CTCR;
+} TC;
+
+#define T0Base ((TC *)0xE0004000)
+#define T0IR (T0Base->TC_IR)
+#define T0TCR (T0Base->TC_TCR)
+#define T0TC (T0Base->TC_TC)
+#define T0PR (T0Base->TC_PR)
+#define T0PC (T0Base->TC_PC)
+#define T0MCR (T0Base->TC_MCR)
+#define T0MR0 (T0Base->TC_MR0)
+#define T0MR1 (T0Base->TC_MR1)
+#define T0MR2 (T0Base->TC_MR2)
+#define T0MR3 (T0Base->TC_MR3)
+#define T0CCR (T0Base->TC_CCR)
+#define T0CR0 (T0Base->TC_CR0)
+#define T0CR1 (T0Base->TC_CR1)
+#define T0CR2 (T0Base->TC_CR2)
+#define T0CR3 (T0Base->TC_CR3)
+#define T0EMR (T0Base->TC_EMR)
+#define T0CTCR (T0Base->TC_CTCR)
+
+#define T1Base ((TC *)0xE0008000)
+#define T1IR (T1Base->TC_IR)
+#define T1TCR (T1Base->TC_TCR)
+#define T1TC (T1Base->TC_TC)
+#define T1PR (T1Base->TC_PR)
+#define T1PC (T1Base->TC_PC)
+#define T1MCR (T1Base->TC_MCR)
+#define T1MR0 (T1Base->TC_MR0)
+#define T1MR1 (T1Base->TC_MR1)
+#define T1MR2 (T1Base->TC_MR2)
+#define T1MR3 (T1Base->TC_MR3)
+#define T1CCR (T1Base->TC_CCR)
+#define T1CR0 (T1Base->TC_CR0)
+#define T1CR1 (T1Base->TC_CR1)
+#define T1CR2 (T1Base->TC_CR2)
+#define T1CR3 (T1Base->TC_CR3)
+#define T1EMR (T1Base->TC_EMR)
+#define T1CTCR (T1Base->TC_CTCR)
+
+/*
+ * Watchdog.
+ */
+typedef struct {
+ IOREG32 WD_MOD;
+ IOREG32 WD_TC;
+ IOREG32 WD_FEED;
+ IOREG32 WD_TV;
+} WD;
+
+#define WDBase ((WD *)0xE0000000)
+#define WDMOD (WDBase->WD_MOD)
+#define WDTC (WDBase->WD_TC)
+#define WDFEED (WDBase->WD_FEED)
+#define WDTV (WDBase->WD_TV)
+
+/*
+ * DAC.
+ */
+#define DACR (*((IOREG32 *)0xE006C000))
+
+#endif /* _LPC214X_H_ */
+
diff --git a/os/ports/GCC/ARM7/LPC214x/lpc214x_serial.c b/os/ports/GCC/ARM7/LPC214x/lpc214x_serial.c
new file mode 100644
index 000000000..e452cec8d
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/lpc214x_serial.c
@@ -0,0 +1,268 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-LPC214x/lpc214x_serial.c
+ * @brief LPC214x Serial driver code.
+ * @addtogroup LPC214x_SERIAL
+ * @{
+ */
+
+#include <ch.h>
+
+#include "lpc214x.h"
+#include "vic.h"
+#include "lpc214x_serial.h"
+#include "board.h"
+
+#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
+/** @brief UART0 serial driver identifier.*/
+FullDuplexDriver COM1;
+
+static uint8_t ib1[SERIAL_BUFFERS_SIZE];
+static uint8_t ob1[SERIAL_BUFFERS_SIZE];
+#endif
+
+#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
+/** @brief UART1 serial driver identifier.*/
+FullDuplexDriver COM2;
+
+static uint8_t ib2[SERIAL_BUFFERS_SIZE];
+static uint8_t ob2[SERIAL_BUFFERS_SIZE];
+#endif
+
+/**
+ * @brief Error handling routine.
+ * @param[in] err UART LSR register value
+ * @param[in] com communication channel associated to the USART
+ */
+static void SetError(IOREG32 err, FullDuplexDriver *com) {
+ dflags_t sts = 0;
+
+ if (err & LSR_OVERRUN)
+ sts |= SD_OVERRUN_ERROR;
+ if (err & LSR_PARITY)
+ sts |= SD_PARITY_ERROR;
+ if (err & LSR_FRAMING)
+ sts |= SD_FRAMING_ERROR;
+ if (err & LSR_BREAK)
+ sts |= SD_BREAK_DETECTED;
+ chSysLockFromIsr();
+ chFDDAddFlagsI(com, sts);
+ chSysUnlockFromIsr();
+}
+
+/** @cond never*/
+__attribute__((noinline))
+/** @endcond*/
+/**
+ * @brief Common IRQ handler.
+ * @param[in] u pointer to an UART I/O block
+ * @param[in] com communication channel associated to the UART
+ * @note Tries hard to clear all the pending interrupt sources, we dont want to
+ * go through the whole ISR and have another interrupt soon after.
+ */
+static void ServeInterrupt(UART *u, FullDuplexDriver *com) {
+
+ while (TRUE) {
+
+ switch (u->UART_IIR & IIR_SRC_MASK) {
+ case IIR_SRC_NONE:
+ return;
+ case IIR_SRC_ERROR:
+ SetError(u->UART_LSR, com);
+ break;
+ case IIR_SRC_TIMEOUT:
+ case IIR_SRC_RX:
+ while (u->UART_LSR & LSR_RBR_FULL) {
+ chSysLockFromIsr();
+ if (chIQPutI(&com->d2.iqueue, u->UART_RBR) < Q_OK)
+ chFDDAddFlagsI(com, SD_OVERRUN_ERROR);
+ chSysUnlockFromIsr();
+ }
+ chSysLockFromIsr();
+ chEvtBroadcastI(&com->d1.ievent);
+ chSysUnlockFromIsr();
+ break;
+ case IIR_SRC_TX:
+ {
+#if UART_FIFO_PRELOAD > 0
+ int i = UART_FIFO_PRELOAD;
+ do {
+ chSysLockFromIsr();
+ msg_t b = chOQGetI(&com->d2.oqueue);
+ chSysUnlockFromIsr();
+ if (b < Q_OK) {
+ u->UART_IER &= ~IER_THRE;
+ chSysLockFromIsr();
+ chEvtBroadcastI(&com->d1.oevent);
+ chSysUnlockFromIsr();
+ break;
+ }
+ u->UART_THR = b;
+ } while (--i);
+#else
+ chSysLockFromIsr();
+ msg_t b = chFDDRequestDataI(com);
+ chSysUnlockFromIsr();
+ if (b < Q_OK)
+ u->UART_IER &= ~IER_THRE;
+ else
+ u->UART_THR = b;
+#endif
+ }
+ default:
+ u->UART_THR;
+ u->UART_RBR;
+ }
+ }
+}
+
+#if UART_FIFO_PRELOAD > 0
+static void preload(UART *u, FullDuplexDriver *com) {
+
+ if (u->UART_LSR & LSR_THRE) {
+ int i = UART_FIFO_PRELOAD;
+ do {
+ chSysLockFromIsr();
+ msg_t b = chOQGetI(&com->d2.oqueue);
+ chSysUnlockFromIsr();
+ if (b < Q_OK) {
+ chSysLockFromIsr();
+ chEvtBroadcastI(&com->d1.oevent);
+ chSysUnlockFromIsr();
+ return;
+ }
+ u->UART_THR = b;
+ } while (--i);
+ }
+ u->UART_IER |= IER_THRE;
+}
+#endif
+
+#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
+CH_IRQ_HANDLER(UART0IrqHandler) {
+
+ CH_IRQ_PROLOGUE();
+
+ ServeInterrupt(U0Base, &COM1);
+ VICVectAddr = 0;
+
+ CH_IRQ_EPILOGUE();
+}
+
+static void OutNotify1(void) {
+#if UART_FIFO_PRELOAD > 0
+
+ preload(U0Base, &COM1);
+#else
+ UART *u = U0Base;
+
+ if (u->UART_LSR & LSR_THRE) {
+ chSysLockFromIsr();
+ u->UART_THR = chOQGetI(&COM1.sd_oqueue);
+ chSysUnlockFromIsr();
+ }
+ u->UART_IER |= IER_THRE;
+#endif
+}
+#endif
+
+#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
+CH_IRQ_HANDLER(UART1IrqHandler) {
+
+ CH_IRQ_PROLOGUE();
+
+ ServeInterrupt(U1Base, &COM2);
+ VICVectAddr = 0;
+
+ CH_IRQ_EPILOGUE();
+}
+
+static void OutNotify2(void) {
+#if UART_FIFO_PRELOAD > 0
+
+ preload(U1Base, &COM2);
+#else
+ UART *u = U1Base;
+
+ if (u->UART_LSR & LSR_THRE)
+ u->UART_THR = chOQGetI(&COM2.sd_oqueue);
+ u->UART_IER |= IER_THRE;
+#endif
+}
+#endif
+
+/**
+ * @brief UART setup.
+ * @param[in] u pointer to an UART I/O block
+ * @param[in] speed serial port speed in bits per second
+ * @param[in] lcr the value for the @p LCR register
+ * @param[in] fcr the value for the @p FCR register
+ * @note Must be invoked with interrupts disabled.
+ * @note Does not reset the I/O queues.
+ */
+void uart_setup(UART *u, int speed, int lcr, int fcr) {
+
+ int div = PCLK / (speed << 4);
+ u->UART_LCR = lcr | LCR_DLAB;
+ u->UART_DLL = div;
+ u->UART_DLM = div >> 8;
+ u->UART_LCR = lcr;
+ u->UART_FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | fcr;
+ u->UART_ACR = 0;
+ u->UART_FDR = 0x10;
+ u->UART_TER = TER_ENABLE;
+ u->UART_IER = IER_RBR | IER_STATUS;
+}
+
+/**
+ * @brief Serial driver initialization.
+ * @param[in] vector1 IRC vector to be used for UART0
+ * @param[in] vector2 IRC vector to be used for UART1
+ * @note Handshake pads are not enabled inside this function because they
+ * may have another use, enable them externally if needed.
+ * RX and TX pads are handled inside.
+ */
+void serial_init(int vector1, int vector2) {
+
+#if USE_LPC214x_UART0
+ SetVICVector(UART0IrqHandler, vector1, SOURCE_UART0);
+ PCONP = (PCONP & PCALL) | PCUART0;
+ chFDDInit(&COM1, ib1, sizeof ib1, NULL, ob1, sizeof ob1, OutNotify1);
+ uart_setup(U0Base,
+ DEFAULT_UART_BITRATE,
+ LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
+ FCR_TRIGGER0);
+ VICIntEnable = INTMASK(SOURCE_UART0);
+#endif
+
+#if USE_LPC214x_UART1
+ SetVICVector(UART1IrqHandler, vector2, SOURCE_UART1);
+ PCONP = (PCONP & PCALL) | PCUART1;
+ chFDDInit(&COM2, ib2, sizeof ib2, NULL, ob2, sizeof ob2, OutNotify2);
+ uart_setup(U1Base,
+ DEFAULT_UART_BITRATE,
+ LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
+ FCR_TRIGGER0);
+ VICIntEnable = INTMASK(SOURCE_UART0) | INTMASK(SOURCE_UART1);
+#endif
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/LPC214x/lpc214x_serial.h b/os/ports/GCC/ARM7/LPC214x/lpc214x_serial.h
new file mode 100644
index 000000000..021dbf6a1
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/lpc214x_serial.h
@@ -0,0 +1,102 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-LPC214x/lpc214x_serial.h
+ * @brief LPC214x Serial driver macros and structures.
+ * @addtogroup LPC214x_SERIAL
+ * @{
+ */
+
+#ifndef _LPC214x_SERIAL_H_
+#define _LPC214x_SERIAL_H_
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 128 bytes for both the transmission and receive buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 128
+#endif
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, at startup the UARTs are configured at
+ * this speed.
+ * @note It is possible to use @p SetUART() in order to change the working
+ * parameters at runtime.
+ */
+#if !defined(DEFAULT_UART_BITRATE) || defined(__DOXYGEN__)
+#define DEFAULT_UART_BITRATE 38400
+#endif
+
+/**
+ * @brief FIFO preload parameter.
+ * @details Configuration parameter, this values defines how many bytes are
+ * preloaded in the HW transmit FIFO for each interrupt, the maximum value is
+ * 16 the minimum is 2, the value 0 disables the feature.
+ * @note An high value reduces the number of interrupts generated but can
+ * also increase the worst case interrupt response time because the
+ * preload loops.
+ * @note The value zero disables the feature and reverts to a simpler code
+ * that will generate an interrupt for each output byte but is much
+ * smaller and simpler.
+ */
+#if !defined(UART_FIFO_PRELOAD) || defined(__DOXYGEN__)
+#define UART_FIFO_PRELOAD 16
+#endif
+
+/**
+ * @brief UART0 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p TRUE .
+ */
+#if !defined(USE_LPC214x_UART0) || defined(__DOXYGEN__)
+#define USE_LPC214x_UART0 TRUE
+#endif
+
+/**
+ * @brief UART1 driver enable switch.
+ * @details If set to @p TRUE the support for USART2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(USE_LPC214x_UART1) || defined(__DOXYGEN__)
+#define USE_LPC214x_UART1 TRUE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void serial_init(int vector1, int vector2);
+ void uart_setup(UART *u, int speed, int lcr, int fcr);
+ CH_IRQ_HANDLER(UART0IrqHandler);
+ CH_IRQ_HANDLER(UART1IrqHandler);
+#ifdef __cplusplus
+}
+#endif
+
+/** @cond never*/
+extern FullDuplexDriver COM1, COM2;
+/** @endcond*/
+
+#endif /* _LPC214x_SERIAL_H_*/
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/LPC214x/lpc214x_ssp.c b/os/ports/GCC/ARM7/LPC214x/lpc214x_ssp.c
new file mode 100644
index 000000000..790182576
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/lpc214x_ssp.c
@@ -0,0 +1,133 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-LPC214x/lpc214x_ssp.c
+ * @brief LPC214x SSP driver code.
+ * @addtogroup LPC214x_SSP
+ * @{
+ */
+
+#include <ch.h>
+#include <pal.h>
+
+#include "lpc214x.h"
+#include "lpc214x_ssp.h"
+
+#if LPC214x_SSP_USE_MUTEX
+static Semaphore me;
+#endif
+
+/**
+ * @brief Aquires access to the SSP bus.
+ * @note This function also handles the mutual exclusion on the SSP bus if
+ * the @p LPC214x_SSP_USE_MUTEX option is enabled.
+ */
+void sspAcquireBus(void) {
+
+#if LPC214x_SSP_USE_MUTEX
+ chSemWait(&me);
+#endif
+ palClearPad(IOPORT_A, 20);
+}
+
+/**
+ * @brief Releases the SSP bus.
+ * @note This function also handles the mutual exclusion on the SSP bus if
+ * the @p LPC214x_SSP_USE_MUTEX option is enabled.
+ */
+void sspReleaseBus(void) {
+
+ palClearPad(IOPORT_A, 20);
+#if LPC214x_SSP_USE_MUTEX
+ chSemSignal(&me);
+#endif
+}
+
+/**
+ * @brief Synchronous SSP transfer.
+ * @param[in] in pointer to the incoming data buffer, if this parameter is set
+ * to @p NULL then the incoming data is discarded
+ * @param[out] out pointer to the outgoing data buffer, if this parameter is
+ * set to @p NULL then 0xFF bytes will be output
+ * @param[in] n the number of bytes to be transferred
+ * @note The transfer is performed in a software loop and is not interrupt
+ * driven for performance reasons, this function should be invoked
+ * by a low priority thread in order to "play nice" with the
+ * rest of the system. This kind of peripheral would really need a
+ * dedicated DMA channel.
+ */
+void sspRW(uint8_t *in, uint8_t *out, size_t n) {
+ int icnt, ocnt;
+
+ SSP *ssp = SSPBase;
+ icnt = ocnt = n;
+ while (icnt) {
+
+ if (ssp->SSP_SR & SR_RNE) {
+ if (in)
+ *in++ = ssp->SSP_DR;
+ else
+ ssp->SSP_DR;
+ icnt--;
+ continue; /* Priority over transmission. */
+ }
+
+ if (ocnt && (ssp->SSP_SR & SR_TNF)) {
+ if (out)
+ ssp->SSP_DR = *out++;
+ else
+ ssp->SSP_DR = 0xFF;
+ ocnt--;
+ }
+ }
+}
+
+/**
+ * @brief SSP setup.
+ * @param[in] cpsr the value for the @p CPSR register
+ * @param[in] cr0 the value for the @p CR0 register
+ * @param[in] cr1 the value for the @p CR1 register
+ */
+void ssp_setup(int cpsr, int cr0, int cr1) {
+
+ SSP *ssp = SSPBase;
+ ssp->SSP_CR1 = 0;
+ ssp->SSP_CR0 = cr0;
+ ssp->SSP_CPSR = cpsr;
+ ssp->SSP_CR1 = cr1 | CR1_SSE;
+}
+
+/**
+ * @brief SSP subsystem initialization.
+ */
+void ssp_init(void) {
+
+ /* Enables the SPI1 clock */
+ PCONP = (PCONP & PCALL) | PCSPI1;
+
+ /* Clock = PCLK / 2 (fastest). */
+ ssp_setup(2, CR0_DSS8BIT | CR0_FRFSPI | CR0_CLOCKRATE(0), 0);
+
+#if LPC214x_SSP_USE_MUTEX
+ chSemInit(&me, 1);
+#endif
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/LPC214x/lpc214x_ssp.h b/os/ports/GCC/ARM7/LPC214x/lpc214x_ssp.h
new file mode 100644
index 000000000..cae264a92
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/lpc214x_ssp.h
@@ -0,0 +1,54 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-LPC214x/lpc214x_ssp.h
+ * @brief LPC214x SSP driver macros and structures.
+ * @addtogroup LPC214x_SSP
+ * @{
+ */
+
+#ifndef _LPC214x_SSP_H_
+#define _LPC214x_SSP_H_
+
+/**
+ * @brief SSP bus mutual exclusion control.
+ * @details Configuration parameter, if set to @p TRUE enforces mutual
+ * exclusion when invoking @p sspAcquireBus() and @p sspReleaseBus().
+ * @note The internally used synchronization mechanism is a @p Semaphore.
+ */
+#if !defined(LPC214x_SSP_USE_MUTEX) || defined(__DOXYGEN__)
+#define LPC214x_SSP_USE_MUTEX TRUE
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+ void ssp_init(void);
+ void ssp_setup(int cpsr, int cr0, int cr1);
+ void sspAcquireBus(void);
+ void sspReleaseBus(void);
+ void sspRW(uint8_t *in, uint8_t *out, size_t n);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LPC214x_SSP_H_*/
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/LPC214x/pal_lld.c b/os/ports/GCC/ARM7/LPC214x/pal_lld.c
new file mode 100644
index 000000000..e197a39fc
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/pal_lld.c
@@ -0,0 +1,89 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-LPC214x/pal_lld.c
+ * @brief LPC214x FIO low level driver code
+ * @addtogroup LPC214x_PAL
+ * @{
+ */
+
+#include <ch.h>
+#include <pal.h>
+
+/**
+ * @brief LPC214x I/O ports configuration.
+ * @details FIO units and PINSEL registers initialization.
+ *
+ * @param[in] config the LPC214x ports configuration
+ */
+void _pal_lld_init(const LPC214xFIOConfig *config) {
+
+ /* Enables the access through the fast registers.*/
+ SCS = 3;
+
+ /* I/O pads initial assignment, device drivers may change this setup at a
+ * later time.*/
+ PINSEL0 = config->pinsel0;
+ PINSEL1 = config->pinsel1;
+ PINSEL2 = config->pinsel2;
+
+ /* I/O pads direction initial setting.*/
+ FIO0Base->FIO_MASK = 0;
+ FIO0Base->FIO_PIN = config->P0Data.pin;
+ FIO0Base->FIO_DIR = config->P0Data.dir;
+ FIO1Base->FIO_MASK = 0;
+ FIO1Base->FIO_PIN = config->P1Data.pin;
+ FIO1Base->FIO_DIR = config->P1Data.dir;
+}
+
+/**
+ * @brief Pads mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
+ * state.
+ * @note This function does not alter the @p PINSELx registers. Alternate
+ * functions setup must be handled by device-specific code.
+ */
+void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ uint_fast8_t mode) {
+
+ switch (mode) {
+ case PAL_MODE_RESET:
+ case PAL_MODE_INPUT:
+ port->FIO_DIR &= ~mask;
+ break;
+ case PAL_MODE_UNCONNECTED:
+ port->FIO_PIN |= mask;
+ case PAL_MODE_OUTPUT_PUSHPULL:
+ port->FIO_DIR |= mask;
+ break;
+ }
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/LPC214x/pal_lld.h b/os/ports/GCC/ARM7/LPC214x/pal_lld.h
new file mode 100644
index 000000000..143fc103f
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/pal_lld.h
@@ -0,0 +1,252 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-LPC214x/pal_lld.h
+ * @brief LPC214x FIO low level driver header
+ * @addtogroup LPC214x_PAL
+ * @{
+ */
+
+#ifndef _PAL_LLD_H_
+#define _PAL_LLD_H_
+
+#include "lpc214x.h"
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+#undef PAL_MODE_INPUT_PULLUP
+#undef PAL_MODE_INPUT_PULLDOWN
+#undef PAL_MODE_OUTPUT_OPENDRAIN
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @brief FIO port setup info.
+ */
+typedef struct {
+ /** Initial value for FIO_PIN register.*/
+ uint32_t pin;
+ /** Initial value for FIO_DIR register.*/
+ uint32_t dir;
+} lpc214x_fio_setup_t;
+
+/**
+ * @brief LPC214x FIO static initializer.
+ * @details An instance of this structure must be passed to @p palInit() at
+ * system startup time in order to initialized the digital I/O
+ * subsystem. This represents only the initial setup, specific pads
+ * or whole ports can be reprogrammed at later time.
+ */
+typedef struct {
+ /** @brief PINSEL0 initial value.*/
+ uint32_t pinsel0;
+ /** @brief PINSEL1 initial value.*/
+ uint32_t pinsel1;
+ /** @brief PINSEL2 initial value.*/
+ uint32_t pinsel2;
+ /** @brief Port 0 setup data.*/
+ lpc214x_fio_setup_t P0Data;
+ /** @brief Port 1 setup data.*/
+ lpc214x_fio_setup_t P1Data;
+} LPC214xFIOConfig;
+
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 32
+
+/**
+ * @brief Digital I/O port sized unsigned type.
+ */
+typedef uint32_t ioportmask_t;
+
+/**
+ * @brief Port Identifier.
+ */
+typedef FIO * ioportid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/*===========================================================================*/
+
+/**
+ * @brief FIO port 0 identifier.
+ */
+#define IOPORT_A FIO0Base
+
+/**
+ * @brief FIO port 1 identifier.
+ */
+#define IOPORT_B FIO1Base
+
+/*===========================================================================*/
+/* Implementation, some of the following macros could be implemented as */
+/* functions, please put them in a file named ioports_lld.c if so. */
+/*===========================================================================*/
+
+/**
+ * @brief FIO subsystem initialization.
+ * @details Enables the access through the fast registers.
+ */
+#define pal_lld_init(config) _pal_lld_init(config)
+
+/**
+ * @brief Reads an I/O port.
+ * @details This function is implemented by reading the FIO PIN register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @return the port bits
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_readport(port) ((port)->FIO_PIN)
+
+/**
+ * @brief Reads the output latch.
+ * @details This function is implemented by reading the FIO SET register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @return The latched logical states.
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_readlatch(port) ((port)->FIO_SET)
+
+/**
+ * @brief Writes a bits mask on a I/O port.
+ * @details This function is implemented by writing the FIO PIN register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @param[in] bits the bits to be written on the specified port
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_writeport(port, bits) ((port)->FIO_PIN = (bits))
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @details This function is implemented by writing the FIO SET register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @param[in] bits the bits to be ORed on the specified port
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_setport(port, bits) ((port)->FIO_SET = (bits))
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @details This function is implemented by writing the FIO CLR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port the port identifier
+ * @param[in] bits the bits to be cleared on the specified port
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_clearport(port, bits) ((port)->FIO_CLR = (bits))
+
+/**
+ * @brief Writes a value on an I/O bus.
+ * @details This function is implemented by writing the FIO PIN and MASK
+ * registers, the implementation is not atomic because the multiple
+ * accesses.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] offset the group bit offset within the port
+ * @param[in] bits the bits to be written. Values exceeding the group width
+ * are masked.
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_writegroup(port, mask, offset, bits) { \
+ (port)->FIO_MASK = (mask) << (offset); \
+ (port)->FIO_PIN = (bits) << (offset); \
+ (port)->FIO_MASK = 0; \
+}
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
+ * state.
+ * @note This function does not alter the @p PINSELx registers. Alternate
+ * functions setup must be handled by device-specific code.
+ */
+#define pal_lld_setgroupmode(port, mask, mode) \
+ _pal_lld_setgroupmode(port, mask, mode)
+
+/**
+ * @brief Writes a logical state on an output pad.
+ *
+ * @param[in] port the port identifier
+ * @param[in] pad the pad number within the port
+ * @param[out] bit the logical value, the value must be @p 0 or @p 1
+ *
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ */
+#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
+
+/**
+ * @brief FIO port setup.
+ * @details This function programs the pins direction within a port.
+ */
+#define pal_lld_lpc214x_set_direction(port, dir) { \
+ (port)->FIO_DIR = (dir); \
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _pal_lld_init(const LPC214xFIOConfig *config);
+ void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ uint_fast8_t mode);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PAL_LLD_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/LPC214x/port.dox b/os/ports/GCC/ARM7/LPC214x/port.dox
new file mode 100644
index 000000000..e46ac4328
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/port.dox
@@ -0,0 +1,83 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @defgroup LPC214x LPC214x Support
+ * @brief LPC214x specific support.
+ * @details The LPC214x support includes:
+ * - VIC support code.
+ * - I/O ports driver.
+ * - Buffered, interrupt driven, serial driver.
+ * - SSP driver.
+ * - A MMC/SD demo driver.
+ * - A timer driven buzzer demo driver.
+ * - A minimal demo, useful as project template.
+ * - A demo supporting the kernel test suite.
+ * - A C++ demo supporting the kernel test suite.
+ * .
+ * @ingroup ARM7
+ */
+
+/**
+ * @defgroup LPC214x_VIC VIC Support
+ * @brief VIC peripheral support.
+ *
+ * @ingroup LPC214x
+ */
+
+/**
+ * @defgroup LPC214x_PAL I/O Ports Support
+ * @brief I/O Ports peripherals support.
+ * @details This module supports the LPC214x FIO controller. The controller
+ * supports the following features (see @ref PAL):
+ * - 32 bits wide ports.
+ * - Atomic set/reset functions.
+ * - Output latched regardless of the pad setting.
+ * - Direct read of input pads regardless of the pad setting.
+ * .
+ * <h2>Supported Setup Modes</h2>
+ * - @p PAL_MODE_RESET.
+ * - @p PAL_MODE_UNCONNECTED.
+ * - @p PAL_MODE_INPUT.
+ * - @p PAL_MODE_OUTPUT_PUSHPULL.
+ * .
+ * Any attempt to setup an invalid mode is ignored.
+ *
+ * <h2>Suboptimal Behavior</h2>
+ * - Pad/port toggling operations are not atomic.
+ * - Pad/group mode setup is not atomic.
+ * .
+ * @ingroup LPC214x
+ */
+
+/**
+ * @defgroup LPC214x_SERIAL UART Support
+ * @brief UART peripherals support.
+ * @details The serial driver supports the LPC214x UART peripherals.
+ *
+ * @ingroup LPC214x
+ */
+
+/**
+ * @defgroup LPC214x_SSP SSP Support
+ * @brief SSP peripheral support.
+ * @details This SPI driver supports the LPC214x SSP peripheral.
+ *
+ * @ingroup LPC214x
+ */
diff --git a/os/ports/GCC/ARM7/LPC214x/vectors.s b/os/ports/GCC/ARM7/LPC214x/vectors.s
new file mode 100644
index 000000000..016a2f1de
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/vectors.s
@@ -0,0 +1,71 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+.section vectors
+.code 32
+.balign 4
+/*
+ * System entry points.
+ */
+_start:
+ ldr pc, _reset
+ ldr pc, _undefined
+ ldr pc, _swi
+ ldr pc, _prefetch
+ ldr pc, _abort
+ nop
+ ldr pc, [pc,#-0xFF0] /* VIC - IRQ Vector Register */
+ ldr pc, _fiq
+
+_reset:
+ .word ResetHandler /* In crt0.s */
+_undefined:
+ .word UndHandler
+_swi:
+ .word SwiHandler
+_prefetch:
+ .word PrefetchHandler
+_abort:
+ .word AbortHandler
+_fiq:
+ .word FiqHandler
+ .word 0
+ .word 0
+
+/*
+ * Default exceptions handlers. The handlers are declared weak in order to be
+ * replaced by the real handling code. Everything is defaulted to an infinite
+ * loop.
+ */
+.weak UndHandler
+UndHandler:
+
+.weak SwiHandler
+SwiHandler:
+
+.weak PrefetchHandler
+PrefetchHandler:
+
+.weak AbortHandler
+AbortHandler:
+
+.weak FiqHandler
+FiqHandler:
+
+.loop: b .loop
diff --git a/os/ports/GCC/ARM7/LPC214x/vic.c b/os/ports/GCC/ARM7/LPC214x/vic.c
new file mode 100644
index 000000000..88e9814bb
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/vic.c
@@ -0,0 +1,63 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-LPC214x/vic.c
+ * @brief LPC214x VIC peripheral support code.
+ * @addtogroup LPC214x_VIC
+ * @{
+ */
+
+#include <ch.h>
+
+#include "lpc214x.h"
+
+/**
+ * @brief VIC Initialization.
+ * @note Better reset everything in the VIC, it is a HUGE source of trouble.
+ */
+void vic_init(void) {
+ int i;
+
+ VIC *vic = VICBase;
+ vic->VIC_IntSelect = 0; /* All sources assigned to IRQ. */
+ vic->VIC_SoftIntClear = ALLINTMASK; /* No interrupts enforced */
+ vic->VIC_IntEnClear = ALLINTMASK; /* All sources disabled. */
+ for (i = 0; i < 16; i++) {
+ vic->VIC_VectCntls[i] = 0;
+ vic->VIC_VectAddrs[i] = 0;
+ vic->VIC_VectAddr = 0;
+ }
+}
+
+/**
+ * @brief Initializes a VIC vector.
+ * @details Set a vector for an interrupt source and enables it.
+ * @param[in] handler the pointer to the IRQ service routine
+ * @param[in] vector the vector number
+ * @param[in] source the IRQ source to be associated to the vector
+ */
+void SetVICVector(void *handler, int vector, int source) {
+
+ VIC *vicp = VICBase;
+ vicp->VIC_VectAddrs[vector] = (IOREG32)handler;
+ vicp->VIC_VectCntls[vector] = (IOREG32)(source | 0x20);
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/LPC214x/vic.h b/os/ports/GCC/ARM7/LPC214x/vic.h
new file mode 100644
index 000000000..b4b88948c
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/vic.h
@@ -0,0 +1,41 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7-LPC214x/vic.h
+ * @brief LPC214x VIC peripheral support code.
+ * @addtogroup LPC214x_VIC
+ * @{
+ */
+
+#ifndef _VIC_H_
+#define _VIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void vic_init(void);
+ void SetVICVector(void *handler, int vector, int source);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VIC_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/LPC214x/wfi.h b/os/ports/GCC/ARM7/LPC214x/wfi.h
new file mode 100644
index 000000000..bd3b5e7cd
--- /dev/null
+++ b/os/ports/GCC/ARM7/LPC214x/wfi.h
@@ -0,0 +1,35 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _WFI_H_
+#define _WFI_H_
+
+#include "lpc214x.h"
+
+#ifndef port_wait_for_interrupt
+#if ENABLE_WFI_IDLE != 0
+#define port_wait_for_interrupt() { \
+ PCON = 1; \
+}
+#else
+#define port_wait_for_interrupt()
+#endif
+#endif
+
+#endif /* _WFI_H_ */
diff --git a/os/ports/GCC/ARM7/chcore.c b/os/ports/GCC/ARM7/chcore.c
new file mode 100644
index 000000000..d0e0071bf
--- /dev/null
+++ b/os/ports/GCC/ARM7/chcore.c
@@ -0,0 +1,42 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7/chcore.c
+ * @brief ARM7 architecture port code.
+ * @addtogroup ARM7_CORE
+ * @{
+ */
+
+#include <ch.h>
+
+/**
+ * Halts the system.
+ */
+/** @cond never */
+__attribute__((weak))
+/** @endcond */
+void port_halt(void) {
+
+ port_disable();
+ while (TRUE) {
+ }
+}
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/chcore.h b/os/ports/GCC/ARM7/chcore.h
new file mode 100644
index 000000000..541207eef
--- /dev/null
+++ b/os/ports/GCC/ARM7/chcore.h
@@ -0,0 +1,331 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7/chcore.h
+ * @brief ARM7 architecture port macros and structures.
+ * @addtogroup ARM7_CORE
+ * @{
+ */
+
+#ifndef _CHCORE_H_
+#define _CHCORE_H_
+
+/**
+ * If enabled allows the idle thread to enter a low power mode.
+ */
+#ifndef ENABLE_WFI_IDLE
+#define ENABLE_WFI_IDLE 0
+#endif
+#include <wfi.h>
+
+/**
+ * Macro defining the ARM7 architecture.
+ */
+#define CH_ARCHITECTURE_ARM7
+
+/**
+ * Name of the implemented architecture.
+ */
+#define CH_ARCHITECTURE_NAME "ARM7TDMI"
+
+/**
+ * 32 bit stack alignment.
+ */
+typedef uint32_t stkalign_t;
+
+/**
+ * Generic ARM register.
+ */
+typedef void *regarm_t;
+
+/** @cond never */
+/**
+ * This structure represents the stack frame saved during a preemption-capable
+ * interrupt handler.
+ */
+struct extctx {
+ regarm_t spsr_irq;
+ regarm_t lr_irq;
+ regarm_t r0;
+ regarm_t r1;
+ regarm_t r2;
+ regarm_t r3;
+ regarm_t r12;
+ regarm_t lr_usr;
+};
+/** @endcond */
+
+/** @cond never */
+/**
+ * This structure represents the inner stack frame during a context switching.
+ */
+struct intctx {
+ regarm_t r4;
+ regarm_t r5;
+ regarm_t r6;
+#ifndef CH_CURRP_REGISTER_CACHE
+ regarm_t r7;
+#endif
+ regarm_t r8;
+ regarm_t r9;
+ regarm_t r10;
+ regarm_t r11;
+ regarm_t lr;
+};
+/** @endcond */
+
+/** @cond never */
+/**
+ * In the ARM7 port this structure contains just the copy of the user mode
+ * stack pointer.
+ */
+struct context {
+ struct intctx *r13;
+};
+/** @endcond */
+
+/**
+ * Platform dependent part of the @p chThdInit() API.
+ */
+#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
+ tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
+ wsize - \
+ sizeof(struct intctx)); \
+ tp->p_ctx.r13->r4 = pf; \
+ tp->p_ctx.r13->r5 = arg; \
+ tp->p_ctx.r13->lr = _port_thread_start; \
+}
+
+/**
+ * Stack size for the system idle thread.
+ */
+#ifndef IDLE_THREAD_STACK_SIZE
+#define IDLE_THREAD_STACK_SIZE 0
+#endif
+
+/**
+ * Per-thread stack overhead for interrupts servicing, it is used in the
+ * calculation of the correct working area size.
+ * In this port 0x10 is a safe value, it can be reduced after careful generated
+ * code analysis.
+ */
+#ifndef INT_REQUIRED_STACK
+#define INT_REQUIRED_STACK 0x10
+#endif
+
+/**
+ * Enforces a correct alignment for a stack area size value.
+ */
+#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
+
+/**
+ * Computes the thread working area global size.
+ */
+#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
+ sizeof(struct intctx) + \
+ sizeof(struct extctx) + \
+ (n) + (INT_REQUIRED_STACK))
+
+/**
+ * Macro used to allocate a thread working area aligned as both position and
+ * size.
+ */
+#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)];
+
+/**
+ * IRQ prologue code, inserted at the start of all IRQ handlers enabled to
+ * invoke system APIs.
+ * @note This macro has a different implementation depending if compiled in
+ * ARM or THUMB mode.
+ * @note The THUMB implementation starts with ARM code because interrupt
+ * vectors are always invoked in ARM mode regardless the bit 0
+ * value. The switch in THUMB mode is done in the function prologue so
+ * it is transparent to the user code.
+ */
+#ifdef THUMB
+#define PORT_IRQ_PROLOGUE() { \
+ asm volatile (".code 32 \n\t" \
+ "stmfd sp!, {r0-r3, r12, lr} \n\t" \
+ "add r0, pc, #1 \n\t" \
+ "bx r0 \n\t" \
+ ".code 16"); \
+}
+#else /* !THUMB */
+#define PORT_IRQ_PROLOGUE() { \
+ asm volatile ("stmfd sp!, {r0-r3, r12, lr}"); \
+}
+#endif /* !THUMB */
+
+/**
+ * IRQ epilogue code, inserted at the end of all IRQ handlers enabled to
+ * invoke system APIs.
+ * @note This macro has a different implementation depending if compiled in
+ * ARM or THUMB mode.
+ */
+#ifdef THUMB
+#define PORT_IRQ_EPILOGUE() { \
+ asm volatile ("ldr r0, =_port_irq_common \n\t" \
+ "bx r0"); \
+}
+#else /* !THUMB */
+#define PORT_IRQ_EPILOGUE() { \
+ asm volatile ("b _port_irq_common"); \
+}
+#endif /* !THUMB */
+
+/**
+ * IRQ handler function declaration.
+ */
+#define PORT_IRQ_HANDLER(id) __attribute__((naked)) void id(void)
+
+/**
+ * This function is empty in this port.
+ */
+#define port_init()
+
+/**
+ * Disables the IRQ sources and keeps the FIQ sources enabled.
+ */
+#ifdef THUMB
+//#define port_lock() _port_lock_thumb()
+#define port_lock() { \
+ asm volatile ("bl _port_lock_thumb" : : : "r3", "lr"); \
+}
+#else /* !THUMB */
+#define port_lock() asm volatile ("msr CPSR_c, #0x9F")
+#endif /* !THUMB */
+
+/**
+ * Enables both the IRQ and FIQ sources.
+ */
+#ifdef THUMB
+//#define port_unlock() _port_unlock_thumb()
+#define port_unlock() { \
+ asm volatile ("bl _port_unlock_thumb" : : : "r3", "lr"); \
+}
+#else /* !THUMB */
+#define port_unlock() asm volatile ("msr CPSR_c, #0x1F")
+#endif /* !THUMB */
+
+/**
+ * This function is empty in this port.
+ */
+#define port_lock_from_isr()
+
+/**
+ * This function is empty in this port.
+ */
+#define port_unlock_from_isr()
+
+/**
+ * Disables both the IRQ and FIQ sources.
+ * @note Implements a workaround for spurious interrupts taken from the NXP
+ * LPC214x datasheet.
+ */
+#ifdef THUMB
+//#define port_disable() _port_disable_thumb()
+#define port_disable() { \
+ asm volatile ("bl _port_disable_thumb" : : : "r3", "lr"); \
+}
+#else /* !THUMB */
+#define port_disable() { \
+ asm volatile ("mrs r3, CPSR \n\t" \
+ "orr r3, #0x80 \n\t" \
+ "msr CPSR_c, r3 \n\t" \
+ "orr r3, #0x40 \n\t" \
+ "msr CPSR_c, r3" : : : "r3"); \
+}
+#endif /* !THUMB */
+
+/**
+ * Disables the IRQ sources and enables the FIQ sources.
+ */
+#ifdef THUMB
+#define port_suspend() { \
+ asm volatile ("bl _port_suspend_thumb" : : : "r3", "lr"); \
+}
+#else /* !THUMB */
+#define port_suspend() asm volatile ("msr CPSR_c, #0x9F")
+#endif /* !THUMB */
+
+/**
+ * Enables both the IRQ and FIQ sources.
+ */
+#ifdef THUMB
+#define port_enable() { \
+ asm volatile ("bl _port_enable_thumb" : : : "r3", "lr"); \
+}
+#else /* !THUMB */
+#define port_enable() asm volatile ("msr CPSR_c, #0x1F")
+#endif /* !THUMB */
+
+/**
+ * Performs a context switch between two threads.
+ * @param otp the thread to be switched out
+ * @param ntp the thread to be switched in
+ */
+#ifdef THUMB
+#if CH_DBG_ENABLE_STACK_CHECK
+#define port_switch(otp, ntp) { \
+ register Thread *_otp asm ("r0") = (otp); \
+ register Thread *_ntp asm ("r1") = (ntp); \
+ register char *sp asm ("sp"); \
+ if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp) \
+ asm volatile ("mov r0, #0 \n\t" \
+ "ldr r1, =chDbgPanic \n\t" \
+ "bx r1"); \
+ _port_switch_thumb(_otp, _ntp); \
+}
+#else /* !CH_DBG_ENABLE_STACK_CHECK */
+#define port_switch(otp, ntp) _port_switch_thumb(otp, ntp)
+#endif /* !CH_DBG_ENABLE_STACK_CHECK */
+#else /* !THUMB */
+#if CH_DBG_ENABLE_STACK_CHECK
+#define port_switch(otp, ntp) { \
+ register Thread *_otp asm ("r0") = (otp); \
+ register Thread *_ntp asm ("r1") = (ntp); \
+ register char *sp asm ("sp"); \
+ if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp) \
+ asm volatile ("mov r0, #0 \n\t" \
+ "b chDbgPanic"); \
+ _port_switch_arm(_otp, _ntp); \
+}
+#else /* !CH_DBG_ENABLE_STACK_CHECK */
+#define port_switch(otp, ntp) _port_switch_arm(otp, ntp)
+#endif /* !CH_DBG_ENABLE_STACK_CHECK */
+#endif /* !THUMB */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void port_halt(void);
+#ifdef THUMB
+ void _port_switch_thumb(Thread *otp, Thread *ntp);
+#else /* !THUMB */
+ void _port_switch_arm(Thread *otp, Thread *ntp);
+#endif /* !THUMB */
+ void _port_thread_start(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CHCORE_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/chcore.lst b/os/ports/GCC/ARM7/chcore.lst
new file mode 100644
index 000000000..db8b7a12c
--- /dev/null
+++ b/os/ports/GCC/ARM7/chcore.lst
@@ -0,0 +1,48 @@
+ 1 .file "chcore.c"
+ 2 __SREG__ = 0x3f
+ 3 __SP_H__ = 0x3e
+ 4 __SP_L__ = 0x3d
+ 5 __CCP__ = 0x34
+ 6 __tmp_reg__ = 0
+ 7 __zero_reg__ = 1
+ 8 .global __do_copy_data
+ 9 .global __do_clear_bss
+ 17 .Ltext0:
+ 18 .weak port_halt
+ 20 port_halt:
+ 21 .LFB7:
+ 22 .LM1:
+ 23 ???? 3F92 push r3
+ 24 /* prologue: function */
+ 25 /* frame size = 0 */
+ 26 .LM2:
+ 27 /* #APP */
+ 28 ; 37 "../../os/ports/GCC/ARM7/chcore.c" 1
+ 29 mrs r3, CPSR
+ 30 orr r3, #0x80
+ 31 msr CPSR_c, r3
+ 32 orr r3, #0x40
+ 33 msr CPSR_c, r3
+ 34 ; 0 "" 2
+ 35 /* #NOAPP */
+ 36 .L2:
+ 37 ???? 00C0 rjmp .L2
+ 38 .LFE7:
+ 64 .Letext0:
+DEFINED SYMBOLS
+ *ABS*:00000000 chcore.c
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:2 *ABS*:0000003f __SREG__
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:3 *ABS*:0000003e __SP_H__
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:4 *ABS*:0000003d __SP_L__
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:5 *ABS*:00000034 __CCP__
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:6 *ABS*:00000000 __tmp_reg__
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:7 *ABS*:00000001 __zero_reg__
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:20 .text:00000000 port_halt
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:39 .text:00000000 L0
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:265 .debug_line:00000000 L0
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:265 .debug_line:0000001d L0
+C:\DOCUME~1\Giovanni\IMPOST~1\Temp/ccjonuJz.s:265 .debug_line:0000001d L0
+
+UNDEFINED SYMBOLS
+__do_copy_data
+__do_clear_bss
diff --git a/os/ports/GCC/ARM7/chcoreasm.s b/os/ports/GCC/ARM7/chcoreasm.s
new file mode 100644
index 000000000..932d39c04
--- /dev/null
+++ b/os/ports/GCC/ARM7/chcoreasm.s
@@ -0,0 +1,234 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7/chcoreasm.s
+ * @brief ARM7 architecture port low level code.
+ * @addtogroup ARM7_CORE
+ * @{
+ */
+/** @cond never */
+
+#include <chconf.h>
+
+.set MODE_USR, 0x10
+.set MODE_FIQ, 0x11
+.set MODE_IRQ, 0x12
+.set MODE_SVC, 0x13
+.set MODE_ABT, 0x17
+.set MODE_UND, 0x1B
+.set MODE_SYS, 0x1F
+
+.equ I_BIT, 0x80
+.equ F_BIT, 0x40
+
+.text
+
+/*
+ * Interrupt enable/disable functions, only present if there is THUMB code in
+ * the system because those are inlined in ARM code.
+ */
+#ifdef THUMB_PRESENT
+.balign 16
+.code 16
+.thumb_func
+.global _port_disable_thumb
+_port_disable_thumb:
+ mov r3, pc
+ bx r3
+.code 32
+ mrs r3, CPSR
+ orr r3, #I_BIT
+ msr CPSR_c, r3
+ orr r3, #F_BIT
+ msr CPSR_c, r3
+ bx lr
+
+.balign 16
+.code 16
+.thumb_func
+.global _port_suspend_thumb
+_port_suspend_thumb:
+.thumb_func
+.global _port_lock_thumb
+_port_lock_thumb:
+ mov r3, pc
+ bx r3
+.code 32
+ msr CPSR_c, #MODE_SYS | I_BIT
+ bx lr
+
+.balign 16
+.code 16
+.thumb_func
+.global _port_enable_thumb
+_port_enable_thumb:
+.thumb_func
+.global _port_unlock_thumb
+_port_unlock_thumb:
+ mov r3, pc
+ bx r3
+.code 32
+ msr CPSR_c, #MODE_SYS
+ bx lr
+
+#endif
+
+.balign 16
+#ifdef THUMB_PRESENT
+.code 16
+.thumb_func
+.global _port_switch_thumb
+_port_switch_thumb:
+ mov r2, pc
+ bx r2
+ // Jumps into _port_switch_arm in ARM mode
+#endif
+.code 32
+.global _port_switch_arm
+_port_switch_arm:
+#ifdef CH_CURRP_REGISTER_CACHE
+ stmfd sp!, {r4, r5, r6, r8, r9, r10, r11, lr}
+ str sp, [r0, #16]
+ ldr sp, [r1, #16]
+#ifdef THUMB_PRESENT
+ ldmfd sp!, {r4, r5, r6, r8, r9, r10, r11, lr}
+ bx lr
+#else /* !THUMB_PRESENT */
+ ldmfd sp!, {r4, r5, r6, r8, r9, r10, r11, pc}
+#endif /* !THUMB_PRESENT */
+#else /* !CH_CURRP_REGISTER_CACHE */
+ stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+ str sp, [r0, #16]
+ ldr sp, [r1, #16]
+#ifdef THUMB_PRESENT
+ ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+ bx lr
+#else /* !THUMB_PRESENT */
+ ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
+#endif /* !THUMB_PRESENT */
+#endif /* !CH_CURRP_REGISTER_CACHE */
+
+/*
+ * Common exit point for all IRQ routines, it performs the rescheduling if
+ * required.
+ * System stack frame structure after a context switch in the
+ * interrupt handler:
+ *
+ * High +------------+
+ * | LR_USR | -+
+ * | R12 | |
+ * | R3 | |
+ * | R2 | | External context: IRQ handler frame
+ * | R1 | |
+ * | R0 | |
+ * | PC | | (user code return address)
+ * | PSR_USR | -+ (user code status)
+ * | .... | <- mk_DoRescheduleI() stack frame, optimize it for space
+ * | LR | -+ (system code return address)
+ * | R11 | |
+ * | R10 | |
+ * | R9 | |
+ * | R8 | | Internal context: mk_SwitchI() frame
+ * | (R7) | | (optional, see CH_CURRP_REGISTER_CACHE)
+ * | R6 | |
+ * | R5 | |
+ * SP-> | R4 | -+
+ * Low +------------+
+ */
+.balign 16
+#ifdef THUMB_NO_INTERWORKING
+.code 16
+.thumb_func
+.globl _port_irq_common
+_port_irq_common:
+ bl chSchRescRequiredI
+ mov lr, pc
+ bx lr
+.code 32
+#else /* !THUMB_NO_INTERWORKING */
+.code 32
+.globl _port_irq_common
+_port_irq_common:
+ bl chSchRescRequiredI
+#endif /* !THUMB_NO_INTERWORKING */
+ cmp r0, #0 // Simply returns if a
+ ldmeqfd sp!, {r0-r3, r12, lr} // reschedule is not
+ subeqs pc, lr, #4 // required.
+
+ // Saves the IRQ mode registers in the system stack.
+ ldmfd sp!, {r0-r3, r12, lr} // IRQ stack now empty.
+ msr CPSR_c, #MODE_SYS | I_BIT
+ stmfd sp!, {r0-r3, r12, lr} // Registers on System Stack.
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ mrs r0, SPSR
+ mov r1, lr
+ msr CPSR_c, #MODE_SYS | I_BIT
+ stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ.
+
+ // Context switch.
+#ifdef THUMB_NO_INTERWORKING
+ add r0, pc, #1
+ bx r0
+.code 16
+ bl chSchDoRescheduleI
+ mov lr, pc
+ bx lr
+.code 32
+#else /* !THUMB_NO_INTERWORKING */
+ bl chSchDoRescheduleI
+#endif /* !THUMB_NO_INTERWORKING */
+
+ // Re-establish the IRQ conditions again.
+ ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ.
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ msr SPSR_fsxc, r0
+ mov lr, r1
+ msr CPSR_c, #MODE_SYS | I_BIT
+ ldmfd sp!, {r0-r3, r12, lr}
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ subs pc, lr, #4
+
+/*
+ * Threads trampoline code.
+ * NOTE: The threads always start in ARM mode then switch to the thread-function mode.
+ */
+.balign 16
+.code 32
+.globl _port_thread_start
+_port_thread_start:
+ msr CPSR_c, #MODE_SYS
+#ifndef THUMB_NO_INTERWORKING
+ mov r0, r5
+ mov lr, pc
+ bx r4
+ bl chThdExit
+#else /* !THUMB_NO_INTERWORKING */
+ add r0, pc, #1
+ bx r0
+.code 16
+ mov r0, r5
+ bl jmpr4
+ bl chThdExit
+jmpr4:
+ bx r4
+#endif /* !THUMB_NO_INTERWORKING */
+
+/** @endcond */
+/** @} */
diff --git a/os/ports/GCC/ARM7/chtypes.h b/os/ports/GCC/ARM7/chtypes.h
new file mode 100644
index 000000000..570c719da
--- /dev/null
+++ b/os/ports/GCC/ARM7/chtypes.h
@@ -0,0 +1,56 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7/chtypes.h
+ * @brief ARM7 architecture port system types.
+ * @addtogroup ARM7_CORE
+ * @{
+ */
+
+#ifndef _CHTYPES_H_
+#define _CHTYPES_H_
+
+#define __need_NULL
+#define __need_size_t
+#define __need_ptrdiff_t
+#include <stddef.h>
+
+#if !defined(_STDINT_H) && !defined(__STDINT_H_)
+#include <stdint.h>
+#endif
+
+typedef int32_t bool_t; /**< Fast boolean type. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Event Id. */
+typedef uint32_t eventmask_t; /**< Events mask. */
+typedef uint32_t systime_t; /**< System time. */
+typedef int32_t cnt_t; /**< Resources counter. */
+
+#define INLINE inline
+#define PACK_STRUCT_STRUCT __attribute__((packed))
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_END
+
+#endif /* _CHTYPES_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARM7/crt0.lst b/os/ports/GCC/ARM7/crt0.lst
new file mode 100644
index 000000000..eed22b391
--- /dev/null
+++ b/os/ports/GCC/ARM7/crt0.lst
@@ -0,0 +1,218 @@
+GAS LISTING /cygdrive/c/DOCUME~1/Giovanni/IMPOST~1/Temp/ccgRWKd6.s page 1
+
+
+ 1 # 1 "../../os/ports/GCC/ARM7/crt0.s"
+ 2 # 1 "<built-in>"
+ 1 /*
+ 0
+ 0
+ 2 ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+ 3
+ 4 This file is part of ChibiOS/RT.
+ 5
+ 6 ChibiOS/RT is free software; you can redistribute it and/or modify
+ 7 it under the terms of the GNU General Public License as published by
+ 8 the Free Software Foundation; either version 3 of the License, or
+ 9 (at your option) any later version.
+ 10
+ 11 ChibiOS/RT is distributed in the hope that it will be useful,
+ 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 14 GNU General Public License for more details.
+ 15
+ 16 You should have received a copy of the GNU General Public License
+ 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
+ 18 */
+ 19
+ 20 /**
+ 21 * @file ports/ARM7/crt0.s
+ 22 * @brief Generic ARM7 startup file for ChibiOS/RT.
+ 23 * @addtogroup ARM7_CORE
+ 24 * @{
+ 25 */
+ 26 /** @cond never */
+ 27
+ 28 .set MODE_USR, 0x10
+ 29 .set MODE_FIQ, 0x11
+ 30 .set MODE_IRQ, 0x12
+ 31 .set MODE_SVC, 0x13
+ 32 .set MODE_ABT, 0x17
+ 33 .set MODE_UND, 0x1B
+ 34 .set MODE_SYS, 0x1F
+ 35
+ 36 .equ I_BIT, 0x80
+ 37 .equ F_BIT, 0x40
+ 38
+ 39 .text
+ 40 .code 32
+ 41 .balign 4
+ 42
+ 43 /*
+ 44 * Reset handler.
+ 45 */
+ 46 .global ResetHandler
+ 47 ResetHandler:
+ 48 /*
+ 49 * Stack pointers initialization.
+ 50 */
+ 51 ldr r0, =__ram_end__
+ 52 /* Undefined */
+ 53 msr CPSR_c, #MODE_UND | I_BIT | F_BIT
+ GAS LISTING /cygdrive/c/DOCUME~1/Giovanni/IMPOST~1/Temp/ccgRWKd6.s page 2
+
+
+ 54 ???? 1040 0000 mov sp, r0
+ 55 ldr r1, =__und_stack_size__
+ 56 ???? 0080 sub r0, r0, r1
+ 57 /* Abort */
+ 58 msr CPSR_c, #MODE_ABT | I_BIT | F_BIT
+ 59 ???? 1040 0000 mov sp, r0
+ 60 ldr r1, =__abt_stack_size__
+ 61 ???? 0080 sub r0, r0, r1
+ 62 /* FIQ */
+ 63 msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT
+ 64 ???? 1040 0000 mov sp, r0
+ 65 ldr r1, =__fiq_stack_size__
+ 66 ???? 0080 sub r0, r0, r1
+ 67 /* IRQ */
+ 68 msr CPSR_c, #MODE_IRQ | I_BIT | F_BIT
+ 69 ???? 1040 0000 mov sp, r0
+ 70 ldr r1, =__irq_stack_size__
+ 71 ???? 0080 sub r0, r0, r1
+ 72 /* Supervisor */
+ 73 msr CPSR_c, #MODE_SVC | I_BIT | F_BIT
+ 74 ???? 1040 0000 mov sp, r0
+ 75 ldr r1, =__svc_stack_size__
+ 76 ???? 0080 sub r0, r0, r1
+ 77 /* System */
+ 78 msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
+ 79 ???? 1040 0000 mov sp, r0
+ 80 // ldr r1, =__sys_stack_size__
+ 81 // sub r0, r0, r1
+ 82 /*
+ 83 * Early initialization.
+ 84 */
+ 85 #ifndef THUMB_NO_INTERWORKING
+ 86 bl hwinit0
+ 87 #else
+ 88 add r0, pc, #1
+ 89 bx r0
+ 90 .code 16
+ 91 bl hwinit0
+ 92 mov r0, pc
+ 93 bx r0
+ 94 .code 32
+ 95 #endif
+ 96 /*
+ 97 * Data initialization.
+ 98 * NOTE: It assumes that the DATA size is a multiple of 4.
+ 99 */
+ 100 ldr r1, =_textdata
+ 101 ldr r2, =_data
+ 102 ldr r3, =_edata
+ 103 dataloop:
+ 104 ???? 0392 cmp r2, r3
+ 105 ldrlo r0, [r1], #4
+ 106 strlo r0, [r2], #4
+ 107 blo dataloop
+ 108 /*
+ 109 * BSS initialization.
+ 110 * NOTE: It assumes that the BSS size is a multiple of 4.
+ GAS LISTING /cygdrive/c/DOCUME~1/Giovanni/IMPOST~1/Temp/ccgRWKd6.s page 3
+
+
+ 111 */
+ 112 ???? 0340 mov r0, #0
+ 113 ldr r1, =_bss_start
+ 114 ldr r2, =_bss_end
+ 115 bssloop:
+ 116 ???? 0291 cmp r1, r2
+ 117 strlo r0, [r1], #4
+ 118 blo bssloop
+ 119 /*
+ 120 * Late initialization.
+ 121 */
+ 122 #ifdef THUMB_NO_INTERWORKING
+ 123 add r0, pc, #1
+ 124 bx r0
+ 125 .code 16
+ 126 bl hwinit1
+ 127 mov r0, #0
+ 128 mov r1, r0
+ 129 bl main
+ 130 ldr r1, =MainExitHandler
+ 131 bx r1
+ 132 .code 32
+ 133 #else
+ 134 bl hwinit1
+ 135 ???? 0340 mov r0, #0
+ 136 ???? 0041 mov r1, r0
+ 137 bl main
+ 138 b MainExitHandler
+ 139 #endif
+ 140
+ 141 /*
+ 142 * Default main function exit handler.
+ 143 */
+ 144 .weak MainExitHandler
+ 145 .globl MainExitHandler
+ 146 MainExitHandler:
+ 147
+ 148 .loop: b .loop
+ 149
+ 150 /*
+ 151 * Default early initialization code. It is declared weak in order to be
+ 152 * replaced by the real initialization code.
+ 153 * Early initialization is performed just after reset before BSS and DATA
+ 154 * segments initialization.
+ 155 */
+ 156 #ifdef THUMB_NO_INTERWORKING
+ 157 .thumb_func
+ 158 .code 16
+ 159 #endif
+ 160 .weak hwinit0
+ 161 hwinit0:
+ 162 bx lr
+ 163 .code 32
+ 164
+ 165 /*
+ 166 * Default late initialization code. It is declared weak in order to be
+ 167 * replaced by the real initialization code.
+ GAS LISTING /cygdrive/c/DOCUME~1/Giovanni/IMPOST~1/Temp/ccgRWKd6.s page 4
+
+
+ 168 * Late initialization is performed after BSS and DATA segments initialization
+ 169 * and before invoking the main() function.
+ 170 */
+ 171 #ifdef THUMB_NO_INTERWORKING
+ 172 .thumb_func
+ 173 .code 16
+ 174 #endif
+ 175 .weak hwinit1
+ 176 hwinit1:
+ 177 bx lr
+ 178 .code 32
+ GAS LISTING /cygdrive/c/DOCUME~1/Giovanni/IMPOST~1/Temp/ccgRWKd6.s page 5
+
+
+DEFINED SYMBOLS
+ *ABS*:00000000 ../../os/ports/GCC/ARM7/crt0.s
+../../os/ports/GCC/ARM7/crt0.s:28 *ABS*:00000010 MODE_USR
+../../os/ports/GCC/ARM7/crt0.s:29 *ABS*:00000011 MODE_FIQ
+../../os/ports/GCC/ARM7/crt0.s:30 *ABS*:00000012 MODE_IRQ
+../../os/ports/GCC/ARM7/crt0.s:31 *ABS*:00000013 MODE_SVC
+../../os/ports/GCC/ARM7/crt0.s:32 *ABS*:00000017 MODE_ABT
+../../os/ports/GCC/ARM7/crt0.s:33 *ABS*:0000001b MODE_UND
+../../os/ports/GCC/ARM7/crt0.s:34 *ABS*:0000001f MODE_SYS
+../../os/ports/GCC/ARM7/crt0.s:36 *ABS*:00000080 I_BIT
+../../os/ports/GCC/ARM7/crt0.s:37 *ABS*:00000040 F_BIT
+../../os/ports/GCC/ARM7/crt0.s:47 .text:00000000 ResetHandler
+../../os/ports/GCC/ARM7/crt0.s:103 .text:00000000 dataloop
+../../os/ports/GCC/ARM7/crt0.s:115 .text:00000000 bssloop
+../../os/ports/GCC/ARM7/crt0.s:146 .text:00000000 MainExitHandler
+../../os/ports/GCC/ARM7/crt0.s:148 .text:00000000 .loop
+../../os/ports/GCC/ARM7/crt0.s:161 .text:00000000 hwinit0
+../../os/ports/GCC/ARM7/crt0.s:176 .text:00000000 hwinit1
+
+UNDEFINED SYMBOLS
+sp
diff --git a/os/ports/GCC/ARM7/crt0.s b/os/ports/GCC/ARM7/crt0.s
new file mode 100644
index 000000000..91d07935b
--- /dev/null
+++ b/os/ports/GCC/ARM7/crt0.s
@@ -0,0 +1,181 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ports/ARM7/crt0.s
+ * @brief Generic ARM7 startup file for ChibiOS/RT.
+ * @addtogroup ARM7_CORE
+ * @{
+ */
+/** @cond never */
+
+.set MODE_USR, 0x10
+.set MODE_FIQ, 0x11
+.set MODE_IRQ, 0x12
+.set MODE_SVC, 0x13
+.set MODE_ABT, 0x17
+.set MODE_UND, 0x1B
+.set MODE_SYS, 0x1F
+
+.equ I_BIT, 0x80
+.equ F_BIT, 0x40
+
+.text
+.code 32
+.balign 4
+
+/*
+ * Reset handler.
+ */
+.global ResetHandler
+ResetHandler:
+ /*
+ * Stack pointers initialization.
+ */
+ ldr r0, =__ram_end__
+ /* Undefined */
+ msr CPSR_c, #MODE_UND | I_BIT | F_BIT
+ mov sp, r0
+ ldr r1, =__und_stack_size__
+ sub r0, r0, r1
+ /* Abort */
+ msr CPSR_c, #MODE_ABT | I_BIT | F_BIT
+ mov sp, r0
+ ldr r1, =__abt_stack_size__
+ sub r0, r0, r1
+ /* FIQ */
+ msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT
+ mov sp, r0
+ ldr r1, =__fiq_stack_size__
+ sub r0, r0, r1
+ /* IRQ */
+ msr CPSR_c, #MODE_IRQ | I_BIT | F_BIT
+ mov sp, r0
+ ldr r1, =__irq_stack_size__
+ sub r0, r0, r1
+ /* Supervisor */
+ msr CPSR_c, #MODE_SVC | I_BIT | F_BIT
+ mov sp, r0
+ ldr r1, =__svc_stack_size__
+ sub r0, r0, r1
+ /* System */
+ msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
+ mov sp, r0
+// ldr r1, =__sys_stack_size__
+// sub r0, r0, r1
+ /*
+ * Early initialization.
+ */
+#ifndef THUMB_NO_INTERWORKING
+ bl hwinit0
+#else
+ add r0, pc, #1
+ bx r0
+.code 16
+ bl hwinit0
+ mov r0, pc
+ bx r0
+.code 32
+#endif
+ /*
+ * Data initialization.
+ * NOTE: It assumes that the DATA size is a multiple of 4.
+ */
+ ldr r1, =_textdata
+ ldr r2, =_data
+ ldr r3, =_edata
+dataloop:
+ cmp r2, r3
+ ldrlo r0, [r1], #4
+ strlo r0, [r2], #4
+ blo dataloop
+ /*
+ * BSS initialization.
+ * NOTE: It assumes that the BSS size is a multiple of 4.
+ */
+ mov r0, #0
+ ldr r1, =_bss_start
+ ldr r2, =_bss_end
+bssloop:
+ cmp r1, r2
+ strlo r0, [r1], #4
+ blo bssloop
+ /*
+ * Late initialization.
+ */
+#ifdef THUMB_NO_INTERWORKING
+ add r0, pc, #1
+ bx r0
+.code 16
+ bl hwinit1
+ mov r0, #0
+ mov r1, r0
+ bl main
+ ldr r1, =MainExitHandler
+ bx r1
+.code 32
+#else
+ bl hwinit1
+ mov r0, #0
+ mov r1, r0
+ bl main
+ b MainExitHandler
+#endif
+
+/*
+ * Default main function exit handler.
+ */
+.weak MainExitHandler
+.globl MainExitHandler
+MainExitHandler:
+
+.loop: b .loop
+
+/*
+ * Default early initialization code. It is declared weak in order to be
+ * replaced by the real initialization code.
+ * Early initialization is performed just after reset before BSS and DATA
+ * segments initialization.
+ */
+#ifdef THUMB_NO_INTERWORKING
+.thumb_func
+.code 16
+#endif
+.weak hwinit0
+hwinit0:
+ bx lr
+.code 32
+
+/*
+ * Default late initialization code. It is declared weak in order to be
+ * replaced by the real initialization code.
+ * Late initialization is performed after BSS and DATA segments initialization
+ * and before invoking the main() function.
+ */
+#ifdef THUMB_NO_INTERWORKING
+.thumb_func
+.code 16
+#endif
+.weak hwinit1
+hwinit1:
+ bx lr
+.code 32
+
+/** @endcond */
+/** @} */
diff --git a/os/ports/GCC/ARM7/port.dox b/os/ports/GCC/ARM7/port.dox
new file mode 100644
index 000000000..780c57083
--- /dev/null
+++ b/os/ports/GCC/ARM7/port.dox
@@ -0,0 +1,200 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @defgroup ARM7 ARM7TDMI
+ * @details The ARM7 architecture is quite complex for a microcontroller and
+ * some explanations are required about the port choices.
+ *
+ * @section ARM7_NOTES The ARM7 modes
+ * The ARM7 port supports three modes:
+ * - Pure ARM mode, this is the preferred mode for code speed. The code size
+ * is larger however. This mode is enabled when all the modules are compiled
+ * in ARM mode, see the Makefiles.
+ * - Pure THUMB mode, this is the preferred mode for code size. In this mode
+ * the execution speed is slower than the ARM mode. This mode is enabled
+ * when all the modules are compiled in THUMB mode, see the Makefiles.
+ * - Interworking mode, when in the system there are ARM modules mixed with
+ * THUMB modules then the interworking compiler option is enabled. This is
+ * usually the slowest mode and the code size is not as good as in pure
+ * THUMB mode.
+ * .
+ * @section ARM7_STATES Mapping of the System States in the ARM7 port
+ * The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM7
+ * port:
+ * - <b>Init</b>. This state is represented by the startup code and the
+ * initialization code before @p chSysInit() is executed. It has not a
+ * special hardware state associated, usually the CPU goes through several
+ * hardware states during the startup phase.
+ * - <b>Normal</b>. This is the state the system has after executing
+ * @p chSysInit(). In this state the ARM7TDMI has both the interrupt sources
+ * (IRQ and FIQ) enabled and is running in ARM System Mode.
+ * - <b>Suspended</b>. In this state the IRQ sources are disabled but the FIQ
+ * sources are served, the core is running in ARM System Mode.
+ * - <b>Disabled</b>. Both the IRQ and FIQ sources are disabled, the core is
+ * running in ARM System Mode.
+ * - <b>Sleep</b>. The ARM7 code does not have any built-in low power mode but
+ * there are clock stop modes implemented in custom ways by the various
+ * silicon vendors. This state is implemented in each microcontroller support
+ * code in a different way, the core is running (or freezed...) in ARM
+ * System Mode.
+ * - <b>S-Locked</b>. IRQ sources disabled, core running in ARM System Mode.
+ * - <b>I-Locked</b>. IRQ sources disabled, core running in ARM IRQ Mode. Note
+ * that this state is not different from the SRI state in this port, the
+ * @p chSysLockI() and @p chSysUnlockI() APIs do nothing (still use them in
+ * order to formally change state because this may change).
+ * - <b>Serving Regular Interrupt</b>. IRQ sources disabled, core running in
+ * ARM IRQ Mode. See also the I-Locked state.
+ * - <b>Serving Fast Interrupt</b>. IRQ and FIQ sources disabled, core running
+ * in ARM FIQ Mode.
+ * - <b>Serving Non-Maskable Interrupt</b>. There are no asynchronous NMI
+ * sources in ARM7 architecture but synchronous SVC, ABT and UND exception
+ * handlers can be seen as belonging to this category.
+ * - <b>Halted</b>. Implemented as an infinite loop after disabling both IRQ
+ * and FIQ sources. The ARM state is whatever the processor was running when
+ * @p chSysHalt() was invoked.
+ * .
+ * @section ARM7_NOTES The ARM7 port notes
+ * The ARM7 port makes some assumptions on the application code organization:
+ * - The @p main() function is invoked in system mode.
+ * - Each thread has a private user/system stack, the system has a single
+ * interrupt stack where all the interrupts are processed.
+ * - The threads are started in system mode.
+ * - The threads code can run in system mode or user mode, however the
+ * code running in user mode cannot invoke the ChibiOS/RT APIs directly
+ * because privileged instructions are used inside.<br>
+ * The kernel APIs can be eventually invoked by using a SWI entry point
+ * that handles the switch in system mode and the return in user mode.
+ * - Other modes are not preempt-able because the system code assumes the
+ * threads running in system mode. When running in supervisor or other
+ * modes make sure that the interrupts are globally disabled.
+ * - Interrupts nesting is not supported in the ARM7 code because their
+ * implementation, even if possible, is not really efficient in this
+ * architecture.
+ * - FIQ sources can preempt the kernel (by design) so it is not possible to
+ * invoke the kernel APIs from inside a FIQ handler. FIQ handlers are not
+ * affected by the kernel activity so there is not added jitter.
+ * .
+ * @section ARM7_IH ARM7 Interrupt Handlers
+ * ARM7 Interrupt handlers do not save function-saved registers so you need to
+ * make sure your code saves them or does not use them (this happens
+ * because in the ARM7 port all the OS interrupt handler functions are declared
+ * naked).<br>
+ * Function-trashed registers (R0-R3, R12, LR, SR) are saved/restored by the
+ * system macros @p CH_IRQ_PROLOGUE() and @p CH_IRQ_EPILOGUE().<br>
+ * The easiest way to ensure this is to just invoke a normal function from
+ * within the interrupt handler, the function code will save all the required
+ * registers.<br>
+ * Example:
+ * @code
+ * CH_IRQ_HANDLER(irq_handler) {
+ * CH_IRQ_PROLOGUE();
+ *
+ * serve_interrupt();
+ *
+ * VICVectAddr = 0; // This is LPC214x-specific.
+ * CH_IRQ_EPILOGUE();
+ * }
+ * @endcode
+ * This is not a bug but an implementation choice, this solution allows to
+ * have interrupt handlers compiled in thumb mode without have to use an
+ * interworking mode (the mode switch is hidden in the macros), this
+ * greatly improves code efficiency and size. You can look at the serial
+ * driver for real examples of interrupt handlers.
+ *
+ * @ingroup Ports
+ */
+
+/**
+ * @defgroup ARM7_CONF Configuration Options
+ * @brief ARM7 specific configuration options.
+ * @details The ARM7 port allows some architecture-specific configurations
+ * settings that can be specified externally, as example on the compiler
+ * command line:
+ * - @p INT_REQUIRED_STACK, this value represent the amount of stack space used
+ * by an interrupt handler between the @p extctx and @p intctx
+ * structures.<br>
+ * In practice this value is the stack space used by the chSchDoReschedule()
+ * stack frame.<br>
+ * This value can be affected by a variety of external things like compiler
+ * version, compiler options, kernel settings (speed/size) and so on.<br>
+ * The default for this value is @p 0x10 which should be a safe value, you
+ * can trim this down by defining the macro externally. This would save
+ * some valuable RAM space for each thread present in the system.<br>
+ * The default value is set into <b>./ports/ARM7/chcore.h</b>.
+ * .
+ * @ingroup ARM7
+ */
+
+/**
+ * @defgroup ARM7_CORE Core Port Implementation
+ * @brief ARM7 specific port code, structures and macros.
+ *
+ * @ingroup ARM7
+ * @file ports/ARM7/chtypes.h Port types.
+ * @file ports/ARM7/chcore.h Port related structures and macros.
+ * @file ports/ARM7/chcore.c Port related code.
+ */
+
+/**
+ * @defgroup ARM7_STARTUP Startup Support
+ * @brief ARM7 startup code support.
+ * @details ChibiOS/RT provides its own generic startup file for the ARM7 port.
+ * Of course it is not mandatory to use it but care should be taken about the
+ * startup phase details.
+ *
+ * <h2>Startup Process</h2>
+ * The startup process, as implemented, is the following:
+ * -# The stacks are initialized by assigning them the sizes defined in the
+ * linker script (usually named @p ch.ld). Stack areas are allocated from
+ * the highest RAM location downward.
+ * -# The ARM state is switched to System with both IRQ and FIQ sources
+ * disabled.
+ * -# An early initialization routine @p hwinit0 is invoked, if the symbol is
+ * not defined then an empty default routine is executed (weak symbol).
+ * -# DATA and BSS segments are initialized.
+ * -# A late initialization routine @p hwinit1 is invoked, if the symbol not
+ * defined then an empty default routine is executed (weak symbol).<br>
+ * This late initialization function is also the proper place for a
+ * @a bootloader, if your application requires one.
+ * -# The @p main() function is invoked with the parameters @p argc and @p argv
+ * set to zero.
+ * -# Should the @p main() function return a branch is performed to the weak
+ * symbol MainExitHandler. The default code is an endless empty loop.
+ * .
+ * <h2>Expected linker symbols</h2>
+ * The startup code starts at the symbol @p ResetHandler and expects the
+ * following symbols to be defined in the linker script:
+ * - @p __ram_end__ RAM end location +1.
+ * - @p __und_stack_size__ Undefined Instruction stack size.
+ * - @p __abt_stack_size__ Memory Abort stack size.
+ * - @p __fiq_stack_size__ FIQ service stack size.
+ * - @p __irq_stack_size__ IRQ service stack size.
+ * - @p __svc_stack_size__ SVC service stack size.
+ * - @p __sys_stack_size__ System/User stack size. This is the stack area used
+ * by the @p main() function.
+ * - @p _textdata address of the data segment source read only data.
+ * - @p _data data segment start location.
+ * - @p _edata data segment end location +1.
+ * - @p _bss_start BSS start location.
+ * - @p _bss_end BSS end location +1.
+ * .
+ * @ingroup ARM7
+ * @file ports/ARM7/crt0.s Startup code.
+ */
diff --git a/os/ports/GCC/ARM7/port.mk b/os/ports/GCC/ARM7/port.mk
new file mode 100644
index 000000000..d81135981
--- /dev/null
+++ b/os/ports/GCC/ARM7/port.mk
@@ -0,0 +1,7 @@
+# List of the ChibiOS/RT Cortex-M3 port files.
+PORTSRC = ../../os/ports/GCC/ARM7/chcore.c
+
+PORTASM = ../../os/ports/GCC/ARM7/crt0.s \
+ ../../os/ports/GCC/ARM7/chcoreasm.s
+
+PORTINC = ../../os/ports/GCC/ARM7