From 0770ffb75e3889ba303013fb00e7b4e8b78c5362 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 20 Aug 2009 12:54:53 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1091 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/io/platforms/LPC214x/lpc214x.h | 523 ++++++++++++++++++++++++++++++++++ os/io/platforms/LPC214x/lpc214x_ssp.c | 133 +++++++++ os/io/platforms/LPC214x/lpc214x_ssp.h | 54 ++++ os/io/platforms/LPC214x/pal_lld.c | 89 ++++++ os/io/platforms/LPC214x/pal_lld.h | 252 ++++++++++++++++ os/io/platforms/LPC214x/platform.dox | 83 ++++++ os/io/platforms/LPC214x/serial_lld.c | 337 ++++++++++++++++++++++ os/io/platforms/LPC214x/serial_lld.h | 179 ++++++++++++ os/io/platforms/LPC214x/vic.c | 63 ++++ os/io/platforms/LPC214x/vic.h | 41 +++ os/io/platforms/LPC214x/wfi.h | 35 +++ 11 files changed, 1789 insertions(+) create mode 100644 os/io/platforms/LPC214x/lpc214x.h create mode 100644 os/io/platforms/LPC214x/lpc214x_ssp.c create mode 100644 os/io/platforms/LPC214x/lpc214x_ssp.h create mode 100644 os/io/platforms/LPC214x/pal_lld.c create mode 100644 os/io/platforms/LPC214x/pal_lld.h create mode 100644 os/io/platforms/LPC214x/platform.dox create mode 100644 os/io/platforms/LPC214x/serial_lld.c create mode 100644 os/io/platforms/LPC214x/serial_lld.h create mode 100644 os/io/platforms/LPC214x/vic.c create mode 100644 os/io/platforms/LPC214x/vic.h create mode 100644 os/io/platforms/LPC214x/wfi.h (limited to 'os') diff --git a/os/io/platforms/LPC214x/lpc214x.h b/os/io/platforms/LPC214x/lpc214x.h new file mode 100644 index 000000000..e260da713 --- /dev/null +++ b/os/io/platforms/LPC214x/lpc214x.h @@ -0,0 +1,523 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file lpc214x.h + * @brief LPC214x register definitions + */ + +#ifndef _LPC214X_H_ +#define _LPC214X_H_ + +typedef volatile unsigned char IOREG8; +typedef volatile unsigned int IOREG32; + +/* + * System. + */ +#define MEMMAP (*((IOREG32 *)0xE01FC040)) +#define PCON (*((IOREG32 *)0xE01FC0C0)) +#define PCONP (*((IOREG32 *)0xE01FC0C4)) +#define VPBDIV (*((IOREG32 *)0xE01FC100)) +#define EXTINT (*((IOREG32 *)0xE01FC140)) +#define INTWAKE (*((IOREG32 *)0xE01FC144)) +#define EXTMODE (*((IOREG32 *)0xE01FC148)) +#define EXTPOLAR (*((IOREG32 *)0xE01FC14C)) +#define RSID (*((IOREG32 *)0xE01FC180)) +#define CSPR (*((IOREG32 *)0xE01FC184)) +#define SCS (*((IOREG32 *)0xE01FC1A0)) + +#define VPD_D4 0 +#define VPD_D1 1 +#define VPD_D2 2 +#define VPD_RESERVED 3 + +#define PCTIM0 (1 << 1) +#define PCTIM1 (1 << 2) +#define PCUART0 (1 << 3) +#define PCUART1 (1 << 4) +#define PCPWM0 (1 << 5) +#define PCI2C0 (1 << 7) +#define PCSPI0 (1 << 8) +#define PCRTC (1 << 9) +#define PCSPI1 (1 << 10) +#define PCAD0 (1 << 12) +#define PCI2C1 (1 << 19) +#define PCAD1 (1 << 20) +#define PCUSB (1 << 31) +#define PCALL (PCTIM0 | PCTIM1 | PCUART0 | PCUART1 | \ + PCPWM0 | PCI2C0 | PCSPI0 | PCRTC | PCSPI1 | \ + PCAD0 | PCI2C1 | PCAD1 | PCUSB) + +#define EINT0 1 +#define EINT1 2 +#define EINT2 4 +#define EINT3 8 + +#define EXTWAKE0 1 +#define EXTWAKE1 2 +#define EXTWAKE2 4 +#define EXTWAKE3 8 +#define USBWAKE 0x20 +#define BODWAKE 0x4000 +#define RTCWAKE 0x8000 + +#define EXTMODE0 1 +#define EXTMODE1 2 +#define EXTMODE2 4 +#define EXTMODE3 8 + +#define EXTPOLAR0 1 +#define EXTPOLAR1 2 +#define EXTPOLAR2 4 +#define EXTPOLAR3 8 + +typedef struct { + IOREG32 PLL_CON; + IOREG32 PLL_CFG; + IOREG32 PLL_STAT; + IOREG32 PLL_FEED; +} PLL; + +#define PLL0Base ((PLL *)0xE01FC080) +#define PLL1Base ((PLL *)0xE01FC0A0) +#define PLL0CON (PLL0Base->PLL_CON) +#define PLL0CFG (PLL0Base->PLL_CFG) +#define PLL0STAT (PLL0Base->PLL_STAT) +#define PLL0FEED (PLL0Base->PLL_FEED) +#define PLL1CON (PLL1Base->PLL_CON) +#define PLL1CFG (PLL1Base->PLL_CFG) +#define PLL1STAT (PLL1Base->PLL_STAT) +#define PLL1FEED (PLL1Base->PLL_FEED) + +/* + * Pins. + */ +typedef struct { + IOREG32 PS_SEL0; + IOREG32 PS_SEL1; + IOREG32 PS_SEL2; +} PS; + +#define PSBase ((PS *)0xE002C000) +#define PINSEL0 (PSBase->PS_SEL0) +#define PINSEL1 (PSBase->PS_SEL1) +#define PINSEL2 (PSBase->PS_SEL2) + +/* + * VIC + */ +#define SOURCE_WDT 0 +#define SOURCE_ARMCore0 2 +#define SOURCE_ARMCore1 3 +#define SOURCE_Timer0 4 +#define SOURCE_Timer1 5 +#define SOURCE_UART0 6 +#define SOURCE_UART1 7 +#define SOURCE_PWM0 8 +#define SOURCE_I2C0 9 +#define SOURCE_SPI0 10 +#define SOURCE_SPI1 11 +#define SOURCE_PLL 12 +#define SOURCE_RTC 13 +#define SOURCE_EINT0 14 +#define SOURCE_EINT1 15 +#define SOURCE_EINT2 16 +#define SOURCE_EINT3 17 +#define SOURCE_ADC0 18 +#define SOURCE_I2C1 19 +#define SOURCE_BOD 20 +#define SOURCE_ADC1 21 +#define SOURCE_USB 22 + +#define INTMASK(n) (1 << (n)) +#define ALLINTMASK (INTMASK(SOURCE_WDT) | INTMASK(SOURCE_ARMCore0) | \ + INTMASK(SOURCE_ARMCore1) | INTMASK(SOURCE_Timer0) | \ + INTMASK(SOURCE_Timer1) | INTMASK(SOURCE_UART0) | \ + INTMASK(SOURCE_UART1) | INTMASK(SOURCE_PWM0) | \ + INTMASK(SOURCE_I2C0) | INTMASK(SOURCE_SPI0) | \ + INTMASK(SOURCE_SPI1) | INTMASK(SOURCE_PLL) | \ + INTMASK(SOURCE_RTC) | INTMASK(SOURCE_EINT0) | \ + INTMASK(SOURCE_EINT1) | INTMASK(SOURCE_EINT2) | \ + INTMASK(SOURCE_EINT3) | INTMASK(SOURCE_ADC0) | \ + INTMASK(SOURCE_I2C1) | INTMASK(SOURCE_BOD) | \ + INTMASK(SOURCE_ADC1) | INTMASK(SOURCE_USB)) + +typedef struct { + IOREG32 VIC_IRQStatus; + IOREG32 VIC_FIQStatus; + IOREG32 VIC_RawIntr; + IOREG32 VIC_IntSelect; + IOREG32 VIC_IntEnable; + IOREG32 VIC_IntEnClear; + IOREG32 VIC_SoftInt; + IOREG32 VIC_SoftIntClear; + IOREG32 VIC_Protection; + IOREG32 unused1[3]; + IOREG32 VIC_VectAddr; + IOREG32 VIC_DefVectAddr; + IOREG32 unused2[50]; + IOREG32 VIC_VectAddrs[16]; + IOREG32 unused3[48]; + IOREG32 VIC_VectCntls[16]; +} VIC; + +#define VICBase ((VIC *)0xFFFFF000) +#define VICVectorsBase ((IOREG32 *)0xFFFFF100) +#define VICControlsBase ((IOREG32 *)0xFFFFF200) + +#define VICIRQStatus (VICBase->VIC_IRQStatus) +#define VICFIQStatus (VICBase->VIC_FIQStatus) +#define VICRawIntr (VICBase->VIC_RawIntr) +#define VICIntSelect (VICBase->VIC_IntSelect) +#define VICIntEnable (VICBase->VIC_IntEnable) +#define VICIntEnClear (VICBase->VIC_IntEnClear) +#define VICSoftInt (VICBase->VIC_SoftInt) +#define VICSoftIntClear (VICBase->VIC_SoftIntClear) +#define VICProtection (VICBase->VIC_Protection) +#define VICVectAddr (VICBase->VIC_VectAddr) +#define VICDefVectAddr (VICBase->VIC_DefVectAddr) + +#define VICVectAddrs(n) (VICBase->VIC_VectAddrs[n]) +#define VICVectCntls(n) (VICBase->VIC_VectCntls[n]) + +/* + * MAM. + */ +typedef struct { + IOREG32 MAM_Control; + IOREG32 MAM_Timing; +} MAM; + +#define MAMBase ((MAM *)0xE01FC000) +#define MAMCR (MAMBase->MAM_Control) +#define MAMTIM (MAMBase->MAM_Timing) + +/* + * GPIO - FIO. + */ +typedef struct { + IOREG32 IO_PIN; + IOREG32 IO_SET; + IOREG32 IO_DIR; + IOREG32 IO_CLR; +} GPIO; + +#define GPIO0Base ((GPIO *)0xE0028000) +#define IO0PIN (GPIO0Base->IO_PIN) +#define IO0SET (GPIO0Base->IO_SET) +#define IO0DIR (GPIO0Base->IO_DIR) +#define IO0CLR (GPIO0Base->IO_CLR) + +#define GPIO1Base ((GPIO *)0xE0028010) +#define IO1PIN (GPIO1Base->IO_PIN) +#define IO1SET (GPIO1Base->IO_SET) +#define IO1DIR (GPIO1Base->IO_DIR) +#define IO1CLR (GPIO1Base->IO_CLR) + +typedef struct { + IOREG32 FIO_DIR; + IOREG32 unused1; + IOREG32 unused2; + IOREG32 unused3; + IOREG32 FIO_MASK; + IOREG32 FIO_PIN; + IOREG32 FIO_SET; + IOREG32 FIO_CLR; +} FIO; + +#define FIO0Base ((FIO *)0x3FFFC000) +#define FIO0DIR (FIO0Base->FIO_DIR) +#define FIO0MASK (FIO0Base->FIO_MASK) +#define FIO0PIN (FIO0Base->FIO_PIN) +#define FIO0SET (FIO0Base->FIO_SET) +#define FIO0CLR (FIO0Base->FIO_CLR) + +#define FIO1Base ((FIO *)0x3FFFC020) +#define FIO1DIR (FIO1Base->FIO_DIR) +#define FIO1MASK (FIO1Base->FIO_MASK) +#define FIO1PIN (FIO1Base->FIO_PIN) +#define FIO1SET (FIO1Base->FIO_SET) +#define FIO1CLR (FIO1Base->FIO_CLR) + +/* + * UART. + */ +typedef struct { + union { + IOREG32 UART_RBR; + IOREG32 UART_THR; + IOREG32 UART_DLL; + }; + union { + IOREG32 UART_IER; + IOREG32 UART_DLM; + }; + union { + IOREG32 UART_IIR; + IOREG32 UART_FCR; + }; + IOREG32 UART_LCR; + IOREG32 UART_MCR; // UART1 only + IOREG32 UART_LSR; + IOREG32 unused18; + IOREG32 UART_SCR; + IOREG32 UART_ACR; + IOREG32 unused24; + IOREG32 UART_FDR; + IOREG32 unused2C; + IOREG32 UART_TER; +} UART; + +#define U0Base ((UART *)0xE000C000) +#define U0RBR (U0Base->UART_RBR) +#define U0THR (U0Base->UART_THR) +#define U0DLL (U0Base->UART_DLL) +#define U0IER (U0Base->UART_IER) +#define U0DLM (U0Base->UART_DLM) +#define U0IIR (U0Base->UART_IIR) +#define U0FCR (U0Base->UART_FCR) +#define U0LCR (U0Base->UART_LCR) +#define U0LSR (U0Base->UART_LSR) +#define U0SCR (U0Base->UART_SCR) +#define U0ACR (U0Base->UART_ACR) +#define U0FDR (U0Base->UART_FDR) +#define U0TER (U0Base->UART_TER) + +#define U1Base ((UART *)0xE0010000) +#define U1RBR (U1Base->UART_RBR) +#define U1THR (U1Base->UART_THR) +#define U1DLL (U1Base->UART_DLL) +#define U1IER (U1Base->UART_IER) +#define U1DLM (U1Base->UART_DLM) +#define U1IIR (U1Base->UART_IIR) +#define U1FCR (U1Base->UART_FCR) +#define U1MCR (U1Base->UART_MCR) +#define U1LCR (U1Base->UART_LCR) +#define U1LSR (U1Base->UART_LSR) +#define U1SCR (U1Base->UART_SCR) +#define U1ACR (U1Base->UART_ACR) +#define U1FDR (U1Base->UART_FDR) +#define U1TER (U1Base->UART_TER) + +#define IIR_SRC_MASK 0x0F +#define IIR_SRC_NONE 0x01 +#define IIR_SRC_TX 0x02 +#define IIR_SRC_RX 0x04 +#define IIR_SRC_ERROR 0x06 +#define IIR_SRC_TIMEOUT 0x0C + +#define IER_RBR 1 +#define IER_THRE 2 +#define IER_STATUS 4 + +#define IIR_INT_PENDING 1 + +#define LCR_WL5 0 +#define LCR_WL6 1 +#define LCR_WL7 2 +#define LCR_WL8 3 +#define LCR_STOP1 0 +#define LCR_STOP2 4 +#define LCR_NOPARITY 0 +#define LCR_PARITYODD 0x08 +#define LCR_PARITYEVEN 0x18 +#define LCR_PARITYONE 0x28 +#define LCR_PARITYZERO 0x38 +#define LCR_BREAK_ON 0x40 +#define LCR_DLAB 0x80 + +#define FCR_ENABLE 1 +#define FCR_RXRESET 2 +#define FCR_TXRESET 4 +#define FCR_TRIGGER0 0 +#define FCR_TRIGGER1 0x40 +#define FCR_TRIGGER2 0x80 +#define FCR_TRIGGER3 0xC0 + +#define LSR_RBR_FULL 1 +#define LSR_OVERRUN 2 +#define LSR_PARITY 4 +#define LSR_FRAMING 8 +#define LSR_BREAK 0x10 +#define LSR_THRE 0x20 +#define LSR_TEMT 0x40 +#define LSR_RXFE 0x80 + +#define TER_ENABLE 0x80 + +/* + * SSP. + */ +typedef struct { + IOREG32 SSP_CR0; + IOREG32 SSP_CR1; + IOREG32 SSP_DR; + IOREG32 SSP_SR; + IOREG32 SSP_CPSR; + IOREG32 SSP_IMSC; + IOREG32 SSP_RIS; + IOREG32 SSP_MIS; + IOREG32 SSP_ICR; +} SSP; + +#define SSPBase ((SSP *)0xE0068000) +#define SSPCR0 (SSPBase->SSP_CR0) +#define SSPCR1 (SSPBase->SSP_CR1) +#define SSPDR (SSPBase->SSP_DR) +#define SSPSR (SSPBase->SSP_SR) +#define SSPCPSR (SSPBase->SSP_CPSR) +#define SSPIMSC (SSPBase->SSP_IMSC) +#define SSPRIS (SSPBase->SSP_RIS) +#define SSPMIS (SSPBase->SSP_MIS) +#define SSPICR (SSPBase->SSP_ICR) + +#define CR0_DSS4BIT 3 +#define CR0_DSS5BIT 4 +#define CR0_DSS6BIT 5 +#define CR0_DSS7BIT 6 +#define CR0_DSS8BIT 7 +#define CR0_DSS9BIT 8 +#define CR0_DSS10BIT 9 +#define CR0_DSS11BIT 0xA +#define CR0_DSS12BIT 0xB +#define CR0_DSS13BIT 0xC +#define CR0_DSS14BIT 0xD +#define CR0_DSS15BIT 0xE +#define CR0_DSS16BIT 0xF +#define CR0_FRFSPI 0 +#define CR0_FRFSSI 0x10 +#define CR0_FRFMW 0x20 +#define CR0_CPOL 0x40 +#define CR0_CPHA 0x80 +#define CR0_CLOCKRATE(n) ((n) << 8) + +#define CR1_LBM 1 +#define CR1_SSE 2 +#define CR1_MS 4 +#define CR1_SOD 8 + +#define SR_TFE 1 +#define SR_TNF 2 +#define SR_RNE 4 +#define SR_RFF 8 +#define SR_BSY 0x10 + +#define IMSC_ROR 1 +#define IMSC_RT 2 +#define IMSC_RX 4 +#define IMSC_TX 8 + +#define RIS_ROR 1 +#define RIS_RT 2 +#define RIS_RX 4 +#define RIS_TX 8 + +#define MIS_ROR 1 +#define MIS_RT 2 +#define MIS_RX 4 +#define MIS_TX 8 + +#define ICR_ROR 1 +#define ICR_RT 2 + +/* + * Timers/Counters. + */ +typedef struct { + IOREG32 TC_IR; + IOREG32 TC_TCR; + IOREG32 TC_TC; + IOREG32 TC_PR; + IOREG32 TC_PC; + IOREG32 TC_MCR; + IOREG32 TC_MR0; + IOREG32 TC_MR1; + IOREG32 TC_MR2; + IOREG32 TC_MR3; + IOREG32 TC_CCR; + IOREG32 TC_CR0; + IOREG32 TC_CR1; + IOREG32 TC_CR2; + IOREG32 TC_CR3; + IOREG32 TC_EMR; + IOREG32 TC_CTCR; +} TC; + +#define T0Base ((TC *)0xE0004000) +#define T0IR (T0Base->TC_IR) +#define T0TCR (T0Base->TC_TCR) +#define T0TC (T0Base->TC_TC) +#define T0PR (T0Base->TC_PR) +#define T0PC (T0Base->TC_PC) +#define T0MCR (T0Base->TC_MCR) +#define T0MR0 (T0Base->TC_MR0) +#define T0MR1 (T0Base->TC_MR1) +#define T0MR2 (T0Base->TC_MR2) +#define T0MR3 (T0Base->TC_MR3) +#define T0CCR (T0Base->TC_CCR) +#define T0CR0 (T0Base->TC_CR0) +#define T0CR1 (T0Base->TC_CR1) +#define T0CR2 (T0Base->TC_CR2) +#define T0CR3 (T0Base->TC_CR3) +#define T0EMR (T0Base->TC_EMR) +#define T0CTCR (T0Base->TC_CTCR) + +#define T1Base ((TC *)0xE0008000) +#define T1IR (T1Base->TC_IR) +#define T1TCR (T1Base->TC_TCR) +#define T1TC (T1Base->TC_TC) +#define T1PR (T1Base->TC_PR) +#define T1PC (T1Base->TC_PC) +#define T1MCR (T1Base->TC_MCR) +#define T1MR0 (T1Base->TC_MR0) +#define T1MR1 (T1Base->TC_MR1) +#define T1MR2 (T1Base->TC_MR2) +#define T1MR3 (T1Base->TC_MR3) +#define T1CCR (T1Base->TC_CCR) +#define T1CR0 (T1Base->TC_CR0) +#define T1CR1 (T1Base->TC_CR1) +#define T1CR2 (T1Base->TC_CR2) +#define T1CR3 (T1Base->TC_CR3) +#define T1EMR (T1Base->TC_EMR) +#define T1CTCR (T1Base->TC_CTCR) + +/* + * Watchdog. + */ +typedef struct { + IOREG32 WD_MOD; + IOREG32 WD_TC; + IOREG32 WD_FEED; + IOREG32 WD_TV; +} WD; + +#define WDBase ((WD *)0xE0000000) +#define WDMOD (WDBase->WD_MOD) +#define WDTC (WDBase->WD_TC) +#define WDFEED (WDBase->WD_FEED) +#define WDTV (WDBase->WD_TV) + +/* + * DAC. + */ +#define DACR (*((IOREG32 *)0xE006C000)) + +#endif /* _LPC214X_H_ */ + diff --git a/os/io/platforms/LPC214x/lpc214x_ssp.c b/os/io/platforms/LPC214x/lpc214x_ssp.c new file mode 100644 index 000000000..fb7b70183 --- /dev/null +++ b/os/io/platforms/LPC214x/lpc214x_ssp.c @@ -0,0 +1,133 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC214x/lpc214x_ssp.c + * @brief LPC214x SSP driver code. + * @addtogroup LPC214x_SSP + * @{ + */ + +#include +#include + +#include "lpc214x.h" +#include "lpc214x_ssp.h" + +#if LPC214x_SSP_USE_MUTEX +static Semaphore me; +#endif + +/** + * @brief Aquires access to the SSP bus. + * @note This function also handles the mutual exclusion on the SSP bus if + * the @p LPC214x_SSP_USE_MUTEX option is enabled. + */ +void sspAcquireBus(void) { + +#if LPC214x_SSP_USE_MUTEX + chSemWait(&me); +#endif + palClearPad(IOPORT_A, 20); +} + +/** + * @brief Releases the SSP bus. + * @note This function also handles the mutual exclusion on the SSP bus if + * the @p LPC214x_SSP_USE_MUTEX option is enabled. + */ +void sspReleaseBus(void) { + + palClearPad(IOPORT_A, 20); +#if LPC214x_SSP_USE_MUTEX + chSemSignal(&me); +#endif +} + +/** + * @brief Synchronous SSP transfer. + * @param[in] in pointer to the incoming data buffer, if this parameter is set + * to @p NULL then the incoming data is discarded + * @param[out] out pointer to the outgoing data buffer, if this parameter is + * set to @p NULL then 0xFF bytes will be output + * @param[in] n the number of bytes to be transferred + * @note The transfer is performed in a software loop and is not interrupt + * driven for performance reasons, this function should be invoked + * by a low priority thread in order to "play nice" with the + * rest of the system. This kind of peripheral would really need a + * dedicated DMA channel. + */ +void sspRW(uint8_t *in, uint8_t *out, size_t n) { + int icnt, ocnt; + + SSP *ssp = SSPBase; + icnt = ocnt = n; + while (icnt) { + + if (ssp->SSP_SR & SR_RNE) { + if (in) + *in++ = ssp->SSP_DR; + else + ssp->SSP_DR; + icnt--; + continue; /* Priority over transmission. */ + } + + if (ocnt && (ssp->SSP_SR & SR_TNF)) { + if (out) + ssp->SSP_DR = *out++; + else + ssp->SSP_DR = 0xFF; + ocnt--; + } + } +} + +/** + * @brief SSP setup. + * @param[in] cpsr the value for the @p CPSR register + * @param[in] cr0 the value for the @p CR0 register + * @param[in] cr1 the value for the @p CR1 register + */ +void ssp_setup(int cpsr, int cr0, int cr1) { + + SSP *ssp = SSPBase; + ssp->SSP_CR1 = 0; + ssp->SSP_CR0 = cr0; + ssp->SSP_CPSR = cpsr; + ssp->SSP_CR1 = cr1 | CR1_SSE; +} + +/** + * @brief SSP subsystem initialization. + */ +void ssp_init(void) { + + /* Enables the SPI1 clock */ + PCONP = (PCONP & PCALL) | PCSPI1; + + /* Clock = PCLK / 2 (fastest). */ + ssp_setup(2, CR0_DSS8BIT | CR0_FRFSPI | CR0_CLOCKRATE(0), 0); + +#if LPC214x_SSP_USE_MUTEX + chSemInit(&me, 1); +#endif +} + +/** @} */ diff --git a/os/io/platforms/LPC214x/lpc214x_ssp.h b/os/io/platforms/LPC214x/lpc214x_ssp.h new file mode 100644 index 000000000..3ad25b37a --- /dev/null +++ b/os/io/platforms/LPC214x/lpc214x_ssp.h @@ -0,0 +1,54 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC214x/lpc214x_ssp.h + * @brief LPC214x SSP driver macros and structures. + * @addtogroup LPC214x_SSP + * @{ + */ + +#ifndef _LPC214x_SSP_H_ +#define _LPC214x_SSP_H_ + +/** + * @brief SSP bus mutual exclusion control. + * @details Configuration parameter, if set to @p TRUE enforces mutual + * exclusion when invoking @p sspAcquireBus() and @p sspReleaseBus(). + * @note The internally used synchronization mechanism is a @p Semaphore. + */ +#if !defined(LPC214x_SSP_USE_MUTEX) || defined(__DOXYGEN__) +#define LPC214x_SSP_USE_MUTEX TRUE +#endif + +#ifdef __cplusplus +} +#endif + void ssp_init(void); + void ssp_setup(int cpsr, int cr0, int cr1); + void sspAcquireBus(void); + void sspReleaseBus(void); + void sspRW(uint8_t *in, uint8_t *out, size_t n); +#ifdef __cplusplus +} +#endif + +#endif /* _LPC214x_SSP_H_*/ + +/** @} */ diff --git a/os/io/platforms/LPC214x/pal_lld.c b/os/io/platforms/LPC214x/pal_lld.c new file mode 100644 index 000000000..666afef55 --- /dev/null +++ b/os/io/platforms/LPC214x/pal_lld.c @@ -0,0 +1,89 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC214x/pal_lld.c + * @brief LPC214x FIO low level driver code + * @addtogroup LPC214x_PAL + * @{ + */ + +#include +#include + +/** + * @brief LPC214x I/O ports configuration. + * @details FIO units and PINSEL registers initialization. + * + * @param[in] config the LPC214x ports configuration + */ +void _pal_lld_init(const LPC214xFIOConfig *config) { + + /* Enables the access through the fast registers.*/ + SCS = 3; + + /* I/O pads initial assignment, device drivers may change this setup at a + * later time.*/ + PINSEL0 = config->pinsel0; + PINSEL1 = config->pinsel1; + PINSEL2 = config->pinsel2; + + /* I/O pads direction initial setting.*/ + FIO0Base->FIO_MASK = 0; + FIO0Base->FIO_PIN = config->P0Data.pin; + FIO0Base->FIO_DIR = config->P0Data.dir; + FIO1Base->FIO_MASK = 0; + FIO1Base->FIO_PIN = config->P1Data.pin; + FIO1Base->FIO_DIR = config->P1Data.dir; +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @note This function is not meant to be invoked directly by the application + * code. + * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high + * state. + * @note This function does not alter the @p PINSELx registers. Alternate + * functions setup must be handled by device-specific code. + */ +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + uint_fast8_t mode) { + + switch (mode) { + case PAL_MODE_RESET: + case PAL_MODE_INPUT: + port->FIO_DIR &= ~mask; + break; + case PAL_MODE_UNCONNECTED: + port->FIO_PIN |= mask; + case PAL_MODE_OUTPUT_PUSHPULL: + port->FIO_DIR |= mask; + break; + } +} + +/** @} */ diff --git a/os/io/platforms/LPC214x/pal_lld.h b/os/io/platforms/LPC214x/pal_lld.h new file mode 100644 index 000000000..50e0ff4a5 --- /dev/null +++ b/os/io/platforms/LPC214x/pal_lld.h @@ -0,0 +1,252 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC214x/pal_lld.h + * @brief LPC214x FIO low level driver header + * @addtogroup LPC214x_PAL + * @{ + */ + +#ifndef _PAL_LLD_H_ +#define _PAL_LLD_H_ + +#include "lpc214x.h" + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +#undef PAL_MODE_INPUT_PULLUP +#undef PAL_MODE_INPUT_PULLDOWN +#undef PAL_MODE_OUTPUT_OPENDRAIN + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @brief FIO port setup info. + */ +typedef struct { + /** Initial value for FIO_PIN register.*/ + uint32_t pin; + /** Initial value for FIO_DIR register.*/ + uint32_t dir; +} lpc214x_fio_setup_t; + +/** + * @brief LPC214x FIO static initializer. + * @details An instance of this structure must be passed to @p palInit() at + * system startup time in order to initialized the digital I/O + * subsystem. This represents only the initial setup, specific pads + * or whole ports can be reprogrammed at later time. + */ +typedef struct { + /** @brief PINSEL0 initial value.*/ + uint32_t pinsel0; + /** @brief PINSEL1 initial value.*/ + uint32_t pinsel1; + /** @brief PINSEL2 initial value.*/ + uint32_t pinsel2; + /** @brief Port 0 setup data.*/ + lpc214x_fio_setup_t P0Data; + /** @brief Port 1 setup data.*/ + lpc214x_fio_setup_t P1Data; +} LPC214xFIOConfig; + +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 32 + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Port Identifier. + */ +typedef FIO * ioportid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/*===========================================================================*/ + +/** + * @brief FIO port 0 identifier. + */ +#define IOPORT_A FIO0Base + +/** + * @brief FIO port 1 identifier. + */ +#define IOPORT_B FIO1Base + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, please put them in a file named ioports_lld.c if so. */ +/*===========================================================================*/ + +/** + * @brief FIO subsystem initialization. + * @details Enables the access through the fast registers. + */ +#define pal_lld_init(config) _pal_lld_init(config) + +/** + * @brief Reads an I/O port. + * @details This function is implemented by reading the FIO PIN register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @return the port bits + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_readport(port) ((port)->FIO_PIN) + +/** + * @brief Reads the output latch. + * @details This function is implemented by reading the FIO SET register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @return The latched logical states. + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_readlatch(port) ((port)->FIO_SET) + +/** + * @brief Writes a bits mask on a I/O port. + * @details This function is implemented by writing the FIO PIN register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be written on the specified port + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_writeport(port, bits) ((port)->FIO_PIN = (bits)) + +/** + * @brief Sets a bits mask on a I/O port. + * @details This function is implemented by writing the FIO SET register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be ORed on the specified port + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_setport(port, bits) ((port)->FIO_SET = (bits)) + +/** + * @brief Clears a bits mask on a I/O port. + * @details This function is implemented by writing the FIO CLR register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be cleared on the specified port + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_clearport(port, bits) ((port)->FIO_CLR = (bits)) + +/** + * @brief Writes a value on an I/O bus. + * @details This function is implemented by writing the FIO PIN and MASK + * registers, the implementation is not atomic because the multiple + * accesses. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] offset the group bit offset within the port + * @param[in] bits the bits to be written. Values exceeding the group width + * are masked. + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_writegroup(port, mask, offset, bits) { \ + (port)->FIO_MASK = (mask) << (offset); \ + (port)->FIO_PIN = (bits) << (offset); \ + (port)->FIO_MASK = 0; \ +} + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @note This function is not meant to be invoked directly by the application + * code. + * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high + * state. + * @note This function does not alter the @p PINSELx registers. Alternate + * functions setup must be handled by device-specific code. + */ +#define pal_lld_setgroupmode(port, mask, mode) \ + _pal_lld_setgroupmode(port, mask, mode) + +/** + * @brief Writes a logical state on an output pad. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * @param[out] bit the logical value, the value must be @p 0 or @p 1 + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit) + +/** + * @brief FIO port setup. + * @details This function programs the pins direction within a port. + */ +#define pal_lld_lpc214x_set_direction(port, dir) { \ + (port)->FIO_DIR = (dir); \ +} + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(const LPC214xFIOConfig *config); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + uint_fast8_t mode); +#ifdef __cplusplus +} +#endif + +#endif /* _PAL_LLD_H_ */ + +/** @} */ diff --git a/os/io/platforms/LPC214x/platform.dox b/os/io/platforms/LPC214x/platform.dox new file mode 100644 index 000000000..e46ac4328 --- /dev/null +++ b/os/io/platforms/LPC214x/platform.dox @@ -0,0 +1,83 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @defgroup LPC214x LPC214x Support + * @brief LPC214x specific support. + * @details The LPC214x support includes: + * - VIC support code. + * - I/O ports driver. + * - Buffered, interrupt driven, serial driver. + * - SSP driver. + * - A MMC/SD demo driver. + * - A timer driven buzzer demo driver. + * - A minimal demo, useful as project template. + * - A demo supporting the kernel test suite. + * - A C++ demo supporting the kernel test suite. + * . + * @ingroup ARM7 + */ + +/** + * @defgroup LPC214x_VIC VIC Support + * @brief VIC peripheral support. + * + * @ingroup LPC214x + */ + +/** + * @defgroup LPC214x_PAL I/O Ports Support + * @brief I/O Ports peripherals support. + * @details This module supports the LPC214x FIO controller. The controller + * supports the following features (see @ref PAL): + * - 32 bits wide ports. + * - Atomic set/reset functions. + * - Output latched regardless of the pad setting. + * - Direct read of input pads regardless of the pad setting. + * . + *

Supported Setup Modes

+ * - @p PAL_MODE_RESET. + * - @p PAL_MODE_UNCONNECTED. + * - @p PAL_MODE_INPUT. + * - @p PAL_MODE_OUTPUT_PUSHPULL. + * . + * Any attempt to setup an invalid mode is ignored. + * + *

Suboptimal Behavior

+ * - Pad/port toggling operations are not atomic. + * - Pad/group mode setup is not atomic. + * . + * @ingroup LPC214x + */ + +/** + * @defgroup LPC214x_SERIAL UART Support + * @brief UART peripherals support. + * @details The serial driver supports the LPC214x UART peripherals. + * + * @ingroup LPC214x + */ + +/** + * @defgroup LPC214x_SSP SSP Support + * @brief SSP peripheral support. + * @details This SPI driver supports the LPC214x SSP peripheral. + * + * @ingroup LPC214x + */ diff --git a/os/io/platforms/LPC214x/serial_lld.c b/os/io/platforms/LPC214x/serial_lld.c new file mode 100644 index 000000000..8c76a4352 --- /dev/null +++ b/os/io/platforms/LPC214x/serial_lld.c @@ -0,0 +1,337 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC214x/serial_lld.c + * @brief LPC214x low level serial driver code + * @addtogroup LPC214x_SERIAL + * @{ + */ + +#include +#include + +#include "board.h" +#include "vic.h" + +#if USE_LPC214x_UART0 || defined(__DOXYGEN__) +/** @brief UART0 serial driver identifier.*/ +SerialDriver COM1; +#endif + +#if USE_LPC214x_UART1 || defined(__DOXYGEN__) +/** @brief UART1 serial driver identifier.*/ +SerialDriver COM2; +#endif + +/** @brief Driver default configuration.*/ +static const SerialDriverConfig default_config = { + 38400, + LCR_WL8 | LCR_STOP1 | LCR_NOPARITY, + FCR_TRIGGER0 +}; + +/*===========================================================================*/ +/* Low Level Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief UART initialization. + * @param[in] u pointer to an UART I/O block + * @param[in] config the architecture-dependent serial driver configuration + */ +void uart_init(UART *u, const SerialDriverConfig *config) { + + uint32_t div = PCLK / (config->baud_rate << 4); + u->UART_LCR = config->lcr | LCR_DLAB; + u->UART_DLL = div; + u->UART_DLM = div >> 8; + u->UART_LCR = config->lcr; + u->UART_FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | config->fcr; + u->UART_ACR = 0; + u->UART_FDR = 0x10; + u->UART_TER = TER_ENABLE; + u->UART_IER = IER_RBR | IER_STATUS; +} + +/** + * @brief UART de-initialization. + * @param[in] u pointer to an UART I/O block + */ +void uart_deinit(UART *u) { + + u->UART_DLL = 1; + u->UART_DLM = 0; + u->UART_FDR = 0x10; + u->UART_IER = 0; + u->UART_FCR = FCR_RXRESET | FCR_TXRESET; + u->UART_LCR = 0; + u->UART_ACR = 0; + u->UART_TER = TER_ENABLE; +} + +/** + * @brief Error handling routine. + * @param[in] err UART LSR register value + * @param[in] sdp communication channel associated to the USART + */ +static void set_error(IOREG32 err, SerialDriver *sdp) { + sdflags_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(); + sdAddFlagsI(sdp, sts); + chSysUnlockFromIsr(); +} + +#if defined(__GNU__) +__attribute__((noinline)) +#endif +/** + * @brief Common IRQ handler. + * @param[in] u pointer to an UART I/O block + * @param[in] sdp communication channel associated to the UART + * @note Tries hard to clear all the pending interrupt sources, we dont want to + * go through the whole ISR and have another interrupt soon after. + */ +static void serve_interrupt(UART *u, SerialDriver *sdp) { + + while (TRUE) { + + switch (u->UART_IIR & IIR_SRC_MASK) { + case IIR_SRC_NONE: + return; + case IIR_SRC_ERROR: + set_error(u->UART_LSR, sdp); + break; + case IIR_SRC_TIMEOUT: + case IIR_SRC_RX: + while (u->UART_LSR & LSR_RBR_FULL) { + chSysLockFromIsr(); + if (chIQPutI(&sdp->d2.iqueue, u->UART_RBR) < Q_OK) + sdAddFlagsI(sdp, SD_OVERRUN_ERROR); + chSysUnlockFromIsr(); + } + chSysLockFromIsr(); + chEvtBroadcastI(&sdp->d1.ievent); + chSysUnlockFromIsr(); + break; + case IIR_SRC_TX: + { +#if UART_FIFO_PRELOAD > 0 + int i = UART_FIFO_PRELOAD; + do { + chSysLockFromIsr(); + msg_t b = chOQGetI(&sdp->d2.oqueue); + chSysUnlockFromIsr(); + if (b < Q_OK) { + u->UART_IER &= ~IER_THRE; + chSysLockFromIsr(); + chEvtBroadcastI(&sdp->d1.oevent); + chSysUnlockFromIsr(); + break; + } + u->UART_THR = b; + } while (--i); +#else + chSysLockFromIsr(); + msg_t b = sdRequestDataI(sdp); + chSysUnlockFromIsr(); + if (b < Q_OK) + u->UART_IER &= ~IER_THRE; + else + u->UART_THR = b; +#endif + } + default: + (void) u->UART_THR; + (void) u->UART_RBR; + } + } +} + +#if UART_FIFO_PRELOAD > 0 +static void preload(UART *u, SerialDriver *sdp) { + + if (u->UART_LSR & LSR_THRE) { + int i = UART_FIFO_PRELOAD; + do { + chSysLockFromIsr(); + msg_t b = chOQGetI(&sdp->d2.oqueue); + chSysUnlockFromIsr(); + if (b < Q_OK) { + chSysLockFromIsr(); + chEvtBroadcastI(&sdp->d1.oevent); + chSysUnlockFromIsr(); + return; + } + u->UART_THR = b; + } while (--i); + } + u->UART_IER |= IER_THRE; +} +#endif + +#if USE_LPC214x_UART0 || defined(__DOXYGEN__) +static void notify1(void) { +#if UART_FIFO_PRELOAD > 0 + + preload(U0Base, &COM1); +#else + UART *u = U0Base; + + if (u->UART_LSR & LSR_THRE) { + chSysLockFromIsr(); + u->UART_THR = chOQGetI(&COM1.sd_oqueue); + chSysUnlockFromIsr(); + } + u->UART_IER |= IER_THRE; +#endif +} +#endif + +#if USE_LPC214x_UART1 || defined(__DOXYGEN__) +static void notify2(void) { +#if UART_FIFO_PRELOAD > 0 + + preload(U1Base, &COM2); +#else + UART *u = U1Base; + + if (u->UART_LSR & LSR_THRE) + u->UART_THR = chOQGetI(&COM2.sd_oqueue); + u->UART_IER |= IER_THRE; +#endif +} +#endif + +/*===========================================================================*/ +/* Low Level Driver interrupt handlers. */ +/*===========================================================================*/ + +#if USE_LPC214x_UART0 || defined(__DOXYGEN__) +CH_IRQ_HANDLER(UART0IrqHandler) { + + CH_IRQ_PROLOGUE(); + + serve_interrupt(U0Base, &COM1); + VICVectAddr = 0; + + CH_IRQ_EPILOGUE(); +} +#endif + +#if USE_LPC214x_UART1 || defined(__DOXYGEN__) +CH_IRQ_HANDLER(UART1IrqHandler) { + + CH_IRQ_PROLOGUE(); + + serve_interrupt(U1Base, &COM2); + VICVectAddr = 0; + + CH_IRQ_EPILOGUE(); +} +#endif + + +/*===========================================================================*/ +/* Low Level Driver exported functions. */ +/*===========================================================================*/ + +/** + * Low level serial driver initialization. + */ +void sd_lld_init(void) { + +#if USE_LPC214x_UART0 + sdObjectInit(&COM1, NULL, notify1); + SetVICVector(UART0IrqHandler, LPC214x_UART1_PRIORITY, SOURCE_UART0); +#endif +#if USE_LPC214x_UART1 + sdObjectInit(&COM2, NULL, notify2); + SetVICVector(UART1IrqHandler, LPC214x_UART2_PRIORITY, SOURCE_UART1); +#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. + */ +void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) { + + if (config == NULL) + config = &default_config; + +#if USE_LPC214x_UART1 + if (&COM1 == sdp) { + PCONP = (PCONP & PCALL) | PCUART0; + uart_init(U0Base, config); + VICIntEnable = INTMASK(SOURCE_UART0); + return; + } +#endif +#if USE_LPC214x_UART2 + if (&COM2 == sdp) { + PCONP = (PCONP & PCALL) | PCUART1; + uart_init(U1Base, config); + VICIntEnable = INTMASK(SOURCE_UART1); + return; + } +#endif +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + */ +void sd_lld_stop(SerialDriver *sdp) { + +#if USE_LPC214x_UART1 + if (&COM1 == sdp) { + uart_deinit(U0Base); + PCONP = (PCONP & PCALL) & ~PCUART0; + VICIntEnClear = INTMASK(SOURCE_UART0); + return; + } +#endif +#if USE_LPC214x_UART2 + if (&COM2 == sdp) { + uart_deinit(U1Base); + PCONP = (PCONP & PCALL) & ~PCUART1; + VICIntEnClear = INTMASK(SOURCE_UART1); + return; + } +#endif +} + +/** @} */ diff --git a/os/io/platforms/LPC214x/serial_lld.h b/os/io/platforms/LPC214x/serial_lld.h new file mode 100644 index 000000000..859983528 --- /dev/null +++ b/os/io/platforms/LPC214x/serial_lld.h @@ -0,0 +1,179 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC214x/serial_lld.h + * @brief LPC214x low level serial driver header + * @addtogroup LPC214x_SERIAL + * @{ + */ + +#ifndef _SERIAL_LLD_H_ +#define _SERIAL_LLD_H_ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 128 bytes for both the transmission and receive buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 128 +#endif + +/** + * @brief FIFO preload parameter. + * @details Configuration parameter, this values defines how many bytes are + * preloaded in the HW transmit FIFO for each interrupt, the maximum value is + * 16 the minimum is 2, the value 0 disables the feature. + * @note An high value reduces the number of interrupts generated but can + * also increase the worst case interrupt response time because the + * preload loops. + * @note The value zero disables the feature and reverts to a simpler code + * that will generate an interrupt for each output byte but is much + * smaller and simpler. + */ +#if !defined(UART_FIFO_PRELOAD) || defined(__DOXYGEN__) +#define UART_FIFO_PRELOAD 16 +#endif + +/** + * @brief UART0 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p TRUE . + */ +#if !defined(USE_LPC214x_UART0) || defined(__DOXYGEN__) +#define USE_LPC214x_UART0 TRUE +#endif + +/** + * @brief UART1 driver enable switch. + * @details If set to @p TRUE the support for USART2 is included. + * @note The default is @p TRUE. + */ +#if !defined(USE_LPC214x_UART1) || defined(__DOXYGEN__) +#define USE_LPC214x_UART1 TRUE +#endif + +/** + * @brief UART1 interrupt priority level setting. + */ +#if !defined(LPC214x_UART1_PRIORITY) || defined(__DOXYGEN__) +#define LPC214x_UART1_PRIORITY 1 +#endif + +/** + * @brief UART2 interrupt priority level setting. + */ +#if !defined(LPC214x_UART2_PRIORITY) || defined(__DOXYGEN__) +#define LPC214x_UART2_PRIORITY 2 +#endif + + +/*===========================================================================*/ +/* Unsupported event flags and custom events. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * Serial Driver condition flags type. + */ +typedef uint32_t sdflags_t; + +/** + * @brief @p SerialDriver specific data. + */ +struct _serial_driver_data { + /** + * Input queue, incoming data can be read from this input queue by + * using the queues APIs. + */ + InputQueue iqueue; + /** + * Output queue, outgoing data can be written to this output queue by + * using the queues APIs. + */ + OutputQueue oqueue; + /** + * Status Change @p EventSource. This event is generated when one or more + * condition flags change. + */ + EventSource sevent; + /** + * I/O driver status flags. + */ + sdflags_t flags; + /** + * Input circular buffer. + */ + uint8_t ib[SERIAL_BUFFERS_SIZE]; + /** + * Output circular buffer. + */ + uint8_t ob[SERIAL_BUFFERS_SIZE]; +}; + +/** + * @brief Generic Serial Driver static initializer. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct { + uint32_t baud_rate; + uint32_t lcr; + uint32_t fcr; +} SerialDriverConfig; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/** @cond never*/ +#if USE_LPC214x_UART0 +extern SerialDriver COM1; +#endif +#if USE_LPC214x_UART1 +extern SerialDriver COM2; +#endif +/** @endcond*/ + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config); + void sd_lld_stop(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* _SERIAL_LLD_H_ */ + +/** @} */ diff --git a/os/io/platforms/LPC214x/vic.c b/os/io/platforms/LPC214x/vic.c new file mode 100644 index 000000000..685830063 --- /dev/null +++ b/os/io/platforms/LPC214x/vic.c @@ -0,0 +1,63 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC214x/vic.c + * @brief LPC214x VIC peripheral support code. + * @addtogroup LPC214x_VIC + * @{ + */ + +#include + +#include "lpc214x.h" + +/** + * @brief VIC Initialization. + * @note Better reset everything in the VIC, it is a HUGE source of trouble. + */ +void vic_init(void) { + int i; + + VIC *vic = VICBase; + vic->VIC_IntSelect = 0; /* All sources assigned to IRQ. */ + vic->VIC_SoftIntClear = ALLINTMASK; /* No interrupts enforced */ + vic->VIC_IntEnClear = ALLINTMASK; /* All sources disabled. */ + for (i = 0; i < 16; i++) { + vic->VIC_VectCntls[i] = 0; + vic->VIC_VectAddrs[i] = 0; + vic->VIC_VectAddr = 0; + } +} + +/** + * @brief Initializes a VIC vector. + * @details Set a vector for an interrupt source and enables it. + * @param[in] handler the pointer to the IRQ service routine + * @param[in] vector the vector number + * @param[in] source the IRQ source to be associated to the vector + */ +void SetVICVector(void *handler, int vector, int source) { + + VIC *vicp = VICBase; + vicp->VIC_VectAddrs[vector] = (IOREG32)handler; + vicp->VIC_VectCntls[vector] = (IOREG32)(source | 0x20); +} + +/** @} */ diff --git a/os/io/platforms/LPC214x/vic.h b/os/io/platforms/LPC214x/vic.h new file mode 100644 index 000000000..486a80b56 --- /dev/null +++ b/os/io/platforms/LPC214x/vic.h @@ -0,0 +1,41 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file LPC214x/vic.h + * @brief LPC214x VIC peripheral support code. + * @addtogroup LPC214x_VIC + * @{ + */ + +#ifndef _VIC_H_ +#define _VIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + void vic_init(void); + void SetVICVector(void *handler, int vector, int source); +#ifdef __cplusplus +} +#endif + +#endif /* _VIC_H_ */ + +/** @} */ diff --git a/os/io/platforms/LPC214x/wfi.h b/os/io/platforms/LPC214x/wfi.h new file mode 100644 index 000000000..bd3b5e7cd --- /dev/null +++ b/os/io/platforms/LPC214x/wfi.h @@ -0,0 +1,35 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _WFI_H_ +#define _WFI_H_ + +#include "lpc214x.h" + +#ifndef port_wait_for_interrupt +#if ENABLE_WFI_IDLE != 0 +#define port_wait_for_interrupt() { \ + PCON = 1; \ +} +#else +#define port_wait_for_interrupt() +#endif +#endif + +#endif /* _WFI_H_ */ -- cgit v1.2.3