Merge pull request #5581 from SiliconLabs/feature/remove-custom-sleepmodes

Remove custom Silicon Labs sleep management
pull/5693/head
Martin Kojtal 2017-12-12 17:30:17 +00:00 committed by GitHub
commit 6c59e13e76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 41 additions and 172 deletions

View File

@ -23,8 +23,7 @@
#include "em_usbtypes.h"
#include "em_usbhal.h"
#include "em_usbd.h"
#include "sleepmodes.h"
#include "mbed_sleep.h"
enum USBISRCommand {
CMD_HANDLED = 0,
@ -134,11 +133,6 @@ USBHAL::USBHAL(void)
// be dynamically removed/reinstated to allow deeper sleep.
usbhal_allow_em2(false);
// When in suspend / Vbus off we can go to EM2, but never below
// that as long as USB is being used. Despite the name the call here
// blocks entering modes _below_ EM2, but allows EM2.
blockSleepMode(EM2);
epCallback[EP0OUT] = NULL;
epCallback[EP0IN ] = NULL;
epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback;
@ -193,17 +187,17 @@ USBHAL::~USBHAL(void)
usbhal_free_buffers();
usbhal_allow_em2(true);
unblockSleepMode(EM2);
}
extern "C" void usbhal_allow_em2(bool allow_em2)
{
if (allow_em2) {
// unblockSleepMode is safe to call even if we would unblock
// an already unblocked mode, so no checks here.
unblockSleepMode(EM1);
} else {
blockSleepMode(EM1);
static bool blocked = false;
if (allow_em2 && blocked) {
sleep_manager_unlock_deep_sleep();
blocked = false;
} else if (!blocked) {
sleep_manager_lock_deep_sleep();
blocked = true;
}
}

View File

@ -25,7 +25,6 @@
#include "pinmap.h"
#include "em_cmu.h"
#include "mbed_assert.h"
#include "sleepmodes.h"
void gpio_write(gpio_t *obj, int value)

View File

@ -31,10 +31,8 @@
#include "em_gpio.h"
#include "em_cmu.h"
#include "sleep_api.h"
#include "sleepmodes.h"
#define NUM_GPIO_CHANNELS (16)
#define GPIO_LEAST_ACTIVE_SLEEPMODE EM3
/* Macro return index of the LSB flag which is set. */
#if ((__CORTEX_M == 3) || (__CORTEX_M == 4))
@ -142,21 +140,16 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
if(GPIO->IEN == 0) was_disabled = true;
GPIO_IntConfig((GPIO_Port_TypeDef)((obj->pin >> 4) & 0xF), obj->pin &0xF, obj->risingEdge, obj->fallingEdge, obj->risingEdge || obj->fallingEdge);
if ((GPIO->IEN != 0) && (obj->risingEdge || obj->fallingEdge) && was_disabled) {
blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
}
}
inline void gpio_irq_enable(gpio_irq_t *obj)
{
if(GPIO->IEN == 0) blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
GPIO_IntEnable(1 << (obj->pin & 0xF)); // pin mask for pins to enable
}
inline void gpio_irq_disable(gpio_irq_t *obj)
{
GPIO_IntDisable(1 << (obj->pin & 0xF)); // pin mask for pins to disable
if(GPIO->IEN == 0) unblockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
}
/***************************************************************************//**

View File

@ -28,10 +28,10 @@
#if DEVICE_I2C
#include "mbed_assert.h"
#include "mbed_sleep.h"
#include "i2c_api.h"
#include "PeripheralPins.h"
#include "pinmap_function.h"
#include "sleepmodes.h"
#include "em_i2c.h"
#include "em_cmu.h"
@ -508,7 +508,7 @@ void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx,
retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer));
if(retval == i2cTransferInProgress) {
blockSleepMode(EM1);
sleep_manager_lock_deep_sleep();
} else {
// something happened, and the transfer did not go through
// So, we need to clean up
@ -541,7 +541,7 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
// Disable interrupt
i2c_enable_interrupt(obj, 0, false);
unblockSleepMode(EM1);
sleep_manager_unlock_deep_sleep();
return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events;
case i2cTransferNack:
@ -549,7 +549,7 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
// Disable interrupt
i2c_enable_interrupt(obj, 0, false);
unblockSleepMode(EM1);
sleep_manager_unlock_deep_sleep();
return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events;
default:
@ -557,7 +557,7 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
// Disable interrupt
i2c_enable_interrupt(obj, 0, false);
unblockSleepMode(EM1);
sleep_manager_unlock_deep_sleep();
// return error
return I2C_EVENT_ERROR & obj->i2c.events;
@ -578,19 +578,19 @@ uint8_t i2c_active(i2c_t *obj)
*/
void i2c_abort_asynch(i2c_t *obj)
{
// Do not deactivate I2C twice
if (!i2c_active(obj)) return;
// Disable interrupt
i2c_enable_interrupt(obj, 0, false);
// Do not deactivate I2C twice
if (!i2c_active(obj)) return;
// Abort
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
// Block until free
while(i2c_active(obj));
unblockSleepMode(EM1);
sleep_manager_unlock_deep_sleep();
}
#endif //DEVICE_I2C ASYNCH

View File

@ -26,11 +26,11 @@
#if DEVICE_PWMOUT
#include "mbed_assert.h"
#include "mbed_sleep.h"
#include "pwmout_api.h"
#include "pinmap.h"
#include "PeripheralPins.h"
#include "device_peripherals.h"
#include "sleepmodes.h"
#include "em_cmu.h"
#include "em_gpio.h"
@ -180,7 +180,7 @@ void pwmout_init(pwmout_t *obj, PinName pin)
return;
} else {
pwmout_set_channel_route(pwmout_get_channel_route(obj->channel));
blockSleepMode(EM1);
sleep_manager_lock_deep_sleep();
pwmout_enable(obj, true);
pwmout_enable_pins(obj, true);
}
@ -226,7 +226,7 @@ void pwmout_free(pwmout_t *obj)
{
if(pwmout_disable_channel_route(pwmout_get_channel_route(obj->channel))) {
//Channel was previously enabled, so do housekeeping
unblockSleepMode(EM1);
sleep_manager_unlock_deep_sleep();
} else {
//This channel was disabled already
}

View File

@ -28,7 +28,6 @@
#include "rtc_api_HAL.h"
#include "em_cmu.h"
#include "sleep_api.h"
#include "sleepmodes.h"
#if (defined RTC_COUNT) && (RTC_COUNT > 0)
#include "em_rtc.h"
@ -48,8 +47,6 @@ static void (*comp0_handler)(void) = NULL;
#ifndef RTCC_COUNT
/* Using RTC API */
#define RTC_LEAST_ACTIVE_SLEEPMODE EM2
#define RTC_NUM_BITS (24)
void RTC_IRQHandler(void)
@ -111,7 +108,6 @@ void rtc_init_real(uint32_t flags)
/* Initialize */
RTC_Init(&init);
blockSleepMode(RTC_LEAST_ACTIVE_SLEEPMODE);
rtc_inited = true;
}
}
@ -131,7 +127,6 @@ void rtc_free_real(uint32_t flags)
NVIC_DisableIRQ(RTC_IRQn);
RTC_Reset();
CMU_ClockEnable(cmuClock_RTC, false);
unblockSleepMode(RTC_LEAST_ACTIVE_SLEEPMODE);
rtc_inited = false;
}
}
@ -139,8 +134,6 @@ void rtc_free_real(uint32_t flags)
#else
/* Using RTCC API */
#define RTCC_LEAST_ACTIVE_SLEEPMODE EM2
#define RTCC_NUM_BITS (32)
void RTCC_IRQHandler(void)
@ -204,8 +197,6 @@ void rtc_init_real(uint32_t flags)
/* Initialize */
RTCC_Init(&init);
blockSleepMode(RTCC_LEAST_ACTIVE_SLEEPMODE);
rtc_inited = true;
}
}
@ -225,7 +216,6 @@ void rtc_free_real(uint32_t flags)
NVIC_DisableIRQ(RTCC_IRQn);
RTCC_Reset();
CMU_ClockEnable(cmuClock_RTCC, false);
unblockSleepMode(RTCC_LEAST_ACTIVE_SLEEPMODE);
rtc_inited = false;
}
}

View File

@ -26,6 +26,7 @@
#if DEVICE_SERIAL
#include "mbed_assert.h"
#include "mbed_sleep.h"
#include "serial_api.h"
#include "serial_api_HAL.h"
#include <string.h>
@ -44,10 +45,6 @@
#include "dma_api.h"
#include "sleep_api.h"
#include "buffer.h"
#include "sleepmodes.h"
#define SERIAL_LEAST_ACTIVE_SLEEPMODE EM1
#define SERIAL_LEAST_ACTIVE_SLEEPMODE_LEUART EM2
/** Validation of LEUART register block pointer reference
* for assert statements. */
@ -2239,13 +2236,11 @@ static void serial_unblock_sleep(serial_t *obj)
{
if( obj->serial.sleep_blocked > 0 ) {
#ifdef LEUART_USING_LFXO
if(LEUART_REF_VALID(obj->serial.periph.leuart) && (LEUART_BaudrateGet(obj->serial.periph.leuart) <= (LEUART_LF_REF_FREQ/2))){
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE_LEUART);
}else{
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
if(!LEUART_REF_VALID(obj->serial.periph.leuart) || (LEUART_BaudrateGet(obj->serial.periph.leuart) > (LEUART_LF_REF_FREQ/2))){
sleep_manager_unlock_deep_sleep();
}
#else
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_unlock_deep_sleep();
#endif
obj->serial.sleep_blocked--;
}
@ -2255,13 +2250,13 @@ static void serial_block_sleep(serial_t *obj)
{
obj->serial.sleep_blocked++;
#ifdef LEUART_USING_LFXO
if(LEUART_REF_VALID(obj->serial.periph.leuart) && (LEUART_BaudrateGet(obj->serial.periph.leuart) <= (LEUART_LF_REF_FREQ/2))){
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE_LEUART);
}else{
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
if(!LEUART_REF_VALID(obj->serial.periph.leuart) || (LEUART_BaudrateGet(obj->serial.periph.leuart) > (LEUART_LF_REF_FREQ/2))){
/* LEUART configured to a baudrate triggering the use of HFCLK, so prevent HFCLK from getting turned off */
sleep_manager_lock_deep_sleep();
}
#else
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
/* HFCLK unavailable in deepsleep */
sleep_manager_lock_deep_sleep();
#endif
}

View File

@ -25,32 +25,15 @@
#if DEVICE_SLEEP
#include "sleep_api.h"
#include "sleepmodes.h"
#include "em_emu.h"
#include "mbed_critical.h"
uint32_t sleep_block_counter[NUM_SLEEP_MODES] = {0};
/**
* Sleep mode.
* Enter the lowest possible sleep mode that is not blocked by ongoing activity.
* Stop the core clock using a WFI.
*/
void hal_sleep(void)
{
if (sleep_block_counter[0] > 0) {
/* Blocked everything below EM0, so just return */
return;
} else if (sleep_block_counter[1] > 0) {
/* Blocked everything below EM1, enter EM1 */
EMU_EnterEM1();
} else if (sleep_block_counter[2] > 0) {
/* Blocked everything below EM2, enter EM2 */
EMU_EnterEM2(true);
} else {
/* Blocked everything below EM3, enter EM3 */
EMU_EnterEM3(true);
} /* Never enter EM4, as mbed has no way of configuring EM4 wakeup */
return;
EMU_EnterEM1();
}
/**
@ -69,35 +52,4 @@ void hal_deepsleep(void)
EMU_EnterEM2(true);
}
/** Block the microcontroller from sleeping below a certain mode
*
* This will block sleep() from entering an energy mode below the one given.
* -- To be called by peripheral HAL's --
*
* After the peripheral is finished with the operation, it should call unblock with the same state
*
*/
void blockSleepMode(sleepstate_enum minimumMode)
{
core_util_critical_section_enter();
sleep_block_counter[minimumMode]++;
core_util_critical_section_exit();
}
/** Unblock the microcontroller from sleeping below a certain mode
*
* This will unblock sleep() from entering an energy mode below the one given.
* -- To be called by peripheral HAL's --
*
* This should be called after all transactions on a peripheral are done.
*/
void unblockSleepMode(sleepstate_enum minimumMode)
{
core_util_critical_section_enter();
if(sleep_block_counter[minimumMode] > 0) {
sleep_block_counter[minimumMode]--;
}
core_util_critical_section_exit();
}
#endif

View File

@ -1,51 +0,0 @@
/***************************************************************************//**
* @file sleepmodes.h
*******************************************************************************
* @section License
* <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Apache-2.0
*
* 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_SLEEPMODES_H
#define MBED_SLEEPMODES_H
#include "em_gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Blocks all sleepmodes below the one passed as argument
*
* @param minimumMode The lowest-power sleep mode which must remain active
*/
void blockSleepMode(sleepstate_enum minimumMode);
/*
* Unblocks a previously-blocked sleep mode
*
*@param minimumMode The same sleepmode that was previously passed to blockSleepMode
*/
void unblockSleepMode(sleepstate_enum minimumMode);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -26,6 +26,7 @@
#if DEVICE_SPI
#include "mbed_assert.h"
#include "mbed_sleep.h"
#include "PeripheralPins.h"
#include "pinmap.h"
#include "pinmap_function.h"
@ -39,12 +40,9 @@
#include "em_cmu.h"
#include "em_dma.h"
#include "sleep_api.h"
#include "sleepmodes.h"
static uint16_t fill_word = SPI_FILL_WORD;
#define SPI_LEAST_ACTIVE_SLEEPMODE EM1
static inline CMU_Clock_TypeDef spi_get_clock_tree(spi_t *obj)
{
switch ((int)obj->spi.spi) {
@ -1188,7 +1186,7 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
spi_enable_event(obj, event, true);
// Set the sleep mode
blockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_lock_deep_sleep();
/* And kick off the transfer */
spi_master_transfer_dma(obj, tx, rx, tx_length, rx_length, (void*)handler, hint);
@ -1244,7 +1242,7 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
/* Wait transmit to complete, before user code is indicated*/
while(!(obj->spi.spi->STATUS & USART_STATUS_TXC));
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_unlock_deep_sleep();
/* return to CPP land to say we're finished */
return SPI_EVENT_COMPLETE;
} else {
@ -1262,7 +1260,7 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
/* disable interrupts */
spi_enable_interrupt(obj, (uint32_t)NULL, false);
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_unlock_deep_sleep();
/* Return the event back to userland */
return event;
}
@ -1370,7 +1368,7 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
/* Wait for transmit to complete, before user code is indicated */
while(!(obj->spi.spi->STATUS & USART_STATUS_TXC));
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_unlock_deep_sleep();
/* return to CPP land to say we're finished */
return SPI_EVENT_COMPLETE;
@ -1391,7 +1389,7 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
/* Wait for transmit to complete, before user code is indicated */
while(!(obj->spi.spi->STATUS & USART_STATUS_TXC));
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_unlock_deep_sleep();
/* Return the event back to userland */
return event;
@ -1433,7 +1431,7 @@ void spi_abort_asynch(spi_t *obj)
}
// Release sleep mode block
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_unlock_deep_sleep();
}
#endif

View File

@ -25,13 +25,12 @@
#include "us_ticker_api.h"
#include "device.h"
#include "mbed_assert.h"
#include "mbed_sleep.h"
#include "em_cmu.h"
#include "em_timer.h"
#include "clocking.h"
#include "sleep_api.h"
#include "sleepmodes.h"
#define TIMER_LEAST_ACTIVE_SLEEPMODE EM1
/**
* Timer functions for microsecond ticker.
* mbed expects a 32-bit timer. Since the EFM32 only has 16-bit timers,
@ -161,7 +160,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
if((US_TICKER_TIMER->IEN & TIMER_IEN_CC0) == 0) {
//Timer was disabled, but is going to be enabled. Set sleep mode.
blockSleepMode(TIMER_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_lock_deep_sleep();
}
TIMER_IntDisable(US_TICKER_TIMER, TIMER_IEN_CC0);
@ -218,7 +217,7 @@ void us_ticker_disable_interrupt(void)
{
if((US_TICKER_TIMER->IEN & TIMER_IEN_CC0) != 0) {
//Timer was enabled, but is going to get disabled. Clear sleepmode.
unblockSleepMode(TIMER_LEAST_ACTIVE_SLEEPMODE);
sleep_manager_unlock_deep_sleep();
}
/* Disable compare channel interrupts */
TIMER_IntDisable(US_TICKER_TIMER, TIMER_IEN_CC0);