#include "include.h" #include "driver_lowpwr.h" #include "driver_gpio.h" #include "ble_user_service.h" #include "bsp_io_key.h" #if SLEEP_SFR_SAVE /* Users save the registers that need to be backed up. Registers that are not backed up will lose their values after they enter deep sleep */ #define LOWPWR_SFR_USER_SAVE #ifdef LOWPWR_SFR_USER_SAVE typedef struct { u32 funcomcon[6]; u32 uart0baud; u16 uart0con; } lowpwr_sfr_user_backup_t; lowpwr_sfr_user_backup_t sfr_user_backup; AT(.com_sleep.lv2) void lowpwr_sleep_sfr_user_save(void) { sfr_user_backup.funcomcon[0] = FUNCOMCON0; sfr_user_backup.funcomcon[1] = FUNCOMCON1; sfr_user_backup.funcomcon[2] = FUNCOMCON4; sfr_user_backup.funcomcon[3] = FUNCOMCON5; sfr_user_backup.funcomcon[4] = FUNCOMCON6; sfr_user_backup.funcomcon[5] = FUNCIMCON0; sfr_user_backup.uart0baud = UART0BAUD; sfr_user_backup.uart0con = UART0CON; } AT(.com_sleep.lv2) void lowpwr_sleep_sfr_user_resume(void) { FUNCOMCON0 = sfr_user_backup.funcomcon[0]; FUNCOMCON1 = sfr_user_backup.funcomcon[1]; FUNCOMCON4 = sfr_user_backup.funcomcon[2]; FUNCOMCON5 = sfr_user_backup.funcomcon[3]; FUNCOMCON6 = sfr_user_backup.funcomcon[4]; FUNCIMCON0 = sfr_user_backup.funcomcon[5]; UART0BAUD = sfr_user_backup.uart0baud; UART0CON = sfr_user_backup.uart0con; UART0CPND = BIT(17) | BIT(16); //CLR Pending } #endif #endif AT(.com_text.sleep_tick) void lowpwr_tout_ticks(void) { #if SYS_SLEEP_LEVEL if(sys_cb.sleep_delay != -1L && sys_cb.sleep_delay > 0) { sys_cb.sleep_delay--; } #endif #if SYS_OFF_TIME if(sys_cb.pwroff_delay != -1L && sys_cb.pwroff_delay > 0) { sys_cb.pwroff_delay--; } #endif } #if SYS_SLEEP_LEVEL AT(.com_sleep.sleep) void sys_sleep_cb(u8 lpclk_type) { //注意!!!!!!!!!!!!!!!!! //此函数只能调用com_sleep或com_text函数 //此处关掉影响功耗的模块 lowpwr_sleep_proc(lpclk_type); //enter sleep //唤醒后,恢复模块功能 } void sleep_pwrdown_timer_cb(uint32_t handle) { #if 1/* TRACE_EN */ GPIO_PORT_GET(BSP_UART_DEBUG_EN)->de |= GPIO_PIN_GET(BSP_UART_DEBUG_EN); printf("sleep pwrdown timeout\n"); #endif func_pwroff(); } void lowpwr_sleep_wakeup_config(void) { lowpwr_wakeup_typedef config; lowpwr_wakeup_disable(); config.source = WK_LP_WK0 | WK_LP_BT; #if BSP_CHARGE_EN || FUNC_USBD_EN config.source |= WK_LP_VUSB; #endif #if BSP_IOKEY_EN config.source |= WK_LP_GPIO; config.gpiox = NULL; config.gpio_pin = 0; #endif config.edge = WK_EDGE_FALLING; config.lp_type = LP_TYPE_SLEEP; lowpwr_wakeup_config_2(&config); #if BSP_IOKEY_EN for (u8 i = 0; i < IO_KEY_COL_TABLE_SIZE; i++) { config.gpiox = key_io_table_column[i].gpiox; config.gpio_pin = key_io_table_column[i].gpio_pin; config.gpio_pupd = GPIO_PUPD_PU10K; // same with init in bsp_io_key.c lowpwr_gpio_wakeup_config(&config); } #if IO_KEY_SCAN_MODE config.edge = WK_EDGE_RISING; for (u8 i = 0; i < IO_KEY_ROW_TABLE_SIZE; i++) { config.gpiox = key_io_table_row[i].gpiox; config.gpio_pin = key_io_table_row[i].gpio_pin; config.gpio_pupd = GPIO_PUPD_PD10K; lowpwr_gpio_wakeup_config(&config); } #endif // IO_KEY_SCAN_MODE #endif // BSP_IOKEY_EN } AT(.text.lowpwr.sleep) static void sfunc_sleep(void) { uint32_t sysclk; u8 pg_de; u16 pa_de, pb_de; printf("%s\n", __func__); ble_enter_sleep_proc(); delay_5ms(1); bt_enter_sleep(); sys_set_tmr_enable(0, 0); sysclk = sys_clk_get(); sys_clk_set(SYS_24M); #if SYS_OFF_TIME bt_timer_mem_t sleep_pwrdown_timer; bt_timer_handle_t sleep_pwrdown_timer_handle; bt_alarm_timer_mem_extend(&sleep_pwrdown_timer, sizeof(sleep_pwrdown_timer)); bt_alarm_timer_acquire(&sleep_pwrdown_timer_handle, 100 * sys_cb.pwroff_delay, 0, sleep_pwrdown_timer_cb); bt_alarm_timer_start(sleep_pwrdown_timer_handle); printf("wk and pwr after: %ds\n", 100 * sys_cb.pwroff_delay / 1000); #endif //io analog input pa_de = GPIOADE; pb_de = GPIOBDE; pg_de = GPIOGDE; GPIOADE = 0; GPIOBDE = 0; GPIOGDE = 0x3F; //MCP FLASH lowpwr_wakeup_disable(); lowpwr_sleep_wakeup_config(); sys_cb.sleep_sta = 1; while (bt_is_sleep()) { WDT_CLR(); bt_sleep_proc(); #if SYS_OFF_TIME { if (func_cb.sta == FUNC_PWROFF) { break; } if (0/* Condition: reset pwr timer */) { bt_alarm_timer_modify_interval(sleep_pwrdown_timer_handle, 6666, 0); } } #endif if (lowpwr_is_wakeup_pending(WK_LP_BT)) { break; } #if BSP_IOKEY_EN if(gpio_is_edge_pending()){ break; } #endif if(ble_proc_pending()){ break; } } sys_cb.sleep_sta = 0; #if SYS_OFF_TIME bt_alarm_timer_mem_free(&sleep_pwrdown_timer, sizeof(sleep_pwrdown_timer)); #endif sys_clk_set(sysclk); //Reinitialize all peripherals, because all register configurations are lost after low power bsp_periph_init(); printf("wakeup\n"); GPIOADE = pa_de; GPIOBDE = pb_de; GPIOGDE = pg_de; lowpwr_wakeup_disable(); sys_set_tmr_enable(1, 1); bt_exit_sleep(); ble_exit_sleep_proc(); printf("sleep_exit\n"); } AT(.text.app.proc.sleep) bool sleep_process(is_sleep_func is_sleep) { if (is_sleep()) { if (sys_cb.sleep_delay == -1L) { return false; } if(sys_cb.sleep_delay == 0) { sfunc_sleep(); lowpwr_sleep_delay_reset(); lowpwr_pwroff_delay_reset(); return true; } } else { lowpwr_sleep_delay_reset(); } return false; } #endif void lowpwr_pwroff_wakeup_config(void) { lowpwr_wakeup_typedef config; lowpwr_wakeup_disable(); config.source = WK_LP_WK0; #if BSP_CHARGE_EN || FUNC_USBD_EN config.source |= WK_LP_VUSB; #endif #if BSP_IOKEY_EN config.source |= WK_LP_GPIO; config.gpiox = NULL; config.gpio_pin = 0; #endif config.edge = WK_EDGE_FALLING; config.lp_type = LP_TYPE_POWOFF; lowpwr_wakeup_config_2(&config); #if BSP_IOKEY_EN for (u8 i = 0; i < IO_KEY_COL_TABLE_SIZE; i++) { config.gpiox = key_io_table_column[i].gpiox; config.gpio_pin = key_io_table_column[i].gpio_pin; config.gpio_pupd = GPIO_PUPD_PU10K; // same with init in bsp_io_key.c lowpwr_gpio_wakeup_config(&config); } #if IO_KEY_SCAN_MODE config.edge = WK_EDGE_RISING; for (u8 i = 0; i < IO_KEY_ROW_TABLE_SIZE; i++) { config.gpiox = key_io_table_row[i].gpiox; config.gpio_pin = key_io_table_row[i].gpio_pin; config.gpio_pupd = GPIO_PUPD_PD10K; lowpwr_gpio_wakeup_config(&config); } #endif // IO_KEY_SCAN_MODE #endif // BSP_IOKEY_EN } void sfunc_pwroff(void) { GPIOADE = 0; GPIOBDE = 0; lowpwr_pwroff_wakeup_config(); pwroff_do(); } AT(.text.lowpwr.pwroff) void func_pwroff(void) { printf("%s\n", __func__); if (SOFT_POWER_ON_OFF) { sfunc_pwroff(); } }