diff --git a/drivers/SerialBase.cpp b/drivers/SerialBase.cpp index 856944fd347..e62c53788d4 100644 --- a/drivers/SerialBase.cpp +++ b/drivers/SerialBase.cpp @@ -30,17 +30,9 @@ SerialBase::SerialBase(PinName tx, PinName rx, int baud) : _rx_callback(NULL), _tx_asynch_set(false), _rx_asynch_set(false), #endif - _serial(), _baud(baud) + _serial(), _baud(baud), _tx(tx), _rx(rx) { - // No lock needed in the constructor - - for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { - _irq[i] = NULL; - } - - serial_init(&_serial, tx, rx); - serial_baud(&_serial, _baud); - serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); + _init(); } void SerialBase::baud(int baudrate) @@ -161,6 +153,22 @@ void SerialBase:: unlock() // Stub } +void SerialBase::_init(void) +{ + for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { + _irq[i] = NULL; + } + + serial_init(&_serial, _tx, _rx); + serial_baud(&_serial, _baud); + serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); +} + +void SerialBase::_deinit(void) +{ + serial_free(&_serial); +} + SerialBase::~SerialBase() { // No lock needed in destructor @@ -169,6 +177,8 @@ SerialBase::~SerialBase() for (int irq = 0; irq < IrqCnt; irq++) { attach(NULL, (IrqType)irq); } + + _deinit(); } #if DEVICE_SERIAL_FC diff --git a/drivers/SerialBase.h b/drivers/SerialBase.h index 99da7a9b45d..99b9e59f416 100644 --- a/drivers/SerialBase.h +++ b/drivers/SerialBase.h @@ -162,6 +162,14 @@ class SerialBase : private NonCopyable { /** Release exclusive access to this serial port */ virtual void unlock(void); + + /** Initialize serial port + */ + void _init(void); + + /** Deinitialize serial port + */ + void _deinit(void); #endif public: @@ -304,6 +312,8 @@ class SerialBase : private NonCopyable { serial_t _serial; Callback _irq[IrqCnt]; int _baud; + PinName _rx; + PinName _tx; #endif }; diff --git a/drivers/UARTSerial.cpp b/drivers/UARTSerial.cpp index e9213555d76..9d534f9cd06 100644 --- a/drivers/UARTSerial.cpp +++ b/drivers/UARTSerial.cpp @@ -371,8 +371,13 @@ void UARTSerial::disable_tx_irq() int UARTSerial::enable_input(bool enabled) { - core_util_critical_section_enter(); + api_lock(); if (_rx_enabled != enabled) { + if (enabled && !_tx_enabled) { + _init(); + } + + core_util_critical_section_enter(); if (enabled) { UARTSerial::rx_irq(); if (!_rxbuf.full()) { @@ -381,17 +386,27 @@ int UARTSerial::enable_input(bool enabled) } else { disable_rx_irq(); } + core_util_critical_section_exit(); + _rx_enabled = enabled; - } - core_util_critical_section_exit(); + if (!enabled && !_tx_enabled) { + _deinit(); + } + } + api_unlock(); return 0; } int UARTSerial::enable_output(bool enabled) { - core_util_critical_section_enter(); + api_lock(); if (_tx_enabled != enabled) { + if (enabled && !_rx_enabled) { + _init(); + } + + core_util_critical_section_enter(); if (enabled) { UARTSerial::tx_irq(); if (!_txbuf.empty()) { @@ -400,10 +415,15 @@ int UARTSerial::enable_output(bool enabled) } else { disable_tx_irq(); } + core_util_critical_section_exit(); + _tx_enabled = enabled; - } - core_util_critical_section_exit(); + if (!enabled && !_rx_enabled) { + _deinit(); + } + } + api_unlock(); return 0; }