概述
单片机的开发过程中,我们会遇到功耗模式管理的问题。
通过功耗模式管理,我们可以实现在需要高性能的时候使用高频率的时钟,以及使用大电流。
在待机的时候,使用低频率时钟,甚至关掉时钟,此时采用小电流(可以达到uA级别)。
如果采取精细化管理,这种操作可以具体到某一个内存块,或者某一个外设都可以做单独的时钟和电源管理配置。

所以功耗管理,包含以下几个方面:

  • 时钟管理
  • 电源管理
  • 唤醒管理

其实,单片机的研发者也很不容易,因为各种应用千差万别。
如果把系统的管理功能做得很强大,就会带来极大的复杂性。
如果做得很简单,有可能又不能满足某些应用的需求。

 

RT1170上搞功耗管理必须知道的知识

各个相关的模块列表:

Clock Control Module (CCM) :时钟管理,源控制、时钟频率生成
Low Power Clock Gating (LPCG) :时钟使能管理
General Power Controller (GPC):功耗模式管理,功耗模式的切换以及SP的切换,是功耗管理的核心单元
Power Management Unit (PMU):电源管理,比如DCDC, LDO
System Reset Controller (SRC):复位管理
Resource Domain Controller(RDC):资源域管理器

 

RT1170的电源管理域

CM7, CM4 WAKEUP, DISPLAY, MEMGA, LPSR, SNVS

 

 

 

 

CPU的工作模式 

typedef enum _gpc_cpu_mode
{

kGPC_RunMode = 0x0UL, /*!< Stay in RUN mode. */
kGPC_WaitMode = 0x1UL, /*!< Transit to WAIT mode. */
kGPC_StopMode = 0x2UL, /*!< Transit to STOP mode. */
kGPC_SuspendMode = 0x3UL, /*!< Transit to SUSPEND mode. */

} gpc_cpu_mode_t;

 

SDK核心函数解析

// 模式转换统一入口

void PowerModeTransition(gpc_cpu_mode_t cpuMode, uint8_t sleepSp, uint8_t targetSp, gpc_cm_wakeup_sp_sel_t wakeupSel, bool stbyEn)
{

… …

if (cpuMode == kGPC_RunMode)
{

// 这里是只切SP的核心代码
gpc_cm_run_sp_tran_config_t runSpTranConfig;
runSpTranConfig.enableRunTransition = true;
runSpTranConfig.setPointRun = targetSp;
GPC_CM_RequestRunModeSetPointTransition(GPC_CPU_MODE_CTRL, &runSpTranConfig);
WaitForSpTransitionDone();

}
else
{

// to STOP/SLEEP/STANDBY mode
GPC_ConfigCpuMode(cpuMode);
gpc_cm_sleep_sp_tran_config_t sleepSpTranConfig;
sleepSpTranConfig.enableSleepTransition = true;
sleepSpTranConfig.setPointSleep = sleepSp;
sleepSpTranConfig.enableWakeupTransition = true;
sleepSpTranConfig.setPointWakeup = targetSp;
sleepSpTranConfig.wakeupSel = wakeupSel;
GPC_CM_RequestSleepModeSetPointTransition(GPC_CPU_MODE_CTRL, &sleepSpTranConfig);
SystemEnterSleepMode(cpuMode);

}

}

// Run to Run, switch SP

void GPC_CM_RequestRunModeSetPointTransition(GPC_CPU_MODE_CTRL_Type *base, const gpc_cm_run_sp_tran_config_t *config)
{

uint32_t tmp32 = base->CM_SP_CTRL;

tmp32 &= ~(GPC_CPU_MODE_CTRL_CM_SP_CTRL_CPU_SP_RUN_MASK);
if (true == config->enableRunTransition)
{

tmp32 |= GPC_CPU_MODE_CTRL_CM_SP_CTRL_CPU_SP_RUN_EN_MASK |
GPC_CPU_MODE_CTRL_CM_SP_CTRL_CPU_SP_RUN(config->setPointRun);

}

base->CM_SP_CTRL = tmp32;

}

// Run to Sleep

void GPC_CM_RequestSleepModeSetPointTransition(GPC_CPU_MODE_CTRL_Type *base, const gpc_cm_sleep_sp_tran_config_t *config)
{

… …

if (true == config->enableSleepTransition)
{
    tmp32 |= GPC_CPU_MODE_CTRL_CM_SP_CTRL_CPU_SP_SLEEP_EN_MASK |
    GPC_CPU_MODE_CTRL_CM_SP_CTRL_CPU_SP_SLEEP(config->setPointSleep); // Sleep下切到哪个SP
}
if (true == config->enableWakeupTransition)
{
    tmp32 |= GPC_CPU_MODE_CTRL_CM_SP_CTRL_CPU_SP_WAKEUP_EN_MASK |
    GPC_CPU_MODE_CTRL_CM_SP_CTRL_CPU_SP_WAKEUP(config->setPointWakeup) | // Wakeup的时候,如果要切到新的SP,指定该SP
    GPC_CPU_MODE_CTRL_CM_SP_CTRL_CPU_SP_WAKEUP_SEL(config->wakeupSel); // Wakeup的时候,是返回原来的SP还是指定的SP
}

base->CM_SP_CTRL = tmp32;

}

 

版权声明:本文为nxa16038原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/nxa16038/p/13785315.html