Free serial resources if not needed anymore

pull/10924/head
Sebastian Stockhammer 2019-07-01 10:43:30 +02:00
parent acf576a9ab
commit e218b5dc19
3 changed files with 104 additions and 30 deletions

View File

@ -295,6 +295,30 @@ protected:
int _base_putc(int c);
/** Initialize serial port
*/
void _init();
/** Deinitialize serial port
*/
void _deinit();
/** Enable serial input
*
* If both serial input and serial output are disabled, the
* peripheral is freed. If either serial input or serial
* output is re-enabled, the peripheral is reinitialized.
*/
void _enable_input(bool enable = true);
/** Enable serial output
*
* If both serial input and serial output are disabled, the
* peripheral is freed. If either serial input or serial
* output is re-enabled, the peripheral is reinitialized.
*/
void _enable_output(bool enable = true);
#if DEVICE_SERIAL_ASYNCH
CThunk<SerialBase> _thunk_irq;
DMAUsage _tx_usage;
@ -308,6 +332,10 @@ protected:
serial_t _serial;
Callback<void()> _irq[IrqCnt];
int _baud;
bool _rx_enabled;
bool _tx_enabled;
const PinName _tx_pin;
const PinName _rx_pin;
#endif
};

View File

@ -30,7 +30,7 @@ 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), _rx_enabled(true), _tx_enabled(true), _tx_pin(tx), _rx_pin(rx)
{
// No lock needed in the constructor
@ -38,9 +38,7 @@ SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
_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)
@ -120,6 +118,74 @@ int SerialBase::_base_putc(int c)
return c;
}
void SerialBase::_init()
{
serial_init(&_serial, _tx_pin, _rx_pin);
serial_baud(&_serial, _baud);
serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this);
}
void SerialBase::_deinit()
{
serial_free(&_serial);
}
void SerialBase::_enable_input(bool enable)
{
if (_rx_enabled != enable) {
if(enable && !_tx_enabled) {
_init();
}
core_util_critical_section_enter();
if (enable) {
// Enable rx IRQ if attached (indicated by rx IRQ callback not NULL)
if(_irq[RxIrq]) {
_irq[RxIrq].call();
serial_irq_set(&_serial, (SerialIrq)RxIrq, 1);
}
} else {
// Disable rx IRQ
serial_irq_set(&_serial, (SerialIrq)RxIrq, 0);
}
core_util_critical_section_exit();
_rx_enabled = enable;
if (!enable && !_tx_enabled) {
_deinit();
}
}
}
void SerialBase::_enable_output(bool enable)
{
if (_tx_enabled != enable) {
if(enable && !_rx_enabled) {
_init();
}
core_util_critical_section_enter();
if (enable) {
// Enable tx IRQ if attached (indicated by tx IRQ callback not NULL)
if(_irq[TxIrq]) {
_irq[TxIrq].call();
serial_irq_set(&_serial, (SerialIrq)TxIrq, 1);
}
} else {
// Disable tx IRQ
serial_irq_set(&_serial, (SerialIrq)TxIrq, 0);
}
core_util_critical_section_exit();
_tx_enabled = enable;
if (!enable && !_rx_enabled) {
_deinit();
}
}
}
void SerialBase::set_break()
{
lock();

View File

@ -366,38 +366,18 @@ void UARTSerial::disable_tx_irq()
int UARTSerial::enable_input(bool enabled)
{
core_util_critical_section_enter();
if (_rx_enabled != enabled) {
if (enabled) {
UARTSerial::rx_irq();
if (!_rxbuf.full()) {
enable_rx_irq();
}
} else {
disable_rx_irq();
}
_rx_enabled = enabled;
}
core_util_critical_section_exit();
api_lock();
_enable_input(enabled);
api_unlock();
return 0;
}
int UARTSerial::enable_output(bool enabled)
{
core_util_critical_section_enter();
if (_tx_enabled != enabled) {
if (enabled) {
UARTSerial::tx_irq();
if (!_txbuf.empty()) {
enable_tx_irq();
}
} else {
disable_tx_irq();
}
_tx_enabled = enabled;
}
core_util_critical_section_exit();
api_lock();
_enable_input(enabled);
api_unlock();
return 0;
}