• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)39 TINY_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)46 TINY_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)54 TINY_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)63 TINY_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)121 TINY_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)148 void GR551xPwrMgmtInit(void)
149 {
150     OsPmEnterHandlerSet(os_pm_enter_handler);
151 }
152