Merge pull request #4912 from 0xc0170/dev_sleep_drivers

Add sleep manager API
pull/5049/merge
Jimmy Brisson 2017-09-07 18:26:49 -05:00 committed by GitHub
commit e12f116ec1
20 changed files with 507 additions and 28 deletions

View File

@ -0,0 +1,60 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#if !DEVICE_SLEEP
#error [NOT_SUPPORTED] test not supported
#endif
using namespace utest::v1;
void sleep_manager_deepsleep_counter_test()
{
bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
TEST_ASSERT_TRUE(deep_sleep_allowed);
sleep_manager_lock_deep_sleep();
deep_sleep_allowed = sleep_manager_can_deep_sleep();
TEST_ASSERT_FALSE(deep_sleep_allowed);
sleep_manager_unlock_deep_sleep();
deep_sleep_allowed = sleep_manager_can_deep_sleep();
TEST_ASSERT_TRUE(deep_sleep_allowed);
}
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
{
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(20, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("sleep manager - deep sleep counter", sleep_manager_deepsleep_counter_test, greentea_failure_handler),
};
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -0,0 +1,99 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#if !DEVICE_SLEEP
#error [NOT_SUPPORTED] test not supported
#endif
using namespace utest::v1;
void sleep_manager_locking_thread_test()
{
for (uint32_t i = 0; i < 100; i++) {
sleep_manager_lock_deep_sleep();
Thread::wait(25);
sleep_manager_unlock_deep_sleep();
}
}
void sleep_manager_multithread_test()
{
{
Callback<void()> cb(sleep_manager_locking_thread_test);
Thread t1;
Thread t2;
t1.start(callback(cb));
Thread::wait(25);
t2.start(callback(cb));
// Wait for the threads to finish
t1.join();
t2.join();
}
bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed");
}
void sleep_manager_locking_irq_test()
{
sleep_manager_lock_deep_sleep();
sleep_manager_unlock_deep_sleep();
}
void sleep_manager_irq_test()
{
{
Ticker ticker1;
Timer timer;
ticker1.attach_us(&sleep_manager_locking_irq_test, 500);
// run this for 5 seconds
timer.start();
int start = timer.read();
int end = start + 5;
while (timer.read() < end) {
sleep_manager_locking_irq_test();
}
timer.stop();
}
bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed");
}
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(30, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("sleep manager HAL - locking multithreaded", sleep_manager_multithread_test),
Case("sleep manager HAL - locking IRQ", sleep_manager_irq_test),
};
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -18,16 +18,15 @@
#if DEVICE_CAN
#include "cmsis.h"
#include "platform/mbed_sleep.h"
namespace mbed {
static void donothing() {}
CAN::CAN(PinName rd, PinName td) : _can(), _irq() {
// No lock needed in constructor
for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
_irq[i] = callback(donothing);
_irq[i] = NULL;
}
can_init(&_can, rd, td);
@ -38,7 +37,7 @@ CAN::CAN(PinName rd, PinName td, int hz) : _can(), _irq() {
// No lock needed in constructor
for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
_irq[i] = callback(donothing);
_irq[i] = NULL;
}
can_init_freq(&_can, rd, td, hz);
@ -115,10 +114,18 @@ int CAN::filter(unsigned int id, unsigned int mask, CANFormat format, int handle
void CAN::attach(Callback<void()> func, IrqType type) {
lock();
if (func) {
// lock deep sleep only the first time
if (!_irq[(CanIrqType)type]) {
sleep_manager_lock_deep_sleep();
}
_irq[(CanIrqType)type] = func;
can_irq_set(&_can, (CanIrqType)type, 1);
} else {
_irq[(CanIrqType)type] = callback(donothing);
// unlock deep sleep only the first time
if (_irq[(CanIrqType)type]) {
sleep_manager_unlock_deep_sleep();
}
_irq[(CanIrqType)type] = NULL;
can_irq_set(&_can, (CanIrqType)type, 0);
}
unlock();
@ -126,7 +133,9 @@ void CAN::attach(Callback<void()> func, IrqType type) {
void CAN::_irq_handler(uint32_t id, CanIrqType type) {
CAN *handler = (CAN*)id;
handler->_irq[type].call();
if (handler->_irq[type]) {
handler->_irq[type].call();
}
}
void CAN::lock() {

View File

@ -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)
*/

View File

@ -17,6 +17,10 @@
#if DEVICE_I2C
#if DEVICE_I2C_ASYNCH
#include "platform/mbed_sleep.h"
#endif
namespace mbed {
I2C *I2C::_owner = NULL;
@ -129,6 +133,7 @@ int I2C::transfer(int address, const char *tx_buffer, int tx_length, char *rx_bu
unlock();
return -1; // transaction ongoing
}
sleep_manager_lock_deep_sleep();
aquire();
_callback = callback;
@ -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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -16,23 +16,23 @@
#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() {};
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(NULL),
_rx_callback(NULL),
#endif
_serial(), _baud(baud) {
// No lock needed in the constructor
for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
_irq[i] = donothing;
_irq[i] = NULL;
}
serial_init(&_serial, tx, rx);
@ -73,10 +73,18 @@ void SerialBase::attach(Callback<void()> func, IrqType type) {
// Disable interrupts when attaching interrupt handler
core_util_critical_section_enter();
if (func) {
// lock deep sleep only the first time
if (!_irq[type]) {
sleep_manager_lock_deep_sleep();
}
_irq[type] = func;
serial_irq_set(&_serial, (SerialIrq)type, 1);
} else {
_irq[type] = donothing;
// unlock deep sleep only the first time
if (_irq[type]) {
sleep_manager_unlock_deep_sleep();
}
_irq[type] = NULL;
serial_irq_set(&_serial, (SerialIrq)type, 0);
}
core_util_critical_section_exit();
@ -85,7 +93,9 @@ void SerialBase::attach(Callback<void()> func, IrqType type) {
void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type) {
SerialBase *handler = (SerialBase*)id;
handler->_irq[irq_type]();
if (handler->_irq[irq_type]) {
handler->_irq[irq_type]();
}
}
int SerialBase::_base_getc() {
@ -173,16 +183,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) {
sleep_manager_unlock_deep_sleep();
}
_tx_callback = NULL;
serial_tx_abort_asynch(&_serial);
}
void SerialBase::abort_read(void)
{
// tx might still be active
if (_tx_callback) {
sleep_manager_unlock_deep_sleep();
}
_rx_callback = NULL;
serial_rx_abort_asynch(&_serial);
}
@ -228,6 +249,7 @@ void SerialBase::start_read(void *buffer, int buffer_size, char buffer_width, co
{
_rx_callback = callback;
_thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
sleep_manager_lock_deep_sleep();
serial_rx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, char_match, _rx_usage);
}
@ -235,14 +257,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

View File

@ -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;

View File

@ -25,6 +25,10 @@ namespace mbed {
void Ticker::detach() {
core_util_critical_section_enter();
remove();
// unlocked only if we were attached (we locked it)
if (_function) {
sleep_manager_unlock_deep_sleep();
}
_function = 0;
core_util_critical_section_exit();
}

View File

@ -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 */
@ -63,10 +64,10 @@ namespace mbed {
class Ticker : public TimerEvent, private NonCopyable<Ticker> {
public:
Ticker() : TimerEvent() {
Ticker() : TimerEvent(), _function(0) {
}
Ticker(const ticker_data_t *data) : TimerEvent(data) {
Ticker(const ticker_data_t *data) : TimerEvent(data), _function(0) {
data->interface->init();
}
@ -102,6 +103,10 @@ public:
* @param t the time between calls in micro-seconds
*/
void attach_us(Callback<void()> func, us_timestamp_t t) {
// lock only for the initial callback setup
if (!_function) {
sleep_manager_lock_deep_sleep();
}
_function = func;
setup(t);
}

View File

@ -18,6 +18,7 @@
#include "drivers/Ticker.h"
#include "platform/NonCopyable.h"
#include "platform/mbed_sleep.h"
namespace mbed {
/** \addtogroup drivers */

View File

@ -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;
}
@ -40,6 +41,9 @@ void Timer::start() {
void Timer::stop() {
core_util_critical_section_enter();
_time += slicetime();
if (_running) {
sleep_manager_unlock_deep_sleep();
}
_running = 0;
core_util_critical_section_exit();
}

View File

@ -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 */

92
hal/mbed_sleep_manager.c Normal file
View File

@ -0,0 +1,92 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_sleep.h"
#include "mbed_critical.h"
#include "sleep_api.h"
#include "mbed_error.h"
#include <limits.h>
#if DEVICE_SLEEP
// deep sleep locking counter. A target is allowed to deep sleep if counter == 0
static uint16_t deep_sleep_lock = 0U;
void sleep_manager_lock_deep_sleep(void)
{
core_util_critical_section_enter();
if (deep_sleep_lock == USHRT_MAX) {
core_util_critical_section_exit();
error("Deep sleep lock would overflow (> USHRT_MAX)");
}
core_util_atomic_incr_u16(&deep_sleep_lock, 1);
core_util_critical_section_exit();
}
void sleep_manager_unlock_deep_sleep(void)
{
core_util_critical_section_enter();
if (deep_sleep_lock == 0) {
core_util_critical_section_exit();
error("Deep sleep lock would underflow (< 0)");
}
core_util_atomic_decr_u16(&deep_sleep_lock, 1);
core_util_critical_section_exit();
}
bool sleep_manager_can_deep_sleep(void)
{
return deep_sleep_lock == 0 ? true : false;
}
void sleep_manager_sleep_auto(void)
{
core_util_critical_section_enter();
// debug profile should keep debuggers attached, no deep sleep allowed
#ifdef MBED_DEBUG
hal_sleep();
#else
if (sleep_manager_can_deep_sleep()) {
hal_deepsleep();
} else {
hal_sleep();
}
#endif
core_util_critical_section_exit();
}
#else
// locking is valid only if DEVICE_SLEEP is defined
// we provide empty implementation
void sleep_manager_lock_deep_sleep(void)
{
}
void sleep_manager_unlock_deep_sleep(void)
{
}
bool sleep_manager_can_deep_sleep(void)
{
// no sleep implemented
return false;
}
#endif

1
mbed.h
View File

@ -90,6 +90,7 @@
#include "platform/FileHandle.h"
#include "platform/DirHandle.h"
#include "platform/CriticalSectionLock.h"
#include "platform/DeepSleepLock.h"
// mbed Non-hardware components
#include "platform/Callback.h"

67
platform/DeepSleepLock.h Normal file
View File

@ -0,0 +1,67 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_DEEPSLEEPLOCK_H
#define MBED_DEEPSLEEPLOCK_H
#include "platform/mbed_sleep.h"
namespace mbed {
/** RAII object for disabling, then restoring the deep sleep mode
* Usage:
* @code
*
* void f() {
* // some code here
* {
* DeepSleepLock lock;
* // Code in this block will run with the deep sleep mode locked
* }
* // deep sleep mode will be restored to their previous state
* }
* @endcode
*/
class DeepSleepLock {
public:
DeepSleepLock()
{
sleep_manager_lock_deep_sleep();
}
~DeepSleepLock()
{
sleep_manager_unlock_deep_sleep();
}
/** Mark the start of a locked deep sleep section
*/
void lock()
{
sleep_manager_lock_deep_sleep();
}
/** Mark the end of a locked deep sleep section
*/
void unlock()
{
sleep_manager_unlock_deep_sleep();
}
};
}
#endif

View File

@ -20,11 +20,87 @@
#define MBED_SLEEP_H
#include "sleep_api.h"
#include "mbed_toolchain.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Sleep manager API
* The sleep manager provides API to automatically select sleep mode.
*
* There are two sleep modes:
* - sleep
* - deepsleep
*
* Use locking/unlocking deepsleep for drivers that depend on features that
* are not allowed (=disabled) during the deepsleep. For instance, high frequency
* clocks.
*
* Example:
* @code
*
* void driver::handler()
* {
* if (_sensor.get_event()) {
* // any event - we are finished, unlock the deepsleep
* sleep_manager_unlock_deep_sleep();
* _callback();
* }
* }
*
* int driver::measure(event_t event, callback_t& callback)
* {
* _callback = callback;
* sleep_manager_lock_deep_sleep();
* // start async transaction, we are waiting for an event
* return _sensor.start(event, callback);
* }
* @endcode
*/
/** Lock the deep sleep mode
*
* This locks the automatic deep mode selection.
* sleep_manager_sleep_auto() will ignore deepsleep mode if
* this function is invoked at least once (the internal counter is non-zero)
*
* Use this locking mechanism for interrupt driven API that are
* running in the background and deepsleep could affect their functionality
*
* The lock is a counter, can be locked up to USHRT_MAX
* This function is IRQ and thread safe
*/
void sleep_manager_lock_deep_sleep(void);
/** Unlock the deep sleep mode
*
* Use unlocking in pair with sleep_manager_lock_deep_sleep().
*
* The lock is a counter, should be equally unlocked as locked
* This function is IRQ and thread safe
*/
void sleep_manager_unlock_deep_sleep(void);
/** Get the status of deep sleep allowance for a target
*
* @return true if a target can go to deepsleep, false otherwise
*/
bool sleep_manager_can_deep_sleep(void);
/** Enter auto selected sleep mode. It chooses the sleep or deeepsleep modes based
* on the deepsleep locking counter
*
* This function is IRQ and thread safe
*
* @note
* If MBED_DEBUG is defined, only hal_sleep is allowed. This ensures the debugger
* to be active for debug modes.
*
*/
void sleep_manager_sleep_auto(void);
/** Send the microcontroller to sleep
*
* @note This function can be a noop if not implemented by the platform.
@ -46,11 +122,9 @@ extern "C" {
__INLINE static void sleep(void)
{
#if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED))
#ifndef MBED_DEBUG
#if DEVICE_SLEEP
hal_sleep();
sleep_manager_sleep_auto();
#endif /* DEVICE_SLEEP */
#endif /* MBED_DEBUG */
#endif /* !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) */
}
@ -60,7 +134,7 @@ __INLINE static void sleep(void)
* @note This function will be a noop in debug mode (debug build profile when MBED_DEBUG is defined)
* @note This function will be a noop while uVisor is in use.
*
* This processor is setup ready for deep sleep, and sent to sleep using __WFI(). This mode
* This processor is setup ready for deep sleep, and sent to sleep. This mode
* has the same sleep features as sleep plus it powers down peripherals and clocks. All state
* is still maintained.
*
@ -71,14 +145,14 @@ __INLINE static void sleep(void)
* Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be
* able to access the LocalFileSystem
*/
MBED_DEPRECATED_SINCE("mbed-os-5.6", "One entry point for an application, use sleep()")
__INLINE static void deepsleep(void)
{
#if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED))
#ifndef MBED_DEBUG
#if DEVICE_SLEEP
hal_deepsleep();
sleep_manager_sleep_auto();
#endif /* DEVICE_SLEEP */
#endif /* MBED_DEBUG */
#endif /* !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) */
}

View File

@ -22,14 +22,16 @@
#include "rtos/rtos_idle.h"
#include "platform/mbed_sleep.h"
#include "mbed_critical.h"
static void default_idle_hook(void)
{
/* Sleep: ideally, we should put the chip to sleep.
Unfortunately, this usually requires disconnecting the interface chip (debugger).
This can be done, but it would break the local file system.
*/
// critical section to complete sleep with locked deepsleep
core_util_critical_section_enter();
sleep_manager_lock_deep_sleep();
sleep();
sleep_manager_unlock_deep_sleep();
core_util_critical_section_exit();
}
static void (*idle_hook_fptr)(void) = &default_idle_hook;