400 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			400 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(); | |||
|  | } |