/* mbed Microcontroller Library ******************************************************************************* * Copyright (c) 2014, STMicroelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* */ #include "sleep_ex_api.h" #include "cmsis.h" extern VOID SleepCG(u8 Option, u32 SDuration, u8 ClkSourceEn, u8 SDREn); extern VOID DeepStandby(u8 Option, u32 SDuration, u8 GpioOption); extern VOID DeepSleep(u8 Option, u32 SDuration); SLEEP_WAKEUP_EVENT DStandbyWakeupEvent={0}; /** * @brief To make the system entering the Clock Gated power saving. * This function just make the system to enter the clock gated * power saving mode and pending on wake up event waitting. * The user application need to configure the peripheral to * generate system wake up event, like GPIO interrupt * , G-Timer timeout, etc. befor entering power saving mode. * * @param wakeup_event: A bit map of wake up event. Available event: * SLEEP_WAKEUP_BY_STIMER * SLEEP_WAKEUP_BY_GTIMER * SLEEP_WAKEUP_BY_GPIO_INT * SLEEP_WAKEUP_BY_WLAN * SLEEP_WAKEUP_BY_NFC * SLEEP_WAKEUP_BY_SDIO * SLEEP_WAKEUP_BY_USB * sleep_duration: the system sleep duration in ms, only valid * for SLEEP_WAKEUP_BY_STIMER wake up event. * * @retval None */ void sleep_ex(uint32_t wakeup_event, uint32_t sleep_duration) { u8 wake_ev=0; wake_ev = wakeup_event & 0xff; if (sleep_duration == 0) { wake_ev &= ~SLP_STIMER; } if (wake_ev == 0) { // error: No wakeup event, skip the entering sleep mode return; } SleepCG(wake_ev, sleep_duration, 0, 0); // same as old configuration: SCLK off & SDR no power off } /** * @brief To make the system entering the Clock Gated power saving. * This function just make the system to enter the clock gated * power saving mode and pending on wake up event waitting. * The user application need to configure the peripheral to * generate system wake up event, like GPIO interrupt * , G-Timer timeout, etc. befor entering power saving mode. * * @param wakeup_event: A bit map of wake up event. Available event: * SLEEP_WAKEUP_BY_STIMER * SLEEP_WAKEUP_BY_GTIMER * SLEEP_WAKEUP_BY_GPIO_INT * SLEEP_WAKEUP_BY_WLAN * SLEEP_WAKEUP_BY_NFC * SLEEP_WAKEUP_BY_SDIO * SLEEP_WAKEUP_BY_USB * sleep_duration: the system sleep duration in ms, only valid * for SLEEP_WAKEUP_BY_STIMER wake up event. * clk_sourec_enable: the option for SCLK on(1)/off(0) * sdr_enable: the option for turn off the SDR controller (1:off, 0:on) * * @retval None */ void sleep_ex_selective(uint32_t wakeup_event, uint32_t sleep_duration, uint32_t clk_sourec_enable, uint32_t sdr_enable) { u8 wake_ev=0; u8 sdr_en=0; u8 clk_source_en=0; wake_ev = wakeup_event & 0xff; sdr_en = sdr_enable & 0xff; clk_source_en = clk_sourec_enable & 0xff; if (sleep_duration == 0) { wake_ev &= ~SLP_STIMER; } if (wake_ev == 0) { // error: No wakeup event, skip the entering sleep mode return; } SleepCG(wake_ev, sleep_duration, clk_source_en, sdr_en); } /** * @brief To add a wake up event to wake up the system from the * deep standby power saving mode. * * @param wakeup_event: A bit map of wake up event. Available event: * STANDBY_WAKEUP_BY_STIMER * STANDBY_WAKEUP_BY_NFC * STANDBY_WAKEUP_BY_PA5 (GPIO) * STANDBY_WAKEUP_BY_PC7 (GPIO) * STANDBY_WAKEUP_BY_PD5 (GPIO) * STANDBY_WAKEUP_BY_PE3 (GPIO) * sleep_duration_ms: the system sleep duration in ms, only valid * for STANDBY_WAKEUP_BY_STIMER wake up event. * gpio_active: for a GPIO pin to wake up the system by * goes high(1) or low(0) * * @retval None */ void standby_wakeup_event_add(uint32_t wakeup_event, uint32_t sleep_duration_ms, uint32_t gpio_active) { u32 i; u8 gpio_event; u8 gpio_en; u8 gpio_act; if (wakeup_event & STANDBY_WAKEUP_BY_STIMER) { DStandbyWakeupEvent.wakeup_event |= DSTBY_STIMER; DStandbyWakeupEvent.timer_duration = sleep_duration_ms; } #if 0 if (wakeup_event & STANDBY_WAKEUP_BY_DS_TIMER) { DStandbyWakeupEvent.wakeup_event |= DSTBY_TIMER33; // TODO: Sleep Duration ? } #endif if (wakeup_event & STANDBY_WAKEUP_BY_NFC) { DStandbyWakeupEvent.wakeup_event |= DSTBY_NFC; } gpio_event = STANDBY_WAKEUP_BY_PA5; gpio_en = BIT0; gpio_act = BIT4; // Loop 4 to check 4 GPIO wake up event for (i=0;i<4;i++) { if (wakeup_event & gpio_event) { DStandbyWakeupEvent.wakeup_event |= DSTBY_GPIO; DStandbyWakeupEvent.gpio_option |= gpio_en; if (gpio_active) { // Active High DStandbyWakeupEvent.gpio_option |= gpio_act; } else { // Active Low DStandbyWakeupEvent.gpio_option &= ~gpio_act; } } gpio_event = gpio_event << 1; gpio_en = gpio_en << 1; gpio_act = gpio_act << 1; } } /** * @brief To delete a wake up event for wakeing up the system from the * deep standby power saving mode. * * @param wakeup_event: A bit map of wake up event. Available event: * STANDBY_WAKEUP_BY_STIMER * STANDBY_WAKEUP_BY_NFC * STANDBY_WAKEUP_BY_PA5 (GPIO) * STANDBY_WAKEUP_BY_PC7 (GPIO) * STANDBY_WAKEUP_BY_PD5 (GPIO) * STANDBY_WAKEUP_BY_PE3 (GPIO) * @retval None */ void standby_wakeup_event_del(uint32_t wakeup_event) { if (wakeup_event & STANDBY_WAKEUP_BY_STIMER) { DStandbyWakeupEvent.wakeup_event &= ~DSTBY_STIMER; } #if 0 if (wakeup_event & STANDBY_WAKEUP_BY_DS_TIMER) { DStandbyWakeupEvent.wakeup_event &= ~DSTBY_TIMER33; } #endif if (wakeup_event & STANDBY_WAKEUP_BY_NFC) { DStandbyWakeupEvent.wakeup_event &= ~DSTBY_NFC; } if (wakeup_event & STANDBY_WAKEUP_BY_PA5) { DStandbyWakeupEvent.gpio_option &= ~BIT0; } if (wakeup_event & STANDBY_WAKEUP_BY_PC7) { DStandbyWakeupEvent.gpio_option &= ~BIT1; } if (wakeup_event & STANDBY_WAKEUP_BY_PD5) { DStandbyWakeupEvent.gpio_option &= ~BIT2; } if (wakeup_event & STANDBY_WAKEUP_BY_PE3) { DStandbyWakeupEvent.gpio_option &= ~BIT3; } if ((DStandbyWakeupEvent.gpio_option & 0x0f) == 0) { // All GPIO wake up pin are disabled DStandbyWakeupEvent.wakeup_event &= ~DSTBY_GPIO; } } /** * @brief To make the system entering the Deep Standby power saving. * The CPU, memory and part fo peripheral power is off when * entering deep standby power saving mode. The program needs * to be reload from the flash at system resume. * * @retval None */ void deepstandby_ex(void) { if ((DStandbyWakeupEvent.wakeup_event & (DSTBY_STIMER|DSTBY_NFC|DSTBY_GPIO)) == 0) { // error: no wakeup event was added, so skip the entering standby power saving return; } DeepStandby(DStandbyWakeupEvent.wakeup_event, DStandbyWakeupEvent.timer_duration, DStandbyWakeupEvent.gpio_option); } /** * @brief To make the system entering the Deep Sleep power saving mode. * The CPU, memory and peripheral power is off when entering * deep sleep power saving mode. The program needs to be reload * and all peripheral needs be re-configure when system resume. * * @param wakeup_event: A bit map of wake up event. Available event: * DSLEEP_WAKEUP_BY_TIMER * DSLEEP_WAKEUP_BY_GPIO * sleep_duration: the system sleep duration in ms, only valid * for DSLEEP_WAKEUP_BY_TIMER wake up event. * * @retval None */ void deepsleep_ex(uint32_t wakeup_event, uint32_t sleep_duration) { u8 wake_ev=0; if ((wakeup_event & DSLEEP_WAKEUP_BY_TIMER) && (sleep_duration > 0)) { // wake up by timeout wake_ev |= DS_TIMER33; } if (wakeup_event & DSLEEP_WAKEUP_BY_GPIO) { // wake up by GPIO pin goes high wake_ev |= DS_GPIO; } if (wake_ev == 0) { // error: No wake up event, skip entering deep sleep mode return; } DeepSleep (wake_ev, sleep_duration); }