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