动态功耗与时钟速度成正比,是计算机系统功耗的重要组成部分。减少CPU负载是减少功耗的一种方法,另一种方法是在空闲模式下降低CPU时钟速度。
动态CPU功耗
在大多数计算系统中,CPU是主要的能源消耗者。CPU消耗的动态功率取决于时钟频率和空闲模式的时间。现代CPU有一条或多条指令可以在空闲时使用,在ARM架构处理器中,指令为WFI(等待中断)或WFE(等待事件)。它们将时钟门控到CPU的一个部分,消除了CPU空闲时的动态功耗。
典型的代码实现:
OS_Idle(void) {
for (;;) {
__wfi();
}
}
编写高效的程序
减少CPU执行代码的时间以最大化空闲时间是有意义的,可以通过高效的编程(智能算法)、好的编译器和高效的运行时库来实现。
嵌入式系统实现的另一个要点是不等待硬件(如下例所示):
// Wait until data is ready
while (NAND_FLASH_BUSY);
让就绪信号触发中断,或者在循环中执行定期检查或延迟(如OS_TASK_Delay_us(30))。SEGGER的embOS-Ultra允许以微秒为单位设置延迟,非常适合硬件通常所需的短时间延迟。
在大多数情况下,中断是最好的方法,但它需要能够产生相应中断的硬件,不通用,并且需要程序员做更多的工作。
空闲时的动态CPU消耗
在空闲模式下仍然有CPU动态功耗!这是因为某些组件(如中断控制器)一直有时钟。因此,即使CPU处于空闲模式,其动态功耗仍然与时钟速度成正比,这意味着在空闲模式下降低时钟速度是一种节能的方法。
空闲模式下的功耗低于执行程序时的功耗,但仍然相当高。我们发现,在J-Link和Flasher中使用的Xilinx Zynq芯片中,空闲时功耗约为执行程序时的50%。在主频600MHz时,CPU使用了大约45mW的动态功耗,将速度降低到200 MHz,测量大约节省30 mW。这意味着如果我们相应地修改OS_Idle(),我们可以节省大约30mW!
OS_Idle(void) {
for (;;) {
// Implemented in a hardware layer, usually only a single write to an sfr to change the clock divider
HW_CPU_SetIdleSpeed();
__wfi();
}
}
在一个设计良好的系统中,CPU的大部分时间都处于空闲状态。缺点是每个中断发生后,都需要将CPU切换回更高的速度(或者至少是那些必须快速响应的CPU)。CPU对中断的反应会稍微慢一些,但是如果以原始速度的1/16运行CPU,应该不会对响应时间产生太大影响。或者只减到1/2,仍然可以节省50%的动态空闲消耗。
然而,ARM将Cortex CPU中的系统计时器与CPU频率相结合,降低CPU频率,也降低了系统计时器的频率。如果系统计时器用于定时,则会出现问题。
解决方法是当改变CPU速度时,动态地重新编程系统计时器,或者使用不同时基的计时器。
嵌入式系统中还有其他的电力消耗(泄漏)来源,有很多事情可以做,以减少嵌入式系统的功耗。但在空闲模式下降低CPU速度,有着惊人的效果!
END