Adding deep power down support
authorNathael Pajani <nathael.pajani@ed3l.fr>
Mon, 3 Oct 2016 15:03:15 +0000 (17:03 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 8 Nov 2022 16:03:05 +0000 (17:03 +0100)
README
core/system.c
include/core/system.h

diff --git a/README b/README
index 7b548ff..808e6c7 100644 (file)
--- 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
index f8e6ecc..103c87e 100644 (file)
@@ -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)
 {
index 4f06c0f..e51bd23 100644 (file)
 /***************************************************************************** */
 /*                       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