/*! * \file pwr.c * * \brief Target pwr implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * * _ __ _ ________ _ * | |/ /(_)___ / ____/ /_ (_)___ * | // / __ \/ / / __ \/ / __ \ * / |/ / / / / /___/ / / / / /_/ / * /_/|_/_/_/ /_/\____/_/ /_/_/ .___/ * /_/ * (C) 2022-2025 XinChip * * \endcode * * \author ( XinChip ) Alex-J * * \author ( XinChip ) */ /*----------------------------------------------------------------------------------- INCLUDE HEADE FILES ------------------------------------------------------------------------------------*/ #include "pwr.h" #include "xc_drv_pwr.h" #include "xc_drv_fmc_spi.h" /*------------------------------------------------------------------------------------ Macros -------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------ Global Variables -------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------ Functions -------------------------------------------------------------------------------------*/ /** * @brief pwr_demo * @details * @param void * @retval void */ void wakeup_timer_set(uint32_t time) { cprao_aon_reg1__timer_ao_sleep_clksw__setf(0); AOTimer_InitCfg_t aotimer_cfg; aotimer_cfg.aotimer_mode = AOTIMER_MODE_CYCLE; // Timer0 Config & Start xc_aotimer_init(AOTIMER0_IDX, &aotimer_cfg); xc_aotimer_set_value(AOTIMER0_IDX, time); xc_aotimer_start(AOTIMER0_IDX); } void wakeup_timer_init() { Timer_InitCfg_t timer_cfg; timer_cfg.timer_src_clk = TIMER_CLK_SRC_32K; timer_cfg.timer_div_clk = TIMER_DIV_CLK_32000Hz; timer_cfg.timer_mode = TIMER_MODE_SINGLE; // Timer0 Config & Start xc_timer_init(TIMER0_IDX, &timer_cfg); } static void system_sleep_init() { uint32_t wake_it_src; #if (USE_XIP == 1) #if (USE_ROM_FLASH) FMC_SPI_Init_Oprt(); #else // (USE_ROM_FLASH) xc_fmc_spi_init_oprt(); #endif // (USE_ROM_FLASH) #endif #if (USE_XIP != 1) SPI_InitCfg_t spi_cfg = {0}; spi_cfg.Mode = SPI_MODE_MASTER; spi_cfg.DataSize = SSI_CTRL0_DFS_LEN_8BIT; spi_cfg.Direction = SSI_CTRL0_TMOD_WR; spi_cfg.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; spi_cfg.CLKPolarity = SSI_CTRL0_SCPOL_LOW; spi_cfg.CLKPhase = SPI_CPHA_LEAD; spi_cfg.FirstBit = SPI_FirstBit_MSB; xc_spi_init(XC_SPI0, &spi_cfg); SPI_Flash_PowerDown(XC_SPI0); #endif xc_pwr_gpio_sleep_config(); wake_it_src = GPIO_IRQn_WAKE | RTC_IRQn_WAKE|TIMER_AO0_IRQn_WAKE| TIMER0_IRQn_WAKE | MPU_IRQn_WAKE; xc_pwr_wake_it_set(wake_it_src); } static void system_lightsleep_cfg() { #if (USE_XIP != 1) cprao_aon_puctrl1_set(0x4); /* puctrl1= 0x4 , SSI0RX must pulldown*/ #endif cprao_aon_sys_time_set((RST_READY_TIME << 12) | (OSC32_STABLE_TIME)); xc_pwr_pd_lightsleep_set(); xc_pwr_sleepsrc_mask_set(0x1e001e); xc_pwr_osc_off(); } void system_deepsleep_cfg() { #if (USE_XIP!=1) cprao_aon_puctrl1_set(0xf); #endif cprao_aon_sys_time_set((RST_READY_TIME<<12) | (OSC32_STABLE_TIME)); xc_pwr_pd_deepsleep_set(); delay_us(100); xc_pwr_sleepsrc_mask_set(0x1e001e); xc_pwr_osc_off(); } void DeepSleep_Demo() { system_sleep_init(); // PWRKEY Initialization is required after deep sleep wakeup xc_pwr_pwrkey_init(); xc_pwr_pwrkey_deepsleep_wake_config(GPIO_2, DEEP_SLEEP_GPIO_WAKE_HIGH_LEVEL); xc_pwr_pwrkey_deepsleep_wake_config(GPIO_3, DEEP_SLEEP_GPIO_WAKE_LOW_LEVEL); system_deepsleep_cfg(); while(1) { xc_deep_sleep(); } } void DeepSleep_Timerwakeup_Demo() { system_sleep_init(); // PWRKEY Initialization is required after deep sleep wakeup xc_pwr_pwrkey_init(); system_deepsleep_cfg(); while(1) { wakeup_timer_set(1000*1000); xc_deep_sleep(); } } static void sleep_init(void) { system_sleep_init(); system_lightsleep_cfg(); /* Timer for sleep-wake*/ Timer_InitCfg_t timer_cfg; timer_cfg.timer_src_clk = TIMER_CLK_SRC_32K; timer_cfg.timer_div_clk = TIMER_DIV_CLK_32000Hz; timer_cfg.timer_mode = TIMER_MODE_SINGLE; xc_timer_init(TIMER0_IDX, &timer_cfg); } __RAM_CODE void xc_mcu_sleep(void) { xc_adc_powerdown(); xc_pwr_usb_off(); xc_pwr_rc16m_off(); xc_pwr_rc32k_calib_off(); xc_pwr_opa_tempsensor_off(); xc_pwr_opa_volr_off(); xc_pwr_revddldo_off(); xc_pwr_dcdc_close(); xc_pwr_rfdigital_off(); xc_pwr_rc32k_calib_off(); cprao_aon_reg4__bb_coreldo_normal_sw_mux__setf(1); xc_pwr_modem_off(); xc_pwr_pd_lightsleep_set(); #if (USE_XIP == 1) #if (USE_ROM_FLASH) FMC_SPI_Flash_PowerDown(); #else // (USE_ROM_FLASH) // xc_fmc_spi_flash_power_down(); #endif // (USE_ROM_FLASH) xc_pwr_rom_off(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); // cpr_fmc_ctl_set(0x3000 | (1 << 9)); // close FMC for (int i = 0; i < 10; i++) { __NOP(); __NOP(); __NOP(); } #endif // __disable_irq(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __WFI(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); // cpr_fmc_ctl_set(0x3503); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); xc_pwr_rom_on(); for (int i = 0; i < 10; i++) { __NOP(); __NOP(); __NOP(); } #if (USE_ROM_FLASH) FMC_SPI_Flash_WakeUp(); #else // (USE_ROM_FLASH) // xc_fmc_spi_flash_wake_up(); #endif // (USE_ROM_FLASH) xc_pwr_ao_timer_pclk32m_Set(); // __enable_irq(); #ifdef USED_DCDC xc_pwr_dcdc_open(); #endif xc_pwr_modem_on(); xc_pwr_rfdigital_on(); xc_adc_wakeup(); } void Sleep_Demo() { xc_rc32k_calib_by_soft(); sleep_init(); xc_pwr_gpio_lightsleep_wake_config(GPIO_3, RIS_EDGE_INT); xc_pwr_gpio_lightsleep_wake_config(GPIO_2, FAIL_EDGE_INT); xc_fmc_spi_init_oprt(); xc_fmc_spi_flash_wake_up(); while(1){ // Checks for sleep have to be done with interrupt disabled GLOBAL_INT_DISABLE(); uint32_t duration_timer = (500*1000); //500ms xc_timer_set_value(TIMER0_IDX, duration_timer); xc_timer_start(TIMER0_IDX); // Before you sleep, turn off the peripheral to make sure it doesn't generate interrupts, // and then turn it on again after you sleep up. // For example, timer interrupts xc_rc32k_soft_calib_disable(); xc_mcu_sleep(); xc_timer_stop(TIMER0_IDX); xc_rc32k_soft_calib_enable(); GLOBAL_INT_RESTORE(); // The delay can be omitted, rc32k will calibrate every time it wakes up, and it takes 2ms. delay_ms(3); } } #define SLEEP_DEMO 1 #define DEEPSLEEP_DEMO 0 #define DEEPSLEEP_TIMERWAKEUP_DEMO 0 void pwr_demo() { #if SLEEP_DEMO Sleep_Demo(); #endif #if DEEPSLEEP_DEMO DeepSleep_Demo(); #endif #if DEEPSLEEP_TIMERWAKEUP_DEMO DeepSleep_Timerwakeup_Demo(); #endif } __RAM_CODE void MPU_Handler(void) { cprao_aon_slp_pd_mask_set(0x001); #if XTAL_32K cprao_aon_ctl_clk32k_set(0x109); #endif printf("MPU_Handler\n"); WDT_InitCfg_t wdt_cfg ; wdt_cfg.WorkMode = WDT_WORK_MODE0; wdt_cfg.ReloadValue = WDT_CLK_32M_RESET_MODE0_4096US; wdt_cfg.PclkSel = WDT_WORK_32M; xc_wdt_init(&wdt_cfg); xc_wdt_start(); while(1); }