mirror of https://github.com/ARMmbed/mbed-os.git
Add LPC812 peripherals
parent
0da3c49fef
commit
498d5efcc4
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue