1 /* 2 * Copyright (c) 2021 GOODIX. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "gr55xx.h" 17 #include "gr55xx_pwr.h" 18 #include "gr55xx_sys.h" 19 20 #include "gr55xx_ll_pwr.h" 21 22 #include "los_pm.h" 23 #include "los_timer.h" 24 #include "los_tick.h" 25 #include "los_task.h" 26 #include "los_sched.h" 27 28 #include "los_port_pm.h" 29 30 #define TICK_MS_IN_HUS (2000) 31 #define SYS_BLE_SLEEP_ALGO_HUS (580) 32 #define SLP_WAKUP_ALGO_LP_CNT (32) 33 #define DEEPSLEEP_TIME_MIN_MS (5) 34 35 static uint64_t g_tickTimerBaseBeforeSleep = 0; 36 static uint32_t g_lpCntWhenTickStop = 0; 37 static uint32_t g_lpCntWhenTickReload = 0; 38 os_sleep_ms_get(void)39TINY_RAM_SECTION uint32_t os_sleep_ms_get(void) 40 { 41 g_tickTimerBaseBeforeSleep = OsGetCurrSchedTimeCycle(); 42 return ((uint32_t)(OsSchedGetNextExpireTime(g_tickTimerBaseBeforeSleep) - g_tickTimerBaseBeforeSleep)) / 43 OS_CYCLE_PER_TICK; 44 } 45 sys_tick_reload(void)46TINY_RAM_SECTION void sys_tick_reload(void) 47 { 48 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; 49 SysTick->LOAD = (UINT32)((OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND) - 1UL); 50 SysTick->VAL = 0UL; 51 SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk); 52 } 53 pwr_mgmt_sleep_dur_limit(uint32_t sleepMs)54TINY_RAM_SECTION static void pwr_mgmt_sleep_dur_limit(uint32_t sleepMs) 55 { 56 uint32_t sleepHus = sleepMs * TICK_MS_IN_HUS - SYS_BLE_SLEEP_ALGO_HUS; 57 if (get_remain_sleep_dur() > sleepHus) { 58 pwr_mgmt_ble_wakeup(); 59 } 60 sys_ble_heartbeat_period_set(sleepHus); 61 } 62 pwr_mgmt_enter_sleep_with_cond(uint32_t sleepMs)63TINY_RAM_SECTION static void pwr_mgmt_enter_sleep_with_cond(uint32_t sleepMs) 64 { 65 pwr_mgmt_sleep_dur_limit(sleepMs); 66 67 uint32_t intSave = LOS_IntLock(); 68 69 if (DEVICE_BUSY == pwr_mgmt_dev_suspend()) { 70 ultra_wfi(); 71 LOS_IntRestore(intSave); 72 return; 73 } 74 75 if (PMR_MGMT_SLEEP_MODE != pwr_mgmt_mode_get()) { 76 LOS_IntRestore(intSave); 77 return; 78 } 79 80 pwr_mgmt_mode_t bleState = pwr_mgmt_baseband_state_get(); 81 switch (bleState) { 82 case PMR_MGMT_IDLE_MODE: 83 ultra_wfi(); 84 case PMR_MGMT_ACTIVE_MODE: 85 LOS_IntRestore(intSave); 86 return; 87 } 88 89 g_lpCntWhenTickStop = ll_pwr_get_comm_sleep_duration(); 90 91 pwr_mgmt_save_context(); 92 93 if (pwr_mgmt_get_wakeup_flag() == COLD_BOOT) { 94 if (PMR_MGMT_IDLE_MODE == pwr_mgmt_shutdown()) { 95 ultra_wfi(); 96 LOS_IntRestore(intSave); 97 return; 98 } 99 LOS_IntRestore(intSave); 100 } else { 101 pwr_mgmt_set_wakeup_flag(COLD_BOOT); 102 103 uint32_t intSaveLocal = LOS_IntLock(); 104 105 g_lpCntWhenTickReload = ll_pwr_get_comm_sleep_duration(); 106 sys_tick_reload(); 107 108 uint32_t sleepLpCycles = g_lpCntWhenTickReload - g_lpCntWhenTickStop + SLP_WAKUP_ALGO_LP_CNT; 109 uint32_t lpCycles2HusErr = 0; 110 uint32_t sleepHus = sys_lpcycles_2_hus(sleepLpCycles, &lpCycles2HusErr); 111 uint32_t sleepSystick = sleepHus * (OS_CYCLE_PER_TICK / TICK_MS_IN_HUS); 112 113 OsTickTimerBaseReset(g_tickTimerBaseBeforeSleep + sleepSystick); 114 LOS_SchedTickHandler(); 115 116 LOS_IntRestore(intSaveLocal); 117 warm_boot_second(); 118 } 119 } 120 os_pm_enter_handler(void)121TINY_RAM_SECTION static void os_pm_enter_handler(void) 122 { 123 uint32_t intSave = LOS_IntLock(); 124 125 if ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk)) { 126 LOS_IntRestore(intSave); 127 return; 128 } 129 130 uint32_t sleepMs = os_sleep_ms_get(); 131 LOS_IntRestore(intSave); 132 133 if (sleepMs < DEEPSLEEP_TIME_MIN_MS) { 134 ultra_wfi(); 135 return; 136 } 137 138 if (PMR_MGMT_SLEEP_MODE != pwr_mgmt_mode_get()) { 139 ultra_wfi(); 140 return; 141 } 142 143 LOS_TaskLock(); 144 pwr_mgmt_enter_sleep_with_cond(sleepMs); 145 LOS_TaskUnlock(); 146 } 147 GR551xPwrMgmtInit(void)148void GR551xPwrMgmtInit(void) 149 { 150 OsPmEnterHandlerSet(os_pm_enter_handler); 151 } 152