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

521 lines
15 KiB
C
Raw 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 "func.h"
bool power_off_check(void);
void lock_code_pwrsave(void);
void unlock_code_pwrsave(void);
AT(.com_text.sleep)
void lowpwr_tout_ticks(void)
{
if(sys_cb.sleep_delay != -1L && sys_cb.sleep_delay > 0) {
sys_cb.sleep_delay--;
}
if(sys_cb.guioff_delay != -1L && sys_cb.guioff_delay > 0) {
sys_cb.guioff_delay--;
}
if(sys_cb.pwroff_delay != -1L && sys_cb.pwroff_delay > 0) {
sys_cb.pwroff_delay--;
}
}
AT(.com_text.sleep)
bool sys_sleep_check(u32 *sleep_time)
{
#if SYS_COTIME_EN
u32 co_min = sys_co_timer_get_min_time(true)*2;
if(*sleep_time > co_min) {
*sleep_time = co_min;
}
if(*sleep_time == 0){
*sleep_time = 1;
}
#endif
if(*sleep_time > sys_cb.sleep_wakeup_time) {
*sleep_time = sys_cb.sleep_wakeup_time;
return true;
}
return false;
}
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;
sys_cb.sleep_counter++;
if (sys_cb.sleep_counter == 10) {
sys_cb.sleep_counter = 0;
#if LPWR_WARNING_VBAT
saradc_init();
saradc_adc15_analog_select(ADCCH15_ANA_VRTC);
saradc_kick_start(0, 0);
while(!bsp_saradc_process(0));
if (sys_cb.vbat < LPWR_WARNING_VBAT) {
//低电需要唤醒sniff mode
ret = 2;
}
saradc_exit();
#endif
}
#if CHARGE_EN
if (xcfg_cb.charge_en) {
charge_detect(0);
}
#endif // CHARGE_EN
sys_cb.sleep_wakeup_time = -1L;
if(sys_cb.pwroff_delay != -1L) {
if(sys_cb.pwroff_delay > 5) {
sys_cb.pwroff_delay -= 5;
} else {
sys_cb.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;
#if LE_EN
u16 interval = 0;
u16 latency = 0;
u16 tout = 0;
u16 adv_interval = 0;
#endif
if (sys_co_timer_is_plan()) {
return;
}
#if VBAT_DETECT_EN
if (bsp_vbat_get_lpwr_status()) { //低电不进sniff mode
return;
}
#endif
printf("%s\n", __func__);
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);
#endif
#if MUSIC_UDISK_EN
if (dev_is_online(DEV_UDISK)) {
udisk_insert(); //udisk需要重新enum
}
#endif
usbcon0 = USBCON0; //需要先关中断再保存
usbcon1 = USBCON1;
USBCON0 = BIT(5);
USBCON1 = 0;
#if GUI_EN
gui_sleep();
#endif
sysclk = sys_clk_get();
sys_clk_set(SYS_26M);
DACDIGCON0 &= ~BIT(0); //disable digital dac
adda_clk_source_sel(0); //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;
GPIOADE = 0;
GPIOBDE = 0;
GPIOGDE = 0x3F; //MCP FLASH
#if SENSOR_EN
if (bsp_sensor_init_sta_get()) {
GPIOEDE = 0 | BIT(2) | BIT(1); //SENSOR I2C
GPIOFDE = 0 | BIT(2); //SENSOR PG
} else {
GPIOEDE = 0;
GPIOFDE = 0;
}
#endif
wkie = WKUPCON & BIT(16);
WKUPCON &= ~BIT(16); //休眠时关掉WKIE
sleep_wakeup_config();
sys_cb.sleep_counter = 0;
sys_cb.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) {
func_cb.sta = FUNC_PWROFF;
}
break;
}
}
wkpnd = port_wakeup_get_status();
bsp_sensor_step_lowpwr_pro(&wkpnd);
if (wkpnd) {
printf("port wakeup: %x\n", wkpnd);
break;
}
if ((RTCCON9 & BIT(2)) || (RTCCON10 & BIT(2))) {
printf("wko wakeup\n");
break;
}
#if LE_EN
if (ble_app_need_wakeup()) {
break;
}
#endif
if (sys_co_timer_pro(true)) {
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
GPIOADE = pa_de;
GPIOBDE = pb_de;
GPIOEDE = pe_de;
GPIOFDE = pf_de;
GPIOGDE = pg_de;
USBCON0 = usbcon0;
USBCON1 = usbcon1;
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
rtc_sleep_exit();
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(1); //adda_clk48_a select pll0
sys_clk_set(sysclk);
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充灯状态
#endif // CHARGE_EN
sys_set_tmr_enable(1, 1);
if (DAC_FAST_SETUP_EN) {
bsp_loudspeaker_mute();
}
#if GUI_EN
gui_wakeup();
#endif
#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(sys_cb.vol);
#if DAC_DNR_EN
dac_dnr_set_sta(sta);
#endif
bt_exit_sleep();
printf("sleep_exit\n");
}
AT(.text.lowpwr.sleep)
bool sleep_process(is_sleep_func is_sleep)
{
if (sys_cb.gui_need_wakeup && sys_cb.gui_sleep_sta) {
#if GUI_EN
gui_wakeup(); //按键亮屏
#endif
reset_sleep_delay_all();
sys_cb.gui_need_wakeup = 0;
return false;
}
#if LE_EN
if (ble_app_need_wakeup()) {
reset_sleep_delay_all();
reset_pwroff_delay();
return false;
}
#endif
if ((*is_sleep)()) {
if (!sys_cb.sleep_en) {
reset_sleep_delay_all();
return false;
}
if (sys_cb.sleep_delay == 0) {
sfunc_sleep(); //熄屏且进入休眠
reset_sleep_delay_all();
reset_pwroff_delay();
return true;
}
} else {
#if GUI_EN
if (sys_cb.guioff_delay == 0 && !sys_cb.gui_sleep_sta) {
gui_sleep(); //仅熄屏
}
#endif
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
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)) | (1 << 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
}
//硬开关方案,低电时,进入省电状态
AT(.text.pwroff)
void sfunc_lowbat_do(void)
{
sfunc_power_save_enter();
WDT_DIS();
RTCCON3 |= BIT(11); //VUSB Wakeup enable
while(1) {
LPMCON |= BIT(0); //Sleep mode enable
asm("nop");asm("nop");asm("nop");
if (RTCCON10 & BIT(3)) { //VUSB wake up pending
WDT_RST();
}
}
}
//软开关方案POWER键/低电时,进入关机状态
AT(.text.pwroff.pwrdwn)
void sfunc_pwrdown_do(u8 vusb_wakeup_en)
{
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
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 |= BIT(5); //PowerDown Reset如果有Pending则马上Reset
RTCCON1 = rtccon1;
RTCCON3 = rtccon3;
LPMCON |= BIT(0);
asm("nop");asm("nop");asm("nop");
while (1);
}
void sfunc_pwrdown(u8 vusb_wakeup_en)
{
lock_code_pwrsave();
sfunc_pwrdown_do(vusb_wakeup_en);
}
void sfunc_lowbat(void)
{
lock_code_pwrsave();
sfunc_lowbat_do();
}
AT(.text.lowpwr.pwroff)
void func_pwroff(int pwroff_tone_en)
{
printf("%s\n", __func__);
#if WARNING_POWER_OFF
if (SOFT_POWER_ON_OFF) {
mp3_res_play(RES_BUF_POWEROFF_MP3, RES_LEN_POWEROFF_MP3);
}
#endif // WARNING_POWER_OFF
// gui_off();
if (SOFT_POWER_ON_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
}
sfunc_pwrdown(1);
} else {
dac_power_off(); //dac power down
bsp_saradc_exit(); //close saradc及相关通路模拟
sfunc_lowbat(); //低电关机进入Sleep Mode
}
}