ChibiOS 2.6.8, until I can figure out where to get it from git.

This commit is contained in:
Jared Boone
2015-07-08 08:40:23 -07:00
parent dc6fee8370
commit e1eea8e08a
1929 changed files with 575326 additions and 0 deletions
+117
View File
@@ -0,0 +1,117 @@
/*
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 LPC214x/hal_lld.c
* @brief LPC214x 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. */
/*===========================================================================*/
/*
* Non-vectored IRQs handler, the default action can be overridden by
* redefining the @p LPC214x_NON_VECTORED_IRQ_HOOK() hook macro.
*/
static CH_IRQ_HANDLER(irq_handler) {
CH_IRQ_PROLOGUE();
LPC214x_NON_VECTORED_IRQ_HOOK();
VICVectAddr = 0;
CH_IRQ_EPILOGUE();
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level HAL driver initialization.
*
* @notapi
*/
void hal_lld_init(void) {
vic_init();
VICDefVectAddr = (IOREG32)irq_handler;
}
/**
* @brief LPC214x 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 lpc214x_clock_init(void) {
/*
* All peripherals clock disabled by default in order to save power.
*/
PCONP = PCRTC | PCTIM0;
/*
* MAM setup.
*/
MAMTIM = 0x3; /* 3 cycles for flash accesses. */
MAMCR = 0x2; /* MAM fully enabled. */
/*
* PLL setup for Fosc=12MHz and CCLK=48MHz.
* P=2 M=3.
*/
PLL *pll = PLL0Base;
pll->PLL_CFG = 0x23; /* P and M values. */
pll->PLL_CON = 0x1; /* Enables the PLL 0. */
pll->PLL_FEED = 0xAA;
pll->PLL_FEED = 0x55;
while (!(pll->PLL_STAT & 0x400))
; /* Wait for PLL lock. */
pll->PLL_CON = 0x3; /* Connects the PLL. */
pll->PLL_FEED = 0xAA;
pll->PLL_FEED = 0x55;
/*
* VPB setup.
* PCLK = CCLK / 4.
*/
VPBDIV = VPD_D4;
}
/** @} */
+83
View File
@@ -0,0 +1,83 @@
/*
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 LPC214x/hal_lld.h
* @brief LPC214x HAL subsystem low level driver header.
*
* @addtogroup HAL
* @{
*/
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
#include "lpc214x.h"
#include "vic.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Defines the support for realtime counters in the HAL.
*/
#define HAL_IMPLEMENTS_COUNTERS FALSE
/**
* @brief Platform name.
*/
#define PLATFORM_NAME "LPC214x"
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Default action for the non vectored IRQ handler, nothing.
*/
#if !defined(LPC214x_NON_VECTORED_IRQ_HOOK) || defined(__DOXYGEN__)
#define LPC214x_NON_VECTORED_IRQ_HOOK()
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void hal_lld_init(void);
void lpc214x_clock_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _HAL_LLD_H_ */
/** @} */
+523
View File
@@ -0,0 +1,523 @@
/*
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 lpc214x.h
* @brief LPC214x register definitions.
*/
#ifndef _LPC214X_H_
#define _LPC214X_H_
typedef volatile uint8_t IOREG8;
typedef volatile uint16_t IOREG16;
typedef volatile uint32_t 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 _dummy[3];
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;
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_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 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_ */
+112
View File
@@ -0,0 +1,112 @@
/*
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 LPC214x/pal_lld.c
* @brief LPC214x FIO 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 LPC214x I/O ports configuration.
* @details FIO units and PINSEL registers initialization.
*
* @param[in] config the LPC214x ports configuration
*
* @notapi
*/
void _pal_lld_init(const PALConfig *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.
* @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->FIO_DIR &= ~mask;
break;
case PAL_MODE_UNCONNECTED:
port->FIO_PIN |= mask;
case PAL_MODE_OUTPUT_PUSHPULL:
port->FIO_DIR |= mask;
break;
}
}
#endif /* HAL_USE_PAL */
/** @} */
+261
View File
@@ -0,0 +1,261 @@
/*
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 LPC214x/pal_lld.h
* @brief LPC214x FIO 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_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 initialize 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;
} PALConfig;
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 32
/**
* @brief Whole port mask.
* @details This macro specifies all the valid bits into a port.
*/
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF)
/**
* @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 FIO * ioportid_t;
/*===========================================================================*/
/* I/O Ports Identifiers. */
/*===========================================================================*/
/**
* @brief FIO port 0 identifier.
*/
#define IOPORT1 FIO0Base
/**
* @brief FIO port 1 identifier.
*/
#define IOPORT2 FIO1Base
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, if so please put them in pal_lld.c. */
/*===========================================================================*/
/**
* @brief FIO subsystem initialization.
* @details Enables the access through the fast registers.
*
* @notapi
*/
#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 port identifier
* @return The port bits.
*
* @notapi
*/
#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 port identifier
* @return The latched logical states.
*
* @notapi
*/
#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 port identifier
* @param[in] bits bits to be written on the specified port
*
* @notapi
*/
#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 port identifier
* @param[in] bits bits to be ORed on the specified port
*
* @notapi
*/
#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 port identifier
* @param[in] bits bits to be cleared on the specified port
*
* @notapi
*/
#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 port identifier
* @param[in] mask group mask, a logical AND is performed on the
* output data
* @param[in] offset the 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) \
((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.
* @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 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.
*
* @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) pal_lld_writegroup(port, 1, pad, bit)
/**
* @brief FIO port setup.
* @details This function programs the pins direction within a port.
*
* @notapi
*/
#define pal_lld_lpc214x_set_direction(port, dir) ((port)->FIO_DIR = (dir))
extern const PALConfig pal_default_config;
#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);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_PAL */
#endif /* _PAL_LLD_H_ */
/** @} */
+118
View File
@@ -0,0 +1,118 @@
/*
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.
*/
/**
* @defgroup LPC214x LPC214x Drivers
* @details This section describes all the supported drivers on the LPC214x
* platform and the implementation details of the single drivers.
*
* @ingroup platforms
*/
/**
* @defgroup LPC214x_HAL LPC214x Initialization Support
* @details The LPC214x HAL support is responsible for system initialization.
*
* @section lpc214x_hal_1 Supported HW resources
* - PLL0.
* - MAM.
* - VPBDIV.
* .
* @section lpc214x_hal_2 LPC214x HAL driver implementation features
* - Clock tree initialization.
* - Clock source selection.
* - MAM initialization.
* .
* @ingroup LPC214x
*/
/**
* @defgroup LPC214x_PAL LPC214x PAL Support
* @details The LPC214x PAL driver uses the FIO peripherals.
*
* @section lpc214x_pal_1 Supported HW resources
* - FIO0.
* - FIO1.
* .
* @section lpc214x_pal_2 LPC214x PAL driver implementation features
* - 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.
* .
* @section lpc214x_pal_3 Supported PAL setup modes
* - @p PAL_MODE_RESET.
* - @p PAL_MODE_UNCONNECTED.
* - @p PAL_MODE_INPUT.
* - @p PAL_MODE_INPUT_ANALOG (same as @p PAL_MODE_INPUT).
* - @p PAL_MODE_OUTPUT_PUSHPULL.
* .
* Any attempt to setup an invalid mode is ignored.
*
* @section lpc214x_pal_4 Suboptimal behavior
* Some FIO features are less than optimal:
* - Pad/port toggling operations are not atomic.
* - Pad/group mode setup is not atomic.
* .
* @ingroup LPC214x
*/
/**
* @defgroup LPC214x_SERIAL LPC214x Serial Support
* @details The LPC214x Serial driver uses the UART peripherals in a
* buffered, interrupt driven, implementation. The serial driver
* also takes advantage of the LPC214x UARTs deep hardware buffers.
*
* @section lpc214x_serial_1 Supported HW resources
* The serial driver can support any of the following hardware resources:
* - UART0.
* - UART1.
* .
* @section lpc214x_serial_2 LPC214x Serial driver implementation features
* - Clock stop for reduced power usage when the driver is in stop state.
* - Fully interrupt driven.
* - Programmable interrupt priority levels for each UART.
* - Takes advantage of the input and output FIFOs.
* .
* @ingroup LPC214x
*/
/**
* @defgroup LPC214x_SPI LPC214x SPI Support
* @details The SPI driver supports the LPC214x SSP peripheral in an interrupt
* driven implementation.
* @note Being the SPI a fast peripheral, much care must be taken to
* not saturate the CPU bandwidth with an excessive IRQ rate. The
* maximum transfer bit rate is likely limited by the IRQ
* handling.
*
* @section lpc214x_spi_1 Supported HW resources
* - SSP (SPI0).
* .
* @section lpc214x_spi_2 LPC214x SPI driver implementation features
* - Clock stop for reduced power usage when the driver is in stop state.
* - Programmable interrupt priority level.
* .
* @ingroup LPC214x
*/
/**
* @defgroup LPC214x_VIC LPC214x VIC Support
* @details This VIC helper driver is used by the other drivers in order to
* access the shared VIC resources in a consistent way.
*
* @ingroup LPC214x
*/
+9
View File
@@ -0,0 +1,9 @@
# List of all the LPC214x platform files.
PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC214x/hal_lld.c \
${CHIBIOS}/os/hal/platforms/LPC214x/pal_lld.c \
${CHIBIOS}/os/hal/platforms/LPC214x/serial_lld.c \
${CHIBIOS}/os/hal/platforms/LPC214x/spi_lld.c \
${CHIBIOS}/os/hal/platforms/LPC214x/vic.c
# Required include directories
PLATFORMINC = ${CHIBIOS}/os/hal/platforms/LPC214x
+347
View File
@@ -0,0 +1,347 @@
/*
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 LPC214x/serial_lld.c
* @brief LPC214x low level serial driver code.
*
* @addtogroup SERIAL
* @{
*/
#include "ch.h"
#include "hal.h"
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
/** @brief UART0 serial driver identifier.*/
SerialDriver SD1;
#endif
#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
/** @brief UART1 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) {
UART *u = sdp->uart;
uint32_t div = PCLK / (config->sc_speed << 4);
u->UART_LCR = config->sc_lcr | LCR_DLAB;
u->UART_DLL = div;
u->UART_DLM = div >> 8;
u->UART_LCR = config->sc_lcr;
u->UART_FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | config->sc_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
*/
static void uart_deinit(UART *u) {
u->UART_LCR = LCR_DLAB;
u->UART_DLL = 1;
u->UART_DLM = 0;
u->UART_LCR = 0;
u->UART_FDR = 0x10;
u->UART_IER = 0;
u->UART_FCR = FCR_RXRESET | FCR_TXRESET;
u->UART_ACR = 0;
u->UART_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();
}
#if defined(__GNUC__)
__attribute__((noinline))
#endif
/**
* @brief Common IRQ handler.
* @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.
*
* @param[in] sdp communication channel associated to the UART
*/
static void serve_interrupt(SerialDriver *sdp) {
UART *u = sdp->uart;
while (TRUE) {
switch (u->UART_IIR & IIR_SRC_MASK) {
case IIR_SRC_NONE:
return;
case IIR_SRC_ERROR:
set_error(sdp, u->UART_LSR);
break;
case IIR_SRC_TIMEOUT:
case IIR_SRC_RX:
chSysLockFromIsr();
if (chIQIsEmptyI(&sdp->iqueue))
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
chSysUnlockFromIsr();
while (u->UART_LSR & LSR_RBR_FULL) {
chSysLockFromIsr();
if (chIQPutI(&sdp->iqueue, u->UART_RBR) < Q_OK)
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
chSysUnlockFromIsr();
}
break;
case IIR_SRC_TX:
{
int i = LPC214x_UART_FIFO_PRELOAD;
do {
msg_t b;
chSysLockFromIsr();
b = chOQGetI(&sdp->oqueue);
chSysUnlockFromIsr();
if (b < Q_OK) {
u->UART_IER &= ~IER_THRE;
chSysLockFromIsr();
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
chSysUnlockFromIsr();
break;
}
u->UART_THR = b;
} while (--i);
}
break;
default:
(void) u->UART_THR;
(void) u->UART_RBR;
}
}
}
/**
* @brief Attempts a TX FIFO preload.
*/
static void preload(SerialDriver *sdp) {
UART *u = sdp->uart;
if (u->UART_LSR & LSR_THRE) {
int i = LPC214x_UART_FIFO_PRELOAD;
do {
msg_t b = chOQGetI(&sdp->oqueue);
if (b < Q_OK) {
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
return;
}
u->UART_THR = b;
} while (--i);
}
u->UART_IER |= IER_THRE;
}
/**
* @brief Driver SD1 output notification.
*/
#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
static void notify1(GenericQueue *qp) {
(void)qp;
preload(&SD1);
}
#endif
/**
* @brief Driver SD2 output notification.
*/
#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
static void notify2(GenericQueue *qp) {
(void)qp;
preload(&SD2);
}
#endif
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/**
* @brief UART0 IRQ handler.
*
* @isr
*/
#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(UART0IrqHandler) {
CH_IRQ_PROLOGUE();
serve_interrupt(&SD1);
VICVectAddr = 0;
CH_IRQ_EPILOGUE();
}
#endif
/**
* @brief UART1 IRQ handler.
*
* @isr
*/
#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(UART1IrqHandler) {
CH_IRQ_PROLOGUE();
serve_interrupt(&SD2);
VICVectAddr = 0;
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level serial driver initialization.
*
* @notapi
*/
void sd_lld_init(void) {
#if USE_LPC214x_UART0
sdObjectInit(&SD1, NULL, notify1);
SD1.uart = U0Base;
SetVICVector(UART0IrqHandler, LPC214x_UART0_PRIORITY, SOURCE_UART0);
#endif
#if USE_LPC214x_UART1
sdObjectInit(&SD2, NULL, notify2);
SD2.uart = U1Base;
SetVICVector(UART1IrqHandler, LPC214x_UART1_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.
*
* @notapi
*/
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
if (config == NULL)
config = &default_config;
if (sdp->state == SD_STOP) {
#if USE_LPC214x_UART0
if (&SD1 == sdp) {
PCONP = (PCONP & PCALL) | PCUART0;
VICIntEnable = INTMASK(SOURCE_UART0);
}
#endif
#if USE_LPC214x_UART1
if (&SD2 == sdp) {
PCONP = (PCONP & PCALL) | PCUART1;
VICIntEnable = INTMASK(SOURCE_UART1);
}
#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 USE_LPC214x_UART0
if (&SD1 == sdp) {
PCONP = (PCONP & PCALL) & ~PCUART0;
VICIntEnClear = INTMASK(SOURCE_UART0);
return;
}
#endif
#if USE_LPC214x_UART1
if (&SD2 == sdp) {
PCONP = (PCONP & PCALL) & ~PCUART1;
VICIntEnClear = INTMASK(SOURCE_UART1);
return;
}
#endif
}
}
#endif /* HAL_USE_SERIAL */
/** @} */
+163
View File
@@ -0,0 +1,163 @@
/*
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 LPC214x/serial_lld.h
* @brief LPC214x low level serial driver header.
*
* @addtogroup SERIAL
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* 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(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 UART1 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_LPC214x_UART1) || defined(__DOXYGEN__)
#define USE_LPC214x_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(LPC214x_UART_FIFO_PRELOAD) || defined(__DOXYGEN__)
#define LPC214x_UART_FIFO_PRELOAD 16
#endif
/**
* @brief UART0 interrupt priority level setting.
*/
#if !defined(LPC214x_UART0_PRIORITY) || defined(__DOXYGEN__)
#define LPC214x_UART0_PRIORITY 1
#endif
/**
* @brief UART1 interrupt priority level setting.
*/
#if !defined(LPC214x_UART1_PRIORITY) || defined(__DOXYGEN__)
#define LPC214x_UART1_PRIORITY 2
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if (LPC214x_UART_FIFO_PRELOAD < 1) || (LPC214x_UART_FIFO_PRELOAD > 16)
#error "invalid LPC214x_UART_FIFO_PRELOAD setting"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief LPC214x 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.*/ \
UART *uart;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if USE_LPC214x_UART0 && !defined(__DOXYGEN__)
extern SerialDriver SD1;
#endif
#if USE_LPC214x_UART1 && !defined(__DOXYGEN__)
extern SerialDriver SD2;
#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_ */
/** @} */
+339
View File
@@ -0,0 +1,339 @@
/*
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 LPC214x/spi_lld.c
* @brief LPC214x low level SPI driver code.
*
* @addtogroup SPI
* @{
*/
#include "ch.h"
#include "hal.h"
#if HAL_USE_SPI || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
#if LPC214x_SPI_USE_SSP || 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) {
SSP *ssp = spip->ssp;
uint32_t n = spip->txcnt > LPC214x_SSP_FIFO_DEPTH ?
LPC214x_SSP_FIFO_DEPTH : spip->txcnt;
while(((ssp->SSP_SR & SR_TNF) != 0) && (n > 0)) {
if (spip->txptr != NULL) {
if ((ssp->SSP_CR0 & CR0_DSSMASK) > CR0_DSS8BIT)
ssp->SSP_DR = *(uint16_t *)spip->txptr++;
else
ssp->SSP_DR = *(uint8_t *)spip->txptr++;
}
else
ssp->SSP_DR = 0xFFFFFFFF;
n--;
spip->txcnt--;
}
}
#if defined(__GNUC__)
__attribute__((noinline))
#endif
/**
* @brief Common IRQ handler.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
static void serve_interrupt(SPIDriver *spip) {
SSP *ssp = spip->ssp;
if ((ssp->SSP_MIS & MIS_ROR) != 0) {
/* The overflow condition should never happen because priority is given
to receive but a hook macro is provided anyway...*/
LPC214x_SPI_SSP_ERROR_HOOK();
}
ssp->SSP_ICR = ICR_RT | ICR_ROR;
while ((ssp->SSP_SR & SR_RNE) != 0) {
if (spip->rxptr != NULL) {
if ((ssp->SSP_CR0 & CR0_DSSMASK) > CR0_DSS8BIT)
*(uint16_t *)spip->rxptr++ = ssp->SSP_DR;
else
*(uint8_t *)spip->rxptr++ = ssp->SSP_DR;
}
else
(void)ssp->SSP_DR;
if (--spip->rxcnt == 0) {
chDbgAssert(spip->txcnt == 0,
"spi_serve_interrupt(), #1", "counter out of synch");
/* Stops the IRQ sources.*/
ssp->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->SSP_IMSC = IMSC_ROR | IMSC_RT | IMSC_RX;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if LPC214x_SPI_USE_SSP || defined(__DOXYGEN__)
/**
* @brief SPI1 interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPI1IrqHandler) {
CH_IRQ_PROLOGUE();
serve_interrupt(&SPID1);
VICVectAddr = 0;
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level SPI driver initialization.
*
* @notapi
*/
void spi_lld_init(void) {
#if LPC214x_SPI_USE_SSP
spiObjectInit(&SPID1);
SPID1.ssp = SSPBase;
SetVICVector(SPI1IrqHandler, LPC214x_SPI_SSP_IRQ_PRIORITY, SOURCE_SPI1);
#endif
}
/**
* @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 LPC214x_SPI_USE_SSP
if (&SPID1 == spip) {
PCONP = (PCONP & PCALL) | PCSPI1;
VICIntEnable = INTMASK(SOURCE_SPI1);
}
#endif
}
/* Configuration.*/
spip->ssp->SSP_CR1 = 0;
/* Emptying the receive FIFO, it happens to not be empty while debugging.*/
while (spip->ssp->SSP_SR & SR_RNE)
(void) spip->ssp->SSP_DR;
spip->ssp->SSP_ICR = ICR_RT | ICR_ROR;
spip->ssp->SSP_CR0 = spip->config->cr0;
spip->ssp->SSP_CPSR = spip->config->cpsr;
spip->ssp->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->SSP_CR1 = 0;
spip->ssp->SSP_CR0 = 0;
spip->ssp->SSP_CPSR = 0;
#if LPC214x_SPI_USE_SSP
if (&SPID1 == spip) {
PCONP = (PCONP & PCALL) & ~PCSPI1;
VICIntEnClear = INTMASK(SOURCE_SPI1);
}
#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->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->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->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->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->SSP_DR = (uint32_t)frame;
while ((spip->ssp->SSP_SR & SR_RNE) == 0)
;
return (uint16_t)spip->ssp->SSP_DR;
}
#endif /* HAL_USE_SPI */
/** @} */
+207
View File
@@ -0,0 +1,207 @@
/*
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 LPC214x/spi_lld.h
* @brief LPC214x 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 LPC214x_SSP_FIFO_DEPTH 8
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief SPI1 driver enable switch.
* @details If set to @p TRUE the support for SSP is included.
* @note The default is @p TRUE.
*/
#if !defined(LPC214x_SPI_USE_SSP) || defined(__DOXYGEN__)
#define LPC214x_SPI_USE_SSP TRUE
#endif
/**
* @brief SSP interrupt priority level setting.
*/
#if !defined(LPC214x_SPI_SSP_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define LPC214x_SPI_SSP_IRQ_PRIORITY 4
#endif
/**
* @brief Overflow error hook.
* @details The default action is to stop the system.
*/
#if !defined(LPC214x_SPI_SSP_ERROR_HOOK) || defined(__DOXYGEN__)
#define LPC214x_SPI_SSP_ERROR_HOOK() chSysHalt()
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if !LPC214x_SPI_USE_SSP
#error "SPI driver activated but no SPI peripheral assigned"
#endif
/*===========================================================================*/
/* 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.
*/
SSP *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 LPC214x_SPI_USE_SSP && !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_ */
/** @} */
+65
View File
@@ -0,0 +1,65 @@
/*
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 LPC214x/vic.c
* @brief LPC214x VIC peripheral support code.
*
* @addtogroup LPC214x_VIC
* @{
*/
#include "ch.h"
#include "hal.h"
/**
* @brief VIC Initialization.
* @note Better reset everything in the VIC, it is a HUGE source of trouble.
*
* @notapi
*/
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
*
* @api
*/
void SetVICVector(void *handler, int vector, int source) {
VIC *vicp = VICBase;
vicp->VIC_VectAddrs[vector] = (IOREG32)handler;
vicp->VIC_VectCntls[vector] = (IOREG32)(source | 0x20);
}
/** @} */
+39
View File
@@ -0,0 +1,39 @@
/*
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 LPC214x/vic.h
* @brief LPC214x VIC peripheral support header.
*
* @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_ */
/** @} */