Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
Diff: drivers/UARTSerial.cpp
- Revision:
- 181:96ed750bd169
- Parent:
- 177:447f873cad2f
diff -r b0033dcd6934 -r 96ed750bd169 drivers/UARTSerial.cpp
--- 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. */
