t
Fork of mbed-dev by
Diff: drivers/SerialBase.cpp
- Revision:
- 174:b96e65c34a4d
- Parent:
- 160:d5399cc887bb
- Child:
- 175:af195413fb11
--- a/drivers/SerialBase.cpp Fri Sep 15 14:59:18 2017 +0100 +++ b/drivers/SerialBase.cpp Mon Oct 02 15:33:19 2017 +0100 @@ -16,23 +16,23 @@ #include "drivers/SerialBase.h" #include "platform/mbed_wait_api.h" #include "platform/mbed_critical.h" +#include "platform/mbed_sleep.h" #if DEVICE_SERIAL namespace mbed { -static void donothing() {}; - SerialBase::SerialBase(PinName tx, PinName rx, int baud) : #if DEVICE_SERIAL_ASYNCH _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER), - _rx_usage(DMA_USAGE_NEVER), + _rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL), + _rx_callback(NULL), #endif _serial(), _baud(baud) { // No lock needed in the constructor for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { - _irq[i] = donothing; + _irq[i] = NULL; } serial_init(&_serial, tx, rx); @@ -73,10 +73,18 @@ // Disable interrupts when attaching interrupt handler core_util_critical_section_enter(); if (func) { + // lock deep sleep only the first time + if (!_irq[type]) { + sleep_manager_lock_deep_sleep(); + } _irq[type] = func; serial_irq_set(&_serial, (SerialIrq)type, 1); } else { - _irq[type] = donothing; + // unlock deep sleep only the first time + if (_irq[type]) { + sleep_manager_unlock_deep_sleep(); + } + _irq[type] = NULL; serial_irq_set(&_serial, (SerialIrq)type, 0); } core_util_critical_section_exit(); @@ -85,7 +93,9 @@ void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type) { SerialBase *handler = (SerialBase*)id; - handler->_irq[irq_type](); + if (handler->_irq[irq_type]) { + handler->_irq[irq_type](); + } } int SerialBase::_base_getc() { @@ -173,16 +183,27 @@ _tx_callback = callback; _thunk_irq.callback(&SerialBase::interrupt_handler_asynch); + sleep_manager_lock_deep_sleep(); serial_tx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, _tx_usage); } void SerialBase::abort_write(void) { + // rx might still be active + if (_rx_callback) { + sleep_manager_unlock_deep_sleep(); + } + _tx_callback = NULL; serial_tx_abort_asynch(&_serial); } void SerialBase::abort_read(void) { + // tx might still be active + if (_tx_callback) { + sleep_manager_unlock_deep_sleep(); + } + _rx_callback = NULL; serial_rx_abort_asynch(&_serial); } @@ -228,6 +249,7 @@ { _rx_callback = callback; _thunk_irq.callback(&SerialBase::interrupt_handler_asynch); + sleep_manager_lock_deep_sleep(); serial_rx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, char_match, _rx_usage); } @@ -235,14 +257,22 @@ { int event = serial_irq_handler_asynch(&_serial); int rx_event = event & SERIAL_EVENT_RX_MASK; + bool unlock_deepsleep = false; + if (_rx_callback && rx_event) { + unlock_deepsleep = true; _rx_callback.call(rx_event); } int tx_event = event & SERIAL_EVENT_TX_MASK; if (_tx_callback && tx_event) { + unlock_deepsleep = true; _tx_callback.call(tx_event); } + // unlock if tx or rx events are generated + if (unlock_deepsleep) { + sleep_manager_unlock_deep_sleep(); + } } #endif