Skip to content

Commit 7b0e937

Browse files
committed
Drivers with interrupts: adding sleep deep locking
Any driver with attach or async API should be considered for deep sleep. Add locking to those that require in most cases high-frequency clocks: - CAN - I2C - SPI - Serial - Ticker/Timeout/Timer
1 parent 568c620 commit 7b0e937

File tree

13 files changed

+63
-4
lines changed

13 files changed

+63
-4
lines changed

drivers/CAN.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ int CAN::filter(unsigned int id, unsigned int mask, CANFormat format, int handle
115115
void CAN::attach(Callback<void()> func, IrqType type) {
116116
lock();
117117
if (func) {
118+
sleep_manager_lock_deep_sleep();
118119
_irq[(CanIrqType)type] = func;
119120
can_irq_set(&_can, (CanIrqType)type, 1);
120121
} else {
122+
sleep_manager_unlock_deep_sleep();
121123
_irq[(CanIrqType)type] = callback(donothing);
122124
can_irq_set(&_can, (CanIrqType)type, 0);
123125
}

drivers/CAN.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "platform/Callback.h"
2525
#include "platform/PlatformMutex.h"
2626
#include "platform/NonCopyable.h"
27+
#include "platform/mbed_sleep.h"
2728

2829
namespace mbed {
2930
/** \addtogroup drivers */
@@ -235,7 +236,9 @@ class CAN : private NonCopyable<CAN> {
235236

236237
/** Attach a function to call whenever a CAN frame received interrupt is
237238
* generated.
238-
*
239+
*
240+
* This function locks the deep sleep while a callback is attached
241+
*
239242
* @param func A pointer to a void function, or 0 to set as none
240243
* @param type Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, CAN::TxIrq for transmitted or aborted, CAN::EwIrq for error warning, CAN::DoIrq for data overrun, CAN::WuIrq for wake-up, CAN::EpIrq for error passive, CAN::AlIrq for arbitration lost, CAN::BeIrq for bus error)
241244
*/

drivers/I2C.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ void I2C::unlock() {
125125
int I2C::transfer(int address, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, const event_callback_t& callback, int event, bool repeated)
126126
{
127127
lock();
128+
sleep_manager_lock_deep_sleep();
128129
if (i2c_active(&_i2c)) {
129130
unlock();
130131
return -1; // transaction ongoing
@@ -143,6 +144,7 @@ void I2C::abort_transfer(void)
143144
{
144145
lock();
145146
i2c_abort_asynch(&_i2c);
147+
sleep_manager_unlock_deep_sleep();
146148
unlock();
147149
}
148150

@@ -152,6 +154,9 @@ void I2C::irq_handler_asynch(void)
152154
if (_callback && event) {
153155
_callback.call(event);
154156
}
157+
if (event) {
158+
sleep_manager_unlock_deep_sleep();
159+
}
155160

156161
}
157162

drivers/I2C.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "platform/CThunk.h"
3030
#include "hal/dma_api.h"
3131
#include "platform/FunctionPointer.h"
32+
#include "platform/mbed_sleep.h"
3233
#endif
3334

3435
namespace mbed {
@@ -159,6 +160,8 @@ class I2C : private NonCopyable<I2C> {
159160

160161
/** Start non-blocking I2C transfer.
161162
*
163+
* This function locks the deep sleep until any event has occured
164+
*
162165
* @param address 8/10 bit I2c slave address
163166
* @param tx_buffer The TX buffer with data to be transfered
164167
* @param tx_length The length of TX buffer in bytes

drivers/SPI.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ int SPI::transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_
136136
void SPI::abort_transfer()
137137
{
138138
spi_abort_asynch(&_spi);
139+
sleep_manager_unlock_deep_sleep();
139140
#if TRANSACTION_QUEUE_SIZE_SPI
140141
dequeue_transaction();
141142
#endif
@@ -195,6 +196,7 @@ int SPI::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, i
195196

196197
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)
197198
{
199+
sleep_manager_lock_deep_sleep();
198200
_acquire();
199201
_callback = callback;
200202
_irq.callback(&SPI::irq_handler_asynch);
@@ -224,6 +226,7 @@ void SPI::irq_handler_asynch(void)
224226
{
225227
int event = spi_irq_handler_asynch(&_spi);
226228
if (_callback && (event & SPI_EVENT_ALL)) {
229+
sleep_manager_unlock_deep_sleep();
227230
_callback.call(event & SPI_EVENT_ALL);
228231
}
229232
#if TRANSACTION_QUEUE_SIZE_SPI

drivers/SPI.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "platform/CircularBuffer.h"
3232
#include "platform/FunctionPointer.h"
3333
#include "platform/Transaction.h"
34+
#include "platform/mbed_sleep.h"
3435
#endif
3536

3637
namespace mbed {
@@ -156,6 +157,8 @@ class SPI : private NonCopyable<SPI> {
156157

157158
/** Start non-blocking SPI transfer using 8bit buffers.
158159
*
160+
* This function locks the deep sleep until any event has occured
161+
*
159162
* @param tx_buffer The TX buffer with data to be transfered. If NULL is passed,
160163
* the default SPI value is sent
161164
* @param tx_length The length of TX buffer in bytes

drivers/SerialBase.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222
namespace mbed {
2323

2424
static void donothing() {};
25+
static void donothing2(int arg) {};
26+
2527

2628
SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
2729
#if DEVICE_SERIAL_ASYNCH
2830
_thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
29-
_rx_usage(DMA_USAGE_NEVER),
31+
_rx_usage(DMA_USAGE_NEVER), _tx_callback(donothing2),
32+
_rx_callback(donothing2),
3033
#endif
3134
_serial(), _baud(baud) {
3235
// No lock needed in the constructor
@@ -73,9 +76,11 @@ void SerialBase::attach(Callback<void()> func, IrqType type) {
7376
// Disable interrupts when attaching interrupt handler
7477
core_util_critical_section_enter();
7578
if (func) {
79+
sleep_manager_lock_deep_sleep();
7680
_irq[type] = func;
7781
serial_irq_set(&_serial, (SerialIrq)type, 1);
7882
} else {
83+
sleep_manager_unlock_deep_sleep();
7984
_irq[type] = donothing;
8085
serial_irq_set(&_serial, (SerialIrq)type, 0);
8186
}
@@ -173,16 +178,27 @@ void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_wi
173178
_tx_callback = callback;
174179

175180
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
181+
sleep_manager_lock_deep_sleep();
176182
serial_tx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, _tx_usage);
177183
}
178184

179185
void SerialBase::abort_write(void)
180186
{
187+
// rx might still be active
188+
if (_rx_callback == &donothing2) {
189+
sleep_manager_unlock_deep_sleep();
190+
}
191+
_tx_callback = donothing2;
181192
serial_tx_abort_asynch(&_serial);
182193
}
183194

184195
void SerialBase::abort_read(void)
185196
{
197+
// tx might still be active
198+
if (_tx_callback == &donothing2) {
199+
sleep_manager_unlock_deep_sleep();
200+
}
201+
_rx_callback = donothing2;
186202
serial_rx_abort_asynch(&_serial);
187203
}
188204

@@ -235,14 +251,22 @@ void SerialBase::interrupt_handler_asynch(void)
235251
{
236252
int event = serial_irq_handler_asynch(&_serial);
237253
int rx_event = event & SERIAL_EVENT_RX_MASK;
254+
bool unlock_deepsleep = false;
255+
238256
if (_rx_callback && rx_event) {
257+
unlock_deepsleep = true;
239258
_rx_callback.call(rx_event);
240259
}
241260

242261
int tx_event = event & SERIAL_EVENT_TX_MASK;
243262
if (_tx_callback && tx_event) {
263+
unlock_deepsleep = true;
244264
_tx_callback.call(tx_event);
245265
}
266+
// unlock if tx or rx events are generated
267+
if (unlock_deepsleep) {
268+
sleep_manager_unlock_deep_sleep();
269+
}
246270
}
247271

248272
#endif

drivers/SerialBase.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "serial_api.h"
2525
#include "mbed_toolchain.h"
2626
#include "platform/NonCopyable.h"
27+
#include "platform/mbed_sleep.h"
2728

2829
#if DEVICE_SERIAL_ASYNCH
2930
#include "CThunk.h"
@@ -167,6 +168,8 @@ class SerialBase : private NonCopyable<SerialBase> {
167168

168169
/** Begin asynchronous write using 8bit buffer. The completition invokes registered TX event callback
169170
*
171+
* This function locks the deep sleep until any event has occured
172+
*
170173
* @param buffer The buffer where received data will be stored
171174
* @param length The buffer length in bytes
172175
* @param callback The event callback function
@@ -176,6 +179,8 @@ class SerialBase : private NonCopyable<SerialBase> {
176179

177180
/** Begin asynchronous write using 16bit buffer. The completition invokes registered TX event callback
178181
*
182+
* This function locks the deep sleep until any event has occured
183+
*
179184
* @param buffer The buffer where received data will be stored
180185
* @param length The buffer length in bytes
181186
* @param callback The event callback function
@@ -189,6 +194,8 @@ class SerialBase : private NonCopyable<SerialBase> {
189194

190195
/** Begin asynchronous reading using 8bit buffer. The completition invokes registred RX event callback.
191196
*
197+
* This function locks the deep sleep until any event has occured
198+
*
192199
* @param buffer The buffer where received data will be stored
193200
* @param length The buffer length in bytes
194201
* @param callback The event callback function
@@ -199,6 +206,8 @@ class SerialBase : private NonCopyable<SerialBase> {
199206

200207
/** Begin asynchronous reading using 16bit buffer. The completition invokes registred RX event callback.
201208
*
209+
* This function locks the deep sleep until any event has occured
210+
*
202211
* @param buffer The buffer where received data will be stored
203212
* @param length The buffer length in bytes
204213
* @param callback The event callback function
@@ -241,10 +250,10 @@ class SerialBase : private NonCopyable<SerialBase> {
241250

242251
#if DEVICE_SERIAL_ASYNCH
243252
CThunk<SerialBase> _thunk_irq;
244-
event_callback_t _tx_callback;
245-
event_callback_t _rx_callback;
246253
DMAUsage _tx_usage;
247254
DMAUsage _rx_usage;
255+
event_callback_t _tx_callback;
256+
event_callback_t _rx_callback;
248257
#endif
249258

250259
serial_t _serial;

drivers/Ticker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ void Ticker::detach() {
2626
core_util_critical_section_enter();
2727
remove();
2828
_function = 0;
29+
sleep_manager_unlock_deep_sleep();
2930
core_util_critical_section_exit();
3031
}
3132

drivers/Ticker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "platform/Callback.h"
2121
#include "platform/mbed_toolchain.h"
2222
#include "platform/NonCopyable.h"
23+
#include "platform/mbed_sleep.h"
2324

2425
namespace mbed {
2526
/** \addtogroup drivers */
@@ -103,6 +104,7 @@ class Ticker : public TimerEvent, private NonCopyable<Ticker> {
103104
*/
104105
void attach_us(Callback<void()> func, us_timestamp_t t) {
105106
_function = func;
107+
sleep_manager_lock_deep_sleep();
106108
setup(t);
107109
}
108110

0 commit comments

Comments
 (0)