Skip to content

Commit e6d8a9a

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 fcdb043 commit e6d8a9a

File tree

13 files changed

+69
-4
lines changed

13 files changed

+69
-4
lines changed

drivers/CAN.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#if DEVICE_CAN
1919

2020
#include "cmsis.h"
21+
#include "platform/mbed_sleep.h"
2122

2223
namespace mbed {
2324

@@ -115,9 +116,11 @@ int CAN::filter(unsigned int id, unsigned int mask, CANFormat format, int handle
115116
void CAN::attach(Callback<void()> func, IrqType type) {
116117
lock();
117118
if (func) {
119+
sleep_manager_lock_deep_sleep();
118120
_irq[(CanIrqType)type] = func;
119121
can_irq_set(&_can, (CanIrqType)type, 1);
120122
} else {
123+
sleep_manager_unlock_deep_sleep();
121124
_irq[(CanIrqType)type] = callback(donothing);
122125
can_irq_set(&_can, (CanIrqType)type, 0);
123126
}

drivers/CAN.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,9 @@ class CAN : private NonCopyable<CAN> {
235235

236236
/** Attach a function to call whenever a CAN frame received interrupt is
237237
* generated.
238-
*
238+
*
239+
* This function locks the deep sleep while a callback is attached
240+
*
239241
* @param func A pointer to a void function, or 0 to set as none
240242
* @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)
241243
*/

drivers/I2C.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
#if DEVICE_I2C
1919

20+
#if DEVICE_I2C_ASYNCH
21+
#include "platform/mbed_sleep.h"
22+
#endif
23+
2024
namespace mbed {
2125

2226
I2C *I2C::_owner = NULL;
@@ -125,6 +129,7 @@ void I2C::unlock() {
125129
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)
126130
{
127131
lock();
132+
sleep_manager_lock_deep_sleep();
128133
if (i2c_active(&_i2c)) {
129134
unlock();
130135
return -1; // transaction ongoing
@@ -143,6 +148,7 @@ void I2C::abort_transfer(void)
143148
{
144149
lock();
145150
i2c_abort_asynch(&_i2c);
151+
sleep_manager_unlock_deep_sleep();
146152
unlock();
147153
}
148154

@@ -152,6 +158,9 @@ void I2C::irq_handler_asynch(void)
152158
if (_callback && event) {
153159
_callback.call(event);
154160
}
161+
if (event) {
162+
sleep_manager_unlock_deep_sleep();
163+
}
155164

156165
}
157166

drivers/I2C.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class I2C : private NonCopyable<I2C> {
159159

160160
/** Start non-blocking I2C transfer.
161161
*
162+
* This function locks the deep sleep until any event has occured
163+
*
162164
* @param address 8/10 bit I2c slave address
163165
* @param tx_buffer The TX buffer with data to be transfered
164166
* @param tx_length The length of TX buffer in bytes

drivers/SPI.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
#include "drivers/SPI.h"
1717
#include "platform/mbed_critical.h"
1818

19+
#if DEVICE_SPI_ASYNCH
20+
#include "platform/mbed_sleep.h"
21+
#endif
22+
1923
#if DEVICE_SPI
2024

2125
namespace mbed {
@@ -136,6 +140,7 @@ int SPI::transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_
136140
void SPI::abort_transfer()
137141
{
138142
spi_abort_asynch(&_spi);
143+
sleep_manager_unlock_deep_sleep();
139144
#if TRANSACTION_QUEUE_SIZE_SPI
140145
dequeue_transaction();
141146
#endif
@@ -195,6 +200,7 @@ int SPI::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, i
195200

196201
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)
197202
{
203+
sleep_manager_lock_deep_sleep();
198204
_acquire();
199205
_callback = callback;
200206
_irq.callback(&SPI::irq_handler_asynch);
@@ -224,6 +230,7 @@ void SPI::irq_handler_asynch(void)
224230
{
225231
int event = spi_irq_handler_asynch(&_spi);
226232
if (_callback && (event & SPI_EVENT_ALL)) {
233+
sleep_manager_unlock_deep_sleep();
227234
_callback.call(event & SPI_EVENT_ALL);
228235
}
229236
#if TRANSACTION_QUEUE_SIZE_SPI

drivers/SPI.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ class SPI : private NonCopyable<SPI> {
156156

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

drivers/SerialBase.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,21 @@
1616
#include "drivers/SerialBase.h"
1717
#include "platform/mbed_wait_api.h"
1818
#include "platform/mbed_critical.h"
19+
#include "platform/mbed_sleep.h"
1920

2021
#if DEVICE_SERIAL
2122

2223
namespace mbed {
2324

2425
static void donothing() {};
26+
static void donothing2(int arg) {};
27+
2528

2629
SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
2730
#if DEVICE_SERIAL_ASYNCH
2831
_thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
29-
_rx_usage(DMA_USAGE_NEVER),
32+
_rx_usage(DMA_USAGE_NEVER), _tx_callback(donothing2),
33+
_rx_callback(donothing2),
3034
#endif
3135
_serial(), _baud(baud) {
3236
// No lock needed in the constructor
@@ -73,9 +77,11 @@ void SerialBase::attach(Callback<void()> func, IrqType type) {
7377
// Disable interrupts when attaching interrupt handler
7478
core_util_critical_section_enter();
7579
if (func) {
80+
sleep_manager_lock_deep_sleep();
7681
_irq[type] = func;
7782
serial_irq_set(&_serial, (SerialIrq)type, 1);
7883
} else {
84+
sleep_manager_unlock_deep_sleep();
7985
_irq[type] = donothing;
8086
serial_irq_set(&_serial, (SerialIrq)type, 0);
8187
}
@@ -173,16 +179,27 @@ void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_wi
173179
_tx_callback = callback;
174180

175181
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
182+
sleep_manager_lock_deep_sleep();
176183
serial_tx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, _tx_usage);
177184
}
178185

179186
void SerialBase::abort_write(void)
180187
{
188+
// rx might still be active
189+
if (_rx_callback == &donothing2) {
190+
sleep_manager_unlock_deep_sleep();
191+
}
192+
_tx_callback = donothing2;
181193
serial_tx_abort_asynch(&_serial);
182194
}
183195

184196
void SerialBase::abort_read(void)
185197
{
198+
// tx might still be active
199+
if (_tx_callback == &donothing2) {
200+
sleep_manager_unlock_deep_sleep();
201+
}
202+
_rx_callback = donothing2;
186203
serial_rx_abort_asynch(&_serial);
187204
}
188205

@@ -235,14 +252,22 @@ void SerialBase::interrupt_handler_asynch(void)
235252
{
236253
int event = serial_irq_handler_asynch(&_serial);
237254
int rx_event = event & SERIAL_EVENT_RX_MASK;
255+
bool unlock_deepsleep = false;
256+
238257
if (_rx_callback && rx_event) {
258+
unlock_deepsleep = true;
239259
_rx_callback.call(rx_event);
240260
}
241261

242262
int tx_event = event & SERIAL_EVENT_TX_MASK;
243263
if (_tx_callback && tx_event) {
264+
unlock_deepsleep = true;
244265
_tx_callback.call(tx_event);
245266
}
267+
// unlock if tx or rx events are generated
268+
if (unlock_deepsleep) {
269+
sleep_manager_unlock_deep_sleep();
270+
}
246271
}
247272

248273
#endif

drivers/SerialBase.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ class SerialBase : private NonCopyable<SerialBase> {
167167

168168
/** Begin asynchronous write using 8bit buffer. The completition invokes registered TX event callback
169169
*
170+
* This function locks the deep sleep until any event has occured
171+
*
170172
* @param buffer The buffer where received data will be stored
171173
* @param length The buffer length in bytes
172174
* @param callback The event callback function
@@ -176,6 +178,8 @@ class SerialBase : private NonCopyable<SerialBase> {
176178

177179
/** Begin asynchronous write using 16bit buffer. The completition invokes registered TX event callback
178180
*
181+
* This function locks the deep sleep until any event has occured
182+
*
179183
* @param buffer The buffer where received data will be stored
180184
* @param length The buffer length in bytes
181185
* @param callback The event callback function
@@ -189,6 +193,8 @@ class SerialBase : private NonCopyable<SerialBase> {
189193

190194
/** Begin asynchronous reading using 8bit buffer. The completition invokes registred RX event callback.
191195
*
196+
* This function locks the deep sleep until any event has occured
197+
*
192198
* @param buffer The buffer where received data will be stored
193199
* @param length The buffer length in bytes
194200
* @param callback The event callback function
@@ -199,6 +205,8 @@ class SerialBase : private NonCopyable<SerialBase> {
199205

200206
/** Begin asynchronous reading using 16bit buffer. The completition invokes registred RX event callback.
201207
*
208+
* This function locks the deep sleep until any event has occured
209+
*
202210
* @param buffer The buffer where received data will be stored
203211
* @param length The buffer length in bytes
204212
* @param callback The event callback function
@@ -241,10 +249,10 @@ class SerialBase : private NonCopyable<SerialBase> {
241249

242250
#if DEVICE_SERIAL_ASYNCH
243251
CThunk<SerialBase> _thunk_irq;
244-
event_callback_t _tx_callback;
245-
event_callback_t _rx_callback;
246252
DMAUsage _tx_usage;
247253
DMAUsage _rx_usage;
254+
event_callback_t _tx_callback;
255+
event_callback_t _rx_callback;
248256
#endif
249257

250258
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)