STM32的低功耗模式有3种:
- 睡眠模式:CM3内核停止,外设仍然运行。
- 停止模式:所有时钟都停止,SRAM 和寄存器内容保留。最低2uA左右的电流,一般不用。
- 待机模式:1.8V内核电源关闭,只有备份的寄存器和待机电路各维持供电。最低2uA左右的电流,一般不用。
模式 | 说明 | 进入语句 | 唤醒方式 | 对1.8V区域时钟影响 | 对VDD区域时钟影响 | 调压器 |
睡眠 | 内核及其外设停止工作,系统时钟(SysTick)等仍在工作 | _WFI() | 任一中断 | 内核时钟关,对其他时钟无影响 | 无 | 开 |
_WFE() | 唤醒事件 | |||||
停止 | 所有时钟都停止 | PWR_EnterSTOPMode() | 任一外部中断 | 关闭所有1.8V区域的时钟 | HSI和HSE时钟关闭 | 开启或处于低功耗模式 |
待机 | 1.8V电源关闭 | PWR_EnterSTANDBMode() | WKUP引脚的上升沿、RTC闹钟事件、复位按键、IWDG复位 | 关 |
WFI和WFE区别:
1. WFI需要中断才能唤醒,WFE是不经过中断的。
2. WFE还会受控于一个1BIT Event Register,此寄存器软件不可访问。此功能时为多核而准备的。
WFE在 Event Register 为0,或为1时,其功能是不一样的。WFE的E就是指这个事件寄存器。
进一步描述:假设两个核,分别为core1和core2,
A、core1可以执行SEV指令更改Event Register,同时它可以
通过TXEV硬连接到core2的RXEV更改core2的Event Register。
B、core1在执行WFE时,如果发现Event Register=1,它是不会进低功耗的,这里就是区别。
基于以上描述WFE是多核低功耗用的,举个例子:当core1和core2抢同一个资源A时,
core1占据A,那core2就WFE进低功耗,等待core1的SEV发过来。
3. WFE因为可以等待事件,因此在某些不能WFI的场合可以采用WFE。比如唤醒后,
系统需要做一些恢复操作才能响应中断,那采用WFE先唤醒系统,完成芯片所需的恢复操作。
FREERTOS中的低功耗:tickless模式
开启自带的低功耗模式(睡眠模式):将宏定义 configUSE_TICKLESS_IDLE 配置为 1 。
系统自动调用低功耗模式满足以下2个条件:
- 当前只有空闲任务正在运行,所有其他的任务处在挂起状态或者阻塞状态。
- 当系统运行于低功耗模式 的时钟节拍数大于宏定义 configEXPECTED_IDLE_TIME_BEFORE_SLEEP (系统默认是2个系统时钟节拍,用户定义必须大于2)。
函数 portSUPPRESS_TICKS_AND_SLEEP 是实现tickless的关键,此函数被空闲任务调用,在portmacro.h中。
在自带的tickless模式基础上实现停机模式,步骤如下:
在FreeRTOSConfig.h定义如下两个函数:
#define configPRE_SLEEP_PROCESSING(x) OS_PreSleepProcessing(x)
#define configPOST_SLEEP_PROCESSING(x) OS_PostSleepProcessing(x)
在port.c里面的函数vPortSuppressTicksAndSleep调用了上面两个函数。
void OS_PreSleepProcessing(uint32_t vParameter)
{
(void)vParameter;
/*用户可以考虑在此处加入关闭外设时钟来进一步降低功耗*/
vParameter = 0;
PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFE);
}
void OS_PostSleepProcessing(uint32_t vParameter)
{
/*当上面关闭了外设,在这里恢复*/
/*恢复外部时钟配置*/
RCC_HSEConfig(RCC_HSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET){}
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while (RCC_GetSYSCLKSource() != 0x08){}
}