t

Fork of mbed-dev by mbed official

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