mcu_ab568x/app/projects/AB5682C_240/functions/common/func_lowpwr.c
2025-05-30 18:03:10 +08:00

887 lines
26 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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、模拟模块置成复位状态
* 支持所有引脚唤醒WKOVUSB插入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();
}