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_PORTOUT 0
#define DEVICE_PORTINOUT 0 #define DEVICE_PORTINOUT 0
#define DEVICE_INTERRUPTIN 0 #define DEVICE_INTERRUPTIN 1
#define DEVICE_ANALOGIN 0 #define DEVICE_ANALOGIN 0
#define DEVICE_ANALOGOUT 0 #define DEVICE_ANALOGOUT 0
#define DEVICE_SERIAL 1 #define DEVICE_SERIAL 1
#define DEVICE_I2C 0 #define DEVICE_I2C 1
#define DEVICE_I2CSLAVE 0 #define DEVICE_I2CSLAVE 0
#define DEVICE_SPI 0 #define DEVICE_SPI 1
#define DEVICE_SPISLAVE 0 #define DEVICE_SPISLAVE 0
#define DEVICE_CAN 0 #define DEVICE_CAN 0

View File

@ -25,9 +25,22 @@
extern "C" { extern "C" {
#endif #endif
struct gpio_irq_s {
uint32_t ch;
};
struct serial_s { struct serial_s {
LPC_USART_TypeDef *uart; 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" #include "gpio_object.h"

View File

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

View File

@ -62,21 +62,38 @@ static const PinMap PinMap_I2C_SCL[] = {
#define I2C_DAT(x) (x->i2c->DAT) #define I2C_DAT(x) (x->i2c->DAT)
#define I2C_SCLL(x, val) (x->i2c->SCLL = val) #define I2C_SCLL(x, val) (x->i2c->SCLL = val)
#define I2C_SCLH(x, val) (x->i2c->SCLH = 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 #endif
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
static const uint32_t I2C_addr_offset[2][4] = { static const uint32_t I2C_addr_offset[2][4] = {
{0x0C, 0x20, 0x24, 0x28}, {0x0C, 0x20, 0x24, 0x28},
{0x30, 0x34, 0x38, 0x3C} {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) I2C_CONCLR(obj) = (start << 5)
| (stop << 4) | (stop << 4)
| (interrupt << 3) | (interrupt << 3)
| (acknowledge << 2); | (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) I2C_CONSET(obj) = (start << 5)
| (stop << 4) | (stop << 4)
| (interrupt << 3) | (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) // 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); 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); return I2C_STAT(obj);
} }
// Wait until the Serial Interrupt (SI) is set // Wait until the Serial Interrupt (SI) is set
static int i2c_wait_SI(i2c_t *obj) { static int i2c_wait_SI(i2c_t *obj) {
int timeout = 0; int timeout = 0;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
while (!(I2C_CONSET(obj) & (1 << 3))) { while (!(I2C_CONSET(obj) & (1 << 3))) {
#elif defined(TARGET_LPC812)
while (!(obj->i2c->STAT & (1 << 0))) {
#endif
timeout++; timeout++;
if (timeout > 100000) return -1; if (timeout > 100000) return -1;
} }
return 0; 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; 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) #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
switch ((int)obj->i2c) { switch ((int)obj->i2c) {
case I2C_0: LPC_SC->PCONP |= 1 << 7; break; 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) #elif defined(TARGET_LPC11U24)
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 5); LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 5);
LPC_SYSCON->PRESETCTRL |= 1 << 1; 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 #endif
} }
void i2c_init(i2c_t *obj, PinName sda, PinName scl) { 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 // determine the SPI to use
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); 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) #elif defined(TARGET_LPC11U24)
obj->i2c = (LPC_I2C_Type *)pinmap_merge(i2c_sda, i2c_scl); obj->i2c = (LPC_I2C_Type *)pinmap_merge(i2c_sda, i2c_scl);
#endif #endif
if ((int)obj->i2c == NC) { if ((int)obj->i2c == NC) {
error("I2C pin mapping failed"); 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(sda, PinMap_I2C_SDA);
pinmap_pinout(scl, PinMap_I2C_SCL); 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) { inline int i2c_start(i2c_t *obj) {
int status; 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: // 8.1 Before master mode can be entered, I2CON must be initialised to:
// - I2EN STA STO SI AA - - // - I2EN STA STO SI AA - -
// - 1 0 0 0 x - - // - 1 0 0 0 x - -
@ -162,35 +217,52 @@ int i2c_start(i2c_t *obj) {
// Clear start bit now transmitted, and interrupt bit // Clear start bit now transmitted, and interrupt bit
i2c_conclr(obj, 1, 0, 0, 0); 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; 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 // write the stop bit
i2c_conset(obj, 0, 1, 0, 0); i2c_conset(obj, 0, 1, 0, 0);
i2c_clear_SI(obj); i2c_clear_SI(obj);
// wait for STO bit to reset // wait for STO bit to reset
while(I2C_CONSET(obj) & (1 << 4)); 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 // write the data
I2C_DAT(obj) = value; I2C_DAT(obj) = value;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
// clear SI to init a send // clear SI to init a send
i2c_clear_SI(obj); i2c_clear_SI(obj);
#elif defined(TARGET_LPC812)
if (!addr)
obj->i2c->MSTCTL = (1 << 0);
#endif
i2c_wait_SI(obj);
// wait and return status // wait and return status
i2c_wait_SI(obj);
return i2c_status(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) // we are in state 0x40 (SLA+R tx'd) or 0x50 (data rx'd and ack)
if(last) { if(last) {
i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK
} else { } else {
@ -199,10 +271,16 @@ static int i2c_do_read(i2c_t *obj, int last) {
// accept byte // accept byte
i2c_clear_SI(obj); i2c_clear_SI(obj);
#endif
// wait for it to arrive // wait for it to arrive
i2c_wait_SI(obj); i2c_wait_SI(obj);
#if defined(TARGET_LPC812)
if (!last)
obj->i2c->MSTCTL = (1 << 0);
#endif
// return the data // return the data
return (I2C_DAT(obj) & 0xFF); return (I2C_DAT(obj) & 0xFF);
} }
@ -211,16 +289,23 @@ void i2c_frequency(i2c_t *obj, int hz) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
// [TODO] set pclk to /4 // [TODO] set pclk to /4
uint32_t PCLK = SystemCoreClock / 4; uint32_t PCLK = SystemCoreClock / 4;
#elif defined(TARGET_LPC11U24) #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC812)
// No peripheral clock divider on the M0 // No peripheral clock divider on the M0
uint32_t PCLK = SystemCoreClock; uint32_t PCLK = SystemCoreClock;
#endif #endif
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
uint32_t pulse = PCLK / (hz * 2); uint32_t pulse = PCLK / (hz * 2);
// I2C Rate // I2C Rate
I2C_SCLL(obj, pulse); I2C_SCLL(obj, pulse);
I2C_SCLH(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 // 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); status = i2c_start(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if ((status != 0x10) && (status != 0x08)) { if ((status != 0x10) && (status != 0x08)) {
i2c_stop(obj); i2c_stop(obj);
return status; 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) { if (status != 0x40) {
#elif defined(TARGET_LPC812)
if (status != 0x01) {
#endif
i2c_stop(obj); i2c_stop(obj);
return status; 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++) { for (count = 0; count < (length - 1); count++) {
int value = i2c_do_read(obj, 0); int value = i2c_do_read(obj, 0);
status = i2c_status(obj); status = i2c_status(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if (status != 0x50) { if (status != 0x50) {
#elif defined(TARGET_LPC812)
if (status != 0x00) {
#endif
i2c_stop(obj); i2c_stop(obj);
return status; return status;
} }
@ -267,7 +362,11 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
// read in last byte // read in last byte
int value = i2c_do_read(obj, 1); int value = i2c_do_read(obj, 1);
status = i2c_status(obj); status = i2c_status(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if (status != 0x58) { if (status != 0x58) {
#elif defined(TARGET_LPC812)
if (status != 0x01) {
#endif
i2c_stop(obj); i2c_stop(obj);
return status; return status;
} }
@ -278,6 +377,11 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
if (stop) { if (stop) {
i2c_stop(obj); i2c_stop(obj);
} }
#if defined(TARGET_LPC812)
else {
repeated_start = 1;
}
#endif
return 0; 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); status = i2c_start(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
if ((status != 0x10) && (status != 0x08)) { if ((status != 0x10) && (status != 0x08)) {
i2c_stop(obj); i2c_stop(obj);
return status; 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) { if (status != 0x18) {
#elif defined(TARGET_LPC812)
if (status != 0x02) {
#endif
i2c_stop(obj); i2c_stop(obj);
return status; return status;
} }
for (i=0; i<length; i++) { 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) { if(status != 0x28) {
#elif defined(TARGET_LPC812)
if (status != 0x02) {
#endif
i2c_stop(obj); i2c_stop(obj);
return status; return status;
} }
} }
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
i2c_clear_SI(obj); i2c_clear_SI(obj);
#endif
// If not repeated start, send stop.
if (stop) { if (stop) {
i2c_stop(obj); i2c_stop(obj);
} }
#if defined(TARGET_LPC812)
else {
repeated_start = 1;
}
#endif
return 0; 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 i2c_byte_write(i2c_t *obj, int data) {
int ack; int ack;
int status = i2c_do_write(obj, (data & 0xFF)); int status = i2c_do_write(obj, (data & 0xFF), 0);
switch(status) { switch(status) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368)
case 0x18: case 0x28: // Master transmit ACKs case 0x18: case 0x28: // Master transmit ACKs
ack = 1; ack = 1;
break; break;
@ -337,6 +460,11 @@ int i2c_byte_write(i2c_t *obj, int data) {
case 0xB8: // Slave transmit ACK case 0xB8: // Slave transmit ACK
ack = 1; ack = 1;
break; break;
#elif defined(TARGET_LPC812)
case 2:
ack = 1;
break;
#endif
default: default:
ack = 0; ack = 0;
break; break;
@ -403,7 +531,7 @@ int i2c_slave_write(i2c_t *obj, const char *data, int length) {
} }
do { do {
status = i2c_do_write(obj, data[count]); status = i2c_do_write(obj, data[count], 0);
count++; count++;
} while ((count < length) && (status == 0xB8)); } while ((count < length) && (status == 0xB8));

View File

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

View File

@ -88,9 +88,46 @@ static const PinMap PinMap_SPI_SSEL[] = {
{NC , NC , 0} {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 #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) { 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 // determine the SPI to use
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); 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) { if ((int)obj->spi == NC) {
error("SPI pinout mapping failed"); 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 // enable power and clocking
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) #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; LPC_SYSCON->PRESETCTRL |= 1 << 2;
break; 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 #endif
// set default format and frequency // 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_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
} }
spi_frequency(obj, 1000000); spi_frequency(obj, 1000000);
// enable the ssp channel // 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 // pin out the spi pins
pinmap_pinout(mosi, PinMap_SPI_MOSI); pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO); 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) { if (ssel != NC) {
pinmap_pinout(ssel, PinMap_SPI_SSEL); pinmap_pinout(ssel, PinMap_SPI_SSEL);
} }
#endif
} }
void spi_free(spi_t *obj) {} 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) { void spi_format(spi_t *obj, int bits, int mode, int slave) {
ssp_disable(obj); ssp_disable(obj);
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) { 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"); error("SPI format error");
} }
int polarity = (mode & 0x2) ? 1 : 0; int polarity = (mode & 0x2) ? 1 : 0;
int phase = (mode & 0x1) ? 1 : 0; int phase = (mode & 0x1) ? 1 : 0;
// set it up // set it up
int DSS = bits - 1; // DSS (data select size) 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 SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
int SPH = (phase) ? 1 : 0; // SPH - clock out phase 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; uint32_t tmp = obj->spi->CR0;
tmp &= ~(0xFFFF); tmp &= ~(0xFFFF);
tmp |= DSS << 0 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 | ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave
| 0 << 3; // SOD - slave output disable - na | 0 << 3; // SOD - slave output disable - na
obj->spi->CR1 = tmp; 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); ssp_enable(obj);
} }
@ -204,6 +305,8 @@ void spi_frequency(spi_t *obj, int hz) {
#endif #endif
uint32_t PCLK = SystemCoreClock; uint32_t PCLK = SystemCoreClock;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
int prescaler; int prescaler;
for (prescaler = 2; prescaler <= 254; prescaler += 2) { 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"); 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) { static inline int ssp_disable(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->CR1 &= ~(1 << 1); 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) { static inline int ssp_enable(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->CR1 |= (1 << 1); 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) { static inline int ssp_readable(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->SR & (1 << 2); 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) { static inline int ssp_writeable(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->SR & (1 << 1); 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) { static inline void ssp_write(spi_t *obj, int value) {
while (!ssp_writeable(obj)); while (!ssp_writeable(obj));
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
obj->spi->DR = value; 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) { static inline int ssp_read(spi_t *obj) {
while (!ssp_readable(obj)); while (!ssp_readable(obj));
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->DR; return obj->spi->DR;
#elif defined(TARGET_LPC812)
return obj->spi->RXDAT;
#endif
} }
static inline int ssp_busy(spi_t *obj) { 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); 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) { 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) { int spi_slave_read(spi_t *obj) {
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
return obj->spi->DR; return obj->spi->DR;
#elif defined(TARGET_LPC812)
return obj->spi->RXDAT;
#endif
} }
void spi_slave_write(spi_t *obj, int value) { void spi_slave_write(spi_t *obj, int value) {
while (ssp_writeable(obj) == 0) ; while (ssp_writeable(obj) == 0) ;
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC11U24)
obj->spi->DR = value; obj->spi->DR = value;
#elif defined(TARGET_LPC812)
obj->spi->TXDAT = value;
#endif
} }
int spi_busy(spi_t *obj) { int spi_busy(spi_t *obj) {

View File

@ -6,7 +6,7 @@
#include "cmsis_nvic.h" #include "cmsis_nvic.h"
#define NVIC_NUM_VECTORS (16 + 32) // CORE + MCU Peripherals #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) { void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
static volatile uint32_t* vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS; static volatile uint32_t* vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS;