Windows CE
Windows CE从4.0版本引入电源管理器(Power Manager)来提供管理电源框架。 电源管理器负责管理设备电源,提高操作系统整体能耗效率,并且与不支持电源管理功能的设备和应用兼容,在内核OAL层、设备驱动程序和应用程序之间充当中间人角色。电源管理器还严格区分系统的电源状态与设备的电源状态,让一些智能设备可管理自己的电源状态。
电源管理器结构
电源管理器直接或间接地与应用程序和驱动程序交互。电源管理器与驱动程序主要通过驱动程序接口进行交互,与应用程序通过API和提醒接口进行交互,如图3所示。
Windows CE系统电源状态的改变可以作为一个OEM事件,或者通过OEM的应用程序和工具调用SetPowerState()函数产生。Windows CE支持以下几种电源状态:(1)ON状态,用户在主动使用设备。(2)UserIdle状态,用户与设备停止交互,但仍有可能使用设备。(3)SystEMIdle状态,在经过一段时间的UserIdle后进入此状态,但是驱动和系统仍然活动。(4)Suspend状态,当驱动程序和系统进程不再与系统交互时进入此状态。(5)ColdReboot和Reboot状态,冷启动后系统电源状态。
Windows CE设备电源状态管理和系统相分离。驱动程序需要实现:(1)响应电源管理器的请求,报告它的电源能力。(2)处理电源管理器发送的电源请求。(3)启动后给设备加电。(4)关闭时给设备停止供电。(5)如果它可以唤醒系统,则为设备启用唤醒功能。设备还可以通过调用RegisterPower Relationship()函数告诉电源管理器它为独立的子设备驱动处理电源请求。例如总线设备驱动或某些设备驱动代理。
电源管理器和支持电源管理的设备之间的交互包括两种机制:(1)电源管理器到驱动程序,电源管理器使用DevICeIoControl()函数向设备驱动程序发送I/O控制(IOCTLs)。设备必须能响应管理器的电源管理能力查询、状态设置等IOCTLs。(2)驱动程序到电源管理器,驱动程序使用DevicePower Notify()函数与电源管理器交互,请求电源管理器把它的设备置于某种状态。如果电源管理器接受该请求则通过发送IOCTL_POWER_SET等IOCTLS来进行设置。
Windows CE应用程序与电源管理有两种交互机制:(1)应用程序接口,用以获取当前系统和设备的电源状态;(2)电源事件提醒接口,提供电源事件的提醒。应用程序接口中,GetSystemPowerState()函数用来返回当前系统电源状态。SetSystemPowerState()函数可被OEM程序或者其他应用程序调用,来把系统电源状态设置为需要值。SetDevicePower()用来设置设备电源状态。为了实现提醒接口,应用程序还得通过CreatEMSgqueue()函数建立消息队列,将其句柄传给电源管理器。而后电源管理器把提醒发送到消息队列中,调用者可选择可用提醒的一个子集进行响应。
在Windows CE中,在OAL层,电源管理需要实现OEMIdle()和OEMPowerOff()函数。当系统中没有任何可调度的线程时,操作系统调用OEMIdle()函数,可以在其中实现降低处理器的频率以达到省电的目的。当有外部中断时,CPU可从其中恢复。OEMPowerOff函数基于硬件平台实现,进行CPU寄存器保存、设置及唤醒恢复等功能。
嵌入式Linux
嵌入式Linux电源管理结构
Linux标准内核标准电源管理有ACPI、APM等机制。这些机制依赖于PC机的BIOS功能实现。 嵌入式系统 一般都没有实现BIOS支持,对其能耗管理机制需要进行其他定义。消费类电子产品联盟—CELF对能耗管理作了定义,其框架如图4所示。
图4 CELF电源管理规范
CELF的能耗管理框架分为内核层和用户层。内核层又划分为体系结构无关层和体系结构相关层。体系结构相关层主要提供可管理硬件支持,例如处理器电压和运行频率调节,各种总线运行频率管理,设备的关断管理等。内核体系结构无关层在体系结构相关层的基础上为用户层提供APIs,进行各种能耗管理功能的支持。它包含一个能耗管理(PM)引擎,根据系统任务负载选择系统运行状态;提供能耗管理的挂起和恢复方法;提供VST技术,通过估计下次准确唤醒时间来确保在进入深度睡眠时,不被原来固定时间产生的定时器中断唤醒;还包含了各种外部设备关闭/开启的操作逻辑。
用户通过编制具有一定智能的管理策略驻留程序,利用系统提供的能耗管理机制,进行有效的系统能耗管理。
此外,在某些实现中,也可以将ACPI中的BIOS调用进行映射,在内核用 软件 实现回调函数,用以支持没有BIOS的电源管理。
嵌入式Linux内核电源管理实现分析
2.6内核提供了一个电源管理框架,在其基础之上容易实现各种电源管理规范,例如ACPI和APM规范。2.6内核中的设备驱动模型(Linux Driver Model,LDM)是内核对电源管理基础支持。Kobject基本结构嵌入到描述设备模型的组件的bus、devices、 drivers结构中。这些容器就是通过kobject连接起来形成树状结构。每个对象的属性(attribute)以文件形式输出到kobject对应的sysfs目录下。通过这种文件系统接口,可以对平台进行有效的电源管理。
就嵌入式系统而言,电源管理可以分为静态电源管理,动态电源管理,设备电源管理等三个方面。
静态 电源管理
Linux内核支持ON, Standby, Suspend, 和Hibernate四种电源状态。Standby指“带电挂起”,通过将CPU置于halt状态,将设备置于D1状态来达到节能的目的(ACPI规范中按能耗从高到低分D0~D3)。节能效果不明显,但是响应延迟最小。Suspend就是挂起到RAM。在该状态下,所有设备被置于D3状态,整个系统,除主存处于节电的自刷新模式(self-refresh)外,全部关闭电源。响应延迟比Standby大。Hibernate 是通过将系统状态保存到非易挥发性存储中(通常是磁盘),关闭整个系统的电源。延迟时间最长,但比一次完整启动来得短。通常情况下嵌入式设备都没有支持这种方式。
通过sysfs文件系统接口触发系统级电源状态转化。转换管理是通过注册好的驱动来进行。例如,prepare函数确认系统能够进入所请求的状态,并且进行相应的准备工作。例如通过禁止抢占和“冷冻”所有进程来准备进入所请求的电源状态。Save函数枚举所有注册有电源管理能力的设备,保存系统和处理器的低层状态。接着PM核心禁止了中断,关闭外部设备电源,调用Sleep函数根据挂起级别进入睡眠状态。在嵌入式设备挂起过程中可以通过写入某些特殊的非易失性处理器寄存器来记录挂起的原因和挂起时的代码执行地址。系统上电后引导程序先执行,从特殊寄存器中判断系统是否从深度睡眠(Hibernation)中恢复。如果是,则负责从非易挥发性存储介质中恢复所有的硬件上下文。如果不是,系统负责从sleep()函数处返回。给所有设备上电,恢复中断。Restore函数被用来恢复系统的低层调用,恢复设备上下文。Cleanup函数从sleep状态恢复必须进行的清尾工作,例如抢占重新被允许,系统恢复正常执行。当一次完整的转换完成后,CPU执行权还给之前执行的进程。
(1)动态电源管理原理
如图5所示,系统无任务时进入空闲,可被中断唤醒,处理完后重新进入空闲或者回到任务态。如果系统被挂起到RAM中,进入深度睡眠。可以关闭除了中断控制器和唤醒源之外的所有设备,实现最大限度地省电。根据运行时不同的任务负载,系统应该有对应的不同电源级别。如图示中的任务、任务-、任务+等代表电源需求的状态。在完成任务的同时,进行最大化的节能。