Windows CE设备驱动开发之电源管理
4.7電源管理
電源管理模塊管理設備電源,從而全面改進操作系統的電源使用效率;它所有設備的電源使用,同時能與不支持電源管理的應用程序及驅動程序共存。
使用電源管理可以有效的減少目標設備的電源消耗,同時,能在運行、空閑、復位及掛起電源狀態時維持并保護RAM中的文件系統。
電源管理具有以下特性:
使設備具有自行電源管理功能的框架;
建立一種在系統中使設備電源在掛起和恢復狀態間切換的機制;
一個對系統環境、電源狀態、設備電源狀態有統一認識的模塊。你可以定制電源管理模塊,使全系統的電源分配適合您的設備;
當系統掛起或恢復時,使系統跳過所有代碼調用PowerOffSystem函數。
對于支持電源管理的驅動程序,在設備枚舉時應盡量準確的向電源管理模塊報告其性能,然后將收到來自電源管理模塊的獲取或更改其電源狀態的請求。對于自行管理電源的設備,必須通過DevicePowerNotify向電源管理模塊發送請求來更改電源狀態。
電源管理模塊與設備在一個正常的線程執行環境中通過調用DeviceIoControl進行通訊。
?
4.7.1、??????????? 電源管理架構
在不依賴Windows CE電源管理模型的情況下,只能對設備進行簡單的管理。電源管理器為OEM廠商提供了較大的靈活性,同時驅動開發人員也不用為了兼容電源管理模型而犧牲驅動程序性能。在基本的Windows CE電源模型中,在操作系統掛起或恢復時,設備會收到標識信息(notification)。這一標識信息在中斷處理時產生,所以設備在掛起狀態時可以做什么工作,有多長時間做這一工作被嚴格限制。下圖描述了Windows CE電源管理的結構。
使用電源管理器時,設備會從I/O控制代碼(IOCTLs)收到電源狀態改變通知。因為IOCTLs在線程中執行,在線程中驅動開發者可以更為靈活的處理電源狀態改變。使用IOCTLs還能夠區分設備電源狀態與系統電源狀態。這樣,在系統運行時可以將部分設備關閉,而某些設備也可以在系統掛起時一直開啟。
除了管理設備電源,電源管理器還向應用程序通知其它與電源相關事件的發生。例如:當系統從掛起狀態恢復運行時,電源管理器會向相關應用程序發出通知。
電源管理器是一個名為pm.dll的動態鏈接庫,系統運行時被Device.exe進程直接調用。當電源管理API被調用時,Device.exe調用pm.dll的入口函數。在Platform Builder 4.0及其后續版本中提供了Pm.dll的源代碼,OEM廠商可以根據其設備修改Pm.dll。
電源管理器擔任設備、應用程序及預定義的操作系統電源狀態的仲裁者。電源管理器定義了下列規則,使上述三部分以這些規則進行通訊:
l???????? 系統電源狀態限定了所有設備的最大功耗;
l???????? 應用程序以最小功耗來獲取指定設備的最低性能等級。
l???????? 當設備功耗在其最大功耗與最小功耗范圍內時,電源管理器允許設備自行管理其電源。
l???????? 如果最小功耗高于最大功耗,那么,在應用程序請求設備運行期間,設備電源將持續提升。
l???????? 設備可以在一個或多個電源狀態下運行。電源狀態以有限的數字表示。詳見設備電源狀態章節。
l???????? 系統轉為掛起狀態后,對應用程序有用的最小功耗將被取消。
l???????? 系統電源狀態是描述所有設備中最大的設備電源狀態。系統電源狀態由OEM廠商定義,并在注冊表中描述,同時,在電源管理器中可以加入部分支持代碼。OEM廠商可以定義任意數量的系統電源狀態。詳見系統電源狀態章節。
在電源管理器框架內部,OEM廠商可以定義系統電源狀態來設定最大設備電源狀態。設備調用DevicePowerNotify來控制其電源等級,應用程序調用SetPowerRequirement來確認它們需要使用的設備是否正在合適的性能等級運行。
?
4.7.1.1????????????? 電源管理器和ACPI/APM
電源管理器并不涉及高級配置與電源接口(ACPI)或高級電源管理(APM)。ACPI規范將系統電源狀態定義為一個從高功率/高性能到低功率/低性能的線性集。Windows CE電源管理器允許OEM廠商定義任意數目的系統電源狀態,但并不要求定義的系統電源狀態是線性的。
我們鼓勵開發者根據情況定義操作系統電源狀態,并根據設備定位或環境控制設備電源。例如:開發者可以定義系統電源狀態,據此可以做到在裝置不在支架(cradle)中時可以關閉某些設備,或者當系統使用外接交流電源時允許設備運行在高功耗電源等級。同樣的,開發者可以根據系統環境定義不同的空閑、掛起狀態。開發者需要定制電源管理器并保證在適當或必須的時候在各種電源狀態間切換。
系統電源狀態與ACPI模式有顯著的區別。然而,設備電源狀態表面上看起來與ACPI規范中的設備電源狀態類似,但實際上,他們仍有細微的區別。例如:在Windows CE中D3電源狀態被設定為在操作系統掛起時可使指定設備擔任喚醒源的功能。
4.7.1.2????????????? 電源掛起、恢復回調函數
掛起和恢復電源事件的回調函數與電源管理器無關。當CPU被停止,操作系統將進入掛起狀態,這時回調函數會被系統調用。并在OEMPowerOff被調用前立即執行。在電源管理器請求關閉系統電源并進入掛起狀態之前,電源管理器會時常對設備驅動進行IOCTL調用。當然,情況并不總是這樣。電源管理器框架允許設備在系統運行時被關閉,也允許設備在系統掛起時處于開啟狀態。
當設備電源狀態為D0,D1或D2,如果掉電事件發生時,開發者可以自行決定進行何種處理。此時,通常關閉設備電源,并在加電事件發生時恢復供電。如果設備可以不依賴CPU即可運行,在掛起狀態時或許可以使此設備運行。如果設備在掛起期間一直處于供電狀態,那可能是電源管理器配置錯誤,或者是應用程序使用POWER_FORCE標記對此設備進行了SetPowerRequirement調用。
?
4.7.1.3????????????? 其他電源管理API
電源管理器創建于標準的Windows CE電源體系結構的上層。所以,不管電源管理器如何運行,流接口設備驅動程序在系統掛起或恢復時總是通過XXX_PowerUp和XXX_PowerDown獲取通知。下表列出了與電源管理相關的API。
| 函數名 | 功能描述 |
| GetSystemPowerStatusEx2 | 獲取電池狀態信息。 |
| PowerPolicyNotify | 以事件的形式通知電源管理器,以便執行必要的處理,從而實現OEM創建的電源策略。 |
| OEMIdle | 被系統內核調用。在沒有線程需要運行時將處理器置為空閑狀態。 |
| OEMPowerOff | 當關機按鈕被按下,或圖形、窗體、事件子系統(GWES)超時時被調用。使處理器進入掛起狀態。 |
| XXX_PowerDown (Device Manager) | 掛起設備電源。僅用于能被軟件控制關閉的設備。 |
| XXX_PowerUp (Device Manager) | 恢復設備電源。 |
?
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代表D0,1代表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下的用于控制設備驅動加載的設置項不用修改。
Windows CE設備驅動開發之電源管理 第三部分?
4.7.3、電源管理器接口
電源管理器有三種不同的使用者。
l???????? 電源管理器能識別的設備的驅動程序。
l???????? 可能需要更改系統電源狀態或設備性能的應用程序。
l???????? 需要電源事件通知的應用程序。
電源管理器使用不同的編程接口與這些使用者進行通訊。
4.7.3.1????????????? 設備驅動接口
電源管理器使用兩種不同的機制與支持電源管理的設備驅動進行通訊。電源管理器向下調用設備驅動確定其設備性能,并更新其設備電源狀態。設備向上調用電源管理器請求進行設備電源狀態更改。向下調用在系統中以IOCTL方式實現。設備通過DevicePowerNotify API函數向上調用電源管理器。
由于電源管理器使用DeviceIoControl與支持電源管理的設備進行通訊,所以設備需要實現一個外部(expose)流接口。在某些情況下,可以用電源管理代理來實現外部流接口。網絡驅動接口規約(NDIS)中實現了一個外部流接口,從而能使用RegisterPowerRelationship API函數進行對NDIS迷你接口的代理管理。電源管理器同時提供了一種與非流接口設備的通訊機制。這一方法由具有打開設備句柄、發送請求等功能的抽象層組成。例如:位于Public/Common/Oak/Drivers/Pm/Mdd/Pmdisplay.cpp的驅動程序實現了一個基于ExtEscape函數的通訊接口。
打開名稱格式為COM1:、并實現了外部流接口的標準設備,可以對其進行讀寫。但是,電源管理器并不要求支持電源管理的設備必須使用這種命名格式;設備名稱可以是任意唯一的字符串。例如:NDIS迷你接口可以被命名為VMINI1。
盡管Platform Builder提供的電源管理器僅支持流接口驅動,但OEM可以自由的實現其他的設備接口。可以為設備定義一個新的唯一類型全局標識符(GUID)來實現新的接口。不過,驅動程序在使用新接口時必須遵循標準電源管理設備驅動準則。
默認情況下,電源管理器可以發現下列GUID表示的設備類型:
l???????? {A32942B7-920C-486b-B0E6-92A702A99B35} 此GUID類型為普通被管理設備。
l???????? {8DD679CE-8AB4-43c8-A14A-EA4963FAA715} 此GUID類型為塊設備。
l???????? {98C5250D-C29A-4985-AE5F-AFE5367E5006} 此GUID類型為NDIS設備。
應用程序可以從HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power /Interfaces注冊表鍵中獲取可被管理的設備類型的列表。
當應用程序調用一個引用了指定設備的電源管理器API時,應用程序必須指定設備的GUID類型名。如果沒有指定設備的GUID類型名,電源管理器會假定此設備為普通被管理設備類型。
有效的設備類型名需要有GUID前綴及反斜杠符號。例如:GUID {8DD679CE-8AB4-43c8-A14A-EA4963FAA715}/DSK1:表示引用一個名為DSK1的塊設備。
電源管理器從注冊表讀取設備類型列表,使用RequestPowerNotifications決定此類型的設備在什么時候被載入。下面時設備類型列表的示例。
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/Interfaces] ??? "{A3292B7-920C-486b-B0E6-92A702A99B35}"="Generic power-manageable devices" ??? "{8DD679CE-8AB4-43c8-A14A-EA4963FAA715}"="Power-manageable block devices" ??? "{98C5250D-C29A-4985-AE5F-AFE5367E5006}"="Power-manageable NDIS miniports"Platform Builder附帶的電源管理器以上述設置執行。如果不定義新的設備注冊表鍵,在注冊表中可以不包含上述設置。下面步驟說明了實現一個表示使用ExtEscape直接管理的顯示驅動類型的過程。
1.???? 使用Guidgen.exe創建一個新的GUID類型,并將其添加到注冊表中。
2.???? 為了識別GUID,需要修改電源管理器,并使用ExtEscape與設備通訊。
3.?????? 調用AdvertiseInterface,使用新的GUID修改顯示驅動。
?
4.7.3.1.1???? IOCTL設備控制符
電源管理器使用下列IOCTL碼與設備通訊:
| IOCTL | 功能 |
| IOCTL_POWER_CAPABILITIES | 要求設備通知電源管理器它所支持的電源狀態及其特性。 |
| IOCTL_POWER_SET | 要求設備更新其設備電源狀態。 |
| IOCTL_POWER_QUERY | 詢問設備是否準備好可以進入另外一個設備電源狀態。 |
| IOCTL_POWER_GET | 要求設備通知電源管理器它現在的設備電源狀態。 |
| IOCTL_REGISTER_POWER_RELATIONSHIP | 通知父設備登記它所控制的所有設備。 |
?
4.7.3.1.2???? 驅動到電源管理器的API函數
電源管理器為被管理設備提供下列函數,設備可以通過調用下列函數相電源管理器請求服務。
| 函數名 | 功能 |
| DevicePowerNotify | 設備驅動調用此函數請求電源管理器更新其設備電源狀態。 |
| RegisterPowerRelationship | 總線驅動及其他代理電源管理器在需要攔截所有設備的電源IOCTL時調用此函數。 |
| ReleasePowerRelationship | 結束由RegisterPowerRelationship調用創建的代理關系。 |
?
4.7.3.2????????????? 應用程序接口
電源管理器提供了一些函數,使應用程序可以使用這些函數進行設備電源管理。下表中的API函數中,只有GetSystemPowerState、SetPowerRequirement及ReleasePowerRequirement是普通應用程序可以直接執行的。例如:應用程序可以調用SetSystemPowerState來掛起系統,但是電源管理器可以限制應用程序可以請求進入的系統電源狀態。其他的API函數是為像控制面板這樣的OEM應用程序準備的。下表是這些函數的說明。
| 函數名 | 功能 |
| GetSystemPowerState | 返回當前系統電源狀態的名稱。 |
| SetSystemPowerState | 請求電源管理器更改當前系統電源狀態。 |
| SetPowerRequirement | 請求電源管理器將指定設備的電源狀態維持在最小等級。 |
| ReleasePowerRequirement | 釋放SetPowerRequirement設置的電源狀態.將設備電源狀態恢復到調用SetPowerRequirement之前的狀態。 |
| GetDevicePower | 返回指定設備的當前電源狀態。 |
| SetDevicePower | 請求電源管理器更改指定設備的當前電源狀態。 |
?
4.7.3.2.1?? 系統電源狀態設置
某些情況下,應用程序需要更改系統電源狀態。在特定的Windows CE設備上,應用程序并不知道哪些電源狀態可用,也不期望知道這些電源狀態的特性。對應用程序而言,最好使用描述電源狀態的掩碼來調用SetSystemPowerState進行電源狀態切換,而不要使用明確的狀態名調用。電源管理器會將此掩碼轉換為對應的電源狀態。例如:應用程序可以使用POWER_STATE_SUSPEND位元請求進行系統電源狀態切換。根據在請求時系統是否在支架(cradle)中,電源管理器隨后會切換到Suspend或SuspendCradle狀態。如果設備被從支架中取下,電源管理器會將設備切換到Suspend狀態。
電源管理器可以限定應用程序可以設置進入哪些系統電源狀態。例如:如果電源管理器使用外部輸入控制系統電源狀態,那么,當系統使用電池供電時,將不會允許進入ACRun狀態。Platform Builder附帶的電源管理器僅允許應用程序設置系統進入Suspend狀態。
下表描述了預定義的電源狀態位元及其含義。
| 位元 | 描述 |
| POWER_STATE_ON | 高性能高功耗。 |
| POWER_STATE_OFF | 所有設備都被關閉。 |
| POWER_STATE_CRITICAL | 電池低電量。 |
| POWER_STATE_BOOT | 系統正在啟動。 |
| POWER_STATE_IDLE | 空閑狀態。 |
| POWER_STATE_RESET | 清除文件,關閉設備并調用KernelIoControl. |
| POWER_STATE_SUSPEND | 掛起操作系統并最終調用OEMPowerOff. |
Platform Builder附帶的電源管理器并沒有使用上表中全部狀態。OEM可以根據其設備自行定義狀態標記。
如果應用程序使用SetSystemPowerState請求進入一個新的電源狀態,電源管理器將進行以下處理:
l???????? 廣播PBT_TRANSITION通知。
l???????? 如果需要更新所有設備的電源狀態。如果設備已處于一個可被新的電源狀態接受的電源狀態下,電源管理器就不會進行IOCTL_POWER_SET請求。
l???????? 如果設備從掛起狀態恢復,電源管理器廣播PBT_RESUME通知。
?
4.7.3.2.2?? 設備電源需求
在某些情況下應用程序需要改變電源管理器對系統電源狀態的管理。例如:某頁面調度程序需要使COM3:保持運行在D3或更高的狀態,即使在掛起時也以此電源狀態運行,從而在COM3:收到一個輸入頁時能喚醒系統。或者,例如一個流音頻程序可能需要網卡及音頻系統即便在系統使用電池供電,并以及空閑了一段時間的情況下也能保持在全功耗(Full Power)運行。電源管理器提供SetPowerRequirement API函數為有特定電源管理需求的應用程序提供支持。
SetPowerRequirement API函數允許應用程序請求電源管理器在設備電源狀態上設置一個較低的下限。如果電源要求有效,電源管理器則不允許設備將自己的電源狀態設為低于要求的下限值。當電源管理器更改系統電源狀態時,如果設備需要維持在高于系統電源狀態所允許的設備電源狀態,電源管理器通常會使設備保持此電源狀態。
當系統掛起時設備的電源需求通常會被取消。當系統處于掛起狀態時,CPU將停止運行,中斷服務也將停止。如果應用程序需要設備在掛起狀態時能繼續運行,可以在調用SetPowerRequirement時設置POWER_FORCE標記。進行此操作需要對應的設備驅動程序支持在系統掛起時自行停用。
電源管理器可能取消其他環境下的設備電源需求。例如,OEM廠商可能會重新解釋系統電源狀態POWER_STATE_CRITICAL標記,以便指示系統在使用電池供電,且電池處于低電量臨界時,應關閉所有設備。
?
4.7.3.3????????????? 通知接口
電源管理器提供了一組API函數,從而允許應用程序獲取電源相關事件的通知,并參與決策系統電源狀態的切換。下表列出了相關的API函數。
| 函數 | 描述 |
| RequestPowerNotifications | 請求電源管理器發送電源事件通知。 |
| StopPowerNotifications | 取消由RequestPowerNotifications發出的通知請求。 |
通知信息通過消息隊列傳遞。為了使用通知,應用程序需要創建一個消息隊列,并通過RequestPowerNotifications API函數將消息隊列句柄傳遞給電源管理器。通常將創建一個線程來監控消息隊列,等待消息產生。
電源管理器定義了以下幾種通知類型。
| 通知 | 描述 |
| PBT_RESUME | 當系統從掛起狀態恢復時產生。 |
| PBT_POWERSTATUSCHANGE | 當系統在AC供電及其他供電方式(如電池)間切換時產生。 |
| PBT_TRANSITION | 當電源管理器進行系統電源狀態變更時產生。 |
?
Windows CE設備驅動開發之電源管理 第四部分
4.7.4、設備電源管理指南
電源管理器對設備功耗、性能及響應時間并沒有進行嚴格的限制。只是在用戶角度而言D0及D1狀態下是可操作的,而更高編號的電源狀態比D0及D1消耗更少的電源。
本指南的目的是為了使OEM廠商能更容易的定義有意義的系統電源狀態,而不用了解特定設備的詳細功耗要求。
4.7.4.1????????????? 設備電源自管理(Device Power Self-Management)
一些設備自行管理其電源的過程可能比較復雜。當設備處于休止狀態時,驅動程序開發人員希望能降低它們的功耗。降低功耗一般會同時降低設備性能,所以當這些設備被使用時,也需要提升其性能等級。提升性能的同時也會增大設備功耗。
這些設備往往根據其被使用頻繁程度來動態的提升或降低其設備電源狀態。但電壓自管理的實際算法根據設備特性的不同而不同。
電源管理器的DevicePowerNotify API函數允許驅動開發人員請求電源管理器調整設備的電源狀態。如果所請求的設備電源狀態在允許的范圍內(即最大及最小值之間),電源管理器將允許對設備電源狀態的調整。最大值為系統電源狀態要求的值,最小值由應用程序調用SetPowerRequirement API設定。
如果電源管理器設備請求的電源狀態調整,電源管理器將調用對應的設備API更新設備電源狀態,如:使用設備的IOCTL_POWER_SET函數。在調用DevicePowerNotify函數時,需要遵循以下要求:
l???????? 當DevicePowerNotify調用成功后設備不能立即更新其電源狀態,直到IOCTL_POWER_SET被引發時才能更新。
l???????? 驅動開發人員不能認為DevicePowerNotify調用成功就意味著電源管理器一定會引發IOCTL_POWER_SET。
l???????? 驅動開發人員不能認為IOCTL_POWER_SET會被作為DevicePowerNotify調用的結果而被立即引發。
l???????? 當能夠喚醒系統的設備進入D3狀態后,不應再使用DevicePowerNotify來請求D3狀態。
一些設備能夠支持D0到D4設備電源狀態以外的其他電源等級。如果需要,驅動開發人員可以將此類設備的多個電源等級映射到電源管理器所能識別的某一設備電源狀態。設備可以不依賴電源管理器在每個設備電源狀態的允許范圍內自由的進行電源自管理。但是,設備仍然需要使用DevicePowerNotify進行設備電源狀態切換。
自管理示例
對于一個實現了所有五種電源狀態的設備,如果在一定的時間周期內無活動,需要動態的從D0降到D1狀態,或從D1降到D2狀態。這是因為D2狀態的耗電量更少,而且設備很少需要響應。如果設備發覺需要活動,但其不在D0狀態,設備將嘗試進入D0狀態。
這樣一個設備的中斷服務線程可能與下面的示例代碼類似。
while(!fDone) {
??? dwStatus = WaitForSingleObject(hInterruptEvent, dwTimeout);
??? switch(dwStatus) {
??? case WAIT_OBJECT_0: // device activity
??????? // service device
??????? ...
??????? if(deviceDx != D0 && !fBoostRequested) {
??????????? fBoostRequested = TRUE;
??????????? DevicePowerNotify(pszDeviceName, D0, POWER_DRIVER | POWER_NAME);
?
??????? }
??????? dwTimeout = INACTIVITY_TIMEOUT;
??????? break;
??? case WAIT_TIMEOUT:? // device inactive
? ??????if(deviceDx < D2 && !fReductionRequested) {
??????????? fReductionRequested = TRUE;
??????????? DevicePowerNotify(pszDeviceName, deviceDx + 1, POWER_DRIVER | POWER_NAME);
?
??????? }
??????? if(deviceDx >= D2) {
??????????? dwTimeout = INFINITE;
???? ???}
??? default:??????????? // error handling
??????? break;
??? }
}
設備的DeviceIoControl處理程序可能包含下列示例代碼。
case IOCTL_POWER_SET:
??? // update device registers
??? ...
??? deviceDx = *(PCEDEVICE_POWER_STATE) pOutBuf;
??? fBoostRequested = FALSE;
??? fReductionRequested = FALSE;
??? break;
上面驅動程序代碼僅表明了是否請求了狀態切換,而不是是否已經切換。這一點非常重要,因為設備可能在D2狀態時請求進入D0狀態,但是由于當前的電源情況,電源管理器可能僅將其設為D1狀態。在下一次設備活動時,設備會再次請求進入D0狀態,而電源管理器可能只允許其運行在D1狀態。明白了狀態切換請求的過程,能夠避免在設備進入活動狀態前進行額外的電源管理API調用。同樣的處理邏輯也用于當設備非活動超時時電源狀態降低的過程。
設備的中斷服務程序在調用DevicePowerNotify函數前設置fBoostRequested和fReductionRequested標記。這是因為DevicePowerNotify調用可能導致調用IOCTL_POWER_SET而在同一線程中再次進入驅動程序。DeviceIoControl調用會清除標記,從而使驅動程序在之后能進一步調整設備電源狀態。
4.7.4.2????????????? 如何為驅動程序添加電源管理(How to Add Power Management to a Device Driver)
開發者可以為驅動程序添加電源管理支持,以便能夠降低目標設備的功耗。為此,驅動程序必須導出流接口。如果已經實現了流接口,那么可以開始添加電源管理支持。
硬件及軟件假定
你掌握了如何從命令行創建WinCE運行時鏡像。詳見Build Tool
| 步驟 | 相關主題 |
| 1. 創建一個流接口驅動。 | How to Create a Device Driver |
| 2. 為流接口驅動添加IOCTLs。關于電源管理IOCTLs的更多信息,見Power Management IOCTLs. | Power-Manageable Device Drivers |
| 3. 通知電源管理器,驅動程序支持電源管理。見Power Management Functions. | 無 |
| 4. 在驅動程序中實現設備電源狀態。關于設備電源狀態的更多信息,見Device Power States. | Power Management Implementation in Drivers |
| 5. 編譯驅動程序。如果編譯無錯,那么你已成功為流接口驅動添加了電源管理。詳見Troubleshooting: Building a Driver. | Building a Device Driver from the Command Line |
| 6. 調試驅動程序. | How to Debug a Device Driver |
4.7.4.3????????????? 電源可管理設備驅動(Power-Manageable Device Drivers)
為了創建一個支持電源管理的設備驅動程序,必須先定義一個non-COM-related設備接口。non-COM-related設備接口表示設備支持電源管理。可以使用以下方式定義這一設備接口:
l???????? 可以在用于激活設備的注冊表鍵的IClass值中定義接口。
l???????? 可以使用驅動程序的Init函數在活動注冊表中定義IClass值。
l???????? 可以調用ActivateDeviceEx函數并使用REGINI參數來定義IClass值。
l???????? 可以在驅動程序中顯式的調用AdvertiseInterface。
關于為電源管理定義non-COM-related接口的更多信息,參見設備接口通知。可以通過調用RequestPowerNotifications函數為電源管理通知注冊設備驅動程序,同時將句柄傳遞給電源管理通知專用的消息隊列。如果驅動程序需要響應電源通知并進行相關處理,就必須這么做。通常情況下,一旦驅動程序實現了電源管理支持,那么此驅動只需要處理電源管理器的DeviceIoControl調用。
電源管理器通過IOCTL碼與設備通訊。下表列出了電源管理器與設備通訊時使用的IOCTL碼:
| Function | Description |
| IOCTL_POWER_CAPABILITIES | 請求設備驅動返回設備支持的電源狀態及相關特征 |
| IOCTL_POWER_SET | 請求驅動更新設備的電源狀態 |
| IOCTL_POWER_QUERY | 電源管理器詢問設備是否準備好進行狀態切換 |
| IOCTL_POWER_GET | 請求驅動返回當前設備的電源狀態 |
| IOCTL_REGISTER_POWER_RELATIONSHIP | 通知父設備注冊所有它所控制的設備 |
?
你可以實現并使用可選的IOCTL_POWER_QUERY控制碼,以便在驅動程序還沒有準備好改變電源狀態時,延遲電源切換。你可以通過修改MDD層來支持IOCTL_POWER_QUERY,雖然這樣修改可能會導致MDD層與電源管理器的未來版本不兼容。
4.7.4.4????????????? 在驅動程序中實現電源管理(Power Management Implementation in Drivers)
在配置驅動程序支持電源管理時,要確定驅動程序每個入口點的電源狀態。如果確定電源狀態正確無誤,那么驅動程序會根據目標設備的當前電源狀態以適當的方式運行。
確保在XXX_PowerUp被調用時驅動程序不會給目標設備加電。而應該恢復電源管理器設置的電源狀態,很可能是D3或D4這樣的狀態值。同樣,在XXX_PowerDown被調用時不會關閉目標設備電源。
注意:如果在掛起前目標設備一直沒有加電,電源管理器也沒有向其發送請求。這種情況下,驅動程序沒有正確配置,所以要在驅動程序中重新配置。
4.7.4.5????????????? 在流接口驅動中實現電源管理(Power Management Implementation in Stream Interface Drivers)
在驅動程序能夠支持電源管理之前,必須先導出一個流接口。導出的流接口會提供一組入口點以便實現標準文件I/O函數,這些函數會被kernel使用。
關于導出流接口的更多信息,見流接口驅動實現(Stream Interface Driver Implementation)。
除流接口函數外,驅動程序還必須支持IOCTL_POWER_CAPABILITIES和IOCTL_POWER_SET這兩個IOCTL。
關于IOCTL_POWER_SET的更多信息,見IOCTL_POWER_SET請求處理(IOCTL_POWER_SET Request Processing)。
關于IOCTL_POWER_CAPABILITIE的更多信息,見設備電源特性(Device Power Capabilities)。
一旦配置了流接口,就可以進一步配置驅動程序來支持電源管理。更多信息參見 4.4在驅動程序中實現電源管理。
4.7.4.6????????????? 設備類型名(Class-Qualified Device Names)
自Windows CE .NET 4.10起,支持電源管理的設備可分屬于不同的設備類型。這些設備類型由預定義類型和自定義類型組成。電源管理器API函數可以接受設備名稱,也可以接受有效地設備類型名稱(class-qualified device names)。例如,下面列出的每一名稱都是有效的設備名稱:
l???????? COM1:
l???????? {A32942B7-920C-486b-B0E6-92A702A99B35}/COM1:
l???????? {98C5250D-C29A-4985-AE5F-AFE5367E5006}/CISCO1
l???????? {8DD679CE-8AB4-43c8-A14A-EA4963FAA715}/DSK1:
如果某個設備的類型無效,那么此設備將被假定屬于默認設備類型。例如,上面COM1:和{A32942B7-920C-486b-B0E6-92A702A99B35}/COM1:是等效的。
4.7.4.7????????????? 設備初始化(Device Initialization Responsibilities)
在初始化期間,設備驅動程序應將設備置為D0狀態,同時在電源管理器通過IOCTL_POWER_CAPABILITIES詢問時應盡可能準確的匯報設備特性。
4.7.4.8????????????? IOCTL_POWER_SET請求處理(IOCTL_POWER_SET Request Processing)
電源管理器使用IOCTL_POWER_SET(設備的IOCTL碼)來調整設備的電源狀態。在實現此IOCTL碼時,驅動程序開發人員應了解下列內容:
l???????? 設備并不一定需要支持所有五種設備電源狀態,但至少必須支持D0狀態;如果設備僅支持D0狀態,那么它也不需要處理IOCTL_POWER_SET。
l???????? 電源管理器可能會要求設備進入任何設備電源狀態,并不僅僅是設備聲明支持的幾個。
l???????? 如果一個設備被要求進入一個它并不支持的電源狀態,它就會進入另一個它支持的更高功耗的狀態。例如,一個設備并不支持D2,它會被要求進入D1。
l???????? 電源管理器可能會通過發出IOCTL_POWER_SET,使設備再次進入它已經處于的當前狀態。在這種情況下,設備驅動程序簡單的返回成功即可。
l???????? 設備的電源狀態不一定與系統的電源狀態同步,因為它可能受到應用程序需求的限制。
?
4.7.4.9????????????? 掛起及恢復處理(Suspend and Resume Handling)
?
支持電源管理的流設備驅動程序通過XXX_PowerDown及XXX_PowerUp不斷接收系統掛起/恢復狀態通知。這些通知在內核調用OEMPowerOff之前的中斷處理中發出。PowerDown/PowerUp回調機制與電源管理器無關,----。
Power managed stream device drivers will continue to receive notifications of system suspend and resume states through their XXX_PowerDown (Device Manager) and XXX_PowerUp (Device Manager). These notifications are sent in an interrupt context just before the kernel calls OEMPowerOff. The PowerDown/PowerUp callback mechanism is independent of the Power Manager and allows legacy device drivers to function under Microsoft? Windows? CE .NET 4.0 and later.
驅動開發人員應該知道,當系統進入掛起狀態,處理器將不再運行。理論上,電源管理器會根據電源狀態映射,使設備進入對應的設備電源狀態。然而,掛起系統電源狀態或應用程序的設備電源需求可能不適合某些設備。例如,多媒體應用程序可能要求音頻設備保持運行在D0狀態。如果音頻芯片需要頻繁使用處理器設置DMA緩存,驅動開發人員可判定此設備在系統掛起狀態不適合運行于D0狀態,并關閉設備電源。
驅動開發者必須知道在系統處于掛起狀態時設備適合使用哪些電源狀態,從而依此實現其驅動程序。這一方法適合保守的驅動開發人員在系統掛起期間進行電源管理決策。但是,在系統掛起時并不是所有的設備都必須被關閉。例如,如果音頻設備可以不依賴處理器播放音樂,那么它可以在系統掛起期間保持供電。
如果驅動開發人員在掛起期間改變了設備的電源狀態,就必須在系統恢復的同時恢復設備的電源狀態。在系統掛起期間,這些設備應盡量保證其實際行為對電源管理器而言是透明的。
當支持電源管理的流設備通過ActivateDeviceEx被加載時,可以自動通知電源管理器。在注冊表HKEY_LOCAL_MACHINE/CurrentControlSet/Control/Power/Interfaces鍵值下的所有設備在加載時都需要通知電源管理器。如果這些設備的注冊表IClass鍵值(REG_MULTI_SZ類型)中包含類似"{A32942B7-920C-486b-B0E6-92A702A99B35}"的GUID,那么在其被加載時電源管理器會收到通知。
設備在收到IOCTL_POWER_CAPABILITIES控制碼后,可以通過調用DevicePowerNotify函數管理其自身電源。在設備處理IOCTL期間,電源管理器允許設備自行管理電源。
如果OEM廠商選擇實現非流接口的設備API,就需要定制電源管理器,使其使用新的機制與設備通訊。
?
4.7.4.10????????? D3設備狀態和系統喚醒(Device State D3 and System Wakeup)
D3設備電源狀態需要特殊考慮,因為它并不是僅僅用于限定設備的功耗等級。設備可以運行與D3狀態,從而在掛起狀態時喚醒系統,但者并不是必須的。
下列指南說明了如何在驅動程序中添加D3狀態支持:
l???????? 可以從掛起狀態喚醒系統的設備不應通過DevicePowerNotify請求進入D3狀態。這是因為在系統進入掛起狀態前,不應存在喚醒源。----。
Devices that can wake the system from a suspend state should not request the D3 state through DevicePowerNotify. This is because enabling a device as a wake source is not always appropriate, unless the system is going to enter a suspend state. The driver cannot distinguish IOCTL_POWER_SET requests for D3 that it has initiated itself from those initiated by the Power Manager as part of a system power state transition.
l???????? 可以將支持喚醒的設備的D2與D3狀態定義為相同的電壓等級,當然D2狀態不支持喚醒功能。
l???????? 不能從掛起狀態喚醒系統,但是具有一個能保持設備運行最低功耗模式的設備,在電源自管理過程中可以使用D3狀態。
l???????? 如果一個非喚醒源設備運行在D3狀態,并且系統掛起,那么它應在XXX_PowerDown處理過程切換到D4狀態;同時在XXX_PowerUp處理中恢復到D3狀態。如果做不到,就不能支持D3狀態,而應在請求進入D3狀態時直接切換到D4狀態。
l???????? 上述指南隱含說明了支持D3狀態的設備不一定能在掛起狀態喚醒系統。
總之,OEM廠商設計系統電源狀態時,應用程序開發者調用SetPowerRequirement時都需要考慮系統掛起期間D3狀態的特殊性。上述指南同時描述了OEM廠商和應用程序開發者可以在掛起期間要求設備進入D3狀態,而不用考慮設備是否支持喚醒功能。
?
4.7.4.11????????? 設備電源特性(Device Power Capabilities)
IOCTL_POWER_CAPABILITIES在即插即用設備枚舉時從驅動程序中查詢設備的具體特性,包括潛伏周期(latency)、功耗、系統喚醒及啟動功率(Inrush)。在驅動程序響應此IOCTL時也同時匯報他所支持的設備電源狀態。電源管理器一般不會要求設備進入它所不支持的電源狀態。但是,驅動開發人員不能認為這種情況不會產生。因為設備制造商可以定制電源管理器,設備制造商可能會忽略POWER_CAPABILITIES結構的DeviceDx字段。
?
Windows CE設備驅動開發之電源管理 第五部分
4.7.1、活動定時器(Activity Timers)
在初始化時,電源管理器從注冊表中讀取活動定時器名稱列表。對于每個定時器,電源管理器都會檢查其超時時間(以秒為單位)以及可選的喚醒源列表。然后創建下列事件:
l???????? 定時器重置事件
l???????? 活動狀態手動重置事件
l???????? 手動重置事件
如果超時與不產生重置事件的定時器到期關聯,電源管理器將重置活動事件并設置非活動事件。如果重置事件產生,電源管理器重置非活動事件并設置活動事件。
下列示例代碼是配置一個活動計時器的注冊表設置: [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/ActivityTimers/SystemActivity]
??? "Timeout"=dword:A
"WakeSources"=multi_sz:"0x20"
上面注冊表設置會引發電源管理器創建三個事件,分別名為:PowerManager/ActivityTimer/SystemActivity、PowerManager/SystemActivity_Active及 PowerManager/SystemActivity_Inactive。第一個事件是一個自動重置事件,任何驅動程序都可能通過發送信號表明系統處于活動狀態。支持重置活動定時器的驅動程序應從注冊表中讀取定時器的重置事件名稱。其他兩個是手動重置事件,這兩個事件在同一時刻只會產生一個,而不會同時發生。驅動程序、應用程序或電源管理器自身都可能打開這些事件的句柄,以便確定定時器是否到期。這些事件表明了活動定時器的狀態。重置事件是活動定時器的輸入,狀態事件是其對應的輸出。
除了創建事件,這一注冊表設置項還將一個喚醒源與此活動定時器關聯。如果系統恢復,并且電源管理器確定系統是由此活動定時器對應的喚醒源所喚醒,那么此活動定時器將被置為活動。電源管理器使用IOCTL_HAL_GET_WAKE_SOURCE內核IOCTL來確定是什么設備喚醒了系統。----。。
In addition to creating events, this set of registry entries associates a wake source identifier with the activity timer. If the OS resumes and the Power Manager determines that the wake source corresponding to this ID caused the system to resume, it will set the associated activity timer to active. The Power Manager uses the IOCTL_HAL_GET_WAKE_SOURCE kernel IOCTL to determine what woke the system. The active timer allows the development workstation that is in finite state to manage OS power state transitions to use the activity timer as input. It then uses that input to make a decision as to which system power state is the most appropriate to enter during the resume process. For example, the Power Manager might enter an OS power state in which the display and backlight are off. The Power Manager enters this state so that network synchronization can occur without disturbing the user.
驅動程序可以在適當的時候重置活動定時器,而在同一時刻可能有多個驅動打開句柄來重置活動定時器事件。驅動在重置活動定時器時需要從注冊表讀取事件名稱。OEM廠商可以對注冊表進行定制,通過定制注冊表,OEM廠商可以決定電源管理器如何理解驅動程序的活動。潛在的活動源包含打開句柄重置活動定時器事件的所有驅動。
會有多個線程打開句柄手動重置活動/非活動事件并等待其確定系統狀態。例如,屏幕背光驅動可以使用為活動定時器創建的一對事件來判斷如何控制背光的電源及亮度。
當系統掛起時,電源管理器重置正在活動的與活動定時器關聯的手動重置事件。在系統恢復時,電源管理器會檢測所有活動定時器,來判斷是否是由與活動定時器關聯的喚醒源引發了系統恢復。如果找到匹配項,就表明系統恢復是由其對應的喚醒源產生的活動事件引發的。
?
4.7.5.1????????????? 活動定時器行為(Activity Timer Behavior)
各種驅動程序都可以重置活動定時器,但是重置活動定時器會導致電源管理器產生一個定時器管理線程。這會給目標設備CPU造成額外負擔。為了解決這個問題,當活動事件從非活動狀態變位活動狀態時,電源管理器在定時器超時前不會再檢測重置事件。如果在此期間產生了活動事件,電源管理器不會處理而會持續等待。如果直到定時器超時都沒有重置事件,那么活動定時器會到期,同時手動重置事件的狀態會改變。
?
4.7.5.2????????????? 活動定時器超時及控制面板的電源選項(Activity Timer Time-outs and the Power Control Panel Utility)
?
活動定時器超時表示電源管理器在等待多長時間后可以判定某一活動源是非活動的。這會引發一個非活動事件。控制面板中的設置工具可以確定在保持非活動狀態多長時間后,電源管理器會進行系統電源狀態切換。
活動定時器超時時間應小于系統電源狀態超時時間,但應大于預期的活動時間間隔。例如,系統狀態超時可能是幾分鐘,而用戶活動定時器可能是10秒。這樣可以預防在正常操作時頻繁的進行活動定時器狀態切換。
控制面板的電源選項工具中列出的超時時間是累加的。也就是說,如果每個超時時間都設置為1分鐘,系統會在3分鐘后掛起。因為每個超時時間表示一次系統電源狀態切換,而系統直到掛起會進行3次狀態切換。
?
4.7.5.3????????????? 活動定時器事件(Activity Timer Events)
?
開發者可以設置在驅動程序中活動定時器事件。電源管理器在等待定時器到期期間不會等待定時器重置事件。在活動定時器超時后,電源管理器會檢測在此期間是否有重置事件被設置。如果沒有設置重置事件,定時器會被認為已經到期。如果有重置事件被設置,電源管理器將在此等待定時器。電源管理器僅在定時器到期且在此期間沒有產生重置事件,或在非活動期間第一次產生重置事件時更新手動重置定時器事件。
如果驅動程序線程運行在較高優先級時,電源管理器的活動定時器線程不會運行,即使電源管理器正在等待定時器重置事件。默認情況下,活動定時器線程運行在THREAD_PRIORITY_ABOVE_NORMAL優先級,而大多數驅動程序運行在THREAD_PRIORITY_HIGHEST或更高優先級。這將導致活動定時器線程不能搶占驅動程序線程。
?
4.7.5.4????????????? 活動定時器重置(Activity Timer Resets)
可以設置電源管理器來監測哪些應用程序正在使用socket,這比僅監測socket是否連接要好。網絡協議棧并沒有直接支持此功能。當然,你可以創建一個線程,周期性的循環調用GetTcpStatistics和GetUdpStatistics函數來確定是否有TCP或UDP報文收發操作。如果收到或發送了報文,線程可以重置活動定時器。此線程可以實現為作為電源管理器一部分的可安裝設備驅動程序;或作為某應用程序的一部分來實現。
注意:如果本地應用程序使用socket進行進程間通訊(IPC)時,GetTcpStatistics和GetUdpStatistics函數可能會返回環回通訊數據。
?
4.7.2、??????????? 掛起超時支持(Suspend Time-out Support)
你可能需要使WindowsCE設備處于非活動狀態一段時間后進入掛起狀態。可以使用以下方式進入掛起狀態:
l???????? GWES會維持一個依據用戶輸入的空閑定時器(Idle timer),并在其處于非活動狀態一段時間后掛起系統。這種方法用于Windows CE .NET 4.1 之前版本。
l???????? 電源管理器可以根據活動定時器、輸入電源及其他輸入來管理系統電源狀態。開發者可以定制電源管理器,使其能在你選擇掛起(如開始菜單的掛起按鈕)時掛起系統。
l???????? 可以編寫一個獨立的應用程序來決定什么時候掛起系統。這種情況下,GWES和電源管理器都必須配置為不對掛起狀態進行管理。
上述三種情況下,都是通過調用PowerOffSystem從而使電源管理器來掛起系統。三種情況的不同之處在于如何使系統進入掛起狀態。開發者應只使用其中一種方法,以便避免GWES、電源管理器及應用程序間的沖突。
如果電源管理器正在管理系統超時,SystemIdleTimerReset函數會通知GWES不應出現屏幕保護程序。
4.7.6.1????????????? GWES掛起超時(GWES Suspend Time-outs)
下表列出控制系統進入掛起狀態的注冊表鍵值。這些值以DWORD類型保存在注冊表HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power鍵下。如果值為0,表示禁用此功能。
| 注冊表值名稱 | 默認值 | 描述 |
| BattPowerOff | 300 (5分鐘) | 表示當系統使用電池供電時,在多少秒無用戶輸入后會掛起系統。 |
| ExtPowerOff | 0 (禁用) | 表示當系統使用外接電源供電時,在多少秒無用戶輸入后會掛起系統。 |
| WakeupPowerOff | 60 (1分鐘) | 表示當系統被非用戶輸入事件喚醒后(例如鬧鐘),在多少秒無活動時會掛起系統。 |
| ScreenPowerOff | 0 (禁用) | 在GWES發送APM_POWERBROADCAST, PBT_APMUSERIDLE消息給任務欄前,多少秒無用戶輸入。 |
為了使GWES控制掛起超時,必須使用這些注冊表設置。同時必須防止電源管理器控制系統掛起狀態。在示例電源管理器實現中,可以通過從注冊表中移除電源管理器超時定義來實現此功能。當GWES管理系統掛起超時時,它通過調用SetSystemPowerState函數使電源管理器將系統切換到掛起狀態。
?
4.7.6.2????????????? 電源管理器掛起超時(Power Manager Suspend Time-outs)
?
示例電源管理器的實現依據系統電源、用戶活動及系統活動進行掛起超時管理。示例電源管理器實現了超時可配置。由于電源管理器可以被OEM廠商定制,所以下列描述并不適用于所有Windows CE設備。OEM控制電源管理器如何、在什么時候改變系統電源狀態。
下面列出了控制電源管理器進行系統電源狀態切換的注冊表值:
ACUserIdle
ACSystemIdle
ACSuspend
BattUserIdle
BattSystemIdle
BattSuspend
BatteryPoll
這些DWORD值保存在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/Timeouts注冊表鍵下。0值表示不會產生超時。示例電源管理器并沒有提供忽略系統電源狀態的方法,OEM可以選擇實現此類方法。
為了使電源管理器能更好的管理系統電源狀態,這些設置必須在注冊表中出現。示例電源管理器是根據ACUserIdle進行電源管理的。
注意:為了防止GWES與電源管理器間的沖突,應禁用GWES電源管理。在電源管理器管理系統電源時,可能會限制應用程序不能進入某些系統電源狀態。
Note?? To prevent conflicts between GWES and the Power Manager, you need to disable GWES power management as described previously. When the Power Manager is actively managing system power, it may restrict applications from entering arbitrary system power states.
如果要刷新系統狀態切換定時器,應創建一個名為PowerManager/ReloadActivityTimeouts的自動重置事件,并在此事件的處理過程中調用SetEvent。這樣可以使電源管理器再次從注冊表中讀取狀態切換定時器設置。
注冊表設置:
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/Timeouts]
??? "ACUserIdle"=dword:3c; 以秒為單位
??? "ACSystemIdle"=dword:12c; 以秒為單位
??? "ACSuspend"=dword:0; 以秒為單位
??? "BattUserIdle"=dword:3c; 以秒為單位
??? "BattSystemIdle"=dword:b4; 以秒為單位
??? "BattSuspend"=dword:12c; 以秒為單位
??? "BatteryPoll"=dword:1f4; 電池輪詢間隔時間,以毫秒為單位
?
?
4.7.6.3????????????? 應用程序掛起超時(Application Suspend Time-outs)
OEM廠商有可能會編寫應用程序直接對系統電源狀態進行管理,而這樣就不需要定制電源管理器。為此,應用程序必須禁用GWES及電源管理器的電源管理功能,并自行處理電源狀態切換。禁用電源管理器及GWES電源管理功能的更多信息,參見6.2 電源管理器掛起超時。
電源管理器可能不能確定從掛起狀態恢復時,應恢復到哪個電源狀態。如果OEM廠商允許系統在掛起后完全恢復,那么可以不考慮這個問題。但是,如果OEM廠商需要部分喚醒系統,就可能需要修改電源管理器。
總結
以上是生活随笔為你收集整理的Windows CE设备驱动开发之电源管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wince 串口调试信息输出
- 下一篇: 项目管理概述学习记录(一)