mirror of https://github.com/ARMmbed/mbed-os.git
commit
34a43eaa41
|
@ -51,6 +51,13 @@ public:
|
||||||
TxIrq
|
TxIrq
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Flow {
|
||||||
|
Disabled = 0,
|
||||||
|
RTS,
|
||||||
|
CTS,
|
||||||
|
RTSCTS
|
||||||
|
};
|
||||||
|
|
||||||
/** Set the transmission format used by the serial port
|
/** Set the transmission format used by the serial port
|
||||||
*
|
*
|
||||||
* @param bits The number of bits in a word (5-8; default = 8)
|
* @param bits The number of bits in a word (5-8; default = 8)
|
||||||
|
@ -100,6 +107,16 @@ public:
|
||||||
*/
|
*/
|
||||||
void send_break();
|
void send_break();
|
||||||
|
|
||||||
|
#if DEVICE_SERIAL_FC
|
||||||
|
/** Set the flow control type on the serial port
|
||||||
|
*
|
||||||
|
* @param type the flow control type (Disabled, RTS, CTS, RTSCTS)
|
||||||
|
* @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS)
|
||||||
|
* @param flow2 the second flow control pin (CTS for RTSCTS)
|
||||||
|
*/
|
||||||
|
void set_flow_control(Flow type, PinName flow1=NC, PinName flow2=NC);
|
||||||
|
#endif
|
||||||
|
|
||||||
static void _irq_handler(uint32_t id, SerialIrq irq_type);
|
static void _irq_handler(uint32_t id, SerialIrq irq_type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -81,6 +81,28 @@ void SerialBase::send_break() {
|
||||||
serial_break_clear(&_serial);
|
serial_break_clear(&_serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEVICE_SERIAL_FC
|
||||||
|
void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) {
|
||||||
|
FlowControl flow_type = (FlowControl)type;
|
||||||
|
switch(type) {
|
||||||
|
case RTS:
|
||||||
|
serial_set_flow_control(&_serial, flow_type, flow1, NC);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CTS:
|
||||||
|
serial_set_flow_control(&_serial, flow_type, NC, flow1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTSCTS:
|
||||||
|
serial_set_flow_control(&_serial, flow_type, flow1, flow2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace mbed
|
} // namespace mbed
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,17 +44,22 @@ uint32_t pinmap_merge(uint32_t a, uint32_t b) {
|
||||||
return (uint32_t)NC;
|
return (uint32_t)NC;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pinmap_peripheral(PinName pin, const PinMap* map) {
|
uint32_t pinmap_find_peripheral(PinName pin, const PinMap* map) {
|
||||||
if (pin == (PinName)NC)
|
|
||||||
return (uint32_t)NC;
|
|
||||||
|
|
||||||
while (map->pin != NC) {
|
while (map->pin != NC) {
|
||||||
if (map->pin == pin)
|
if (map->pin == pin)
|
||||||
return map->peripheral;
|
return map->peripheral;
|
||||||
map++;
|
map++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no mapping available
|
|
||||||
error("pinmap not found for peripheral");
|
|
||||||
return (uint32_t)NC;
|
return (uint32_t)NC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pinmap_peripheral(PinName pin, const PinMap* map) {
|
||||||
|
uint32_t peripheral = (uint32_t)NC;
|
||||||
|
|
||||||
|
if (pin == (PinName)NC)
|
||||||
|
return (uint32_t)NC;
|
||||||
|
peripheral = pinmap_find_peripheral(pin, map);
|
||||||
|
if ((uint32_t)NC == peripheral) // no mapping available
|
||||||
|
error("pinmap not found for peripheral");
|
||||||
|
return peripheral;
|
||||||
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ void pin_mode (PinName pin, PinMode mode);
|
||||||
uint32_t pinmap_peripheral(PinName pin, const PinMap* map);
|
uint32_t pinmap_peripheral(PinName pin, const PinMap* map);
|
||||||
uint32_t pinmap_merge (uint32_t a, uint32_t b);
|
uint32_t pinmap_merge (uint32_t a, uint32_t b);
|
||||||
void pinmap_pinout (PinName pin, const PinMap *map);
|
void pinmap_pinout (PinName pin, const PinMap *map);
|
||||||
|
uint32_t pinmap_find_peripheral(PinName pin, const PinMap* map);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,13 @@ typedef enum {
|
||||||
TxIrq
|
TxIrq
|
||||||
} SerialIrq;
|
} SerialIrq;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FlowControlNone,
|
||||||
|
FlowControlRTS,
|
||||||
|
FlowControlCTS,
|
||||||
|
FlowControlRTSCTS
|
||||||
|
} FlowControl;
|
||||||
|
|
||||||
typedef void (*uart_irq_handler)(uint32_t id, SerialIrq event);
|
typedef void (*uart_irq_handler)(uint32_t id, SerialIrq event);
|
||||||
|
|
||||||
typedef struct serial_s serial_t;
|
typedef struct serial_s serial_t;
|
||||||
|
@ -60,6 +67,8 @@ void serial_break_clear(serial_t *obj);
|
||||||
|
|
||||||
void serial_pinout_tx(PinName tx);
|
void serial_pinout_tx(PinName tx);
|
||||||
|
|
||||||
|
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#define DEVICE_ANALOGOUT 1
|
#define DEVICE_ANALOGOUT 1
|
||||||
|
|
||||||
#define DEVICE_SERIAL 1
|
#define DEVICE_SERIAL 1
|
||||||
|
#define DEVICE_SERIAL_FC 1
|
||||||
|
|
||||||
#define DEVICE_I2C 1
|
#define DEVICE_I2C 1
|
||||||
#define DEVICE_I2CSLAVE 1
|
#define DEVICE_I2CSLAVE 1
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "PortNames.h"
|
#include "PortNames.h"
|
||||||
#include "PeripheralNames.h"
|
#include "PeripheralNames.h"
|
||||||
#include "PinNames.h"
|
#include "PinNames.h"
|
||||||
|
#include "gpio_object.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -47,7 +48,6 @@ struct pwmout_s {
|
||||||
struct serial_s {
|
struct serial_s {
|
||||||
LPC_UART_TypeDef *uart;
|
LPC_UART_TypeDef *uart;
|
||||||
int index;
|
int index;
|
||||||
uint8_t count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct analogin_s {
|
struct analogin_s {
|
||||||
|
@ -71,8 +71,6 @@ struct spi_s {
|
||||||
LPC_SSP_TypeDef *spi;
|
LPC_SSP_TypeDef *spi;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "gpio_object.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "gpio_api.h"
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* INITIALIZATION
|
* INITIALIZATION
|
||||||
|
@ -51,12 +52,35 @@ static const PinMap PinMap_UART_RX[] = {
|
||||||
{NC , NC , 0}
|
{NC , NC , 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t serial_irq_ids[UART_NUM] = {0};
|
static const PinMap PinMap_UART_RTS[] = {
|
||||||
|
{P0_22, UART_1, 1},
|
||||||
|
{P2_7, UART_1, 2},
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PinMap PinMap_UART_CTS[] = {
|
||||||
|
{P0_17, UART_1, 1},
|
||||||
|
{P2_2, UART_1, 2},
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define UART_MCR_RTSEN_MASK (1 << 6)
|
||||||
|
#define UART_MCR_CTSEN_MASK (1 << 7)
|
||||||
|
#define UART_MCR_FLOWCTRL_MASK (UART_MCR_RTSEN_MASK | UART_MCR_CTSEN_MASK)
|
||||||
|
|
||||||
static uart_irq_handler irq_handler;
|
static uart_irq_handler irq_handler;
|
||||||
|
|
||||||
int stdio_uart_inited = 0;
|
int stdio_uart_inited = 0;
|
||||||
serial_t stdio_uart;
|
serial_t stdio_uart;
|
||||||
|
|
||||||
|
struct serial_global_data_s {
|
||||||
|
uint32_t serial_irq_id;
|
||||||
|
gpio_t sw_rts, sw_cts;
|
||||||
|
uint8_t rx_irq_set_flow, rx_irq_set_api;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct serial_global_data_s uart_data[UART_NUM];
|
||||||
|
|
||||||
void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
||||||
int is_stdio_uart = 0;
|
int is_stdio_uart = 0;
|
||||||
|
|
||||||
|
@ -106,7 +130,9 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
||||||
case UART_2: obj->index = 2; break;
|
case UART_2: obj->index = 2; break;
|
||||||
case UART_3: obj->index = 3; break;
|
case UART_3: obj->index = 3; break;
|
||||||
}
|
}
|
||||||
obj->count = 0;
|
uart_data[obj->index].sw_rts.pin = NC;
|
||||||
|
uart_data[obj->index].sw_cts.pin = NC;
|
||||||
|
serial_set_flow_control(obj, FlowControlNone, NC, NC);
|
||||||
|
|
||||||
is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
|
is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
|
||||||
|
|
||||||
|
@ -117,7 +143,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_free(serial_t *obj) {
|
void serial_free(serial_t *obj) {
|
||||||
serial_irq_ids[obj->index] = 0;
|
uart_data[obj->index].serial_irq_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// serial_baud
|
// serial_baud
|
||||||
|
@ -251,7 +277,7 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* INTERRUPTS HANDLING
|
* INTERRUPTS HANDLING
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static inline void uart_irq(uint32_t iir, uint32_t index) {
|
static inline void uart_irq(uint32_t iir, uint32_t index, LPC_UART_TypeDef *puart) {
|
||||||
// [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) {
|
switch (iir) {
|
||||||
|
@ -259,22 +285,28 @@ static inline void uart_irq(uint32_t iir, uint32_t index) {
|
||||||
case 2: irq_type = RxIrq; break;
|
case 2: irq_type = RxIrq; break;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) {
|
||||||
if (serial_irq_ids[index] != 0)
|
gpio_write(&uart_data[index].sw_rts, 1);
|
||||||
irq_handler(serial_irq_ids[index], irq_type);
|
// Disable interrupt if it wasn't enabled by other part of the application
|
||||||
|
if (!uart_data[index].rx_irq_set_api)
|
||||||
|
puart->IER &= ~(1 << RxIrq);
|
||||||
|
}
|
||||||
|
if (uart_data[index].serial_irq_id != 0)
|
||||||
|
if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api))
|
||||||
|
irq_handler(uart_data[index].serial_irq_id, irq_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart0_irq() {uart_irq((LPC_UART0->IIR >> 1) & 0x7, 0);}
|
void uart0_irq() {uart_irq((LPC_UART0->IIR >> 1) & 0x7, 0, (LPC_UART_TypeDef*)LPC_UART0);}
|
||||||
void uart1_irq() {uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1);}
|
void uart1_irq() {uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1, (LPC_UART_TypeDef*)LPC_UART1);}
|
||||||
void uart2_irq() {uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2);}
|
void uart2_irq() {uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2, (LPC_UART_TypeDef*)LPC_UART2);}
|
||||||
void uart3_irq() {uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3);}
|
void uart3_irq() {uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3, (LPC_UART_TypeDef*)LPC_UART3);}
|
||||||
|
|
||||||
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) {
|
||||||
irq_handler = handler;
|
irq_handler = handler;
|
||||||
serial_irq_ids[obj->index] = id;
|
uart_data[obj->index].serial_irq_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
|
static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) {
|
||||||
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) {
|
||||||
|
@ -288,7 +320,7 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
|
||||||
obj->uart->IER |= 1 << irq;
|
obj->uart->IER |= 1 << irq;
|
||||||
NVIC_SetVector(irq_n, vector);
|
NVIC_SetVector(irq_n, vector);
|
||||||
NVIC_EnableIRQ(irq_n);
|
NVIC_EnableIRQ(irq_n);
|
||||||
} else { // disable
|
} else if ((TxIrq == irq) || (uart_data[obj->index].rx_irq_set_api + uart_data[obj->index].rx_irq_set_flow == 0)) { // disable
|
||||||
int all_disabled = 0;
|
int all_disabled = 0;
|
||||||
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
||||||
obj->uart->IER &= ~(1 << irq);
|
obj->uart->IER &= ~(1 << irq);
|
||||||
|
@ -298,18 +330,33 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
|
||||||
|
if (RxIrq == irq)
|
||||||
|
uart_data[obj->index].rx_irq_set_api = enable;
|
||||||
|
serial_irq_set_internal(obj, irq, enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void serial_flow_irq_set(serial_t *obj, uint32_t enable) {
|
||||||
|
uart_data[obj->index].rx_irq_set_flow = enable;
|
||||||
|
serial_irq_set_internal(obj, RxIrq, enable);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* READ/WRITE
|
* READ/WRITE
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int serial_getc(serial_t *obj) {
|
int serial_getc(serial_t *obj) {
|
||||||
while (!serial_readable(obj));
|
while (!serial_readable(obj));
|
||||||
return obj->uart->RBR;
|
int data = obj->uart->RBR;
|
||||||
|
if (NC != uart_data[obj->index].sw_rts.pin) {
|
||||||
|
gpio_write(&uart_data[obj->index].sw_rts, 0);
|
||||||
|
obj->uart->IER |= 1 << RxIrq;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_putc(serial_t *obj, int c) {
|
void serial_putc(serial_t *obj, int c) {
|
||||||
while (!serial_writable(obj));
|
while (!serial_writable(obj));
|
||||||
obj->uart->THR = c;
|
obj->uart->THR = c;
|
||||||
obj->count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int serial_readable(serial_t *obj) {
|
int serial_readable(serial_t *obj) {
|
||||||
|
@ -318,11 +365,10 @@ int serial_readable(serial_t *obj) {
|
||||||
|
|
||||||
int serial_writable(serial_t *obj) {
|
int serial_writable(serial_t *obj) {
|
||||||
int isWritable = 1;
|
int isWritable = 1;
|
||||||
if (obj->uart->LSR & 0x20)
|
if (NC != uart_data[obj->index].sw_cts.pin)
|
||||||
obj->count = 0;
|
isWritable = gpio_read(&uart_data[obj->index].sw_cts) == 0;
|
||||||
else if (obj->count >= 16)
|
if (isWritable)
|
||||||
isWritable = 0;
|
isWritable = obj->uart->LSR & 0x40;
|
||||||
|
|
||||||
return isWritable;
|
return isWritable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,3 +391,49 @@ void serial_break_clear(serial_t *obj) {
|
||||||
obj->uart->LCR &= ~(1 << 6);
|
obj->uart->LCR &= ~(1 << 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) {
|
||||||
|
// Only UART1 has hardware flow control on LPC176x
|
||||||
|
LPC_UART1_TypeDef *uart1 = (uint32_t)obj->uart == (uint32_t)LPC_UART1 ? LPC_UART1 : NULL;
|
||||||
|
int index = obj->index;
|
||||||
|
|
||||||
|
// First, disable flow control completely
|
||||||
|
if (uart1)
|
||||||
|
uart1->MCR = uart1->MCR & ~UART_MCR_FLOWCTRL_MASK;
|
||||||
|
uart_data[index].sw_rts.pin = uart_data[index].sw_cts.pin = NC;
|
||||||
|
serial_flow_irq_set(obj, 0);
|
||||||
|
if (FlowControlNone == type)
|
||||||
|
return;
|
||||||
|
// Check type(s) of flow control to use
|
||||||
|
UARTName uart_rts = (UARTName)pinmap_find_peripheral(rxflow, PinMap_UART_RTS);
|
||||||
|
UARTName uart_cts = (UARTName)pinmap_find_peripheral(txflow, PinMap_UART_CTS);
|
||||||
|
if (((FlowControlCTS == type) || (FlowControlRTSCTS == type)) && (NC != txflow)) {
|
||||||
|
// Can this be enabled in hardware?
|
||||||
|
if ((UART_1 == uart_cts) && (NULL != uart1)) {
|
||||||
|
// Enable auto-CTS mode
|
||||||
|
uart1->MCR |= UART_MCR_CTSEN_MASK;
|
||||||
|
pinmap_pinout(txflow, PinMap_UART_CTS);
|
||||||
|
} else {
|
||||||
|
// Can't enable in hardware, use software emulation
|
||||||
|
gpio_init(&uart_data[index].sw_cts, txflow, PIN_INPUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (((FlowControlRTS == type) || (FlowControlRTSCTS == type)) && (NC != rxflow)) {
|
||||||
|
// Enable FIFOs, trigger level of 1 char on RX FIFO
|
||||||
|
obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
|
||||||
|
| 1 << 1 // Rx Fifo Reset
|
||||||
|
| 1 << 2 // Tx Fifo Reset
|
||||||
|
| 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
|
||||||
|
// Can this be enabled in hardware?
|
||||||
|
if ((UART_1 == uart_rts) && (NULL != uart1)) {
|
||||||
|
// Enable auto-RTS mode
|
||||||
|
uart1->MCR |= UART_MCR_RTSEN_MASK;
|
||||||
|
pinmap_pinout(rxflow, PinMap_UART_RTS);
|
||||||
|
} else { // can't enable in hardware, use software emulation
|
||||||
|
gpio_init(&uart_data[index].sw_rts, rxflow, PIN_OUTPUT);
|
||||||
|
gpio_write(&uart_data[index].sw_rts, 0);
|
||||||
|
// Enable RX interrupt
|
||||||
|
serial_flow_irq_set(obj, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#define DEVICE_ANALOGOUT 0
|
#define DEVICE_ANALOGOUT 0
|
||||||
|
|
||||||
#define DEVICE_SERIAL 1
|
#define DEVICE_SERIAL 1
|
||||||
|
#define DEVICE_SERIAL_FC 1
|
||||||
|
|
||||||
#define DEVICE_I2C 1
|
#define DEVICE_I2C 1
|
||||||
#define DEVICE_I2CSLAVE 0
|
#define DEVICE_I2CSLAVE 0
|
||||||
|
|
|
@ -39,6 +39,18 @@ static const SWM_Map SWM_UART_RX[] = {
|
||||||
{2, 24},
|
{2, 24},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const SWM_Map SWM_UART_RTS[] = {
|
||||||
|
{0, 16},
|
||||||
|
{1, 24},
|
||||||
|
{3, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const SWM_Map SWM_UART_CTS[] = {
|
||||||
|
{0, 24},
|
||||||
|
{2, 0},
|
||||||
|
{3, 8}
|
||||||
|
};
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -60,6 +72,7 @@ static int get_available_uart(void) {
|
||||||
#define TXRDY (0x01<<2)
|
#define TXRDY (0x01<<2)
|
||||||
|
|
||||||
#define TXBRKEN (0x01<<1)
|
#define TXBRKEN (0x01<<1)
|
||||||
|
#define CTSEN (0x01<<9)
|
||||||
|
|
||||||
static uint32_t UARTSysClk;
|
static uint32_t UARTSysClk;
|
||||||
|
|
||||||
|
@ -278,3 +291,34 @@ void serial_break_clear(serial_t *obj) {
|
||||||
obj->uart->CTRL &= ~TXBRKEN;
|
obj->uart->CTRL &= ~TXBRKEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) {
|
||||||
|
const SWM_Map *swm_rts, *swm_cts;
|
||||||
|
uint32_t regVal_rts, regVal_cts;
|
||||||
|
|
||||||
|
swm_rts = &SWM_UART_RTS[obj->index];
|
||||||
|
swm_cts = &SWM_UART_CTS[obj->index];
|
||||||
|
regVal_rts = LPC_SWM->PINASSIGN[swm_rts->n] & ~(0xFF << swm_rts->offset);
|
||||||
|
regVal_cts = LPC_SWM->PINASSIGN[swm_cts->n] & ~(0xFF << swm_cts->offset);
|
||||||
|
|
||||||
|
if (FlowControlNone == type) {
|
||||||
|
LPC_SWM->PINASSIGN[swm_rts->n] = regVal_rts | (0xFF << swm_rts->offset);
|
||||||
|
LPC_SWM->PINASSIGN[swm_cts->n] = regVal_cts | (0xFF << swm_cts->offset);
|
||||||
|
obj->uart->CFG &= ~CTSEN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((FlowControlRTS == type || FlowControlRTSCTS == type) && (rxflow != NC)) {
|
||||||
|
LPC_SWM->PINASSIGN[swm_rts->n] = regVal_rts | (rxflow << swm_rts->offset);
|
||||||
|
if (FlowControlRTS == type) {
|
||||||
|
LPC_SWM->PINASSIGN[swm_cts->n] = regVal_cts | (0xFF << swm_cts->offset);
|
||||||
|
obj->uart->CFG &= ~CTSEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((FlowControlCTS == type || FlowControlRTSCTS == type) && (txflow != NC)) {
|
||||||
|
LPC_SWM->PINASSIGN[swm_cts->n] = regVal_cts | (txflow << swm_cts->offset);
|
||||||
|
obj->uart->CFG |= CTSEN;
|
||||||
|
if (FlowControlCTS == type) {
|
||||||
|
LPC_SWM->PINASSIGN[swm_rts->n] = regVal_rts | (0xFF << swm_rts->offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "mbed.h"
|
||||||
|
|
||||||
|
#if defined(TARGET_LPC1768)
|
||||||
|
#define UART_TX p13
|
||||||
|
#define UART_RX p14
|
||||||
|
#define FLOW_CONTROL_RTS p30
|
||||||
|
#define FLOW_CONTROL_CTS p12
|
||||||
|
#define RTS_CHECK_PIN p15
|
||||||
|
#else
|
||||||
|
#error This test is not supported on this target
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Serial pc(UART_TX, UART_RX);
|
||||||
|
|
||||||
|
#ifdef RTS_CHECK_PIN
|
||||||
|
InterruptIn in(RTS_CHECK_PIN);
|
||||||
|
DigitalOut led(LED1);
|
||||||
|
static void checker(void) {
|
||||||
|
led = !led;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
pc.set_flow_control(Serial::RTSCTS, FLOW_CONTROL_RTS, FLOW_CONTROL_CTS);
|
||||||
|
#ifdef RTS_CHECK_PIN
|
||||||
|
in.fall(checker);
|
||||||
|
#endif
|
||||||
|
while (1) {
|
||||||
|
pc.gets(buf, 256);
|
||||||
|
pc.printf("%s", buf);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ from os.path import join, abspath, dirname
|
||||||
|
|
||||||
# Be sure that the tools directory is in the search path
|
# Be sure that the tools directory is in the search path
|
||||||
ROOT = abspath(join(dirname(__file__), ".."))
|
ROOT = abspath(join(dirname(__file__), ".."))
|
||||||
sys.path.append(ROOT)
|
sys.path.insert(0, ROOT)
|
||||||
|
|
||||||
from workspace_tools.toolchains import TOOLCHAINS
|
from workspace_tools.toolchains import TOOLCHAINS
|
||||||
from workspace_tools.targets import TARGET_NAMES, TARGET_MAP
|
from workspace_tools.targets import TARGET_NAMES, TARGET_MAP
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
"""
|
||||||
|
mbed SDK
|
||||||
|
Copyright (c) 2011-2013 ARM Limited
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
"""
|
||||||
|
from host_test import Test
|
||||||
|
|
||||||
|
|
||||||
|
class EchoTest(Test):
|
||||||
|
def __init__(self):
|
||||||
|
Test.__init__(self)
|
||||||
|
self.mbed.init_serial()
|
||||||
|
self.mbed.extra_serial.rtscts = True
|
||||||
|
self.mbed.reset()
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
self.mbed.flush()
|
||||||
|
self.notify("Starting the ECHO test")
|
||||||
|
TEST="longer serial test"
|
||||||
|
check = True
|
||||||
|
for i in range(1, 100):
|
||||||
|
self.mbed.extra_serial.write(TEST + "\n")
|
||||||
|
l = self.mbed.extra_serial.readline().strip()
|
||||||
|
if not l: continue
|
||||||
|
|
||||||
|
if l != TEST:
|
||||||
|
check = False
|
||||||
|
self.notify('"%s" != "%s"' % (l, TEST))
|
||||||
|
else:
|
||||||
|
if (i % 10) == 0:
|
||||||
|
self.notify('.')
|
||||||
|
|
||||||
|
return check
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
EchoTest().run()
|
|
@ -39,6 +39,9 @@ class Mbed:
|
||||||
parser.add_option("-t", "--timeout", dest="timeout",
|
parser.add_option("-t", "--timeout", dest="timeout",
|
||||||
help="Timeout", metavar="TIMEOUT")
|
help="Timeout", metavar="TIMEOUT")
|
||||||
|
|
||||||
|
parser.add_option("-e", "--extra", dest="extra",
|
||||||
|
help="Extra serial port (used by some tests)", metavar="EXTRA")
|
||||||
|
|
||||||
(self.options, _) = parser.parse_args()
|
(self.options, _) = parser.parse_args()
|
||||||
|
|
||||||
if self.options.port is None:
|
if self.options.port is None:
|
||||||
|
@ -46,14 +49,19 @@ class Mbed:
|
||||||
|
|
||||||
self.port = self.options.port
|
self.port = self.options.port
|
||||||
self.disk = self.options.disk
|
self.disk = self.options.disk
|
||||||
|
self.extra_port = self.options.extra
|
||||||
|
self.extra_serial = None
|
||||||
self.serial = None
|
self.serial = None
|
||||||
self.timeout = 10 if self.options.timeout is None else self.options.timeout
|
self.timeout = 10 if self.options.timeout is None else self.options.timeout
|
||||||
|
|
||||||
print 'Mbed: "%s" "%s"' % (self.port, self.disk)
|
print 'Mbed: "%s" "%s"' % (self.port, self.disk)
|
||||||
|
|
||||||
def init_serial(self, baud=9600):
|
def init_serial(self, baud=9600, extra_baud=9600):
|
||||||
self.serial = Serial(self.port, timeout = 1)
|
self.serial = Serial(self.port, timeout = 1)
|
||||||
self.serial.setBaudrate(baud)
|
self.serial.setBaudrate(baud)
|
||||||
|
if self.extra_port:
|
||||||
|
self.extra_serial = Serial(self.extra_port, timeout = 1)
|
||||||
|
self.extra_serial.setBaudrate(extra_baud)
|
||||||
self.flush()
|
self.flush()
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
|
@ -64,7 +72,9 @@ class Mbed:
|
||||||
def flush(self):
|
def flush(self):
|
||||||
self.serial.flushInput()
|
self.serial.flushInput()
|
||||||
self.serial.flushOutput()
|
self.serial.flushOutput()
|
||||||
|
if self.extra_serial:
|
||||||
|
self.extra_serial.flushInput()
|
||||||
|
self.extra_serial.flushOutput()
|
||||||
|
|
||||||
class Test:
|
class Test:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
@ -57,9 +57,9 @@ class ProcessObserver(Thread):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def run_host_test(client, name, disk, port, duration):
|
def run_host_test(client, name, disk, port, duration, extra_serial):
|
||||||
print "{%s}" % name,
|
print "{%s}" % name,
|
||||||
cmd = ["python", "%s.py" % name, '-p', port, '-d', disk, '-t', str(duration)]
|
cmd = ["python", "%s.py" % name, '-p', port, '-d', disk, '-t', str(duration), "-e", extra_serial]
|
||||||
proc = Popen(cmd, stdout=PIPE, cwd=HOST_TESTS)
|
proc = Popen(cmd, stdout=PIPE, cwd=HOST_TESTS)
|
||||||
obs = ProcessObserver(proc)
|
obs = ProcessObserver(proc)
|
||||||
start = time()
|
start = time()
|
||||||
|
@ -144,6 +144,7 @@ class Tester(BaseRequestHandler):
|
||||||
|
|
||||||
disk = mut['disk']
|
disk = mut['disk']
|
||||||
port = mut['port']
|
port = mut['port']
|
||||||
|
extra_serial = mut.get('extra_serial', "")
|
||||||
target = TARGET_MAP[mut['mcu']]
|
target = TARGET_MAP[mut['mcu']]
|
||||||
|
|
||||||
# Program
|
# Program
|
||||||
|
@ -169,7 +170,7 @@ class Tester(BaseRequestHandler):
|
||||||
|
|
||||||
# Host test
|
# Host test
|
||||||
self.request.setblocking(0)
|
self.request.setblocking(0)
|
||||||
result = run_host_test(self.request, test.host_test, disk, port, duration)
|
result = run_host_test(self.request, test.host_test, disk, port, duration, extra_serial)
|
||||||
self.send_result(result)
|
self.send_result(result)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,15 @@ TESTS = [
|
||||||
"automated": True,
|
"automated": True,
|
||||||
"mcu": ["LPC4088"]
|
"mcu": ["LPC4088"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "MBED_A24", "description": "Serial echo with RTS/CTS flow control",
|
||||||
|
"source_dir": join(TEST_DIR, "mbed", "echo_flow_control"),
|
||||||
|
"dependencies": [MBED_LIBRARIES],
|
||||||
|
"automated": "True",
|
||||||
|
"host_test": "echo_flow_control",
|
||||||
|
"mcu": ["LPC1768"],
|
||||||
|
"peripherals": ["extra_serial"]
|
||||||
|
},
|
||||||
|
|
||||||
# Size benchmarks
|
# Size benchmarks
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue