/** * @file pwrmgr.c * @author chipsea * @brief * @version 0.1 * @date 2020-11-30 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd. * @note */ #include "sdk_config.h" #include "rom_sym_def.h" #include "types.h" #include "ll_sleep.h" #include "cst92f2x.h" #include "string.h" #include "pwrmgr.h" #include "error.h" #include "gpio.h" #include "log.h" #include "clock.h" #include "jump_function.h" #include "rf_phy_driver.h" #if(CFG_SLEEP_MODE == PWR_MODE_NO_SLEEP) static uint8_t mPwrMode = PWR_MODE_NO_SLEEP; #elif(CFG_SLEEP_MODE == PWR_MODE_SLEEP) static uint8_t mPwrMode = PWR_MODE_SLEEP; #elif(CFG_SLEEP_MODE == PWR_MODE_PWROFF_NO_SLEEP) static uint8_t mPwrMode = PWR_MODE_PWROFF_NO_SLEEP; #else #error "CFG_SLEEP_MODE define incorrect" #endif //#define CFG_FLASH_ENABLE_DEEP_SLEEP #ifdef CFG_FLASH_ENABLE_DEEP_SLEEP #warning "CONFIG FLASH ENABLE DEEP SLEEP !!!" #endif typedef struct _pwrmgr_Context_t{ MODULE_e moudle_id; bool lock; pwrmgr_Hdl_t sleep_handler; pwrmgr_Hdl_t wakeup_handler; }pwrmgr_Ctx_t; static pwrmgr_Ctx_t mCtx[HAL_PWRMGR_TASK_MAX_NUM]; static uint32_t sramRet_config; static uint32_t s_config_swClk0 = DEF_CLKG_CONFIG_0; uint32_t s_config_swClk1 = DEF_CLKG_CONFIG_1; uint32_t s_gpio_wakeup_src_group1,s_gpio_wakeup_src_group2; int hal_pwrmgr_init(void) { memset(&mCtx, 0, sizeof(mCtx)); switch(mPwrMode){ case PWR_MODE_NO_SLEEP: case PWR_MODE_PWROFF_NO_SLEEP: disableSleep(); break; case PWR_MODE_SLEEP: enableSleep(); break; } return ERR_NONE; } int hal_pwrmgr_clk_gate_config(MODULE_e module) { if (module < MOD_CP_CPU) { s_config_swClk0 |= BIT(module); } else if (module < MOD_PCLK_CACHE) { s_config_swClk1 |= BIT(module - MOD_CP_CPU); } return ERR_NONE; } bool hal_pwrmgr_is_lock(MODULE_e mod) { int i; int ret = FALSE; if(mPwrMode == PWR_MODE_NO_SLEEP || mPwrMode == PWR_MODE_PWROFF_NO_SLEEP ){ return TRUE; } HAL_ENTER_CRITICAL_SECTION(); for(i = 0; i< HAL_PWRMGR_TASK_MAX_NUM; i++){ if(mCtx[i].moudle_id == MOD_NONE) break; if(mCtx[i].moudle_id == mod){ if(mCtx[i].lock == TRUE) ret = TRUE; break; } } HAL_EXIT_CRITICAL_SECTION(); return ret; } int hal_pwrmgr_lock(MODULE_e mod) { int i; int ret = ERR_NOT_REGISTED; if(mPwrMode == PWR_MODE_NO_SLEEP || mPwrMode == PWR_MODE_PWROFF_NO_SLEEP ){ disableSleep(); return ERR_NONE; } HAL_ENTER_CRITICAL_SECTION(); for(i = 0; i< HAL_PWRMGR_TASK_MAX_NUM; i++){ if(mCtx[i].moudle_id == MOD_NONE) break; if(mCtx[i].moudle_id == mod){ mCtx[i].lock = TRUE; disableSleep(); //LOG("LOCK\n"); ret = ERR_NONE; break; } } HAL_EXIT_CRITICAL_SECTION(); return ret; } int hal_pwrmgr_unlock(MODULE_e mod) { int i, cnt = 0; if(mPwrMode == PWR_MODE_NO_SLEEP || mPwrMode == PWR_MODE_PWROFF_NO_SLEEP ){ disableSleep(); return ERR_NONE; } HAL_ENTER_CRITICAL_SECTION(); for(i = 0; i< HAL_PWRMGR_TASK_MAX_NUM; i++){ if(mCtx[i].moudle_id == MOD_NONE) break; if(mCtx[i].moudle_id == mod){ mCtx[i].lock = FALSE; } if(mCtx[i].lock) cnt ++; } if(cnt == 0) enableSleep(); else disableSleep(); HAL_EXIT_CRITICAL_SECTION(); //LOG("sleep mode:%d\n", isSleepAllow()); return ERR_NONE; } ErrCode_t hal_pwrmgr_register(MODULE_e mod, pwrmgr_Hdl_t sleepHandle, pwrmgr_Hdl_t wakeupHandle) { int i; pwrmgr_Ctx_t* pctx = NULL; for(i = 0; i< HAL_PWRMGR_TASK_MAX_NUM; i++){ if(mCtx[i].moudle_id == mod) return ERR_INVALID_STATE; if(mCtx[i].moudle_id == MOD_NONE){ pctx = &mCtx[i]; break; } } if(pctx == NULL) return ERR_NO_MEM; pctx->lock = FALSE; pctx->moudle_id = mod; pctx->sleep_handler = sleepHandle; pctx->wakeup_handler = wakeupHandle; return ERR_NONE; } int hal_pwrmgr_unregister(MODULE_e mod) { int i; pwrmgr_Ctx_t* pctx = NULL; for(i = 0; i< HAL_PWRMGR_TASK_MAX_NUM; i++){ if(mCtx[i].moudle_id == mod){ pctx = &mCtx[i]; break; } if(mCtx[i].moudle_id == MOD_NONE){ return ERR_NOT_REGISTED; } } if(pctx == NULL) return ERR_NOT_REGISTED; HAL_ENTER_CRITICAL_SECTION(); memcpy(pctx, pctx+1, sizeof(pwrmgr_Ctx_t)*(HAL_PWRMGR_TASK_MAX_NUM-i-1)); HAL_EXIT_CRITICAL_SECTION(); return ERR_NONE; } int __attribute__((used)) hal_pwrmgr_wakeup_process(void) { int i; #ifdef CFG_FLASH_ENABLE_DEEP_SLEEP extern void spif_release_deep_sleep(void); spif_release_deep_sleep(); WaitRTCCount(8); #endif AP_PCR->SW_CLK = s_config_swClk0; AP_PCR->SW_CLK1 = s_config_swClk1|0x01;//force set M0 CPU s_gpio_wakeup_src_group1 = AP_AON->GPIO_WAKEUP_SRC[0]; s_gpio_wakeup_src_group2 = AP_AON->GPIO_WAKEUP_SRC[1]; //restore BB TIMER IRQ_PRIO NVIC_SetPriority((IRQn_Type)BB_IRQn, IRQ_PRIO_REALTIME); NVIC_SetPriority((IRQn_Type)TIM1_IRQn, IRQ_PRIO_HIGH); //ll_EVT NVIC_SetPriority((IRQn_Type)TIM2_IRQn, IRQ_PRIO_HIGH); //OSAL_TICK NVIC_SetPriority((IRQn_Type)TIM4_IRQn, IRQ_PRIO_HIGH); //LL_EXA_ADV for(i = 0; i< HAL_PWRMGR_TASK_MAX_NUM; i++){ if(mCtx[i].moudle_id == MOD_NONE){ return ERR_NOT_REGISTED; } if(mCtx[i].wakeup_handler) mCtx[i].wakeup_handler(); } return ERR_NONE; } int __attribute__((used)) hal_pwrmgr_sleep_process(void) { int i; hal_pwrmgr_RAM_retention_set(); //LOG("Sleep\n"); for(i = 0; i< HAL_PWRMGR_TASK_MAX_NUM; i++){ if(mCtx[i].moudle_id == MOD_NONE){ //return ERR_NOT_REGISTED; //found last module break; } if(mCtx[i].sleep_handler) mCtx[i].sleep_handler(); } #ifdef CFG_FLASH_ENABLE_DEEP_SLEEP extern void spif_set_deep_sleep(void); spif_set_deep_sleep(); #endif return ERR_NONE; } /************************************************************************************** * @fn hal_pwrmgr_RAM_retention * * @brief This function process for enable retention sram * * input parameters * * @param uint32_t sram: sram bit map * * output parameters * * @param None. * * @return refer error.h. **************************************************************************************/ int hal_pwrmgr_RAM_retention(uint32_t sram) { if(sram & 0xffffffe0) { sramRet_config = 0x00; return ERR_INVALID_PARAM; } sramRet_config = sram; return ERR_NONE; } int hal_pwrmgr_RAM_retention_clr(void) { subWriteReg(0x4000f01c,21,17,0x00); return ERR_NONE; } int hal_pwrmgr_RAM_retention_set(void) { subWriteReg(0x4000f01c,21,17,sramRet_config); return ERR_NONE; } int hal_pwrmgr_LowCurrentLdo_enable(void) { subWriteReg(0x4000f014,26,26, 1); return ERR_NONE; } int hal_pwrmgr_LowCurrentLdo_disable(void) { subWriteReg(0x4000f014,26,26, 0); return ERR_NONE; } extern void gpio_wakeup_set(GpioPin_t pin, gpio_polarity_e type); extern void gpio_pull_set(GpioPin_t pin, gpio_pupd_e type); extern void GpioSleepHandler(void); __attribute__((section("_section_standby_code_"))) void hal_pwrmgr_poweroff(pwroff_cfg_t* pcfg, uint8_t wakeup_pin_num) { HAL_ENTER_CRITICAL_SECTION(); subWriteReg(0x4000f01c,6,6,0x00); //disable software control GpioSleepHandler(); for(uint8_t i=0; iSLEEP_R[0] = 2; // write_reg(0x4000f000,0x5a5aa5a5); enter_sleep_off_mode(SYSTEM_OFF_MODE); while(1); } __attribute__((section("_section_standby_code_"))) void hal_pwrmgr_enter_sleep_rtc_reset(uint32_t sleepRtcTick) { HAL_ENTER_CRITICAL_SECTION(); subWriteReg(0x4000f01c,6,6,0x00); //disable software control config_RTC(sleepRtcTick); // clear sram0 and sram1 retention // hal_pwrmgr_RAM_retention_clr(); subWriteReg(0x4000f01c,21,17,0x04); /** config reset casue as RSTC_WARM_NDWC reset path walkaround dwc */ AON_CLEAR_XTAL_TRACKING_AND_CALIB; AP_AON->SLEEP_R[0]=4; enter_sleep_off_mode(SYSTEM_SLEEP_MODE); while(1) {}; } #define STANDBY_WAIT_MS(a) WaitRTCCount((a)<<5) // 32us * 32 around 1ms __attribute__((section("_section_standby_code_"))) pwroff_cfg_t s_pwroff_cfg[WAKEUP_PIN_MAX]; __attribute__((section("_section_standby_code_"))) __attribute__((used)) uint8 pwroff_register_number=0; __attribute__((section("_section_standby_code_"))) void wakeupProcess_standby(void) { subWriteReg(0x4000f014,29,27,0x07); STANDBY_WAIT_MS(5); #ifdef CFG_FLASH_ENABLE_DEEP_SLEEP extern void spif_release_deep_sleep(void); spif_release_deep_sleep(); STANDBY_WAIT_MS(15); #endif uint32_t volatile cnt=0; uint8_t volatile find_flag=0; uint8 pin_n=0; extern bool gpio_read(GpioPin_t pin); for(pin_n=0; pin_n(s_pwroff_cfg[pin_n].on_time>>5)) { write_reg(0x4000f030, 0x01); break; } } else hal_pwrmgr_enter_standby(&s_pwroff_cfg[0],pwroff_register_number); } JUMP_FUNCTION(WAKEUP_PROCESS) = 0; wakeupProcess0(); // set_sleep_flag(0); // HAL_ENTER_CRITICAL_SECTION(); // AP_PCR->SW_RESET1 = 0; // while(1); } extern void gpio_wakeup_set(GpioPin_t pin, gpio_polarity_e type); extern void gpio_pull_set(GpioPin_t pin, gpio_pupd_e type); __attribute__((section("_section_standby_code_"))) void hal_pwrmgr_enter_standby(pwroff_cfg_t* pcfg,uint8_t wakeup_pin_num) { HAL_ENTER_CRITICAL_SECTION(); subWriteReg(0x4000f01c,6,6,0x00); //disable software control,Hardware automatically controls power on/off of 32M RCOSC, 32K RCOSC, 32K XOSC, Bandgap, DIGLDO, LCLDO, RTC, LPCMP. uint8_t i = 0; if(wakeup_pin_num>WAKEUP_PIN_MAX) { wakeup_pin_num=WAKEUP_PIN_MAX; } GpioSleepHandler(); pwroff_register_number = wakeup_pin_num; for(i = 0; i < wakeup_pin_num; i++) { if(pcfg[i].type==POL_FALLING) gpio_pull_set(pcfg[i].pin,GPIO_PULL_UP_S); else gpio_pull_set(pcfg[i].pin,GPIO_PULL_DOWN); gpio_wakeup_set(pcfg[i].pin, pcfg[i].type); osal_memcpy(&s_pwroff_cfg[i],&(pcfg[i]),sizeof(pwroff_cfg_t)); } JUMP_FUNCTION(WAKEUP_PROCESS)= (uint32_t)&wakeupProcess_standby; #ifdef CFG_FLASH_ENABLE_DEEP_SLEEP extern void spif_set_deep_sleep(void); spif_set_deep_sleep(); WaitRTCCount(50); #endif subWriteReg(0x4000f014,29,27,0); set_sleep_flag(1); AP_AON->SLEEP_R[0] = 2; subWriteReg(0x4000f01c,21,17,sramRet_config); enter_sleep_off_mode(SYSTEM_SLEEP_MODE); while(1); }