如何从软件上实现低功耗
降低功耗是每个便携式产品开发人员的设计目标之一,但功耗不仅仅与硬件设计有关,控制软件也会对产品的功耗产生很大影响。不管是操作系统、BIOS控制程序还是外设驱动程序,这些软件编写的方式决定了最终产品的功耗水平,因此在开发时必须加以考虑。本文介绍四种通过软件降低功耗的方法,可供中国的设计工程师们参考。
作为嵌入式软件工程师,我们需要在质量与效率之间寻求平衡。为此,我们要优化软件性能,使之能在速度较慢而价格低廉的处理器上运行;我们要调整软件大小,这样就能使用更小且更便宜的存储器。现在随着为手持式和无线装置编写的软件越来越多,我们还需要优化产品的功耗,以延长小型低成本电源的寿命。
有个好消息是,无论你在开发操作系统、外设驱动程序还是应用程序,现在已有多种软件设计技术可以帮助降低功耗,下面我们重点讨论其中的四种方法。
很多最新的嵌入式处理器都具有能降低功耗的电源工作模式,最常用的是空闲模式,此时处理器内核指令执行部分关闭,而所有外设和中断信号仍有电并起作用。空闲模式比处理器执行指令时的功耗要小得多。
空闲模式一个主要特点是其进入退出基本上不需要额外开销,通常一个毫秒可以反复很多次。任何时候只要操作系统检查到所有线程都处于阻塞状态如等待中断、事件或定时时间,它都可以把处理器置于空闲模式以省电。由于任何中断都能把处理器从空闲模式中唤醒,所以采用这种模式可使软件智能等待系统事件,不过为最大程度提高电源效率,该工具要求我们认真地设计软件。
我们都编写过这样的代码,如记录状态寄存器内容并等待设定标记出现,也许是检查串口的FIFO状态标记,看是否收到数据;也许是监测一个双端口存储器看系统中是否有另外处理器写入一个变量,使我们能控制共享资源。尽管从表面上看这样的代码没有什么问题,但在每个时钟周期里不断记录寄存器状态将无法有效延长手持装置的电池寿命。
更好的解决办法是使用一个外部中断来表明状态何时改变。在单线程软件环境里,你可以调用处理器空闲模式降低功耗直到发生实际事件,出现中断时,处理器自动唤醒然后继续执行后面的代码。
空闲模式甚至能用于事件不能直接连接到外部中断的场合,在这种情况下,用一个系统定时器定期唤醒处理器是个很好的方法。例如你在等待一个事件并且知道只要事件发生后在一毫秒内能检测到都能迅速做出处理,那么可以启动1ms定时器并把处理器置于空闲模式,每次中断时检查事件状态,如果状态没有变化,就立刻回到空闲模式。
这种等待机理应用很普遍,现今大多数PDA和智能电话都是由具有空闲模式功能的处理器和操作系统控制。事实上,很多这些设备每秒会多次进出空闲模式,只要有触摸、按键或时间到就会被唤醒。
减少事件
另一种可以考虑的技术是减少事件。智能等待是使处理器尽可能高频率地进入空闲模式,减少事件则是尽可能长时间地将处理器置于空闲模式,它通过分析代码和系统要求来决定你是否能改变处理中断的方式实现。
例如一个通过时隙安排线程的多任务操作系统,一般设定的定时中断通常在只有1ms的时隙间隔发生。假定你的代码很好利用了智能等待技术,操作系统会频繁使处理器置于空闲模式,并一直维持直到被中断唤醒。当然,在这种情形下,最有可能唤醒处理器的中断是定时器中断本身。即使所有其它线程被阻塞,在其它中断、内部事件及长时间延迟之前,定时器中断也会以每秒1,000次的频率把处理器从空闲模式中唤醒,以运行调度安排程序。
但就算调度安排程序确定所有线路都被阻塞,并很快将处理器回复到空闲模式,这样频繁操作也会浪费大量电源。在这样的情况下,进入空闲模式时应关闭时隙中断信号,只有再次出现中断信号时才被唤醒。
当然把时隙中断完全关闭通常不太合适。尽管多数阻塞的线程可以直接或间接等待外部中断,有些在特定时间还是服从于操作系统。例如一个驱动器会在等待外设时睡眠500ms,这时空闲模式下如果完全关闭系统定时器,可能意味着线路不能按时恢复工作。
操作系统最好能为调度安排程序进行可变超时设定。操作系统知道每个线程是否无法确定等待的是外部还是内部事件,或者计划在某特定时间再次运行,操作系统可算出第一个线程预定何时运行,并相应地在处理器置于空闲模式之前设定定时器工作。可变超时设定不会对调度安排程序造成很大的负担,但却能节省电源和处理时间。
可变计划超时限定只是减少事件的一种方法,存储器直接存取(DMA)也可让处理器长时间处于空闲模式,即使数据正在发送至外设或从外设收取。所以只要可能,都应在外围驱动器中使用DMA,省电效果相当令人满意。
例如英特尔公司StrongARM处理器串口接收FIFO时,大约每收到8个字节发生一次中断,在115,200bps速度下,发送到这个端口的11KB脉冲数据会引起处理器内核每秒中断1,500次,很可能使其从空闲模式中唤醒,但如果实际上你不需要在这些小的8字节设备中处理数据,浪费是很惊人的。DMA最好与大容量缓冲器一起使用,以使中断发生的水平更加容易管理,或许是每秒10次或100次,让处理器在两次中断之间空闲。事实证明,在这些场合应用DMA能减少使用率达20%,可降低CPU功耗并提高供其它线程使用的处理器带宽。
性能控制
动态时钟和电压调整代表了微控制器在降低功耗方面的最新进展,电源管理的这种进展是基于以下观察,即处理器消耗的能量与驱动处理器的时钟频率以及应用其内核上的电压平方成正比。
处理器允许动态降低时钟速度为节省电源迈出了第一步,降低一半时钟速度,功耗将成比例下降。但是光采用这种技术有效实现节能需要一些技巧,因为执行的代码可能要两倍长的时间才能完成,那样的话也不会省电。
动态降低电压是另一种做法。越来越多的处理器允许降低电压,以适应处理器时钟速度的下降,这样在降低时钟速度时也能省电。事实上,只要处理器不饱和,频率和电压就能不断减少,这样还是能完成工作,而消耗的电源总体上却比较低。
考虑到并不是所有线程都消耗同样多处理器带宽,所以即使这些方法也还是可以改进的。有效应用处理器带宽的线程会随着处理器时钟速度下降而花更长的时间才能完成,这些线程使用分配给它们的每一个周期。另一方面,I/O约束线程采用分配给它的所有处理器周期,即便处理器时钟速率下降也要用同样长的时间才能完成。
举一个例子,像很多PDA使用的PC卡(以前称为PCMCIA卡)接口,当数据写入快闪存储卡时,系统瓶颈不是处理器的速度,而是物理总线接口以及卡的固件为擦掉和重新编程闪存所花的时间。理想情况下,上面讨论的智能等待技术可在这里应用以最大程度降低功耗,但是等待时间经常变化很大,远小于操作系统运行时间,所以智能等待会影响到性能。这些驱动程序常常检测状态寄存器,此时降低时钟速度将节省一部分电源,但会对数据写入卡时间产生轻微影响(多数处理器循环用于查询)。
当然,问题是要知道何时能降低时钟频率和电压而不会显著影响性能。作为软件开发商,考虑什么时候降低驱动器和应用代码的时钟速度比较难处理,该技术在多任务处理环境中更加富有技巧性。
智能关机
迄今为止,我们只讨论了设备在运行时能做什么,现在让我们来考虑关闭时会出现什么情况。我们很多人都希望,打开PDA后它会处于我们上次使用结束时的状态,假如我们正在输入一个新的联系信息时关机,那么我们一周或一月以后重新打开还将在这个地方。这可以采用智能关机程序实现,该程序能有效地“骗过”任何执行应用软件,使其以为设备根本就没有关闭。
在用户按下电源按钮关闭设备时,有一个中断给操作系统发出关机信号,然后的动作包括保存系统最底层寄存器内容。操作系统实际上没有关闭程序,只是把其内容(代码、栈、堆、静态数据)留在存储器里,然后把处理器置于睡眠模式,关闭处理器内核和外设,但继续供电给重要的内部电路,如实时时钟。此外,靠电池支持的DRAM在睡眠模式期间保持自刷新状态,以使其内容完整无缺。
再次按下电源按钮时,一个中断发信号唤醒处理器。唤醒中断服务程序(ISR)采用求校验和程序来验证处理器内部状态恢复之前DRAM的内容仍然保持原样。由于DRAM应含有与关机时一样的数据,所以操作系统能直接回到设备关闭时运行的线程,就应用而言,它甚至根本不知道发生了什么。
说这个方法省电主要原因是它避免了需要处理器大量计算且耗时的重启工作。一个复杂设备重新启动要花好几秒时间,其间系统装载驱动程序。从用户的立场来看,这个时间是浪费,因为他在这段时间实际上不能用设备。考虑到需要多次开关的这种电池驱动装置,智能关机程序有很大意义,一是降低了功耗,二是提高了可用性。
智能关机另一个重要特性是在睡眠模式期间可最大程度降低功耗。由于电池驱动设备会一整夜或整个周末放在一边的桌上,需要电源刷新DRAM和部分处理器外设接口,所以电池实际上在睡眠期间也会损失一些能量,最大限度减少睡眠模式下的功耗可以一次充电用上数周,而不用每天都给电池充电。
减少睡眠模式下的功耗需要分析系统硬件,并确定如何将其设置为尽可能最低的电源状态。大多数电池驱动系统在睡眠模式期间仍然要给通用I/O引出端供电。这些I/O引出端作为输入可用做中断以唤醒设备,作为输出则用于给外接外设进行配置。认真考虑这些引出端如何配置将对睡眠模式下的功耗产生很大影响。
例如把某个I/O引脚配置成输出,它将被上拉到Vcc,但如果在关机时把引出端设置为逻辑0将会导致电流穿过睡眠模式下的上拉电阻。另外,如果把一个引脚设置为输入而不与输出端连接,它将会漂浮引起虚假的逻辑变换,从而增加功耗。重要的是,应分析这些情况并适当配置引脚。
本文结论
有很多技术可以用来降低电池驱动装置的功耗,有些简单易懂,有些则不是如此。幸运的是,由于嵌入式装置中的电源管理越来越重要,设计人员未来在很多地方都能得到支持,如已经出现的软件技术就可以有助于降低功耗。同时,研究人员还在研究能优化代码的编译器,以进一步降低功耗,而且你还可以让软件开发工具自动考虑这些电源管理技术。