日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Windows CE的電源管理

系統(tǒng) 2554 0

Windows CE的電源管理之一

Windows CE的基本電源管理功能

在所有版本的Windows CE操作系統(tǒng)中,圖形、視窗和事件子系統(tǒng)(GWES)在電源管理方面都發(fā)揮了關(guān)鍵作用。這是因?yàn)樵缙诎姹镜碾娫垂芾砉δ苁怯捎脩舻幕顒?dòng)所驅(qū)動(dòng)的,而GWES負(fù)責(zé)處理所有用戶的輸入,如鍵盤、鼠標(biāo)和觸摸屏。GWES設(shè)置定時(shí)器監(jiān)控用戶的活動(dòng),當(dāng)一段時(shí)間內(nèi)用戶沒有任何輸入時(shí),便使系統(tǒng)進(jìn)入休眠狀態(tài)。通過注冊(cè)表可以設(shè)置這幾個(gè)定時(shí)器的超時(shí)值,它們可以分別被用于電池供電或外部電源供電時(shí)。當(dāng)然,通過注冊(cè)表也可以禁用GWES的電源管理功能,它在Windows CE.NET以后的版本中是默認(rèn)被禁用的,這有利于電源管理器的集中管理。

Windows CE的電源管理
圖1 Windows CE基本的電源轉(zhuǎn)換流程

狀態(tài)及其轉(zhuǎn)換 描述
No Power 既沒有電池也沒有外部電源供電.
On 所有設(shè)備上電的常規(guī)運(yùn)行狀態(tài).
Suspend 休眠狀態(tài),這時(shí)大部分設(shè)備關(guān)閉,僅RAM(自刷新)和外部時(shí)鐘運(yùn)行.
Idle 空閑狀態(tài),這時(shí)可停止CPU的運(yùn)行.
Critical off 電池電壓過低的狀態(tài).
Power-on reset 系統(tǒng)清空RAM并初始化文件系統(tǒng).
Cold boot First application of power, for example, when a backup battery is installed.
Warm boot 軟啟(熱啟動(dòng)),清空RAM并返回運(yùn)行(On)狀態(tài).
On-to-Idle 從全速運(yùn)行狀態(tài)到空閑狀態(tài)的轉(zhuǎn)換.
Idle-to-On 處理器從低功耗狀態(tài)回到全速運(yùn)行狀態(tài).
On-to-Suspend 由于某些事件的觸發(fā),處理器轉(zhuǎn)換到停止運(yùn)行狀態(tài)。并調(diào)用設(shè)備驅(qū)動(dòng)函數(shù) XXX_PowerDown.
Suspend-to-On 由特定的喚醒事件觸發(fā),處理器從停止?fàn)顟B(tài)返回到全速運(yùn)行態(tài)。并調(diào)用設(shè)備驅(qū)動(dòng)函數(shù)XXX_PowerUp.
On-to-Critical off 當(dāng)電池電壓過低時(shí)轉(zhuǎn)換到Critical off狀態(tài).


上圖是Windows CE系統(tǒng)基本的電源狀態(tài)轉(zhuǎn)換策略,對(duì)應(yīng)有5種系統(tǒng)電源狀態(tài)(等級(jí)):No Power, On, Suspend, Idle, Critical off。相關(guān)描述和轉(zhuǎn)換方式參見上表。

基本的電源管理功能所采用的節(jié)能方法是使系統(tǒng)適時(shí)的進(jìn)入休眠狀態(tài),當(dāng)下面的一種事件發(fā)生時(shí),系統(tǒng)將進(jìn)入休眠狀態(tài)( SUSPEND ):
l 用戶按下 On/Off 按鈕;
l 監(jiān)控用戶活動(dòng)的定時(shí)器超時(shí);
l 應(yīng)用程序調(diào)用 API ,如 GwesPowerOffSystem SetSystemPowerState

當(dāng)下面的一種事件發(fā)生時(shí),系統(tǒng)將退出休眠狀態(tài):
l 用戶再次按下 On/Off 按鈕;
l 發(fā)生某個(gè)警告事件,如某個(gè)日期或時(shí)間定時(shí)器的到時(shí)提醒;
l 發(fā)生某個(gè)喚醒事件,由外設(shè)如串口設(shè)備或者網(wǎng)卡觸發(fā)中斷來喚醒系統(tǒng)。

雖然通過用戶操作、應(yīng)用程序或者外設(shè)都可以使系統(tǒng)進(jìn)入或者退出休眠狀態(tài),但基本的電源管理功能所能控制的粒度過大,對(duì)應(yīng)于 CPU 只有三種狀態(tài): On Idle Suspend ,對(duì)應(yīng)于所有外設(shè)只有兩種狀態(tài): On Suspend 。而且,當(dāng)系統(tǒng)進(jìn)出休眠狀態(tài)時(shí),應(yīng)用程序都得不到任何通知。

Windows CE 的高級(jí)電源管理功能

加入了電源管理組件的 Windows CE 具有高級(jí)的電源管理功能,它允許每個(gè)外設(shè)具有自己的電源狀態(tài),有別于一般的系統(tǒng)電源狀態(tài)( System Power State ),被稱作設(shè)備電源狀態(tài)( Device Power State )。現(xiàn)在應(yīng)用程序有能力設(shè)置個(gè)別外設(shè)的電源狀態(tài),比如一個(gè)文件傳輸程序,在保持串口或者藍(lán)牙端口正常通訊時(shí),可以關(guān)閉顯示屏幕和背光。這就為實(shí)現(xiàn)更高級(jí)別的動(dòng)態(tài)電源管理提供了可能。

我們可以通過注冊(cè)表任意設(shè)定一組系統(tǒng)電源狀態(tài),使其對(duì)應(yīng)于我們?cè)O(shè)計(jì)的狀態(tài)模型。對(duì)于設(shè)備電源狀態(tài)則沒有這么大的靈活度,它具有 5 個(gè)設(shè)備狀態(tài):

D0 Full on D1 Low on D2 Standby D3 Sleep D4 Off

當(dāng)定義好系統(tǒng)電源狀態(tài),并為每個(gè)外設(shè)分配了設(shè)備電源狀態(tài)后,通過注冊(cè)表,我們可以將兩者進(jìn)行映射。在某個(gè)系統(tǒng)電源狀態(tài)下,比如一個(gè)電池供電的系統(tǒng),當(dāng)電池電量已經(jīng)少于 50% 時(shí),顯示屏幕和背光可能處于 D1 狀態(tài),而網(wǎng)絡(luò)設(shè)備可以設(shè)置為 D3 狀態(tài)。也就是說,在同一時(shí)刻,不同的外設(shè)可能處于不同的設(shè)備電源狀態(tài)中。這樣的靈活性意味著每個(gè)設(shè)備可以最小程度的消耗電池資源。

Windows CE的電源管理
2 Windows CE 高級(jí)電源管理框架

如圖 2 所示,電源管理器實(shí)現(xiàn)為一個(gè)名為 Pm.dll 的動(dòng)態(tài)鏈接庫(kù),電源管理接口分為應(yīng)用程序和驅(qū)動(dòng)程序兩部分。驅(qū)動(dòng)程序通過 DeviceIoControl 服務(wù)例程來處理電源管理器發(fā)來的設(shè)備電源狀態(tài)改變請(qǐng)求,另外電源管理器通過消息隊(duì)列通知應(yīng)用程序電源相關(guān)的事件。

為了獲得高級(jí)電源控制的功能,必須通過Platform Builder將電源管理組件編譯到內(nèi)核鏡像中。實(shí)現(xiàn)的源代碼參見{WINCEROOT}\Private\Winceos\Coreos\Device\PMIF\pmif.c,這段代碼只是一個(gè)封裝,它會(huì)調(diào)用{WINCEROOT}\Public\Common\Oak\Drivers\PM中的組件。參考這個(gè)實(shí)現(xiàn)OEM可以根據(jù)需要設(shè)計(jì)自己的電源管理策略。

下一篇將分三個(gè)部分來解讀WinCE的電源管理,首先從系統(tǒng)平臺(tái)開發(fā)的角度,這部分一般由OEM廠商負(fù)責(zé)實(shí)現(xiàn),然后介紹電源管理的接口,分別從設(shè)備驅(qū)動(dòng)和應(yīng)用程序的角度介紹如何應(yīng)用電源管理。

Windows CE的電源管理之二

1. OAL 的電源管理

OEM Adaptation Layer OAL )是一層與硬件平臺(tái)相關(guān)的代碼,它在電源狀態(tài)轉(zhuǎn)換中扮演著重要的角色。首先必須實(shí)現(xiàn)的是以下幾個(gè)與硬件相關(guān)的函數(shù):

OEMInit :初次上電時(shí)(或在冷啟后)被調(diào)用,一般在這個(gè)函數(shù)中處理一些重要的初始化工作,如初始化系統(tǒng)內(nèi)存,建立調(diào)試環(huán)境,設(shè)置系統(tǒng)中斷等;

OEMIdle :沒有線程可調(diào)度運(yùn)行時(shí)被內(nèi)核調(diào)用,這時(shí)可將 CPU 置于低功耗狀態(tài),并保證其可以快速返回運(yùn)行狀態(tài);

OEMPowerOff :系統(tǒng)進(jìn)入休眠( Suspend )狀態(tài)前被調(diào)用,它即是系統(tǒng)進(jìn)入休眠狀態(tài)前被調(diào)用的最后一個(gè)函數(shù),也是在系統(tǒng)被喚醒后所執(zhí)行的第一個(gè)函數(shù)(中斷處理程序以外);

Interrupt Handler :一些用來喚醒系統(tǒng)的中斷處理程序。當(dāng)中斷發(fā)生時(shí),內(nèi)核首先調(diào)用中斷處理程序,其中一些中斷是可以將系統(tǒng)從睡眠狀態(tài)中喚醒的,但中斷時(shí)間內(nèi)能處理的事情非常少,在中斷處理程序里大部分 API 也是不能被調(diào)用的。

高級(jí)的電源管理功能允許任何設(shè)備驅(qū)動(dòng)將其中斷作為系統(tǒng)的喚醒源,在版本 Windows CE.NET 4.1 以前, OAL 掌管著所有的中斷處理,這就意味著在生成內(nèi)核鏡像以后,我們就無法在系統(tǒng)中添加新的中斷處理程序了。現(xiàn)在即使這個(gè)設(shè)備是在運(yùn)行時(shí)才安裝到系統(tǒng)中來的,比如 PCMCIA 或者 CF 接口的無線網(wǎng)卡,它可以通過調(diào)用 API LoadIntChainHandler FreeIntChainHandler )實(shí)現(xiàn)中斷處理程序的安裝和卸載。在系統(tǒng)中添加了新的中斷處理程序后,它就可以通過內(nèi)核 IOCTL 代碼( IOCTL_HAL_ENABLE_WAKE )實(shí)現(xiàn)其作為系統(tǒng)的喚醒源。

位于操作系統(tǒng)內(nèi)核層的電源管理策略,也要為設(shè)備驅(qū)動(dòng)及上層應(yīng)用程序提供接口,通過 PowerPolicyNotify 向電源管理組件發(fā)送事件請(qǐng)求,設(shè)備及應(yīng)用程序就可以參與到系統(tǒng)的電源管理策略中來。

2. 設(shè)備驅(qū)動(dòng)的電源管理

我們可以為設(shè)備驅(qū)動(dòng)添加電源管理功能,首先就是要在驅(qū)動(dòng)程序中添加電源管理的 IOCTL 代碼,然后通知電源管理器該驅(qū)動(dòng)是支持電源管理的,最后在驅(qū)動(dòng)中編碼實(shí)現(xiàn)該設(shè)備支持的幾種電源狀態(tài)。

2.1 建立支持電源管理的設(shè)備驅(qū)動(dòng)

為了建立一個(gè)能夠?qū)υO(shè)備進(jìn)行電源管理的驅(qū)動(dòng)程序,我們必須首先建立一個(gè)支持 non-COM-related 設(shè)備接口的驅(qū)動(dòng)程序。 non-COM-related 設(shè)備接口標(biāo)明這個(gè)設(shè)備是支持電源管理的。可以用以下方式建立這種接口:
l 可以在注冊(cè)表中,用激活設(shè)備所用的 IClass 值定義接口;
l 可以在驅(qū)動(dòng)程序的 Init 函數(shù)中,設(shè)置注冊(cè)表中的 IClass 值;
l 可以使用 ActivateDeviceEx 的參數(shù) REGINI 設(shè)置 IClass 值;
l 可以在驅(qū)動(dòng)程序中顯示地調(diào)用 AdvertiseInterface 函數(shù)。

電源管理器通過 IOCTL 代碼來和驅(qū)動(dòng)通信。通常情況下,當(dāng)一個(gè)驅(qū)動(dòng)程序聲明為支持電源管理時(shí),驅(qū)動(dòng)只需要在 DeviceIoControl 中實(shí)現(xiàn)電源的管理即可。下面是電源管理器用來與驅(qū)動(dòng)通信的 IOCTL 代碼:
l IOCTL_POWER_CAPABILITIES :代表電源管理器請(qǐng)求設(shè)備驅(qū)動(dòng)返回設(shè)備支持的電源狀態(tài)及相關(guān)特征;
l IOCTL_POWER_SET :請(qǐng)求驅(qū)動(dòng)更新設(shè)備的電源狀態(tài);
l IOCTL_POWER_QUERY :電源管理器詢問設(shè)備是否準(zhǔn)備好進(jìn)行狀態(tài)切換;
l IOCTL_POWER_GET :請(qǐng)求驅(qū)動(dòng)返回當(dāng)前設(shè)備的電源狀態(tài);
l IOCTL_REGISTER_POWER_RELATIONSHIP :通知父設(shè)備注冊(cè)所有它所控制的設(shè)備。

其中 IOCTL_POWER_CAPABILITIES IOCTL_POWER_SET 是支持電源管理的設(shè)備驅(qū)動(dòng)必須實(shí)現(xiàn)的。

2.2 IOCTL 代碼的實(shí)現(xiàn)

在設(shè)備自舉的時(shí)候,設(shè)備驅(qū)動(dòng)必須使設(shè)備處于 D0 狀態(tài),當(dāng)電源管理器通過 IOCTL_POWER_CAPABILITIES 向設(shè)備發(fā)出查詢時(shí),設(shè)備驅(qū)動(dòng)應(yīng)該盡可能詳細(xì)的報(bào)告該設(shè)備的電源管理能力,以便將自己納入到系統(tǒng)的電源管理策略中去。在自舉完成后,電源管理器可以根據(jù)管理策略,調(diào)用 IOCTL_POWER_SET 調(diào)整設(shè)備的電源狀態(tài)。在設(shè)備自我管理電源的情況下,設(shè)備應(yīng)該通過 DevicePowerNotify 函數(shù)請(qǐng)求系統(tǒng)改變它們的電源狀態(tài)。在實(shí)現(xiàn)對(duì) IOCTL_POWER_SET 支持時(shí),設(shè)備驅(qū)動(dòng)開發(fā)應(yīng)該注意以下幾點(diǎn):
l 設(shè)備并不一定具備所有五種設(shè)備電源狀態(tài),但至少可以工作在 D0 狀態(tài);
l 電源管理器可能會(huì)要求設(shè)備進(jìn)入任何設(shè)備電源狀態(tài),并不僅僅是設(shè)備聲明支持的幾個(gè)。
l 如果一個(gè)設(shè)備被要求進(jìn)入一個(gè)它并不支持的電源狀態(tài),它就會(huì)進(jìn)入另一個(gè)它支持的更高功耗的狀態(tài)。例如,一個(gè)設(shè)備并不支持 D2 ,它會(huì)被要求進(jìn)入 D1
l 電源管理器可能會(huì)通過發(fā)出 IOCTL_POWER_SET ,使設(shè)備再次進(jìn)入它已經(jīng)處于的當(dāng)前狀態(tài)。在這種情況下,設(shè)備驅(qū)動(dòng)程序簡(jiǎn)單的返回成功即可。
l 設(shè)備的電源狀態(tài)不一定與系統(tǒng)的電源狀態(tài)同步,因?yàn)樗赡苁艿綉?yīng)用程序需求的限制。

2.3 休眠和喚醒的處理

支持電源管理的流設(shè)備驅(qū)動(dòng)通過 XXX_PowerDown XXX_PowerUp 接收系統(tǒng)休眠和喚醒的通知,這些通知在內(nèi)核調(diào)用 OEMPowerOff 之前發(fā)出,并處于中斷上下文中。

設(shè)備驅(qū)動(dòng)的開發(fā)者必須清楚,在系統(tǒng)休眠期間,設(shè)備應(yīng)該處于何種狀態(tài)。并不是所有的設(shè)備在這個(gè)時(shí)候都應(yīng)該強(qiáng)制被關(guān)閉,比如在音頻設(shè)備可以不依賴處理器來播放音樂時(shí),在系統(tǒng)休眠期間它的狀態(tài)就應(yīng)該交給電源管理器和應(yīng)用程序來處理。而如果這個(gè)音頻設(shè)備的播放需要處理器頻繁的工作,在系統(tǒng)進(jìn)入休眠狀態(tài)時(shí),驅(qū)動(dòng)程序應(yīng)該果斷的關(guān)閉設(shè)備的電源,即使該設(shè)備由于應(yīng)用程序的請(qǐng)求不處于 D4 狀態(tài)。

另外,設(shè)備的 D3 狀態(tài)值得特殊考慮,因?yàn)檫@個(gè)狀態(tài)不僅僅與設(shè)備的功耗級(jí)別相關(guān),處于 D3 狀態(tài)的設(shè)備還被允許將系統(tǒng)從休眠狀態(tài)中喚醒。所以當(dāng)我們開發(fā)支持電源管理的設(shè)備驅(qū)動(dòng)時(shí)需要注意以下幾點(diǎn):
l 支持喚醒系統(tǒng)的設(shè)備不應(yīng)該主動(dòng)通過 DevicePowerNotify 請(qǐng)求進(jìn)入 D3 狀態(tài),因?yàn)橐话闱闆r下,只有當(dāng)系統(tǒng)打算進(jìn)入休眠狀態(tài)時(shí),電源管理器才將設(shè)備作為喚醒源啟用。從代碼的角度也應(yīng)該避免這一點(diǎn),因?yàn)轵?qū)動(dòng)程序無法區(qū)分來自 IOCTL_POWER_SET 中對(duì) D3 狀態(tài)的請(qǐng)求是由它自己還是電源管理器發(fā)起的;
l 如果有必要,能喚醒系統(tǒng)的設(shè)備可以定義一樣的 D2 D3 狀態(tài),而只有 D3 具有啟動(dòng)喚醒的功能;
l 支持 D3 的設(shè)備不一定具有將系統(tǒng)從休眠狀態(tài)喚醒的功能,不能將系統(tǒng)喚醒的設(shè)備,但它又具有低功耗模式,是可以自己主動(dòng)請(qǐng)求進(jìn)入 D3 狀態(tài)的;
l 如果不能喚醒系統(tǒng)的設(shè)備處于 D3 狀態(tài),在系統(tǒng)進(jìn)入休眠狀態(tài)時(shí),它應(yīng)該在 XXX_PowerDown 中將狀態(tài)轉(zhuǎn)換為 D4 ,并且在 XXX_PowerUp 中恢復(fù)到 D3 狀態(tài);如果無法這么做,它就不應(yīng)該支持 D3 狀態(tài),而是在請(qǐng)求進(jìn)入 D3 時(shí)直接進(jìn)入 D4 狀態(tài);

做到了以上幾點(diǎn),在系統(tǒng)進(jìn)入休眠狀態(tài)時(shí), OEM 和應(yīng)用程序開發(fā)人員就可以請(qǐng)求將設(shè)備進(jìn)入 D3 狀態(tài),而不必關(guān)心這個(gè)設(shè)備是否支持喚醒系統(tǒng)。

3. 應(yīng)用程序的電源管理

電源管理組件提供了一組接口供應(yīng)用程序參與到電源管理的活動(dòng)中,應(yīng)用程序可以通過 RequestPowerNotifications 函數(shù)請(qǐng)求電源管理器向其發(fā)送電源相關(guān)的通知,也可以通過 SetPowerRequirement 通知電源管理器將設(shè)備設(shè)置在特殊的電源狀態(tài)下。這樣,指定設(shè)備的電源狀態(tài)就不會(huì)隨系統(tǒng)電源狀態(tài)的改變而改變。

3.1 電源通知機(jī)制

電源相關(guān)的通知通過消息隊(duì)列傳遞給應(yīng)用程序,通常應(yīng)用程序新建一個(gè)消息隊(duì)列,并通過 RequestPowerNotifications 將這個(gè)消息隊(duì)列的句柄傳遞給電源管理器,同時(shí)創(chuàng)建一個(gè)線程偵聽來自這個(gè)隊(duì)列的消息。電源管理器定義了如下幾種通知:
l PBT_RESUME :當(dāng)系統(tǒng)從休眠狀態(tài)被喚醒是產(chǎn)生;
l PBT_POWERSTATUSCHANGE :當(dāng)系統(tǒng)接入或者斷開外部電源時(shí)產(chǎn)生;
l PBT_TRANSITION :當(dāng)電源管理器執(zhí)行系統(tǒng)電源狀態(tài)轉(zhuǎn)換時(shí)發(fā)生;
l PBT_POWERINFOCHANGE :當(dāng)電池信息更新時(shí)發(fā)生。

3.2 電源請(qǐng)求機(jī)制

電源請(qǐng)求機(jī)制為應(yīng)用程序提供了強(qiáng)大的能力控制電源管理器調(diào)整設(shè)備的電源等級(jí),與其他所有的電源設(shè)置相比,它具有很高的優(yōu)先級(jí)。舉例來說,假設(shè)有一個(gè)條形碼閱讀器連接在 COM1 端口,并且 COM1 只有在最高電源等級(jí)( D0 )時(shí)才能驅(qū)動(dòng)這個(gè)條形碼閱讀器。為了使其正常工作,應(yīng)用程序?qū)⒄{(diào)用 SetPowerRequirement COM1 指定 D0 狀態(tài)。假設(shè)之后串口驅(qū)動(dòng)自身決定降低一個(gè)電源等級(jí),驅(qū)動(dòng)調(diào)用 DevicePowerNotify 通知電源管理器它期望的設(shè)備電源狀態(tài),驅(qū)動(dòng)程序的這個(gè)請(qǐng)求將不起作用,直到應(yīng)用程序調(diào)用 ReleasePowerRequirement 為止。繼續(xù)這個(gè)例子,假設(shè)這時(shí)的系統(tǒng)電源狀態(tài)轉(zhuǎn)換為低能耗等級(jí),雖然與之相關(guān)的 COM1 電源等級(jí)為 D3 ,由于應(yīng)用程序的電源請(qǐng)求, COM1 將繼續(xù)維持在 D0 狀態(tài)。

在調(diào)用 SetPowerRequirement 函數(shù)時(shí),指定 POWER_FORCE 標(biāo)志將強(qiáng)制設(shè)備不進(jìn)入休眠狀態(tài),即使這時(shí)系統(tǒng)已處于休眠狀態(tài)。

3.3 設(shè)置系統(tǒng)電源狀態(tài)

在某些應(yīng)用的場(chǎng)合下,應(yīng)用程序可能需要改變系統(tǒng)的電源狀態(tài)。 OEM 通過注冊(cè)表定義了系統(tǒng)支持的電源狀態(tài), 應(yīng)用程序可以通過 GetSystemPowerState 返回當(dāng)前系統(tǒng)電源狀態(tài)的名稱,也可以通過 SetSystemPowerState 改變系統(tǒng)的電源狀態(tài)。

Windows CE的電源管理之三

本篇將以Windows Mobile為例介紹Windows CE電源管理的實(shí)現(xiàn),大體上,Windows Mobile分為Pocket PC和Smartphone兩種版本。這兩者之間的主要區(qū)別在于觸摸屏和電源模型,Smartphone采用的是“Always On”模型。為了說清楚它們的區(qū)別,我們就先從系統(tǒng)電源狀態(tài)說起吧(這里有些系統(tǒng)電源狀態(tài)是從WM5開始才有的)。

1. Windows Mobile的系統(tǒng)電源狀態(tài)

  • On:用戶與系統(tǒng)交互時(shí)的狀態(tài);
  • BacklightOff:在一段時(shí)間內(nèi)(默認(rèn)15秒),如果一直沒有用戶操作(比如按下某個(gè)鍵或者觸摸屏幕),就關(guān)閉背光,這時(shí)其他的設(shè)備都沒變化。這個(gè)timeout值可以通過控制面板進(jìn)行設(shè)置;
  • UserIdle:這個(gè)狀態(tài)只在Smartphone中被使用。經(jīng)過一段稍長(zhǎng)的時(shí)間,如果一直沒有用戶操作,就關(guān)閉背光和LCD。這個(gè)timeout值可以通過控制面板進(jìn)行設(shè)置;
  • ScreenOff:一般由某些程序指定,才進(jìn)入這個(gè)狀態(tài)。比如音樂播放器程序,當(dāng)你聽音樂時(shí)按下某個(gè)鍵可以將屏幕關(guān)閉。PocketPC和Smartphone都使用這個(gè)狀態(tài),它與UserIdle的不同在于,ScreenOff意味著“用戶主動(dòng)關(guān)閉了顯示,只有當(dāng)他按下電源鍵時(shí)才重新顯示”,而UserIdle意味著“用戶有段時(shí)間沒操作了,那么我們可以關(guān)閉屏幕來省電”,所以在UserIdle時(shí),隨便按下Smartphone的哪個(gè)鍵都會(huì)啟動(dòng)顯示;
  • Suspend:這是PocketPC的睡眠模式,幾乎所有設(shè)備都被關(guān)閉,直到某個(gè)硬件設(shè)備觸發(fā)中斷才將系統(tǒng)喚醒,這個(gè)timeout值可以通過控制面板進(jìn)行設(shè)置(默認(rèn)為3分鐘);
  • Resuming:這是PocketPC被喚醒后的狀態(tài),這時(shí)屏幕是關(guān)閉的,并啟動(dòng)一個(gè)15秒的計(jì)時(shí)器,在這段時(shí)間內(nèi)決定接下來進(jìn)入哪個(gè)狀態(tài),如果計(jì)時(shí)器超時(shí)則重新回到睡眠狀態(tài);
  • Unattended:這個(gè)狀態(tài)只在PocketPC中被使用,用戶對(duì)其不會(huì)有所察覺。有些程序,如ActiveSync每5分鐘會(huì)喚醒系統(tǒng)進(jìn)行同步,同步完成后再讓系統(tǒng)繼續(xù)睡眠,這段時(shí)間不希望打擾用戶,即程序在后臺(tái)執(zhí)行。

可以通過注冊(cè)表查看系統(tǒng)電源狀態(tài)對(duì)應(yīng)的具體設(shè)備的電源狀態(tài),[HLM\System\CurrentControlSet\Control\Power\State]。

現(xiàn)在我們知道,Smartphone沒有真正的睡眠模式,即使它會(huì)在一段時(shí)間后關(guān)閉背光和屏幕,但它并沒有睡著,只是休息一下眼睛罷了,它的大腦和四肢仍在正常工作。PocketPC所采用的模型比Smartphone要復(fù)雜的多,你可以按下電源鍵讓系統(tǒng)睡眠,在必要時(shí),也可以喚醒系統(tǒng)做一些工作然后再繼續(xù)睡眠。如果你在Smartphone上運(yùn)行一個(gè)桌面精靈之類的程序,她為了引起你的注意,長(zhǎng)時(shí)間的蹦啊跳啊,不管白天還是黑夜,可想而知,你的待機(jī)時(shí)間將......

你可能會(huì)覺得PocketPC的“Sleep”模型比Smartphone的“Always On”模型要省電,其實(shí)恰恰相反。因?yàn)樵谙到y(tǒng)睡眠的過程中,它需要通知所有的設(shè)備驅(qū)動(dòng),為了讓它們保存一些重要的信息并關(guān)閉相應(yīng)的硬件設(shè)備,在系統(tǒng)被喚醒時(shí)也需要通知它們恢復(fù)先前的工作。這個(gè)過程不僅耗時(shí)還可能會(huì)耗更多的電,因?yàn)橐恍┰O(shè)備在頻繁的狀態(tài)轉(zhuǎn)換過程中會(huì)消耗比較多的能量。這也就是為什么當(dāng)你收到一條短信時(shí),睡眠狀態(tài)的PocketPC要花3到6秒的時(shí)間來處理,而Smartphone只需要幾個(gè)微秒:)

2. Windows Mobile的電源管理策略

我們可以用系統(tǒng)電源狀態(tài)機(jī)來簡(jiǎn)單的描述Windows Mobile的電源管理策略,以PocketPC為例,系統(tǒng)電源狀態(tài)機(jī)如下圖所示:

FSM

系統(tǒng)內(nèi)部的電源管理器負(fù)責(zé)協(xié)調(diào)電源狀態(tài)的轉(zhuǎn)換,電源狀態(tài)的轉(zhuǎn)換主要由一下幾種方式觸發(fā):

  • 計(jì)時(shí)器超時(shí):SuspendTimeout和ResumingSuspendTimeout,分別對(duì)應(yīng)于第一節(jié)介紹Suspend和Resuming狀態(tài)時(shí)所提到的計(jì)時(shí)器。細(xì)說起來,它們每個(gè)又有兩個(gè)值,分別對(duì)應(yīng)著電源供電時(shí)和電池供電時(shí)的超時(shí)值,也就是注冊(cè)表[HLM\System\CurrentControlSet\Control\Power\Timeout]中的ACSuspendTimeout、BattSuspendTimeout、ACResumingSuspendTimeout、BattResumingSuspendTimeout;
  • 系統(tǒng)調(diào)用:驅(qū)動(dòng)程序或應(yīng)用程序通過相應(yīng)的API,請(qǐng)求進(jìn)入某種電源狀態(tài)。這類API在前面的文章中已經(jīng)有所介紹,如SetSystemPowerState、SetPowerRequirement、DevicePowerNotify等;
  • 平臺(tái)相關(guān)的系統(tǒng)調(diào)用:通過PowerPolicyNotify通知電源管理器發(fā)生了某個(gè)事件,它的實(shí)現(xiàn)比較靈活,驅(qū)動(dòng)程序或應(yīng)用程序可以通過相應(yīng)的參數(shù)與電源管理器進(jìn)行交互,比如PPN_POWERCHANGE、PPN_SUSPENDKEYPRESSED、PPN_UNATTENDEDMODE等,參見"pmpolicy.h";
  • 直接訪問內(nèi)核對(duì)象:事件(Event)作為Windows CE系統(tǒng)的內(nèi)核對(duì)象,可以通過事件名稱在進(jìn)程間共享,因此我們可以訪問電源管理器中的兩個(gè)事件,它們的名字分別是_T("PowerManager/ReloadActivityTimeouts")、_T("PowerManager/SystemIdleTimerReset")。如果你的程序需要?jiǎng)討B(tài)修改那幾個(gè)計(jì)時(shí)器的時(shí)間長(zhǎng)度,可以通過第一個(gè)事件通知電源管理器重新讀取注冊(cè)表中計(jì)時(shí)器的值,而第二個(gè)事件與SystemIdleTimerReset功能一樣,可以阻止系統(tǒng)進(jìn)入睡眠狀態(tài)。

3. Windows Mobile電源管理相關(guān)API的應(yīng)用

最后,通過幾個(gè)應(yīng)用場(chǎng)景簡(jiǎn)單介紹一下常用的電源管理相關(guān)的API的使用:

  • 如果你在設(shè)計(jì)的是媒體播放器程序,不希望在播放電影時(shí),系統(tǒng)自動(dòng)轉(zhuǎn)入Suspend狀態(tài),這時(shí)可以每隔30秒調(diào)用一次SystemIdleTimerReset,它會(huì)幫你重置那個(gè)計(jì)時(shí)器;如果你還想同時(shí)保持背光,那么可以調(diào)用SetPowerRequirement(TEXT("BKL1:"), D0, POWER_NAME, NULL, 0);如果你提供一個(gè)按鈕允許用戶關(guān)閉屏幕,那么調(diào)用SetSystemPowerState(NULL, POWER_STATE_IDLE, 0);
  • 如果你在設(shè)計(jì)的是天氣預(yù)報(bào)程序,需要每天早上6點(diǎn)在線更新天氣信息,這時(shí)可以調(diào)用CeRunAppAtTime,系統(tǒng)到時(shí)會(huì)被RTC中斷喚醒,還記得前面提到的那個(gè)15秒的計(jì)時(shí)器嗎,這時(shí)你的程序應(yīng)該在15秒內(nèi)請(qǐng)求進(jìn)入U(xiǎn)nattended狀態(tài),否則系統(tǒng)將重新回到睡眠狀態(tài)。在處理更新的過程中,還是應(yīng)該每隔30秒調(diào)用一次SystemIdleTimerReset,在處理完更新后,應(yīng)該再次調(diào)用CeRunAppAtTime,并放棄Unattended狀態(tài)。請(qǐng)注意,在電源管理器的實(shí)現(xiàn)代碼中,用了一個(gè)引用計(jì)數(shù)的變量(gdwUnattendedModeRequests)統(tǒng)計(jì)所有對(duì)Unattended狀態(tài)的請(qǐng)求,所以PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);和PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);要成對(duì)出現(xiàn),否則系統(tǒng)將無法回到睡眠狀態(tài)。
  • 如果你要開發(fā)一個(gè)監(jiān)控電池狀態(tài)的程序,首先應(yīng)該創(chuàng)建一個(gè)接收狀態(tài)通知的線程,在這個(gè)線程里調(diào)用RequestPowerNotifications,這個(gè)函數(shù)的第一個(gè)參數(shù)是一個(gè)消息隊(duì)列的句柄,所以必須先創(chuàng)建一個(gè)消息隊(duì)列(CreateMsgQueue),第二個(gè)參數(shù)是你希望得到的通知類型,這里要用到的是PBT_POWERSTATUSCHANGE|PBT_POWERINFOCHANGE,然后線程就可以等待通知了(WaitForSingleObject),一旦有通知到來,線程通過ReadMsgQueue讀取消息的內(nèi)容,再做些更新UI的工作。
    相關(guān)示例代碼
    <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> // ***************************************************************************
    // Function Name: PowerNotificationThread
    //
    // Purpose: listens for power change notifications
    //
    DWORD PowerNotificationThread(LPVOID pVoid)
    {
    // size of a POWER_BROADCAST message
    DWORD cbPowerMsgSize = sizeof POWER_BROADCAST + (MAX_PATH * sizeof TCHAR);

    // Initialize our MSGQUEUEOPTIONS structure
    MSGQUEUEOPTIONS mqo;
    mqo.dwSize
    = sizeof (MSGQUEUEOPTIONS);
    mqo.dwFlags
    = MSGQUEUE_NOPRECOMMIT;
    mqo.dwMaxMessages
    = 4 ;
    mqo.cbMaxMessage
    = cbPowerMsgSize;
    mqo.bReadAccess
    = TRUE;

    // Create a message queue to receive power notifications
    HANDLE hPowerMsgQ = CreateMsgQueue(NULL, & mqo);
    if (NULL == hPowerMsgQ)
    {
    RETAILMSG(
    1 , (L " CreateMsgQueue failed: %x\n " , GetLastError()));
    goto Error;
    }


    // Request power notifications
    HANDLE hPowerNotifications = RequestPowerNotifications(hPowerMsgQ, PBT_POWERSTATUSCHANGE | PBT_POWERINFOCHANGE);

    if (NULL == hPowerNotifications)
    {
    RETAILMSG(
    1 , (L " RequestPowerNotifications failed: %x\n " , GetLastError()));
    goto Error;
    }


    HANDLE rgHandles[
    2 ] = { 0 } ;
    rgHandles[
    0 ] = hPowerMsgQ;
    rgHandles[
    1 ] = g_hEventShutDown;

    // Wait for a power notification or for the app to exit
    while (WaitForMultipleObjects( 2 , rgHandles, FALSE, INFINITE) == WAIT_OBJECT_0)
    {
    DWORD cbRead;
    DWORD dwFlags;
    POWER_BROADCAST
    * ppb = (POWER_BROADCAST * ) new BYTE[cbPowerMsgSize];

    // loop through in case there is more than 1 msg
    while (ReadMsgQueue(hPowerMsgQ, ppb, cbPowerMsgSize, & cbRead,
    0 , & dwFlags))
    {
    switch (ppb -> Message)
    {
    case PBT_POWERINFOCHANGE:
    {
    RETAILMSG(
    1 ,(L " Power Notification Message: PBT_POWERINFOCHANGE\n " ));

    // PBT_POWERINFOCHANGE message embeds a
    // POWER_BROADCAST_POWER_INFO structure into the
    // SystemPowerState field
    PPOWER_BROADCAST_POWER_INFO ppbpi =
    (PPOWER_BROADCAST_POWER_INFO) ppb
    -> SystemPowerState;
    if (ppbpi)
    {
    RETAILMSG(
    1 ,(L " Length: %d " , ppb -> Length));
    RETAILMSG(
    1 ,(L " BatteryLifeTime = %d\n " ,ppbpi -> dwBatteryLifeTime));
    RETAILMSG(
    1 ,(L " BatterFullLifeTime = %d\n " ,
    ppbpi
    -> dwBatteryFullLifeTime));
    RETAILMSG(
    1 ,(L " BackupBatteryLifeTime = %d\n " ,
    ppbpi
    -> dwBackupBatteryLifeTime));
    RETAILMSG(
    1 ,(L " BackupBatteryFullLifeTime = %d\n " ,
    ppbpi
    -> dwBackupBatteryFullLifeTime));
    RETAILMSG(
    1 ,(L " ACLineStatus = %d\n " ,ppbpi -> bACLineStatus));
    RETAILMSG(
    1 ,(L " BatteryFlag = %d\n " ,ppbpi -> bBatteryFlag));
    RETAILMSG(
    1 ,(L " BatteryLifePercent = %d\n " ,
    ppbpi
    -> bBatteryLifePercent));
    RETAILMSG(
    1 ,(L " BackupBatteryFlag = %d\n " ,
    ppbpi
    -> bBackupBatteryFlag));
    http://www.cnblogs.com/Images/Outli
    分享到:
    評(píng)論

Windows CE的電源管理


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 泗水县| 正定县| 文水县| 察雅县| 利川市| 横山县| 西宁市| 西乌| 耿马| 昭苏县| 安仁县| 荔浦县| 清水河县| 舒城县| 安泽县| 墨脱县| 鹿邑县| 乌鲁木齐县| 如皋市| 桃江县| 墨玉县| 凉城县| 陆良县| 新邵县| 六安市| 临湘市| 游戏| 克什克腾旗| 新源县| 普陀区| 景德镇市| 潮安县| 桑植县| 礼泉县| 栾城县| 盐池县| 西和县| 红桥区| 渭南市| 大城县| 尚义县|