mirror of https://github.com/ARMmbed/mbed-os.git
UARTSerial: add flow control and format APIs
Add passthrough APIs to enable the flow control and format methods from SerialBase to be accessed. Modify the RX data pump so it stops reading data and disables the IRQ when the buffer is full, to allow UART automatic flow control to work. In principle it would also be possible as a future enhancement to provide XON/XOFF flow control, or manual RTS/CTS control using GPIO, but this commit at least restores the functionality present in Serial, SerialBase and RawSerial that was missing in UARTSerial.pull/5088/head
parent
7b428916f5
commit
c262a035f6
drivers
|
@ -27,6 +27,7 @@ UARTSerial::UARTSerial(PinName tx, PinName rx, int baud) :
|
|||
SerialBase(tx, rx, baud),
|
||||
_blocking(true),
|
||||
_tx_irq_enabled(false),
|
||||
_rx_irq_enabled(true),
|
||||
_dcd_irq(NULL)
|
||||
{
|
||||
/* Attatch IRQ routines to the serial device. */
|
||||
|
@ -63,6 +64,22 @@ void UARTSerial::set_data_carrier_detect(PinName dcd_pin, bool active_high)
|
|||
}
|
||||
}
|
||||
|
||||
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 ?
|
||||
|
@ -171,6 +188,16 @@ ssize_t UARTSerial::read(void* buffer, size_t length)
|
|||
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;
|
||||
|
@ -238,13 +265,14 @@ void UARTSerial::rx_irq(void)
|
|||
|
||||
/* 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. */
|
||||
|
|
|
@ -158,6 +158,42 @@ public:
|
|||
*/
|
||||
void set_baud(int baud);
|
||||
|
||||
// Expose private SerialBase::Parity as UARTSerial::Parity
|
||||
using SerialBase::Parity;
|
||||
// In C++11, we wouldn't need to also have using directives for each value
|
||||
using SerialBase::None;
|
||||
using SerialBase::Odd;
|
||||
using SerialBase::Even;
|
||||
using SerialBase::Forced1;
|
||||
using SerialBase::Forced0;
|
||||
|
||||
/** Set the transmission format used by the serial port
|
||||
*
|
||||
* @param bits The number of bits in a word (5-8; default = 8)
|
||||
* @param parity The parity used (None, Odd, Even, Forced1, Forced0; default = None)
|
||||
* @param stop_bits The number of stop bits (1 or 2; default = 1)
|
||||
*/
|
||||
void set_format(int bits=8, Parity parity=UARTSerial::None, int stop_bits=1);
|
||||
|
||||
#if DEVICE_SERIAL_FC
|
||||
// For now use the base enum - but in future we may have extra options
|
||||
// such as XON/XOFF or manual GPIO RTSCTS.
|
||||
using SerialBase::Flow;
|
||||
// In C++11, we wouldn't need to also have using directives for each value
|
||||
using SerialBase::Disabled;
|
||||
using SerialBase::RTS;
|
||||
using SerialBase::CTS;
|
||||
using SerialBase::RTSCTS;
|
||||
|
||||
/** 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
|
||||
|
||||
private:
|
||||
|
||||
/** SerialBase lock override */
|
||||
|
@ -184,6 +220,7 @@ private:
|
|||
|
||||
bool _blocking;
|
||||
bool _tx_irq_enabled;
|
||||
bool _rx_irq_enabled;
|
||||
InterruptIn *_dcd_irq;
|
||||
|
||||
/** Device Hanged up
|
||||
|
|
Loading…
Reference in New Issue