From 9ea9237ea525a73da7da23f7017e4a87cbe2f390 Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Mon, 3 Oct 2016 17:03:15 +0200 Subject: [PATCH] Adding deep power down support --- README | 1 + core/system.c | 38 ++++++++++++++++++++++++++++++++++++++ include/core/system.h | 27 +++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/README b/README index 7b548ff..808e6c7 100644 --- a/README +++ b/README @@ -70,6 +70,7 @@ SUPPORTED FEATURES and INTERFACES - systick - precise msleep and usleep functions (using systick) - pio configuration + - deep power down - Simple C Library - memcpy and memset diff --git a/core/system.c b/core/system.c index f8e6ecc..103c87e 100644 --- a/core/system.c +++ b/core/system.c @@ -127,6 +127,44 @@ void enter_deep_sleep(void) /* FIXME */ } +/* Enter deep power down. + * NOTE : entering deep power down implies a lot of side effects. I'll try to list them all here + * so this can be done right. + * - The device watchdog must not have deep power-down locked. + * + * Note : see remark about RTC and deep sleep in section 5.3.3 of UM10441 + */ +void enter_deep_power_down(void) +{ + struct lpc_sys_config* sys_config = LPC_SYS_CONFIG; + struct syst_ctrl_block_regs* scb = LPC_SCB; + struct lpc_pm_unit* pmu = LPC_PMU; + + /* Clear deep power down flag */ + pmu->power_ctrl |= LPC_DPD_FLAG; + + /* Ask for the same clock status when waking up */ + sys_config->powerdown_wake_cfg = sys_config->powerdown_run_cfg; + + /* Set power-down sleep config : Turn Watchdog and BOD off when entering deep power down */ + sys_config->powerdown_sleep_cfg = 0xFFFF; + /* Switch to low-speed WDO */ + sys_config->main_clk_sel = LPC_MAIN_CLK_SRC_IRC_OSC; + sys_config->main_clk_upd_en = 0; + sys_config->main_clk_upd_en = 1; + while (!(sys_config->main_clk_upd_en & 0x01)); + + /* Enter deep power-down on next wfi() call */ + pmu->power_ctrl |= LPC_PD_EN; + scb->scr |= SCB_SCR_SLEEPDEEP; + + /* Power down everything but the IRC and Flash */ + sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_IRC_OUT | LPC_POWER_DOWN_IRC | LPC_POWER_DOWN_FLASH); + + /* "wfi" instruction to enter deep power-down */ + wfi(); +} + /* Power on or off a subsystem */ void subsystem_power(uint32_t power_bit, uint32_t on_off) { diff --git a/include/core/system.h b/include/core/system.h index 4f06c0f..e51bd23 100644 --- a/include/core/system.h +++ b/include/core/system.h @@ -35,26 +35,45 @@ /***************************************************************************** */ /* Power up defaults */ /***************************************************************************** */ -/* Change reset power state to our default, removing power from unused - * interfaces */ +/* Change reset power state to our default, removing power from unused interfaces */ void system_set_default_power_state(void); + /***************************************************************************** */ /* Power */ /***************************************************************************** */ +/* Enter deep sleep. + * NOTE : entering deep sleep implies a lot of side effects. I'll try to list them all here + * so this can be done right. + * + * Note : see remark about RTC and deep sleep in section 5.3.3 of UM10441 + */ void enter_deep_sleep(void); +/* Enter deep power down. + * NOTE : entering deep power down implies a lot of side effects. I'll try to list them all here + * so this can be done right. + * - The device watchdog must not have deep power-down locked. + * + * There are only two ways to get out of deep power down : RTC interrupt and wakeup pin going low. + * Even RESET pin won't get the chip out of power down. + */ +void enter_deep_power_down(void); + + /* Power on or off a subsystem */ void subsystem_power(uint32_t power_bit, uint32_t on_off); /* Check whether a subsystem is powered or not */ uint8_t subsystem_powered(uint32_t power_bit); + /* Configure the brown-out detection. * Note: Brown-Out detection must be powered to operate the ADC (See Section 19.2 * of UM10441 revision 2.1 or newer for more information) */ void system_brown_out_detection_config(uint32_t level); + /***************************************************************************** */ /* System Clock */ /***************************************************************************** */ @@ -264,6 +283,10 @@ struct lpc_pm_unit }; #define LPC_PMU ((struct lpc_pm_unit *) LPC_PMU_BASE) +/* Power control register */ +#define LPC_PD_EN (0x01 << 1) +#define LPC_SLEEP_FLAG (0x01 << 8) +#define LPC_DPD_FLAG (0x01 << 11) /* System config register */ #define LPC_WAKEUP_PIN_HYST_MASK (0x01 << 10) #define LPC_RTC_CLK_SRC_SHIFT 11 -- 2.43.0