Add LPC812 peripherals

pull/1/merge
Emilio Monti 2013-04-11 17:19:34 +01:00
parent 0da3c49fef
commit 498d5efcc4
7 changed files with 413 additions and 103 deletions

View File

@ -20,17 +20,17 @@
#define DEVICE_PORTOUT 0
#define DEVICE_PORTINOUT 0
#define DEVICE_INTERRUPTIN 0
#define DEVICE_INTERRUPTIN 1
#define DEVICE_ANALOGIN 0
#define DEVICE_ANALOGOUT 0
#define DEVICE_SERIAL 1
#define DEVICE_I2C 0
#define DEVICE_I2C 1
#define DEVICE_I2CSLAVE 0
#define DEVICE_SPI 0
#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 0
#define DEVICE_CAN 0

View File

@ -25,9 +25,22 @@
extern "C" {
#endif
struct gpio_irq_s {
uint32_t ch;
};
struct serial_s {
LPC_USART_TypeDef *uart;
unsigned char uart_n;
unsigned char index;
};
struct i2c_s {
LPC_I2C_TypeDef *i2c;
};
struct spi_s {
LPC_SPI_TypeDef *spi;
unsigned char spi_n;
};
#include "gpio_object.h"

View File

@ -23,9 +23,16 @@
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
#define CHANNEL_NUM 48
#endif
#elif defined(TARGET_LPC11U24)
#if defined(TARGET_LPC11U24)
#define CHANNEL_NUM 8
#define LPC_GPIO_X LPC_GPIO_PIN_INT
#define PININT_IRQ 0
#elif defined(TARGET_LPC812)
#define CHANNEL_NUM 8
#define LPC_GPIO_X LPC_PIN_INT
#define PININT_IRQ PININT0_IRQn
#endif
static uint32_t channel_ids[CHANNEL_NUM] = {0};
@ -79,25 +86,25 @@ static void handle_interrupt_in(void) {
LPC_GPIOINT->IO2IntClr = mask2;
}
#elif defined(TARGET_LPC11U24)
#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC812)
static inline void handle_interrupt_in(uint32_t channel) {
uint32_t ch_bit = (1 << channel);
// Return immediately if:
// * The interrupt was already served
// * There is no user handler
// * It is a level interrupt, not an edge interrupt
if ( ((LPC_GPIO_PIN_INT->IST & ch_bit) == 0) ||
(channel_ids[channel] == 0 ) ||
(LPC_GPIO_PIN_INT->ISEL & ch_bit ) ) return;
if ( ((LPC_GPIO_X->IST & ch_bit) == 0) ||
(channel_ids[channel] == 0 ) ||
(LPC_GPIO_X->ISEL & ch_bit ) ) return;
if ((LPC_GPIO_PIN_INT->IENR & ch_bit) && (LPC_GPIO_PIN_INT->RISE & ch_bit)) {
if ((LPC_GPIO_X->IENR & ch_bit) && (LPC_GPIO_X->RISE & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_RISE);
LPC_GPIO_PIN_INT->RISE = ch_bit;
LPC_GPIO_X->RISE = ch_bit;
}
if ((LPC_GPIO_PIN_INT->IENF & ch_bit) && (LPC_GPIO_PIN_INT->FALL & ch_bit)) {
if ((LPC_GPIO_X->IENF & ch_bit) && (LPC_GPIO_X->FALL & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_FALL);
}
LPC_GPIO_PIN_INT->IST = ch_bit;
LPC_GPIO_X->IST = ch_bit;
}
void gpio_irq0(void) {handle_interrupt_in(0);}
@ -108,6 +115,7 @@ void gpio_irq4(void) {handle_interrupt_in(4);}
void gpio_irq5(void) {handle_interrupt_in(5);}
void gpio_irq6(void) {handle_interrupt_in(6);}
void gpio_irq7(void) {handle_interrupt_in(7);}
#endif
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
@ -132,7 +140,7 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
NVIC_SetVector(EINT3_IRQn, (uint32_t)handle_interrupt_in);
NVIC_EnableIRQ(EINT3_IRQn);
#elif defined(TARGET_LPC11U24)
#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC812)
int found_free_channel = 0;
int i = 0;
for (i=0; i<CHANNEL_NUM; i++) {
@ -148,6 +156,7 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
/* Enable AHB clock to the GPIO domain. */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
#if defined(TARGET_LPC11U24)
/* Enable AHB clock to the FlexInt, GroupedInt domain. */
LPC_SYSCON->SYSAHBCLKCTRL |= ((1<<19) | (1<<23) | (1<<24));
@ -156,6 +165,9 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
* @see: mbed_capi/PinNames.h
*/
LPC_SYSCON->PINTSEL[obj->ch] = (pin >> 5) ? (pin - 8) : (pin);
#elif defined(TARGET_LPC812)
LPC_SYSCON->PINTSEL[obj->ch] = pin;
#endif
// Interrupt Wake-Up Enable
LPC_SYSCON->STARTERP0 |= 1 << obj->ch;
@ -171,15 +183,15 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
case 6: channels_irq = &gpio_irq6; break;
case 7: channels_irq = &gpio_irq7; break;
}
NVIC_SetVector((IRQn_Type)obj->ch, (uint32_t)channels_irq);
NVIC_EnableIRQ((IRQn_Type)obj->ch);
NVIC_SetVector((IRQn_Type)(PININT_IRQ + obj->ch), (uint32_t)channels_irq);
NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
#endif
return 0;
}
void gpio_irq_free(gpio_irq_t *obj) {
channel_ids[obj->ch] = 0;
#if defined(TARGET_LPC11U24)
#if defined(TARGET_LPC11U24) || defined(TARGET_LPC812)
LPC_SYSCON->STARTERP0 &= ~(1 << obj->ch);
#endif
}
@ -228,26 +240,26 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
break;
}
}
#elif defined(TARGET_LPC11U24)
#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC812)
unsigned int ch_bit = (1 << obj->ch);
// Clear interrupt
if (!(LPC_GPIO_PIN_INT->ISEL & ch_bit))
LPC_GPIO_PIN_INT->IST = ch_bit;
if (!(LPC_GPIO_X->ISEL & ch_bit))
LPC_GPIO_X->IST = ch_bit;
// Edge trigger
LPC_GPIO_PIN_INT->ISEL &= ~ch_bit;
LPC_GPIO_X->ISEL &= ~ch_bit;
if (event == IRQ_RISE) {
if (enable) {
LPC_GPIO_PIN_INT->IENR |= ch_bit;
LPC_GPIO_X->IENR |= ch_bit;
} else {
LPC_GPIO_PIN_INT->IENR &= ~ch_bit;
LPC_GPIO_X->IENR &= ~ch_bit;
}
} else {
if (enable) {
LPC_GPIO_PIN_INT->IENF |= ch_bit;
LPC_GPIO_X->IENF |= ch_bit;
} else {
LPC_GPIO_PIN_INT->IENF &= ~ch_bit;
LPC_GPIO_X->IENF &= ~ch_bit;
}
}
#endif

View File

@ -62,21 +62,38 @@ static const PinMap PinMap_I2C_SCL[] = {
#define I2C_DAT(x) (x->i2c->DAT)
#define I2C_SCLL(x, val) (x->i2c->SCLL = val)
#define I2C_SCLH(x, val) (x->i2c->SCLH = val)
#elif defined(TARGET_LPC812)
static const SWM_Map SWM_I2C_SDA[] = {
{7, 24},
};
static const SWM_Map SWM_I2C_SCL[] = {
{8, 0},
};
static uint8_t repeated_start = 0;
#define I2C_DAT(x) (x->i2c->MSTDAT)
#define I2C_STAT(x) ((x->i2c->STAT >> 1) & (0x07))
#endif
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
static const uint32_t I2C_addr_offset[2][4] = {
{0x0C, 0x20, 0x24, 0x28},
{0x30, 0x34, 0x38, 0x3C}
};
static void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
static inline void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
I2C_CONCLR(obj) = (start << 5)
| (stop << 4)
| (interrupt << 3)
| (acknowledge << 2);
}
static void i2c_conset(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
static inline void i2c_conset(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
I2C_CONSET(obj) = (start << 5)
| (stop << 4)
| (interrupt << 3)
@ -84,29 +101,39 @@ static void i2c_conset(i2c_t *obj, int start, int stop, int interrupt, int ackno
}
// Clear the Serial Interrupt (SI)
static void i2c_clear_SI(i2c_t *obj) {
static inline void i2c_clear_SI(i2c_t *obj) {
i2c_conclr(obj, 0, 0, 1, 0);
}
#endif
static int i2c_status(i2c_t *obj) {
static inline int i2c_status(i2c_t *obj) {
return I2C_STAT(obj);
}
// Wait until the Serial Interrupt (SI) is set
static int i2c_wait_SI(i2c_t *obj) {
int timeout = 0;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
while (!(I2C_CONSET(obj) & (1 << 3))) {
#elif defined(TARGET_LPC812)
while (!(obj->i2c->STAT & (1 << 0))) {
#endif
timeout++;
if (timeout > 100000) return -1;
}
return 0;
}
static void i2c_interface_enable(i2c_t *obj) {
static inline void i2c_interface_enable(i2c_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
I2C_CONSET(obj) = 0x40;
#elif defined(TARGET_LPC812)
obj->i2c->CFG |= (1 << 0);
#endif
}
static void i2c_power_enable(i2c_t *obj) {
static inline void i2c_power_enable(i2c_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
switch ((int)obj->i2c) {
case I2C_0: LPC_SC->PCONP |= 1 << 7; break;
@ -116,10 +143,15 @@ static void i2c_power_enable(i2c_t *obj) {
#elif defined(TARGET_LPC11U24)
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 5);
LPC_SYSCON->PRESETCTRL |= 1 << 1;
#elif defined(TARGET_LPC812)
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
LPC_SYSCON->PRESETCTRL &= ~(0x1<<6);
LPC_SYSCON->PRESETCTRL |= (0x1<<6);
#endif
}
void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
// determine the SPI to use
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
@ -128,6 +160,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
#elif defined(TARGET_LPC11U24)
obj->i2c = (LPC_I2C_Type *)pinmap_merge(i2c_sda, i2c_scl);
#endif
if ((int)obj->i2c == NC) {
error("I2C pin mapping failed");
}
@ -142,11 +175,33 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
pinmap_pinout(sda, PinMap_I2C_SDA);
pinmap_pinout(scl, PinMap_I2C_SCL);
#elif defined (TARGET_LPC812)
obj->i2c = (LPC_I2C_TypeDef *)LPC_I2C;
const SWM_Map *swm;
uint32_t regVal;
swm = &SWM_I2C_SDA[0];
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
LPC_SWM->PINASSIGN[swm->n] = regVal | (sda << swm->offset);
swm = &SWM_I2C_SCL[0];
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
LPC_SWM->PINASSIGN[swm->n] = regVal | (scl << swm->offset);
// enable power
i2c_power_enable(obj);
// set default frequency at 100k
i2c_frequency(obj, 100000);
i2c_interface_enable(obj);
#endif
}
int i2c_start(i2c_t *obj) {
int status;
inline int i2c_start(i2c_t *obj) {
int status = 0;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
// 8.1 Before master mode can be entered, I2CON must be initialised to:
// - I2EN STA STO SI AA - -
// - 1 0 0 0 x - -
@ -162,35 +217,52 @@ int i2c_start(i2c_t *obj) {
// Clear start bit now transmitted, and interrupt bit
i2c_conclr(obj, 1, 0, 0, 0);
#elif defined(TARGET_LPC812)
if (repeated_start) {
obj->i2c->MSTCTL = (1 << 1) | (1 << 0);
repeated_start = 0;
} else {
obj->i2c->MSTCTL = (1 << 1);
}
#endif
return status;
}
void i2c_stop(i2c_t *obj) {
inline void i2c_stop(i2c_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
// write the stop bit
i2c_conset(obj, 0, 1, 0, 0);
i2c_clear_SI(obj);
// wait for STO bit to reset
while(I2C_CONSET(obj) & (1 << 4));
#elif defined(TARGET_LPC812)
obj->i2c->MSTCTL = (1 << 2) | (1 << 0);
while ((obj->i2c->STAT & ((1 << 0) | (7 << 1))) != ((1 << 0) | (0 << 1)));
#endif
}
static int i2c_do_write(i2c_t *obj, int value) {
static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) {
// write the data
I2C_DAT(obj) = value;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
// clear SI to init a send
i2c_clear_SI(obj);
#elif defined(TARGET_LPC812)
if (!addr)
obj->i2c->MSTCTL = (1 << 0);
#endif
i2c_wait_SI(obj);
// wait and return status
i2c_wait_SI(obj);
return i2c_status(obj);
}
static int i2c_do_read(i2c_t *obj, int last) {
static inline int i2c_do_read(i2c_t *obj, int last) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
// we are in state 0x40 (SLA+R tx'd) or 0x50 (data rx'd and ack)
if(last) {
i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK
} else {
@ -199,10 +271,16 @@ static int i2c_do_read(i2c_t *obj, int last) {
// accept byte
i2c_clear_SI(obj);
#endif
// wait for it to arrive
i2c_wait_SI(obj);
#if defined(TARGET_LPC812)
if (!last)
obj->i2c->MSTCTL = (1 << 0);
#endif
// return the data
return (I2C_DAT(obj) & 0xFF);
}
@ -211,16 +289,23 @@ void i2c_frequency(i2c_t *obj, int hz) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
// [TODO] set pclk to /4
uint32_t PCLK = SystemCoreClock / 4;
#elif defined(TARGET_LPC11U24)
#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC812)
// No peripheral clock divider on the M0
uint32_t PCLK = SystemCoreClock;
#endif
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
uint32_t pulse = PCLK / (hz * 2);
// I2C Rate
I2C_SCLL(obj, pulse);
I2C_SCLH(obj, pulse);
#elif defined(TARGET_LPC812)
uint32_t clkdiv = PCLK / (hz * 4) - 1;
obj->i2c->DIV = clkdiv;
obj->i2c->MSTTIME = 0;
#endif
}
// The I2C does a read or a write as a whole operation
@ -242,13 +327,19 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
status = i2c_start(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if ((status != 0x10) && (status != 0x08)) {
i2c_stop(obj);
return status;
}
#endif
status = i2c_do_write(obj, (address | 0x01));
status = i2c_do_write(obj, (address | 0x01), 1);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if (status != 0x40) {
#elif defined(TARGET_LPC812)
if (status != 0x01) {
#endif
i2c_stop(obj);
return status;
}
@ -257,7 +348,11 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
for (count = 0; count < (length - 1); count++) {
int value = i2c_do_read(obj, 0);
status = i2c_status(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if (status != 0x50) {
#elif defined(TARGET_LPC812)
if (status != 0x00) {
#endif
i2c_stop(obj);
return status;
}
@ -267,7 +362,11 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
// read in last byte
int value = i2c_do_read(obj, 1);
status = i2c_status(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if (status != 0x58) {
#elif defined(TARGET_LPC812)
if (status != 0x01) {
#endif
i2c_stop(obj);
return status;
}
@ -278,6 +377,11 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
if (stop) {
i2c_stop(obj);
}
#if defined(TARGET_LPC812)
else {
repeated_start = 1;
}
#endif
return 0;
}
@ -287,30 +391,48 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
status = i2c_start(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if ((status != 0x10) && (status != 0x08)) {
i2c_stop(obj);
return status;
}
#endif
status = i2c_do_write(obj, (address & 0xFE));
status = i2c_do_write(obj, (address & 0xFE), 1);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if (status != 0x18) {
#elif defined(TARGET_LPC812)
if (status != 0x02) {
#endif
i2c_stop(obj);
return status;
}
for (i=0; i<length; i++) {
status = i2c_do_write(obj, data[i]);
status = i2c_do_write(obj, data[i], 0);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if(status != 0x28) {
#elif defined(TARGET_LPC812)
if (status != 0x02) {
#endif
i2c_stop(obj);
return status;
}
}
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
i2c_clear_SI(obj);
#endif
// If not repeated start, send stop.
if (stop) {
i2c_stop(obj);
}
#if defined(TARGET_LPC812)
else {
repeated_start = 1;
}
#endif
return 0;
}
@ -325,9 +447,10 @@ int i2c_byte_read(i2c_t *obj, int last) {
int i2c_byte_write(i2c_t *obj, int data) {
int ack;
int status = i2c_do_write(obj, (data & 0xFF));
int status = i2c_do_write(obj, (data & 0xFF), 0);
switch(status) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
case 0x18: case 0x28: // Master transmit ACKs
ack = 1;
break;
@ -337,6 +460,11 @@ int i2c_byte_write(i2c_t *obj, int data) {
case 0xB8: // Slave transmit ACK
ack = 1;
break;
#elif defined(TARGET_LPC812)
case 2:
ack = 1;
break;
#endif
default:
ack = 0;
break;
@ -403,7 +531,7 @@ int i2c_slave_write(i2c_t *obj, const char *data, int length) {
}
do {
status = i2c_do_write(obj, data[count]);
status = i2c_do_write(obj, data[count], 0);
count++;
} while ((count < length) && (status == 0xB8));

View File

@ -30,6 +30,9 @@
* INITIALIZATION
******************************************************************************/
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
#define UART_NUM 4
static const PinMap PinMap_UART_TX[] = {
{P0_0, UART_3, 2},
{P0_2, UART_0, 1},
@ -54,9 +57,11 @@ static const PinMap PinMap_UART_RX[] = {
{NC , NC , 0}
};
#define UART_NUM 4
#elif defined(TARGET_LPC11U24)
#define UART_NUM 1
static const PinMap PinMap_UART_TX[] = {
{P0_19, UART_0, 1},
{P1_13, UART_0, 3},
@ -71,10 +76,11 @@ static const PinMap PinMap_UART_RX[] = {
{NC , NC , 0}
};
#define UART_NUM 1
#elif defined(TARGET_LPC812)
#define UART_NUM 3
static const SWM_Map SWM_UART_TX[] = {
{0, 0},
{1, 8},
@ -90,7 +96,8 @@ static const SWM_Map SWM_UART_RX[] = {
// bit flags for used UARTs
static unsigned char uart_used = 0;
static int get_available_uart(void) {
for (int i=0; i<3; i++) {
int i;
for (i=0; i<3; i++) {
if ((uart_used & (1 << i)) == 0)
return i;
}
@ -109,10 +116,8 @@ static int get_available_uart(void) {
static uint32_t UARTSysClk;
#endif
#ifndef TARGET_LPC812
static uint32_t serial_irq_ids[UART_NUM] = {0};
static uart_irq_handler irq_handler;
#endif
int stdio_uart_inited = 0;
serial_t stdio_uart;
@ -125,8 +130,9 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
if (uart_n == -1) {
error("No available UART");
}
obj->uart_n = uart_n;
obj->index = uart_n;
obj->uart = (LPC_USART_TypeDef *)(LPC_USART0_BASE + (0x4000 * uart_n));
uart_used |= (1 << uart_n);
const SWM_Map *swm;
uint32_t regVal;
@ -193,7 +199,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
#elif defined(TARGET_LPC11U24)
obj->uart = (LPC_USART_Type *)uart;
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
// [TODO] Consider more elegant approach
// disconnect USBTX/RX mapping mux, for case when switching ports
pin_function(USBTX, 0);
@ -210,19 +216,19 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
obj->uart->IER = 0 << 0 // Rx Data available irq enable
| 0 << 1 // Tx Fifo empty irq enable
| 0 << 2; // Rx Line Status irq enable
// set default baud rate and format
serial_baud (obj, 9600);
serial_format(obj, 8, ParityNone, 1);
// pinout the chosen uart
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
// set rx/tx pins in PullUp mode
pin_mode(tx, PullUp);
pin_mode(rx, PullUp);
switch (uart) {
case UART_0: obj->index = 0; break;
#if (UART_NUM > 1)
@ -235,7 +241,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
case UART_3: obj->index = 3; break;
#endif
}
is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
#endif
@ -247,10 +253,9 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
void serial_free(serial_t *obj) {
#ifdef TARGET_LPC812
uart_used &= ~(1 << obj->uart_n);
#else
serial_irq_ids[obj->index] = 0;
uart_used &= ~(1 << obj->index);
#endif
serial_irq_ids[obj->index] = 0;
}
// serial_baud
@ -284,15 +289,15 @@ void serial_baud(serial_t *obj, int baudrate) {
#else
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
// The LPC2300 and LPC1700 have a divider and a fractional divider to control the
// baud rate. The formula is:
//
// Baudrate = (1 / PCLK) * 16 * DL * (1 + DivAddVal / MulVal)
// where:
// 1 < MulVal <= 15
// 0 <= DivAddVal < 14
// DivAddVal < MulVal
//
// The LPC2300 and LPC1700 have a divider and a fractional divider to control the
// baud rate. The formula is:
//
// Baudrate = (1 / PCLK) * 16 * DL * (1 + DivAddVal / MulVal)
// where:
// 1 < MulVal <= 15
// 0 <= DivAddVal < 14
// DivAddVal < MulVal
//
// set pclk to /1
switch ((int)obj->uart) {
case UART_0: LPC_SC->PCLKSEL0 &= ~(0x3 << 6); LPC_SC->PCLKSEL0 |= (0x1 << 6); break;
@ -391,7 +396,6 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
if (data_bits < 5 || data_bits > 8) {
error("Invalid number of bits (%d) in serial format, should be 5..8", data_bits);
}
data_bits -= 5;
int parity_enable, parity_select;
@ -405,10 +409,10 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
error("Invalid serial parity setting");
return;
}
obj->uart->LCR = data_bits << 0
| stop_bits << 2
| parity_enable << 3
obj->uart->LCR = data_bits << 0
| stop_bits << 2
| parity_enable << 3
| parity_select << 4;
#endif
}
@ -416,13 +420,10 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
/******************************************************************************
* INTERRUPTS HANDLING
******************************************************************************/
#ifdef TARGET_LPC812
#else
static inline void uart_irq(uint32_t iir, uint32_t index) {
// [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
SerialIrq irq_type;
switch (((iir >> 1) & 0x7)) {
switch (iir) {
case 1: irq_type = TxIrq; break;
case 2: irq_type = RxIrq; break;
default: return;
@ -433,29 +434,27 @@ static inline void uart_irq(uint32_t iir, uint32_t index) {
}
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
void uart0_irq() {uart_irq(LPC_UART0->IIR, 0);}
void uart1_irq() {uart_irq(LPC_UART1->IIR, 1);}
void uart2_irq() {uart_irq(LPC_UART2->IIR, 2);}
void uart3_irq() {uart_irq(LPC_UART3->IIR, 3);}
void uart0_irq() {uart_irq((LPC_UART0->IIR >> 1) & 0x7, 0);}
void uart1_irq() {uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1);}
void uart2_irq() {uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2);}
void uart3_irq() {uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3);}
#elif defined(TARGET_LPC11U24)
void uart0_irq() {uart_irq(LPC_USART->IIR, 0);}
#endif
void uart0_irq() {uart_irq((LPC_USART->IIR >> 1) & 0x7, 0);}
#elif defined(TARGET_LPC812)
void uart0_irq() {uart_irq((LPC_USART0->STAT & (1 << 2)) ? 2 : 1, 0);}
void uart1_irq() {uart_irq((LPC_USART1->STAT & (1 << 2)) ? 2 : 1, 1);}
void uart2_irq() {uart_irq((LPC_USART2->STAT & (1 << 2)) ? 2 : 1, 2);}
#endif
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
#ifdef TARGET_LPC812
#else
irq_handler = handler;
serial_irq_ids[obj->index] = id;
#endif
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
#ifdef TARGET_LPC812
#else
IRQn_Type irq_n = (IRQn_Type)0;
uint32_t vector = 0;
switch ((int)obj->uart) {
@ -466,23 +465,34 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
case UART_3: irq_n=UART3_IRQn; vector = (uint32_t)&uart3_irq; break;
#elif defined(TARGET_LPC11U24)
case UART_0: irq_n=UART_IRQn ; vector = (uint32_t)&uart0_irq; break;
#elif defined(TARGET_LPC812)
case LPC_USART0_BASE: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
case LPC_USART1_BASE: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
case LPC_USART2_BASE: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
#endif
}
if (enable) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
obj->uart->IER |= 1 << irq;
#elif defined(TARGET_LPC812)
obj->uart->INTENSET = (1 << ((irq == RxIrq) ? 0 : 2));
#endif
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);
} else { // disable
int all_disabled = 0;
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
obj->uart->IER &= ~(1 << irq);
all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
#elif defined(TARGET_LPC812)
obj->uart->INTENSET &= ~(1 << ((irq == RxIrq) ? 0 : 2));
all_disabled = (obj->uart->INTENSET & (1 << ((other_irq == RxIrq) ? 0 : 2))) == 0;
#endif
if (all_disabled)
NVIC_DisableIRQ(irq_n);
}
#endif
}
/******************************************************************************

View File

@ -88,9 +88,46 @@ static const PinMap PinMap_SPI_SSEL[] = {
{NC , NC , 0}
};
#elif defined(TARGET_LPC812)
static const SWM_Map SWM_SPI_SSEL[] = {
{4, 16},
{5, 16},
};
static const SWM_Map SWM_SPI_SCLK[] = {
{3, 24},
{4, 24},
};
static const SWM_Map SWM_SPI_MOSI[] = {
{4, 0},
{5, 0},
};
static const SWM_Map SWM_SPI_MISO[] = {
{4, 8},
{5, 16},
};
// bit flags for used SPIs
static unsigned char spi_used = 0;
static int get_available_spi(void) {
int i;
for (i=0; i<2; i++) {
if ((spi_used & (1 << i)) == 0)
return i;
}
return -1;
}
#endif
static inline int ssp_disable(spi_t *obj);
static inline int ssp_enable(spi_t *obj);
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
// determine the SPI to use
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
@ -106,6 +143,38 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
if ((int)obj->spi == NC) {
error("SPI pinout mapping failed");
}
#elif defined(TARGET_LPC812)
int spi_n = get_available_spi();
if (spi_n == -1) {
error("No available SPI");
}
obj->spi_n = spi_n;
spi_used |= (1 << spi_n);
obj->spi = (spi_n) ? (LPC_SPI_TypeDef *)(LPC_SPI1_BASE) : (LPC_SPI_TypeDef *)(LPC_SPI0_BASE);
const SWM_Map *swm;
uint32_t regVal;
swm = &SWM_SPI_SCLK[obj->spi_n];
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
LPC_SWM->PINASSIGN[swm->n] = regVal | (sclk << swm->offset);
swm = &SWM_SPI_MOSI[obj->spi_n];
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
LPC_SWM->PINASSIGN[swm->n] = regVal | (mosi << swm->offset);
swm = &SWM_SPI_MISO[obj->spi_n];
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
LPC_SWM->PINASSIGN[swm->n] = regVal | (miso << swm->offset);
swm = &SWM_SPI_SSEL[obj->spi_n];
regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
LPC_SWM->PINASSIGN[swm->n] = regVal | (ssel << swm->offset);
// clear interrupts
obj->spi->INTENCLR = 0x3f;
#endif
// enable power and clocking
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
@ -126,6 +195,20 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
LPC_SYSCON->PRESETCTRL |= 1 << 2;
break;
}
#elif defined(TARGET_LPC812)
switch (obj->spi_n) {
case 0:
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11);
LPC_SYSCON->PRESETCTRL &= ~(0x1<<0);
LPC_SYSCON->PRESETCTRL |= (0x1<<0);
break;
case 1:
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
LPC_SYSCON->PRESETCTRL &= ~(0x1<<1);
LPC_SYSCON->PRESETCTRL |= (0x1<<1);
break;
}
#endif
// set default format and frequency
@ -135,10 +218,11 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
}
spi_frequency(obj, 1000000);
// enable the ssp channel
obj->spi->CR1 |= 1 << 1;
ssp_enable(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
// pin out the spi pins
pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO);
@ -146,28 +230,33 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
if (ssel != NC) {
pinmap_pinout(ssel, PinMap_SPI_SSEL);
}
#endif
}
void spi_free(spi_t *obj) {}
static inline int ssp_disable(spi_t *obj);
static inline int ssp_enable(spi_t *obj);
void spi_format(spi_t *obj, int bits, int mode, int slave) {
ssp_disable(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) {
#elif defined(TARGET_LPC812)
if (!(bits >= 1 && bits <= 16) || !(mode >= 0 && mode <= 3)) {
#endif
error("SPI format error");
}
int polarity = (mode & 0x2) ? 1 : 0;
int phase = (mode & 0x1) ? 1 : 0;
// set it up
int DSS = bits - 1; // DSS (data select size)
int FRF = 0; // FRF (frame format) = SPI
int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
int SPH = (phase) ? 1 : 0; // SPH - clock out phase
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
int FRF = 0; // FRF (frame format) = SPI
uint32_t tmp = obj->spi->CR0;
tmp &= ~(0xFFFF);
tmp |= DSS << 0
@ -182,6 +271,18 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) {
| ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave
| 0 << 3; // SOD - slave output disable - na
obj->spi->CR1 = tmp;
#elif defined(TARGET_LPC812)
uint32_t tmp = obj->spi->CFG;
tmp &= ~((1 << 2) | (1 << 4) | (1 << 5));
tmp |= (SPH << 4) | (SPO << 5) | ((slave ? 0 : 1) << 2);
obj->spi->CFG = tmp;
// select frame length
tmp = obj->spi->TXDATCTL;
tmp &= ~(0xf << 24);
tmp |= (DSS << 24);
obj->spi->TXDATCTL = tmp;
#endif
ssp_enable(obj);
}
@ -204,6 +305,8 @@ void spi_frequency(spi_t *obj, int hz) {
#endif
uint32_t PCLK = SystemCoreClock;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
int prescaler;
for (prescaler = 2; prescaler <= 254; prescaler += 2) {
@ -225,36 +328,72 @@ void spi_frequency(spi_t *obj, int hz) {
}
}
error("Couldn't setup requested SPI frequency");
#elif defined(TARGET_LPC812)
obj->spi->DIV = PCLK/hz - 1;
obj->spi->DLY = 0;
ssp_enable(obj);
#endif
}
static inline int ssp_disable(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->CR1 &= ~(1 << 1);
#elif defined(TARGET_LPC812)
return obj->spi->CFG &= ~(1 << 0);
#endif
}
static inline int ssp_enable(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->CR1 |= (1 << 1);
#elif defined(TARGET_LPC812)
return obj->spi->CFG |= (1 << 0);
#endif
}
static inline int ssp_readable(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->SR & (1 << 2);
#elif defined(TARGET_LPC812)
return obj->spi->STAT & (1 << 0);
#endif
}
static inline int ssp_writeable(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->SR & (1 << 1);
#elif defined(TARGET_LPC812)
return obj->spi->STAT & (1 << 1);
#endif
}
static inline void ssp_write(spi_t *obj, int value) {
while (!ssp_writeable(obj));
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
obj->spi->DR = value;
#elif defined(TARGET_LPC812)
// end of transfer
obj->spi->TXDATCTL |= (1 << 20);
obj->spi->TXDAT = value;
#endif
}
static inline int ssp_read(spi_t *obj) {
while (!ssp_readable(obj));
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->DR;
#elif defined(TARGET_LPC812)
return obj->spi->RXDAT;
#endif
}
static inline int ssp_busy(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return (obj->spi->SR & (1 << 4)) ? (1) : (0);
#elif defined(TARGET_LPC812)
// TODO
return 0;
#endif
}
int spi_master_write(spi_t *obj, int value) {
@ -267,12 +406,20 @@ int spi_slave_receive(spi_t *obj) {
};
int spi_slave_read(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->DR;
#elif defined(TARGET_LPC812)
return obj->spi->RXDAT;
#endif
}
void spi_slave_write(spi_t *obj, int value) {
while (ssp_writeable(obj) == 0) ;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
obj->spi->DR = value;
#elif defined(TARGET_LPC812)
obj->spi->TXDAT = value;
#endif
}
int spi_busy(spi_t *obj) {

View File

@ -6,7 +6,7 @@
#include "cmsis_nvic.h"
#define NVIC_NUM_VECTORS (16 + 32) // CORE + MCU Peripherals
#define NVIC_RAM_VECTOR_ADDRESS (0x1FFFF000) // Vectors positioned at start of RAM
#define NVIC_RAM_VECTOR_ADDRESS (0x10000000) // Vectors positioned at start of RAM
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
static volatile uint32_t* vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS;