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_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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue