原文
http://blog.mcuol.com/User/basicygp/Article/4340_1.htm
在mediaplayer全屏播放的時(shí)候,我可以用鍵盤(pán)上的某一個(gè)鍵調(diào)節(jié)聲音大小,現(xiàn)在我想在屏幕上顯示調(diào)節(jié)的結(jié)果就跟我們看電視一樣能出來(lái)一些標(biāo)記。當(dāng)聲音變大在屏幕上就增多,當(dāng)聲音變小的時(shí)候就減少
得到播放窗口的DC,然后在上面顯示一個(gè)不同顏色的矩形或者其它形狀。
在ce自制平臺(tái)中如何添加自己的驅(qū)動(dòng)?cec文件和reg,bib文件有何區(qū)別?看混了,不知道如何才能讓驅(qū)動(dòng)注冊(cè)到平臺(tái)中。另外,reg和bib是我在編寫(xiě)驅(qū)動(dòng)必須要自己寫(xiě)的么
CE 的驅(qū)動(dòng)分為本機(jī)驅(qū)動(dòng)和流驅(qū)動(dòng),本機(jī)驅(qū)動(dòng)你可以修改源碼(在%_WINCEROOT%\PUBLIC\COMMON\OAK\DRIVERS),然后 build驅(qū)動(dòng)源碼,之后用PB編譯內(nèi)核。流驅(qū)動(dòng)是以DLL的形式被系統(tǒng)程序加載的。加載流驅(qū)動(dòng)要在注冊(cè)表中添加信息,這和cec文件沒(méi)關(guān)。如果你想把此驅(qū)動(dòng)DLL和注冊(cè)信息作為一個(gè)整體給別人使用,那么就要做一個(gè)cec文件,PB能夠讀取cec文件內(nèi)容并加載到內(nèi)核工程中。cec文件相當(dāng)于安裝程序。
我安裝的是evc4.0,我開(kāi)發(fā)的系統(tǒng)要顯示中文比如姓名什么的。在編輯的時(shí)候是中文顯示,但是到了輸出時(shí),顯示的都是亂碼。不知道應(yīng)該怎么去解決
EVC的模擬器不支持中文。所以顯示出來(lái)的都是亂碼。1、你可以只顯示英文,調(diào)試結(jié)束后在改界面為中文。2、安裝PB,PB的模擬器支持中文。
CStatic及其控件的文字無(wú)法垂直居中顯示,雖然在evc的資源編輯器中可設(shè)置,但是一旦運(yùn)行,卻無(wú)法垂直居中顯示
這種情況正常,而且除此之外還不能右對(duì)齊。
獲取設(shè)備ID的種類(lèi)有哪些
除了手機(jī)模塊外,還有CF卡有序列號(hào)、硬盤(pán)有ID號(hào)、網(wǎng)卡有MAC號(hào)等。這幾種方法數(shù)獲取手機(jī)模塊ID最簡(jiǎn)單。
在應(yīng)用程序中,如何向修改本機(jī)的ip 地址等網(wǎng)絡(luò)參數(shù),并使之立即生效?
網(wǎng)絡(luò)設(shè)置保存在注冊(cè)表中,位置[HKEY_LOCAL_MACHINE\Comm\網(wǎng)卡名稱(chēng)\Parms\TcpIp],例如常見(jiàn)的CS8900網(wǎng)卡設(shè)置:
[HKEY_LOCAL_MACHINE\Comm\CS89001\Parms\TcpIp]
"EnableDHCP"=dword:0
"DefaultGateway"="192.168.0.1"
"DNS"="111.111.111.111"
"UseZeroBroadcast"=dword:0
"IpAddress"="192.168.0.2"
"Subnetmask"="255.255.255.0"
設(shè)置之后要生效有兩種辦法:一種熱啟動(dòng),調(diào)用KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL),熱啟動(dòng)時(shí)間很短暫;另外一種調(diào)用DevieceIoControl API,傳遞IOCTL= IOCTL_NDIS_REBIND_ADAPTER。
如何向控制面板中那樣,修改系統(tǒng)聲音的音量
調(diào)用API waveOutSetVolume(HWAVEOUT, dwVolume ),一般參數(shù)1為0。在[HKEY_CURRENT_USER\ControlPanel\Volume]下是系統(tǒng)聲音的注冊(cè)表設(shè)置。
在應(yīng)用程序中如何實(shí)現(xiàn)jpg、gif圖片的顯示
有幾種辦法:
1、在MSDN中搜索標(biāo)題為“Windows CE .NET Technical Frequently Asked Questions”的文檔,其中有一個(gè)問(wèn)題“How can I display JPEG, GIF, and other graphics files?”,下面就是答案。
2、如果安裝了Windows CE 5.0,一個(gè)例子源碼位于WINCE500\PUBLIC\GDIEX\SDK\SAMPLES\SIMPLE。
3、用IWebBrowser組件實(shí)現(xiàn)。
在應(yīng)用程序中如何實(shí)現(xiàn)系統(tǒng)待機(jī)
void GwesPowerOffSystem(void);
在WINCE下如何實(shí)現(xiàn)鍵盤(pán)鉤子
我寫(xiě)了一個(gè)簡(jiǎn)單的例子,把其中主要部分截取出來(lái)放到了我的FTP里。用戶名以及密碼均為winceuser,地址是ftp://211.95.73.26/fllsoft@sina.com/SourceCode/用鉤子禁止系統(tǒng)鍵.rar。
在WINCE中如何得到網(wǎng)卡MAC地址
事實(shí)證明,獲得物理網(wǎng)卡的MAC地址并沒(méi)有被統(tǒng)一成一個(gè)API或者IOCTL,如果網(wǎng)卡驅(qū)動(dòng)程序沒(méi)有提供接口的話只能直接訪問(wèn)寄存器獲得。讀者可以參考目錄WINCE500\PUBLIC\COMMON\OAK\DRIVERS\NETCARD里的一些驅(qū)動(dòng)源碼。
Windows XP Embedded 和Windows CE有何區(qū)別
簡(jiǎn)單地說(shuō)Windows XP Embedded采用Windows XP內(nèi)核,只能運(yùn)行在x86處理器上,優(yōu)點(diǎn)是能夠運(yùn)行PC上現(xiàn)有的應(yīng)用軟件,缺點(diǎn)是授權(quán)費(fèi)太高,標(biāo)價(jià)¥900元;Windows CE采用Windows CE內(nèi)核,能夠運(yùn)行在多種處理器上,如x86、ARM、SHX、MIPS等,優(yōu)點(diǎn)是授權(quán)費(fèi)低,最低Core版標(biāo)價(jià)¥30元。缺點(diǎn)是需要單獨(dú)開(kāi)發(fā)應(yīng)用軟件、定制內(nèi)核,甚至開(kāi)發(fā)BSP、Driver。
wince下只是把調(diào)制解調(diào)器的驅(qū)動(dòng)掛接在了com1,如何將器驅(qū)動(dòng)掛接在com2上?
1、在HLM\drivers\buildin\com2\unimodem下復(fù)制和com1一樣的數(shù)據(jù) 2、在HLM\ExtModems\ HayesCompat下改寫(xiě)Port為COM2:,再改寫(xiě)FriendlyName為"Hayes Compatible 在 COM2:"。
如何定制自己的外殼
1、先開(kāi)發(fā)一個(gè)外殼軟件,假設(shè)名稱(chēng)為MyShell.exe
2、刪除注冊(cè)表[HKEY_LOCAL_MACHINE\init]下如下一行:
"Launch50"="explorer.exe"
3、在注冊(cè)表[HKEY_LOCAL_MACHINE\init]下添加如下一行:
"Launch50"="MyShell.exe"
上述的“LaunchXX”中的XX為序列數(shù),內(nèi)核依據(jù)這個(gè)序列數(shù)按由小到大的順序來(lái)分別執(zhí)行所有子鍵列出的應(yīng)用程序,具體數(shù)值應(yīng)該為多少請(qǐng)參考幫助文檔的說(shuō)明。
如果原來(lái)的內(nèi)核中添加了標(biāo)準(zhǔn)外殼(standard shell)組件,或者添加了其它組件而這些組件需要依賴(lài)標(biāo)準(zhǔn)外殼,那么在PB中是無(wú)法刪除標(biāo)準(zhǔn)外殼組件的,解決辦法一是保留explorer.exe在內(nèi)核中,二是刪除依賴(lài)標(biāo)準(zhǔn)外殼的組件。
我原來(lái)的工程是x86版本的,編譯選項(xiàng)只有x86,我如何能夠編譯ARM版本的
兩種辦法:
1、用EVC新建一個(gè)工程的時(shí)候,建議復(fù)選“CPUs”列表,這樣發(fā)生了這種事情也能夠輕易通過(guò)選擇“WCE Configuration”工具欄中的CPU列表來(lái)編譯不同CPU版本的軟件
2、如果打開(kāi)工程后CPU列表中只有x86,而此時(shí)已經(jīng)安裝了ARM版本的SDK,那么單擊EVC菜單“build”-“configurations”,然后單擊“add”按鈕來(lái)添加CPU。
通常情況下WINCE采用串口1作為調(diào)試時(shí)輸出信息用途,要正式出產(chǎn)品前如何去掉串口1的調(diào)試功能
正常情況下串口1只有在編譯debug版本的內(nèi)核時(shí)才在BootLoader中初始化串口1用于輸出信息,而編譯release版本會(huì)跳過(guò)此代碼。而有些 BSP設(shè)計(jì)成沒(méi)有宏定義,也就是說(shuō)無(wú)論什么版本都會(huì)在BootLoader中初始化串口1,這樣造成WINCE啟動(dòng)后串口1無(wú)法被應(yīng)用程序使用。對(duì)于這種情況只能在BootLoader源碼中刪除初始化代碼,如OEMInitDebugSerial。
基于wince的應(yīng)用程序能建成console project么?
不能
ARM系統(tǒng)外擴(kuò)一片512K RAM,驅(qū)動(dòng)程序經(jīng)過(guò)映射可以使用這一段RAM。1、應(yīng)用系統(tǒng)如何使用這一段RAM?要加一層驅(qū)動(dòng)嗎?2、如果要將這一段RAM當(dāng)作RAM盤(pán)存儲(chǔ)系統(tǒng),該如何作呢?應(yīng)該要加文件系統(tǒng)吧,如何加呢?
解答這個(gè)問(wèn)題前,先要說(shuō)一下WINCE的地址映射機(jī)制。對(duì)于包含MMU(存儲(chǔ)器管理單元)的處理器來(lái)說(shuō),如ARM和x86,WINCE要求OEM在定制內(nèi)核的時(shí)候填寫(xiě)一個(gè)虛擬地址與物理地址映射關(guān)系的表,稱(chēng)為OEMAddressTable,在這個(gè)表中定義了所有物理設(shè)備的起始物理地址,對(duì)應(yīng)的起始虛擬地址,地址空間大小,RAM就包括在其中(如果是x86平臺(tái)還要求RAM起始虛擬地址從0x80000000開(kāi)始)。如果有多片RAM,應(yīng)該在 OEMAddressTable中將它們定義在一起,使之地址連續(xù)。對(duì)于非OEM的開(kāi)發(fā)者來(lái)說(shuō),他們拿到的是定制好的內(nèi)核,不能做任何修改,如果在產(chǎn)品中外擴(kuò)一片RAM,只能通過(guò)API函數(shù)通知操作系統(tǒng)增加一條虛擬地址與物理地址映射關(guān)系表項(xiàng)。相關(guān)API函數(shù)有兩個(gè),分別是 CreateStaticMapping和VirtualCopy。它們的相同之處是都用于建立物理地址和虛擬地址的映射關(guān)系。它們的不同之處是 CreateStaticMapping映射的虛擬地址范圍在0xC400 0000 到 0xE000 0000之間,這個(gè)范圍只能由內(nèi)核訪問(wèn),一般用于ISR訪問(wèn),因?yàn)?/span>ISR只能訪問(wèn)靜態(tài)映射的虛擬地址空間,不能用VirtualCopy。VirtualCopy通常和VirtualAlloc配合使用,映射的虛擬地址空間在0x8000 0000以下,一般用于驅(qū)動(dòng)程序和應(yīng)用程序訪問(wèn)。
1、應(yīng)用程序要訪問(wèn)這片RAM,和驅(qū)動(dòng)程序訪問(wèn)方法一樣,調(diào)用VirtualAlloc和VirtualCopy。
2、可以做一個(gè)流驅(qū)動(dòng)程序?qū)iT(mén)用于讀寫(xiě)這片RAM,這樣所有應(yīng)用程序就可以通過(guò)調(diào)用流驅(qū)動(dòng)接口函數(shù)來(lái)訪問(wèn),非要加文件系統(tǒng)也是可行的,通過(guò)修改注冊(cè)表就可以做到,但是麻煩一些。
我怎么能在PB左邊的定制平臺(tái)加進(jìn)我的驅(qū)動(dòng)呢?
兩種辦法:
1、在platform.bib或者project.bib的MODULES部分添加一條語(yǔ)句,例如:
MyDriver.dll C:\Driver\MyDriver.dll NK SH
這樣編譯內(nèi)核的時(shí)候就會(huì)把你的驅(qū)動(dòng)DLL文件添加到內(nèi)核中,如果有注冊(cè)表需要設(shè)置,在platform.reg或者project.reg中添加注冊(cè)表內(nèi)容。
2、通過(guò)制作.cec文件來(lái)添加驅(qū)動(dòng),制作.cec文件的優(yōu)點(diǎn)是只需制作一次,以后就可以通過(guò)將.cec文件導(dǎo)入到PB的Catalog中,象PB自帶的feature一樣通過(guò)菜單“Add to OS Design”添加到左邊的內(nèi)核工程中。
WINCE有沒(méi)有相對(duì)路徑概念?如果沒(méi)有如何得到當(dāng)前模塊的路徑?
1、WINCE沒(méi)有相對(duì)路徑概念,只有絕對(duì)路徑,所以凡是涉及到路徑均為絕對(duì)路徑。
2、調(diào)用API GetModuleFileName,傳遞一個(gè)模塊的實(shí)例句柄就能夠得到模塊的絕對(duì)路徑。
怎樣讓 POCKET WORD打開(kāi)*.dat格式(里面都是數(shù)據(jù))的文件?
兩種辦法:
1、調(diào)用API ShellExecuteEx,在結(jié)構(gòu)體SHELLEXECUTEINFO中添加.dat文件的路徑。
2、調(diào)用API CreateProcess,在第二個(gè)參數(shù)中設(shè)置.dat文件的路徑。
x86 Rom Boot Loader真的可以實(shí)現(xiàn)嗎?它確實(shí)能代替BIOS啟動(dòng)計(jì)算機(jī)?
Rom Boot 被設(shè)計(jì)存放在Flash/EEPROM中,也就是原來(lái)BIOS的位置,這樣當(dāng)上電后CPU到固定地址執(zhí)行代碼,也就是執(zhí)行了Rom Boot的代碼,它對(duì)整個(gè)硬件系統(tǒng)進(jìn)行初始化和檢測(cè),并且支持通過(guò)網(wǎng)卡從遠(yuǎn)程機(jī)器上下載nk.bin或者從本地IDE/ATA 硬盤(pán)的活動(dòng)分區(qū)中尋找nk.bin文件加載。 Rom Boot的優(yōu)點(diǎn)就是引導(dǎo)并且加載速度快,而且它自身完成了所有的操作,這樣就不用BIOS、MSDOS,更不用Loadcepc了。
對(duì)于x86 Rom Boot Loader,如何Build得到Romboot.rom?
1、在PB中打開(kāi)一個(gè)內(nèi)核工程(x86的) 2、單擊PB菜單“Build”-“Open Build Release Directory” 3、用cd命令進(jìn)入 %_WINCEROOT%\Platform\Geode\Romboot 4、build
如何設(shè)置、更改顯示分辨率
能否設(shè)置、更改顯示分辨率由顯示驅(qū)動(dòng)程序決定,而沒(méi)有統(tǒng)一的標(biāo)準(zhǔn)。例如CEPC,在啟動(dòng)的時(shí)候可以通過(guò)設(shè)置loadcepc.exe的參數(shù) /L來(lái)決定 WINCE啟動(dòng)后的顯示分辨率,這是由于顯示驅(qū)動(dòng)“VGA Linear Framebuffer”支持,而Geode可以通過(guò)在定制內(nèi)核時(shí)修改注冊(cè)表項(xiàng)來(lái)決定WINCE啟動(dòng)后的顯示分辨率。
幾個(gè)硬件使用同一個(gè)IRQ,那么發(fā)生中斷的時(shí)候系統(tǒng)怎么判斷到底是哪一個(gè)硬件發(fā)生的中斷呢?ISR里面又應(yīng)該怎么控制呢?
Windows CE 支持多個(gè)設(shè)備中斷共享一個(gè)IRQ,當(dāng)一個(gè)共享IRQ發(fā)生時(shí),CE內(nèi)核的異常處理程序檢測(cè)設(shè)備特定的寄存器,因?yàn)榇蠖鄶?shù)設(shè)備都有一個(gè)單獨(dú)的寄存器用于表示設(shè)備的活動(dòng)狀態(tài),所以通過(guò)遍歷共享這個(gè)IRQ的所有設(shè)備的寄存器就可以判斷哪個(gè)設(shè)備發(fā)生中斷。nk.exe加載一個(gè)giisr.dll,這個(gè).dll是微軟提供的,它其實(shí)是第一個(gè)可安裝ISR。默認(rèn)CE內(nèi)核就是調(diào)用這個(gè)dll來(lái)檢測(cè)寄存器狀態(tài)的,當(dāng)然OEM可以編寫(xiě)自己的.dll。
CE內(nèi)部有一個(gè)ISR鏈,也就是可安裝ISR。因?yàn)?/span>CE允許OEM添加自己的ISR處理程序,所以ISR被設(shè)計(jì)成一個(gè)鏈表。排在前面的ISR比后面的ISR優(yōu)先處理中斷,如果當(dāng)前ISR能夠處理當(dāng)前中斷,那就返回中斷ID由IST處理或者返回SYSINTR_NOP,如果當(dāng)前ISR不能夠處理當(dāng)前中斷,那就返回 SYSINTR_CHAIN讓下一個(gè)ISR處理。
請(qǐng)問(wèn)在wince中如何在內(nèi)核中增加一個(gè)與\windows同級(jí)的目錄?
在platform.dat或者project.dat中添加語(yǔ)句。例如要?jiǎng)?chuàng)建根目錄下子目錄Program Files,語(yǔ)句如下:
root:-Directory("Program Files")
文件格式如下所示,我想把每行的4個(gè)值讀到4個(gè)變量中,用EVC如何編程?
第一行: 460.000, 3384672.357342, 521268.972763
第二行: 475.117, 3384663.772419, 521281.415271
偽代碼如下:
FILE *stream;
stream = _wfopen(L"\\a.txt", L"r+");
if( stream == NULL )
return;
fseek(stream, 0L, SEEK_SET );
while( !feof( stream ) )
{
fwscanf(stream, L"%s", WCHAR1);
fwscanf(stream, L"%f", float1);
fwscanf(stream, L"%f", float2);
fwscanf(stream, L"%f", float3);
}
fclose( stream );
GWES組件的功能有哪些?
GWES不僅負(fù)責(zé)GDI、窗口、消息,還負(fù)責(zé)管理本機(jī)設(shè)備驅(qū)動(dòng)程序,負(fù)責(zé)加載顯示、鍵盤(pán)鼠標(biāo)、觸摸屏驅(qū)動(dòng)程序,而且GWES本身包含電源、LED驅(qū)動(dòng)程序。
如何在PB中預(yù)先設(shè)定好存儲(chǔ)內(nèi)存和程序內(nèi)存的大小,我想多劃分一些空間給程序內(nèi)存?
兩種辦法:
1、在定制內(nèi)核時(shí)在config.bib文件中設(shè)置FSRAMPERCENT = number,具體number可參考標(biāo)題為“FSRAMPERCENT ”的幫助文檔。這種辦法是修改內(nèi)核的設(shè)置,所有一直有效。
2、在應(yīng)用程序中調(diào)用API SetSystemMemoryDivision,如果函數(shù)返回SYSMEM_CHANGED表示成功,如果返回SYSMEM_MUSTREBOOT表示需要熱啟動(dòng)才能有效。這種辦法需要每次啟動(dòng)后調(diào)用API才有效。
如何取消鼠標(biāo)光標(biāo)?
通過(guò)取消SYS變量來(lái)實(shí)現(xiàn)此目的,在PB命令行下鍵入“set SYSGEN_CURSOR=”,然后回車(chē)確認(rèn)。
EVC下調(diào)用TextOut如何編譯會(huì)出錯(cuò)?
類(lèi)似這樣的問(wèn)題很多,這是因?yàn)?/span>EVC的幫助文檔內(nèi)容有錯(cuò)誤。可能EVC的幫助文檔內(nèi)容是從桌面Windows幫助文檔復(fù)制過(guò)來(lái)的,所以很多API函數(shù)還有例子代碼都有錯(cuò)誤,例如幫助文檔中包含一個(gè)API函數(shù)的說(shuō)明,但是實(shí)際編譯的時(shí)候提示沒(méi)有這個(gè)API,有的例子代碼采用ANSI字符串,而WINCE的 API都是寬字符版本,造成直接復(fù)制過(guò)來(lái)編譯失敗。
因?yàn)?/span>MFC for WINCE的CDC類(lèi)中沒(méi)有TextOut成員函數(shù),所以編譯會(huì)出錯(cuò),可以用其它類(lèi)成員函數(shù)ExtTextOut或者DrawText替換。
我如何將我的dll軟件讓現(xiàn)有的ce系統(tǒng)認(rèn)可?盡管我也知道應(yīng)該使用signfile.exe程序進(jìn)行簽名,但是我并不知道那個(gè)ce系統(tǒng)認(rèn)可的簽名應(yīng)該是啥
如果你說(shuō)的WINCE系統(tǒng)內(nèi)核已經(jīng)加入了簽名認(rèn)證機(jī)制,那么沒(méi)有私鑰對(duì)你的DLL文件簽名肯定是無(wú)法運(yùn)行在此內(nèi)核中的,一般簽名密鑰的密鑰長(zhǎng)度都是1024位,很難破解。
如果查看WINCE注冊(cè)表中的內(nèi)容?
兩種辦法:
1、建立同步后,用EVC自帶的工具“Remote Registry Editor”打開(kāi)查看。
2、從網(wǎng)上下載注冊(cè)表查看工具,放到WINCE設(shè)備中。
調(diào)用directshow出現(xiàn)鏈接錯(cuò)誤,如何解決?
player.obj : error LNK2001: unresolved external symbol _IID_IVideoWindow
player.obj : error LNK2001: unresolved external symbol _IID_IMediaControl
這是因?yàn)殒溄悠鳑](méi)有找到合適的.lib文件。兩種辦法:
1、在EVC菜單Tools—options—directories 里把library files的路徑重新調(diào)整一下。如果你只安裝了EVC自帶的 Standard SDK而沒(méi)有其它SDK,可以指定WINCE目錄中的.lib文件路徑,例如D:\WINCE500\PUBLIC\DIRECTX\ OAK\LIB\X86\RETAIL。注意CPU的類(lèi)型。
2、安裝SDK,前提是導(dǎo)出SDK的PB內(nèi)核工程必須包括DirectShow或者其它組件。
在PB的config.bib文件中,“IMGFLASH”表示什么意思呢?
表示能夠刷NK到ROM中,具體請(qǐng)查看標(biāo)題為“IMG Environment Variables”的幫助文檔。
x86平臺(tái)如何映射各種地址空間?如何編寫(xiě)中斷服務(wù)例程?
如果是x86平臺(tái),可以調(diào)用HalTranslateBusAddress轉(zhuǎn)換物理總線地址到物理系統(tǒng)地址,調(diào)用 HalTranslateSystemAddress轉(zhuǎn)換物理系統(tǒng)地址到邏輯總線地址,也可以不調(diào)用這兩個(gè)函數(shù),因?yàn)?/span>x86平臺(tái)除32位物理地址外還有 16位的IO地址空間,對(duì)于16位的IO地址空間,可以直接調(diào)用WRITE_PORT_UCHAR或者READ_PORT_UCHAR等函數(shù)直接讀寫(xiě)端口。對(duì)于32位物理地址可以調(diào)用VirtualAlloc和VirtualCopy來(lái)映射。這樣做思路清晰,簡(jiǎn)單明了。
在x86平臺(tái)要實(shí)現(xiàn)ISR,有如下幾個(gè)步驟(以Geode BSP為例):
1、用SETUP_INTERRUPT_MAP宏關(guān)聯(lián)SYSINTR和IRQ。以“SYSINTR_”為前綴的常量由內(nèi)核使用,用于唯一標(biāo)識(shí)發(fā)生中斷的硬件,又稱(chēng)為中斷ID。在Nkintr.h文件中預(yù)定義了一些SYSINTR,OEM可以在Oalintr.h文件中自定義SYSINTR。
2、用HookInterrupt函數(shù)關(guān)聯(lián)硬件中斷號(hào)和ISR。這里提到的硬件中斷號(hào)為物理中斷號(hào),IRQ為邏輯中斷號(hào)。在InitPICs函數(shù)的最后調(diào)用了HookInterrupt函數(shù),如下:
for (i = 64; i < 80; i++)
HookInterrupt(i, (void *)PeRPISR); ///用ISR關(guān)聯(lián)16個(gè)中斷號(hào)
3、調(diào)用InterruptInitialize函數(shù)關(guān)聯(lián)SYSINTR和IST創(chuàng)建的事件對(duì)象,也是IST等待的事件對(duì)象。詳細(xì)內(nèi)容請(qǐng)參考Geode BSP源碼。
在x86 平臺(tái)要實(shí)現(xiàn)可安裝ISR,先調(diào)用LoadIntChainHandler函數(shù)注冊(cè)在注冊(cè)表中指定的ISR DLL,然后填充GIISR_INFO結(jié)構(gòu)體并調(diào)用KernelLibIoControl函數(shù)將此結(jié)構(gòu)體傳遞給可安裝ISR。詳細(xì)內(nèi)容請(qǐng)參考WINCE幫助文檔或者我著的《Windows CE下驅(qū)動(dòng)開(kāi)發(fā)基礎(chǔ)》。
修改了WINCE自帶的驅(qū)動(dòng)程序后如何編譯?如果是自己開(kāi)發(fā)的驅(qū)動(dòng)程序如何編譯?
1、分為IDE方式和命令行方式。
IDE 方式的編譯很簡(jiǎn)單,以PB5.0為例,打開(kāi)定制內(nèi)核的工程,在左邊的“workspace”—“FileView”中找到你已經(jīng)修改了的目錄,然后單擊右鍵彈出菜單,在菜單中選擇“Build and Sysgen Current Project”,這樣PB就會(huì)編譯指定的目錄中的項(xiàng)目源碼文件,然后執(zhí)行sysgen命令根據(jù)source文件中的內(nèi)容生成目標(biāo)文件并復(fù)制到當(dāng)前內(nèi)核工程目錄下。
命令行方式的編譯需要打開(kāi)“Build OS” —“Open Release Directory”,以cd命令進(jìn)入你已經(jīng)修改的驅(qū)動(dòng)程序目錄中,然后鍵入“build –cfs”,然后鍵入 “sysgen –p 項(xiàng)目名稱(chēng)”,一般項(xiàng)目名稱(chēng)為source文件中的“TARGETNAME”。
2、如果想完全自己開(kāi)發(fā)驅(qū)動(dòng)程序,建議直接采用EVC或者PB來(lái)編寫(xiě)編譯。
開(kāi)發(fā)PCI設(shè)備驅(qū)動(dòng)時(shí),InterruptInitialize函數(shù)的第一參數(shù)是否是PCI卡配置空間信息中的InterruptLine 參數(shù)?是否需要在HKLM\Drivers\BuiltIn\PCI\Template 加一個(gè)自己的 subkey,并填寫(xiě)相應(yīng)內(nèi)容?如何填?
1、InterruptInitialize的第一參數(shù)是IRQ,也就是邏輯中斷號(hào),而不是物理中斷號(hào),InterruptLine是指物理中斷號(hào)
2、需要在template下加自己的PCI設(shè)備的信息,例如:
[HKEY_LOCAL_MACHINE\Drivers\PCI\Template\Serial]
"Dll"="Com16550.Dll"
"Class"=dword:07
"SubClass"=dword:00
"ProgIF"=dword:02
"VendorID"=multi_sz:"0AF0","B320","B320"
"DeviceID"=multi_sz:"0020","0300","0302"
"Prefix"="COM"
而這些信息就來(lái)自于你執(zhí)行pcienum.exe的結(jié)果。
編譯器報(bào)錯(cuò):error C2065: ''CFileFind'' : undeclared identifier,如何解決?
MFC for WINCE版本沒(méi)有CFileFind類(lèi),所以要查找文件只能調(diào)用API FindFirstFile 和FindNextFile。
如何設(shè)置WINCE系統(tǒng)字體、字號(hào)?如何設(shè)置自己開(kāi)發(fā)的軟件的字體、字號(hào)?
1、系統(tǒng)字體通過(guò)注冊(cè)表設(shè)置。如下:
[HKEY_LOCAL_MACHINE\System\GDI\SysFnt] ///系統(tǒng)字體
Wt=420
Ht=18
Nm=Arial
[HKEY_LOCAL_MACHINE\System\GWE\Menu\BarFnt] ///菜單欄字體
[HKEY_LOCAL_MACHINE\System\GWE\Menu\PopFnt] ///彈出窗口字體
[HKEY_LOCAL_MACHINE\System\GWE\Menu] ///菜單字體
HKEY_LOCAL_MACHINE\System\GWE\Button ///按鈕字體
2、創(chuàng)建字體時(shí)把字體高度參數(shù)設(shè)置大點(diǎn)就可以了。如CFont::CreateFont(nHeight,...),也可以在LOGFONT結(jié)構(gòu)中設(shè)置字體高度或者字體種類(lèi)。如果是控件,調(diào)用控件的SetFont成員函數(shù)。如果是直接畫(huà),在OnPaint響應(yīng)函數(shù)中調(diào)用SelectObject選字體到DC。
nk.bin和nk.nb0有什么區(qū)別?
這里提到的bin是一種二進(jìn)制鏡像格式,以片斷(section)為單位組織數(shù)據(jù),每個(gè)片斷都包括一個(gè)頭,頭里指定了起始地址,長(zhǎng)度,校驗(yàn)值。Platform Builder調(diào)用工具將WINCE內(nèi)核所有文件以bin格式合并成一個(gè)文件,默認(rèn)文件名為nk.bin。BootLoader又以同樣的格式將nk.bin分解成多個(gè)文件放到RAM中。可以在命令行中鍵入 “viewbin nk.bin”來(lái)查看bin文件中具體包括了哪些內(nèi)容。鍵入Cvrtbin命令轉(zhuǎn)換.bin格式文件為.sre格式或者.abx格式。
nb0格式是原始的二進(jìn)制鏡像,它不包括頭,一般情況下將內(nèi)核下載到設(shè)備的RAM中運(yùn)行都采用nb0格式。要生成nbx格式的文件,需要在相關(guān).bib文件中確定如下值:ROMSTART、ROMWIDTH、ROMSIZE。
在不采用硬件計(jì)時(shí)器的情況下如何創(chuàng)建更精確的計(jì)時(shí)器?最精確周期能否達(dá)到1毫秒?
對(duì)于精確值的要求不同,所采用的辦法不同。以下闡述幾種辦法。
1、在單線程中循環(huán)調(diào)用API Sleep函數(shù),Sleep函數(shù)精確程度為如果Sleep(N),那么實(shí)際睡眠時(shí)間在N到N+1毫秒之間。而且還要注意調(diào)用Sleep的線程優(yōu)先級(jí)的問(wèn)題。如果任務(wù)過(guò)多并且此線程優(yōu)先級(jí)低,那誤差就更大些。
2、調(diào)用API QueryPerformanceCounter函數(shù),舉例如下:
LARGE_INTEGER liFrequency;
if (QueryPerformanceFrequency(&liFrequency)) // 查詢系統(tǒng)時(shí)鐘的頻率,這里將返回1000
{
liFrequency.QuadPart /= 1000;
LARGE_INTEGER liTimeOut;
if (QueryPerformanceCounter(&liTimeOut)) //得到截至到當(dāng)前累計(jì)發(fā)生的系統(tǒng)時(shí)鐘中斷次數(shù)
{
liTimeOut.QuadPart += liFrequency.QuadPart; ///計(jì)算下一秒到來(lái)時(shí)總的中斷次數(shù)是多少
LARGE_INTEGER liCurrent;
do
{
QueryPerformanceCounter(&liCurrent); // 循環(huán)查詢累計(jì)的的中斷次數(shù)
} while (liCurrent.QuadPart < liTimeOut.QuadPart); ///到達(dá)下一秒
}
}
調(diào)用QueryPerformanceCounter同調(diào)用Sleep在本質(zhì)上都是一樣的,都是在單線程中無(wú)限循環(huán)等到周期一到執(zhí)行任務(wù),相比較 QueryPerformanceCounter要比Sleep更精確些,越精確就越要求線程的優(yōu)先級(jí),保障線程能夠正常得到處理器。
3、以上辦法難以保證周期精確到1毫秒并且WINCE系統(tǒng)穩(wěn)定地運(yùn)行,所以要從中斷入手。以x86平臺(tái)為例,先在Timer.c中將默認(rèn)的SetTimer0 (TIMER_COUNT)中的TIMER_COUNT /=2,SetTimer0函數(shù)負(fù)責(zé)設(shè)置系統(tǒng)時(shí)鐘的頻率,默認(rèn)1毫秒發(fā)生一次中斷,如果除以2就是0.5毫秒發(fā)生一次中斷。然后在fwpc.c文件中修改ISR函數(shù)PeRPISR,因?yàn)樵瓉?lái)默認(rèn)是1毫秒發(fā)生一次中斷,在處理INTR_TIMER0時(shí)系統(tǒng)負(fù)責(zé)累計(jì)計(jì)數(shù)、管理線程的調(diào)度,返回相應(yīng)的SYSINTR值,而我們沒(méi)有辦法再添加代碼返回自己定義的SYSINTR值,所以現(xiàn)在要修改原來(lái)的處理代碼,例如設(shè)置一個(gè)BOOL型變量,TRUE就執(zhí)行原來(lái)默認(rèn)的代碼,而FALSE就返回我們自己定義的SYSINTR值,這樣即不影響原來(lái)的ISR處理,又加入了我們的中斷響應(yīng)代碼。ISR返回我們定義的SYSINTR后WINCE內(nèi)核激活相對(duì)應(yīng)的EVENT事件,我們就可以在我們編寫(xiě)的IST里處理任務(wù)了。
flash中存放了BootLoader和內(nèi)核鏡像,如何把剩余flash部分劃分為一個(gè)存儲(chǔ)區(qū)域供應(yīng)用程序讀寫(xiě)?
以WINCE 提供的驅(qū)動(dòng)(FAT文件系統(tǒng)和MSFLASH驅(qū)動(dòng))來(lái)舉例說(shuō)明。如果采用默認(rèn)common.reg中的注冊(cè)表設(shè)置,那么MSFLASH驅(qū)動(dòng)默認(rèn)把整個(gè) flash作為存儲(chǔ)區(qū)域來(lái)讀寫(xiě),這不符合問(wèn)題的要求,所以必須告訴MSFLASH驅(qū)動(dòng)程序可供讀寫(xiě)的區(qū)域的起始地址和長(zhǎng)度。以下是一個(gè)注冊(cè)表例子:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\FASLD]
"Dll"="fasld.dll" ///實(shí)際Flash存儲(chǔ)器的驅(qū)動(dòng)程序
"Order"=dword:2 ///該驅(qū)動(dòng)程序相對(duì)于其它驅(qū)動(dòng)程序的加載順序
"Prefix"="DSK" ///前綴
"Ioctl"=dword:4 ///IOCTL碼,設(shè)備管理器加載驅(qū)動(dòng)的時(shí)候調(diào)用IOControl函數(shù),傳遞這個(gè)IOCTL碼。
"Profile"="MSFlash" ///Profile名稱(chēng),也就是[HLM\System\StorageManager\Profiles\MSFlash]
///當(dāng)設(shè)備管理器加載此驅(qū)動(dòng)程序的同時(shí)發(fā)送通知給系統(tǒng),IClass(GUID)的值表明這是一個(gè)存儲(chǔ)設(shè)備的驅(qū)動(dòng)程序。
"IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
"MemBase"=dword:00000000 ///Flash中可供讀寫(xiě)區(qū)域的起始物理地址,也就是Flash的首地址+偏移量
"MemLen"=dword:00000000 ///Flash中可供讀寫(xiě)區(qū)域的長(zhǎng)度
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\MSFlash]
"DefaultFileSystem"="FATFS" ///MSFlash驅(qū)動(dòng)默認(rèn)采用的文件系統(tǒng)
"PartitionDriver"="mspart.dll" ///采用的分區(qū)驅(qū)動(dòng)程序
"MountAsRoot"=dword:1 ///此目錄作為文件系統(tǒng)的根目錄
"Folder"="NOR Flash" ///目錄名稱(chēng)
"Name"="FLASH Disk Block Device" ///Flash驅(qū)動(dòng)名稱(chēng)
"PartitionDriverName"="MSPART" ///分區(qū)驅(qū)動(dòng)名稱(chēng)
"AutoMount"=dword:1 ///自動(dòng)裝載檢測(cè)到的分區(qū)
"AutoPart"=dword:1 ///自動(dòng)分區(qū)
"AutoFormat"=dword:1 ///自動(dòng)格式化分區(qū)
[HKEY_LOCAL_MACHINE\System\StorageManager\AutoLoad\MSFlash]
"DriverPath"="Drivers\\BuiltIn\\FASLD" ///Flash驅(qū)動(dòng)在注冊(cè)表中的位置
"LoadFlags"=dword:1 ///這個(gè)值可以被設(shè)置為0、1、2。1表示同步加載,其它表示異步加載
"Order"=dword:0
[HKEY_LOCAL_MACHINE\System\StorageManager\FATFS]
"FriendlyName"="FAT FileSystem" ///文件系統(tǒng)名稱(chēng)
"Dll"="fatfsd.dll" ///文件系統(tǒng)驅(qū)動(dòng)程序
"Flags"=dword:00000064 ///標(biāo)志,詳見(jiàn)幫助文檔
"Paging"=dword:1 ///是否分頁(yè)
"EnableCache"=dword:1 ///是否允許緩存數(shù)據(jù)
"CacheSize"=dword:0 ///指定緩存大小,0表示默認(rèn)
驅(qū)動(dòng)程序如何發(fā)通知給應(yīng)用程序?
這里介紹一下常見(jiàn)的兩種辦法。
1、驅(qū)動(dòng)程序調(diào)用API SendNotifyMessage,發(fā)送特定的消息給應(yīng)用程序,這就要求應(yīng)用程序要有消息循環(huán)機(jī)制并且要事先做好消息的處理。參數(shù) 1為窗口句柄,可以設(shè)置HWND_BROADCAST表示廣播消息。要注意的是不要在參數(shù)中傳遞指針(虛擬地址),因?yàn)閳?zhí)行驅(qū)動(dòng)程序的線程和應(yīng)用程序并不在同一個(gè)進(jìn)程空間中。解決辦法可以利用內(nèi)存映射文件技術(shù),比如在驅(qū)動(dòng)程序中創(chuàng)建一個(gè)內(nèi)存映射文件對(duì)象,申請(qǐng)一塊物理內(nèi)存,然后把對(duì)象名稱(chēng)和內(nèi)存長(zhǎng)度傳遞給應(yīng)用程序,應(yīng)用程序打開(kāi)同名的內(nèi)存映射文件對(duì)象,讀取里面的數(shù)據(jù)。對(duì)象名稱(chēng)可以事先協(xié)定好,也可以通過(guò)注冊(cè)表來(lái)傳遞,內(nèi)存長(zhǎng)度是32位值,通過(guò)消息參數(shù)就可以傳遞,也可以通過(guò)注冊(cè)表來(lái)傳遞。另外一種解決辦法是在定制內(nèi)核時(shí)候預(yù)留一塊物理內(nèi)存,這樣驅(qū)動(dòng)程序和應(yīng)用程序都可以通過(guò)VirtualAlloc和 VirtualCopy來(lái)映射到同一塊物理內(nèi)存,其原理同內(nèi)存映射文件技術(shù)一樣,但是這塊物理內(nèi)存不具備通用性。最后一個(gè)辦法是應(yīng)用程序事先將一個(gè)緩沖區(qū)地址傳遞給驅(qū)動(dòng)程序,驅(qū)動(dòng)程序調(diào)用MapPtrToProcess映射應(yīng)用程序傳遞過(guò)來(lái)的地址,當(dāng)驅(qū)動(dòng)程序調(diào)用SendNotifyMessage后應(yīng)用程序可以直接到該地址中讀取數(shù)據(jù)。
設(shè)備管理器就是調(diào)用此函數(shù)廣播WM_DEVICECHANGE消息的。另外WINCE的一個(gè)例子程序RNAApp在撥號(hào)連接建立的時(shí)候也是調(diào)用這個(gè)函數(shù)廣播WM_NETCONNECT消息的。
2、驅(qū)動(dòng)程序調(diào)用API CeEventHasOccurred指明一個(gè)事件A發(fā)生,在此之前應(yīng)用程序調(diào)用API CeRunAppAtEvent將驅(qū)動(dòng)程序指明的A事件和一個(gè)應(yīng)用程序名稱(chēng)相關(guān)聯(lián),或者和一個(gè)事件B相關(guān)聯(lián)。這樣當(dāng)A事件發(fā)生時(shí),如果指明和一個(gè)應(yīng)用程序名稱(chēng)關(guān)聯(lián),那這個(gè)應(yīng)用程序就會(huì)被啟動(dòng)。如果指明了和一個(gè)事件B相關(guān)聯(lián),那么等待事件B的線程將被激活。如果想了解當(dāng)前系統(tǒng)內(nèi)部所有驅(qū)動(dòng)程序支持哪些類(lèi)似事件A的事件,調(diào)用 API CeNotifyPublic_FilterEvent,在該API的幫助文檔里也列舉了常見(jiàn)的事件,例如 NOTIFICATION_EVENT_NET_CONNECT和 NOTIFICATION_EVENT_NET_DISCONNECT。
EVC創(chuàng)建的工程名稱(chēng)如果用中文就出錯(cuò),該怎么辦?
用EVC創(chuàng)建的工程名稱(chēng)如果為中文將導(dǎo)致資源文件打不開(kāi)和編譯出錯(cuò),可以改資源文件名稱(chēng)為英文,再編輯.rc文件中的資源文件名稱(chēng)。但建議盡量不要用中文為工程名稱(chēng)。
作為習(xí)慣,應(yīng)該在EVC創(chuàng)建一個(gè)工程后,立刻在“project”—“settings”中設(shè)置資源的語(yǔ)言屬性,然后在“resource view”中設(shè)置每個(gè)資源的語(yǔ)言屬性,這些工作做完后再修改資源就沒(méi)有問(wèn)題了。有人詢問(wèn)對(duì)話框的標(biāo)題為亂碼,其原因就是在沒(méi)有修改語(yǔ)言屬性的情況下設(shè)置標(biāo)題為中文。
WinCE下如何讀寫(xiě)幾百兆的大文件呢? 使用內(nèi)存映射文件嗎?
一般嵌入式設(shè)備配備128MB物理內(nèi)存就算頂級(jí)的了,所以要讀寫(xiě)幾百MB的文件用內(nèi)存映射文件技術(shù)是最好的選擇了。映射文件之后讀數(shù)據(jù)是非常容易的,要注意的是寫(xiě)數(shù)據(jù),內(nèi)存映射方面的API沒(méi)有提供改變文件長(zhǎng)度的功能,所以要在關(guān)閉映射文件對(duì)象后用文件API改變文件長(zhǎng)度。
請(qǐng)問(wèn)如何改系統(tǒng)調(diào)度的默認(rèn)時(shí)間片值?
更改schedule.c文件中的dwDefaultThreadQuantum 變量,然后重新編譯該文件并SYSGEN。調(diào)用API CeGetThreadQuantum就知道更改是否生效。
如何讓系統(tǒng)加載自己寫(xiě)的驅(qū)動(dòng)程序?
兩種辦法:
1、在[HKEY_LOCAL_MACHINE\Drivers\BuiltIn]下添加注冊(cè)鍵。
2、在應(yīng)用程序中調(diào)用ActivateDeviceEx。
在一些文件中用分號(hào)來(lái)表示注釋?zhuān)缦旅娴膬?nèi)容
; @CESYSGEN IF SERVERS_MODULES_HTTPD
; @CESYSGEN ENDIF
在“CESYSGEN...”前加了“@”,有沒(méi)有什么特別的含義?
在WINCE的一些文件中,用“;”作為注釋并在注釋文字中用@CESYSGEN作為標(biāo)記,后面接條件語(yǔ)句。Cefilter.exe工具負(fù)責(zé)按照條件來(lái)篩選文件內(nèi)容,所以不要輕易地刪除包含@CESYSGEN的注釋語(yǔ)句。
通過(guò)串口建立ActiveSync聯(lián)接,串口線用三線的可以嗎?
不可以,因?yàn)橛么谕綍r(shí)要用到其余口的狀態(tài)。
WINCE是否支持MAPI?
不支持。WINCE自帶的pmail.exe軟件也不是很好用。建議自開(kāi)發(fā)郵件收發(fā)軟件。如果需要購(gòu)買(mǎi)WINCE下郵件收發(fā)軟件可以聯(lián)系我。
如何旋轉(zhuǎn)屏幕顯示的內(nèi)容?
例子代碼如下(前提是顯示驅(qū)動(dòng)程序支持旋轉(zhuǎn)):
DEVMODE devmode = {0};
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDisplayOrientation = DMDO_90; ///垂直模式
devmode.dmFields = DM_DISPLAYORIENTATION;
ChangeDisplaySettingsEx(NULL, &devmode, NULL, 0, NULL); ///改變顯示的設(shè)置
CRect rcWorkArea(0, 0, 320, 240); ///整個(gè)屏幕尺寸
///設(shè)置客戶區(qū)大小并廣播消息,這樣所有軟件也就隨之更改顯示
SystemParametersInfo(SPI_SETWORKAREA, 0, (void*)&rcWorkArea, SPIF_SENDCHANGE);
請(qǐng)問(wèn)如何修改字形緩存的容量?
[HKEY_LOCAL_MACHINE\System\GDI\GLYPHCACHE]
"limit"=dword:0400
如何得到從WINCE啟動(dòng)開(kāi)始到現(xiàn)在的時(shí)間?
調(diào)用API GetTickCount,得到的值為32位整數(shù),單位為毫秒。
如何調(diào)用WINCE的軟鍵盤(pán)?
調(diào)用API SipShowIM(SIPF_ON),前提是內(nèi)核加入了軟鍵盤(pán)組件。
基于HIVE的注冊(cè)表,如何在系統(tǒng)關(guān)閉前保存注冊(cè)表的數(shù)據(jù)到文件system.hv?
調(diào)用API RegFlushKey函數(shù)。
使用VirtualAlloc和VirtualCopy的時(shí)候需要注意哪些事項(xiàng)?
1、 VirtualAlloc的作用是申請(qǐng)?zhí)摂M地址空間,這肯定不是最終的目的,最終目的可能是申請(qǐng)物理內(nèi)存、映射寄存器、提交文件等。沒(méi)有一個(gè)目的會(huì)在意虛擬地址空間的位置,所以盡量傳遞參數(shù)1為0,也就是讓WINCE自動(dòng)分配虛擬地址空間。VirtualAlloc分配地址空間實(shí)際上是以64KB為單位,所以要指定申請(qǐng)的虛擬空間的首地址的話,參數(shù)1應(yīng)該為64KB的整數(shù)倍,申請(qǐng)的長(zhǎng)度也應(yīng)該為64KB的整數(shù)倍,即使你不需要那么大。
2、 VirtualCopy的主要作用是映射物理地址空間,如果參數(shù)2為物理地址,那么最后一個(gè)參數(shù)要添加PAGE_PHYSICAL,參數(shù)2必須是256的整數(shù)倍。如果參數(shù)2為虛擬地址(0x80000000以上),那么最后一個(gè)參數(shù)就不要添加PAGE_PHYSICAL,WINCE內(nèi)核會(huì)根據(jù)這個(gè)虛擬地址找到對(duì)應(yīng)的物理地址。
驅(qū)動(dòng)程序和應(yīng)用程序之間傳遞數(shù)據(jù)時(shí)何時(shí)調(diào)用MapPtrToProcess?
因?yàn)樵O(shè)備管理器負(fù)責(zé)加載驅(qū)動(dòng)程序DLL,這意味著當(dāng)應(yīng)用程序調(diào)用驅(qū)動(dòng)程序接口函數(shù)的時(shí)候,WINCE內(nèi)核會(huì)將調(diào)用驅(qū)動(dòng)程序接口函數(shù)的線程轉(zhuǎn)移到設(shè)備管理器的進(jìn)程空間然后執(zhí)行具體的驅(qū)動(dòng)程序代碼,應(yīng)用程序和設(shè)備管理器處于兩個(gè)進(jìn)程空間,這就造成設(shè)備管理器無(wú)法訪問(wèn)應(yīng)用程序傳遞的指針(虛擬地址),所以當(dāng)我們?cè)趹?yīng)用程序中傳遞指針給流驅(qū)動(dòng)程序接口函數(shù)時(shí),WINCE內(nèi)核從中作了一個(gè)地址映射,例如ReadFile、WriteFile、DeviceIoControl函數(shù)的參數(shù)凡是指針都經(jīng)過(guò)了映射才傳遞給驅(qū)動(dòng)程序,所以很多驅(qū)動(dòng)程序開(kāi)發(fā)者并不了解其中的奧秘就可以編程了。但是如果參數(shù)是一個(gè)指向一個(gè)結(jié)構(gòu)體的指針,而結(jié)構(gòu)體里包括一個(gè)或多個(gè)指針,那么WINCE內(nèi)核并不負(fù)責(zé)映射,所以就需要開(kāi)發(fā)者在驅(qū)動(dòng)程序接口函數(shù)中調(diào)用API函數(shù)MapPtrToProcess來(lái)映射地址。例如:pPointer_retval = MapPtrToProcess(pPointer, GetCallerProcess());
如何判斷可插拔的設(shè)備是否存在?
1、通過(guò)查找注冊(cè)表的值。凡是由API ActivateDeviceEx加載的驅(qū)動(dòng)程序都在[HKEY_LOCAL_MACHINE\Drivers\Active]鍵下有注冊(cè)鍵,通過(guò)查找“name”或者其它鍵值就能夠找到。設(shè)備管理器就調(diào)用這個(gè)API。如果是PCI設(shè)備,在注冊(cè)表[HLM\Drivers\BuiltIn\PCI\Instance]下查找關(guān)鍵字,例如[HLM\ Drivers\BuiltIn\PCI\Instance\WaveDev1],說(shuō)明音頻驅(qū)動(dòng)已經(jīng)加載。
2、調(diào)用驅(qū)動(dòng)程序接口函數(shù),根據(jù)返回值或者執(zhí)行結(jié)果來(lái)判斷。
如何做到通過(guò)串口過(guò)來(lái)的一個(gè)信號(hào)啟動(dòng)自己開(kāi)發(fā)的應(yīng)用程序?
創(chuàng)建一個(gè)線程負(fù)責(zé)等待串口過(guò)來(lái)的信號(hào),調(diào)用API SetCommMask設(shè)置要等待的信號(hào)種類(lèi),具體可以等待的信號(hào)種類(lèi)參見(jiàn)參數(shù)2的說(shuō)明。然后再調(diào)用 API WaitCommEvent函數(shù)等待這個(gè)信號(hào),接收之后再調(diào)用API CreateProcess啟動(dòng)應(yīng)用程序。
在WINCE中如何只能啟動(dòng)應(yīng)用程序的一個(gè)實(shí)例?
常用的兩種辦法:
1、如果應(yīng)用程序?qū)嵗齽?chuàng)建了窗口,可通過(guò)API FindWindow函數(shù)通過(guò)窗口類(lèi)名和窗口標(biāo)題名稱(chēng)來(lái)查找,前提是系統(tǒng)內(nèi)不會(huì)出現(xiàn)窗口名稱(chēng)重復(fù)的情況。
2、應(yīng)用程序初始化的時(shí)候創(chuàng)建一個(gè)事件或互斥等內(nèi)核對(duì)象,因?yàn)閮?nèi)核對(duì)象是由內(nèi)核創(chuàng)建,名稱(chēng)在系統(tǒng)內(nèi)唯一。
能不能自己編輯一個(gè)數(shù)字簽名文件導(dǎo)入到手機(jī)上,這樣就可以用這個(gè)簽名簽自己的程序了?
WINCE的內(nèi)核簽名機(jī)制的用途是限制非法的可執(zhí)行模塊EXE、DLL等在設(shè)備上運(yùn)行。要求內(nèi)核的加載模塊用公鑰驗(yàn)證請(qǐng)求加載的EXE、DLL的簽名是否合法,而這個(gè)公鑰是在定制內(nèi)核的時(shí)候加進(jìn)去的,所以除內(nèi)核的定制者以外的人無(wú)法修改這個(gè)驗(yàn)證機(jī)制。
我按照版主的文章《加密WINCE系統(tǒng)》里操作,提示錯(cuò)誤如下:
Error 80090016 during CryptSignHash 1!
Error signing hash
這是因?yàn)閭鬟f了無(wú)效的鑰容器名稱(chēng),使CryptoAPI調(diào)用失敗。應(yīng)該在使用signfile工具之前創(chuàng)建一個(gè)鑰容器,在桌面Windows中調(diào)用 API CryptAcquireContext創(chuàng)建一個(gè)指定名稱(chēng)的鑰容器,接著再創(chuàng)建一個(gè)簽名密鑰對(duì),這時(shí)再使用signfile工具就可以了。我在文章里寫(xiě)成-kfulinlin是因?yàn)槲覄?chuàng)建鑰容器的時(shí)候沒(méi)有指定名稱(chēng),系統(tǒng)就采用當(dāng)前登錄的用戶名為容器名。
編譯錯(cuò)誤:CVTRES : fatal error CVT1102: out of memory; 42 bytes required ?
多數(shù)情況下出現(xiàn)這種錯(cuò)誤是因EVC的bug而起,應(yīng)該在安裝EVC之后就立刻安裝EVC的SP補(bǔ)丁。另外為了避開(kāi)BUG,使用EVC編程應(yīng)該養(yǎng)成一些習(xí)慣,比如定期備份工程所有文件,每次編譯時(shí)采用Clean + Rebuild All,正調(diào)試時(shí)不要關(guān)閉模擬器等等。
在WINCE下是否能夠得到某一進(jìn)程使用的物理內(nèi)存總量?
目前沒(méi)發(fā)現(xiàn)有這樣一個(gè)API能夠得到指定進(jìn)程使用的物理內(nèi)存總量。只有GlobalMemoryStatus能夠得到整個(gè)系統(tǒng)使用的物理內(nèi)存總量。
應(yīng)用程序如何控制lcd的亮度?如何獲得電池的電量?
從常見(jiàn)的平臺(tái)如Geode、三星ARM系列來(lái)看,的確在驅(qū)動(dòng)方面沒(méi)有統(tǒng)一的控制LCD或者其它種類(lèi)屏幕亮度的接口函數(shù),所以只能根據(jù)具體平臺(tái)提供的接口來(lái)做。從幫助文檔來(lái)看微軟的帶有DirectDraw功能的顯示驅(qū)動(dòng)程序的確有標(biāo)準(zhǔn)的增加亮度的接口函數(shù),關(guān)于背景光參見(jiàn)標(biāo)題為 “Enabling a Backlight”的幫助文檔。
獲得電池電量有標(biāo)準(zhǔn)的接口函數(shù)GetSystemPowerStatusEx,前提是驅(qū)動(dòng)程序和硬件都要支持。
WINCE的socket函數(shù)好像不支持發(fā)送/接收超時(shí)?
是的,最早版本的WINCE支持選項(xiàng)SO_RCVTIMEO、SO_SNDTIMEO,后來(lái)卻不支持了。
WINCE下如何設(shè)置窗口最大化和最小化?
WINCE 的幫助文檔在介紹API ShowWindow函數(shù)的參數(shù)時(shí)指出SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOWDEFAULT, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE都不被支持,但實(shí)際上并不完全是這樣,具體來(lái)說(shuō):
SW_MAXIMIZE 比原來(lái)窗口大,但不是最大化
SW_MINIMIZE 編譯成功,但是不起作用
SW_SHOWMAXIMIZED 最大化
SW_SHOWMINIMIZED 編譯出錯(cuò)
SW_RESTORE 能恢復(fù)
SW_SHOWDEFAULT 編譯出錯(cuò)
SW_SHOWMINNOACTIVE 編譯出錯(cuò)
SW_HIDE 能夠隱藏
如何用程序調(diào)用控制面板的觸摸屏校對(duì)程序?
兩種辦法:
1、調(diào)用API TouchCalibrate函數(shù)
2、調(diào)用CreateProcess,參數(shù)1為L"\\windows\\ctlpnl.exe",參數(shù)2為L"cplmain.cpl,9"。
如何獲得U盤(pán)或者其它類(lèi)型的存儲(chǔ)器總?cè)萘亢褪S嗫捎萌萘浚?/span>
調(diào)用API GetStoreInfo得到扇區(qū)數(shù)、每扇區(qū)字節(jié)數(shù),相乘即是總?cè)萘俊U{(diào)用API GetDiskFreeSpaceEx得到剩余可用容量。
三星2440頭文件定義#define IIC_BASE 0xB1400000 // 54000000,datasheet是54000000,那么怎么轉(zhuǎn)成0xB1400000?
物理地址映射方法分為兩種,一種靜態(tài)映射另一種為動(dòng)態(tài)映射。在OEMAddressTable中定義了物理地址與虛擬地址的映射關(guān)系屬于靜態(tài)映射,用 VirtualCopy映射屬于動(dòng)態(tài)映射,采用哪種辦法都可以。問(wèn)題中提到的屬于靜態(tài)映射,2440的BSP在map.a文件中定義了IIC控制寄存器的物理起始地址和對(duì)應(yīng)的虛擬地址如下:
DCD 0x91400000, 0x54000000, 1 ;
在OEMAddressTable 中定義的虛擬地址范圍在0x8000 0000—0x9FFF FFFF,這部分可緩存,適合內(nèi)核程序和應(yīng)用程序使用,同時(shí)WINCE內(nèi)核在 0xA000 0000—0xBFFF FFFF中映射了另一份,指向了同樣的物理地址,這部分不可緩存,適合驅(qū)動(dòng)程序使用。三星ARM處理器帶有L1級(jí)高速緩存,可緩存會(huì)提高執(zhí)行效率。對(duì)于特殊的設(shè)備寄存器適合映射到不可緩存的虛擬地址。
當(dāng)驅(qū)動(dòng)程序調(diào)用VirtualCopy對(duì)0xB1400000地址讀寫(xiě)時(shí),WINCE自動(dòng)將這個(gè)地址減去0x2000 0000,也就是0x91400000,對(duì)應(yīng)的物理地址就是0x54000000,也就是IIC控制寄存器的物理起始地址。
基于RAM的注冊(cè)表如何保存數(shù)據(jù)?
調(diào)用API RegCopyFile備份注冊(cè)表。調(diào)用API RegRestoreFile恢復(fù)注冊(cè)表,然后調(diào)用KernelIoControl熱啟動(dòng)使恢復(fù)生效。
如何隱藏和顯示winCE下標(biāo)準(zhǔn)外殼的任務(wù)欄?
HANDLE hTaskBar = FindWindow(L"HHTaskBar", NULL);
ShowWindow(hTaskBar, SW_HIDE);
ShowWindow(hTaskBar, SW_SHOWNORMAL);
如果能讓WINCE的IE瀏覽器播放flash動(dòng)畫(huà)?
播放flash需要Macromedia Flash Player SDK,參見(jiàn)http://www.adobe.com/products/flashplayer_sdk/。這和real player相似,都需要WINCE平臺(tái)的SDK,都需要申請(qǐng)。
WINCE下內(nèi)核模式和用戶模式有什么區(qū)別?
為了使讀者能夠詳細(xì)了解WINCE的地址映射原理還有兩種模式,在這里我分幾個(gè)部分說(shuō)明:
1、 WINCE內(nèi)核nk.exe的任務(wù)是管理操作系統(tǒng)核心功能。按照OEMAddressTable的映射要求,所有物理地址都映射到0x80000000以上,所以對(duì)于內(nèi)核程序nk.exe和內(nèi)核模式下的線程來(lái)說(shuō),只要訪問(wèn)0x80000000以上的有效虛擬地址經(jīng)MMU就能夠訪問(wèn)物理地址,無(wú)需再映射是內(nèi)核模式的一個(gè)特點(diǎn)。內(nèi)核模式的第二個(gè)特點(diǎn)是沒(méi)有地址訪問(wèn)限制,內(nèi)核模式線程可以訪問(wèn)任何有效虛擬地址,所謂有效虛擬地址是指有實(shí)際事物對(duì)應(yīng)。
2、用戶模式線程只能訪問(wèn)0x80000000以下的虛擬地址空間,WINCE6.0之前版本的內(nèi)核為每個(gè)進(jìn)程劃分32MB的地址空間,在不調(diào)用特殊函數(shù)的情況下不能相互訪問(wèn),這樣的設(shè)計(jì)使得WINCE系統(tǒng)更安全、更穩(wěn)定,限制訪問(wèn)地址是用戶模式的第一個(gè)特點(diǎn)。第二個(gè)特點(diǎn)就是需要多一層映射,如果線程要訪問(wèn)物理內(nèi)存的話需要先映射到0x80000000以上,再經(jīng)MMU訪問(wèn)物理內(nèi)存地址。
WINCE的線程具有轉(zhuǎn)移性(參考 API GetCallerProcess的說(shuō)明,有一個(gè)很好的例子),當(dāng)應(yīng)用程序的線程調(diào)用API或者調(diào)用驅(qū)動(dòng)程序接口函數(shù)時(shí),該線程會(huì)轉(zhuǎn)移到 gwes.exe、device.exe、filesys.exe等進(jìn)程中執(zhí)行,轉(zhuǎn)移是由WINCE內(nèi)核操作的,它會(huì)修改線程的上下文,記錄線程的當(dāng)前進(jìn)程、調(diào)用者進(jìn)程、擁有者進(jìn)程三個(gè)值。
3、如果在定制內(nèi)核的時(shí)候選擇了“Full Kernel Mode”,那么在這個(gè)內(nèi)核上運(yùn)行的所有線程都處于內(nèi)核模式,即使調(diào)用SetKMode(FALSE)后線程仍然具有內(nèi)核模式的特點(diǎn),能夠訪問(wèn)任何有效的虛擬地址。假設(shè)現(xiàn)有一個(gè)64MB RAM的 WINCE產(chǎn)品,RAM映射從0x80000000到0x84000000,如果線程處于內(nèi)核模式,它就直接可以訪問(wèn)這個(gè)范圍的虛擬地址:
在OnButton1()中編寫(xiě)
DWORD oldMode = SetKMode(FALSE);
volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)
*piTemp = 12345;
在OnButton2()中編寫(xiě)
DWORD oldMode = SetKMode(FALSE);
volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)
int iTemp = *piTemp;
先只執(zhí)行OnButton1()然后關(guān)閉程序,再重啟程序然后執(zhí)行OnButton2(),iTemp仍然等于12345。結(jié)果說(shuō)明了兩點(diǎn):內(nèi)核模式線程可以直接訪問(wèn)0x80000000以上的有效虛擬地址;我們寫(xiě)到RAM中的數(shù)據(jù)沒(méi)有丟失,說(shuō)明虛擬地址有效。
如果在定制內(nèi)核的時(shí)候沒(méi)有選擇“Full Kernel Mode”,那么在這個(gè)內(nèi)核上運(yùn)行的所有線程都處于用戶模式。可以調(diào)用SetKMode(TRUE)使調(diào)用線程暫時(shí)處于內(nèi)核模式,還是原來(lái)的假設(shè)環(huán)境,我再舉個(gè)例子:
在OnButton1()中編寫(xiě)
DWORD oldMode = SetKMode(TRUE);
volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)
*piTemp = 12345;
在用戶模式下,如果不調(diào)用SetKMode(TRUE),那么執(zhí)行*piTemp = 12345一定會(huì)彈出對(duì)話框,提示地址訪問(wèn)非法,如果調(diào)用SetKMode(TRUE)就不會(huì)提示地址訪問(wèn)非法,而且在OnButton2()中仍然能得到12345這個(gè)值。
通過(guò)這兩個(gè)例子我相信讀者能夠完全了解兩種模式的區(qū)別了。
4、 WINCE提供了兩個(gè)函數(shù)SetKMode和SetProcPermissions,其中SetKMode能夠把調(diào)用線程切換到內(nèi)核模式,還可以切換回用戶模式。SetProcPermissions + GetCurrentPermissions添加當(dāng)前進(jìn)程訪問(wèn)權(quán)限給調(diào)用線程, SetProcPermissions (0xFFFFFFFF)能讓調(diào)用線程訪問(wèn)所有進(jìn)程空間,但是調(diào)用線程仍然處于用戶模式。SetKMode和 SetProcPermissions函數(shù)使得用戶模式的特點(diǎn)不那么明晰。
如上所說(shuō)一個(gè)應(yīng)用程序的線程可能轉(zhuǎn)移到其它兩個(gè)進(jìn)程地址空間中讀寫(xiě)數(shù)據(jù),而每一個(gè)線程在被創(chuàng)建的時(shí)候只有訪問(wèn)創(chuàng)建它的進(jìn)程地址空間的權(quán)限,所以驅(qū)動(dòng)程序開(kāi)發(fā)者必須在驅(qū)動(dòng)程序讀寫(xiě)數(shù)據(jù)前調(diào)用SetKMode或者 SetProcPermissions增加調(diào)用此函數(shù)的線程訪問(wèn)其它進(jìn)程空間的權(quán)限。如果一個(gè)應(yīng)用程序的線程只轉(zhuǎn)移到一個(gè)進(jìn)程地址空間,一般為設(shè)備管理器進(jìn)程device.exe,這種情況下不必增加線程訪問(wèn)其它進(jìn)程空間的權(quán)限,但如果驅(qū)動(dòng)程序本身創(chuàng)建了一個(gè)線程,那還是要調(diào)用SetKMode或者 SetProcPermissions增加新的線程訪問(wèn)其它進(jìn)程的權(quán)限的,因?yàn)轵?qū)動(dòng)程序創(chuàng)建線程時(shí),當(dāng)前進(jìn)程為設(shè)備管理器,所以新線程只具有訪問(wèn)設(shè)備管理器進(jìn)程空間的權(quán)限,而不具備訪問(wèn)應(yīng)用程序進(jìn)程空間的權(quán)限。
5、可能一個(gè)編寫(xiě)過(guò)簡(jiǎn)單的流驅(qū)動(dòng)的初學(xué)者會(huì)很疑惑,因?yàn)殚_(kāi)發(fā)一個(gè)簡(jiǎn)單的流驅(qū)動(dòng)程序根本不需要調(diào)用這些函數(shù),也沒(méi)有調(diào)用過(guò)MapPtrToProcess,那是因?yàn)槿绻麡?biāo)準(zhǔn)流驅(qū)動(dòng)接口函數(shù)的參數(shù)為指針(ReadFile、 WriteFile、DeviceIoControl參數(shù)都有指針),WINCE內(nèi)核會(huì)自動(dòng)映射指針包含的地址,但僅此而已,其余任何情況都要求開(kāi)發(fā)者自行處理,比如流接口函數(shù)的參數(shù)是一個(gè)指向結(jié)構(gòu)體的指針PA,而結(jié)構(gòu)體中包括指針PB,PB指針就必須在流接口函數(shù)中映射,映射后才能訪問(wèn),否則就會(huì)造成地址訪問(wèn)非法。所以結(jié)構(gòu)體中每個(gè)指針都要映射。
為了讓讀者能了解其中的原因,我舉個(gè)例子:
假設(shè)設(shè)備管理器被加載到Slot4,應(yīng)用程序A被加載到Slot 8,A只有一個(gè)主線程T,T開(kāi)始執(zhí)行,按照WINCE的規(guī)定,正獲得CPU的進(jìn)程必須映射到Slot0,那么在執(zhí)行代碼的時(shí)候 A的所有虛擬地址都被減去一個(gè)偏移值,也就是8×0x02000000,A調(diào)用DeviceIoControl,傳遞一個(gè)指向一個(gè)結(jié)構(gòu)體的指針B,而這個(gè)結(jié)構(gòu)體中包含一個(gè)指針C,指針C包含的地址假設(shè)為0x00030000,當(dāng)執(zhí)行DeviceIoControl時(shí)WINCE把設(shè)備管理器的進(jìn)程地址空間映射到Slot0,因?yàn)榉旁谧?cè)表[HKLM\Drivers\BuiltIn]下的驅(qū)動(dòng)程序是由設(shè)備管理器加載的,自然驅(qū)動(dòng)程序的代碼段被加載到設(shè)備管理器進(jìn)程空間,但是線程仍然是T,此時(shí)T的當(dāng)前所在進(jìn)程為設(shè)備管理器(CurrentProcess),A變成了T的調(diào)用者進(jìn)程(CallerProcess),T自動(dòng)具有了訪問(wèn)調(diào)用者進(jìn)程空間的權(quán)限。這時(shí)訪問(wèn)Slot0中的虛擬地址其實(shí)質(zhì)就是訪問(wèn)設(shè)備管理器的進(jìn)程地址空間,要把地址加上一個(gè)偏移值,也就是4×0x02000000,所以DeviceIoControl訪問(wèn)指針C包含的地址時(shí)本應(yīng)該加上8×0x02000000,卻加上4×0x02000000,結(jié)果地址并不是設(shè)備管理器的合法區(qū)域,系統(tǒng)就會(huì)提示地址訪問(wèn)非法。而如果做了一個(gè)映射,指針C包含的地址就會(huì)被加一個(gè)正確的偏移值,使地址處于A的地址空間Slot 8中,T此時(shí)具有訪問(wèn)A進(jìn)程空間的權(quán)限,訪問(wèn)到正確的虛擬地址當(dāng)然會(huì)得到正確的數(shù)據(jù)了。
為什么WINCE目錄下的例子用build+sysgen能夠編譯成EXE文件,而我添加的例子就不能編譯呢?
如果這個(gè)例子是一個(gè)應(yīng)用程序,那么肯定包括代碼文件(.h .c .cpp)和資源文件(.rc和其它資源文件),build工具根據(jù)source文件內(nèi)容把代碼文件編譯成lib文件,資源文件編譯成.res文件,sysgen工具根據(jù)makefile文件內(nèi)容將source文件中列出的需要鏈接的各個(gè)庫(kù)文件合并成一個(gè)EXE文件。所以說(shuō)關(guān)鍵在于makefile文件,WINCE目錄下凡是能夠用build+sysgen編譯的都在makefile中有如何鏈接的設(shè)置,而我們添加的例子當(dāng)然沒(méi)有在makefile中找到如何鏈接的設(shè)置,nmake工具就會(huì)提示不知道如何創(chuàng)建。
pcienum.exe干什么用的?
如果你要開(kāi)發(fā)某一個(gè)PCI設(shè)備的驅(qū)動(dòng)程序,首先要知道這個(gè)PCI設(shè)備的信息(如VendorID、DeviceID、BaseClass、 SubClass)和PCI總線的信息。運(yùn)行這個(gè)pcienum.exe就能得到相關(guān)信息。pcienum.exe提供了源碼,位置\Public\ Common\Oak\Drivers\Ceddk\Test\Pcienum。
wince下如何讓操作系統(tǒng)進(jìn)入待機(jī)模式?又如何把它激活?
通過(guò)注冊(cè)表就可以設(shè)置,前提是你的驅(qū)動(dòng)和硬件都支持。注冊(cè)表項(xiàng)參見(jiàn)標(biāo)題為“GWES Suspend Time-outs”的幫助文檔。
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Power]
"BattPowerOff"=dword:300
"ExtPowerOff"=dword:0
"WakeupPowerOff"=dword:60
"ScreenPowerOff"=dword:0
現(xiàn)有一個(gè)GPRS模塊,如何通過(guò)GPRS連接到Internet?
1、先在內(nèi)核中加入WAN下面的幾個(gè)組件,如RAS/PPP、TAPI。WINCE采用unimodem驅(qū)動(dòng),所以不必?fù)?dān)心沒(méi)有Modem驅(qū)動(dòng)的支持。
2、WINCE啟動(dòng)后新建一個(gè)撥號(hào)連接,比如名稱(chēng)叫“gprs1”,輸入用戶名、密碼、電話號(hào)碼。電話號(hào)碼不同,所采用的模式不一樣,例如“*99#”是GPRS模式,“17201”是普通的數(shù)據(jù)模式,速度差很多,價(jià)錢(qián)也差很多。
3、開(kāi)始連接,連接過(guò)程會(huì)在對(duì)話框中顯示,直到顯示“連接成功”。
4、打開(kāi)瀏覽器或者自己開(kāi)發(fā)的通訊軟件測(cè)試網(wǎng)絡(luò)連接情況。
5、關(guān)閉連接。
6、保存[HKEY_CURRENT_USER\Comm\RasBook\gprs1]下的所有數(shù)據(jù),添加到project.reg中,重新編譯后內(nèi)核中就有了一個(gè)撥號(hào)連接“gprs1”。
7、調(diào)用RAS函數(shù)可以修改撥號(hào)連接“gprs1”的參數(shù),如用戶名、密碼、電話號(hào)碼,但是不能修改硬件設(shè)置,如波特率、串口、數(shù)據(jù)位、停止位等。RAS函數(shù)還能夠撥號(hào)、掛斷。為了修改波特率可以多保存幾個(gè)撥號(hào)連接,也可以直接調(diào)用TAPI開(kāi)發(fā)撥號(hào)軟件,另外WINCE自帶的撥號(hào)連接是有源碼的,位置在\ PUBLIC\COMMON\OAK\DRIVERS\NETSAMP\CONNMC。
采用基于HIVE的注冊(cè)表如何刪除用戶保存在注冊(cè)表中的數(shù)據(jù),恢復(fù)到出廠時(shí)的注冊(cè)表?
用戶修改的數(shù)據(jù)保存在user.hv文件中,直接刪除一定失敗,所以不能通過(guò)刪除文件實(shí)現(xiàn)恢復(fù)出廠設(shè)置。微軟考慮到了這個(gè)問(wèn)題,在WINCE啟動(dòng)過(guò)程中 filesys.exe加載注冊(cè)表時(shí)會(huì)調(diào)用OEMIoControl函數(shù)并傳遞一個(gè)IOCTL,這個(gè)IOCTL在pkfuncs.h中定義如下:
#define IOCTL_HAL_GET_HIVE_CLEAN_FLAG CTL_CODE(FILE_DEVICE_HAL, 49, METHOD_BUFFERED, FILE_ANY_ACCESS)
filesys.exe 會(huì)分別傳遞參數(shù)HIVECLEANFLAG_SYSTEM和HIVECLEANFLAG_USERS,如果返回值為TRUE那么filesys.exe清除原來(lái)的注冊(cè)表文件,如果返回值為FALSE那么filesys.exe保留原來(lái)的注冊(cè)表文件。默認(rèn)WINCE并沒(méi)有實(shí)現(xiàn)這個(gè)IOCTL,所以OEM要?jiǎng)h除注冊(cè)表文件就必須先編寫(xiě)這個(gè)IOCTL代碼。代碼的例子可參考標(biāo)題為“IOCTL_HAL_GET_HIVE_CLEAN_FLAG”的幫助文檔。另外必須在ioctl.h和ioctl.c兩個(gè)文件中編寫(xiě)該代碼。在ioctl.c文件中找到 const OAL_IOCTL_HANDLER g_oalIoCtlTable[],添加IOCTL和對(duì)應(yīng)的處理函數(shù)。要進(jìn)一步了解這個(gè)全局?jǐn)?shù)組,參見(jiàn)標(biāo)題為“IOCTL Library”的幫助文檔。
如何在不刪除必要組件的前提下減小內(nèi)核文件長(zhǎng)度?
要減小內(nèi)核文件長(zhǎng)度首先要在使用PB的定制內(nèi)核向?qū)е羞x擇自定義,也就是說(shuō)對(duì)于每個(gè)組件都由自己來(lái)選擇,而不是選擇PB的標(biāo)準(zhǔn)配置。但減小內(nèi)核文件長(zhǎng)度最有效最直接的辦法是縮小字體,尤其對(duì)于東亞字體,采用字體壓縮技術(shù)并且選擇合理的字庫(kù)文件將明顯縮小文件長(zhǎng)度。
1、在定制內(nèi)核時(shí)選擇AGFA AC3 Font Compression組件。SYSGEN變量為SYSGEN_AGFA_FONT。
2、參考標(biāo)題為“East Asian Font Versions”的幫助文檔,從中選擇你需要的字庫(kù)文件加到內(nèi)核中,從文檔可以看出加AC3壓縮比不加壓縮在文件長(zhǎng)度方面差距很大。
如何得到WAV文件播放的總時(shí)間?
1、直接讀取wav文件頭信息,從文件起始地址偏移28個(gè)字節(jié)長(zhǎng)度為4個(gè)字節(jié)保存的是每秒鐘播放的字節(jié)數(shù),從文件起始地址偏移40個(gè)字節(jié)長(zhǎng)度為4個(gè)字節(jié)保存的是聲音數(shù)據(jù)的總的字節(jié)數(shù),相除就是播放時(shí)間。
2、調(diào)用IGraphBuilder::RenderFile打開(kāi)一個(gè)wav文件,然后通過(guò)IGraphBuilder得到IMediaSeeking指針,再調(diào)用IMediaSeeking::GetDuration得到總的時(shí)間(結(jié)果要除以10000000),IMediaSeeking:: GetCurrentPosition得到當(dāng)前播放時(shí)間。
如何在Dialog-Based程序中加入menubar?
先調(diào)用CommandBar_Create再調(diào)用CommandBar_InsertMenubar。
請(qǐng)問(wèn)MultiByteToWideChar與_T、L、TEXT的區(qū)別?
MultiByteToWideChar函數(shù)轉(zhuǎn)換的對(duì)象可以是常量也可以是變量。其它只能轉(zhuǎn)換常量。_T和TEXT會(huì)根據(jù)當(dāng)前系統(tǒng)是否定義_UNICODE宏來(lái)決定是否轉(zhuǎn)換,而L就是轉(zhuǎn)換成寬字符,當(dāng)然也包括其他類(lèi)型常量的轉(zhuǎn)換。
在用UBS線纜通過(guò)ActiveSync同步有效的情況下,如何插上USB線纜后WINCE自動(dòng)與PC同步?
1、新建一個(gè)撥號(hào)連接,假設(shè)名稱(chēng)為“usb1”,選擇連接類(lèi)型為“直接連接”,并在連接設(shè)備里選擇通過(guò)USB線纜連接。
2、將注冊(cè)表[HKEY_CURRENT_USER\Comm\RasBook\usb1]下的數(shù)據(jù)添加到project.reg或者platform.reg中。
3、在[HKEY_CURRENT_USER\ControlPanel\Comm]下添加如下:
"AutoCnct"=dword:1 ///直接連接
"Cnct"="usb1" ///連接名稱(chēng)
4、重新編譯內(nèi)核。為了節(jié)省編譯時(shí)間也可以在內(nèi)核工程下搜索*.reg文件,將2、3步驟中的注冊(cè)表數(shù)據(jù)添加其中,然后直接make image。
如何通過(guò)進(jìn)程句柄來(lái)獲得該進(jìn)程的主窗口句柄?
好像沒(méi)有API能夠通過(guò)進(jìn)程句柄直接獲得主窗口的句柄,因?yàn)椴⒎敲總€(gè)應(yīng)用程序都帶UI。但是可以反過(guò)來(lái),先枚舉當(dāng)前系統(tǒng)所有主窗口,然后根據(jù)每個(gè)窗口的句柄調(diào)用GetWindowThreadProcessId函數(shù)得到進(jìn)程的ID,再調(diào)用OpenProcess得到進(jìn)程句柄,與現(xiàn)有的進(jìn)程句柄比較。
我做的顯示驅(qū)動(dòng)DLL已經(jīng)編譯成功了,但是在加載顯示驅(qū)動(dòng)的過(guò)程中彈出話框,提示如下:
unhandled exception in gwes.exe (0xc0000005 access violation)
提示的錯(cuò)誤——地址訪問(wèn)非法,表明你的驅(qū)動(dòng)程序代碼并沒(méi)有在讀寫(xiě)數(shù)據(jù)前添加SetKMode(TRUE)或者SetProcPermissions (0xFFFFFFFF)函數(shù)讓線程能夠訪問(wèn)任何進(jìn)程的地址空間。你可以調(diào)用 IsBadReadPtr和IsBadWritePtr函數(shù)檢測(cè)地址是否能夠合法訪問(wèn)。編寫(xiě)和gwes有關(guān)的驅(qū)動(dòng)程序應(yīng)該首先調(diào)用SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF) 函數(shù),這是一個(gè)好習(xí)慣。
請(qǐng)問(wèn)在嵌入式系統(tǒng)中如何設(shè)置GPRS拔號(hào)用的APN?
對(duì)一個(gè)撥號(hào)連接比如“我的連接”單擊鼠標(biāo)右鍵,在彈出的菜單中選擇“屬性”,然后單擊“配置”—“撥號(hào)選項(xiàng)”,在“附加設(shè)置”中添加AT命令如“+cgdcont=1,"ip","cmnet"”。“cmnet”位置即為APN。
WINCE的IP Phone功能如何?
WINCE的voip需要c-s-c結(jié)構(gòu),既需要服務(wù)器的中轉(zhuǎn),而skype采用第三代p2p技術(shù)就不需要中轉(zhuǎn),但是在gprs下也做不到語(yǔ)音流暢。skype有pocket pc版本,但是無(wú)線方面需要wlan或者cdma。
三星ARM平臺(tái)如何定義自己的中斷ID?
以S3C2410 為例,在oalintr.h文件中定義中斷ID,也稱(chēng)SYSINTR,例如 #define SYSINTR_MYINT (SYSINTR_FIRMWARE+20),最大值不能超過(guò)SYSINTR_FIRMWARE+23。然后在armint.c文件中找到 OEMInterruptHandler函數(shù),用if (IntPendVal == INTSRC_XXX) 判斷當(dāng)前發(fā)生的中斷源號(hào),然后返回 SYSINTR_MYINT。內(nèi)核分別調(diào)用OEMInterruptDisable(禁止當(dāng)前中斷)、OEMInterruptDone(中斷處理結(jié)束)、OEMInterruptEnable(當(dāng)前中斷有效)三個(gè)函數(shù),參數(shù)都為中斷ID,在這三個(gè)函數(shù)中用 case SYSINTR_MYINT判斷當(dāng)前要處理的中斷。
如何開(kāi)發(fā)軟件從PC端復(fù)制文件到基于WINCE的設(shè)備?
調(diào)用RAPI (Remote Application Programming Interface)函數(shù),此函數(shù)集由桌面計(jì)算機(jī)調(diào)用,由基于WINCE的設(shè)備執(zhí)行。一旦連接上就可以在桌面計(jì)算機(jī)端調(diào)用RAPI。通過(guò)注冊(cè)表還可以限制RAPI能夠訪問(wèn)目錄的范圍。具體參考RAPI和RDP(遠(yuǎn)程桌面協(xié)議)。
請(qǐng)問(wèn)如何對(duì)NandFlash分區(qū)、格式化?
你看看WINCE420\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BOOTPART\bootpart.cpp,在Eboot中先要調(diào)用BP_LowLevelFormat(
DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)再flash的一個(gè)區(qū)域建立空的MBR,然后連續(xù)兩次調(diào)用 BP_OpenPartition(DWORD dwStartSector, DWORD dwNumSectors, DWORD dwPartType, BOOL fActive, DWORD dwCreationFlags)函數(shù)來(lái)建立BINFS和FAT分區(qū)。建好后,將nk.bin燒入binfs 分區(qū)中。
要做個(gè)彈出對(duì)話框具有 always on top 屬性,如何實(shí)現(xiàn)?
調(diào)用SetWindowPos(.. , HWND_TOPMOST, ...., SWP_NOACTIVATE)。
s3c2410+WINCE下網(wǎng)絡(luò)PING一會(huì)就斷,如何解決?
原因在于中斷處理程序把已經(jīng)產(chǎn)生的中斷標(biāo)志清除掉了,這樣就丟失一次中斷。因?yàn)樵?qū)動(dòng)里配置中斷為上升沿觸發(fā),一次中斷丟失就導(dǎo)致不會(huì)再產(chǎn)生中斷信號(hào)跳變,因?yàn)橹挥性谥袛喾?wù)中讀取了cs8900的 Interrupt status queue寄存器后,才會(huì)產(chǎn)生下一次中斷!解決辦法:
1、在cfw.c文件中全局定義BOOL Inited = FALSE
2、修改OEMInterruptEnable()中case SYSINTR_ETHER: 下面的語(yǔ)句為:
if(Inited == FALSE)
{
s2410IOP->rEINTPEND = 0x200;
s2410INT->rSRCPND = BIT_EINT8_23;
if (s2410INT->rINTPND & BIT_EINT8_23)
s2410INT->rINTPND = BIT_EINT8_23;
Inited = TRUE;
}
s2410IOP->rEINTMASK &= ~0x200;
s2410INT->rINTMSK &= ~BIT_EINT8_23;
break;
注:本解決辦法轉(zhuǎn)載于http://stoned.blogchina.com/stoned/3083045.html,非我本人研究成果。
已經(jīng)搜索到文件,如何用CListBox以圖標(biāo)形式顯示出來(lái)?
CListCtrl ListCtrl;
CImageList ImageList;
ImageList.Create(IDB_BITMAP, 48, 2, RGB(0,0,0));
ListCtrl.SetImageList(&ImageList, LVSIL_NORMAL);
ListCtrl.InsertItem(iListIndex, strItem, 1);
如何改變控制面板中電源屬性對(duì)話框的尺寸?
1、需要修改對(duì)話框的尺寸是因?yàn)閷?duì)話框是以資源方式加載的,不會(huì)根據(jù)當(dāng)前系統(tǒng)顯示分辨率而自我調(diào)節(jié)尺寸。
2、安裝WINCE后有一些組件(feature)的資源文件*.res就已經(jīng)有了,如果你不改變,那么build內(nèi)核的時(shí)候PB只是把這些.res復(fù)制到工程目錄下,然后與*.obj合并成EXE、DLL、CPL。所以修改了.rc文件里面的對(duì)話框尺寸后要重新編譯.rc文件為.res文件,然后再覆蓋原來(lái) WINCE自帶的.res文件。
3、改變對(duì)話框尺寸有兩種辦法:一種方法是更改系統(tǒng)字體字號(hào),系統(tǒng)字體的字號(hào)變化會(huì)影響對(duì)話框的尺寸,但是缺點(diǎn)是所有系統(tǒng)字體有關(guān)的UI都會(huì)改變。另一種是在.rc文件中調(diào)整對(duì)話框尺寸,然后編譯成.res文件,再將.res復(fù)制到對(duì)應(yīng)的語(yǔ)言目錄里,比如目錄名為0804(中文),再執(zhí)行Rebuild命令重新編譯內(nèi)核,或者執(zhí)行sysgen+build。在研究中我發(fā)現(xiàn).res文件雖然能夠直接用EVC打開(kāi)、修改、保存,但是和其它Obj鏈接成EXE、DLL、CPL后并不能運(yùn)行,所以還是建議讀者用CE自帶的rc工具編譯最好。讀者可在PB的命令行中鍵入“rc /?”了解rc.exe工具的用途和參數(shù)。
使用EVC build之后連接模擬器的時(shí)候,提示download file等了一會(huì)又出現(xiàn)download failed?
一般這樣的問(wèn)題從下面幾個(gè)步驟解決:
1、如果之前能啟動(dòng)模擬器而現(xiàn)在不能,那么先clean然后重啟計(jì)算機(jī)再build。
2、如果開(kāi)發(fā)的主機(jī)為WINXP+SP2,可能存在與EVC模擬器不兼容的情況,檢查C:\boot.ini,將/noexecute=optin改為/execute=optin。
3、檢查你的模擬器是否能運(yùn)行,假設(shè)你正用的SDK名稱(chēng)為MYSDK,單擊菜單tools—configure platform manager,選擇 MYSDK—MYSDK emulator,再單擊properties—test,看看模擬器是否能夠啟動(dòng),如果能啟動(dòng)那問(wèn)題就不大。
4、單擊菜單build—update remote output files,看看模擬器是否能夠啟動(dòng)。
5、如果上述辦法均不行,關(guān)閉EVC然后重新建立一個(gè)新的工程,編譯,看看模擬器是否能夠啟動(dòng),如果能啟動(dòng)說(shuō)明原來(lái)工程出了問(wèn)題,最好恢復(fù)原工程的備份。
如何設(shè)置能夠自動(dòng)撥號(hào)、禁止自動(dòng)撥號(hào)?
在[HKEY_LOCAL_MACHINE\Comm\Autodial]下是自動(dòng)撥號(hào)的注冊(cè)表設(shè)置。
Enabled=DWORD:1 ///是否能夠自動(dòng)撥號(hào)
FailRetryWaitMS=DWORD ///如果失敗再次撥號(hào)的等待時(shí)間
RasEntryName1= REG_SZ ///自動(dòng)撥號(hào)采用的撥號(hào)連接名稱(chēng)
更多細(xì)節(jié)請(qǐng)參考標(biāo)題為“Auto Dial Registry Settings”的幫助文檔。
posted on 2008-09-16 10:35
greatws 閱讀(1946)
評(píng)論(0) 編輯 收藏 引用