/****************************************************************************** * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK") * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *****************************************************************************/ #ifndef DRIVERS_B91_DRIVER_EXT_EXT_PM_H_ #define DRIVERS_B91_DRIVER_EXT_EXT_PM_H_ #include #undef irq_enable #undef irq_disable #undef ARRAY_SIZE #include "../pm.h" #include "types.h" #include "ext_misc.h" #ifndef PM_32k_RC_CALIBRATION_ALGORITHM_EN #define PM_32k_RC_CALIBRATION_ALGORITHM_EN 1 #endif #define SYS_NEED_REINIT_EXT32K BIT(1) #define WAKEUP_STATUS_TIMER_CORE ( WAKEUP_STATUS_TIMER | WAKEUP_STATUS_CORE) #define WAKEUP_STATUS_TIMER_PAD ( WAKEUP_STATUS_TIMER | WAKEUP_STATUS_PAD) /** * @brief analog register below can store infomation when MCU in deepsleep mode * store your information in these ana_regs before deepsleep by calling analog_write function * when MCU wakeup from deepsleep, read the information by by calling analog_read function * Reset these analog registers only by power cycle */ #define DEEP_ANA_REG0 0x39 //initial value =0x00 #define DEEP_ANA_REG1 0x3a //initial value =0x00 #define DEEP_ANA_REG2 0x3b //initial value =0x00 #define DEEP_ANA_REG3 0x3c //initial value =0x00 #define DEEP_ANA_REG4 0x3d //initial value =0x00 #define DEEP_ANA_REG5 0x3e //initial value =0x00 #define DEEP_ANA_REG6 0x3f //initial value =0x0f /** * @brief these analog register can store data in deepsleep mode or deepsleep with SRAM retention mode. * Reset these analog registers by watchdog, chip reset, RESET Pin, power cycle */ #define DEEP_ANA_REG7 0x38 //initial value =0xff //ana3e system used, user can not use #define SYS_DEEP_ANA_REG PM_ANA_REG_POWER_ON_CLR_BUF0 #define cpu_set_gpio_wakeup pm_set_gpio_wakeup #define PM_MIN_SLEEP_US 1500 /* Eagle chip specific */ /** * @brief available wake-up source for customer */ typedef enum { //not available wake-up source for customer PM_TIM_RECOVER_START = BIT(14), PM_TIM_RECOVER_END = BIT(15), }pm_tim_recover_wakeup_src_e; typedef pm_sleep_mode_e SleepMode_TypeDef; typedef pm_sleep_wakeup_src_e SleepWakeupSrc_TypeDef; typedef int (*suspend_handler_t)(void); typedef void (*check_32k_clk_handler_t)(void); typedef unsigned int (*pm_get_32k_clk_handler_t)(void); typedef int (*cpu_pm_handler_t)(SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick); typedef unsigned int (*pm_tim_recover_handler_t)(unsigned int); extern cpu_pm_handler_t cpu_sleep_wakeup; extern suspend_handler_t func_before_suspend; extern check_32k_clk_handler_t pm_check_32k_clk_stable; extern pm_get_32k_clk_handler_t pm_get_32k_tick; extern pm_tim_recover_handler_t pm_tim_recover; /** * @brief gpio wakeup level definition */ typedef enum{ Level_Low=0, Level_High =1, }pm_gpio_wakeup_Level_e; /** * @brief deepsleep wakeup by external xtal */ typedef struct{ unsigned char ext_cap_en; //24xtal cap unsigned char pad32k_en; unsigned char pm_enter_en; unsigned char rsvd; }misc_para_t; extern _attribute_aligned_(4) misc_para_t blt_miscParam; /********************************** Internal APIs (not for user) ***************************************************/ extern unsigned char tl_24mrc_cal; extern unsigned int g_pm_tick_32k_calib; extern unsigned int g_pm_tick_cur; extern unsigned int g_pm_tick_32k_cur; extern unsigned char g_pm_long_suspend; extern unsigned int g_pm_multi_addr; extern unsigned int g_sleep_32k_rc_cnt; extern unsigned int g_sleep_stimer_tick; extern unsigned int ota_program_bootAddr; extern unsigned int ota_program_offset; /******************************** end of Internal APIs (not for user) **********************************************/ /** * @brief This function sets pm suspend handler. * @param[in] func - handler function. * @return none. */ void bls_pm_registerFuncBeforeSuspend(suspend_handler_t func); /** * @brief This function serves to set the working mode of MCU based on 32k crystal,e.g. suspend mode, deepsleep mode, deepsleep with SRAM retention mode and shutdown mode. * @param[in] sleep_mode - sleep mode type select. * @param[in] wakeup_src - wake up source select. * @param[in] wakeup_tick - the time of short sleep, which means MCU can sleep for less than 5 minutes. * @return indicate whether the cpu is wake up successful. */ int cpu_sleep_wakeup_32k_rc(SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick); /** * @brief This function serves to set the working mode of MCU based on 32k crystal,e.g. suspend mode, deepsleep mode, deepsleep with SRAM retention mode and shutdown mode. * @param[in] sleep_mode - sleep mode type select. * @param[in] wakeup_src - wake up source select. * @param[in] wakeup_tick - the time of short sleep, which means MCU can sleep for less than 5 minutes. * @return indicate whether the cpu is wake up successful. */ int cpu_sleep_wakeup_32k_xtal(SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick); /** * @brief This function serves to start sleep mode. * @param none. * @return none. */ void pm_sleep_start(void); /** * @brief This function serves to reboot chip. * @param none. * @return none. */ void start_reboot(void); /** * @brief This function serves to recover system timer from tick of internal 32k RC. * @param none. * @return none. */ unsigned int pm_tim_recover_32k_rc(unsigned int now_tick_32k); /** * @brief This function serves to recover system timer from tick of external 32k crystal. * @param none. * @return none. */ unsigned int pm_tim_recover_32k_xtal(unsigned int now_tick_32k); /** * @brief This function serves to get the 32k tick. * @param none * @return tick of 32k. */ extern unsigned int get_32k_tick(void); /** * @brief This function serves to get the 32k digital tick. * @param none * @return digital tick of 32k. */ unsigned int clock_get_digital_32k_tick(void); /** * @brief This function serves to determine whether external wakeup source to be used * @param[in] none. * @return none. */ static inline void blc_pm_set_extern_wakeup_recover(cpu_pm_handler_t wakeup, pm_tim_recover_handler_t recover) { cpu_sleep_wakeup = wakeup; pm_tim_recover = recover; blt_miscParam.pm_enter_en = 1; } /** * @brief This function serves to determine whether wake up source is internal 32k RC. * @param[in] none. * @return none. */ static inline void blc_pm_select_internal_32k_crystal(void) { cpu_sleep_wakeup = cpu_sleep_wakeup_32k_rc; pm_tim_recover = pm_tim_recover_32k_rc; blt_miscParam.pm_enter_en = 1; // allow enter pm, 32k rc does not need to wait for 32k clk to be stable } /** * @brief This function waits for 32K oscillator frequency stabilization. * @param[in] none. * @return none. */ extern void check_32k_clk_stable(void); /** * @brief This function serves to determine whether wake up source is external 32k RC. * @param[in] none. * @return none. */ static inline void blc_pm_select_external_32k_crystal(void) { cpu_sleep_wakeup = cpu_sleep_wakeup_32k_xtal; pm_check_32k_clk_stable = check_32k_clk_stable; pm_tim_recover = pm_tim_recover_32k_xtal; pm_get_32k_tick = get_32k_tick; blt_miscParam.pad32k_en = 1; // set '1': 32k clk src use external 32k crystal } /** * @brief This function servers to wake up the cpu from sleep mode. * @param[in] sleep_mode - sleep mode type select. * @param[in] wakeup_src - wake up source select. * @param[in] wakeup_tick - the time of sleep,unit is 31.25us,1ms = 32. * @return indicate whether the cpu is wake up successful. */ int cpu_long_sleep_wakeup_32k_rc(SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick); /** * @brief This function serves to determine whether mcu is waked up from deep retention. * @param[in] none. * @return 1- yes , 0- no. */ static inline int pm_is_MCU_deepRetentionWakeup(void) { return (g_pm_status_info.mcu_status & MCU_STATUS_DEEPRET_BACK); } /** * @brief This function serves to determine whether mcu is waked up by pad. * @param[in] none. * @return 1- yes , 0- no. */ static inline int pm_is_deepPadWakeup(void) { return g_pm_status_info.is_pad_wakeup; } /** * @brief This function serves to get the status of mcu. * @param[in] none. * @return mcu_status. */ static inline int pm_get_mcu_status(void) { return g_pm_status_info.mcu_status; } static inline unsigned int pm_get_latest_offset_cal_time(void) { return pmcd.offset_cal_tick; } #endif /* DRIVERS_B91_DRIVER_EXT_EXT_PM_H_ */