aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortheshed <theshed@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-04-26 18:11:10 +0000
committertheshed <theshed@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-04-26 18:11:10 +0000
commit6d4cee3b28ab9446fa8f567bdd0199c16561bad8 (patch)
tree175fe9491d99535e4e7e02112f3af945722a1b41
parentc4a01fccefa5105067b4f8c05709c4ccf4734310 (diff)
downloadChibiOS-6d4cee3b28ab9446fa8f567bdd0199c16561bad8.tar.gz
ChibiOS-6d4cee3b28ab9446fa8f567bdd0199c16561bad8.tar.bz2
ChibiOS-6d4cee3b28ab9446fa8f567bdd0199c16561bad8.zip
Add LPC122x support
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5633 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--boards/OLIMEX_LPC-P1227/board.c58
-rw-r--r--boards/OLIMEX_LPC-P1227/board.h98
-rw-r--r--boards/OLIMEX_LPC-P1227/board.mk5
-rw-r--r--os/hal/platforms/LPC122x/LPC122x.h725
-rw-r--r--os/hal/platforms/LPC122x/gpt_lld.c338
-rw-r--r--os/hal/platforms/LPC122x/gpt_lld.h204
-rw-r--r--os/hal/platforms/LPC122x/hal_lld.c123
-rw-r--r--os/hal/platforms/LPC122x/hal_lld.h217
-rw-r--r--os/hal/platforms/LPC122x/pal_lld.c154
-rw-r--r--os/hal/platforms/LPC122x/pal_lld.h337
-rw-r--r--os/hal/platforms/LPC122x/platform.mk9
-rw-r--r--os/hal/platforms/LPC122x/serial_lld.c383
-rw-r--r--os/hal/platforms/LPC122x/serial_lld.h317
-rw-r--r--os/hal/platforms/LPC122x/spi_lld.c352
-rw-r--r--os/hal/platforms/LPC122x/spi_lld.h281
-rw-r--r--os/hal/platforms/LPC122x/system_LPC122x.h65
-rw-r--r--os/ports/GCC/ARMCMx/LPC122x/cmparams.h62
-rw-r--r--os/ports/GCC/ARMCMx/LPC122x/ld/LPC1227.ld152
-rw-r--r--os/ports/GCC/ARMCMx/LPC122x/port.mk15
-rw-r--r--os/ports/GCC/ARMCMx/LPC122x/vectors.c198
-rw-r--r--testhal/LPC122x/IRQ_STORM/Makefile196
-rw-r--r--testhal/LPC122x/IRQ_STORM/chconf.h535
-rw-r--r--testhal/LPC122x/IRQ_STORM/halconf.h316
-rw-r--r--testhal/LPC122x/IRQ_STORM/main.c324
-rw-r--r--testhal/LPC122x/IRQ_STORM/mcuconf.h88
-rw-r--r--testhal/LPC122x/IRQ_STORM/readme.txt25
26 files changed, 5577 insertions, 0 deletions
diff --git a/boards/OLIMEX_LPC-P1227/board.c b/boards/OLIMEX_LPC-P1227/board.c
new file mode 100644
index 000000000..a59b00b4d
--- /dev/null
+++ b/boards/OLIMEX_LPC-P1227/board.c
@@ -0,0 +1,58 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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/>.
+*/
+
+#include "ch.h"
+#include "hal.h"
+
+/**
+ * @brief PAL setup.
+ * @details Digital I/O ports static configuration as defined in @p board.h.
+ * This variable is used by the HAL when initializing the PAL driver.
+ */
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+const PALConfig pal_default_config = {
+ {VAL_GPIO0DATA, VAL_GPIO0DIR},
+ {VAL_GPIO1DATA, VAL_GPIO1DIR},
+ {VAL_GPIO2DATA, VAL_GPIO2DIR},
+};
+#endif
+
+/*
+ * Early initialization code.
+ * This initialization must be performed just after stack setup and before
+ * any other initialization.
+ */
+void __early_init(void) {
+
+ lpc122x_clock_init();
+}
+
+/*
+ * Board-specific initialization code.
+ */
+void boardInit(void) {
+
+ /*
+ * Extra, board-specific, initializations.
+ */
+ LPC_IOCON->PIO1_4 = 0x80; /* Disables pull-up on LED2 output. */
+ LPC_IOCON->PIO1_5 = 0x80; /* Disables pull-up on LED1 output */
+ LPC_IOCON->PIO1_6 = 0x80; /* Disables pull-up on Buzzer output */
+}
diff --git a/boards/OLIMEX_LPC-P1227/board.h b/boards/OLIMEX_LPC-P1227/board.h
new file mode 100644
index 000000000..ae2e879a7
--- /dev/null
+++ b/boards/OLIMEX_LPC-P1227/board.h
@@ -0,0 +1,98 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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 _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * Setup for Olimex LPC-P1227 board.
+ *
+ */
+
+/*
+ * Board identifiers.
+ */
+#define OLIMEX_LPC_P1227
+#define BOARD_NAME "Olimex LPC-P1227"
+
+/*
+ * Board frequencies.
+ */
+#define SYSOSCCLK 12000000
+
+
+/*
+ * GPIO 0 initial setup.
+ */
+#define VAL_GPIO0DIR 0x00000000
+#define VAL_GPIO0DATA 0x00000000
+
+/*
+ * GPIO 1 initial setup.
+ */
+#define VAL_GPIO1DIR PAL_PORT_BIT(GPIO1_LED1) | \
+ PAL_PORT_BIT(GPIO1_LED2) | \
+ PAL_PORT_BIT(GPIO1_BUZZER)
+
+#define VAL_GPIO1DATA PAL_PORT_BIT(GPIO1_LED1)
+
+
+/*
+ * GPIO 2 initial setup.
+ */
+#define VAL_GPIO2DIR PAL_PORT_BIT(GPIO2_LCD_DC) | \
+ PAL_PORT_BIT(GPIO2_LCD_SS) | \
+ PAL_PORT_BIT(GPIO2_LCD_RES)
+#define VAL_GPIO2DATA PAL_PORT_BIT(GPIO2_LCD_SS)
+
+
+/*
+ * Pin definitions.
+ */
+
+#define GPIO1_LED1 5
+#define GPIO1_LED2 4
+#define GPIO1_SW_WAKEUP 3
+#define GPIO1_BUZZER 6
+
+#define GPIO2_SW_USER1 12
+#define GPIO2_SW_USER2 11
+#define GPIO2_SW_USER3 10
+#define GPIO2_LCD_DC 15
+#define GPIO2_LCD_SS 14
+#define GPIO2_LCD_RES 13
+
+/* LCD3310 pins */
+#define LCD3310_RES_PIN GPIO2_LCD_RES
+#define LCD3310_RES_PORT GPIO2
+#define LCD3310_DC_PIN GPIO2_LCD_DC
+#define LCD3310_DC_PORT GPIO2
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/boards/OLIMEX_LPC-P1227/board.mk b/boards/OLIMEX_LPC-P1227/board.mk
new file mode 100644
index 000000000..090251880
--- /dev/null
+++ b/boards/OLIMEX_LPC-P1227/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = ${CHIBIOS}/boards/OLIMEX_LPC-P1227/board.c
+
+# Required include directories
+BOARDINC = ${CHIBIOS}/boards/OLIMEX_LPC-P1227
diff --git a/os/hal/platforms/LPC122x/LPC122x.h b/os/hal/platforms/LPC122x/LPC122x.h
new file mode 100644
index 000000000..8415b06fa
--- /dev/null
+++ b/os/hal/platforms/LPC122x/LPC122x.h
@@ -0,0 +1,725 @@
+/**************************************************************************//**
+ * $Id: LPC122x.h 6933 2011-03-23 19:02:11Z nxp28548 $
+ *
+ * @file LPC122x.h
+ * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File for
+ * NXP LPC122x Device Series
+ * @version 1.1
+ * @date $Date:: 2011-03-23#$
+ * @author NXP MCU Team
+ *
+ * @note
+ * Copyright (C) 2011 NXP Semiconductors(NXP). All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ ******************************************************************************/
+
+
+
+/** @addtogroup (null)
+ * @{
+ */
+
+/** @addtogroup LPC122x
+ * @{
+ */
+
+#ifndef __LPC122X_H__
+#define __LPC122X_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined ( __CC_ARM )
+ #pragma anon_unions
+#endif
+
+ /* Interrupt Number Definition */
+
+typedef enum {
+ // ------------------------- Cortex-M0 Processor Exceptions Numbers -----------------------------
+ Reset_IRQn = -15, /*!< 1 Reset Vector, invoked on Power up and warm reset */
+ NonMaskableInt_IRQn = -14, /*!< 2 Non maskable Interrupt, cannot be stopped or preempted */
+ HardFault_IRQn = -13, /*!< 3 Hard Fault, all classes of Fault */
+ SVCall_IRQn = -5, /*!< 11 System Service Call via SVC instruction */
+ DebugMonitor_IRQn = -4, /*!< 12 Debug Monitor */
+ PendSV_IRQn = -2, /*!< 14 Pendable request for system service */
+ SysTick_IRQn = -1, /*!< 15 System Tick Timer */
+ // --------------------------- LPC122x Specific Interrupt Numbers -------------------------------
+ WAKEUP0_IRQn = 0, /*!< PIO0_0 to PIO0_11 Wakeup */
+ WAKEUP1_IRQn = 1,
+ WAKEUP2_IRQn = 2,
+ WAKEUP3_IRQn = 3,
+ WAKEUP4_IRQn = 4,
+ WAKEUP5_IRQn = 5,
+ WAKEUP6_IRQn = 6,
+ WAKEUP7_IRQn = 7,
+ WAKEUP8_IRQn = 8,
+ WAKEUP9_IRQn = 9,
+ WAKEUP10_IRQn = 10,
+ WAKEUP11_IRQn = 11, /*!< PIO0_0 to PIO0_11 Wakeup */
+ I2C_IRQn =12, /*!< I2C Interrupt */
+ TIMER_16_0_IRQn = 13, /*!< 16-bit Timer0 Interrupt */
+ TIMER_16_1_IRQn = 14, /*!< 16-bit Timer1 Interrupt */
+ TIMER_32_0_IRQn = 15, /*!< 32-bit Timer0 Interrupt */
+ TIMER_32_1_IRQn = 16, /*!< 32-bit Timer1 Interrupt */
+ SSP_IRQn = 17, /*!< SSP Interrupt */
+ UART0_IRQn = 18, /*!< UART0 Interrupt */
+ UART1_IRQn = 19, /*!< UART1 Interrupt */
+ CMP_IRQn = 20, /*!< Comparator Interrupt */
+ ADC_IRQn = 21, /*!< A/D Converter Interrupt */
+ WDT_IRQn = 22, /*!< Watchdog timer Interrupt */
+ BOD_IRQn = 23, /*!< Brown Out Detect(BOD) Interrupt */
+ EINT0_IRQn = 25, /*!< External Interrupt 0 Interrupt */
+ EINT1_IRQn = 26, /*!< External Interrupt 1 Interrupt */
+ EINT2_IRQn = 27, /*!< External Interrupt 2 Interrupt */
+ DMA_IRQn = 29, /*!< DMA Interrupt */
+ RTC_IRQn = 30, /*!< RTC Interrupt */
+} IRQn_Type;
+
+
+/** @addtogroup Configuration_of_CMSIS
+ * @{
+ */
+
+/*
+ * ==========================================================================
+ * ----------- Processor and Core Peripheral Section ------------------------
+ * ==========================================================================
+ */
+
+/* Configuration of the Cortex-M0 Processor and Core Peripherals */
+#define __MPU_PRESENT 0 /*!< MPU present or not */
+#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels */
+#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
+
+/*@}*/ /* end of group LPC12xx_CMSIS */
+
+
+#include "core_cm0.h" /* Cortex-M0 processor and core peripherals */
+#include "system_LPC122x.h" /* System Header */
+
+/** @addtogroup Device_Peripheral_Registers
+ * @{
+ */
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- I2C -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x I2C-bus controller Modification date=2/2/2011 Major revision=0 Minor revision=17 (I2C)
+ */
+
+typedef struct { /*!< (@ 0x40000000) I2C Structure */
+ __IO uint32_t CONSET; /*!< (@ 0x40000000) I2C Control Set Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is set. Writing a zero has no effect on the corresponding bit in the I2C control register. */
+ __I uint32_t STAT; /*!< (@ 0x40000004) I2C Status Register. During I2C operation, this register provides detailed status codes that allow software to determine the next action needed. */
+ __IO uint32_t DAT; /*!< (@ 0x40000008) I2C Data Register. During master or slave transmit mode, data to be transmitted is written to this register. During master or slave receive mode, data that has been received may be read from this register. */
+ __IO uint32_t ADR0; /*!< (@ 0x4000000C) I2C Slave Address Register 0. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */
+ __IO uint32_t SCLH; /*!< (@ 0x40000010) SCH Duty Cycle Register High Half Word. Determines the high time of the I2C clock. */
+ __IO uint32_t SCLL; /*!< (@ 0x40000014) SCL Duty Cycle Register Low Half Word. Determines the low time of the I2C clock. I2nSCLL and I2nSCLH together determine the clock frequency generated by an I2C master and certain times used in slave mode. */
+ __IO uint32_t CONCLR; /*!< (@ 0x40000018) I2C Control Clear Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is cleared. Writing a zero has no effect on the corresponding bit in the I2C control register. */
+ __IO uint32_t MMCTRL; /*!< (@ 0x4000001C) Monitor mode control register. */
+ __IO uint32_t ADR1; /*!< (@ 0x40000020) I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */
+ __IO uint32_t ADR2; /*!< (@ 0x40000024) I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */
+ __IO uint32_t ADR3; /*!< (@ 0x40000028) I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */
+ __I uint32_t DATA_BUFFER; /*!< (@ 0x4000002C) Data buffer register. The contents of the 8 MSBs of the I2DAT shift register will be transferred to the DATA_BUFFER automatically after every nine bits (8 bits of data plus ACK or NACK) has been received on the bus. */
+ __IO uint32_t MASK[4]; /*!< (@ 0x40000030) I2C Slave address mask register. This mask register is associated with I2ADR0 to determine an address match. The mask register has no effect when comparing to the General Call address (0000000). */
+} LPC_I2C_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- WWDT -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x Windowed Watchdog Timer (WWDT) Modification date=2/2/2011 Major revision=0 Minor revision=17 (WWDT)
+ */
+
+typedef struct { /*!< (@ 0x40004000) WWDT Structure */
+ __IO uint32_t MOD; /*!< (@ 0x40004000) Watchdog mode register. This register contains the basic mode and status of the Watchdog Timer. */
+ __IO uint32_t TC; /*!< (@ 0x40004004) Watchdog timer constant register. This register determines the time-out value. */
+ __IO uint32_t FEED; /*!< (@ 0x40004008) Watchdog feed sequence register. Writing 0xAA followed by 0x55 to this register reloads the Watchdog timer with the value contained in TC. */
+ __I uint32_t TV; /*!< (@ 0x4000400C) Watchdog timer value register. This register reads out the current value of the Watchdog timer. */
+ __IO uint32_t CLKSEL; /*!< (@ 0x40004010) Watchdog clock source selection register. */
+ __IO uint32_t WARNINT; /*!< (@ 0x40004014) Watchdog Warning Interrupt compare value. */
+ __IO uint32_t WINDOW; /*!< (@ 0x40004018) Watchdog Window compare value. */
+} LPC_WWDT_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- UART0 -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x UART0 with modem control Modification date=2/2/2011 Major revision=0 Minor revision=17 (UART0)
+ */
+
+typedef struct { /*!< (@ 0x40008000) UART0 Structure */
+
+ union {
+ __IO uint32_t DLL; /*!< (@ 0x40008000) Divisor Latch LSB. Least significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. (DLAB = 1) */
+ __IO uint32_t THR; /*!< (@ 0x40008000) Transmit Holding Register. The next character to be transmitted is written here. (DLAB=0) */
+ __I uint32_t RBR; /*!< (@ 0x40008000) Receiver Buffer Register. Contains the next received character to be read. (DLAB=0) */
+ };
+
+ union {
+ __IO uint32_t IER; /*!< (@ 0x40008004) Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential UART interrupts. (DLAB=0) */
+ __IO uint32_t DLM; /*!< (@ 0x40008004) Divisor Latch MSB. Most significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. (DLAB = 1) */
+ };
+
+ union {
+ __IO uint32_t FCR; /*!< (@ 0x40008008) FIFO Control Register. Controls UART FIFO usage and modes. */
+ __I uint32_t IIR; /*!< (@ 0x40008008) Interrupt ID Register. Identifies which interrupt(s) are pending. */
+ };
+ __IO uint32_t LCR; /*!< (@ 0x4000800C) Line Control Register. Contains controls for frame formatting and break generation. */
+ __IO uint32_t MCR; /*!< (@ 0x40008010) Modem control register */
+ __I uint32_t LSR; /*!< (@ 0x40008014) Line Status Register. Contains flags for transmit and receive status, including line errors. */
+ __I uint32_t MSR; /*!< (@ 0x40008018) Modem status register */
+ __IO uint32_t SCR; /*!< (@ 0x4000801C) Scratch Pad Register. Eight-bit temporary storage for software. */
+ __IO uint32_t ACR; /*!< (@ 0x40008020) Auto-baud Control Register. Contains controls for the auto-baud feature. */
+ __I uint32_t RESERVED0[1];
+ __IO uint32_t FDR; /*!< (@ 0x40008028) Fractional Divider Register. Generates a clock input for the baud rate divider. */
+ __I uint32_t RESERVED1[1];
+ __IO uint32_t TER; /*!< (@ 0x40008030) Transmit Enable Register. Turns off UART transmitter for use with software flow control. */
+ __I uint32_t RESERVED2[6];
+ __IO uint32_t RS485CTRL; /*!< (@ 0x4000804C) RS-485/EIA-485 Control. Contains controls to configure various aspects of RS-485/EIA-485 modes. */
+ __IO uint32_t RS485ADRMATCH; /*!< (@ 0x40008050) RS-485/EIA-485 address match. Contains the address match value for RS-485/EIA-485 mode. */
+ __IO uint32_t RS485DLY; /*!< (@ 0x40008054) RS-485/EIA-485 direction control delay. */
+ __I uint32_t FIFOLVL; /*!< (@ 0x40008058) FIFO Level register. Provides the current fill levels of the transmit and receive FIFOs. */
+} LPC_UART0_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- UART1 -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x UART1 Modification date=2/3/2011 Major revision=0 Minor revision=17 (UART1)
+ */
+
+typedef struct { /*!< (@ 0x4000C000) UART1 Structure */
+
+ union {
+ __IO uint32_t DLL; /*!< (@ 0x4000C000) Divisor Latch LSB. Least significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. */
+ __IO uint32_t THR; /*!< (@ 0x4000C000) Transmit Holding Register. The next character to be transmitted is written here. */
+ __I uint32_t RBR; /*!< (@ 0x4000C000) Receiver Buffer Register. Contains the next received character to be read. */
+ };
+
+ union {
+ __IO uint32_t IER; /*!< (@ 0x4000C004) Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential UART interrupts. */
+ __IO uint32_t DLM; /*!< (@ 0x4000C004) Divisor Latch MSB. Most significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. */
+ };
+
+ union {
+ __IO uint32_t FCR; /*!< (@ 0x4000C008) FIFO Control Register. Controls UART FIFO usage and modes. */
+ __I uint32_t IIR; /*!< (@ 0x4000C008) Interrupt ID Register. Identifies which interrupt(s) are pending. */
+ };
+ __IO uint32_t LCR; /*!< (@ 0x4000C00C) Line Control Register. Contains controls for frame formatting and break generation. */
+ __I uint32_t RESERVED0[1];
+ __I uint32_t LSR; /*!< (@ 0x4000C014) Line Status Register. Contains flags for transmit and receive status, including line errors. */
+ __I uint32_t RESERVED1[1];
+ __IO uint32_t SCR; /*!< (@ 0x4000C01C) Scratch Pad Register. Eight-bit temporary storage for software. */
+ __IO uint32_t ACR; /*!< (@ 0x4000C020) Auto-baud Control Register. Contains controls for the auto-baud feature. */
+ __IO uint32_t ICR; /*!< (@ 0x4000C024) IrDA Control Register. Enables and configures the IrDA mode. */
+ __IO uint32_t FDR; /*!< (@ 0x4000C028) Fractional Divider Register. Generates a clock input for the baud rate divider. */
+ __I uint32_t RESERVED2[1];
+ __IO uint32_t TER; /*!< (@ 0x4000C030) Transmit Enable Register. Turns off UART transmitter for use with software flow control. */
+ __I uint32_t RESERVED3[9];
+ __I uint32_t FIFOLVL; /*!< (@ 0x4000C058) FIFO Level register. Provides the current fill levels of the transmit and receive FIFOs. */
+} LPC_UART1_Type;
+
+// ------------------------------------------------------------------------------------------------
+// ----- CT32B0 -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x 32-bit Counter/timer 0/1 (CT32B0/1) Modification date=2/3/2011 Major revision=0 Minor revision=17 (CT32B0)
+ */
+
+typedef struct { /*!< (@ 0x40018000) CT32B0 Structure */
+ __IO uint32_t IR; /*!< (@ 0x40018000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */
+ __IO uint32_t TCR; /*!< (@ 0x40018004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */
+ __IO uint32_t TC; /*!< (@ 0x40018008) Timer Counter. The 32-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */
+ __IO uint32_t PR; /*!< (@ 0x4001800C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */
+ __IO uint32_t PC; /*!< (@ 0x40018010) Prescale Counter. The 32-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */
+ __IO uint32_t MCR; /*!< (@ 0x40018014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */
+ union {
+ __IO uint32_t MR[4]; /*!< (@ 0x40018018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */
+ struct{
+ __IO uint32_t MR0; /*!< (@ 0x40018018) Match Register. MR0 */
+ __IO uint32_t MR1; /*!< (@ 0x40018018) Match Register. MR1 */
+ __IO uint32_t MR2; /*!< (@ 0x40018018) Match Register. MR2 */
+ __IO uint32_t MR3; /*!< (@ 0x40018018) Match Register. MR3 */
+ };
+ };
+ __IO uint32_t CCR; /*!< (@ 0x40018028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */
+ union{
+ __I uint32_t CR[4]; /*!< (@ 0x4001802C) Capture Register. CR is loaded with the value of TC when there is an event on the CT32B_CAP input. */
+ struct{
+ __I uint32_t CR0; /*!< (@ 0x4001802C) Capture Register. CR 0 */
+ __I uint32_t CR1; /*!< (@ 0x4001802C) Capture Register. CR 1 */
+ __I uint32_t CR2; /*!< (@ 0x4001802C) Capture Register. CR 2 */
+ __I uint32_t CR3; /*!< (@ 0x4001802C) Capture Register. CR 3 */
+ };
+ };
+ __IO uint32_t EMR; /*!< (@ 0x4001803C) External Match Register. The EMR controls the match function and the external match pins CT32Bn_MAT[3:0]. */
+ __I uint32_t RESERVED0[12];
+ __IO uint32_t CTCR; /*!< (@ 0x40018070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */
+ __IO uint32_t PWMC; /*!< (@ 0x40018074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT32Bn_MAT[3:0]. */
+} LPC_CTxxBx_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- ADC -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x ADC Modification date=2/9/2011 Major revision=0 Minor revision=17 (ADC)
+ */
+
+typedef struct { /*!< (@ 0x40020000) ADC Structure */
+ __IO uint32_t CR; /*!< (@ 0x40020000) A/D Control Register. The CR register must be written to select the operating mode before A/D conversion can occur. */
+ __IO uint32_t GDR; /*!< (@ 0x40020004) A/D Global Data Register. Contains the result of the most recent A/D conversion. */
+ __I uint32_t RESERVED0[1];
+ __IO uint32_t INTEN; /*!< (@ 0x4002000C) A/D Interrupt Enable Register. This register contains enable bits that allow the DONE flag of each A/D channel to be included or excluded from contributing to the generation of an A/D interrupt. */
+ union{
+ __IO uint32_t DR[8]; /*!< (@ 0x40020010) A/D Channel Data Register. This register contains the result of the most recent conversion completed on channel. */
+ struct{
+ __IO uint32_t DR0; /*!< (@ 0x40020010) A/D Channel Data Register 0*/
+ __IO uint32_t DR1; /*!< (@ 0x40020010) A/D Channel Data Register 1*/
+ __IO uint32_t DR2; /*!< (@ 0x40020010) A/D Channel Data Register 2*/
+ __IO uint32_t DR3; /*!< (@ 0x40020010) A/D Channel Data Register 3*/
+ __IO uint32_t DR4; /*!< (@ 0x40020010) A/D Channel Data Register 4*/
+ __IO uint32_t DR5; /*!< (@ 0x40020010) A/D Channel Data Register 5*/
+ __IO uint32_t DR6; /*!< (@ 0x40020010) A/D Channel Data Register 6*/
+ __IO uint32_t DR7; /*!< (@ 0x40020010) A/D Channel Data Register 7*/
+ };
+ };
+ __I uint32_t STAT; /*!< (@ 0x40020030) A/D Status Register. This register contains DONE and OVERRUN flags for all of the A/D channels, as well as the A/D interrupt flag. */
+ __IO uint32_t TRM; /*!< (@ 0x40020034) A/D trim register */
+} LPC_ADC_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- PMU -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x Power Monitor Unit (PMU) Modification date=2/10/2011 Major revision=0 Minor revision=17 (PMU)
+ */
+
+typedef struct { /*!< (@ 0x40038000) PMU Structure */
+ __IO uint32_t PCON; /*!< (@ 0x40038000) Power control register */
+ union{
+ __IO uint32_t GPREG[4]; /*!< (@ 0x40038004) General purpose register */
+ struct{
+ __IO uint32_t GPREG0; /*!< (@ 0x40038004) General purpose register 0 */
+ __IO uint32_t GPREG1; /*!< (@ 0x40038004) General purpose register 1 */
+ __IO uint32_t GPREG2; /*!< (@ 0x40038004) General purpose register 2 */
+ __IO uint32_t GPREG3; /*!< (@ 0x40038004) General purpose register 3 */
+ };
+ };
+ __IO uint32_t SYSCFG; /*!< (@ 0x40038014) System configuration register (RTC clock control and hysteresis of the WAKEUP pin). */
+} LPC_PMU_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- SSP -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x SSP controller Modification date=2/10/2011 Major revision=0 Minor revision=17 (SSP)
+ */
+
+typedef struct { /*!< (@ 0x40040000) SSP Structure */
+ union{
+ __IO uint32_t CR[2]; /*!< (@ 0x40040000) Control Registers. */
+ struct{
+ __IO uint32_t CR0; /*!< (@ 0x40040000) Control Register 0. Selects the serial clock rate, bus type, and data size. */
+ __IO uint32_t CR1; /*!< (@ 0x40040004) Control Register 1. Selects master/slave and other modes. */
+ };
+ };
+ __IO uint32_t DR; /*!< (@ 0x40040008) Data Register. Writes fill the transmit FIFO, and reads empty the receive FIFO. */
+ __I uint32_t SR; /*!< (@ 0x4004000C) Status Register */
+ __IO uint32_t CPSR; /*!< (@ 0x40040010) Clock Prescale Register */
+ __IO uint32_t IMSC; /*!< (@ 0x40040014) Interrupt Mask Set and Clear Register */
+ __I uint32_t RIS; /*!< (@ 0x40040018) Raw Interrupt Status Register */
+ __I uint32_t MIS; /*!< (@ 0x4004001C) Masked Interrupt Status Register */
+ __IO uint32_t ICR; /*!< (@ 0x40040020) SSPICR Interrupt Clear Register */
+ __IO uint32_t DMACR; /*!< (@ 0x40040024) DMA Control Register */
+} LPC_SSP_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- IOCON -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x /O configuration (IOCONFIG) Modification date=2/11/2011 Major revision=1 Minor revision=0 (IOCON)
+ */
+
+typedef struct { /*!< (@ 0x40044000) IOCON Structure */
+ __I uint32_t RESERVED0[2];
+ __IO uint32_t PIO0_19; /*!< (@ 0x40044008) Configures pin PIO0_19/ACMP0_I0/CT32B0_1. */
+ __IO uint32_t PIO0_20; /*!< (@ 0x4004400C) Configures pin PIO0_20/ACMP0_I1/CT32B0_2. */
+ __IO uint32_t PIO0_21; /*!< (@ 0x40044010) Configures pin PIO0_21/ACMP0_I2/CT32B0_3. */
+ __IO uint32_t PIO0_22; /*!< (@ 0x40044014) Configures pin PIO0_22/ACMP0_I3. */
+ __IO uint32_t PIO0_23; /*!< (@ 0x40044018) Configures pin PIO0_23/ACMP1_I0/CT32B1_0. */
+ __IO uint32_t PIO0_24; /*!< (@ 0x4004401C) Configures pin PIO0_24/ACMP1_I1/CT32B1_1. */
+ __IO uint32_t SWDIO_PIO0_25; /*!< (@ 0x40044020) Configures pin SWDIO/ACMP1_I2/ CT32B1_2/PIO0_25. */
+ __IO uint32_t SWCLK_PIO0_26; /*!< (@ 0x40044024) Configures pin SWCLK/PIO0_26/ACMP1_I3/ CT32B1_3/PIO0_26 */
+ __IO uint32_t PIO0_27; /*!< (@ 0x40044028) Configures pin PIO0_27/ACMP0_O. */
+ __IO uint32_t PIO2_12; /*!< (@ 0x4004402C) Configures pin PIO2_12/RXD1. */
+ __IO uint32_t PIO2_13; /*!< (@ 0x40044030) Configures pin PIO2_13/TXD1. */
+ __IO uint32_t PIO2_14; /*!< (@ 0x40044034) Configures pin PIO2_14. */
+ __IO uint32_t PIO2_15; /*!< (@ 0x40044038) Configures pin PIO2_15. */
+ __IO uint32_t PIO0_28; /*!< (@ 0x4004403C) Configures pin PIO0_28/ACMP1_O/CT16B0_0. */
+ __IO uint32_t PIO0_29; /*!< (@ 0x40044040) Configures pin PIO0_29/ROSC/CT16B0_1. */
+ __IO uint32_t PIO0_0; /*!< (@ 0x40044044) Configures pin PIO0_0/ RTS0. */
+ __IO uint32_t PIO0_1; /*!< (@ 0x40044048) Configures pin PIO0_1CT32B0_0/RXD0. */
+ __IO uint32_t PIO0_2; /*!< (@ 0x4004404C) Configures pin PIO0_2/TXD0/CT32B0_1. */
+ __I uint32_t RESERVED1[1];
+ __IO uint32_t PIO0_3; /*!< (@ 0x40044054) Configures pin PIO0_3/DTR0/CT32B0_2. */
+ __IO uint32_t PIO0_4; /*!< (@ 0x40044058) Configures pin PIO0_4/ DSR0/CT32B0_3. */
+ __IO uint32_t PIO0_5; /*!< (@ 0x4004405C) Configures pin PIO0_5. */
+ __IO uint32_t PIO0_6; /*!< (@ 0x40044060) Configures pin PIO0_6/RI0/CT32B1_0. */
+ __IO uint32_t PIO0_7; /*!< (@ 0x40044064) Configures pin PIO0_7CTS0/CT32B1_1. */
+ __IO uint32_t PIO0_8; /*!< (@ 0x40044068) Configures pin PIO0_8/RXD1/CT32B1_2. */
+ __IO uint32_t PIO0_9; /*!< (@ 0x4004406C) Configures pin PIO0_9/TXD1/CT32B1_3. */
+ __IO uint32_t PIO2_0; /*!< (@ 0x40044070) Configures pin PIO2_0/CT16B0_0/ RTS0. */
+ __IO uint32_t PIO2_1; /*!< (@ 0x40044074) Configures pin PIO2_1/CT16B0_1/RXD0. */
+ __IO uint32_t PIO2_2; /*!< (@ 0x40044078) Configures pin PIO2_2/CT16B1_0/TXD0. */
+ __IO uint32_t PIO2_3; /*!< (@ 0x4004407C) Configures pin PIO2_3/CT16B1_1/DTR0. */
+ __IO uint32_t PIO2_4; /*!< (@ 0x40044080) Configures pin PIO2_4/CT32B0_0/CTS0. */
+ __IO uint32_t PIO2_5; /*!< (@ 0x40044084) Configures pin PIO2_5/CT32B0_1/ DCD0. */
+ __IO uint32_t PIO2_6; /*!< (@ 0x40044088) Configures pin PIO2_6/CT32B0_2/RI0. */
+ __IO uint32_t PIO2_7; /*!< (@ 0x4004408C) Configures pin PIO2_7/CT32B0_3/DSR0. */
+ __IO uint32_t PIO0_10; /*!< (@ 0x40044090) Configures pin PIO0_10/SCL. */
+ __IO uint32_t PIO0_11; /*!< (@ 0x40044094) Configures pin PIO0_11/SDA/CT16B0_0. */
+ __IO uint32_t PIO0_12; /*!< (@ 0x40044098) Configures pin PIO0_12/CLKOUT/CT16B0_1. */
+ __IO uint32_t RESET_PIO0_13; /*!< (@ 0x4004409C) Configures pin RESET/PIO0_13. */
+ __IO uint32_t PIO0_14; /*!< (@ 0x400440A0) Configures pin PIO0_14/SSP_CLK. */
+ __IO uint32_t PIO0_15; /*!< (@ 0x400440A4) Configures pin PIO0_15/SSP_SSEL/CT16B1_0. */
+ __IO uint32_t PIO0_16; /*!< (@ 0x400440A8) Configures pin PIO0_16/SSP_MISO/CT16B1_1. */
+ __IO uint32_t PIO0_17; /*!< (@ 0x400440AC) Configures pin PIO0_17/SSP_MOSI. */
+ __IO uint32_t PIO0_18; /*!< (@ 0x400440B0) Configures pin PIO0_18/SWCLK/CT32B0_0. */
+ __IO uint32_t R_PIO0_30; /*!< (@ 0x400440B4) Configures pin R/PIO0_30/AD0. */
+ __IO uint32_t R_PIO0_31; /*!< (@ 0x400440B8) Configures pin R/PIO0_31/AD1. */
+ __IO uint32_t R_PIO1_0; /*!< (@ 0x400440BC) Configures pin R/PIO1_0/AD2. */
+ __IO uint32_t R_PIO1_1; /*!< (@ 0x400440C0) Configures pin R/PIO1_1/AD3. */
+ __IO uint32_t PIO1_2; /*!< (@ 0x400440C4) Configures pin PIO1_2/SWDIO/AD4. */
+ __IO uint32_t PIO1_3; /*!< (@ 0x400440C8) Configures pin PIO1_3/AD5/WAKEUP. */
+ __IO uint32_t PIO1_4; /*!< (@ 0x400440CC) Configures pin PIO1_4/AD6 */
+ __IO uint32_t PIO1_5; /*!< (@ 0x400440D0) Configures pin PIO1_5/AD7/CT16B1_0. */
+ __IO uint32_t PIO1_6; /*!< (@ 0x400440D4) Configures pin PIO1_6/CT16B1_1. */
+ __I uint32_t RESERVED2[2];
+ __IO uint32_t PIO2_8; /*!< (@ 0x400440E0) Configures pin PIO2_8/CT32B1_0. */
+ __IO uint32_t PIO2_9; /*!< (@ 0x400440E4) Configures pin PIO2_9/CT32B1_1. */
+ __IO uint32_t PIO2_10; /*!< (@ 0x400440E8) Configures pin PIO2_10/CT32B1_2/TXD1. */
+ __IO uint32_t PIO2_11; /*!< (@ 0x400440EC) Configures pin PIO2_11/CT32B1_3/RXD1. */
+} LPC_IOCON_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- SYSCON -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x System control (SYSCON) Modification date=2/10/2011 Major revision=1 Minor revision=0 (SYSCON)
+ */
+
+typedef struct { /*!< (@ 0x40048000) SYSCON Structure */
+ __IO uint32_t SYSMEMREMAP; /*!< (@ 0x40048000) System memory remap */
+ __IO uint32_t PRESETCTRL; /*!< (@ 0x40048004) Peripheral reset control and flash timing overwrite */
+ __IO uint32_t SYSPLLCTRL; /*!< (@ 0x40048008) System PLL control */
+ __I uint32_t SYSPLLSTAT; /*!< (@ 0x4004800C) System PLL status */
+ __I uint32_t RESERVED0[4];
+ __IO uint32_t SYSOSCCTRL; /*!< (@ 0x40048020) System oscillator control */
+ __IO uint32_t WDTOSCCTRL; /*!< (@ 0x40048024) Watchdog oscillator control */
+ __IO uint32_t IRCCTRL; /*!< (@ 0x40048028) IRC control */
+ __I uint32_t RESERVED1[1];
+ __IO uint32_t SYSRESSTAT; /*!< (@ 0x40048030) System reset status register */
+ __I uint32_t RESERVED2[3];
+ __IO uint32_t SYSPLLCLKSEL; /*!< (@ 0x40048040) System PLL clock source select */
+ __IO uint32_t SYSPLLCLKUEN; /*!< (@ 0x40048044) System PLL clock source update enable */
+ __I uint32_t RESERVED3[10];
+ __IO uint32_t MAINCLKSEL; /*!< (@ 0x40048070) Main clock source select */
+ __IO uint32_t MAINCLKUEN; /*!< (@ 0x40048074) Main clock source update enable */
+ __IO uint32_t SYSAHBCLKDIV; /*!< (@ 0x40048078) System AHB clock divider */
+ __I uint32_t RESERVED4[1];
+ __IO uint32_t SYSAHBCLKCTRL; /*!< (@ 0x40048080) System AHB clock control */
+ __I uint32_t RESERVED5[4];
+ __IO uint32_t SSPCLKDIV; /*!< (@ 0x40048094) SSP clock divder */
+ __IO uint32_t UART0CLKDIV; /*!< (@ 0x40048098) UART0 clock divider */
+ __IO uint32_t UART1CLKDIV; /*!< (@ 0x4004809C) UART1 clock divider */
+ __IO uint32_t RTCCLKDIV; /*!< (@ 0x400480A0) RTC clock divider */
+ __I uint32_t RESERVED6[15];
+ __IO uint32_t CLKOUTCLKSEL; /*!< (@ 0x400480E0) CLKOUT clock source select */
+ __IO uint32_t CLKOUTUEN; /*!< (@ 0x400480E4) CLKOUT clock source update enable */
+ __IO uint32_t CLKOUTDIV; /*!< (@ 0x400480E8) CLKOUT clock divider */
+ __I uint32_t RESERVED7[5];
+ __I uint32_t PIOPORCAP0; /*!< (@ 0x40048100) POR captured PIO status 0 */
+ __I uint32_t PIOPORCAP1; /*!< (@ 0x40048104) POR captured PIO status 1 */
+ __I uint32_t RESERVED8[11];
+ __IO uint32_t IOCONFIGCLKDIV6; /*!< (@ 0x40048134) Peripheral clock 6 to the IOCONFIG block for programmable glitch filter */
+ __IO uint32_t IOCONFIGCLKDIV5; /*!< (@ 0x40048138) Peripheral clock 5 to the IOCONFIG block for programmable glitch filter */
+ __IO uint32_t IOCONFIGCLKDIV4; /*!< (@ 0x4004813C) Peripheral clock 4 to the IOCONFIG block for programmable glitch filter */
+ __IO uint32_t IOCONFIGCLKDIV3; /*!< (@ 0x40048140) Peripheral clock 3to the IOCONFIG block for programmable glitch filter */
+ __IO uint32_t IOCONFIGCLKDIV2; /*!< (@ 0x40048144) Peripheral clock 2 to the IOCONFIG block for programmable glitch filter */
+ __IO uint32_t IOCONFIGCLKDIV1; /*!< (@ 0x40048148) Peripheral clock 1 to the IOCONFIG block for programmable glitch filter */
+ __IO uint32_t IOCONFIGCLKDIV0; /*!< (@ 0x4004814C) Peripheral clock 0 to the IOCONFIG block for programmable glitch filter */
+ __IO uint32_t BODCTRL; /*!< (@ 0x40048150) BOD control */
+ __IO uint32_t SYSTCKCAL; /*!< (@ 0x40048154) System tick counter calibration */
+ __IO uint32_t AHBPRIO; /*!< (@ 0x40048158) AHB priority setting */
+ __I uint32_t RESERVED9[5];
+ __IO uint32_t IRQLATENCY; /*!< (@ 0x40048170) IQR delay. Allows trade-off between interrupt latency and determinism. */
+ __IO uint32_t INTNMI; /*!< (@ 0x40048174) NMI interrupt source configuration control */
+ __I uint32_t RESERVED10[34];
+ __IO uint32_t STARTAPRP0; /*!< (@ 0x40048200) Start logic edge control register 0 */
+ __IO uint32_t STARTERP0; /*!< (@ 0x40048204) Start logic signal enable register 0 */
+ __IO uint32_t STARTRSRP0CLR; /*!< (@ 0x40048208) Start logic reset register 0 */
+ __I uint32_t STARTSRP0; /*!< (@ 0x4004820C) Start logic status register 0 */
+ __IO uint32_t STARTAPRP1; /*!< (@ 0x40048210) Start logic edge control register 1; peripheral interrupts */
+ __IO uint32_t STARTERP1; /*!< (@ 0x40048214) Start logic signal enable register 1; peripheral interrupts */
+ __IO uint32_t STARTRSRP1CLR; /*!< (@ 0x40048218) Start logic reset register 1; peripheral interrupts */
+ __I uint32_t STARTSRP1; /*!< (@ 0x4004821C) Start logic status register 1; peripheral interrupts */
+ __I uint32_t RESERVED11[4];
+ __IO uint32_t PDSLEEPCFG; /*!< (@ 0x40048230) Power-down states in Deep-sleep mode */
+ __IO uint32_t PDAWAKECFG; /*!< (@ 0x40048234) Power-down states after wake-up from Deep-sleep mode */
+ __IO uint32_t PDRUNCFG; /*!< (@ 0x40048238) Power-down configuration register */
+ __I uint32_t RESERVED12[110];
+ __I uint32_t DEVICE_ID; /*!< (@ 0x400483F4) Device ID */
+} LPC_SYSCON_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- MICRO_DMA -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x General purpose micro DMA controller Modification date=2/10/2011 Major revision=0 Minor revision=17 (MICRO_DMA)
+ */
+
+typedef struct { /*!< (@ 0x4004C000) MICRO_DMA Structure */
+ __I uint32_t DMA_STATUS; /*!< (@ 0x4004C000) DMA status register */
+ __IO uint32_t DMA_CFG; /*!< (@ 0x4004C004) DMA configuration register */
+ __IO uint32_t CTRL_BASE_PTR; /*!< (@ 0x4004C008) Channel control base pointer register */
+ __I uint32_t ATL_CTRL_BASE_PTR; /*!< (@ 0x4004C00C) Channel alternate control base pointer register */
+ __I uint32_t DMA_WAITONREQ_STATUS; /*!< (@ 0x4004C010) Channel wait on request status register */
+ __IO uint32_t CHNL_SW_REQUEST; /*!< (@ 0x4004C014) Channel software request register */
+ __IO uint32_t CHNL_USEBURST_SET; /*!< (@ 0x4004C018) Channel useburst set register */
+ __IO uint32_t CHNL_USEBURST_CLR; /*!< (@ 0x4004C01C) Channel useburst clear register */
+ __IO uint32_t CHNL_REQ_MASK_SET; /*!< (@ 0x4004C020) Channel request mask set register */
+ __IO uint32_t CHNL_REQ_MASK_CLR; /*!< (@ 0x4004C024) Channel request mask clear register */
+ __IO uint32_t CHNL_ENABLE_SET; /*!< (@ 0x4004C028) Channel enable set register */
+ __IO uint32_t CHNL_ENABLE_CLR; /*!< (@ 0x4004C02C) Channel enable clear register */
+ __IO uint32_t CHNL_PRI_ALT_SET; /*!< (@ 0x4004C030) Channel primary-alternate set register */
+ __IO uint32_t CHNL_PRI_ALT_CLR; /*!< (@ 0x4004C034) Channel primary-alternate clear register */
+ __IO uint32_t CHNL_PRIORITY_SET; /*!< (@ 0x4004C038) Channel priority set register */
+ __IO uint32_t CHNL_PRIORITY_CLR; /*!< (@ 0x4004C03C) Channel priority clear register */
+ __I uint32_t RESERVED0[3];
+ __IO uint32_t ERR_CLR; /*!< (@ 0x4004C04C) Bus error clear register */
+ __I uint32_t RESERVED1[12];
+ __IO uint32_t CHNL_IRQ_STATUS; /*!< (@ 0x4004C080) Channel DMA interrupt status register */
+ __IO uint32_t IRQ_ERR_ENABLE; /*!< (@ 0x4004C084) DMA error interrupt enable register */
+ __IO uint32_t CHNL_IRQ_ENABLE; /*!< (@ 0x4004C088) Channel DMA interrupt enable register */
+} LPC_MICRO_DMA_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- RTC -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x Real-Time Clock (RTC) Modification date=2/11/2011 Major revision=1 Minor revision=0 (RTC)
+ */
+
+typedef struct { /*!< (@ 0x40050000) RTC Structure */
+ __I uint32_t DR; /*!< (@ 0x40050000) Data register */
+ __IO uint32_t MR; /*!< (@ 0x40050004) Match register */
+ __IO uint32_t LR; /*!< (@ 0x40050008) Load register */
+ __IO uint32_t CR; /*!< (@ 0x4005000C) Control register */
+ __IO uint32_t ICSC; /*!< (@ 0x40050010) Interrupt control set/clear register */
+ __I uint32_t RIS; /*!< (@ 0x40050014) Raw interrupt status register */
+ __I uint32_t MIS; /*!< (@ 0x40050018) Masked interrupt status register */
+ __IO uint32_t ICR; /*!< (@ 0x4005001C) Interrupt clear register */
+} LPC_RTC_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- ACOMP -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x Comparator Modification date=2/11/2011 Major revision=0 Minor revision=17 (ACOMP)
+ */
+
+typedef struct { /*!< (@ 0x40054000) ACOMP Structure */
+ __IO uint32_t CMP; /*!< (@ 0x40054000) Comparator control register */
+ __IO uint32_t VLAD; /*!< (@ 0x40054004) Voltage ladder register */
+} LPC_ACOMP_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- GPIO0/1/2 -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x General Purpose I/O (GPIO) Modification date=2/11/2011 Major revision=0 Minor revision=17 (GPIO0)
+ */
+
+typedef struct { /*!< (@ 0x500X0000) GPIO0 Structure */
+ __IO uint32_t MASK; /*!< (@ 0x500X0000) Pin value mask register. Affects operations on PIN, OUT, SET, CLR, and NOT registers. */
+ __I uint32_t PIN; /*!< (@ 0x500X0004) Pin value register. */
+ __IO uint32_t OUT; /*!< (@ 0x500X0008) Pin output value register. */
+ __IO uint32_t SET; /*!< (@ 0x500X000C) Pin output value set register. */
+ __IO uint32_t CLR; /*!< (@ 0x500X0010) Pin output value clear register. */
+ __IO uint32_t NOT; /*!< (@ 0x500X0014) Pin output value invert register. */
+ __I uint32_t RESERVED0[2];
+ __IO uint32_t DIR; /*!< (@ 0x500X0020) Data direction register. */
+ __IO uint32_t IS; /*!< (@ 0x500X0024) Interrupt sense register. */
+ __IO uint32_t IBE; /*!< (@ 0x500X0028) Interrupt both edges register. */
+ __IO uint32_t IEV; /*!< (@ 0x500X002C) Interrupt event register. */
+ __IO uint32_t IE; /*!< (@ 0x500X0030) Interrupt mask register. */
+ __I uint32_t RIS; /*!< (@ 0x500X0034) Raw interrupt status register. */
+ __I uint32_t MIS; /*!< (@ 0x500X0038) Masked interrupt status register. */
+ __IO uint32_t IC; /*!< (@ 0x5000003C) Interrupt clear register. */
+} LPC_GPIO_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- FLASHCTRL -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x System control (SYSCON) Modification date=2/16/2011 Major revision=1 Minor revision=0 (FLASHCTRL)
+ */
+
+typedef struct { /*!< (@ 0x50060000) FLASHCTRL Structure */
+ __I uint32_t RESERVED0[10];
+ __IO uint32_t FLASHCFG; /*!< (@ 0x50060028) Flash read cycle configuration */
+} LPC_FLASHCTRL_Type;
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- CRC -----
+// ------------------------------------------------------------------------------------------------
+
+
+/**
+ * @brief Product name title=UM10441 Chapter title=LPC122x CRC engine Modification date=2/11/2011 Major revision=0 Minor revision=17 (CRC)
+ */
+
+typedef struct { /*!< (@ 0x50070000) CRC Structure */
+ __IO uint32_t MODE; /*!< (@ 0x50070000) CRC mode register */
+ __IO uint32_t SEED; /*!< (@ 0x50070004) CRC seed register */
+
+ union {
+ union{
+ __O uint8_t WR_DATA_8; /*!< (@ 0x50070008) CRC 8-bit data register */
+ __O uint16_t WR_DATA_16; /*!< (@ 0x50070008) CRC 16-bit data register */
+ __O uint32_t WR_DATA_32; /*!< (@ 0x50070008) CRC 32-bit data register */
+ };
+ __I uint32_t SUM; /*!< (@ 0x50070008) CRC checksum register */
+ };
+} LPC_CRC_Type;
+
+
+#if defined ( __CC_ARM )
+ #pragma no_anon_unions
+#endif
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- Peripheral memory map -----
+// ------------------------------------------------------------------------------------------------
+
+#define LPC_I2C_BASE (0x40000000)
+#define LPC_WWDT_BASE (0x40004000)
+#define LPC_UART0_BASE (0x40008000)
+#define LPC_UART1_BASE (0x4000C000)
+#define LPC_CT16B0_BASE (0x40010000)
+#define LPC_CT16B1_BASE (0x40014000)
+#define LPC_CT32B0_BASE (0x40018000)
+#define LPC_CT32B1_BASE (0x4001C000)
+#define LPC_ADC_BASE (0x40020000)
+#define LPC_PMU_BASE (0x40038000)
+#define LPC_SSP_BASE (0x40040000)
+#define LPC_IOCON_BASE (0x40044000)
+#define LPC_SYSCON_BASE (0x40048000)
+#define LPC_MICRO_DMA_BASE (0x4004C000)
+#define LPC_RTC_BASE (0x40050000)
+#define LPC_ACOMP_BASE (0x40054000)
+#define LPC_GPIO0_BASE (0x50000000)
+#define LPC_GPIO1_BASE (0x50010000)
+#define LPC_GPIO2_BASE (0x50020000)
+#define LPC_FLASHCTRL_BASE (0x50060000)
+#define LPC_CRC_BASE (0x50070000)
+
+
+// ------------------------------------------------------------------------------------------------
+// ----- Peripheral declaration -----
+// ------------------------------------------------------------------------------------------------
+
+#define LPC_I2C ((LPC_I2C_Type *) LPC_I2C_BASE)
+#define LPC_WWDT ((LPC_WWDT_Type *) LPC_WWDT_BASE)
+#define LPC_UART0 ((LPC_UART0_Type *) LPC_UART0_BASE)
+#define LPC_UART1 ((LPC_UART1_Type *) LPC_UART1_BASE)
+#define LPC_CT16B0 ((LPC_CTxxBx_Type *) LPC_CT16B0_BASE)
+#define LPC_CT16B1 ((LPC_CTxxBx_Type *) LPC_CT16B1_BASE)
+#define LPC_CT32B0 ((LPC_CTxxBx_Type *) LPC_CT32B0_BASE)
+#define LPC_CT32B1 ((LPC_CTxxBx_Type *) LPC_CT32B1_BASE)
+#define LPC_ADC ((LPC_ADC_Type *) LPC_ADC_BASE)
+#define LPC_PMU ((LPC_PMU_Type *) LPC_PMU_BASE)
+#define LPC_SSP ((LPC_SSP_Type *) LPC_SSP_BASE)
+#define LPC_IOCON ((LPC_IOCON_Type *) LPC_IOCON_BASE)
+#define LPC_SYSCON ((LPC_SYSCON_Type *) LPC_SYSCON_BASE)
+#define LPC_MICRO_DMA ((LPC_MICRO_DMA_Type *) LPC_MICRO_DMA_BASE)
+#define LPC_RTC ((LPC_RTC_Type *) LPC_RTC_BASE)
+#define LPC_ACOMP ((LPC_ACOMP_Type *) LPC_ACOMP_BASE)
+#define LPC_GPIO0 ((LPC_GPIO_Type *) LPC_GPIO0_BASE)
+#define LPC_GPIO1 ((LPC_GPIO_Type *) LPC_GPIO1_BASE)
+#define LPC_GPIO2 ((LPC_GPIO_Type *) LPC_GPIO2_BASE)
+#define LPC_FLASHCTRL ((LPC_FLASHCTRL_Type *) LPC_FLASHCTRL_BASE)
+#define LPC_CRC ((LPC_CRC_Type *) LPC_CRC_BASE)
+
+
+/** @} */ /* End of group Device_Peripheral_Registers */
+/** @} */ /* End of group (null) */
+/** @} */ /* End of group LPC122x */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // __LPC122X_H__
diff --git a/os/hal/platforms/LPC122x/gpt_lld.c b/os/hal/platforms/LPC122x/gpt_lld.c
new file mode 100644
index 000000000..86ea73759
--- /dev/null
+++ b/os/hal/platforms/LPC122x/gpt_lld.c
@@ -0,0 +1,338 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file LPC122x/gpt_lld.c
+ * @brief LPC122x GPT subsystem low level driver source.
+ *
+ * @addtogroup GPT
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if HAL_USE_GPT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief GPT1 driver identifier.
+ * @note The driver GPT1 allocates the complex timer CT16B0 when enabled.
+ */
+#if LPC122x_GPT_USE_CT16B0 || defined(__DOXYGEN__)
+GPTDriver GPTD1;
+#endif
+
+/**
+ * @brief GPT2 driver identifier.
+ * @note The driver GPT2 allocates the timer CT16B1 when enabled.
+ */
+#if LPC122x_GPT_USE_CT16B1 || defined(__DOXYGEN__)
+GPTDriver GPTD2;
+#endif
+
+/**
+ * @brief GPT3 driver identifier.
+ * @note The driver GPT3 allocates the timer CT32B0 when enabled.
+ */
+#if LPC122x_GPT_USE_CT32B0 || defined(__DOXYGEN__)
+GPTDriver GPTD3;
+#endif
+
+/**
+ * @brief GPT4 driver identifier.
+ * @note The driver GPT4 allocates the timer CT32B1 when enabled.
+ */
+#if LPC122x_GPT_USE_CT32B1 || defined(__DOXYGEN__)
+GPTDriver GPTD4;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Shared IRQ handler.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ */
+static void gpt_lld_serve_interrupt(GPTDriver *gptp) {
+
+ gptp->tmr->IR = 1; /* Clear interrupt on match MR0.*/
+ if (gptp->state == GPT_ONESHOT) {
+ gptp->state = GPT_READY; /* Back in GPT_READY state. */
+ gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */
+ }
+ gptp->config->callback(gptp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if LPC122x_GPT_USE_CT16B0
+/**
+ * @brief CT16B0 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(Vector74) {
+
+ CH_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD1);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* LPC122x_GPT_USE_CT16B0 */
+
+#if LPC122x_GPT_USE_CT16B1
+/**
+ * @brief CT16B1 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(Vector78) {
+
+ CH_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD2);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* LPC122x_GPT_USE_CT16B0 */
+
+#if LPC122x_GPT_USE_CT32B0
+/**
+ * @brief CT32B0 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(Vector7C) {
+
+ CH_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD3);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* LPC122x_GPT_USE_CT32B0 */
+
+#if LPC122x_GPT_USE_CT32B1
+/**
+ * @brief CT32B1 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(Vector80) {
+
+ CH_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD4);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif /* LPC122x_GPT_USE_CT32B1 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level GPT driver initialization.
+ *
+ * @notapi
+ */
+void gpt_lld_init(void) {
+
+#if LPC122x_GPT_USE_CT16B0
+ /* Driver initialization.*/
+ GPTD1.tmr = LPC_CT16B0;
+ gptObjectInit(&GPTD1);
+#endif
+
+#if LPC122x_GPT_USE_CT16B1
+ /* Driver initialization.*/
+ GPTD2.tmr = LPC_CT16B1;
+ gptObjectInit(&GPTD2);
+#endif
+
+#if LPC122x_GPT_USE_CT32B0
+ /* Driver initialization.*/
+ GPTD3.tmr = LPC_CT32B0;
+ gptObjectInit(&GPTD3);
+#endif
+
+#if LPC122x_GPT_USE_CT32B1
+ /* Driver initialization.*/
+ GPTD4.tmr = LPC_CT32B1;
+ gptObjectInit(&GPTD4);
+#endif
+}
+
+/**
+ * @brief Configures and activates the GPT peripheral.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_start(GPTDriver *gptp) {
+ uint32_t pr;
+
+ if (gptp->state == GPT_STOP) {
+ /* Clock activation.*/
+#if LPC122x_GPT_USE_CT16B0
+ if (&GPTD1 == gptp) {
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7);
+ nvicEnableVector(TIMER_16_0_IRQn, CORTEX_PRIORITY_MASK(2));
+ }
+#endif
+#if LPC122x_GPT_USE_CT16B1
+ if (&GPTD2 == gptp) {
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8);
+ nvicEnableVector(TIMER_16_1_IRQn, CORTEX_PRIORITY_MASK(3));
+ }
+#endif
+#if LPC122x_GPT_USE_CT32B0
+ if (&GPTD3 == gptp) {
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9);
+ nvicEnableVector(TIMER_32_0_IRQn, CORTEX_PRIORITY_MASK(2));
+ }
+#endif
+#if LPC122x_GPT_USE_CT32B1
+ if (&GPTD4 == gptp) {
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 10);
+ nvicEnableVector(TIMER_32_1_IRQn, CORTEX_PRIORITY_MASK(2));
+ }
+#endif
+ }
+
+ /* Prescaler value calculation.*/
+ pr = (uint16_t)((LPC122x_SYSCLK / gptp->config->frequency) - 1);
+ chDbgAssert(((uint32_t)(pr + 1) * gptp->config->frequency) == LPC122x_SYSCLK,
+ "gpt_lld_start(), #1", "invalid frequency");
+
+ /* Timer configuration.*/
+ gptp->tmr->PR = pr;
+ gptp->tmr->IR = 1;
+ gptp->tmr->MCR = 0;
+ gptp->tmr->TCR = 0;
+}
+
+/**
+ * @brief Deactivates the GPT peripheral.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_stop(GPTDriver *gptp) {
+
+ if (gptp->state == GPT_READY) {
+ gptp->tmr->MCR = 0;
+ gptp->tmr->TCR = 0;
+
+#if LPC122x_GPT_USE_CT16B0
+ if (&GPTD1 == gptp) {
+ nvicDisableVector(TIMER_16_0_IRQn);
+ LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 7);
+ }
+#endif
+#if LPC122x_GPT_USE_CT16B1
+ if (&GPTD2 == gptp) {
+ nvicDisableVector(TIMER_16_1_IRQn);
+ LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 8);
+ }
+#endif
+#if LPC122x_GPT_USE_CT32B0
+ if (&GPTD3 == gptp) {
+ nvicDisableVector(TIMER_32_0_IRQn);
+ LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 9);
+ }
+#endif
+#if LPC122x_GPT_USE_CT32B1
+ if (&GPTD4 == gptp) {
+ nvicDisableVector(TIMER_32_1_IRQn);
+ LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 10);
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts the timer in continuous mode.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval period in ticks
+ *
+ * @notapi
+ */
+void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
+
+ gptp->tmr->MR0 = interval - 1;
+ gptp->tmr->IR = 1;
+ gptp->tmr->MCR = 3; /* IRQ and clr TC on match MR0. */
+ gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
+ gptp->tmr->TCR = 1; /* Timer enabled. */
+}
+
+/**
+ * @brief Stops the timer.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_stop_timer(GPTDriver *gptp) {
+
+ gptp->tmr->IR = 1;
+ gptp->tmr->MCR = 0;
+ gptp->tmr->TCR = 0;
+}
+
+/**
+ * @brief Starts the timer in one shot mode and waits for completion.
+ * @details This function specifically polls the timer waiting for completion
+ * in order to not have extra delays caused by interrupt servicing,
+ * this function is only recommended for short delays.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval time interval in ticks
+ *
+ * @notapi
+ */
+void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
+
+ gptp->tmr->MR0 = interval - 1;
+ gptp->tmr->IR = 1;
+ gptp->tmr->MCR = 4; /* Stop TC on match MR0. */
+ gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
+ gptp->tmr->TCR = 1; /* Timer enabled. */
+ while (gptp->tmr->TCR & 1)
+ ;
+}
+
+#endif /* HAL_USE_GPT */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/gpt_lld.h b/os/hal/platforms/LPC122x/gpt_lld.h
new file mode 100644
index 000000000..e38fe17c1
--- /dev/null
+++ b/os/hal/platforms/LPC122x/gpt_lld.h
@@ -0,0 +1,204 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file LPC122x/gpt_lld.h
+ * @brief LPC122x GPT subsystem low level driver header.
+ *
+ * @addtogroup GPT
+ * @{
+ */
+
+#ifndef _GPT_LLD_H_
+#define _GPT_LLD_H_
+
+#if HAL_USE_GPT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief GPT1 driver enable switch.
+ * @details If set to @p TRUE the support for GPT1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LPC122x_GPT_USE_CT16B0) || defined(__DOXYGEN__)
+#define LPC122x_GPT_USE_CT16B0 TRUE
+#endif
+
+/**
+ * @brief GPT2 driver enable switch.
+ * @details If set to @p TRUE the support for GPT2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LPC122x_GPT_USE_CT16B1) || defined(__DOXYGEN__)
+#define LPC122x_GPT_USE_CT16B1 TRUE
+#endif
+
+/**
+ * @brief GPT3 driver enable switch.
+ * @details If set to @p TRUE the support for GPT3 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LPC122x_GPT_USE_CT32B0) || defined(__DOXYGEN__)
+#define LPC122x_GPT_USE_CT32B0 TRUE
+#endif
+
+/**
+ * @brief GPT4 driver enable switch.
+ * @details If set to @p TRUE the support for GPT4 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LPC122x_GPT_USE_CT32B1) || defined(__DOXYGEN__)
+#define LPC122x_GPT_USE_CT32B1 TRUE
+#endif
+
+/**
+ * @brief GPT1 interrupt priority level setting.
+ */
+#if !defined(LPC122x_GPT_CT16B0_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define LPC122x_GPT_CT16B0_IRQ_PRIORITY 2
+#endif
+
+/**
+ * @brief GPT2 interrupt priority level setting.
+ */
+#if !defined(LPC122x_GPT_CT16B1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define LPC122x_GPT_CT16B1_IRQ_PRIORITY 2
+#endif
+
+/**
+ * @brief GPT3 interrupt priority level setting.
+ */
+#if !defined(LPC122x_GPT_CT32B0_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define LPC122x_GPT_CT32B0_IRQ_PRIORITY 2
+#endif
+
+/**
+ * @brief GPT4 interrupt priority level setting.
+ */
+#if !defined(LPC122x_GPT_CT32B1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define LPC122x_GPT_CT32B1_IRQ_PRIORITY 2
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !LPC122x_GPT_USE_CT16B0 && !LPC122x_GPT_USE_CT16B1 && \
+ !LPC122x_GPT_USE_CT32B0 && !LPC122x_GPT_USE_CT32B1
+#error "GPT driver activated but no CT peripheral assigned"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief GPT frequency type.
+ */
+typedef uint32_t gptfreq_t;
+
+/**
+ * @brief GPT counter type.
+ */
+typedef uint32_t gptcnt_t;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Timer clock in Hz.
+ * @note The low level can use assertions in order to catch invalid
+ * frequency specifications.
+ */
+ gptfreq_t frequency;
+ /**
+ * @brief Timer callback pointer.
+ * @note This callback is invoked on GPT counter events.
+ */
+ gptcallback_t callback;
+ /* End of the mandatory fields.*/
+} GPTConfig;
+
+/**
+ * @brief Structure representing a GPT driver.
+ */
+struct GPTDriver {
+ /**
+ * @brief Driver state.
+ */
+ gptstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const GPTConfig *config;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the CTxxBy registers block.
+ */
+ LPC_CTxxBx_Type *tmr;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if LPC122x_GPT_USE_CT16B0 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD1;
+#endif
+
+#if LPC122x_GPT_USE_CT16B1 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD2;
+#endif
+
+#if LPC122x_GPT_USE_CT32B0 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD3;
+#endif
+
+#if LPC122x_GPT_USE_CT32B1 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD4;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void gpt_lld_init(void);
+ void gpt_lld_start(GPTDriver *gptp);
+ void gpt_lld_stop(GPTDriver *gptp);
+ void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
+ void gpt_lld_stop_timer(GPTDriver *gptp);
+ void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_GPT */
+
+#endif /* _GPT_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/hal_lld.c b/os/hal/platforms/LPC122x/hal_lld.c
new file mode 100644
index 000000000..9069434ba
--- /dev/null
+++ b/os/hal/platforms/LPC122x/hal_lld.c
@@ -0,0 +1,123 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file LPC122x/hal_lld.c
+ * @brief LPC122x HAL subsystem low level driver source.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level HAL driver initialization.
+ *
+ * @notapi
+ */
+void hal_lld_init(void) {
+
+ /* SysTick initialization using the system clock.*/
+ nvicSetSystemHandlerPriority(HANDLER_SYSTICK, CORTEX_PRIORITY_SYSTICK);
+ SysTick->LOAD = LPC122x_SYSCLK / CH_FREQUENCY - 1;
+ SysTick->VAL = 0;
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_ENABLE_Msk |
+ SysTick_CTRL_TICKINT_Msk;
+}
+
+/**
+ * @brief LPC122x clocks and PLL initialization.
+ * @note All the involved constants come from the file @p board.h.
+ * @note This function must be invoked only after the system reset.
+ *
+ * @special
+ */
+void lpc122x_clock_init(void) {
+ unsigned i;
+
+ LPC_WWDT->MOD = 0; /* Disable Watchdog */
+ LPC_WWDT->FEED = 0xAA;
+ LPC_WWDT->FEED = 0x55;
+
+#if LPC122x_FLASHCFG_FLASHTIM == 0
+ LPC_SYSCON->PRESETCTRL |= (1 << 15); /* Flash 1-cycle read mode */
+#else
+ LPC_FLASHCTRL->FLASHCFG = 0; /* 2 system clock cycles flash access time */
+ LPC_SYSCON->PRESETCTRL &= ~(1 << 15); /* Flash multi-cycle read mode */
+#endif
+
+ /* System oscillator initialization if required.*/
+#if LPC122x_MAINCLK_SOURCE == SYSMAINCLKSEL_PLLOUT
+#if LPC122x_PLLCLK_SOURCE == SYSPLLCLKSEL_SYSOSC
+ LPC_SYSCON->SYSOSCCTRL = LPC122x_SYSOSCCTRL;
+ LPC_SYSCON->PDRUNCFG &= ~(1 << 5); /* System oscillator ON. */
+ for (i = 0; i < 200; i++)
+ __NOP(); /* Stabilization delay. */
+#endif /* LPC122x_PLLCLK_SOURCE == SYSPLLCLKSEL_SYSOSC */
+
+ /* PLL initialization if required.*/
+ LPC_SYSCON->SYSPLLCLKSEL = LPC122x_PLLCLK_SOURCE;
+ LPC_SYSCON->SYSPLLCLKUEN = 1; /* Really required? */
+ LPC_SYSCON->SYSPLLCLKUEN = 0;
+ LPC_SYSCON->SYSPLLCLKUEN = 1;
+ LPC_SYSCON->SYSPLLCTRL = LPC122x_SYSPLLCTRL_MSEL | LPC122x_SYSPLLCTRL_PSEL;
+ LPC_SYSCON->PDRUNCFG &= ~(1 << 7); /* System PLL ON. */
+ while ((LPC_SYSCON->SYSPLLSTAT & 1) == 0) /* Wait PLL lock. */
+ ;
+#endif /* LPC122x_MAINCLK_SOURCE == SYSMAINCLKSEL_PLLOUT */
+
+ /* Main clock source selection.*/
+ LPC_SYSCON->MAINCLKSEL = LPC122x_MAINCLK_SOURCE;
+ LPC_SYSCON->MAINCLKUEN = 1; /* Really required? */
+ LPC_SYSCON->MAINCLKUEN = 0;
+ LPC_SYSCON->MAINCLKUEN = 1;
+ while ((LPC_SYSCON->MAINCLKUEN & 1) == 0) /* Wait switch completion. */
+ ;
+
+ /* ABH divider initialization, peripheral clocks are initially disabled,
+ the various device drivers will handle their own setup except GPIO and
+ IOCON that are left enabled.*/
+ LPC_SYSCON->SYSAHBCLKDIV = LPC122x_SYSABHCLK_DIV;
+ LPC_SYSCON->SYSAHBCLKCTRL = 0xE009001F;
+
+ /* Memory remapping, vectors always in ROM.*/
+ LPC_SYSCON->SYSMEMREMAP = 2;
+}
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/hal_lld.h b/os/hal/platforms/LPC122x/hal_lld.h
new file mode 100644
index 000000000..35624962a
--- /dev/null
+++ b/os/hal/platforms/LPC122x/hal_lld.h
@@ -0,0 +1,217 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file LPC122x/hal_lld.h
+ * @brief HAL subsystem low level driver header template.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef _HAL_LLD_H_
+#define _HAL_LLD_H_
+
+#include "LPC122x.h"
+#include "nvic.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Defines the support for realtime counters in the HAL.
+ */
+#define HAL_IMPLEMENTS_COUNTERS FALSE
+
+/**
+ * @brief Platform name.
+ */
+#define PLATFORM_NAME "LPC122x"
+
+#define IRCOSCCLK 12000000 /**< High speed internal clock. */
+#define WDGOSCCLK 1600000 /**< Watchdog internal clock. */
+
+#define SYSPLLCLKSEL_IRCOSC 0 /**< Internal RC oscillator
+ clock source. */
+#define SYSPLLCLKSEL_SYSOSC 1 /**< System oscillator clock
+ source. */
+
+#define SYSMAINCLKSEL_IRCOSC 0 /**< Clock source is IRC. */
+#define SYSMAINCLKSEL_PLLIN 1 /**< Clock source is PLLIN. */
+#define SYSMAINCLKSEL_WDGOSC 2 /**< Clock source is WDGOSC. */
+#define SYSMAINCLKSEL_PLLOUT 3 /**< Clock source is PLLOUT. */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief System PLL clock source.
+ */
+#if !defined(LPC122x_PLLCLK_SOURCE) || defined(__DOXYGEN__)
+#define LPC122x_PLLCLK_SOURCE SYSPLLCLKSEL_SYSOSC
+#endif
+
+/**
+ * @brief System PLL multiplier.
+ * @note The value must be in the 1..32 range and the final frequency
+ * must not exceed the CCO ratings.
+ */
+#if !defined(LPC122x_SYSPLL_MUL) || defined(__DOXYGEN__)
+#define LPC122x_SYSPLL_MUL 2
+#endif
+
+/**
+ * @brief System PLL divider.
+ * @note The value must be chosen between (2, 4, 8, 16).
+ */
+#if !defined(LPC122x_SYSPLL_DIV) || defined(__DOXYGEN__)
+#define LPC122x_SYSPLL_DIV 8
+#endif
+
+/**
+ * @brief System main clock source.
+ */
+#if !defined(LPC122x_MAINCLK_SOURCE) || defined(__DOXYGEN__)
+#define LPC122x_MAINCLK_SOURCE SYSMAINCLKSEL_PLLOUT
+#endif
+
+/**
+ * @brief AHB clock divider.
+ * @note The value must be chosen between (1...255).
+ */
+#if !defined(LPC122x_SYSCLK_DIV) || defined(__DOXYGEN__)
+#define LPC122x_SYSABHCLK_DIV 1
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/**
+ * @brief Calculated SYSOSCCTRL setting.
+ */
+#if (SYSOSCCLK < 18000000) || defined(__DOXYGEN__)
+#define LPC122x_SYSOSCCTRL 0
+#else
+#define LPC122x_SYSOSCCTRL 1
+#endif
+
+/**
+ * @brief PLL input clock frequency.
+ */
+#if (LPC122x_PLLCLK_SOURCE == SYSPLLCLKSEL_SYSOSC) || defined(__DOXYGEN__)
+#define LPC122x_SYSPLLCLKIN SYSOSCCLK
+#elif LPC122x_PLLCLK_SOURCE == SYSPLLCLKSEL_IRCOSC
+#define LPC122x_SYSPLLCLKIN IRCOSCCLK
+#else
+#error "invalid LPC122x_PLLCLK_SOURCE clock source specified"
+#endif
+
+/**
+ * @brief MSEL mask in SYSPLLCTRL register.
+ */
+#if (LPC122x_SYSPLL_MUL >= 1) && (LPC122x_SYSPLL_MUL <= 32) || \
+ defined(__DOXYGEN__)
+#define LPC122x_SYSPLLCTRL_MSEL (LPC122x_SYSPLL_MUL - 1)
+#else
+#error "LPC122x_SYSPLL_MUL out of range (1...32)"
+#endif
+
+/**
+ * @brief PSEL mask in SYSPLLCTRL register.
+ */
+#if (LPC122x_SYSPLL_DIV == 2) || defined(__DOXYGEN__)
+#define LPC122x_SYSPLLCTRL_PSEL (0 << 5)
+#elif LPC122x_SYSPLL_DIV == 4
+#define LPC122x_SYSPLLCTRL_PSEL (1 << 5)
+#elif LPC122x_SYSPLL_DIV == 8
+#define LPC122x_SYSPLLCTRL_PSEL (2 << 5)
+#elif LPC122x_SYSPLL_DIV == 16
+#define LPC122x_SYSPLLCTRL_PSEL (3 << 5)
+#else
+#error "invalid LPC122x_SYSPLL_DIV value (2,4,8,16)"
+#endif
+
+/**
+ * @brief CCP frequency.
+ */
+#define LPC122x_SYSPLLCCO (LPC122x_SYSPLLCLKIN * LPC122x_SYSPLL_MUL * \
+ LPC122x_SYSPLL_DIV)
+
+#if (LPC122x_SYSPLLCCO < 156000000) || (LPC122x_SYSPLLCCO > 320000000)
+#error "CCO frequency out of the acceptable range (156...320)"
+#endif
+
+/**
+ * @brief PLL output clock frequency.
+ */
+#define LPC122x_SYSPLLCLKOUT (LPC122x_SYSPLLCCO / LPC122x_SYSPLL_DIV)
+
+#if (LPC122x_MAINCLK_SOURCE == SYSMAINCLKSEL_IRCOSC) || defined(__DOXYGEN__)
+#define LPC122x_MAINCLK IRCOSCCLK
+#elif LPC122x_MAINCLK_SOURCE == SYSMAINCLKSEL_PLLIN
+#define LPC122x_MAINCLK LPC122x_SYSPLLCLKIN
+#elif LPC122x_MAINCLK_SOURCE == SYSMAINCLKSEL_WDGOSC
+#define LPC122x_MAINCLK WDGOSCCLK
+#elif LPC122x_MAINCLK_SOURCE == SYSMAINCLKSEL_PLLOUT
+#define LPC122x_MAINCLK LPC122x_SYSPLLCLKOUT
+#else
+#error "invalid LPC122x_MAINCLK_SOURCE clock source specified"
+#endif
+
+/**
+ * @brief AHB clock.
+ */
+#define LPC122x_SYSCLK (LPC122x_MAINCLK / LPC122x_SYSABHCLK_DIV)
+#if LPC122x_SYSCLK > 45000000
+#error "AHB clock frequency out of the acceptable range (45MHz max)"
+#endif
+
+/**
+ * @brief Flash wait states.
+ */
+#if (LPC122x_SYSCLK <= 30000000) || defined(__DOXYGEN__)
+#define LPC122x_FLASHCFG_FLASHTIM 0
+#else
+#define LPC122x_FLASHCFG_FLASHTIM 1
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hal_lld_init(void);
+ void lpc122x_clock_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HAL_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/pal_lld.c b/os/hal/platforms/LPC122x/pal_lld.c
new file mode 100644
index 000000000..c23608a75
--- /dev/null
+++ b/os/hal/platforms/LPC122x/pal_lld.c
@@ -0,0 +1,154 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+
+/**
+ * @file LPC122x/pal_lld.c
+ * @brief LPC122x GPIO low level driver code.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+/**
+ * @brief LPC122x I/O ports configuration.
+ * @details GPIO unit registers initialization.
+ *
+ * @param[in] config the LPC122x ports configuration
+ *
+ * @notapi
+ */
+void _pal_lld_init(const PALConfig *config) {
+
+ LPC_GPIO0->DIR = config->P0.dir;
+ LPC_GPIO1->DIR = config->P1.dir;
+ LPC_GPIO2->DIR = config->P2.dir;
+ LPC_GPIO0->MASK = 0;
+ LPC_GPIO1->MASK = 0;
+ LPC_GPIO2->MASK = 0;
+ LPC_GPIO0->OUT = config->P0.data;
+ LPC_GPIO1->OUT = config->P1.data;
+ LPC_GPIO2->OUT = config->P2.data;
+}
+
+/**
+ * @brief Reads a group of bits.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @return The group logical states.
+ *
+ * @notapi
+ */
+uint32_t _pal_lld_readgroup(ioportid_t port,
+ ioportmask_t mask,
+ uint32_t offset) {
+
+ uint32_t p;
+
+ port->MASK = ~((mask) << offset);
+ p = port->PIN;
+ port->MASK = 0;
+ return p;
+}
+
+/**
+ * @brief Writes a group of bits.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] bits bits to be written. Values exceeding the group width
+ * are masked.
+ *
+ * @notapi
+ */
+void _pal_lld_writegroup(ioportid_t port,
+ ioportmask_t mask,
+ uint32_t offset,
+ uint32_t bits) {
+
+ port->MASK = ~((mask) << offset);
+ port->OUT = bits;
+ port->MASK = 0;
+}
+
+/**
+ * @brief Pads mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @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.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @notapi
+ */
+void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode) {
+
+ switch (mode) {
+ case PAL_MODE_RESET:
+ case PAL_MODE_INPUT:
+ port->DIR &= ~mask;
+ break;
+ case PAL_MODE_UNCONNECTED:
+ palSetPort(port, PAL_WHOLE_PORT);
+ case PAL_MODE_OUTPUT_PUSHPULL:
+ port->DIR |= mask;
+ break;
+ }
+}
+
+#endif /* HAL_USE_PAL */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/pal_lld.h b/os/hal/platforms/LPC122x/pal_lld.h
new file mode 100644
index 000000000..4cf870410
--- /dev/null
+++ b/os/hal/platforms/LPC122x/pal_lld.h
@@ -0,0 +1,337 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+
+/**
+ * @file LPC122x/pal_lld.h
+ * @brief LPC122x GPIO low level driver header.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#ifndef _PAL_LLD_H_
+#define _PAL_LLD_H_
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+#undef PAL_MODE_INPUT_PULLUP
+#undef PAL_MODE_INPUT_PULLDOWN
+#undef PAL_MODE_INPUT_ANALOG
+#undef PAL_MODE_OUTPUT_OPENDRAIN
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO port setup info.
+ */
+typedef struct {
+ /** Initial value for FIO_PIN register.*/
+ uint32_t data;
+ /** Initial value for FIO_DIR register.*/
+ uint32_t dir;
+} lpc122x_gpio_setup_t;
+
+/**
+ * @brief GPIO 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.
+ * @note The @p IOCON block is not configured, initially all pins have
+ * enabled pullups and are programmed as GPIO. It is responsibility
+ * of the various drivers to reprogram the pins in the proper mode.
+ * Pins that are not handled by any driver may be programmed in
+ * @p board.c.
+ */
+typedef struct {
+ /** @brief GPIO 0 setup data.*/
+ lpc122x_gpio_setup_t P0;
+ /** @brief GPIO 1 setup data.*/
+ lpc122x_gpio_setup_t P1;
+ /** @brief GPIO 2 setup data.*/
+ lpc122x_gpio_setup_t P2;
+} PALConfig;
+
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 32
+
+/**
+ * @brief Whole port mask.
+ * @brief This macro specifies all the valid bits into a port.
+ */
+#define PAL_WHOLE_PORT ((ioportmask_t)0xFFF)
+
+/**
+ * @brief Digital I/O port sized unsigned type.
+ */
+typedef uint32_t ioportmask_t;
+
+/**
+ * @brief Digital I/O modes.
+ */
+typedef uint32_t iomode_t;
+
+/**
+ * @brief Port Identifier.
+ */
+typedef LPC_GPIO_Type *ioportid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO0 port identifier.
+ */
+#define IOPORT1 LPC_GPIO0
+#define GPIO0 LPC_GPIO0
+
+/**
+ * @brief GPIO1 port identifier.
+ */
+#define IOPORT2 LPC_GPIO1
+#define GPIO1 LPC_GPIO1
+
+/**
+ * @brief GPIO2 port identifier.
+ */
+#define IOPORT3 LPC_GPIO2
+#define GPIO2 LPC_GPIO2
+
+/*===========================================================================*/
+/* Implementation, some of the following macros could be implemented as */
+/* functions, if so please put them in pal_lld.c. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level PAL subsystem initialization.
+ *
+ * @param[in] config architecture-dependent ports configuration
+ *
+ * @notapi
+ */
+#define pal_lld_init(config) \
+ _pal_lld_init(config)
+
+/**
+ * @brief Reads the physical I/O port states.
+ *
+ * @param[in] port port identifier
+ * @return The port bits.
+ *
+ * @notapi
+ */
+#define pal_lld_readport(port) \
+ ((port)->PIN)
+
+/**
+ * @brief Reads the output latch.
+ * @details The purpose of this function is to read back the latched output
+ * value.
+ *
+ * @param[in] port port identifier
+ * @return The latched logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readlatch(port) \
+ ((port)->PIN)
+
+/**
+ * @brief Writes a bits mask on a I/O port.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be written on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_writeport(port, bits) \
+ ((port)->OUT = (bits))
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be ORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_setport(port, bits) \
+ ((port)->SET = (bits))
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be cleared on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_clearport(port, bits) \
+ ((port)->CLR = (bits))
+
+/**
+ * @brief Reads a group of bits.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @return The group logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readgroup(port, mask, offset) \
+ _pal_lld_readgroup(port, mask, offset)
+
+/**
+ * @brief Writes a group of bits.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] bits bits to be written. Values exceeding the group width
+ * are masked.
+ *
+ * @notapi
+ */
+#define pal_lld_writegroup(port, mask, offset, bits) \
+ _pal_lld_writegroup(port, mask, offset, bits)
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] mode group mode
+ *
+ * @notapi
+ */
+#define pal_lld_setgroupmode(port, mask, offset, mode) \
+ _pal_lld_setgroupmode(port, mask << offset, mode)
+
+/**
+ * @brief Writes a logical state on an output pad.
+ * @note This function is not meant to be invoked directly by the
+ * application code.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] bit logical value, the value must be @p PAL_LOW or
+ * @p PAL_HIGH
+ *
+ * @notapi
+ */
+#define pal_lld_writepad(port, pad, bit) \
+ ((bit) == PAL_LOW) ? pal_lld_clearpad(port, pad) : \
+ pal_lld_setpad(port, pad)
+
+/**
+ * @brief Sets a pad logical state to @p PAL_HIGH.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_setpad(port, pad) \
+ ((port)->SET = 1 << (pad))
+
+/**
+ * @brief Clears a pad logical state to @p PAL_LOW.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_clearpad(port, pad) \
+ ((port)->CLR = 1 << (pad))
+
+/**
+ * @brief Toggles a pad logical state.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_togglepad(port, pad) \
+ ((port)->NOT = 1 << (pad))
+
+#if !defined(__DOXYGEN__)
+extern const PALConfig pal_default_config;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _pal_lld_init(const PALConfig *config);
+ void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode);
+ uint32_t _pal_lld_readgroup(ioportid_t port,
+ ioportmask_t mask,
+ uint32_t offset);
+ void _pal_lld_writegroup(ioportid_t port,
+ ioportmask_t mask,
+ uint32_t offset,
+ uint32_t bits);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PAL */
+
+#endif /* _PAL_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/platform.mk b/os/hal/platforms/LPC122x/platform.mk
new file mode 100644
index 000000000..dbf5aaf48
--- /dev/null
+++ b/os/hal/platforms/LPC122x/platform.mk
@@ -0,0 +1,9 @@
+# List of all the LPC122x platform files.
+PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC122x/hal_lld.c \
+ ${CHIBIOS}/os/hal/platforms/LPC122x/gpt_lld.c \
+ ${CHIBIOS}/os/hal/platforms/LPC122x/pal_lld.c \
+ ${CHIBIOS}/os/hal/platforms/LPC122x/serial_lld.c \
+ ${CHIBIOS}/os/hal/platforms/LPC122x/spi_lld.c
+
+# Required include directories
+PLATFORMINC = ${CHIBIOS}/os/hal/platforms/LPC122x
diff --git a/os/hal/platforms/LPC122x/serial_lld.c b/os/hal/platforms/LPC122x/serial_lld.c
new file mode 100644
index 000000000..88ba5661f
--- /dev/null
+++ b/os/hal/platforms/LPC122x/serial_lld.c
@@ -0,0 +1,383 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file LPC122x/serial_lld.c
+ * @brief LPC122x low level serial driver code.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+#if LPC122x_SERIAL_USE_UART0 || defined(__DOXYGEN__)
+/** @brief UART0 serial driver identifier.*/
+SerialDriver SD1;
+#endif
+
+#if LPC122x_SERIAL_USE_UART1 || defined(__DOXYGEN__)
+/** @brief UART0 serial driver identifier.*/
+SerialDriver SD2;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/** @brief Driver default configuration.*/
+static const SerialConfig default_config = {
+ SERIAL_DEFAULT_BITRATE,
+ LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
+ FCR_TRIGGER0
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief UART initialization.
+ *
+ * @param[in] sdp communication channel associated to the UART
+ * @param[in] config the architecture-dependent serial driver configuration
+ */
+static void uart_init(SerialDriver *sdp, const SerialConfig *config) {
+ LPC_UART0_Type *u = sdp->uart;
+ uint32_t upclk;
+#if LPC122x_SERIAL_USE_UART0
+ if (&SD1 == sdp) {
+ upclk = LPC122x_SERIAL_UART0_PCLK;
+ }
+#endif
+#if LPC122x_SERIAL_USE_UART1
+ if (&SD2 == sdp) {
+ upclk = LPC122x_SERIAL_UART1_PCLK;
+ }
+#endif
+ uint32_t div = upclk / (config->sc_speed << 4);
+ u->LCR = config->sc_lcr | LCR_DLAB;
+ u->DLL = div;
+ u->DLM = div >> 8;
+ u->LCR = config->sc_lcr;
+ u->FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | config->sc_fcr;
+ u->ACR = 0;
+ u->FDR = 0x10;
+ u->TER = TER_ENABLE;
+ u->IER = IER_RBR | IER_STATUS;
+}
+
+/**
+ * @brief UART de-initialization.
+ *
+ * @param[in] u pointer to an UART I/O block
+ */
+static void uart_deinit(LPC_UART0_Type *u) {
+
+ u->LCR = LCR_DLAB;
+ u->DLL = 1;
+ u->DLM = 0;
+ u->LCR = 0;
+ u->FDR = 0x10;
+ u->IER = 0;
+ u->FCR = FCR_RXRESET | FCR_TXRESET;
+ u->ACR = 0;
+ u->TER = TER_ENABLE;
+}
+
+/**
+ * @brief Error handling routine.
+ *
+ * @param[in] sdp communication channel associated to the UART
+ * @param[in] err UART LSR register value
+ */
+static void set_error(SerialDriver *sdp, IOREG32 err) {
+ flagsmask_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();
+ chnAddFlagsI(sdp, sts);
+ chSysUnlockFromIsr();
+}
+
+/**
+ * @brief Common IRQ handler.
+ * @note Tries hard to clear all the pending interrupt sources, we don't
+ * want to go through the whole ISR and have another interrupt soon
+ * after.
+ *
+ * @param[in] u pointer to an UART I/O block
+ * @param[in] sdp communication channel associated to the UART
+ */
+static void serve_interrupt(SerialDriver *sdp) {
+ LPC_UART0_Type *u = sdp->uart;
+
+ while (TRUE) {
+ switch (u->IIR & IIR_SRC_MASK) {
+ case IIR_SRC_NONE:
+ return;
+ case IIR_SRC_ERROR:
+ set_error(sdp, u->LSR);
+ break;
+ case IIR_SRC_TIMEOUT:
+ case IIR_SRC_RX:
+ chSysLockFromIsr();
+ if (chIQIsEmptyI(&sdp->iqueue))
+ chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
+ chSysUnlockFromIsr();
+ while (u->LSR & LSR_RBR_FULL) {
+ chSysLockFromIsr();
+ if (chIQPutI(&sdp->iqueue, u->RBR) < Q_OK)
+ chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
+ chSysUnlockFromIsr();
+ }
+ break;
+ case IIR_SRC_TX:
+ {
+ int i = LPC122x_SERIAL_FIFO_PRELOAD;
+ do {
+ msg_t b;
+
+ chSysLockFromIsr();
+ b = chOQGetI(&sdp->oqueue);
+ chSysUnlockFromIsr();
+ if (b < Q_OK) {
+ u->IER &= ~IER_THRE;
+ chSysLockFromIsr();
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ chSysUnlockFromIsr();
+ break;
+ }
+ u->THR = b;
+ } while (--i);
+ }
+ break;
+ default:
+ (void) u->THR;
+ (void) u->RBR;
+ }
+ }
+}
+
+/**
+ * @brief Attempts a TX FIFO preload.
+ */
+static void preload(SerialDriver *sdp) {
+ LPC_UART0_Type *u = sdp->uart;
+
+ if (u->LSR & LSR_THRE) {
+ int i = LPC122x_SERIAL_FIFO_PRELOAD;
+ do {
+ msg_t b = chOQGetI(&sdp->oqueue);
+ if (b < Q_OK) {
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ return;
+ }
+ u->THR = b;
+ } while (--i);
+ }
+ u->IER |= IER_THRE;
+}
+
+/**
+ * @brief Driver SD1 output notification.
+ */
+#if LPC122x_SERIAL_USE_UART0 || defined(__DOXYGEN__)
+static void notify1(GenericQueue *qp) {
+
+ (void)qp;
+ preload(&SD1);
+}
+#endif
+
+/**
+ * @brief Driver SD2 output notification.
+ */
+#if LPC122x_SERIAL_USE_UART1 || defined(__DOXYGEN__)
+static void notify2(GenericQueue *qp) {
+
+ (void)qp;
+ preload(&SD2);
+}
+#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief UART0 IRQ handler.
+ *
+ * @isr
+ */
+#if LPC122x_SERIAL_USE_UART0 || defined(__DOXYGEN__)
+CH_IRQ_HANDLER(Vector88) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD1);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif
+
+/**
+ * @brief UART0 IRQ handler.
+ *
+ * @isr
+ */
+#if LPC122x_SERIAL_USE_UART1 || defined(__DOXYGEN__)
+CH_IRQ_HANDLER(Vector8C) {
+
+ CH_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD2);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level serial driver initialization.
+ *
+ * @notapi
+ */
+void sd_lld_init(void) {
+
+#if LPC122x_SERIAL_USE_UART0
+ sdObjectInit(&SD1, NULL, notify1);
+ SD1.uart = LPC_UART0;
+#if LLPC122x_SERIAL_RXD0_SELECTOR == RXD0_IS_PIO0_1
+ LPC_IOCON->PIO0_1 = 0x82; /* RDX0 without resistors. */
+#else /* LPC122x_SERIAL_RXD0_SELECTOR == RXD1_IS_PIO2_1 */
+ LPC_IOCON->PIO2_1 = 0x84; /* RXD0 without resistors. */
+#endif
+#if LLPC122x_SERIAL_TXD0_SELECTOR == TXD0_IS_PIO0_8
+ LPC_IOCON->PIO0_2 = 0x82; /* TDX0 without resistors. */
+#else /* LPC122x_SERIAL_TXD0_SELECTOR == TXD0_IS_PIO2_2 */
+ LPC_IOCON->PIO2_2 = 0x84; /* TXD0 without resistors. */
+#endif
+#endif
+
+#if LPC122x_SERIAL_USE_UART1
+ sdObjectInit(&SD2, NULL, notify1);
+ SD2.uart = (LPC_UART0_Type *) LPC_UART1;
+#if LLPC122x_SERIAL_RXD1_SELECTOR == RXD1_IS_PIO0_8
+ LPC_IOCON->PIO0_8 = 0x82; /* RXD1 without resistors. */
+#elif LPC122x_SERIAL_RXD1_SELECTOR == RXD1_IS_PIO2_11
+ LPC_IOCON->PIO2_11 = 0x85; /* RXD1 without resistors. */
+#else /* LPC122x_SERIAL_RXD1_SELECTOR == RXD1_IS_PIO2_12 */
+ LPC_IOCON->PIO2_12 = 0x83; /* RXD1 without resistors. */
+#endif
+#if LLPC122x_SERIAL_TXD1_SELECTOR == TXD1_IS_PIO0_8
+ LPC_IOCON->PIO0_9 = 0x82; /* TXD1 without resistors. */
+#elif LPC122x_SERIAL_TXD1_SELECTOR == TXD1_IS_PIO2_11
+ LPC_IOCON->PIO2_10 = 0x85; /* TXD1 without resistors. */
+#else /* LPC122x_SERIAL_TXD1_SELECTOR == TXD1_IS_PIO2_12 */
+ LPC_IOCON->PIO2_13 = 0x83; /* TXD1 without resistors. */
+#endif
+#endif
+}
+
+/**
+ * @brief Low level serial driver configuration and (re)start.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration.
+ * If this parameter is set to @p NULL then a default
+ * configuration is used.
+ *
+ * @notapi
+ */
+void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
+
+ if (config == NULL)
+ config = &default_config;
+
+ if (sdp->state == SD_STOP) {
+#if LPC122x_SERIAL_USE_UART0
+ if (&SD1 == sdp) {
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 12);
+ LPC_SYSCON->UART0CLKDIV = LPC122x_SERIAL_UART0CLKDIV;
+ nvicEnableVector(UART0_IRQn,
+ CORTEX_PRIORITY_MASK(LPC122x_SERIAL_UART0_IRQ_PRIORITY));
+ }
+#endif
+#if LPC122x_SERIAL_USE_UART1
+ if (&SD2 == sdp) {
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 13);
+ LPC_SYSCON->UART1CLKDIV = LPC122x_SERIAL_UART1CLKDIV;
+ nvicEnableVector(UART1_IRQn,
+ CORTEX_PRIORITY_MASK(LPC122x_SERIAL_UART1_IRQ_PRIORITY));
+ }
+#endif
+ }
+ uart_init(sdp, config);
+}
+
+/**
+ * @brief Low level serial driver stop.
+ * @details De-initializes the UART, stops the associated clock, resets the
+ * interrupt vector.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ *
+ * @notapi
+ */
+void sd_lld_stop(SerialDriver *sdp) {
+
+ if (sdp->state == SD_READY) {
+ uart_deinit(sdp->uart);
+#if LPC122x_SERIAL_USE_UART0
+ if (&SD1 == sdp) {
+ LPC_SYSCON->UART0CLKDIV = 0;
+ LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 12);
+ nvicDisableVector(UART0_IRQn);
+ return;
+ }
+#endif
+#if LPC122x_SERIAL_USE_UART1
+ if (&SD2 == sdp) {
+ LPC_SYSCON->UART1CLKDIV = 0;
+ LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 13);
+ nvicDisableVector(UART1_IRQn);
+ return;
+ }
+#endif
+ }
+}
+
+#endif /* HAL_USE_SERIAL */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/serial_lld.h b/os/hal/platforms/LPC122x/serial_lld.h
new file mode 100644
index 000000000..c7ed627d0
--- /dev/null
+++ b/os/hal/platforms/LPC122x/serial_lld.h
@@ -0,0 +1,317 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file LPC122x/serial_lld.h
+ * @brief LPC122x low level serial driver header.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#ifndef _SERIAL_LLD_H_
+#define _SERIAL_LLD_H_
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define IIR_SRC_MASK 0x0F
+#define IIR_SRC_NONE 0x01
+#define IIR_SRC_MODEM 0x00
+#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 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
+
+/**
+ * @brief RXD0 signal assigned to pin PIO0_1.
+ */
+#define RXD0_IS_PIO0_1 0
+
+/**
+ * @brief RXD0 signal assigned to pin PIO2_1.
+ */
+#define RXD0_IS_PIO2_1 1
+
+/**
+ * @brief TXD0 signal assigned to pin PIO0_2.
+ */
+#define TXD0_IS_PIO0_2 0
+
+/**
+ * @brief TXD0 signal assigned to pin PIO2_2.
+ */
+#define TXD0_IS_PIO2_2 1
+
+/**
+ * @brief RXD1 signal assigned to pin PIO0_8.
+ */
+#define RXD1_IS_PIO0_8 0
+
+/**
+ * @brief RXD1 signal assigned to pin PIO2_11.
+ */
+#define RXD1_IS_PIO2_11 1
+
+/**
+ * @brief RXD1 signal assigned to pin PIO2_12.
+ */
+#define RXD1_IS_PIO2_12 2
+
+/**
+ * @brief TXD1 signal assigned to pin PIO0_9.
+ */
+#define TXD1_IS_PIO0_9 0
+
+/**
+ * @brief TXD1 signal assigned to pin PIO2_10.
+ */
+#define TXD1_IS_PIO2_10 1
+
+/**
+ * @brief TXD1 signal assigned to pin PIO2_13.
+ */
+#define TXD1_IS_PIO2_13 2
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief UART0 driver enable switch.
+ * @details If set to @p TRUE the support for UART0 is included.
+ * @note The default is @p TRUE .
+ */
+#if !defined(LPC122x_SERIAL_USE_UART0) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_USE_UART0 TRUE
+#endif
+
+/**
+ * @brief UART1 driver enable switch.
+ * @details If set to @p TRUE the support for UART0 is included.
+ * @note The default is @p TRUE .
+ */
+#if !defined(LPC122x_SERIAL_USE_UART1) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_USE_UART1 TRUE
+#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 1.
+ * @note An high value reduces the number of interrupts generated but can
+ * also increase the worst case interrupt response time because the
+ * preload loops.
+ */
+#if !defined(LPC122x_SERIAL_FIFO_PRELOAD) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_FIFO_PRELOAD 16
+#endif
+
+/**
+ * @brief UART0 PCLK divider.
+ */
+#if !defined(LPC122x_SERIAL_UART0CLKDIV) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_UART0CLKDIV 1
+#endif
+
+/**
+ * @brief UART1 PCLK divider.
+ */
+#if !defined(LPC122x_SERIAL_UART1CLKDIV) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_UART1CLKDIV 1
+#endif
+
+/**
+ * @brief UART0 interrupt priority level setting.
+ */
+#if !defined(LPC122x_SERIAL_UART0_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_UART0_IRQ_PRIORITY 3
+#endif
+
+/**
+ * @brief UART0 interrupt priority level setting.
+ */
+#if !defined(LPC122x_SERIAL_UART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_UART1_IRQ_PRIORITY 3
+#endif
+
+/**
+ * @brief RXD0 signal selector.
+ */
+#if !defined(LPC122x_SERIAL_RXD0_SELECTOR) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_RXD0_SELECTOR RXD0_IS_PIO0_1
+#endif
+
+/**
+ * @brief TXD0 signal selector.
+ */
+#if !defined(LPC122x_SERIAL_TXD0_SELECTOR) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_TXD0_SELECTOR TXD0_IS_PIO0_2
+#endif
+
+/**
+ * @brief RXD1 signal selector.
+ */
+#if !defined(LPC122x_SERIAL_RXD1_SELECTOR) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_RXD1_SELECTOR RXD1_IS_PIO0_8
+#endif
+
+/**
+ * @brief TXD1 signal selector.
+ */
+#if !defined(LPC122x_SERIAL_TXD1_SELECTOR) || defined(__DOXYGEN__)
+#define LPC122x_SERIAL_TXD1_SELECTOR TXD1_IS_PIO0_9
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (LPC122x_SERIAL_UART0CLKDIV < 1) || (LPC122x_SERIAL_UART0CLKDIV > 255)
+#error "invalid LPC122x_SERIAL_UART0CLKDIV setting"
+#endif
+
+#if (LPC122x_SERIAL_UART1CLKDIV < 1) || (LPC122x_SERIAL_UART10CLKDIV > 255)
+#error "invalid LPC122x_SERIAL_UART1CLKDIV setting"
+#endif
+
+#if (LPC122x_SERIAL_FIFO_PRELOAD < 1) || (LPC122x_SERIAL_FIFO_PRELOAD > 16)
+#error "invalid LPC122x_SERIAL_FIFO_PRELOAD setting"
+#endif
+
+/**
+ * @brief UART0 clock.
+ */
+#define LPC122x_SERIAL_UART0_PCLK \
+ (LPC122x_MAINCLK / LPC122x_SERIAL_UART0CLKDIV)
+
+/**
+ * @brief UART0 clock.
+ */
+#define LPC122x_SERIAL_UART1_PCLK \
+ (LPC122x_MAINCLK / LPC122x_SERIAL_UART1CLKDIV)
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief LPC122x Serial Driver configuration structure.
+ * @details An instance of this structure must be passed to @p sdStart()
+ * in order to configure and start a serial driver operations.
+ */
+typedef struct {
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t sc_speed;
+ /**
+ * @brief Initialization value for the LCR register.
+ */
+ uint32_t sc_lcr;
+ /**
+ * @brief Initialization value for the FCR register.
+ */
+ uint32_t sc_fcr;
+} SerialConfig;
+
+/**
+ * @brief @p SerialDriver specific data.
+ */
+#define _serial_driver_data \
+ _base_asynchronous_channel_data \
+ /* Driver state.*/ \
+ sdstate_t state; \
+ /* Input queue.*/ \
+ InputQueue iqueue; \
+ /* Output queue.*/ \
+ OutputQueue oqueue; \
+ /* Input circular buffer.*/ \
+ uint8_t ib[SERIAL_BUFFERS_SIZE]; \
+ /* Output circular buffer.*/ \
+ uint8_t ob[SERIAL_BUFFERS_SIZE]; \
+ /* End of the mandatory fields.*/ \
+ /* Pointer to the USART registers block.*/ \
+ LPC_UART0_Type *uart;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if LPC122x_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
+extern SerialDriver SD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sd_lld_init(void);
+ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
+ void sd_lld_stop(SerialDriver *sdp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SERIAL */
+
+#endif /* _SERIAL_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/spi_lld.c b/os/hal/platforms/LPC122x/spi_lld.c
new file mode 100644
index 000000000..4f8799a54
--- /dev/null
+++ b/os/hal/platforms/LPC122x/spi_lld.c
@@ -0,0 +1,352 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file LPC122x/spi_lld.c
+ * @brief LPC122x low level SPI driver code.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+#if LPC122x_SPI_USE_SSP0 || defined(__DOXYGEN__)
+/** @brief SPI1 driver identifier.*/
+SPIDriver SPID1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Preloads the transmit FIFO.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ */
+static void ssp_fifo_preload(SPIDriver *spip) {
+ LPC_SSP_Type *ssp = spip->ssp;
+ uint32_t n = spip->txcnt > LPC122x_SSP_FIFO_DEPTH ?
+ LPC122x_SSP_FIFO_DEPTH : spip->txcnt;
+
+ while(((ssp->SR & SR_TNF) != 0) && (n > 0)) {
+ if (spip->txptr != NULL) {
+ if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
+ const uint16_t *p = spip->txptr;
+ ssp->DR = *p++;
+ spip->txptr = p;
+ }
+ else {
+ const uint8_t *p = spip->txptr;
+ ssp->DR = *p++;
+ spip->txptr = p;
+ }
+ }
+ else
+ ssp->DR = 0xFFFFFFFF;
+ n--;
+ spip->txcnt--;
+ }
+}
+
+/**
+ * @brief Common IRQ handler.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ */
+static void spi_serve_interrupt(SPIDriver *spip) {
+ LPC_SSP_Type *ssp = spip->ssp;
+
+ if ((ssp->MIS & MIS_ROR) != 0) {
+ /* The overflow condition should never happen because priority is given
+ to receive but a hook macro is provided anyway...*/
+ LPC122x_SPI_SSP_ERROR_HOOK(spip);
+ }
+ ssp->ICR = ICR_RT | ICR_ROR;
+ while ((ssp->SR & SR_RNE) != 0) {
+ if (spip->rxptr != NULL) {
+ if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
+ uint16_t *p = spip->rxptr;
+ *p++ = ssp->DR;
+ spip->rxptr = p;
+ }
+ else {
+ uint8_t *p = spip->rxptr;
+ *p++ = ssp->DR;
+ spip->rxptr = p;
+ }
+ }
+ else
+ (void)ssp->DR;
+ if (--spip->rxcnt == 0) {
+ chDbgAssert(spip->txcnt == 0,
+ "spi_serve_interrupt(), #1", "counter out of synch");
+ /* Stops the IRQ sources.*/
+ ssp->IMSC = 0;
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+ return;
+ }
+ }
+ ssp_fifo_preload(spip);
+ if (spip->txcnt == 0)
+ ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_RX;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if LPC122x_SPI_USE_SSP0 || defined(__DOXYGEN__)
+/**
+ * @brief SSP0 interrupt handler.
+ *
+ * @isr
+ */
+CH_IRQ_HANDLER(Vector84) {
+
+ CH_IRQ_PROLOGUE();
+
+ spi_serve_interrupt(&SPID1);
+
+ CH_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SPI driver initialization.
+ *
+ * @notapi
+ */
+void spi_lld_init(void) {
+
+#if LPC122x_SPI_USE_SSP0
+ spiObjectInit(&SPID1);
+ SPID1.ssp = LPC_SSP;
+
+ LPC_IOCON->PIO0_14 = 0x82; /* SCK0 without resistors. */
+ LPC_IOCON->PIO0_16 = 0x82; /* MISO0 without resistors. */
+ LPC_IOCON->PIO0_17 = 0x82; /* MOSI0 without resistors. */
+#endif /* LPC122x_SPI_USE_SSP0 */
+}
+
+/**
+ * @brief Configures and activates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_start(SPIDriver *spip) {
+
+ if (spip->state == SPI_STOP) {
+ /* Clock activation.*/
+#if LPC122x_SPI_USE_SSP0
+ if (&SPID1 == spip) {
+ LPC_SYSCON->SSPCLKDIV = LPC122x_SPI_SSP0CLKDIV;
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 11);
+ LPC_SYSCON->PRESETCTRL |= 1;
+ nvicEnableVector(SSP_IRQn,
+ CORTEX_PRIORITY_MASK(LPC122x_SPI_SSP0_IRQ_PRIORITY));
+ }
+#endif
+ }
+ /* Configuration.*/
+ spip->ssp->CR1 = 0;
+ spip->ssp->ICR = ICR_RT | ICR_ROR;
+ spip->ssp->CR0 = spip->config->cr0;
+ spip->ssp->CPSR = spip->config->cpsr;
+ spip->ssp->CR1 = CR1_SSE;
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_stop(SPIDriver *spip) {
+
+ if (spip->state != SPI_STOP) {
+ spip->ssp->CR1 = 0;
+ spip->ssp->CR0 = 0;
+ spip->ssp->CPSR = 0;
+#if LPC122x_SPI_USE_SSP0
+ if (&SPID1 == spip) {
+ LPC_SYSCON->PRESETCTRL &= ~1;
+ LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 11);
+ LPC_SYSCON->SSPCLKDIV = 0;
+ nvicDisableVector(SSP_IRQn);
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_select(SPIDriver *spip) {
+
+ palClearPad(spip->config->ssport, spip->config->sspad);
+}
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_unselect(SPIDriver *spip) {
+
+ palSetPad(spip->config->ssport, spip->config->sspad);
+}
+
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This function transmits a series of idle words on the SPI bus and
+ * ignores the received data. This function can be invoked even
+ * when a slave select signal has not been yet asserted.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @notapi
+ */
+void spi_lld_ignore(SPIDriver *spip, size_t n) {
+
+ spip->rxptr = NULL;
+ spip->txptr = NULL;
+ spip->rxcnt = spip->txcnt = n;
+ ssp_fifo_preload(spip);
+ spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ spip->rxptr = rxbuf;
+ spip->txptr = txbuf;
+ spip->rxcnt = spip->txcnt = n;
+ ssp_fifo_preload(spip);
+ spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ spip->rxptr = NULL;
+ spip->txptr = txbuf;
+ spip->rxcnt = spip->txcnt = n;
+ ssp_fifo_preload(spip);
+ spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ spip->rxptr = rxbuf;
+ spip->txptr = NULL;
+ spip->rxcnt = spip->txcnt = n;
+ ssp_fifo_preload(spip);
+ spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
+}
+
+/**
+ * @brief Exchanges one frame using a polled wait.
+ * @details This synchronous function exchanges one frame using a polled
+ * synchronization method. This function is useful when exchanging
+ * small amount of data on high speed channels, usually in this
+ * situation is much more efficient just wait for completion using
+ * polling than suspending the thread waiting for an interrupt.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] frame the data frame to send over the SPI bus
+ * @return The received data frame from the SPI bus.
+ */
+uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
+
+ spip->ssp->DR = (uint32_t)frame;
+ while ((spip->ssp->SR & SR_RNE) == 0)
+ ;
+ return (uint16_t)spip->ssp->DR;
+}
+
+#endif /* HAL_USE_SPI */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/spi_lld.h b/os/hal/platforms/LPC122x/spi_lld.h
new file mode 100644
index 000000000..0cb48f89f
--- /dev/null
+++ b/os/hal/platforms/LPC122x/spi_lld.h
@@ -0,0 +1,281 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file LPC122x/spi_lld.h
+ * @brief LPC122x low level SPI driver header.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#ifndef _SPI_LLD_H_
+#define _SPI_LLD_H_
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Hardware FIFO depth.
+ */
+#define LPC122x_SSP_FIFO_DEPTH 8
+
+#define CR0_DSSMASK 0x0F
+#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 16
+
+#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
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief SPI1 driver enable switch.
+ * @details If set to @p TRUE the support for device SSP0 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LPC122x_SPI_USE_SSP0) || defined(__DOXYGEN__)
+#define LPC122x_SPI_USE_SSP0 TRUE
+#endif
+
+/**
+ * @brief SSP0 PCLK divider.
+ */
+#if !defined(LPC122x_SPI_SSP0CLKDIV) || defined(__DOXYGEN__)
+#define LPC122x_SPI_SSP0CLKDIV 1
+#endif
+
+/**
+ * @brief SPI0 interrupt priority level setting.
+ */
+#if !defined(LPC122x_SPI_SSP0_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define LPC122x_SPI_SSP0_IRQ_PRIORITY 1
+#endif
+
+/**
+ * @brief Overflow error hook.
+ * @details The default action is to stop the system.
+ */
+#if !defined(LPC122x_SPI_SSP_ERROR_HOOK) || defined(__DOXYGEN__)
+#define LPC122x_SPI_SSP_ERROR_HOOK(spip) chSysHalt()
+#endif
+
+/**
+ * @brief SCK0 signal selector.
+ */
+#if !defined(LPC122x_SPI_SCK0_SELECTOR) || defined(__DOXYGEN__)
+#define LPC122x_SPI_SCK0_SELECTOR SCK0_IS_PIO2_11
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (LPC122x_SPI_SSP0CLKDIV < 1) || (LPC122x_SPI_SSP0CLKDIV > 255)
+#error "invalid LPC122x_SPI_SSP0CLKDIV setting"
+#endif
+
+#if !LPC122x_SPI_USE_SSP0 && !LPC122x_SPI_USE_SSP1
+#error "SPI driver activated but no SPI peripheral assigned"
+#endif
+
+/**
+ * @brief SSP0 clock.
+ */
+#define LPC122x_SPI_SSP0_PCLK \
+ (LPC122x_MAINCLK / LPC122x_SPI_SSP0CLKDIV)
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an SPI driver.
+ */
+typedef struct SPIDriver SPIDriver;
+
+/**
+ * @brief SPI notification callback type.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object triggering the
+ * callback
+ */
+typedef void (*spicallback_t)(SPIDriver *spip);
+
+/**
+ * @brief Driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief Operation complete callback or @p NULL.
+ */
+ spicallback_t end_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief The chip select line port.
+ */
+ ioportid_t ssport;
+ /**
+ * @brief The chip select line pad number.
+ */
+ uint16_t sspad;
+ /**
+ * @brief SSP CR0 initialization data.
+ */
+ uint16_t cr0;
+ /**
+ * @brief SSP CPSR initialization data.
+ */
+ uint32_t cpsr;
+} SPIConfig;
+
+/**
+ * @brief Structure representing a SPI driver.
+ */
+struct SPIDriver {
+ /**
+ * @brief Driver state.
+ */
+ spistate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const SPIConfig *config;
+#if SPI_USE_WAIT || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ Thread *thread;
+#endif /* SPI_USE_WAIT */
+#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+#if CH_USE_MUTEXES || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the bus.
+ */
+ Mutex mutex;
+#elif CH_USE_SEMAPHORES
+ Semaphore semaphore;
+#endif
+#endif /* SPI_USE_MUTUAL_EXCLUSION */
+#if defined(SPI_DRIVER_EXT_FIELDS)
+ SPI_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the SSP registers block.
+ */
+ LPC_SSP_Type *ssp;
+ /**
+ * @brief Number of bytes yet to be received.
+ */
+ uint32_t rxcnt;
+ /**
+ * @brief Receive pointer or @p NULL.
+ */
+ void *rxptr;
+ /**
+ * @brief Number of bytes yet to be transmitted.
+ */
+ uint32_t txcnt;
+ /**
+ * @brief Transmit pointer or @p NULL.
+ */
+ const void *txptr;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if LPC122x_SPI_USE_SSP0 && !defined(__DOXYGEN__)
+extern SPIDriver SPID1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void spi_lld_init(void);
+ void spi_lld_start(SPIDriver *spip);
+ void spi_lld_stop(SPIDriver *spip);
+ void spi_lld_select(SPIDriver *spip);
+ void spi_lld_unselect(SPIDriver *spip);
+ void spi_lld_ignore(SPIDriver *spip, size_t n);
+ void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf);
+ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
+ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
+ uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SPI */
+
+#endif /* _SPI_LLD_H_ */
+
+/** @} */
diff --git a/os/hal/platforms/LPC122x/system_LPC122x.h b/os/hal/platforms/LPC122x/system_LPC122x.h
new file mode 100644
index 000000000..0a8ecda0f
--- /dev/null
+++ b/os/hal/platforms/LPC122x/system_LPC122x.h
@@ -0,0 +1,65 @@
+/**************************************************************************//**
+ * $Id: system_LPC122x.h 6933 2011-03-23 19:02:11Z nxp28548 $
+ *
+ * @file system_LPC12xx.h
+ * @brief CMSIS Cortex-M0 Device Peripheral Access Layer Header File
+ * for the NXP LPC12xx Device Series
+ * @version 1.1
+ * @date $Date:: 2011-03-23#$
+ * @author NXP MCU Team
+ *
+ * @note
+ * Copyright (C) 2010 NXP Semiconductors(NXP). All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ ******************************************************************************/
+
+#ifndef __SYSTEM_LPC12xx_H
+#define __SYSTEM_LPC12xx_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
+extern uint32_t MainClock; /*!< Main Clock Frequency (Main Clock) */
+
+/**
+ * Initialize the system
+ *
+ * @param none
+ * @return none
+ *
+ * @brief Setup the microcontroller system.
+ * Initialize the System and update the SystemCoreClock variable.
+ */
+extern void SystemInit (void);
+
+/**
+ * Update SystemCoreClock variable
+ *
+ * @param none
+ * @return none
+ *
+ * @brief Updates the SystemCoreClock with current core Clock
+ * retrieved from cpu registers.
+ */
+extern void SystemCoreClockUpdate (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SYSTEM_LPC12xx_H */
diff --git a/os/ports/GCC/ARMCMx/LPC122x/cmparams.h b/os/ports/GCC/ARMCMx/LPC122x/cmparams.h
new file mode 100644
index 000000000..b70ce42a3
--- /dev/null
+++ b/os/ports/GCC/ARMCMx/LPC122x/cmparams.h
@@ -0,0 +1,62 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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 GCC/ARMCMx/LPC13xx/cmparams.h
+ * @brief ARM Cortex-M0 LPC122x Specific Parameters.
+ *
+ * @defgroup ARMCMx_LPC122x LPC122x Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M0 specific parameters for the
+ * LPC122x platform.
+ * @{
+ */
+
+#ifndef _CMPARAMS_H_
+#define _CMPARAMS_H_
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL CORTEX_M0
+
+/**
+ * @brief Systick unit presence.
+ */
+#define CORTEX_HAS_ST TRUE
+
+/**
+ * @brief Memory Protection unit presence.
+ */
+#define CORTEX_HAS_MPU FALSE
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU FALSE
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 2
+
+#endif /* _CMPARAMS_H_ */
+
+/** @} */
diff --git a/os/ports/GCC/ARMCMx/LPC122x/ld/LPC1227.ld b/os/ports/GCC/ARMCMx/LPC122x/ld/LPC1227.ld
new file mode 100644
index 000000000..b7171526d
--- /dev/null
+++ b/os/ports/GCC/ARMCMx/LPC122x/ld/LPC1227.ld
@@ -0,0 +1,152 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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/>.
+*/
+
+/*
+ * LPC1227 memory setup.
+ */
+__main_stack_size__ = 0x0200;
+__process_stack_size__ = 0x0200;
+
+MEMORY
+{
+ flash : org = 0x00000000, len = 128k
+ ram : org = 0x10000000, len = 8k
+}
+
+__ram_start__ = ORIGIN(ram);
+__ram_size__ = LENGTH(ram);
+__ram_end__ = __ram_start__ + __ram_size__;
+
+ENTRY(ResetHandler)
+
+SECTIONS
+{
+ . = 0;
+ _text = .;
+
+ startup : ALIGN(16) SUBALIGN(16)
+ {
+ KEEP(*(vectors))
+ } > flash
+
+ constructors : ALIGN(4) SUBALIGN(4)
+ {
+ PROVIDE(__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE(__init_array_end = .);
+ } > flash
+
+ destructors : ALIGN(4) SUBALIGN(4)
+ {
+ PROVIDE(__fini_array_start = .);
+ KEEP(*(.fini_array))
+ KEEP(*(SORT(.fini_array.*)))
+ PROVIDE(__fini_array_end = .);
+ } > flash
+
+ .text : ALIGN(16) SUBALIGN(16)
+ {
+ *(.text.startup.*)
+ *(.text)
+ *(.text.*)
+ *(.rodata)
+ *(.rodata.*)
+ *(.glue_7t)
+ *(.glue_7)
+ *(.gcc*)
+ } > flash
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > flash
+
+ .ARM.exidx : {
+ PROVIDE(__exidx_start = .);
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ PROVIDE(__exidx_end = .);
+ } > flash
+
+ .eh_frame_hdr :
+ {
+ *(.eh_frame_hdr)
+ } > flash
+
+ .eh_frame : ONLY_IF_RO
+ {
+ *(.eh_frame)
+ } > flash
+
+ .textalign : ONLY_IF_RO
+ {
+ . = ALIGN(8);
+ } > flash
+
+ _etext = .;
+ _textdata = _etext;
+
+ .stacks :
+ {
+ . = ALIGN(8);
+ __main_stack_base__ = .;
+ . += __main_stack_size__;
+ . = ALIGN(8);
+ __main_stack_end__ = .;
+ __process_stack_base__ = .;
+ __main_thread_stack_base__ = .;
+ . += __process_stack_size__;
+ . = ALIGN(8);
+ __process_stack_end__ = .;
+ __main_thread_stack_end__ = .;
+ } > ram
+
+ .data :
+ {
+ . = ALIGN(4);
+ PROVIDE(_data = .);
+ *(.data)
+ . = ALIGN(4);
+ *(.data.*)
+ . = ALIGN(4);
+ *(.ramtext)
+ . = ALIGN(4);
+ PROVIDE(_edata = .);
+ } > ram AT > flash
+
+ .bss :
+ {
+ . = ALIGN(4);
+ PROVIDE(_bss_start = .);
+ *(.bss)
+ . = ALIGN(4);
+ *(.bss.*)
+ . = ALIGN(4);
+ *(COMMON)
+ . = ALIGN(4);
+ PROVIDE(_bss_end = .);
+ } > ram
+}
+
+PROVIDE(end = .);
+_end = .;
+
+__heap_base__ = _end;
+__heap_end__ = __ram_end__;
diff --git a/os/ports/GCC/ARMCMx/LPC122x/port.mk b/os/ports/GCC/ARMCMx/LPC122x/port.mk
new file mode 100644
index 000000000..475861ee2
--- /dev/null
+++ b/os/ports/GCC/ARMCMx/LPC122x/port.mk
@@ -0,0 +1,15 @@
+# List of the ChibiOS/RT Cortex-M0 LPC122x port files.
+PORTSRC = $(CHIBIOS)/os/ports/GCC/ARMCMx/crt0.c \
+ $(CHIBIOS)/os/ports/GCC/ARMCMx/LPC122x/vectors.c \
+ ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore.c \
+ ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore_v6m.c \
+ ${CHIBIOS}/os/ports/common/ARMCMx/nvic.c
+
+PORTASM =
+
+PORTINC = ${CHIBIOS}/os/ports/common/ARMCMx/CMSIS/include \
+ ${CHIBIOS}/os/ports/common/ARMCMx \
+ ${CHIBIOS}/os/ports/GCC/ARMCMx \
+ ${CHIBIOS}/os/ports/GCC/ARMCMx/LPC122x
+
+PORTLD = ${CHIBIOS}/os/ports/GCC/ARMCMx/LPC122x/ld
diff --git a/os/ports/GCC/ARMCMx/LPC122x/vectors.c b/os/ports/GCC/ARMCMx/LPC122x/vectors.c
new file mode 100644
index 000000000..39e4007a3
--- /dev/null
+++ b/os/ports/GCC/ARMCMx/LPC122x/vectors.c
@@ -0,0 +1,198 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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 GCC/ARMCMx/LPC122x/vectors.c
+ * @brief Interrupt vectors for the LPC122x family.
+ *
+ * @defgroup ARMCMx_LPC122x_VECTORS LPC122x Interrupt Vectors
+ * @ingroup ARMCMx_SPECIFIC
+ * @details Interrupt vectors for the LPC122x family.
+ * @{
+ */
+
+#include "ch.h"
+
+/**
+ * @brief Type of an IRQ vector.
+ */
+typedef void (*irq_vector_t)(void);
+
+/**
+ * @brief Type of a structure representing the whole vectors table.
+ */
+typedef struct {
+ uint32_t *init_stack;
+ irq_vector_t reset_vector;
+ irq_vector_t nmi_vector;
+ irq_vector_t hardfault_vector;
+ irq_vector_t memmanage_vector;
+ irq_vector_t busfault_vector;
+ irq_vector_t usagefault_vector;
+ irq_vector_t vector1c;
+ irq_vector_t vector20;
+ irq_vector_t vector24;
+ irq_vector_t vector28;
+ irq_vector_t svcall_vector;
+ irq_vector_t debugmonitor_vector;
+ irq_vector_t vector34;
+ irq_vector_t pendsv_vector;
+ irq_vector_t systick_vector;
+ irq_vector_t vectors[32];
+} vectors_t;
+
+#if !defined(__DOXYGEN__)
+extern uint32_t __main_stack_end__;
+extern void ResetHandler(void);
+extern void NMIVector(void);
+extern void HardFaultVector(void);
+extern void MemManageVector(void);
+extern void BusFaultVector(void);
+extern void UsageFaultVector(void);
+extern void Vector1C(void);
+extern void Vector20(void);
+extern void Vector24(void);
+extern void Vector28(void);
+extern void SVCallVector(void);
+extern void DebugMonitorVector(void);
+extern void Vector34(void);
+extern void PendSVVector(void);
+extern void SysTickVector(void);
+extern void Vector40(void);
+extern void Vector44(void);
+extern void Vector48(void);
+extern void Vector4C(void);
+extern void Vector50(void);
+extern void Vector54(void);
+extern void Vector58(void);
+extern void Vector5C(void);
+extern void Vector60(void);
+extern void Vector64(void);
+extern void Vector68(void);
+extern void Vector6C(void);
+extern void Vector70(void);
+extern void Vector74(void);
+extern void Vector78(void);
+extern void Vector7C(void);
+extern void Vector80(void);
+extern void Vector84(void);
+extern void Vector88(void);
+extern void Vector8C(void);
+extern void Vector90(void);
+extern void Vector94(void);
+extern void Vector98(void);
+extern void Vector9C(void);
+extern void VectorA0(void);
+extern void VectorA4(void);
+extern void VectorA8(void);
+extern void VectorAC(void);
+extern void VectorB0(void);
+extern void VectorB4(void);
+extern void VectorB8(void);
+extern void VectorBC(void);
+#endif
+
+/**
+ * @brief LPC11xx vectors table.
+ */
+#if !defined(__DOXYGEN__)
+__attribute__ ((section("vectors")))
+#endif
+vectors_t _vectors = {
+ &__main_stack_end__,ResetHandler, NMIVector, HardFaultVector,
+ MemManageVector, BusFaultVector, UsageFaultVector, Vector1C,
+ Vector20, Vector24, Vector28, SVCallVector,
+ DebugMonitorVector, Vector34, PendSVVector, SysTickVector,
+ {
+ Vector40, Vector44, Vector48, Vector4C,
+ Vector50, Vector54, Vector58, Vector5C,
+ Vector60, Vector64, Vector68, Vector6C,
+ Vector70, Vector74, Vector78, Vector7C,
+ Vector80, Vector84, Vector88, Vector8C,
+ Vector90, Vector94, Vector98, Vector9C,
+ VectorA0, VectorA4, VectorA8, VectorAC,
+ VectorB0, VectorB4, VectorB8, VectorBC
+ }
+};
+
+/**
+ * @brief Unhandled exceptions handler.
+ * @details Any undefined exception vector points to this function by default.
+ * This function simply stops the system into an infinite loop.
+ *
+ * @notapi
+ */
+#if !defined(__DOXYGEN__)
+__attribute__ ((naked))
+#endif
+void _unhandled_exception(void) {
+
+ while (TRUE)
+ ;
+}
+
+void NMIVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void HardFaultVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void MemManageVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void BusFaultVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void UsageFaultVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector1C(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector20(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector24(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector28(void) __attribute__((weak, alias("_unhandled_exception")));
+void SVCallVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void DebugMonitorVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector34(void) __attribute__((weak, alias("_unhandled_exception")));
+void PendSVVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void SysTickVector(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector40(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector44(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector48(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector4C(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector50(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector54(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector58(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector5C(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector60(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector64(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector68(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector6C(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector70(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector74(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector78(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector7C(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector80(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector84(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector88(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector8C(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector90(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector94(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector98(void) __attribute__((weak, alias("_unhandled_exception")));
+void Vector9C(void) __attribute__((weak, alias("_unhandled_exception")));
+void VectorA0(void) __attribute__((weak, alias("_unhandled_exception")));
+void VectorA4(void) __attribute__((weak, alias("_unhandled_exception")));
+void VectorA8(void) __attribute__((weak, alias("_unhandled_exception")));
+void VectorAC(void) __attribute__((weak, alias("_unhandled_exception")));
+void VectorB0(void) __attribute__((weak, alias("_unhandled_exception")));
+void VectorB4(void) __attribute__((weak, alias("_unhandled_exception")));
+void VectorB8(void) __attribute__((weak, alias("_unhandled_exception")));
+void VectorBC(void) __attribute__((weak, alias("_unhandled_exception")));
+
+/** @} */
diff --git a/testhal/LPC122x/IRQ_STORM/Makefile b/testhal/LPC122x/IRQ_STORM/Makefile
new file mode 100644
index 000000000..507fe3f00
--- /dev/null
+++ b/testhal/LPC122x/IRQ_STORM/Makefile
@@ -0,0 +1,196 @@
+##############################################################################
+# Build global options
+# NOTE: Can be overridden externally.
+#
+
+# Compiler options here.
+ifeq ($(USE_OPT),)
+ USE_OPT = -O2 -ggdb -fomit-frame-pointer
+endif
+
+# C specific options here (added to USE_OPT).
+ifeq ($(USE_COPT),)
+ USE_COPT =
+endif
+
+# C++ specific options here (added to USE_OPT).
+ifeq ($(USE_CPPOPT),)
+ USE_CPPOPT = -fno-rtti
+endif
+
+# Enable this if you want the linker to remove unused code and data
+ifeq ($(USE_LINK_GC),)
+ USE_LINK_GC = yes
+endif
+
+# If enabled, this option allows to compile the application in THUMB mode.
+ifeq ($(USE_THUMB),)
+ USE_THUMB = yes
+endif
+
+# Enable this if you want to see the full log while compiling.
+ifeq ($(USE_VERBOSE_COMPILE),)
+ USE_VERBOSE_COMPILE = no
+endif
+
+#
+# Build global options
+##############################################################################
+
+##############################################################################
+# Architecture or project specific options
+#
+
+#
+# Architecture or project specific options
+##############################################################################
+
+##############################################################################
+# Project, sources and paths
+#
+
+# Define project name here
+PROJECT = ch
+
+# Imported source files and paths
+CHIBIOS = ../../..
+include $(CHIBIOS)/boards/OLIMEX_LPC-P1227/board.mk
+include $(CHIBIOS)/os/hal/platforms/LPC122x/platform.mk
+include $(CHIBIOS)/os/hal/hal.mk
+include $(CHIBIOS)/os/ports/GCC/ARMCMx/LPC122x/port.mk
+include $(CHIBIOS)/os/kernel/kernel.mk
+include $(CHIBIOS)/test/test.mk
+
+# Define linker script file here
+LDSCRIPT= $(PORTLD)/LPC1227.ld
+
+# C sources that can be compiled in ARM or THUMB mode depending on the global
+# setting.
+CSRC = $(PORTSRC) \
+ $(KERNSRC) \
+ $(TESTSRC) \
+ $(HALSRC) \
+ $(PLATFORMSRC) \
+ $(BOARDSRC) \
+ $(CHIBIOS)/os/various/evtimer.c \
+ $(CHIBIOS)/os/various/syscalls.c \
+ main.c
+
+# C++ sources that can be compiled in ARM or THUMB mode depending on the global
+# setting.
+CPPSRC =
+
+# C sources to be compiled in ARM mode regardless of the global setting.
+# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
+# option that results in lower performance and larger code size.
+ACSRC =
+
+# C++ sources to be compiled in ARM mode regardless of the global setting.
+# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
+# option that results in lower performance and larger code size.
+ACPPSRC =
+
+# C sources to be compiled in THUMB mode regardless of the global setting.
+# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
+# option that results in lower performance and larger code size.
+TCSRC =
+
+# C sources to be compiled in THUMB mode regardless of the global setting.
+# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
+# option that results in lower performance and larger code size.
+TCPPSRC =
+
+# List ASM source files here
+ASMSRC = $(PORTASM)
+
+INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
+ $(HALINC) $(PLATFORMINC) $(BOARDINC) \
+ $(CHIBIOS)/os/various
+
+#
+# Project, sources and paths
+##############################################################################
+
+##############################################################################
+# Compiler settings
+#
+
+MCU = cortex-m0
+
+TRGT = arm-none-eabi-
+CC = $(TRGT)gcc
+CPPC = $(TRGT)g++
+# Enable loading with g++ only if you need C++ runtime support.
+# NOTE: You can use C++ even without C++ support if you are careful. C++
+# runtime support makes code size explode.
+LD = $(TRGT)gcc
+#LD = $(TRGT)g++
+CP = $(TRGT)objcopy
+AS = $(TRGT)gcc -x assembler-with-cpp
+OD = $(TRGT)objdump
+HEX = $(CP) -O ihex
+BIN = $(CP) -O binary
+
+# ARM-specific options here
+AOPT =
+
+# THUMB-specific options here
+TOPT = -mthumb -DTHUMB
+
+# Define C warning options here
+CWARN = -Wall -Wextra -Wstrict-prototypes
+
+# Define C++ warning options here
+CPPWARN = -Wall -Wextra
+
+#
+# Compiler settings
+##############################################################################
+
+##############################################################################
+# Start of default section
+#
+
+# List all default C defines here, like -D_DEBUG=1
+DDEFS = -DLPC1227 -D__NEWLIB__
+
+# List all default ASM defines here, like -D_DEBUG=1
+DADEFS =
+
+# List all default directories to look for include files here
+DINCDIR =
+
+# List the default directory to look for the libraries here
+DLIBDIR =
+
+# List all default libraries here
+DLIBS =
+
+#
+# End of default section
+##############################################################################
+
+##############################################################################
+# Start of user section
+#
+
+# List all user C define here, like -D_DEBUG=1
+UDEFS =
+
+# Define ASM defines here
+UADEFS =
+
+# List all user directories here
+UINCDIR =
+
+# List the user directory to look for the libraries here
+ULIBDIR =
+
+# List all user libraries here
+ULIBS =
+
+#
+# End of user defines
+##############################################################################
+
+include $(CHIBIOS)/os/ports/GCC/ARMCMx/rules.mk
diff --git a/testhal/LPC122x/IRQ_STORM/chconf.h b/testhal/LPC122x/IRQ_STORM/chconf.h
new file mode 100644
index 000000000..ae54d3edf
--- /dev/null
+++ b/testhal/LPC122x/IRQ_STORM/chconf.h
@@ -0,0 +1,535 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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 templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef _CHCONF_H_
+#define _CHCONF_H_
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#if !defined(CH_FREQUENCY) || defined(__DOXYGEN__)
+#define CH_FREQUENCY 1000
+#endif
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ *
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ */
+#if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__)
+#define CH_TIME_QUANTUM 20
+#endif
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_USE_MEMCORE.
+ */
+#if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__)
+#define CH_MEMCORE_SIZE 0
+#endif
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread automatically. The application has
+ * then the responsibility to do one of the following:
+ * - Spawn a custom idle thread at priority @p IDLEPRIO.
+ * - Change the main() thread priority to @p IDLEPRIO then enter
+ * an endless loop. In this scenario the @p main() thread acts as
+ * the idle thread.
+ * .
+ * @note Unless an idle thread is spawned the @p main() thread must not
+ * enter a sleep state.
+ */
+#if !defined(CH_NO_IDLE_THREAD) || defined(__DOXYGEN__)
+#define CH_NO_IDLE_THREAD FALSE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__)
+#define CH_OPTIMIZE_SPEED TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__)
+#define CH_USE_REGISTRY TRUE
+#endif
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__)
+#define CH_USE_WAITEXIT TRUE
+#endif
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__)
+#define CH_USE_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special requirements.
+ * @note Requires @p CH_USE_SEMAPHORES.
+ */
+#if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__)
+#define CH_USE_SEMAPHORES_PRIORITY FALSE
+#endif
+
+/**
+ * @brief Atomic semaphore API.
+ * @details If enabled then the semaphores the @p chSemSignalWait() API
+ * is included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_USE_SEMAPHORES.
+ */
+#if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__)
+#define CH_USE_SEMSW TRUE
+#endif
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__)
+#define CH_USE_MUTEXES TRUE
+#endif
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_USE_MUTEXES.
+ */
+#if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__)
+#define CH_USE_CONDVARS TRUE
+#endif
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_USE_CONDVARS.
+ */
+#if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__)
+#define CH_USE_CONDVARS_TIMEOUT TRUE
+#endif
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__)
+#define CH_USE_EVENTS TRUE
+#endif
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_USE_EVENTS.
+ */
+#if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__)
+#define CH_USE_EVENTS_TIMEOUT TRUE
+#endif
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__)
+#define CH_USE_MESSAGES TRUE
+#endif
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special requirements.
+ * @note Requires @p CH_USE_MESSAGES.
+ */
+#if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__)
+#define CH_USE_MESSAGES_PRIORITY FALSE
+#endif
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_USE_SEMAPHORES.
+ */
+#if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__)
+#define CH_USE_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief I/O Queues APIs.
+ * @details If enabled then the I/O queues APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__)
+#define CH_USE_QUEUES TRUE
+#endif
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_MEMCORE) || defined(__DOXYGEN__)
+#define CH_USE_MEMCORE TRUE
+#endif
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_USE_MEMCORE and either @p CH_USE_MUTEXES or
+ * @p CH_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#if !defined(CH_USE_HEAP) || defined(__DOXYGEN__)
+#define CH_USE_HEAP TRUE
+#endif
+
+/**
+ * @brief C-runtime allocator.
+ * @details If enabled the the heap allocator APIs just wrap the C-runtime
+ * @p malloc() and @p free() functions.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_USE_HEAP.
+ * @note The C-runtime may or may not require @p CH_USE_MEMCORE, see the
+ * appropriate documentation.
+ */
+#if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__)
+#define CH_USE_MALLOC_HEAP FALSE
+#endif
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__)
+#define CH_USE_MEMPOOLS TRUE
+#endif
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_USE_WAITEXIT.
+ * @note Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS.
+ */
+#if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__)
+#define CH_USE_DYNAMIC TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__)
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+#endif
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
+#define CH_DBG_ENABLE_CHECKS FALSE
+#endif
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
+#define CH_DBG_ENABLE_ASSERTS FALSE
+#endif
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the context switch circular trace buffer is
+ * activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__)
+#define CH_DBG_ENABLE_TRACE FALSE
+#endif
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+#endif
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__)
+#define CH_DBG_FILL_THREADS FALSE
+#endif
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p Thread structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p TRUE.
+ * @note This debug option is defaulted to TRUE because it is required by
+ * some test cases into the test suite.
+ */
+#if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__)
+#define CH_DBG_THREADS_PROFILING TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p Thread structure.
+ */
+#if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
+#define THREAD_EXT_FIELDS \
+ /* Add threads custom fields here.*/
+#endif
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#if !defined(THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__)
+#define THREAD_EXT_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+#endif
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ *
+ * @note It is inserted into lock zone.
+ * @note It is also invoked when the threads simply return in order to
+ * terminate.
+ */
+#if !defined(THREAD_EXT_EXIT_HOOK) || defined(__DOXYGEN__)
+#define THREAD_EXT_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+#endif
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#if !defined(THREAD_CONTEXT_SWITCH_HOOK) || defined(__DOXYGEN__)
+#define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* System halt code here.*/ \
+}
+#endif
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__)
+#define IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+#endif
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__)
+#define SYSTEM_TICK_EVENT_HOOK() { \
+ /* System tick event code here.*/ \
+}
+#endif
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#if !defined(SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)
+#define SYSTEM_HALT_HOOK() { \
+ /* System halt code here.*/ \
+}
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* _CHCONF_H_ */
+
+/** @} */
diff --git a/testhal/LPC122x/IRQ_STORM/halconf.h b/testhal/LPC122x/IRQ_STORM/halconf.h
new file mode 100644
index 000000000..c78a58996
--- /dev/null
+++ b/testhal/LPC122x/IRQ_STORM/halconf.h
@@ -0,0 +1,316 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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 templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the TM subsystem.
+ */
+#if !defined(HAL_USE_TM) || defined(__DOXYGEN__)
+#define HAL_USE_TM FALSE
+#endif
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT TRUE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL TRUE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @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 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/testhal/LPC122x/IRQ_STORM/main.c b/testhal/LPC122x/IRQ_STORM/main.c
new file mode 100644
index 000000000..27b93337f
--- /dev/null
+++ b/testhal/LPC122x/IRQ_STORM/main.c
@@ -0,0 +1,324 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include <stdlib.h>
+
+#include "ch.h"
+#include "hal.h"
+
+/*===========================================================================*/
+/* Configurable settings. */
+/*===========================================================================*/
+
+#ifndef RANDOMIZE
+#define RANDOMIZE FALSE
+#endif
+
+#ifndef ITERATIONS
+#define ITERATIONS 100
+#endif
+
+#ifndef NUM_THREADS
+#define NUM_THREADS 4
+#endif
+
+#ifndef MAILBOX_SIZE
+#define MAILBOX_SIZE 4
+#endif
+
+/*===========================================================================*/
+/* Test related code. */
+/*===========================================================================*/
+
+#define MSG_SEND_LEFT 0
+#define MSG_SEND_RIGHT 1
+
+static bool_t saturated;
+
+/*
+ * Mailboxes and buffers.
+ */
+static Mailbox mb[NUM_THREADS];
+static msg_t b[NUM_THREADS][MAILBOX_SIZE];
+
+/*
+ * Test worker threads.
+ */
+static WORKING_AREA(waWorkerThread[NUM_THREADS], 128);
+static msg_t WorkerThread(void *arg) {
+ static volatile unsigned x = 0;
+ static unsigned cnt = 0;
+ unsigned me = (unsigned)arg;
+ unsigned target;
+ unsigned r;
+ msg_t msg;
+
+ chRegSetThreadName("worker");
+
+ /* Work loop.*/
+ while (TRUE) {
+ /* Waiting for a message.*/
+ chMBFetch(&mb[me], &msg, TIME_INFINITE);
+
+#if RANDOMIZE
+ /* Pseudo-random delay.*/
+ {
+ chSysLock();
+ r = rand() & 15;
+ chSysUnlock();
+ while (r--)
+ x++;
+ }
+#else
+ /* Fixed delay.*/
+ {
+ r = me >> 4;
+ while (r--)
+ x++;
+ }
+#endif
+
+ /* Deciding in which direction to re-send the message.*/
+ if (msg == MSG_SEND_LEFT)
+ target = me - 1;
+ else
+ target = me + 1;
+
+ if (target < NUM_THREADS) {
+ /* If this thread is not at the end of a chain re-sending the message,
+ note this check works because the variable target is unsigned.*/
+ msg = chMBPost(&mb[target], msg, TIME_IMMEDIATE);
+ if (msg != RDY_OK)
+ saturated = TRUE;
+ }
+ else {
+ /* Provides a visual feedback about the system.*/
+ if (++cnt >= 500) {
+ cnt = 0;
+ palTogglePad(GPIO1, GPIO1_LED1);
+ }
+ }
+ }
+}
+
+/*
+ * GPT1 callback.
+ */
+static void gpt1cb(GPTDriver *gptp) {
+ msg_t msg;
+
+ (void)gptp;
+ chSysLockFromIsr();
+ msg = chMBPostI(&mb[0], MSG_SEND_RIGHT);
+ if (msg != RDY_OK)
+ saturated = TRUE;
+ chSysUnlockFromIsr();
+}
+
+/*
+ * GPT2 callback.
+ */
+static void gpt2cb(GPTDriver *gptp) {
+ msg_t msg;
+
+ (void)gptp;
+ chSysLockFromIsr();
+ msg = chMBPostI(&mb[NUM_THREADS - 1], MSG_SEND_LEFT);
+ if (msg != RDY_OK)
+ saturated = TRUE;
+ chSysUnlockFromIsr();
+}
+
+/*
+ * GPT1 configuration.
+ */
+static const GPTConfig gpt1cfg = {
+ 1000000, /* 1MHz timer clock.*/
+ gpt1cb /* Timer callback.*/
+};
+
+/*
+ * GPT2 configuration.
+ */
+static const GPTConfig gpt2cfg = {
+ 1000000, /* 1MHz timer clock.*/
+ gpt2cb /* Timer callback.*/
+};
+
+
+/*===========================================================================*/
+/* Generic demo code. */
+/*===========================================================================*/
+
+static void print(char *p) {
+
+ while (*p) {
+ chSequentialStreamPut(&SD1, *p++);
+ }
+}
+
+static void println(char *p) {
+
+ while (*p) {
+ chSequentialStreamPut(&SD1, *p++);
+ }
+ chSequentialStreamWrite(&SD1, (uint8_t *)"\r\n", 2);
+}
+
+static void printn(uint32_t n) {
+ char buf[16], *p;
+
+ if (!n)
+ chSequentialStreamPut(&SD1, '0');
+ else {
+ p = buf;
+ while (n)
+ *p++ = (n % 10) + '0', n /= 10;
+ while (p > buf)
+ chSequentialStreamPut(&SD1, *--p);
+ }
+}
+
+/*
+ * Application entry point.
+ */
+int main(void) {
+ unsigned i;
+ gptcnt_t interval, threshold, worst;
+
+ /*
+ * System initializations.
+ * - HAL initialization, this also initializes the configured device drivers
+ * and performs the board-specific initializations.
+ * - Kernel initialization, the main() function becomes a thread and the
+ * RTOS is active.
+ */
+ halInit();
+ chSysInit();
+
+ /*
+ * Prepares the Serial driver 2 and GPT drivers 1 and 2.
+ */
+ sdStart(&SD1, NULL); /* Default is 38400-8-N-1.*/
+ gptStart(&GPTD1, &gpt1cfg);
+ gptStart(&GPTD2, &gpt2cfg);
+
+ /*
+ * Initializes the mailboxes and creates the worker threads.
+ */
+ for (i = 0; i < NUM_THREADS; i++) {
+ chMBInit(&mb[i], b[i], MAILBOX_SIZE);
+ chThdCreateStatic(waWorkerThread[i], sizeof waWorkerThread[i],
+ NORMALPRIO - 20, WorkerThread, (void *)i);
+ }
+
+ /*
+ * Test procedure.
+ */
+ println("");
+ println("*** ChibiOS/RT IRQ-STORM long duration test");
+ println("***");
+ print("*** Kernel: ");
+ println(CH_KERNEL_VERSION);
+#ifdef CH_COMPILER_NAME
+ print("*** Compiler: ");
+ println(CH_COMPILER_NAME);
+#endif
+ print("*** Architecture: ");
+ println(CH_ARCHITECTURE_NAME);
+#ifdef CH_CORE_VARIANT_NAME
+ print("*** Core Variant: ");
+ println(CH_CORE_VARIANT_NAME);
+#endif
+#ifdef CH_PORT_INFO
+ print("*** Port Info: ");
+ println(CH_PORT_INFO);
+#endif
+#ifdef PLATFORM_NAME
+ print("*** Platform: ");
+ println(PLATFORM_NAME);
+#endif
+#ifdef BOARD_NAME
+ print("*** Test Board: ");
+ println(BOARD_NAME);
+#endif
+ println("***");
+ print("*** System Clock: ");
+ printn(LPC122x_SYSCLK);
+ println("");
+ print("*** Iterations: ");
+ printn(ITERATIONS);
+ println("");
+ print("*** Randomize: ");
+ printn(RANDOMIZE);
+ println("");
+ print("*** Threads: ");
+ printn(NUM_THREADS);
+ println("");
+ print("*** Mailbox size: ");
+ printn(MAILBOX_SIZE);
+ println("");
+
+ println("");
+ worst = 0;
+ for (i = 1; i <= ITERATIONS; i++){
+ print("Iteration ");
+ printn(i);
+ println("");
+ saturated = FALSE;
+ threshold = 0;
+ for (interval = 2000; interval >= 20; interval -= interval / 10) {
+ gptStartContinuous(&GPTD1, interval - 1); /* Slightly out of phase.*/
+ gptStartContinuous(&GPTD2, interval + 1); /* Slightly out of phase.*/
+ chThdSleepMilliseconds(1000);
+ gptStopTimer(&GPTD1);
+ gptStopTimer(&GPTD2);
+ if (!saturated)
+ print(".");
+ else {
+ print("#");
+ if (threshold == 0)
+ threshold = interval;
+ }
+ }
+ /* Gives the worker threads a chance to empty the mailboxes before next
+ cycle.*/
+ chThdSleepMilliseconds(20);
+ println("");
+ print("Saturated at ");
+ printn(threshold);
+ println(" uS");
+ println("");
+ if (threshold > worst)
+ worst = threshold;
+ }
+ gptStopTimer(&GPTD1);
+ gptStopTimer(&GPTD2);
+
+ print("Worst case at ");
+ printn(worst);
+ println(" uS");
+ println("");
+ println("Test Complete");
+
+ /*
+ * Normal main() thread activity, nothing in this test.
+ */
+ while (TRUE) {
+ chThdSleepMilliseconds(5000);
+ }
+ return 0;
+}
diff --git a/testhal/LPC122x/IRQ_STORM/mcuconf.h b/testhal/LPC122x/IRQ_STORM/mcuconf.h
new file mode 100644
index 000000000..fca6b4cf9
--- /dev/null
+++ b/testhal/LPC122x/IRQ_STORM/mcuconf.h
@@ -0,0 +1,88 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
+ 2011,2012,2013 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/>.
+*/
+
+/*
+ * LPC1227 drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the driver
+ * is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 3...0 Lowest...highest.
+ */
+
+/*
+ * HAL driver system settings.
+ */
+#define LPC122x_PLLCLK_SOURCE SYSPLLCLKSEL_SYSOSC
+#define LPC122x_SYSPLL_MUL 3
+#define LPC122x_SYSPLL_DIV 8
+#define LPC122x_MAINCLK_SOURCE SYSMAINCLKSEL_PLLOUT
+#define LPC122x_SYSABHCLK_DIV 1
+
+/*
+ * ADC driver system settings.
+ */
+
+/*
+ * CAN driver system settings.
+ */
+
+/*
+ * GPT driver system settings.
+ */
+#define LPC122x_GPT_USE_CT16B0 TRUE
+#define LPC122x_GPT_USE_CT16B1 TRUE
+#define LPC122x_GPT_USE_CT32B0 TRUE
+#define LPC122x_GPT_USE_CT32B1 TRUE
+#define LPC122x_GPT_CT16B0_IRQ_PRIORITY 1
+#define LPC122x_GPT_CT16B1_IRQ_PRIORITY 3
+#define LPC122x_GPT_CT32B0_IRQ_PRIORITY 2
+#define LPC122x_GPT_CT32B1_IRQ_PRIORITY 2
+
+/*
+ * PWM driver system settings.
+ */
+
+/*
+ * SERIAL driver system settings.
+ */
+#define LPC122x_SERIAL_USE_UART0 TRUE
+#define LPC122x_SERIAL_FIFO_PRELOAD 16
+#define LPC122x_SERIAL_UART0CLKDIV 1
+#define LPC122x_SERIAL_UART0_IRQ_PRIORITY 3
+#define LPC122x_SERIAL_TXD0_SELECTOR TXD0_IS_PIO0_2
+#define LPC122x_SERIAL_RXD0_SELECTOR RXD0_IS_PIO0_1
+
+#define LPC122x_SERIAL_USE_UART1 FALSE
+#define LPC122x_SERIAL_FIFO_PRELOAD 16
+#define LPC122x_SERIAL_UART1CLKDIV 1
+#define LPC122x_SERIAL_UART1_IRQ_PRIORITY 3
+#define LPC122x_SERIAL_RXD1_SELECTOR RXD1_IS_PIO0_8
+#define LPC122x_SERIAL_TXD1_SELECTOR TXD1_IS_PIO0_9
+
+/*
+ * SPI driver system settings.
+ */
+#define LPC122x_SPI_USE_SSP0 TRUE
+#define LPC122x_SPI_SSP0CLKDIV 1
+#define LPC122x_SPI_SSP0_IRQ_PRIORITY 1
+#define LPC122x_SPI_SSP_ERROR_HOOK(spip) chSysHalt()
diff --git a/testhal/LPC122x/IRQ_STORM/readme.txt b/testhal/LPC122x/IRQ_STORM/readme.txt
new file mode 100644
index 000000000..58f143f05
--- /dev/null
+++ b/testhal/LPC122x/IRQ_STORM/readme.txt
@@ -0,0 +1,25 @@
+*****************************************************************************
+** ChibiOS/RT HAL - IRQ-STORM demo for LPC122x. **
+*****************************************************************************
+
+** TARGET **
+
+The demo will on an LPCXpresso LPC1114 board.
+
+** The Demo **
+
+The application demonstrates the use of the LPC11xx GPT, PAL and Serial drivers
+in order to implement a system stress demo.
+
+** Build Procedure **
+
+The demo has been tested using the free LPCXpresso toolchain but also with
+Codesourcery and YAGARTO.
+Just modify the TRGT line in the makefile in order to use different GCC ports.
+
+** Notes **
+
+Some files used by the demo are not part of ChibiOS/RT but are copyright of
+NXP and are licensed under a different license.
+
+ http://www.nxp.com