mbed library with additional peripherals for ST F401 board

Fork of mbed-src by mbed official

This mbed LIB has additional peripherals for ST F401 board

  • UART2 : PA_3 rx, PA_2 tx
  • UART3 : PC_7 rx, PC_6 tx
  • I2C2 : PB_3 SDA, PB_10 SCL
  • I2C3 : PB_4 SDA, PA_8 SCL

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);        
+        }
+    }    
+}
+