低功耗模式分为两种:1、掉电模式(shutdown),2、睡眠模式(sleep 或者 standby)
1、睡眠模式
即规格书中说的 Standby 模式,电流功耗 1.1uA,只有 RTC,RAM/CPU 保持运行
int_fast16_t Power_sleep(uint_fast16_t sleepState)
参数说明
sleepState 目前只支持 PowerCC26XX_STANDBY
示例:
Power_sleep(PowerCC26XX_STANDBY);
2、掉电模式
只能通过外部中断唤醒,电流功耗 100nA
int_fast16_t Power_shutdown(uint_fast16_t shutdownState, uint_fast32_t shutdownTime)
参数说明
shutdownState:没有使用
shutdownTime:没有使用
注意:
调用该 API 时需要先禁用所有中断
睡眠之前,需要调用函数PINCC26XX_setWakeup配置管脚唤醒
示例:
PIN_Config ButtonTableWakeUp[] = {
CONFIG_PIN_BUTTON_0 | PIN_INPUT_EN | PIN_PULLUP | PINCC26XX_WAKEUP_NEGEDGE,
PIN_TERMINATE /* Terminate list */
};
/* Configure DIO for wake up from shutdown */
PINCC26XX_setWakeup(ButtonTableWakeUp);
/* Go to shutdown */
Power_shutdown(0, 0);
3、注册监听电源状态
int_fast16_t Power_registerNotify(Power_NotifyObj * pNotifyObj, uint_fast16_t eventTypes, Power_NotifyFxn notifyFxn, uintptr_t clientArg)
参数说明
pNotifyObj: 通知对象结构体
eventTypes: 需要注册的事件类型
notifyFxn: 回调函数
clientArg: 回调函数的参数
4、TIRTOS睡眠
使能睡眠功能,通过TI图形化配置工具,选中Enable Policy,或者通过代码调用Power_enablePolicy/Power_disablePolicy来使能/禁止
a、配置完成后系统自动生成以下代码
const PowerCC26X2_Config PowerCC26X2_config = {
.enablePolicy = true,
.policyInitFxn = NULL,
.policyFxn = PowerCC26XX_standbyPolicy,
.calibrateFxn = PowerCC26XX_calibrate,
.calibrateRCOSC_LF = true,
.calibrateRCOSC_HF = true,
.enableTCXOFxn = NULL
};
b、待机策略函数是 PowerCC26XX_standbyPolicy 也可以通过代码调用Power_setPolicy设置
c、在Power_idleFunc函数会调用 PowerCC26XX_standbyPolicy (在Power_init函数已经把PowerCC26X2_config.policyFxn赋值给PowerCC26X2_module.policyFxn,而PowerCC26X2_config.policyFxn初始化时就赋值为PowerCC26XX_standbyPolicy)
void Power_idleFunc()
{
if (PowerCC26X2_module.enablePolicy) {
if (PowerCC26X2_module.policyFxn != NULL) {
(*(PowerCC26X2_module.policyFxn))();
}
}
}
d、Power_idleFunc函数在空闲任务中被调用
#pragma location = ".const_ti_sysbios_knl_Idle_funcList__A"
const __T1_ti_sysbios_knl_Idle_funcList ti_sysbios_knl_Idle_funcList__A[1] = {
((xdc_Void(*)(xdc_Void))(Power_idleFunc)), /* [0] */
};
e、睡眠策略函数 PowerCC26XX_standbyPolicy
void PowerCC26XX_standbyPolicy(void)
{
bool justIdle = TRUE;
uint32_t constraints;
uint32_t ticks, time;
/* disable interrupts */
CPUcpsid();
/* check operating conditions, optimally choose DCDC versus GLDO */
SysCtrl_DCDC_VoltageConditionalControl();
/* query the declared constraints */
constraints = Power_getConstraintMask();
/* do quick check to see if only WFI allowed; if yes, do it now */
if ((constraints &
((1 << PowerCC26XX_DISALLOW_STANDBY) | (1 << PowerCC26XX_DISALLOW_IDLE))) ==
((1 << PowerCC26XX_DISALLOW_STANDBY) | (1 << PowerCC26XX_DISALLOW_IDLE))) {
/* Flush any remaining log messages in the ITM */
ITM_flush();
PRCMSleep();
/* Restore ITM settings */
ITM_restore();
}
/*
* check if any sleep modes are allowed for automatic activation
*/
else {
/* check if we are allowed to go to standby */
if ((constraints & (1 << PowerCC26XX_DISALLOW_STANDBY)) == 0) {
/*
* Check how many ticks until the next scheduled wakeup. A value of
* zero indicates a wakeup will occur as the current Clock tick
* period expires; a very large value indicates a very large number
* of Clock tick periods will occur before the next scheduled
* wakeup.
*/
ticks = Clock_getTicksUntilInterrupt();
/* convert ticks to usec */
time = ticks * Clock_tickPeriod;
/* check if can go to STANDBY */
if (time > Power_getTransitionLatency(PowerCC26XX_STANDBY,
Power_TOTAL)) {
/* schedule the wakeup event */
ticks -= PowerCC26X2_WAKEDELAYSTANDBY / Clock_tickPeriod;
Clock_setTimeout(Clock_handle((Clock_Struct *)&PowerCC26X2_module.clockObj), ticks);
Clock_start(Clock_handle((Clock_Struct *)&PowerCC26X2_module.clockObj));
/* Flush any remaining log messages in the ITM */
ITM_flush();
/* go to standby mode */
Power_sleep(PowerCC26XX_STANDBY);
/* Restore ITM settings */
ITM_restore();
Clock_stop(Clock_handle((Clock_Struct *)&PowerCC26X2_module.clockObj));
justIdle = FALSE;
}
}
/* idle if allowed */
if (justIdle) {
/* Flush any remaining log messages in the ITM */
ITM_flush();
/*
* Power off the CPU domain; VIMS will power down if SYSBUS is
* powered down, and SYSBUS will power down if there are no
* dependencies
* NOTE: if radio driver is active it must force SYSBUS enable to
* allow access to the bus and SRAM
*/
if ((constraints & (1 << PowerCC26XX_DISALLOW_IDLE)) == 0) {
uint32_t modeVIMS;
/* 1. Get the current VIMS mode */
do {
modeVIMS = VIMSModeGet(VIMS_BASE);
} while (modeVIMS == VIMS_MODE_CHANGING);
/* 2. Configure flash to remain on in IDLE or not and keep
* VIMS powered on if it is configured as GPRAM
* 3. Always keep cache retention ON in IDLE
* 4. Turn off the CPU power domain
* 5. Ensure any possible outstanding AON writes complete
* 6. Enter IDLE
*/
if ((constraints & (1 << PowerCC26XX_NEED_FLASH_IN_IDLE)) ||
(modeVIMS == VIMS_MODE_DISABLED)) {
SysCtrlIdle(VIMS_ON_BUS_ON_MODE);
}
else {
SysCtrlIdle(VIMS_ON_CPU_ON_MODE);
}
/* 7. Make sure MCU and AON are in sync after wakeup */
SysCtrlAonUpdate();
}
else {
PRCMSleep();
}
/* Restore ITM settings */
ITM_restore();
}
}
/* re-enable interrupts */
CPUcpsie();
}
任务空闲时,程序会调用PowerCC26XX_standbyPolicy,根据当前系统的状态进入不同的睡眠模式,并根据最短的那个任务调度时间设置定时唤醒。
参考官方文档“Power_Management.pdf”