887 lines
26 KiB
C
887 lines
26 KiB
C
#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();
|
||
}
|