4.7 电源管理 第二部分 ---- Windows CE设备驱动开发之电源管理

2019-07-13 23:34发布

Windows CE设备驱动开发之电源管理      第二部分 4.7.2、电源状态 电源管理器期望所有被管理的设备能支持一个或多个设备电源状态。设备电源状态的数量是有限的。设备必须通知电源管理器其功耗特性。设备常以功耗换取性能。 电源管理器在OEM定义的系统电源状态下管理设备电源状态。系统电源状态在注册表中定义,可以用任意数字定义。系统电源状态会给设备电源状态设置一个上限。 某些应用程序可能需要特定设备保持运行在指定的设备功率等级上。例如:当一个音频播放程序在播放音乐时,可能需要网卡及音频解码器保持运行在高功率等级。视频播放程序可能需要网络、音频,同时可能要使显示设备在进入屏幕保护模式后一直显示,并保持背光常亮。应用程序可以请求电源管理器设置最小设备电源状态,电源管理器会调用SetPowerRequirement和ReleasePowerRequirement系统API来进行设置。 4.7.2.1              设备电源状态 设备电源状态是预定义的静态值。电源管理器将设备状态传给驱动程序,驱动程序负责将其映射为自身的设备性能,然后在物理设备上进行状态转换。 下表是对各种设备电源状态的描述。 设备电源状态 注册表键值 描述 Full on D0 此状态表示设备已开启或正在运行。设备将以系统允许的最大功耗及最高性能运行。 Low on D1 此状态表示设备已开启或正在运行,但以低于D0状态的功耗及性能运行。D1状态适用于设备已经被使用,但以较低的性能运行即可,没有必要以最大性能运行,会产生额外的功率消耗。 Standby D2 此状态表示设备被部分供电,保证设备在需要时能自动唤醒。 Sleep D3 睡眠状态。保证唤醒的最小供电,在需要时能自动唤醒并初始化。 Off D4 关闭状态,不供电。 一种物理设备并不能支持上述所有的设备电源状态。但是,所有的设备都必须支持D0设备电源状态。如果驱动程序收到请求,要求其将设备进入它不支持的电源状态,驱动程序应使设备进入下一个支持的电源状态。例如:电源管理器请求设备进入D2电源状态,但设备并不支持D2状态,这时如果设备支持D3或D4状态,驱动程序应使设备进入D3或D4状态。如果某一设备需要进入D3状态,但是此设备却不能唤醒系统,那么应使此设备进入D4状态。上述这些规则可以使驱动程序的执行简单化。 电源管理器有选择的将系统电源状态映射为对应的设备电源状态。例如:如果设备仅支持D0及D4电源状态,那么,电源管理器不会直接请求设备进入D4电源状态。如果D3或D4被设为此设备的最小电源状态,电源管理器会一直等待直到系统进入D3或D4状态时,再将设备设为D4状态。如果此设备的最小电源状态被设为D0、D1或D2,电源管理器将使设备一直运行于D0状态。 当设备驱动程序被加载时,应将设备设为D0状态。在驱动程序被卸载时,应将设备设为D4状态。如果在启动时设备进入了D0外的其他设备电源状态,那么可以在处理IOCTL_POWER_CAPABILITIES时发出一个DevicePowerNotify请求。   4.7.2.2              系统电源状态 系统电源状态由OEM定义,并由OEM引用。OEM可以将其命名为像On,SystemIdle,OnBattery,InCradle,OutOfCradle等名称。这些名称并没有被系统预定义,也不要求将其定义为线性序列。系统电源状态在系统配置注册表键中定义。Windows CE并没有限制可以定义多少种系统电源状态。 当然,也可以创建系统电源状态与预定义的设备电源状态的显式映射。显式映射需要在注册表中定义。系统电源状态明确的制定系统中所有设备的最大设备电源状态。 电源管理器示例定义了On,UserIdle,SystemIdle及Suspend四种系统电源状态。当用户使用系统时,电源状态设为On。如果用户停止使用,电源状态被设为UserIdle。当用户在一定的周期内(如30s)不使用系统,则进入SystemIdle状态;只要设备驱动程序处于活动状态,系统将一直保持在SystemIdle状态。如果设备驱动程序停止活动,系统进入Suspend状态。 UserIdle状态用于用户正在使用设备,但却没有操作设备。例如,用户一直观看屏幕显示,但没有手动操作。SystemIdle状态被用于用户没有直接使用设备,但处理器仍在继续运行。例如,在传输文件期间,用户可能人为设备已处于空闲状态,但实际上处理器依旧在持续运行,直到文件传输完成。 电源管理器示例实现了根据UserActivity和SystemActivity定时器对用户及系统活动进行判断。在定时器超时后,根据当前系统供电状况(使用外接电源或电池)进行不同的系统电源状态切换。 Platform Builder提供的Windows CE运行时image示例均使用外接电源供电模式。你可以选择实现一套在使用电池供电时的电源状态。复制电源管理器示例代码的PDD目录,并对其做适当的修改即可。 4.7.2.2.1   将系统电源状态映射为设备电源状态 在注册表系统配置中明确定义系统电源状态名称。系统电源状态到设备电源状态的映射在注册表的每一个电源状态名称键值下被枚举。如下示例代码: [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/Example]     Default=dword:0; D0     Flags=dword:10000; POWER_STATE_ON     COM1:=dword1; D1 上面的注册表片段定义了名为Example的系统电源状态,并设置了除COM1:被限制为最高运行于D1设备电源状态外,其他的所有设备最高均可运行于D0设备电源状态。其中Flags列是一个标识码,用于表示Pm.h头文件中定义的POWER_STATE_ON标记。如果需要,OEM可以定义自己的电源状态标记。 下表列出了键值名称及其描述。 键名 描述 Name 系统电源状态名称 Flags 标识码。用于表示在Pm.h头文件中预定义的类似于POWER_STATE_ON的标记。 Default 表示在此系统电源状态下时,所有设备的默认设备电源状态。此键值用数字表示,0代表D01代表D1,以此类推。 DeviceName 设置在此系统电源状态下指定设备的最大设备电源状态。可以对任意数目的设备进行定义。   电源管理器支持多种设备类型的映射。例如:NDIS迷你接口及块设备驱动器设备类型在Pm.h中会被指定为其自身的GUID类型。其他类型被管理设备的默认值也可以在注册表中指定。例如: [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/Example/{98C5250D-C29A-4985-AE5F-AFE5367E5006}]     Default=dword:1; D1     "CISCO1"=dword:0; D0 上面注册表片段设置电源管理器限值所有NDIS迷你接口设备在Example系统电源状态下时均运行于D1设备电源状态,只有名为CISCO1的设备最高可运行于D0状态。   4.7.2.2.2   系统电源状态切换 电源管理器在下列情况下进行系统电源状态切换: l         OEM定义的状态切换事件发生。 l         应用程序调用SetSystemPowerState OEM定义的事件可能包含设备供电从外接电源切换为使用电池供电,延长系统空闲周期,将设备插入底座(Cradle),电池电量低等。OEM需要根据情况修改电源管理器,以便判断两种系统电源状态间的切换是否合理,并在必要时切换系统电源状态。Platform Builder提供的电源管理器源代码仅支持在设备从外接电源切换为使用电池供电时进行系统电源状态切换。 应用程序可以使用系统电源状态名或表示系统电源状态的数值为参数调用SetSystemPowerState函数。如果应用程序了解OEM定义的系统电源状态,那么可以选择使用电源状态名进行显式调用。对于独立于平台的应用程序,则设置数值进行调用,并允许电源管理器决定如何进行电源状态映射。电源管理器可对应用程序能请求的状态进行限制。   4.7.2.2.3   系统电源状态示例 下面的注册表片段是表示系统电源状态到设备电源状态映射的示例。 [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/On]     "Default"=dword:0           ; D0     "Flags"=dword:10000         ; POWER_STATE_ON [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/UserIdle]     "Default"=dword:1           ; D1     "Flags"=dword:0 [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/SystemIdle]     "Default"=dword:2           ; D2     "Flags"=dword:0 [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/Suspend]     "Default"=dword:3           ; D3     "Flags"=dword:200000        ; POWER_STATE_SUSPEND ; @CESYSGEN IF CE_MODULES_NDIS [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/Suspend/{98C5250D-C29A-4985-AE5F-AFE5367E5006}]     "Default"=dword:4           ; D4 ; @CESYSGEN ENDIF CE_MODULES_NDIS 下表描述了上面注册表片段的映射方式。 系统电源状态 设备电源状态 On D0 UserIdle D1 SystemIdle D2 Suspend D3。NDIS迷你接口单独被映射为D4。 当系统使用上面的注册表配置,并进入Suspend状态,除了NDIS迷你接口会被关闭外,其他可唤醒源都将处于可激活状态。如果有设备不支持D3状态,它将自动进入D4状态。 应用程序可以使用SetPowerRequirement创建设备电源要求。也可以使用电源管理器控制面板程序创建附加的设备电源要求。   4.7.2.3              设备及系统电源状态名称 电源管理器要求使用小写字母命名设备及系统电源状态名称。一些类似于wsprintf(buf, "%u", n)或不区分大小写的比较这样的操作,会涉及区位表(Locale table)查询。区位表(Locale table)Wince.nls内存映射文件中被实现。在挂起期间,电源管理器不能使用FileSystemPowerFunction访问文件系统。从挂起的线程中访问文件系统可能造成操作系统死锁。如果Wince.nls中必须的页面无法在内存中找到,就会产生死锁。 在处理API调用时,电源管理器将名称转换为小写字母。然而,在挂起及恢复状态时,电源管理器在文件系统操作被禁止后访问注册表。这时不能将注册表设置项转换为小写。所以必须将系统电源状态注册表设置改为小写字母。例如:WAV1:应被描述为wav1:。其他类似于注册表HKLM/Drivers/Builtin下的用于控制设备驱动加载的设置项不用修改。