From b32910bdb85c6e9d19abf97f1465c573a0bf9d38 Mon Sep 17 00:00:00 2001
From: zhangbo <zhangbo@qq.com>
Date: 星期四, 13 二月 2025 14:06:13 +0800
Subject: [PATCH] 测试版

---
 keil/include/drivers/mk_power.c |  163 +++++++++++++++++++++++++++++-------------------------
 1 files changed, 87 insertions(+), 76 deletions(-)

diff --git a/keil/include/drivers/mk_power.c b/keil/include/drivers/mk_power.c
index d5f84b8..023a558 100644
--- a/keil/include/drivers/mk_power.c
+++ b/keil/include/drivers/mk_power.c
@@ -77,19 +77,26 @@
 #include "mk_i2c.h"
 #endif
 
-#ifndef LOW_POWER_CLOCK_PPM
-#define LOW_POWER_CLOCK_PPM (50)
-#endif
-
 #ifndef SYS_CLK_SOURCE
 #define SYS_CLK_SOURCE CLOCK_62P4M_XTAL38P4M_TO_SYS_CLK
 #endif
 
-// Including 38.4MHz clock PLL ready time and application recovery time, unit: us
-#define RECOVERY_TIME_FROM_LOW_POWER (1000)
+/** XTAL32K clock source ppm */
+#ifndef LOW_POWER_CLOCK_PPM
+#define LOW_POWER_CLOCK_PPM (100)
+#endif
 
-// Considering 32KHz clock ppm and sleep time, x = sleep time (us), the result should < PHY_SLEEP_TIME_US_MIN
-#define WAKEUP_IN_ADVANCE_TIME(x) (RECOVERY_TIME_FROM_LOW_POWER + (x)*LOW_POWER_CLOCK_PPM / 1000000)
+/** RCO32K clock source ppm */
+#ifndef LOW_POWER_CLOCK_PPM_RCO
+#define LOW_POWER_CLOCK_PPM_RCO (1000)
+#endif
+
+// Including 38.4MHz clock PLL ready time and application recovery time, unit: 32768Hz tick. 32tick ~= 1ms
+#define RECOVERY_TIME_FROM_LOW_POWER (32)
+
+// Considering 32KHz clock ppm and power down time, x = low power ticks to power down ( unit: 32768 tick)
+#define WAKEUP_IN_ADVANCE_TIME(x) \
+    (x - (RECOVERY_TIME_FROM_LOW_POWER + (x) * ((SYSCON->SYS_CMU & SYSCON_SYS_CMU_32K_CLK_SEL_MSK) ? LOW_POWER_CLOCK_PPM : LOW_POWER_CLOCK_PPM_RCO) / 1000000))
 
 #ifdef UWB_EN
 extern uint32_t slp_cnt;
@@ -130,8 +137,8 @@
     }
     else
     {
-        // enable PMU, disable Xtal32k
-        SYSCON->PMU_CTRL0 |= (1U << 31) | (1 << 7);
+        // enable PMU
+        SYSCON->PMU_CTRL0 |= (1U << 31);
     }
 
     // DG REF from LP_BG
@@ -262,12 +269,11 @@
     NVIC_ClearPendingIRQ(WAKEUP_IRQn);
     NVIC_EnableIRQ(WAKEUP_IRQn);
 
-    // flash power down  - by flash_close()
-    flash_power_down(FLASH_ID0);
-
     uint8_t val = REG_READ_BYTE(EFUSE_SHADOW_BASE + 0x67);
     if ((val & 0x80) == 0)
     {
+        // flash power down  - by flash_close()
+        flash_power_down(FLASH_ID0);
         // switch to external flash io
         REG_WRITE_BYTE(EFUSE_SHADOW_BASE + 0x67, val | 0x80);
     }
@@ -287,6 +293,7 @@
     SYSCON->IO_SLP_PUP[0] = SYSCON->IO_PUP[0];
     SYSCON->IO_SLP_PUP[1] = SYSCON->IO_PUP[1];
     SYSCON->IO_SLP_PUP[2] = SYSCON->IO_PUP[2];
+    // SYSCON->IO_SLP_AEN |= (1U << 31);
 
     // reduce DG current 60%
     SYSCON->CAP_DIV_CFG = 0x0;
@@ -304,26 +311,27 @@
     // Clock on - CALIB
     SYSCON->SYS_CMU |= (1U << CLOCK_CALIB);
 
+    SYSCON->CAP_DIV_CFG = 0x7;
+
     if ((val & 0x80) == 0)
     {
         // switch to internal flash io
         REG_WRITE_BYTE(EFUSE_SHADOW_BASE + 0x67, val & 0x7f);
+        // flash power up
+        flash_power_up(FLASH_ID0);
     }
-
-    SYSCON->CAP_DIV_CFG = 0x7;
-
-    // flash power up
-    flash_power_up(FLASH_ID0);
 
 #ifdef XIP_EN
     flash_open_for_xip(FLASH_ID0);
 #endif
+
     NVIC_DisableIRQ(WAKEUP_IRQn);
     NVIC_ClearPendingIRQ(WAKEUP_IRQn);
 
     // Restore IO
     GPIO->DATAOUT = SYSCON->IO_SLP_OUT;
     GPIO->OUTENSET = SYSCON->IO_SLP_OE;
+    // SYSCON->IO_SLP_AEN &= ~(1U << 31);
 
 #ifdef SWD_WAKEUP_EN
     // power_swd_restore();
@@ -402,7 +410,7 @@
         SYSCON->PMU_CTRL1 &= ~((1U << 7) | (1U << 5));
     }
 
-    // switch system clock from XTAL to RO
+    // switch system clock from XTAL_38M4 to RO_48M
     clock_attach(CLOCK_48M_RO_TO_SYS_CLK);
 
     // for XIP
@@ -422,7 +430,7 @@
     // REFPLL - ON
     SYSCON->PMU_CTRL0 &= ~(1U << 10);
 
-    // switch system clock from RO to XTAL
+    // switch system clock from RO_48M to XTAL_38M4
     clock_attach(SYS_CLK_SOURCE);
 
 #ifdef UWB_EN
@@ -594,61 +602,68 @@
 }
 
 #ifdef UWB_EN
+/*
+ *  nextExpiration can also be zero for an active timer, as said in WsfTimerNextExpiration's brief.
+ *  But we are calling this WsfTimerNextExpiration with
+ *    1. disabling global interrupt at first, (at the beginning of power_manage())
+ *    2. then checking WSF_TIMER_EVENT is not set (POWER_UNIT_OS is cleared for all power modes).
+ *  So here nextExpiration can not be zero for an active wsf timer.
+ */
+static uint32_t os_timer_tick_left(void)
+{
+    uint32_t left = UINT32_MAX;
+
+#ifdef WSF_EN
+    uint32_t nextExpiration = WsfTimerNextExpiration();
+
+    if (nextExpiration != UINT32_MAX)
+    {
+        uint32_t elapsed_ticks = sys_tick_elapse_ticks();
+        if (nextExpiration > elapsed_ticks)
+            left = nextExpiration - elapsed_ticks;
+        else
+            left = 0;
+    }
+#endif
+    return left;
+}
+
+#ifdef WSF_EN
+static wsfTimer_t phy_pd_ctrl_timer = {
+    .msg =
+        {
+            .event = PHY_PD_TIMER_EVENT,
+        },
+};
+#endif
+
 static void power_check_uwb_power_mode(void)
 {
-    enum POWER_MODE_T pm;
-    // check os timer
-    uint32_t os_time_ms = PHY_SLEEP_TIME_MS_MAX;
-    uint32_t phy_time_us = PHY_SLEEP_TIME_MS_MAX * 1000;
+    enum POWER_MODE_T pm = POWER_MODE_SLEEP;
 
-#ifdef WSF_EN
-    if (wsfOsReadyToSleep())
+    // power_check_if_power_mode() may request active or sleep mode, then abort here
+    if ((false == mac_is_busy()) && (power_env.power_request[POWER_MODE_SLEEP] == 0))
     {
-        pm = WsfTimerSleepCheck(&os_time_ms);
-
-        if (pm)
+        uint32_t pd_tick = phy_timer_lp_tick_left();
+        if (pd_tick != UINT32_MAX)
         {
-#endif
-            uint8_t busy = mac_is_busy();
-            if (busy)
-            {
-                pm = POWER_MODE_SLEEP;
-            }
-            else
-            {
-                if (phy_timer_is_programmed())
-                {
-                    // check phy timer
-                    uint32_t phy_time_tick = phy_timer_count_left();
-                    phy_time_us = PHY_TIMER_COUNT_TO_US(phy_time_tick);
-                }
+            pd_tick += sys_tick_elapse_ticks();
+            WsfTimerStartTick(&phy_pd_ctrl_timer, pd_tick, WSF_TIMER_ONE_SHOT);
+        }
 
-                // sleep time
-                uint32_t sleep_time_us = MIN((uint32_t)(os_time_ms * 1000), (uint32_t)phy_time_us);
-
-                if (sleep_time_us > PHY_SLEEP_TIME_US_MIN)
-                {
-                    pm = POWER_MODE_POWER_DOWN;
-                    // make sure wakeup in advance, need to correct by 32K ppm
-                    sleep_time_us -= WAKEUP_IN_ADVANCE_TIME(sleep_time_us);
-
-                    uint32_t sleep_time_tick = __US_TO_32K_CNT(sleep_time_us);
-
-                    sleep_timer_start(sleep_time_tick);
-                }
-                else
-                {
-                    pm = POWER_MODE_SLEEP;
-                }
-            }
-#ifdef WSF_EN
+        pd_tick = os_timer_tick_left();
+        if (pd_tick > POWER_DOWN_TIME_TICK_MIN)
+        {
+            pm = POWER_MODE_POWER_DOWN;
+            // make sure wakeup in advance, need to correct by 32K ppm
+            sleep_timer_start(WAKEUP_IN_ADVANCE_TIME(pd_tick));
+        }
+        else if (pd_tick == UINT32_MAX)
+        {
+            pm = POWER_MODE_DEEP_POWER_DOWN;
         }
     }
-    else
-    {
-        pm = POWER_MODE_ACTIVE;
-    }
-#endif
+
     power_mode_request(POWER_UNIT_UWB, pm);
 }
 #endif
@@ -660,6 +675,8 @@
 
     // check GPIO wakeup source
     power_check_io_power_mode();
+    // check interface wakeup source
+    power_check_if_power_mode();
 
     if (power_env.power_request[POWER_MODE_ACTIVE])
     {
@@ -670,13 +687,7 @@
 #ifdef UWB_EN
         power_check_uwb_power_mode();
 #endif
-        power_check_if_power_mode();
-
-        if (power_env.power_request[POWER_MODE_ACTIVE])
-        {
-            // stay in active mode
-        }
-        else if (power_env.power_request[POWER_MODE_SLEEP])
+        if (power_env.power_request[POWER_MODE_SLEEP])
         {
             // enter sleep mode
             power_enter_sleep_mode();
@@ -702,13 +713,13 @@
             power_enter_shelf_mode();
         }
 
-        power_clear_if_power_mode();
 #ifdef UWB_EN
         power_mode_clear(POWER_UNIT_UWB);
 #endif
     }
 
-    // uint32_t int_pending = REG_READ(0xE000E200);
+    power_clear_if_power_mode();
+
     int_unlock(lock);
 
     if (wakeup_from_power_down)

--
Gitblit v1.9.3