#include "include.h" #include "app_variable.h" bool power_off_check(void); void lock_code_pwrsave(void); void unlock_code_pwrsave(void); AT(.com_text.sleep) void en_auto_pwroff(void) { SysVariable.pwroff_delay = SysVariable.pwroff_time; } AT(.com_text.sleep) void dis_auto_pwroff(void) { SysVariable.pwroff_delay = -1L; } AT(.com_text.sleep) void reset_pwroff_delay(void) { if(SysVariable.pwroff_delay != -1L) {SysVariable.pwroff_delay = SysVariable.pwroff_time;} } AT(.com_text.sleep) void reset_sleep_delay(void) { SysVariable.sleep_delay = SysVariable.sleep_time; } AT(.com_text.sleep) void reset_guioff_delay(void) { SysVariable.guioff_delay = SysVariable.sleep_time; } AT(.com_text.sleep) void reset_sleep_delay_all(void) { {SysVariable.sleep_delay = SysVariable.sleep_time; SysVariable.guioff_delay = SysVariable.sleep_time;} } AT(.com_text.sleep) void reset_sleep_delay_message_display(void) { SysVariable.sleep_delay = 5 * 10; // unit:100ms SysVariable.guioff_delay = 5 * 10; // unit:100ms } AT(.com_text.sleep) void lowpwr_tout_ticks(void) { if(SysVariable.sleep_delay != -1L && SysVariable.sleep_delay > 0) { SysVariable.sleep_delay--; } if(SysVariable.guioff_delay != -1L && SysVariable.guioff_delay > 0) { SysVariable.guioff_delay--; } if(SysVariable.pwroff_delay != -1L && SysVariable.pwroff_delay > 0) { SysVariable.pwroff_delay--; } } AT(.com_text.sleep) bool sys_sleep_check(u32 *sleep_time) { u32 co_min = co_timer_get_min_time(true)*2; if(*sleep_time > co_min) { *sleep_time = co_min; } if(*sleep_time == 0){ *sleep_time = 1; } if(*sleep_time > SysVariable.sleep_wakeup_time) { *sleep_time = SysVariable.sleep_wakeup_time; return true; } return false; } bool adpll_is_sleep(void) { return sleep_cb.adpll_is_sleep; } AT(.sleep_text.sleep) void sys_sleep_cb(u8 lpclk_type) { //注意!!!!!!!!!!!!!!!!! //此函数只能调用sleep_text或com_text函数 //此处关掉影响功耗的模块 u32 gpiogde = GPIOGDE; GPIOGDE = BIT(2) | BIT(4); //SPICS, SPICLK sys_enter_sleep(lpclk_type); //enter sleep //唤醒后,恢复模块功能 GPIOGDE = gpiogde; } //休眠定时器,500ms进一次 AT(.sleep_text.sleep) uint32_t sleep_timer(void) { uint32_t ret = 0; SysVariable.sleep_counter++; if (SysVariable.sleep_counter == 10) { SysVariable.sleep_counter = 0; #if LPWR_WARNING_VBAT u32 rtccon8 = RTCCON8; #if CHARGE_VOL_DYNAMIC_DET if (RTCCON & BIT(20)) { //vusb is online? RTCCON8 |= BIT(1); //charge stop delay_5ms(2); } #endif saradc_init(); saradc_adc15_analog_channel_sleep(); delay_us(600); saradc_kick_start(0, 0); while(!bsp_saradc_process(0)); sys_cb.vbat = bsp_vbat_get_voltage(1); RTCCON8 = rtccon8; saradc_exit(); #endif } #if CHARGE_EN if (xcfg_cb.charge_en) { charge_detect(0); } #endif // CHARGE_EN SysVariable.sleep_wakeup_time = -1L; if(SysVariable.pwroff_delay != -1L) { if(SysVariable.pwroff_delay > 5) { SysVariable.pwroff_delay -= 5; } else { SysVariable.pwroff_delay = 0; return 1; } } if ((PWRKEY_2_HW_PWRON) && (!IS_PWRKEY_PRESS())){ ret = 1; } rtc_sleep_process(); return ret; } AT(.text.lowpwr.sleep) static void sfunc_sleep(void) { uint32_t status, ret; uint32_t usbcon0, usbcon1; u8 pa_de, pb_de, pe_de, pf_de, pg_de; u16 adc_ch; uint32_t sysclk; u32 wkie, wkpnd; bool wko_wkup_flag; bool gui_need_wkp = false; #if LE_EN u16 interval = 0; u16 latency = 0; u16 tout = 0; u16 adv_interval = 0; #endif printf("%s\n", __func__); sleep_cb.sys_is_sleep = true; sys_cb.wkp_flag = false; sys_cb.charge_sta = false; sys_cb.ble_flag = false; sys_cb.raise_hand = false; sys_cb.rtc_flag = false; bt_enter_sleep(); #if LE_EN adv_interval = ble_get_adv_interval(); ble_set_adv_interval(800); //interval: 500 * 0.625ms = 500ms if (ble_is_connect()) { //ble已连接 interval = ble_get_conn_interval(); latency = ble_get_conn_latency(); tout = ble_get_conn_timeout(); ble_update_conn_param(400, 0, 500); //interval: 400*1.25ms = 500ms } #endif #if BT_SINGLE_SLEEP_LPW_EN if (!bt_is_connected()){ //蓝牙未连接 if (bt_get_scan()) { //双模休眠 bt_set_scan_param(0x0a20); //pscan int = 0x2100 , iscan int = 0xb00; } else { bt_set_scan_param(0xc0c0); bt_scan_disable(); } } #else if (!bt_is_connected()){ //蓝牙未连接 bt_set_scan_param(0x0a20); //pscan int = 0x2100 , iscan int = 0xb00; } #endif #if DAC_DNR_EN u8 sta = dac_dnr_get_sta(); dac_dnr_set_sta(0); #endif dac_power_off(); //dac power down sys_set_tmr_enable(0, 0); adc_ch = bsp_saradc_exit(); //close saradc及相关通路模拟 saradc_clr_channel(adc_ch); saradc_set_channel(BIT(ADCCH_VBAT) | BIT(ADCCH_BGOP)); #if CHARGE_EN bsp_charge_set_stop_time(3600); charge_set_detect_cnt(1); #if CHARGE_VOL_DYNAMIC_DET if(sys_cb.chg_on){ RTCCON8 &= ~BIT(1); //charge open } #endif #endif usbcon0 = USBCON0; //需要先关中断再保存 usbcon1 = USBCON1; USBCON0 = BIT(5); USBCON1 = 0; gui_sleep(); sleep_cb.adpll_is_sleep = true; sysclk = sys_clk_get(); sys_clk_set(SYS_26M); DACDIGCON0 &= ~BIT(0); //disable digital dac adda_clk_source_sel(1); //adda_clk48_a select xosc52m PLL0CON &= ~(BIT(18) | BIT(6)); //pll0 sdm & analog disable rtc_sleep_enter(); //io analog input pa_de = GPIOADE; pb_de = GPIOBDE; pe_de = GPIOEDE; pf_de = GPIOFDE; pg_de = GPIOGDE; if(sleep_cb.sleep_enter_callback_func){ sleep_cb.sleep_enter_callback_func(NULL); }else{ GPIOADE = 0; #if (SENSOR_STEP_SEL == SENSOR_STEP_INTER) GPIOBDE = 0 |BIT(7); #else GPIOBDE = BIT(3)| BIT(2) | BIT(1) ;//假心率拉低&IIC GPIOBPU &= ~BIT(0); #endif GPIOGDE = 0x3F; //MCP FLASH // if (bsp_sensor_init_sta_get(SENSOR_INIT_ALL)) { // GPIOEDE = 0 | BIT(2) | BIT(1); //SENSOR I2C // GPIOFDE = 0 | BIT(2); //SENSOR PG // } else { GPIOEDE = 0; GPIOFDE = 0; // } } wkie = WKUPCON & BIT(16); WKUPCON &= ~BIT(16); //休眠时关掉WKIE sleep_wakeup_config(); SysVariable.sleep_counter = 0; SysVariable.sleep_wakeup_time = -1L; while(bt_is_sleep()) { WDT_CLR(); status = bt_sleep_proc(); if(status == 1) { ret = sleep_timer(); if(ret) { if (ret == 1) { printf("enter to power off by func_lowpwr\n"); func_switch_to_assign_screen(FUN_POWER_OFF_LOGO, true); } break; } } wkpnd = port_wakeup_get_status(); wko_wkup_flag = port_wko_is_wakeup(); port_int_sleep_process(&wkpnd); bsp_sensor_step_lowpwr_pro(); if (wkpnd) { printf("port wakeup: %x\n", wkpnd); break; } if ((RTCCON9 & BIT(2)) || (RTCCON10 & BIT(2)) || wko_wkup_flag) { printf("wko wakeup\n"); gui_need_wkp = true; break; } #if LE_EN if (ble_app_need_wakeup()) { printf("ble_app_need_wakeup\n"); gui_need_wkp = true; break; } #endif if (co_timer_pro(true)) { break; } if (sys_cb.wkp_flag) { printf("wakeup\n"); break; } if (sys_cb.raise_hand) { printf("raise hand wakeup\n"); break; } if (sys_cb.ble_flag) { sys_cb.ble_flag = false; printf("ble wakeup\n"); break; } if (sys_cb.charge_sta) { printf("charge wakeup\n"); break; } if(!sleep_cb.sleep_terminate){ printf("sleep_terminate_wakeup\n"); break; } if (sys_cb.rtc_flag) { printf("RTC calibration wakeup\n"); break; } } RTCCON9 = BIT(7) | BIT(5) | BIT(2); //clr port, bt, wko wakeup pending RTCCON3 &= ~(BIT(17) | BIT(13)); //disable port, bt wakeup sleep_wakeup_exit(); WKUPCON |= wkie; //还原WKIE if(sleep_cb.sleep_enter_callback_func == NULL){ GPIOADE = pa_de; GPIOBDE = pb_de; GPIOEDE = pe_de; GPIOFDE = pf_de; GPIOGDE = pg_de; GPIOBPU |= BIT(0); } USBCON0 = usbcon0; USBCON1 = usbcon1; CLKCON0 = (CLKCON0 & ~(0x03 << 2)) | (0x01 << 2); //sysclk select xosc26m_clk RSTCON0 &= ~BIT(4); //pllsdm disable adpll_init(DAC_OUT_SPR); //enable adpll adda_clk_source_sel(0); //adda_clk48_a select pll0 sys_clk_set(sysclk); sleep_cb.adpll_is_sleep = false; bt_set_scan_param(0x0303); //pscan int = 0x400 , iscan int = 0x400; #if BT_SINGLE_SLEEP_LPW_EN if(!bt_is_connected() && bt_get_scan()){ //单模 bt_scan_enable(); } #endif saradc_set_channel(adc_ch); bsp_saradc_init(); #if CHARGE_EN bsp_charge_set_stop_time(18000); bsp_charge_sta(sys_cb.charge_sta); //update充灯状态 charge_set_detect_cnt(5); #if CHARGE_VOL_DYNAMIC_DET if(sys_cb.chg_on){ RTCCON8 &= ~BIT(1); //charge open } #endif #endif // CHARGE_EN rtc_sleep_exit(); sys_set_tmr_enable(1, 1); if (DAC_FAST_SETUP_EN) { bsp_loudspeaker_mute(); } // gui_wakeup(); if (sys_cb.raise_hand || sys_cb.wkp_flag || wkpnd) { sys_cb.raise_hand = false; sys_cb.wkp_flag = false; gui_wakeup(); printf("raise hand wakeup2 func_cb.sta = %d %d\n",func_cb.sta,sys_cb.gui_need_wakeup); } #if LE_EN ble_set_adv_interval(adv_interval); if (interval | latency | tout) { ble_update_conn_param(interval, latency, tout); //还原连接参数 } #endif dac_restart(); bsp_change_volume(SysVariable.vol); #if DAC_DNR_EN dac_dnr_set_sta(sta); #endif bt_exit_sleep(); if(sleep_cb.sleep_exit_callback_func){ sleep_cb.sleep_exit_callback_func(NULL); } sleep_cb.sys_is_sleep = false; sys_cb.gui_need_wakeup = false; sys_cb.wkp_flag = false; printf("sleep_exit\n"); printf("sleep_exit wakeup[%d,%d,%d,%d]\n",sys_cb.gui_need_wakeup,sys_cb.wkp_flag,sys_cb.raise_hand,sys_cb.gui_sleep_sta); sys_cb.sleep_exit_tick = tick_get(); } AT(.text.lowpwr.sleep) bool sleep_process(is_sleep_func is_sleep) { if ((sys_cb.gui_need_wakeup || sys_cb.wkp_flag || sys_cb.raise_hand) && sys_cb.gui_sleep_sta) { printf("sleep_process wakeup[%d,%d,%d,%d]\n",sys_cb.gui_need_wakeup,sys_cb.wkp_flag,sys_cb.raise_hand,sys_cb.gui_sleep_sta); gui_wakeup(); //按键亮屏 reset_sleep_delay_all(); sys_cb.gui_need_wakeup = 0; sys_cb.wkp_flag = 0; sys_cb.raise_hand = 0; return false; } #if LE_EN if (ble_app_need_wakeup()) { reset_sleep_delay_all(); reset_pwroff_delay(); return false; } #endif if ((*is_sleep)() \ && sleep_cb.sleep_terminate \ && !sys_cb.charge_sta \ && !sys_cb.stopwatch_sta \ && sys_cb.timer_sta != 1 \ && get_sport_pause_state()) { if (!sys_cb.sleep_en) { reset_sleep_delay_all(); return false; } if (SysVariable.sleep_delay == 0) { sfunc_sleep(); // 熄屏且进入休眠 if (sys_cb.rtc_flag == true) { /* RTC校准需求唤醒 - 校准后再次进入休眠 */ sys_cb.rtc_flag = false; system_time_Calculation(); } else { reset_sleep_delay_all(); reset_pwroff_delay(); } if (SysVariable.password_cnt == 4) { if (task_stack_find(FUNC_PASSWORD_SUB_DISP) == -1) { SysVariable.password_change = 0; SysVariable.password_switch = 0; SysVariable.password_need = 1; } else if (!SysVariable.password_change && !SysVariable.password_switch) { SysVariable.password_need = 1; } } return true; } } else { if ((SysVariable.guioff_delay == 0||SysVariable.sleep_delay == 0) && !sys_cb.gui_sleep_sta) { gui_sleep(); //仅熄屏 if (SysVariable.password_cnt == 4) { if (task_stack_find(FUNC_PASSWORD_SUB_DISP) == -1) { SysVariable.password_change = 0; SysVariable.password_switch = 0; SysVariable.password_need = 1; } else if (!SysVariable.password_change && !SysVariable.password_switch) { SysVariable.password_need = 1; } } } if(SysVariable.sleep_delay == 0||SysVariable.guioff_delay == 0) { reset_sleep_delay(); reset_pwroff_delay(); } } return false; } ////红外关机进入sleep mode //AT(.text.lowpwr.sleep) //void func_sleepmode(void) //{ // //} ///解决充满关机等待5V掉电,超时1分钟 AT(.text.pwroff.vusb) u8 sfunc_pwrdown_w4_vusb_offline(void) { // u32 timeout = 10000, off_cnt = 0; // while (timeout--) { // WDT_CLR(); // delay_us(330); //5ms // if (!CHARGE_DC_IN()) { // off_cnt++; // } else { // off_cnt = 0; // } // if (off_cnt > 5) { // return 1; //VUSB已掉线,打开VUSB唤醒 // } // } return 0; //关VUSB唤醒 } AT(.text.pwroff.enter) void sfunc_power_save_enter(void) { // sys_clk_set(SYS_26M); LOUDSPEAKER_MUTE_DIS(); WDT_CLR(); #if CHARGE_EN if (xcfg_cb.charge_en) { bsp_charge_off(); } #endif set_buck_mode(0); //关机前切回ldo mode vusb_delay_rst_dis(); RTCCON4 = (RTCCON4 & ~(3 << 5)) | (1 << 5); //RI_VCORE_SVBT = 0, RI_VCORE_SVIO = 1 asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); USBCON0 = BIT(5); USBCON1 = 0; GPIOADE = 0; GPIOBDE = 0; GPIOEDE = 0; GPIOFDE = 0; GPIOGDE = 0x3F; //MCP FLASH RTCCON8 &= ~BIT(15); //RI_EN_VUSBDIV = 0 RTCCON0 = (RTCCON0 & ~(3 << 8)) | (2 << 8); //CLK32K_RTC Select RC2M_RTC PICCONCLR = BIT(0); //Globle IE disable CLKCON0 |= BIT(0); //enable RC CLKCON0 = (CLKCON0 & ~(0x3 << 2)); //system clk select RC RSTCON0 &= ~(BIT(4) | BIT(6)); //pllsdm, adda_clk CLKGAT0 &= ~(BIT(12) | BIT(14)); //disable dac clk PLL0CON &= ~(BIT(6) | BIT(18)); //PLL0 disable XO26MCON &= ~((0xf<<24) | BIT(10) | BIT(5));//X26 output, xosc, xosc52m disable PLL0CON &= ~(BIT(12) | BIT(0) | BIT(1)); //PLL0 & XOSC关电 RTCCON9 = 0xfff; //Clr pending } //软开关方案,POWER键/低电时,进入关机状态 AT(.text.pwroff.pwrdwn) void sfunc_pwrdown_do(u8 vusb_wakeup_en) { printf("%s:%d\n", __func__, vusb_wakeup_en); sys_cb.flag_pwroff = true; sys_set_tmr_enable(0, 0); rtc_set_alarm_wakeup(900); //15min sfunc_power_save_enter(); if (!vusb_wakeup_en) { RTCCON8 = (RTCCON8 & ~BIT(6)) | BIT(1); //disable charger function vusb_wakeup_en = sfunc_pwrdown_w4_vusb_offline(); } RTCCON1 &= ~(BIT(5) | BIT(7)); //BIT(7): VRTC voltage for ADC, BIT(5):WK pin analog enable, output WKO voltage for ADC RTCCON11 = (RTCCON11 & ~0x03) | BIT(2); //WK PIN filter select 8ms // RTCCON0 &= ~(BIT(0) | /*BIT(18) | */BIT(2)); //RI_EN_SNIFF = 0, RI_EN_RINGOSC = 0 RTCCON4 = (RTCCON4 & ~(0x3f<<9)) | (4<<9) | (4<<12); //LVCORE档位调到4防止软关机漏电 uint rtccon3 = RTCCON3 & ~BIT(11); uint rtccon1 = RTCCON1 & ~0x1f; #if CHARGE_EN if ((xcfg_cb.charge_en) && (vusb_wakeup_en)) { rtccon3 |= BIT(11); //VUSB wakeup enable } #endif RTCCON3 = rtccon3 & ~BIT(10); //关WK PIN,再打开,以清除Pending rtccon3 = RTCCON3 & ~0x87; //Disable VDDCORE VDDIO VDDBUCK VDDIO_AON rtccon3 &= ~BIT(22); //RI_EN_VLCORE = 0, rtccon3 &= ~(3 << 20); //RL2VDD12 = 0, C2VDD12 = 0 rtccon3 |= BIT(6) | BIT(4) | BIT(19); //PDCORE, PDCORE2, PDCORE3 rtccon3 |= BIT(10); //WK pin wake up enable // rtccon3 |= BIT(16); //RTC_WDT wake ep enable rtccon1 |= BIT(0) | BIT(2) | BIT(4); //WK 90K pull up enable WDT_DIS(); RTCCON12 |= (0x3<<6); //DIS RTC_WDT RTCCON &= ~(3 << 1); //避免关机时rtc配置来不及生效问题 RTCCON |= BIT(5); //PowerDown Reset,如果有Pending,则马上Reset RTCCON1 = rtccon1; RTCCON3 = rtccon3; LPMCON |= BIT(0); //sleep mode LPMCON |= BIT(1); //idle mode asm("nop");asm("nop");asm("nop"); while (1); } void sfunc_pwrdown(u8 vusb_wakeup_en) { lock_code_pwrsave(); sfunc_pwrdown_do(vusb_wakeup_en); } AT(.text.lowpwr.pwroff) void func_pwroff(int pwroff_tone_en) { printf("%s\n", __func__); rtc_sleep_enter(); rtc_calibration_write(PARAM_RTC_CAL_ADDR); cm_write8(PARAM_RTC_CAL_VALID, 1); cm_sync(); rtc_printf(); gui_sleep(); #if WARNING_POWER_OFF if (SOFT_POWER_ON_OFF) { mp3_res_play(RES_BUF_POWEROFF_MP3, RES_LEN_POWEROFF_MP3); } #endif // WARNING_POWER_OFF if (!PWRKEY_2_HW_PWRON) { while (IS_PWRKEY_PRESS()) { //等待PWRKWY松开 delay_5ms(1); WDT_CLR(); } } dac_power_off(); //dac power down if (CHARGE_DC_IN()) { if (power_off_check()) { //充电过程中等待结束再关机 return; } } bsp_saradc_exit(); //close saradc及相关通路模拟 if ((PWRKEY_2_HW_PWRON) && (sys_cb.poweron_flag)) { RTCCON1 |= BIT(6); //WK PIN High level wakeup } sys_clk_set(SYS_26M); sfunc_pwrdown(1); } /**************************************************************************************************************** * Deep mode模式 * VDDCORE关闭、VDDIO用ano电源域、lp_top用vrtc11供电、关掉VDDBT、模拟模块置成复位状态 * 支持所有引脚唤醒,WKO,VUSB插入,INBOX或者RTC定时唤醒,MCLR引脚复位等 * 唤醒后VDDCORE重新上电复位,重新load flash程序跑起来 * 开rtc计时(时钟选择sniff rc) 开rtc计时(时钟选择ring rc) 不开rtc计时 * 基础电流 12~13uA 6~7uA 4~5uA *使用方式:调用 func_deepsleep()函数即可进入该模式, 唤醒方式配置了PA1下降沿唤醒,可根据具体情况修改唤醒源 ****************************************************************************************************************/ //关机RTC走时的时钟选择, 二选一 #define SNF_RC_EN 1 //关机走时使用sniff rc, 走时比较准, 功耗在12~13ua #define RING_RC_EN 0 //关机走时使用ring rc, 走不准, 功耗在6~7ua //关机时VDDIO LDO选择, 二选一 #define VDDIO_EN 0 //关机时使用标准VDDIO, 3.3V, 功耗在45~46ua(开了sniff rc) #define VDDIO_AON_EN 1 //关机时使用VDDIO_AON, 档位2.8V, 功耗在12~13ua(开了sniff rc) AT(.com_text.lp.deepsleep) void deepsleep_save_to_cache(u8 *src_addr, u32 length) { //需要把RAM0的程序copy到ICACHE RAM上面跑 u32 i; u8 *cp_dst_ptr, *cp_src_ptr; cp_src_ptr = (u8*) src_addr; cp_dst_ptr = (u8*) 0x70000; for(i = 0; i < length; i++){ *cp_dst_ptr++ = *cp_src_ptr++; } asm("j 0x70000"); while(1); } AT(.com_text.lp.deepsleep) void port_wkup_init(void) { PORTINTEDG |= BIT(1); //PA1 fall edge PORTINTEN |= BIT(1); //enable PA1 WKPINMAP = 0x3<<12; WKUPEDG |= BIT(6); //fall edge WKUPCON |= BIT(6); //6 enable WKUPCPND = BIT(22); //clear 6 pending //pwrkey 唤醒 RTCCON11 &= ~BIT(4); RTCCON1 |= BIT(0) | BIT(2) | BIT(4); //OPEN WKO_IE pull_up WKPINMAP |= 0x3<<0; WKUPEDG |= BIT(0); //fall edge WKUPCON |= BIT(0); //6 enable WKUPCPND |= BIT(16); //clear 6 pending WKUPCON |= 1<<20; //fall filter select WKUPCON |= BIT(17); //wakup sniff enable } AT(.com_text.lp.deepsleep) void deepsleep_port_state(void) { //关机下不需要用到的IO,都配置为模拟IO,避免漏电 GPIOADE = 0x0; GPIOADE |= BIT(1); GPIOBDE = 0x0; GPIOGDE = 0x0; GPIOEDE = 0x0; GPIOFDE = 0x0; GPIOAFEN = 0x0; GPIOBFEN = 0x0; GPIOGFEN = 0x0; GPIOEFEN = 0x0; GPIOFFEN = 0x0; GPIOAPU = 0x0; GPIOAPU |= BIT(1); GPIOBPU = 0x0; GPIOGPU = 0x0; GPIOEPU = 0x0; GPIOFPU = 0x0; port_wkup_init(); PWRCON1 &= ~(0xF<<14); //disable flash PG GPIOGDE = BIT(2); GPIOGPU = BIT(2); //pull up cs WKUPCPND = 0xff<<16; //clear pendind CLKGAT0 &= ~BIT(15); //disable lp_top clock RTCCON5 &= ~BIT(12); //IO interface disable, io控制寄存器无法写 } AT(.com_text.lp.deepsleep) void sfunc_deepsleep_do(void) { CLKCON0 |= BIT(0); //rosc_en CLKCON0 = (CLKCON0 & ~(0x3<<2)) | (0x0<<2);//sys_clk sel rc2m CLKGAT1 &= ~BIT(29);//disable x26m_clken XO26MCON = 0; PLL0CON = 0; CLKGAT0 &= ~(3<<2); //disable ram0/1 clock RTCCON5 &= ~BIT(11); //lpif_en interface disable RTCCON5 |= BIT(18); //power_flag RTCCON0 = (RTCCON0 & ~(0x7<<22)) | (0x1<<22); RTCCON4 = (RTCCON4 & ~(0x3f<<24)) | (4<<24) | (4<<27); RTCCON3 = //BIT(19) //pd_core3 BIT(17) //wk1_en // BIT(9) //rtc1s_wken #if VDDIO_EN | BIT(1) //VDDIO LDO #elif VDDIO_AON_EN | BIT(7) //en vddio_aon #endif // | BIT(6) //pd_core | BIT(4) //pd_core2 | BIT(3) //rl2vlc ; LPMCON |= BIT(0); while(1); } AT(.com_text.str) const char str2[] = "RTCCON0: %x, RTCCON3: %x, RTCCON4: %x, RTCCON5: %x, RTCCON12: %x\n"; AT(.com_text.str) const char str3[] = "GPIOAPU: %x, GPIOBPU: %x, GPIOGPU: %x\n"; AT(.com_text.lp.deepsleep) void sfunc_deepsleep(void) { PICCONCLR = BIT(0); //关总中断 WDT_DIS(); #if RING_RC_EN RTCCON0 &= ~(0x3f<<8); RTCCON0 |= BIT(0); //enable PMU RC RTCCON0 &= ~BIT(18); //disable SNIFF RC RTCCON0 = (RTCCON0 & ~(3<<8)) | (1<<8); //CLK32K_RTC Select RC2M_RTC #elif SNF_RC_EN RTCCON0 &= ~(0x3f<<8); //2m bt,tk,rtc disable RTCCON0 |= BIT(18); //enable SNIFF RC RTCCON0 = (RTCCON0 & ~(0x3<<16)) | (0x2<<16); //SNF_BIAS RTCCON0 = (RTCCON0 & ~(3<<8)) | (2<<8); //CLK32K_RTC Select SNF_RC_RTC #else RTCCON0 &= ~(0x3f<<8); RTCCON0 &= ~BIT(18); //disable SNIFF RC RTCCON0 &= ~BIT(0); //disable PMU RC RTCCON0 = (RTCCON0 & ~(0x3<<16)) | (0x0<<16); //SNF_BIAS RTCCON0 &= ~BIT(25); //CAP2PLL #endif // printf(str2, RTCCON0, RTCCON3, RTCCON4, RTCCON5, RTCCON12); // printf(str3, GPIOAPU, GPIOBPU, GPIOGPU); //配置关机下,VRTC 数字的工作电压;RTCCON BIT0为0则选择RTCCON4 BIT26:24; 为1则选择BIT 29:27 RTCCON4 = (RTCCON4 & ~(7<<24)) | (4<<24); #if VDDIO_AON_EN //VDDIO LDO从正常LDO切换到VDDIO_AON RTCCON3 |= BIT(7); //VDDIO_AON enable RTCCON3 &= ~BIT(1); // RTCCON4 |= BIT(23); //VDDIO_AON SEL 3.3V #elif VDDIO_EN PWRCON0 = (PWRCON0 & ~(0xf<<5)) | (0x9<<5); //VDDIO=3.3v RTCCON4 = (RTCCON4 & ~(3<<17)) | (0<<17); //VIO_TC #endif RTCCON11 |= BIT(4); //wko protect RTCCON4 &= ~BIT(22); //rtcbg_uvm disable RTCCON4 &= ~BIT(16); //VIOPD RTCCON8 = (RTCCON8 & ~(0X1F<<24)) | (0XF<<24); //BGTRIM RTCCON1 = 0; RTCCON12 = 0xfa; //disable wkp10s, gpio, wdt reset deepsleep_port_state(); //需要把RAM0的程序copy到ICACHE RAM上面跑 deepsleep_save_to_cache((u8 *)sfunc_deepsleep_do, 500); } AT(.text.lowpwr.deepsleep) void func_deepsleep(void) { printf("%s\n", __func__); rtc_sleep_enter(); rtc_calibration_write(PARAM_RTC_CAL_ADDR); cm_write8(PARAM_RTC_CAL_VALID, 1); cm_sync(); rtc_printf(); dac_power_off(); //dac power down if (CHARGE_DC_IN()) { if (power_off_check()) { //充电过程中等待结束再关机 return; } } bsp_saradc_exit(); //close saradc及相关通路模拟 sys_clk_set(SYS_26M); sfunc_deepsleep(); }