From c2670870dc721979e4e2ea6d822773dcaa27bc93 Mon Sep 17 00:00:00 2001 From: Steven Cartmell Date: Mon, 18 Dec 2017 11:36:30 +0000 Subject: [PATCH] Fix bug allowing SPI::abort_transfer to incorrectly unlock deep sleep mode - Add flag to SPI class to track if the SPI instance has locked deep sleep mode. - Wrap call to sleep_manager_lock_deep_sleep to only be called if SPI instance hasn't already locked deep sleep. - Wrap call to sleep_manager_unlock_deep_sleep to only be called if SPI has currently locked deep sleep mode. --- drivers/SPI.cpp | 23 ++++++++++++++++++++--- drivers/SPI.h | 9 +++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/SPI.cpp b/drivers/SPI.cpp index 9b2209b0fe..e21922b258 100644 --- a/drivers/SPI.cpp +++ b/drivers/SPI.cpp @@ -33,6 +33,7 @@ SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) : #if DEVICE_SPI_ASYNCH _irq(this), _usage(DMA_USAGE_NEVER), + _deep_sleep_locked(false), #endif _bits(8), _mode(0), @@ -140,7 +141,7 @@ int SPI::transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_ void SPI::abort_transfer() { spi_abort_asynch(&_spi); - sleep_manager_unlock_deep_sleep(); + unlock_deep_sleep(); #if TRANSACTION_QUEUE_SIZE_SPI dequeue_transaction(); #endif @@ -200,13 +201,29 @@ int SPI::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, i void SPI::start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event) { - sleep_manager_lock_deep_sleep(); + lock_deep_sleep(); _acquire(); _callback = callback; _irq.callback(&SPI::irq_handler_asynch); spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage); } +void SPI::lock_deep_sleep() +{ + if (_deep_sleep_locked == false) { + sleep_manager_lock_deep_sleep(); + _deep_sleep_locked = true; + } +} + +void SPI::unlock_deep_sleep() +{ + if (_deep_sleep_locked == true) { + sleep_manager_unlock_deep_sleep(); + _deep_sleep_locked = false; + } +} + #if TRANSACTION_QUEUE_SIZE_SPI void SPI::start_transaction(transaction_t *data) @@ -230,7 +247,7 @@ void SPI::irq_handler_asynch(void) { int event = spi_irq_handler_asynch(&_spi); if (_callback && (event & SPI_EVENT_ALL)) { - sleep_manager_unlock_deep_sleep(); + unlock_deep_sleep(); _callback.call(event & SPI_EVENT_ALL); } #if TRANSACTION_QUEUE_SIZE_SPI diff --git a/drivers/SPI.h b/drivers/SPI.h index e312dcc7b3..af102dc07c 100644 --- a/drivers/SPI.h +++ b/drivers/SPI.h @@ -246,6 +246,14 @@ protected: */ void start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event); +private: + /** Lock deep sleep only if it is not yet locked */ + void lock_deep_sleep(); + + /** Unlock deep sleep in case it is locked */ + void unlock_deep_sleep(); + + #if TRANSACTION_QUEUE_SIZE_SPI /** Start a new transaction @@ -274,6 +282,7 @@ protected: CThunk _irq; event_callback_t _callback; DMAUsage _usage; + bool _deep_sleep_locked; #endif void aquire(void);