399 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			399 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /********************************** (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();
 | ||
|     }
 | ||
|     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();
 | ||
|         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 x32Mpw;
 | ||
|     uint16_t power_plan;
 | ||
| 
 | ||
|     GetMACAddress(MacAddr);
 | ||
| 
 | ||
|     x32Mpw = R8_XT32M_TUNE;
 | ||
|     x32Mpw = (x32Mpw & 0xfc) | 0x03; // 150%额定电流
 | ||
| 
 | ||
|     sys_safe_access_enable();
 | ||
|     R8_BAT_DET_CTRL = 0; // 关闭电压监控
 | ||
|     sys_safe_access_disable();
 | ||
|     sys_safe_access_enable();
 | ||
|     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_PWR_PLAN_EN;
 | ||
|     sys_safe_access_disable();
 | ||
| 
 | ||
|     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();
 | ||
|     R16_INT32K_TUNE = 0xFFFF;
 | ||
|     R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET;
 | ||
|     sys_safe_access_disable();
 | ||
| }
 |