mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
180:96ed750bd169
Parent:
176:447f873cad2f
Child:
186:707f6e361f3e
--- a/drivers/UARTSerial.cpp	Thu Dec 07 14:01:42 2017 +0000
+++ b/drivers/UARTSerial.cpp	Wed Jan 17 15:23:54 2018 +0000
@@ -32,6 +32,7 @@
         SerialBase(tx, rx, baud),
         _blocking(true),
         _tx_irq_enabled(false),
+        _rx_irq_enabled(true),
         _dcd_irq(NULL)
 {
     /* Attatch IRQ routines to the serial device. */
@@ -68,6 +69,22 @@
     }
 }
 
+void UARTSerial::set_format(int bits, Parity parity, int stop_bits)
+{
+    api_lock();
+    SerialBase::format(bits, parity, stop_bits);
+    api_unlock();
+}
+
+#if DEVICE_SERIAL_FC
+void UARTSerial::set_flow_control(Flow type, PinName flow1, PinName flow2)
+{
+    api_lock();
+    SerialBase::set_flow_control(type, flow1, flow2);
+    api_unlock();
+}
+#endif
+
 int UARTSerial::close()
 {
     /* Does not let us pass a file descriptor. So how to close ?
@@ -121,36 +138,47 @@
     size_t data_written = 0;
     const char *buf_ptr = static_cast<const char *>(buffer);
 
-    api_lock();
-
-    while (_txbuf.full()) {
-        if (!_blocking) {
-            api_unlock();
-            return -EAGAIN;
-        }
-        api_unlock();
-        wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
-        api_lock();
+    if (length == 0) {
+        return 0;
     }
 
-    while (data_written < length && !_txbuf.full()) {
-        _txbuf.push(*buf_ptr++);
-        data_written++;
-    }
+    api_lock();
+
+    // Unlike read, we should write the whole thing if blocking. POSIX only
+    // allows partial as a side-effect of signal handling; it normally tries to
+    // write everything if blocking. Without signals we can always write all.
+    while (data_written < length) {
 
-    core_util_critical_section_enter();
-    if (!_tx_irq_enabled) {
-        UARTSerial::tx_irq();                // only write to hardware in one place
-        if (!_txbuf.empty()) {
-            SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
-            _tx_irq_enabled = true;
+        if (_txbuf.full()) {
+            if (!_blocking) {
+                break;
+            }
+            do {
+                api_unlock();
+                wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
+                api_lock();
+            } while (_txbuf.full());
         }
+
+        while (data_written < length && !_txbuf.full()) {
+            _txbuf.push(*buf_ptr++);
+            data_written++;
+        }
+
+        core_util_critical_section_enter();
+        if (!_tx_irq_enabled) {
+            UARTSerial::tx_irq();                // only write to hardware in one place
+            if (!_txbuf.empty()) {
+                SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
+                _tx_irq_enabled = true;
+            }
+        }
+        core_util_critical_section_exit();
     }
-    core_util_critical_section_exit();
 
     api_unlock();
 
-    return data_written;
+    return data_written != 0 ? (ssize_t) data_written : (ssize_t) -EAGAIN;
 }
 
 ssize_t UARTSerial::read(void* buffer, size_t length)
@@ -159,6 +187,10 @@
 
     char *ptr = static_cast<char *>(buffer);
 
+    if (length == 0) {
+        return 0;
+    }
+
     api_lock();
 
     while (_rxbuf.empty()) {
@@ -176,6 +208,16 @@
         data_read++;
     }
 
+    core_util_critical_section_enter();
+    if (!_rx_irq_enabled) {
+        UARTSerial::rx_irq();               // only read from hardware in one place
+        if (!_rxbuf.full()) {
+            SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
+            _rx_irq_enabled = true;
+        }
+    }
+    core_util_critical_section_exit();
+
     api_unlock();
 
     return data_read;
@@ -243,13 +285,14 @@
 
     /* Fill in the receive buffer if the peripheral is readable
      * and receive buffer is not full. */
-    while (SerialBase::readable()) {
+    while (!_rxbuf.full() && SerialBase::readable()) {
         char data = SerialBase::_base_getc();
-        if (!_rxbuf.full()) {
-            _rxbuf.push(data);
-        } else {
-            /* Drop - can we report in some way? */
-        }
+        _rxbuf.push(data);
+    }
+
+    if (_rx_irq_enabled && _rxbuf.full()) {
+        SerialBase::attach(NULL, RxIrq);
+        _rx_irq_enabled = false;
     }
 
     /* Report the File handler that data is ready to be read from the buffer. */