低功耗系统设计
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.5 软件低功耗设计

软件可以区分为“系统软件”、“实时操作系统”和“应用软件”。软件对于一个低功耗系统的重要性常常被人们忽略。一个重要的原因是,软件上与功耗设计有关的缺陷并不像硬件那样容易发现,同时软件的低功耗特性也没有一个严格的标准来判断。而对于一个低功耗系统设计,设计者必须注意软件的低功耗设计方法,尽可能避免那些“看不见”的功耗损失周文.嵌入式系统低功耗设计方法研究[D].湖南师范大学硕士学位论文,2008.车健.嵌入式系统中的低功耗设计考虑.[EB/OL].http://www.ed-china.com/ART_8800011853_400011_500009_TS_41d96a85.HTM.孟海斌,张红雨.超低功耗嵌入式系统设计技巧.单片机与嵌入式系统应用.2010.8:16-19.胡叔军.基于MPC8270的嵌入式系统研究和低功耗设计[D].北京邮电大学硕士学位论文,2008.

1.5.1 编译优化

在微处理器执行的程序中,每一条指令都将激活微处理器中的某些硬件部件。因此,可以认为每一条指令都有一个固定的功率消耗量,正确选择指令可以降低微处理器的功耗。通过建立特定处理器架构下指令集的功耗信息,采用“减少跳转的指令重排序”等方法,可以有效地优化软件的低功耗设计。

编译器的作用是将由高级语言(如C/C++等)编写的程序,翻译成能够在目标机上执行的程序。编译器为高级语言程序员提供了一个抽象层,使得程序员能够不用汇编或机器语言,而直接采用高级语言代码编写解决实际问题的程序。同时,编译器也使得程序的可读性和可维护性得到保证,可以提高软件开发的效率。另外,当需要将程序移植到新的目标机时,也只需要采用相应的编译器对程序进行重新编译,而不必重新编写程序。

但在某些情况下,编译器的一些做法是以牺牲程序的执行能力为代价的,即需要增加执行的指令数。因此,通过对编译器的优化,生成效率更高的代码,可以有效地降低微处理器的功耗。

1.5.2 指令排序

对于一个微处理器,执行某一特定程序的功耗为

E=P×t (1.8)

式中,P=I×VDD(I为平均电流,VDD为微处理器的电源电压);t为程序的执行时间(t=N×T,T为指令周期,即为主频的倒数,N为程序执行的周期数)。

因此有

E=(I×VDD)×(N×T) (1.9)

由式(1.9)可见,当VDD和T都是已知量时,程序消耗的电能E与电流I和程序周期数N的乘积成正比。

可以通过建立一定的模型来测量并估计执行每条指令所需要的电流I。在一个嵌入式系统中,可以利用嵌入式微处理器中的多数据存储区域的特性,实现数据的并行处理,通过对指令的排序,减少指令的执行周期,从而达到降低功耗的目的。

现假设需要完成图1.15(a)所示的运算周文.嵌入式系统低功耗设计方法研究[D].湖南师范大学硕士学位论文,2008.,图1.15(b)所示是其相应的汇编代码。图1.15(c)所示为每个节点带有两个权值的数据依赖图(DataDependenceGraph,DDG),第一个权值表示节点在DDG中的深度,如V10的第一个权值为1,V0的第一个权值为6。假设这个权值越大,表示其优先级越高,如图1.15(c)中V0和V1具有最高的优先级。

指令排序前节点的执行顺序见表1.9。注意,表中V2(ADD)、V6(ADD)和V9(MPY)的指令与其他指令(MOVE)不同,ADD和MPY指令需要用到系统的ALU部件。在同一指令周期中,可以同时执行ALU运算及MOVE操作,但是不可以同时执行两个ALU操作。

图1.15 运算要求、汇编代码与数据依赖图

表1.9 指令排序前节点的执行顺序

节点的第二个权值,表示相关寄存器的生命周期。指令排序前的状态如图1.16所示,V0所依赖的寄存器是r0,它的生命周期为1到3,即为2。从图1.16中可以得出以下结论:此段程序总共需要11个指令周期和最少同时使用2个寄存器。

基于排序算法,将指令重新排序后的情况如图1.17所示,程序总的执行周期变为6,但是所占用的寄存器个数增加到3。由此也可以看到,程序的执行周期与寄存器的个数之间也是一个折中权衡的结果。

图1.16 指令排序前的状态

图1.17 基于排序算法的重新排序

可以通过建立一定的模型来测量并估计执行每条指令所需要的电流I。在该示例中,程序执行时所需要的总电流I=780mA。如图1.16所示,在不使用任何算法的情况,即I=N×I=11×780(mA)=8580(mA)。在图1.17中,总的执行周期数为N=6,因此电路消耗的电流为I=N×I=6×780(mA)=4680(mA)。由此可见,通过使用基于排序算法,减少了程序的执行周期,程序的执行性能得到提高。同时,由E=(I×VDD)×(N×T)可知,N的减少,也大大降低了执行程序的功耗。

优化的算法描述,主要是以减少程序的执行周期为目的,同时考虑到使用尽量少的寄存器。从优化系统的功耗层面上来看,算法的优化也是非常重要的。

1.5.3 常用的降低软件功耗的方法

采用高效率的算法可以有效地降低功耗,一些常用的方法周文.嵌入式系统低功耗设计方法研究[D].湖南师范大学硕士学位论文,2008.车健.嵌入式系统中的低功耗设计考虑.[EB/OL].http://www.ed-china.com/ART_8800011853_400011_500009_TS_41d96a85.HTM.孟海斌,张红雨.超低功耗嵌入式系统设计技巧.单片机与嵌入式系统应用.2010.8:16-19.胡叔军.基于MPC8270的嵌入式系统研究和低功耗设计[D].北京邮电大学硕士学位论文,2008.如下:

(1)用查表的方法代替实时的计算,尽量减少CPU的运算量。特别是在没有硬件浮点处理单元的MCU进行浮点处理时,直接用MCU进行浮点处理将会消耗大量的时间。将一些运算的结果预先算好,放在Flash存储器中,用查表的方法替代实时的计算,减少CPU的运算工作量,可以有效地降低CPU的功耗。很多微处理器都有快速有效的查表指令和寻址方式,用于优化查表算法。这种处理方法在离散余弦变换和A/D数据采集中能够带来可观的效率提升。

(2)对于不可避免的实时计算,应注意计算的精度,算到精度够了就应立即结束,避免“过度”的计算。在精度允许的情况下,使用简单函数代替复杂函数作近似运算,也是减少功耗的有效方法。

(3)尽量使用短的数据类型,如尽量使用字符型的8位数据替代16位的整型数据。

(4)尽量使用分数运算而避免浮点数运算等。

(5)用移位运算代替乘除法运算。采用MCU计算乘除法也是非常耗时的,如果采用左移和右移的办法来实现乘除法运算,将会减少运算时间。注意,除法的移位计算只能针对除数比较特殊的情况。

(6)采用快速算法。在搜索算法中,使用二分搜索算法和分段查找算法的效率是不同的。从理论上可以估算,在1024个测量值的查找中,二分搜索最坏情况下10次可以查找到结果,顺序搜索最坏可能需要1024次。这在测量数值更多的情况下更为突出,一个高效率的查找算法有助于减小程序运行功耗。

(7)数字信号处理中的运算,采用FFT和快速卷积等,可以节省大量运算时间。

(8)一个程序使用中断方式还是查询方式,对于很多应用来说并不那么重要,但在软件低功耗设计特性上却相差甚远。例如,ADC在采集少量的数据时,MCU读取A/D转换数据可以采用查询方式或中断方式。查询方式和中断方式的低功耗特性相差甚远。使用中断方式,MCU可以什么都不做,甚至可以进入待机或停止模式。而采用查询方式,MCU必须不停地读取I/O端口寄存器,需要消耗很多额外的功耗。

(9)采用定时器。在程序中可以采用软件延时。但是,如果系统的定时器资源充裕,在需要定时的场合,最好采用硬件定时器,当定时器到了定时时间后,向MCU发出中断请求信号,这样可以减少MCU的工作时间,进而可以降低功耗。

(10)用宏代替子程序。在程序执行的过程中,读RAM需要比读Flash更大的功耗。宏是在编译器预处理阶段进行替代,而在子程序的调用中MCU需要进行现场保护。在一次子程序调用中,因为CPU进入子程序时会首先将当前CPU寄存器推入堆栈(RAM),在离开时又将CPU寄存器弹出堆栈,这样至少对RAM有两次操作。对于程序设计来说,调用一个子程序还是一个宏,在程序写法上并没有什么不同,但宏会在编译时展开,CPU只是顺序执行指令,避免了调用子程序。唯一的问题是增加了代码的长度(代码量)。目前,MCU片内的Flash空间越来越大,对于一些不在乎程序代码量大一些的应用,用宏代替子程序无疑可以降低系统的功耗。