mbed library sources(for async_print)
Fork of mbed-src by
Revision 64:7b352733b00a, committed 2013-12-19
- Comitter:
- mbed_official
- Date:
- Thu Dec 19 13:15:07 2013 +0000
- Parent:
- 63:a46ad637dc84
- Child:
- 65:46be7cdf873f
- Commit message:
- Synchronized with git revision 4b4b986cdb24f240f416b7538e9766bec33be31f
Full URL: https://github.com/mbedmicro/mbed/commit/4b4b986cdb24f240f416b7538e9766bec33be31f/
Changed in this revision
--- a/api/RawSerial.h Thu Dec 19 09:00:06 2013 +0000 +++ b/api/RawSerial.h Thu Dec 19 13:15:07 2013 +0000 @@ -71,6 +71,16 @@ * @returns The char read from the serial port */ int getc(); + + /** Write a string to the serial port + * + * @param str The string to write + * + * @returns 0 if the write succeeds, EOF for error + */ + int puts(const char *str); + + int printf(const char *format, ...); }; } // namespace mbed
--- a/api/SerialBase.h Thu Dec 19 09:00:06 2013 +0000 +++ b/api/SerialBase.h Thu Dec 19 13:15:07 2013 +0000 @@ -51,6 +51,13 @@ TxIrq }; + enum Flow { + Disabled = 0, + RTS, + CTS, + RTSCTS + }; + /** Set the transmission format used by the serial port * * @param bits The number of bits in a word (5-8; default = 8) @@ -99,6 +106,16 @@ /** Generate a break condition on the serial line */ 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);
--- a/common/RawSerial.cpp Thu Dec 19 09:00:06 2013 +0000 +++ b/common/RawSerial.cpp Thu Dec 19 13:15:07 2013 +0000 @@ -15,9 +15,12 @@ */ #include "RawSerial.h" #include "wait_api.h" +#include <cstdarg> #if DEVICE_SERIAL +#define STRING_STACK_LIMIT 120 + namespace mbed { RawSerial::RawSerial(PinName tx, PinName rx) : SerialBase(tx, rx) { @@ -31,6 +34,34 @@ return _base_putc(c); } +int RawSerial::puts(const char *str) { + while (*str) + putc(*str ++); + return 0; +} + +// Experimental support for printf in RawSerial. No Stream inheritance +// means we can't call printf() directly, so we use sprintf() instead. +// We only call malloc() for the sprintf() buffer if the buffer +// length is above a certain threshold, otherwise we use just the stack. +int RawSerial::printf(const char *format, ...) { + std::va_list arg; + va_start(arg, format); + int len = vsnprintf(NULL, 0, format, arg); + if (len < STRING_STACK_LIMIT) { + char temp[STRING_STACK_LIMIT]; + vsprintf(temp, format, arg); + puts(temp); + } else { + char *temp = new char[len + 1]; + vsprintf(temp, format, arg); + puts(temp); + delete[] temp; + } + va_end(arg); + return len; +} + } // namespace mbed #endif
--- a/common/SerialBase.cpp Thu Dec 19 09:00:06 2013 +0000 +++ b/common/SerialBase.cpp Thu Dec 19 13:15:07 2013 +0000 @@ -81,6 +81,28 @@ 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 #endif
--- a/common/pinmap_common.c Thu Dec 19 09:00:06 2013 +0000 +++ b/common/pinmap_common.c Thu Dec 19 13:15:07 2013 +0000 @@ -44,17 +44,22 @@ return (uint32_t)NC; } -uint32_t pinmap_peripheral(PinName pin, const PinMap* map) { - if (pin == (PinName)NC) - return (uint32_t)NC; - +uint32_t pinmap_find_peripheral(PinName pin, const PinMap* map) { while (map->pin != NC) { if (map->pin == pin) return map->peripheral; map++; } - - // no mapping available - error("pinmap not found for peripheral"); 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; +}
--- a/hal/pinmap.h Thu Dec 19 09:00:06 2013 +0000 +++ b/hal/pinmap.h Thu Dec 19 13:15:07 2013 +0000 @@ -34,6 +34,7 @@ uint32_t pinmap_peripheral(PinName pin, const PinMap* map); uint32_t pinmap_merge (uint32_t a, uint32_t b); void pinmap_pinout (PinName pin, const PinMap *map); +uint32_t pinmap_find_peripheral(PinName pin, const PinMap* map); #ifdef __cplusplus }
--- a/hal/serial_api.h Thu Dec 19 09:00:06 2013 +0000 +++ b/hal/serial_api.h Thu Dec 19 13:15:07 2013 +0000 @@ -37,6 +37,13 @@ TxIrq } SerialIrq; +typedef enum { + FlowControlNone, + FlowControlRTS, + FlowControlCTS, + FlowControlRTSCTS +} FlowControl; + typedef void (*uart_irq_handler)(uint32_t id, SerialIrq event); typedef struct serial_s serial_t; @@ -60,6 +67,8 @@ void serial_pinout_tx(PinName tx); +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow); + #ifdef __cplusplus } #endif
--- a/targets/hal/TARGET_NXP/TARGET_LPC176X/device.h Thu Dec 19 09:00:06 2013 +0000 +++ b/targets/hal/TARGET_NXP/TARGET_LPC176X/device.h Thu Dec 19 13:15:07 2013 +0000 @@ -26,6 +26,7 @@ #define DEVICE_ANALOGOUT 1 #define DEVICE_SERIAL 1 +#define DEVICE_SERIAL_FC 1 #define DEVICE_I2C 1 #define DEVICE_I2CSLAVE 1
--- a/targets/hal/TARGET_NXP/TARGET_LPC176X/objects.h Thu Dec 19 09:00:06 2013 +0000 +++ b/targets/hal/TARGET_NXP/TARGET_LPC176X/objects.h Thu Dec 19 13:15:07 2013 +0000 @@ -20,6 +20,7 @@ #include "PortNames.h" #include "PeripheralNames.h" #include "PinNames.h" +#include "gpio_object.h" #ifdef __cplusplus extern "C" { @@ -47,7 +48,6 @@ struct serial_s { LPC_UART_TypeDef *uart; int index; - uint8_t count; }; struct analogin_s { @@ -71,8 +71,6 @@ LPC_SSP_TypeDef *spi; }; -#include "gpio_object.h" - #ifdef __cplusplus } #endif
--- a/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c Thu Dec 19 09:00:06 2013 +0000 +++ b/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c Thu Dec 19 13:15:07 2013 +0000 @@ -21,6 +21,7 @@ #include "cmsis.h" #include "pinmap.h" #include "error.h" +#include "gpio_api.h" /****************************************************************************** * INITIALIZATION @@ -51,12 +52,35 @@ {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; int stdio_uart_inited = 0; 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) { int is_stdio_uart = 0; @@ -106,7 +130,9 @@ case UART_2: obj->index = 2; 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); @@ -117,7 +143,7 @@ } void serial_free(serial_t *obj) { - serial_irq_ids[obj->index] = 0; + uart_data[obj->index].serial_irq_id = 0; } // serial_baud @@ -251,7 +277,7 @@ /****************************************************************************** * 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 SerialIrq irq_type; switch (iir) { @@ -259,22 +285,28 @@ case 2: irq_type = RxIrq; break; default: return; } - - if (serial_irq_ids[index] != 0) - irq_handler(serial_irq_ids[index], irq_type); + if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) { + gpio_write(&uart_data[index].sw_rts, 1); + // 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 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);} +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, (LPC_UART_TypeDef*)LPC_UART1);} +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, (LPC_UART_TypeDef*)LPC_UART3);} void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { 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; uint32_t vector = 0; switch ((int)obj->uart) { @@ -288,7 +320,7 @@ obj->uart->IER |= 1 << irq; NVIC_SetVector(irq_n, vector); 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; SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq); obj->uart->IER &= ~(1 << irq); @@ -298,18 +330,33 @@ } } +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 ******************************************************************************/ int serial_getc(serial_t *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) { while (!serial_writable(obj)); obj->uart->THR = c; - obj->count++; } int serial_readable(serial_t *obj) { @@ -318,11 +365,10 @@ int serial_writable(serial_t *obj) { int isWritable = 1; - if (obj->uart->LSR & 0x20) - obj->count = 0; - else if (obj->count >= 16) - isWritable = 0; - + if (NC != uart_data[obj->index].sw_cts.pin) + isWritable = gpio_read(&uart_data[obj->index].sw_cts) == 0; + if (isWritable) + isWritable = obj->uart->LSR & 0x40; return isWritable; } @@ -345,3 +391,49 @@ 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); + } + } +} +
--- a/targets/hal/TARGET_NXP/TARGET_LPC81X/device.h Thu Dec 19 09:00:06 2013 +0000 +++ b/targets/hal/TARGET_NXP/TARGET_LPC81X/device.h Thu Dec 19 13:15:07 2013 +0000 @@ -26,6 +26,7 @@ #define DEVICE_ANALOGOUT 0 #define DEVICE_SERIAL 1 +#define DEVICE_SERIAL_FC 1 #define DEVICE_I2C 1 #define DEVICE_I2CSLAVE 0
--- a/targets/hal/TARGET_NXP/TARGET_LPC81X/serial_api.c Thu Dec 19 09:00:06 2013 +0000 +++ b/targets/hal/TARGET_NXP/TARGET_LPC81X/serial_api.c Thu Dec 19 13:15:07 2013 +0000 @@ -39,6 +39,18 @@ {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 static unsigned char uart_used = 0; static int get_available_uart(void) { @@ -60,6 +72,7 @@ #define TXRDY (0x01<<2) #define TXBRKEN (0x01<<1) +#define CTSEN (0x01<<9) static uint32_t UARTSysClk; @@ -278,3 +291,34 @@ 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); + } + } +} +