WINCE电源管理
********************************LoongEmbedded************************
作者:LoongEmbedded(kandi)
時間:2011.03.07
類別:WINCE嵌入式系統開發
********************************LoongEmbedded************************
?
?
1.?????? WINCE電源管理的架構
圖1
使用電源管理器,設備可以接收電源狀態改變的通知,這個通知是以I/O控制的方式(IOCTL控制碼)的方式來和設備驅動通信的。因為I/O控制運行在線程上下文環境中,驅動開發者可以很靈活去實現電源狀態的改變。使用I/O控制的方式來管理電源也可以讓設備電源狀態獨立于整體的OS電源狀態。所以,當OS在運行的時候一些設備可以關閉,而在OS掛起的時候一些設備可以繼續保持正常的工作狀態。
電源管理器除了管理設備電源之外,它可以通知應用程序相關的電源事件,比如,當OS從掛起的狀態恢復的時候,電源管理器會通知感興趣的應用程序。電源管理器作為設備驅動和應用程序的中間層(傳遞者),它定義了OS電源狀態,并且在這三者之間的通信中實現下面這些功能
⑴OS電源狀態決定了所有的設備的最大的電源消耗。
⑵應用程序通過強制限制特定的設備最小的電源功耗來讓此設備獲得最小的性能水平。
⑶電源管理器允許設備聰明地管理自己的電源,只要設備的電源等級在最大和最小的限制值之間。
⑷如果設置最小的電源功耗大于它本身的最大值,只要應用程序需要設備,那么這個設備就會保持在高的電源功耗狀態。
⑸設備可以有一個或者多個設備電源狀態,但被限制在D0到D4之間。
⑹如果OS轉變為掛起的狀態,應用程序決定設備的最小功耗的限制。
?
設備驅動可以調用DevicePowerNotify函數來調整設備自身的功耗水平,并且應用程序可以調用SetPowerRequirement來核實設備需要運行在可以受的性能水平上。
?
WinCE電源管理器通過一個名為Pm.dll的動態鏈接庫與設備管理器Device.exe鏈接。Pm.dll動態鏈接庫支持三類接口:一是驅動程序接口:為需要進行電源管理的設備的驅動程序使用;二是應用程序接口:為需要利用電源管理的應用程序使用;三是提醒接口(Notification):為需要接受電源事件提醒的應用程序使用。
?
2.?????? 系統電源狀態
系統電源狀態明確指定了系統中所有設備的最大設備電源狀態,并且由OEM來定義系統的電源狀態,而系統電源狀態大概有以下幾種
⑴on
用戶與系統交互時的狀態,在common.reg中的相關信息如下:
圖2
⑵BacklightOff
在一段時間內,如果一直沒有用戶操作(比如按下某個鍵或者觸摸屏幕),就關閉背光,這時其他的設備也可以關閉,這需要看設計的需要了,這個timeout值可以通過控制面板進行設置。
?
⑶ UserIdle
在一段時間內,如果一直沒有用戶操作,LCD屏工作在低功耗模式或者關閉顯示 (這取決于OEM的設計了),在common.reg中的相關信息如下:
圖3
⑷ SystemIdle
用戶沒有直接使用系統,這種狀態下認為設備處于空閑的狀態,當處理器仍然在工作,比如在進行文件傳輸,在common.reg中的相關信息如下:
圖4
⑸Suspended
睡眠狀態,沒有線程在運行。CPU處于idle的狀態,這時候只能通過硬件的喚醒中斷才能喚醒系統。
圖5
?
?
3.?????? 設備電源狀態
設備電源狀態是預先定義的,電源管理器遞給一個設備狀態給設備驅動,然后這個驅動負責根據設備的能力來映射為相應的電源狀態,并且讓設備工作在恰當的電源狀態下。
⑴Full on
D0,此狀態表示設備已開啟或正在運行,系統要求設備工作在最大功耗和最高性能的狀態。
?
⑵Low on
D1,此狀態表示設備已開啟或正在運行,但以低于D0狀態的功耗及性能運行。D1狀態適用于設備已經被使用,但以較低的性能運行即可,沒有必要以最大性能運行,會產生額外的功率消耗。
?
⑶Standby
D2,此狀態表示設備被部分供電,且設備在需要時可以自動喚醒。
?
⑷Sleep
D3,睡眠狀態。保證喚醒的最小供電,在需要時能自動喚醒并初始化。
?
⑸Off
D4,關閉狀態,不供電。
?
圖6
?
?
?
4.?????? 電源管理器接口
4.1??? 應用程序電源管理接口
應用程序可以利用這些接口來調整系統及設備的電源狀態,這些接口中,只有GetSystemPowerState()、SetPowerRequirement()和ReleasePowerRequirement()函數是為一般的應用程序設計的。比如,應用程序可以調用SetSystemPowerState函數來掛起系統,但電源管理器可以限制應用程序請求系統進入掛起狀態的情況,所以其他一些應用程序電源管理接口函數SetSystemPowerState()、GetDevicePower?? ()和SetDevicePower()是為OEM應用來設計的,比如控制面板應用程序,下面來學習這些函數
⑴GetSystemPowerState函數
這個函數用戶返回系統電源狀態(比如是on),在power按鍵驅動中加入下面的代碼
dwErr = GetSystemPowerState(wPState, 20, &dFlag);
輸出的wPState=“on”,dFlag=0x12010000,這個dFlag的值表示什么意思呢?見下圖
是在pm.h下定義的
圖7
⑵SetSystemPowerState函數
SetSystemPowerState函數可被OEM程序或者其他應用程序調用,來把系統電源狀態設置為需要值,相關描述見VS2005中的相關文檔
圖8
如可以像下面一樣來使用
Result = SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);
?
⑶SetPowerRequirement函數
?
調用SetSystemPowerState是一個直接改變電源狀態的方法。更巧妙的方法是通過調用SetPowerRequirement來請求系統維持應用程序所需最低限度的電源狀態。SetSystemPowerState是假定應用程序知道所需狀態,而調用SetPowerRequirement是允許系統對電源設定做優化以滿足應用程序的需要。一個使用SetPowerRequirement會比較方便的例子是,一個使用串口的應用程序需要串口在進行通信時保持住電源狀態。SetPowerRequirement被定義如下
圖9
第一個參數指定了應用程序需要維護電源狀態的設備。DeviceState參數定義了設備的電源狀態。CEDEVICE_POWER_STATE指定了狀態范圍是從D0(意味著設備是處于最大功耗狀態)到D4(表示設備被關閉)(譯者注:其實D0到D4的狀態的具體表現,完全是由OEM廠商可自定義的,對應用程序開發者來說,比如是在D1關LCD背光還是在D2,都是不確定的,微軟只給出標準定義,而不是實際定義)。DeviceFlags參數由兩個標志合并而成:POWER_NAME,表示設備名有效;POWER_FORCE,表示設備應當維持當前狀態甚至當系統掛起時。如果pvSystemState不為NULL,它表示只有對于在pvSystemState中已命名的電源請求才是有效的。設備可能無法更改請求的狀態,應用如下:
const WCHAR VideoCallDialog_t::sc_BacklightDeviceName[] = L"bkl1:";
m_BacklightPowerRequirementHandle = SetPowerRequirement(
??????????? (PVOID)(sc_BacklightDeviceName),
??????????? D0,
??????????? POWER_NAME,
??????????? NULL, 0
??????????? );
舉例來說,假設有一個條形碼閱讀器連接在COM1端口,并且COM1只有在最高電源等級(D0)時才能驅動這個條形碼閱讀器。為了使其正常工作,應用程序將調用SetPowerRequirement把COM1指定D0狀態。假設之后串口驅動自身決定降低一個電源等級,驅動調用DevicePowerNotify通知電源管理器它期望的設備電源狀態,驅動程序的這個請求將不起作用,直到應用程序調用ReleasePowerRequirement為止。繼續這個例子,假設這時的系統電源狀態轉換為低能耗等級,雖然與之相關的COM1電源等級為D3,由于應用程序的電源請求,COM1將繼續維持在D0狀態。
在調用SetPowerRequirement函數時,指定POWER_FORCE標志將強制設備不進入休眠狀態,即使這時系統已處于休眠狀態。
?
⑷ ReleasePowerRequirement函數
這個函數請求電源管理器釋放SetPowerRequirement函數的電源請求,應用程序和驅動應該在停止電源請求的時候明確地釋放掉此電源請求。
?
⑸ GetDevicePower函數
返回某個設備當前的電源狀態
圖10
?
⑹ SetDevicePower函數
這個函數用于某個設備為某種電源狀態,這個函數使用的時候需要注意下面的原則
If a device is requested to go into a power state that the device does not support, Power Manager sets the device power state to the next highest supported power level, where D0 (full power) is the highest level.
?
For example, if the D4 state is requested and the device does not support D4, then D4 is mapped to D3. If D3 is not supported, then D3 is mapped to D2 and so on. All devices must at least support D0. For more information about the power states, see CEDEVICE_POWER_STATE. The Power Manager code is located in the public/common/oak/drivers/pm directory.
?
4.2??? 設備驅動電源管理接口
電源管理器默認的實現可以檢測到下面幾種GUID(globally unique identifier,全球唯一標識符),分別如下:
圖11
我們的工程中interfaces在common.reg中的注冊表項內容如下:
; Power Manager interfaces.? These list the interface classes that the Power
; Manager will monitor for new devices.
;
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/Interfaces]
??? "{A32942B7-920C-486b-B0E6-92A702A99B35}"="Generic power-manageable devices"
??? "{8DD679CE-8AB4-43c8-A14A-EA4963FAA715}"="Power-manageable block devices"
; @CESYSGEN IF CE_MODULES_NDIS
??? "{98C5250D-C29A-4985-AE5F-AFE5367E5006}"="Power-manageable NDIS miniports"
; @CESYSGEN ENDIF CE_MODULES_NDIS
; @CESYSGEN IF CE_MODULES_GWES
??? "{EB91C7C9-8BF6-4a2d-9AB8-69724EED97D1}"="Power-manageable display"
; @CESYSGEN ENDIF CE_MODULES_GWES
?
電源管理器用兩種機制來和支持電源管理的驅動通信:
4.2.1電源管理器調用DeviceIoControl控制設備電源狀態
電源管理器通過DeviceIoControl及對應的ControlCode可以查詢設備支持電源管理的能力及可以更新設備的電源狀態,電源管理器使用下面的控制碼來和設備通信
⑴IOCTL_POWER_CAPABILITIES
電源管理器請求設備驅動返回設備支持的電源狀態及相關特征.
⑵IOCTL_POWER_SET
請求設備驅動更新設備的電源狀態。
⑶IOCTL_POWER_QUERY
電源管理器詢問設備是否做好狀態更新的準備。
⑷IOCTL_POWER_GET
請求驅動返回設備當前的電源狀態。
⑸IOCTL_REGISTER_POWER_RELATIONSHIP
通知父設備注冊所有它所控制的設備。
4.2.2設備可以請求電源管理器來改變自身的電源狀態
電源管理器提供下面的函數用于支持電源管理的設備來向電源管理器請求電源服務:
⑴DevicePowerNotify函數
設備驅動通過DevicePowerNotify函數請求系統改變它們的電源狀態,這個時候電源管理模塊就用調用相應的IOCTL(比如IOCTL_POWER_SET)來實現電源狀態的管理,比如camera驅動中的應用如下,在初始化函數CIS_Init中調用:
DevicePowerNotify(_T("CIS1:"),(_CEDEVICE_POWER_STATE)D0, POWER_NAME);
?
⑵RegisterPowerRelationship函數
用于建立動態的父設備及其子設備的關系,或者是總線及客戶端驅動的關系,這樣設備驅動就可以管理一系列依賴的子和客戶端驅動。
圖12
?
⑶ReleasePowerRelationship函數
釋放RegisterPowerRelationship函數返回的句柄。
?
?
5.?????? 電源管理的實現
5.1??? 電源管理器對應的組件
圖13
電源管理器對應的代碼在/WINCE600/PUBLIC/COMMON/OAK/DRIVERS/PM下面
?
5.2??? 在需要的設備驅動中添加電源管理功能
不是所有的設備驅動都需要支持電源管理功能的,這需要根據設備的特性來決定,但是為了讓Power Manager知道哪些驅動是支持電源管理功能的,需要在注冊表中包含相應的鍵值(IClass)或者在驅動初始化時調用AdvertiseInterface()。一般來說,流驅動用注冊表鍵值比較方便一些,而顯示驅動通常用AdvertiseInterface()來告知。流驅動和顯示驅動在實現電源管理的功能上也有所不同。流驅動主要是在XXX_IOControl中,實現IOCTL_POWER_CAPABILITIES、IOCTL_POWER_QUERY、IOCTL_POWER_SET和IOCTL_POWER_GET,而顯示驅動主要是在DrvEscape中實現以上幾個IoControlCode,另外需要注意在QUERYESCSUPPORT添加相應的IoControlCode,下面是支持電源管理的I2C驅動在platform.reg中的注冊表內容
圖14
我們可以到my device->control panel->power->device status下來查看系統中哪些驅動支持電源管理功能,見下圖
圖15
5.3??? 在驅動和應用程序中添加相應的支持
在驅動的DeviceIoControl中實現4.2中提到的“設備驅動電源管理接口“,而在應用程序中通過調用電源管理的API,協助系統管理各個設備和整個系統的工作狀態。具體的細節可以參考BSP包中的支持電源管理的驅動及微軟自帶的應用程序了。
?
?
?
?
WINCE電源管理
http://www.cnblogs.com/we-hjb/archive/2010/01/27/1657973.html
?
WINCE 電源管理中的應用程序API
http://www.xici.net/#d120135354.htm
?
WINCE 設備驅動中實現電源管理
http://apps.hi.baidu.com/share/detail/5889365
?
?
CSDN帖子
http://topic.csdn.net/u/20100123/16/a070bb34-3415-459c-96f4-65250cf87319.html
?
總結
- 上一篇: WINCE6.0+S3C2443下ADC
- 下一篇: WinCE CEDDK之Bus操作函数