mirror of https://github.com/ARMmbed/mbed-os.git
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/Timerpull/4912/head
parent
fcdb04351f
commit
e6d8a9a8a4
|
@ -18,6 +18,7 @@
|
|||
#if DEVICE_CAN
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "platform/mbed_sleep.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
|
@ -115,9 +116,11 @@ int CAN::filter(unsigned int id, unsigned int mask, CANFormat format, int handle
|
|||
void CAN::attach(Callback<void()> func, IrqType type) {
|
||||
lock();
|
||||
if (func) {
|
||||
sleep_manager_lock_deep_sleep();
|
||||
_irq[(CanIrqType)type] = func;
|
||||
can_irq_set(&_can, (CanIrqType)type, 1);
|
||||
} else {
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
_irq[(CanIrqType)type] = callback(donothing);
|
||||
can_irq_set(&_can, (CanIrqType)type, 0);
|
||||
}
|
||||
|
|
|
@ -235,7 +235,9 @@ public:
|
|||
|
||||
/** Attach a function to call whenever a CAN frame received interrupt is
|
||||
* generated.
|
||||
*
|
||||
*
|
||||
* This function locks the deep sleep while a callback is attached
|
||||
*
|
||||
* @param func A pointer to a void function, or 0 to set as none
|
||||
* @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)
|
||||
*/
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
#if DEVICE_I2C
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
#include "platform/mbed_sleep.h"
|
||||
#endif
|
||||
|
||||
namespace mbed {
|
||||
|
||||
I2C *I2C::_owner = NULL;
|
||||
|
@ -125,6 +129,7 @@ void I2C::unlock() {
|
|||
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)
|
||||
{
|
||||
lock();
|
||||
sleep_manager_lock_deep_sleep();
|
||||
if (i2c_active(&_i2c)) {
|
||||
unlock();
|
||||
return -1; // transaction ongoing
|
||||
|
@ -143,6 +148,7 @@ void I2C::abort_transfer(void)
|
|||
{
|
||||
lock();
|
||||
i2c_abort_asynch(&_i2c);
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
@ -152,6 +158,9 @@ void I2C::irq_handler_asynch(void)
|
|||
if (_callback && event) {
|
||||
_callback.call(event);
|
||||
}
|
||||
if (event) {
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -159,6 +159,8 @@ public:
|
|||
|
||||
/** Start non-blocking I2C transfer.
|
||||
*
|
||||
* This function locks the deep sleep until any event has occured
|
||||
*
|
||||
* @param address 8/10 bit I2c slave address
|
||||
* @param tx_buffer The TX buffer with data to be transfered
|
||||
* @param tx_length The length of TX buffer in bytes
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
#include "drivers/SPI.h"
|
||||
#include "platform/mbed_critical.h"
|
||||
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
#include "platform/mbed_sleep.h"
|
||||
#endif
|
||||
|
||||
#if DEVICE_SPI
|
||||
|
||||
namespace mbed {
|
||||
|
@ -136,6 +140,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();
|
||||
#if TRANSACTION_QUEUE_SIZE_SPI
|
||||
dequeue_transaction();
|
||||
#endif
|
||||
|
@ -195,6 +200,7 @@ 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();
|
||||
_acquire();
|
||||
_callback = callback;
|
||||
_irq.callback(&SPI::irq_handler_asynch);
|
||||
|
@ -224,6 +230,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();
|
||||
_callback.call(event & SPI_EVENT_ALL);
|
||||
}
|
||||
#if TRANSACTION_QUEUE_SIZE_SPI
|
||||
|
|
|
@ -156,6 +156,8 @@ public:
|
|||
|
||||
/** Start non-blocking SPI transfer using 8bit buffers.
|
||||
*
|
||||
* This function locks the deep sleep until any event has occured
|
||||
*
|
||||
* @param tx_buffer The TX buffer with data to be transfered. If NULL is passed,
|
||||
* the default SPI value is sent
|
||||
* @param tx_length The length of TX buffer in bytes
|
||||
|
|
|
@ -16,17 +16,21 @@
|
|||
#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() {};
|
||||
static void donothing2(int arg) {};
|
||||
|
||||
|
||||
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(donothing2),
|
||||
_rx_callback(donothing2),
|
||||
#endif
|
||||
_serial(), _baud(baud) {
|
||||
// No lock needed in the constructor
|
||||
|
@ -73,9 +77,11 @@ void SerialBase::attach(Callback<void()> func, IrqType type) {
|
|||
// Disable interrupts when attaching interrupt handler
|
||||
core_util_critical_section_enter();
|
||||
if (func) {
|
||||
sleep_manager_lock_deep_sleep();
|
||||
_irq[type] = func;
|
||||
serial_irq_set(&_serial, (SerialIrq)type, 1);
|
||||
} else {
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
_irq[type] = donothing;
|
||||
serial_irq_set(&_serial, (SerialIrq)type, 0);
|
||||
}
|
||||
|
@ -173,16 +179,27 @@ void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_wi
|
|||
_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 == &donothing2) {
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
}
|
||||
_tx_callback = donothing2;
|
||||
serial_tx_abort_asynch(&_serial);
|
||||
}
|
||||
|
||||
void SerialBase::abort_read(void)
|
||||
{
|
||||
// tx might still be active
|
||||
if (_tx_callback == &donothing2) {
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
}
|
||||
_rx_callback = donothing2;
|
||||
serial_rx_abort_asynch(&_serial);
|
||||
}
|
||||
|
||||
|
@ -235,14 +252,22 @@ void SerialBase::interrupt_handler_asynch(void)
|
|||
{
|
||||
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
|
||||
|
|
|
@ -167,6 +167,8 @@ public:
|
|||
|
||||
/** Begin asynchronous write using 8bit buffer. The completition invokes registered TX event callback
|
||||
*
|
||||
* This function locks the deep sleep until any event has occured
|
||||
*
|
||||
* @param buffer The buffer where received data will be stored
|
||||
* @param length The buffer length in bytes
|
||||
* @param callback The event callback function
|
||||
|
@ -176,6 +178,8 @@ public:
|
|||
|
||||
/** Begin asynchronous write using 16bit buffer. The completition invokes registered TX event callback
|
||||
*
|
||||
* This function locks the deep sleep until any event has occured
|
||||
*
|
||||
* @param buffer The buffer where received data will be stored
|
||||
* @param length The buffer length in bytes
|
||||
* @param callback The event callback function
|
||||
|
@ -189,6 +193,8 @@ public:
|
|||
|
||||
/** Begin asynchronous reading using 8bit buffer. The completition invokes registred RX event callback.
|
||||
*
|
||||
* This function locks the deep sleep until any event has occured
|
||||
*
|
||||
* @param buffer The buffer where received data will be stored
|
||||
* @param length The buffer length in bytes
|
||||
* @param callback The event callback function
|
||||
|
@ -199,6 +205,8 @@ public:
|
|||
|
||||
/** Begin asynchronous reading using 16bit buffer. The completition invokes registred RX event callback.
|
||||
*
|
||||
* This function locks the deep sleep until any event has occured
|
||||
*
|
||||
* @param buffer The buffer where received data will be stored
|
||||
* @param length The buffer length in bytes
|
||||
* @param callback The event callback function
|
||||
|
@ -241,10 +249,10 @@ protected:
|
|||
|
||||
#if DEVICE_SERIAL_ASYNCH
|
||||
CThunk<SerialBase> _thunk_irq;
|
||||
event_callback_t _tx_callback;
|
||||
event_callback_t _rx_callback;
|
||||
DMAUsage _tx_usage;
|
||||
DMAUsage _rx_usage;
|
||||
event_callback_t _tx_callback;
|
||||
event_callback_t _rx_callback;
|
||||
#endif
|
||||
|
||||
serial_t _serial;
|
||||
|
|
|
@ -26,6 +26,7 @@ void Ticker::detach() {
|
|||
core_util_critical_section_enter();
|
||||
remove();
|
||||
_function = 0;
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "platform/Callback.h"
|
||||
#include "platform/mbed_toolchain.h"
|
||||
#include "platform/NonCopyable.h"
|
||||
#include "platform/mbed_sleep.h"
|
||||
|
||||
namespace mbed {
|
||||
/** \addtogroup drivers */
|
||||
|
@ -103,6 +104,7 @@ public:
|
|||
*/
|
||||
void attach_us(Callback<void()> func, us_timestamp_t t) {
|
||||
_function = func;
|
||||
sleep_manager_lock_deep_sleep();
|
||||
setup(t);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "drivers/Ticker.h"
|
||||
#include "platform/NonCopyable.h"
|
||||
#include "platform/mbed_sleep.h"
|
||||
|
||||
namespace mbed {
|
||||
/** \addtogroup drivers */
|
||||
|
|
|
@ -31,6 +31,7 @@ Timer::Timer(const ticker_data_t *data) : _running(), _start(), _time(), _ticker
|
|||
void Timer::start() {
|
||||
core_util_critical_section_enter();
|
||||
if (!_running) {
|
||||
sleep_manager_lock_deep_sleep();
|
||||
_start = ticker_read_us(_ticker_data);
|
||||
_running = 1;
|
||||
}
|
||||
|
@ -41,6 +42,7 @@ void Timer::stop() {
|
|||
core_util_critical_section_enter();
|
||||
_time += slicetime();
|
||||
_running = 0;
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "platform/platform.h"
|
||||
#include "hal/ticker_api.h"
|
||||
#include "platform/NonCopyable.h"
|
||||
#include "platform/mbed_sleep.h"
|
||||
|
||||
namespace mbed {
|
||||
/** \addtogroup drivers */
|
||||
|
|
Loading…
Reference in New Issue