You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

409 lines
10 KiB

/********************************** (C) COPYRIGHT *******************************
* File Name : CH59x_pwr.c
* Author : WCH
* Version : V1.2
* Date : 2021/11/17
* 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 "CH59x_common.h"
/*********************************************************************
* @fn PWR_DCDCCfg
*
* @brief 启用内部DC/DC电源,用于节约系统功耗
*
* @param s - 是否打开DCDC电源
*
* @return none
*/
void PWR_DCDCCfg(FunctionalState s)
{
uint16_t adj = R16_AUX_POWER_ADJ;
uint16_t plan = R16_POWER_PLAN;
if(s == DISABLE)
{
adj &= ~RB_DCDC_CHARGE;
plan &= ~(RB_PWR_DCDC_EN | RB_PWR_DCDC_PRE); // 旁路 DC/DC
sys_safe_access_enable();
R16_AUX_POWER_ADJ = adj;
R16_POWER_PLAN = plan;
sys_safe_access_disable();
}
else
{
uint32_t HW_Data[2];
FLASH_EEPROM_CMD(CMD_GET_ROM_INFO, ROM_CFG_ADR_HW, HW_Data, 0);
if((HW_Data[0]) & (1 << 13))
{
return;
}
adj |= RB_DCDC_CHARGE;
plan |= RB_PWR_DCDC_PRE;
sys_safe_access_enable();
R16_AUX_POWER_ADJ = adj;
R16_POWER_PLAN = plan;
sys_safe_access_disable();
DelayUs(10);
sys_safe_access_enable();
R16_POWER_PLAN |= RB_PWR_DCDC_EN;
sys_safe_access_disable();
}
}
/*********************************************************************
* @fn PWR_UnitModCfg
*
* @brief 可控单元模块的电源控制
*
* @param s - 是否打开电源
* @param unit - please refer to unit of controllable power supply
*
* @return none
*/
void PWR_UnitModCfg(FunctionalState s, uint8_t unit)
{
uint8_t ck32k_cfg = R8_CK32K_CONFIG;
if(s == DISABLE) //关闭
{
ck32k_cfg &= ~(unit & 0x03);
}
else //打开
{
ck32k_cfg |= (unit & 0x03);
}
sys_safe_access_enable();
R8_CK32K_CONFIG = ck32k_cfg;
sys_safe_access_disable();
}
/*********************************************************************
* @fn PWR_PeriphClkCfg
*
* @brief 外设时钟控制位
*
* @param s - 是否打开对应外设时钟
* @param perph - please refer to Peripher CLK control bit define
*
* @return none
*/
void PWR_PeriphClkCfg(FunctionalState s, uint16_t perph)
{
uint32_t sleep_ctrl = R32_SLEEP_CONTROL;
if(s == DISABLE)
{
sleep_ctrl |= perph;
}
else
{
sleep_ctrl &= ~perph;
}
sys_safe_access_enable();
R32_SLEEP_CONTROL = sleep_ctrl;
sys_safe_access_disable();
}
/*********************************************************************
* @fn PWR_PeriphWakeUpCfg
*
* @brief 睡眠唤醒源配置
*
* @param s - 是否打开此外设睡眠唤醒功能
* @param perph - 需要设置的唤醒源
* RB_SLP_USB_WAKE - USB 为唤醒源
* RB_SLP_RTC_WAKE - RTC 为唤醒源
* RB_SLP_GPIO_WAKE - GPIO 为唤醒源
* RB_SLP_BAT_WAKE - BAT 为唤醒源
* @param mode - refer to WakeUP_ModeypeDef
*
* @return none
*/
void PWR_PeriphWakeUpCfg(FunctionalState s, uint8_t perph, WakeUP_ModeypeDef mode)
{
uint8_t m;
if(s == DISABLE)
{
sys_safe_access_enable();
R8_SLP_WAKE_CTRL &= ~perph;
sys_safe_access_disable();
if(perph & RB_SLP_GPIO_WAKE)
{
sys_safe_access_enable();
R8_SLP_WAKE_CTRL &= ~RB_GPIO_WAKE_MODE;
sys_safe_access_disable();
}
}
else
{
switch(mode)
{
case Short_Delay:
m = 0x01;
break;
case Long_Delay:
m = 0x00;
break;
default:
m = 0x01;
break;
}
sys_safe_access_enable();
R8_SLP_WAKE_CTRL |= RB_WAKE_EV_MODE | perph;
sys_safe_access_disable();
if(perph & RB_SLP_GPIO_WAKE)
{
sys_safe_access_enable();
R8_SLP_WAKE_CTRL |= RB_GPIO_WAKE_MODE;
sys_safe_access_disable();
}
sys_safe_access_enable();
R8_SLP_POWER_CTRL &= ~(RB_WAKE_DLY_MOD);
sys_safe_access_disable();
sys_safe_access_enable();
R8_SLP_POWER_CTRL |= m;
sys_safe_access_disable();
}
}
/*********************************************************************
* @fn PowerMonitor
*
* @brief 电源监控
*
* @param s - 是否打开此功能
* @param vl - refer to VolM_LevelypeDef
*
* @return none
*/
void PowerMonitor(FunctionalState s, VolM_LevelypeDef vl)
{
uint8_t ctrl = R8_BAT_DET_CTRL;
uint8_t cfg = R8_BAT_DET_CFG;
if(s == DISABLE)
{
sys_safe_access_enable();
R8_BAT_DET_CTRL = 0;
sys_safe_access_disable();
}
else
{
if(vl & 0x80)
{
cfg = vl & 0x03;
ctrl = RB_BAT_MON_EN | ((vl >> 2) & 1);
}
else
{
cfg = vl & 0x03;
ctrl = RB_BAT_DET_EN;
}
sys_safe_access_enable();
R8_BAT_DET_CTRL = ctrl;
R8_BAT_DET_CFG = cfg;
sys_safe_access_disable();
mDelayuS(1);
sys_safe_access_enable();
R8_BAT_DET_CTRL |= RB_BAT_LOW_IE | RB_BAT_LOWER_IE;
sys_safe_access_disable();
}
}
/*********************************************************************
* @fn LowPower_Idle
*
* @brief 低功耗-Idle模式
*
* @param none
*
* @return none
*/
__HIGH_CODE
void LowPower_Idle(void)
{
FLASH_ROM_SW_RESET();
R8_FLASH_CTRL = 0x04; //flash关闭
PFIC->SCTLR &= ~(1 << 2); // sleep
__WFI();
__nop();
__nop();
}
/*********************************************************************
* @fn LowPower_Halt
*
* @brief 低功耗-Halt模式,此低功耗切到HSI/5时钟运行,唤醒后需要用户自己重新选择系统时钟源
*
* @param none
*
* @return none
*/
__HIGH_CODE
void LowPower_Halt(void)
{
uint8_t x32Kpw, x32Mpw;
FLASH_ROM_SW_RESET();
R8_FLASH_CTRL = 0x04; //flash关闭
x32Kpw = R8_XT32K_TUNE;
x32Mpw = R8_XT32M_TUNE;
x32Mpw = (x32Mpw & 0xfc) | 0x03; // 150%额定电流
x32Kpw = (x32Kpw & 0xfc) | 0x01; // LSE驱动电流降低到额定电流
sys_safe_access_enable();
R8_BAT_DET_CTRL = 0; // 关闭电压监控
sys_safe_access_disable();
sys_safe_access_enable();
R8_XT32K_TUNE = x32Kpw;
R8_XT32M_TUNE = x32Mpw;
sys_safe_access_disable();
sys_safe_access_enable();
R8_PLL_CONFIG |= (1 << 5);
sys_safe_access_disable();
PFIC->SCTLR |= (1 << 2); //deep sleep
__WFI();
__nop();
__nop();
sys_safe_access_enable();
R8_PLL_CONFIG &= ~(1 << 5);
sys_safe_access_disable();
}
/*******************************************************************************
* Function Name : LowPower_Sleep
* Description : 低功耗-Sleep模式。
注意当主频为80M时,睡眠唤醒中断不可调用flash内代码,且退出此函数前需要加上30us延迟。
* Input : rm:
RB_PWR_RAM2K - 2K retention SRAM 供电
RB_PWR_RAM24K - 24K main SRAM 供电
RB_PWR_EXTEND - USB 和 BLE 单元保留区域供电
RB_PWR_XROM - FlashROM 供电
NULL - 以上单元都断电
* Return : None
*******************************************************************************/
__HIGH_CODE
void LowPower_Sleep(uint16_t rm)
{
__attribute__((aligned(4))) uint8_t MacAddr[6] = {0};
uint8_t x32Kpw, x32Mpw;
uint16_t power_plan;
GetMACAddress(MacAddr);
x32Kpw = R8_XT32K_TUNE;
x32Mpw = R8_XT32M_TUNE;
x32Mpw = (x32Mpw & 0xfc) | 0x03; // 150%额定电流
x32Kpw = (x32Kpw & 0xfc) | 0x01; // LSE驱动电流降低到额定电流
sys_safe_access_enable();
R8_BAT_DET_CTRL = 0; // 关闭电压监控
sys_safe_access_disable();
sys_safe_access_enable();
R8_XT32K_TUNE = x32Kpw;
R8_XT32M_TUNE = x32Mpw;
sys_safe_access_disable();
sys_safe_access_enable();
R16_POWER_PLAN &= ~RB_XT_PRE_EN;
sys_safe_access_disable();
PFIC->SCTLR |= (1 << 2); //deep sleep
power_plan = R16_POWER_PLAN & (RB_PWR_DCDC_EN | RB_PWR_DCDC_PRE);
power_plan |= RB_PWR_PLAN_EN | RB_PWR_CORE | rm | (2<<11);
sys_safe_access_enable();
R8_SLP_POWER_CTRL |= RB_RAM_RET_LV;
R16_POWER_PLAN = power_plan;
sys_safe_access_disable();
if((rm & RB_XT_PRE_EN) == 0)
{
sys_safe_access_enable();
R8_PLL_CONFIG |= (1 << 5);
sys_safe_access_disable();
}
__WFI();
__nop();
__nop();
sys_safe_access_enable();
R16_POWER_PLAN &= ~RB_XT_PRE_EN;
sys_safe_access_disable();
if((rm & RB_XT_PRE_EN) == 0)
{
sys_safe_access_enable();
R8_PLL_CONFIG &= ~(1 << 5);
sys_safe_access_disable();
DelayUs(20);
}
}
/*********************************************************************
* @fn LowPower_Shutdown
*
* @brief 低功耗-Shutdown模式,此低功耗切到HSI/5时钟运行,唤醒后需要用户自己重新选择系统时钟源
* @note 注意调用此函数,DCDC功能强制关闭,唤醒后可以手动再次打开
*
* @param rm - 供电模块选择
* RB_PWR_RAM2K - 2K retention SRAM 供电
* RB_PWR_RAM16K - 16K main SRAM 供电
* NULL - 以上单元都断电
*
* @return none
*/
__HIGH_CODE
void LowPower_Shutdown(uint16_t rm)
{
uint8_t x32Kpw, x32Mpw;
FLASH_ROM_SW_RESET();
x32Kpw = R8_XT32K_TUNE;
x32Mpw = R8_XT32M_TUNE;
x32Mpw = (x32Mpw & 0xfc) | 0x03; // 150%额定电流
x32Kpw = (x32Kpw & 0xfc) | 0x01; // LSE驱动电流降低到额定电流
sys_safe_access_enable();
R8_BAT_DET_CTRL = 0; // 关闭电压监控
sys_safe_access_disable();
sys_safe_access_enable();
R8_XT32K_TUNE = x32Kpw;
R8_XT32M_TUNE = x32Mpw;
sys_safe_access_disable();
SetSysClock(CLK_SOURCE_HSE_6_4MHz);
PFIC->SCTLR |= (1 << 2); //deep sleep
sys_safe_access_enable();
R8_SLP_POWER_CTRL |= RB_RAM_RET_LV;
sys_safe_access_disable();
sys_safe_access_enable();
R16_POWER_PLAN = RB_PWR_PLAN_EN | rm;
sys_safe_access_disable();
__WFI();
__nop();
__nop();
FLASH_ROM_SW_RESET();
sys_safe_access_enable();
R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET;
sys_safe_access_disable();
}