Skip to content

Commit 27c5dfc

Browse files
Steven Cartmelladbridge
authored andcommitted
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.
1 parent 4f331b6 commit 27c5dfc

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

drivers/SPI.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
3333
#if DEVICE_SPI_ASYNCH
3434
_irq(this),
3535
_usage(DMA_USAGE_NEVER),
36+
_deep_sleep_locked(false),
3637
#endif
3738
_bits(8),
3839
_mode(0),
@@ -140,7 +141,7 @@ int SPI::transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_
140141
void SPI::abort_transfer()
141142
{
142143
spi_abort_asynch(&_spi);
143-
sleep_manager_unlock_deep_sleep();
144+
unlock_deep_sleep();
144145
#if TRANSACTION_QUEUE_SIZE_SPI
145146
dequeue_transaction();
146147
#endif
@@ -200,13 +201,29 @@ int SPI::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, i
200201

201202
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)
202203
{
203-
sleep_manager_lock_deep_sleep();
204+
lock_deep_sleep();
204205
_acquire();
205206
_callback = callback;
206207
_irq.callback(&SPI::irq_handler_asynch);
207208
spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage);
208209
}
209210

211+
void SPI::lock_deep_sleep()
212+
{
213+
if (_deep_sleep_locked == false) {
214+
sleep_manager_lock_deep_sleep();
215+
_deep_sleep_locked = true;
216+
}
217+
}
218+
219+
void SPI::unlock_deep_sleep()
220+
{
221+
if (_deep_sleep_locked == true) {
222+
sleep_manager_unlock_deep_sleep();
223+
_deep_sleep_locked = false;
224+
}
225+
}
226+
210227
#if TRANSACTION_QUEUE_SIZE_SPI
211228

212229
void SPI::start_transaction(transaction_t *data)
@@ -230,7 +247,7 @@ void SPI::irq_handler_asynch(void)
230247
{
231248
int event = spi_irq_handler_asynch(&_spi);
232249
if (_callback && (event & SPI_EVENT_ALL)) {
233-
sleep_manager_unlock_deep_sleep();
250+
unlock_deep_sleep();
234251
_callback.call(event & SPI_EVENT_ALL);
235252
}
236253
#if TRANSACTION_QUEUE_SIZE_SPI

drivers/SPI.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ class SPI : private NonCopyable<SPI> {
246246
*/
247247
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);
248248

249+
private:
250+
/** Lock deep sleep only if it is not yet locked */
251+
void lock_deep_sleep();
252+
253+
/** Unlock deep sleep in case it is locked */
254+
void unlock_deep_sleep();
255+
256+
249257
#if TRANSACTION_QUEUE_SIZE_SPI
250258

251259
/** Start a new transaction
@@ -274,6 +282,7 @@ class SPI : private NonCopyable<SPI> {
274282
CThunk<SPI> _irq;
275283
event_callback_t _callback;
276284
DMAUsage _usage;
285+
bool _deep_sleep_locked;
277286
#endif
278287

279288
void aquire(void);

0 commit comments

Comments
 (0)