mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Files at this revision

API Documentation at this revision

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

api/RawSerial.h Show annotated file Show diff for this revision Revisions of this file
api/SerialBase.h Show annotated file Show diff for this revision Revisions of this file
common/RawSerial.cpp Show annotated file Show diff for this revision Revisions of this file
common/SerialBase.cpp Show annotated file Show diff for this revision Revisions of this file
common/pinmap_common.c Show annotated file Show diff for this revision Revisions of this file
hal/pinmap.h Show annotated file Show diff for this revision Revisions of this file
hal/serial_api.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_NXP/TARGET_LPC176X/device.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_NXP/TARGET_LPC176X/objects.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_NXP/TARGET_LPC81X/device.h Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_NXP/TARGET_LPC81X/serial_api.c Show annotated file Show diff for this revision Revisions of this file
--- 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);        
+        }
+    }    
+}
+