/********************************** (C) COPYRIGHT ******************************* * File Name : SLEEP.c * Author : WCH * Version : V1.2 * Date : 2022/01/18 * Description : 睡眠配置及其初始化 ********************************************************************************* * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. * Attention: This software (modified or not) and binary are used for * microcontroller manufactured by Nanjing Qinheng Microelectronics. *******************************************************************************/ /******************************************************************************/ /* 头文件包含 */ #include "HAL.h" #include "bsp_key.h" #include "log.h" #include "bsp_uart.h" #include "bsp_beep_led_emv.h" #undef LOG_ENABLE #define LOG_ENABLE 1 #undef LOG_TAG #define LOG_TAG "sleep" static volatile bool block_sleep_flag = false; static volatile bool block_boost_flag = false; __HIGH_CODE void BSP_RequestSleep(void) { block_sleep_flag = false; } __HIGH_CODE void BSP_BlockSleep(void) { block_sleep_flag = true; } __HIGH_CODE void BSP_RequestBoost(void) { BOOST_EN; block_boost_flag = false; } __HIGH_CODE void BSP_NoNeedBoost(void) { block_boost_flag = true; } pfnLowPowerGapProcessCB_t LowPowerGapProcess; /******************************************************************************* * @fn CH58x_LowPower * * @brief 启动睡眠 * * @param time - 唤醒的时间点(RTC绝对值) * * @return state. */ __HIGH_CODE uint32_t CH58x_LowPower(uint32_t time) { // BSP_UART1_TxLowPower(); if (block_boost_flag == false) { BOOST_EN; } else { BOOST_OFF_DEINIT; } if (true == block_sleep_flag) { // logDebug("block_sleep"); return 0; } #if (defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE) volatile uint32_t i; uint32_t time_tign, time_sleep, time_curr; unsigned long irq_status; // 提前唤醒 if (time <= WAKE_UP_RTC_MAX_TIME) { time_tign = time + (RTC_MAX_COUNT - WAKE_UP_RTC_MAX_TIME); } else { time_tign = time - WAKE_UP_RTC_MAX_TIME; } SYS_DisableAllIrq(&irq_status); time_curr = RTC_GetCycle32k(); // 检测睡眠时间 if (time_tign < time_curr) { time_sleep = time_tign + (RTC_MAX_COUNT - time_curr); } else { time_sleep = time_tign - time_curr; } // 若睡眠时间小于最小睡眠时间或大于最大睡眠时间,则不睡眠 if ((time_sleep < SLEEP_RTC_MIN_TIME) || (time_sleep > SLEEP_RTC_MAX_TIME)) { SYS_RecoverIrq(irq_status); return 2; } RTC_SetTignTime(time_tign); SYS_RecoverIrq(irq_status); #if (DEBUG == Debug_UART0) // 使用其他串口输出打印信息需要修改这行代码 while ((R8_UART0_LSR & RB_LSR_TX_ALL_EMP) == 0) { __nop(); } #elif (DEBUG == Debug_UART1) // 使用其他串口输出打印信息需要修改这行代码 while ((R8_UART1_LSR & RB_LSR_TX_ALL_EMP) == 0) { __nop(); } #endif // LOW POWER-sleep模式 if (!RTCTigFlag) { if (block_boost_flag == false) { BOOST_EN; } else { BOOST_OFF_DEINIT; } if (true == block_sleep_flag) { // logDebug("block_sleep"); return 0; } BSP_KEY_EnterLowpower(); LowPower_Sleep(RB_PWR_RAM32K | RB_PWR_RAM96K | RB_PWR_EXTEND); R8_RTC_FLAG_CTRL = (RB_RTC_TMR_CLR | RB_RTC_TRIG_CLR); RTC_SetTignTime(time); sys_safe_access_enable(); R8_HFCK_PWR_CTRL |= RB_CLK_XT32M_KEEP; sys_safe_access_disable(); if(!RTCTigFlag) { LowPower_Halt(); } R8_RTC_FLAG_CTRL = (RB_RTC_TMR_CLR | RB_RTC_TRIG_CLR); HSECFG_Current(HSE_RCur_100); // 降为额定电流(低功耗函数中提升了HSE偏置电流) // i = RTC_GetCycle32k(); // while (i == RTC_GetCycle32k()); return 0; } #endif return 3; } /******************************************************************************* * @fn LowPowerGapProcess_Register * * @brief 注册低功耗唤醒间隙执行回调 * * @param None. * * @return None. */ void LowPowerGapProcess_Register(pfnLowPowerGapProcessCB_t cb) { if((uint32_t)cb & 0x20000000) { LowPowerGapProcess = cb; } } /******************************************************************************* * @fn HAL_SleepInit * * @brief 配置睡眠唤醒的方式 - RTC唤醒,触发模式 * * @param None. * * @return None. */ void HAL_SleepInit(void) { #if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE) sys_safe_access_enable(); R8_SLP_WAKE_CTRL |= RB_SLP_RTC_WAKE; // RTC唤醒 sys_safe_access_disable(); sys_safe_access_enable(); R8_RTC_MODE_CTRL |= RB_RTC_TRIG_EN; // 触发模式 sys_safe_access_disable(); PFIC_EnableIRQ(RTC_IRQn); #endif }