《ARM Cortex-M0 权威指南》笔记(9)—低功耗特性
1. 低功耗概述
总体来说,Cortex-M0处理器包含以下低功耗特性:
两个架构相关的休眠模式:普通休眠和深度休眠。
两个指令用于进入休眠模式:WFE(等待事件)和WFI(等待中断)。这两个指令都可用于普通休眠和深度休眠。
退出休眠特性(从异常退出):使得中断驱动的应用程序可以尽可能地处于休眠模式。
可选的唤醒中断控制器(WIC):应用这种特性,处理器处于深度休眠时,其时钟完全关闭。
2. 休眠模式
Cortex-M0具有两种休眠模式:
普通休眠
深度休眠
一般来说,可以通过以下方法来降低休眠时的功耗:
停止部分或所有的时钟信号;
降低微控制器某些部分的时钟频率;
降低微控制器各部分的电压;
关掉微控制器某些部分电源;
可以通过下面三种方法进入休眠模
执行WFE指令
执行WFI指令
利用退出休眠特性
进入普通休眠模式还是深度休眠模式,由SLEEPDEEP控制位决定。该位位于系统控制块(SCB)区域中的系统控制寄存器(SCR),寄存器中还包括了Cortex-M0的低功耗特性的控制位。使用CMSIS操作,可使用寄存器 “SCB->SCR”来访问。关于SCB的介绍,参考章节 1.7 系统异常控制寄存器
使用CMSIS,可以按照 “SCB -> SCR” 的方式来访问系统控制寄存器。例如:
SCB -> SCR |= 1<<2; // 使能深度休眠特性
不同休眠模式以及不同休眠操作产生多种组合,如下:
3. 等待事件(WFE)和等待中断(WFI)
Cortex-M0处理器进入休眠模式,可以使用两条指令:WFE 和 WFI。WFE可以被中断请求以及事件唤醒,而WFI则只能被中断请求和调试请求唤醒。
使用CMSIS,对应的内置函数,如下:
3.1 等待事件(WFE)
当使用WFE进入休眠以后,可以通过以下的中断或事件来唤醒:
新挂起的中断(仅当系统控制寄存器中的SEVONPEND置位时有效);
外部事件请求;
调试事件;
Cortex-M0处理器内部有一个事件寄存器,并且只有一位有效。处理器在运行中并且有事件发生时,寄存器置1,并且该信息将保存到处理器执行WFE指令。可以通过以下任何事件来置位事件寄存器:
产生了需要服务的中断请求;
异常进入和异常退出;
不管中断是否允许,有新的挂起中断(仅当系统控制寄存器中的SEVONPEND置位时有效);
发送事件(SEV)指令执行;
调试事件。
在处理器唤醒后发生的多个事件会被当成一个事件。
如上图,当处于WFE状态的处理器被事件寄存器中存储的事件唤醒后,寄存器就会被清零。
如果在执行WFE指令时,事件寄存器已经置位,则事件寄存器会被清零,WFE指令也会马上结束,并且处理器不会进入休眠。
如果执行WFE指令时事件寄存器没有置位,则处理器会进入休眠,下一个事件将唤醒处理器,并且事件寄存器会保存清零状态。
如上图,在轮询循环中,WFE可以用于降低功耗。例如,若外设能够产生适用于WFE的事件,则处理器就可以在外设的任务完成后唤醒。由于处理器可以被不同的事件唤醒,所有处理器被唤醒后,也应该检查任务是否已经完成。
如果SCR中的SEVONPEND置位,任何挂起的中断都会产生事件并且唤醒处理器。如果执行WFE时中断已经处于挂起状态,则同一中断的新的请求不会产生事件,并且处理器也不会被唤醒。
3.2 等待中断(WFI)
WFI指令可以被以下方式唤醒:调试请求,或比当前优先级高的中断请求。
WFI操作还有一个特殊用途,也就是在WFI休眠期间,如果PRIMASK屏蔽了某中断该中断的优先级大于当前优先级,那么该中断仍然可以唤醒处理器,只有在PRIMASK清除之前,处理器不会执行该中断处理。
有了这种特性,就可以关闭微控制器的某些部分(如外设总线时钟),而唤醒后执行中断服务程序之前再将它们打开。
3.3 唤醒条件
当处理器利用退出休眠(sleep-on-exit)特性或者执行WFI指令进入休眠之后,就会停止指令执行,并且当发生了中断请求(更高优先级)并且需要处理时,处理器就会唤醒。
如果处理器在异常处理中进入了休眠,并且新产生的中断的优先级与当前相等或者更低,那么处理器将不会被唤醒,并且保持在挂起状态。
处理器也可以通过复位或者调试器的暂停请求唤醒。
在执行WFE指令时,处理器的动作取决于事件锁存的当前状态:
如果事件锁存置位,那么WFE指令完成,它将会被清零,并且处理器不会进入休眠;
如果事件锁存清零,那么处理器会在事件发生前保持在休眠状态;
此处的事件,指以下任何一个:
待处理的中断请求;
进入或退出中断处理;
暂停调试请求;
片上硬件的外部信号(设备相关)
SEVONPEND置位并且产生了新的挂起中断;
执行SEV(发送事件)指令;
处理器内的事件锁存可以保持过去发生的事件的状态,以前的事件也可以将处理器从WFE指令唤醒。因此,WFE一般用于空循环或者轮询循环,它能够让处理器进入休眠是不确定的。
WFE和WFI指令的唤醒条件,如下:
WFI和WFE唤醒条件比对,如下:
这里有个问题,为什么在PRIMASK置位时,处理器不能执行中断服务程序却可以被唤醒?
如上,根据这种特性,处理器可以在执行中断服务程序前进行系统管理任务(例如,恢复外设的时钟)。
4. 退出休眠(sleep-on-exit)特性
退出休眠(sleep-on-exit)是Cortex-M0处理器低功耗特性之一,当其被使能时,如果处理器从异常处理器中退出时没有其他异常等待执行,则自动进入等待中断的休眠模式。
退出休眠特性非常适合中断驱动的应用程序。当该特性使能时,只要完成了异常处理并且返回了线程模式,处理器就会进入休眠模式,而从一个异常处理返回到另外一个异常处理则不会引发处理器休眠(即嵌套中断)。利用退出休眠特性,处理器可以尽可能多处于休眠模式。
处理器的运行情况如下:
退出休眠特性通过以下两点来降低系统功耗:
中断驱动的应用无需执行线程中不必要的程序;
减少了两次中断之间不必要的压栈和出栈操作;
退出休眠特性由系统控制寄存器中的 SLEEPONEXIT位控制,在中断驱动程序中对该位的置位一般为初始化操作的最后一步完成。否则,如果在初始化期间产生中断,则处理器可能此时就是进入休眠。
使用CMSIS,可以按照 “SCB -> SCR” 的方式来访问系统控制寄存器。例如:
SCB -> SCR |= 0x02; // 强系统控制寄存器的SLEEPONEXIT置位 while(1) { __WFI(); // 执行WFI并进入休眠 }
实际应用中,低功耗模式一览(以STM32F051xx为例),如下:
STM32F051xx系列有三种低功耗模式:
睡眠模式 (Sleep mode) (CPU 时钟关闭 , 所有外设包括内核外设如 NVIC, SysTick, 等仍在 运行 )
停止模式 (Stop mode) ( 所有时钟都停止 )
待机模式 (Standby mode) (1.8V 供电域断电 )
模式 | 进入 | 唤醒 | 对 1.8V 区域 时钟的影响 | 对 VDD 区域 时钟的影响 | 电压调节器 |
---|---|---|---|---|---|
睡眠 (SLEEP-NOW 或SLEEP-ON-EXIT) | WFI | 任一中断 | CPU时钟关闭,对其它时钟及ADC时钟无影响 | 无 | 开 |
WFE | 唤醒事件 | ||||
停机 (Stop) | PDDS和LPDS 位+ SLEEPDEEP 位+ WFI 或 WFE | 任一外部中断(在EXTI寄存器中设置)指定通信口接收事件(CEC,USART, I2C) | 关闭所有1.8V区域时钟 | HSI和HSE振荡器关闭 | 开启或处于低功耗模式(依据(电源控制寄存器PWR_CR的设置) |
待机(Standby) | PDDS位+SLEEPDEEP位+WFI或WFE | 唤醒引脚上升沿,RTC 闹钟,NRST脚的外部复位,IWDG复位 |