得到播放窗口的DC,然后在上面顯示一個不同顏色的矩形或者其它形狀。
在ce自制平臺中如何添加自己的驅動?cec文件和reg,bib文件有何區(qū)別?看混了,不知道如何才能讓驅動注冊到平臺中。另外,reg和bib是我在編寫驅動必須要自己寫的么
CE的驅動分為本機驅動和流驅動,本機驅動你可以修改源碼(在%_WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS),然后build驅動源碼,之后用PB編譯內(nèi)核。流驅動是以DLL的形式被系統(tǒng)程序加載的。加載流驅動要在注冊表中添加信息,這和cec文件沒關。如果你想把此驅動DLL和注冊信息作為一個整體給別人使用,那么就要做一個cec文件,PB能夠讀取cec文件內(nèi)容并加載到內(nèi)核工程中。cec文件相當于安裝程序。
我安裝的是evc4.0,我開發(fā)的系統(tǒng)要顯示中文比如姓名什么的。在編輯的時候是中文顯示,但是到了輸出時,顯示的都是亂碼。不知道應該怎么去解決
EVC的模擬器不支持中文。所以顯示出來的都是亂碼。1、你可以只顯示英文,調試結束后在改界面為中文。2、安裝PB,PB的模擬器支持中文。
CStatic及其控件的文字無法垂直居中顯示,雖然在evc的資源編輯器中可設置,但是一旦運行,卻無法垂直居中顯示
這種情況正常,而且除此之外還不能右對齊。
獲取設備ID的種類有哪些
除了手機模塊外,還有CF卡有序列號、硬盤有ID號、網(wǎng)卡有MAC號等。這幾種方法數(shù)獲取手機模塊ID最簡單。
在應用程序中,如何向修改本機的ip地址等網(wǎng)絡參數(shù),并使之立即生效?
網(wǎng)絡設置保存在注冊表中,位置[HKEY_LOCAL_MACHINE/Comm/網(wǎng)卡名稱/Parms/TcpIp],例如常見的CS8900網(wǎng)卡設置:
[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"
設置之后要生效有兩種辦法:一種熱啟動,調用KernelIoControl(IOCTL_HAL_REBOOT,NULL,0,NULL,0,NULL),熱啟動時間很短暫;另外一種調用DevieceIoControlAPI,傳遞IOCTL=IOCTL_NDIS_REBIND_ADAPTER。
如何向控制面板中那樣,修改系統(tǒng)聲音的音量
調用APIwaveOutSetVolume(HWAVEOUT,dwVolume),一般參數(shù)1為0。在[HKEY_CURRENT_USER/ControlPanel/Volume]下是系統(tǒng)聲音的注冊表設置。
在應用程序中如何實現(xiàn)jpg、gif圖片的顯示
有幾種辦法:
1、在MSDN中搜索標題為“WindowsCE.NETTechnicalFrequentlyAskedQuestions”的文檔,其中有一個問題“HowcanIdisplayJPEG,GIF,andothergraphicsfiles?”,下面就是答案。
2、如果安裝了WindowsCE5.0,一個例子源碼位于WINCE500/PUBLIC/GDIEX/SDK/SAMPLES/SIMPLE。
3、用IWebBrowser組件實現(xiàn)。
在應用程序中如何實現(xiàn)系統(tǒng)待機
voidGwesPowerOffSystem(void);
在WINCE下如何實現(xiàn)鍵盤鉤子
我寫了一個簡單的例子,把其中主要部分截取出來放到了我的FTP里。用戶名以及密碼均為winceuser,地址是ftp://211.95.73.26/fllsoft@sina.com/SourceCode/用鉤子禁止系統(tǒng)鍵.rar。
在WINCE中如何得到網(wǎng)卡MAC地址
事實證明,獲得物理網(wǎng)卡的MAC地址并沒有被統(tǒng)一成一個API或者IOCTL,如果網(wǎng)卡驅動程序沒有提供接口的話只能直接訪問寄存器獲得。讀者可以參考目錄WINCE500/PUBLIC/COMMON/OAK/DRIVERS/NETCARD里的一些驅動源碼。
WindowsXPEmbedded和WindowsCE有何區(qū)別
簡單地說WindowsXPEmbedded采用WindowsXP內(nèi)核,只能運行在x86處理器上,優(yōu)點是能夠運行PC上現(xiàn)有的應用軟件,缺點是授權費太高,標價¥900元;WindowsCE采用WindowsCE內(nèi)核,能夠運行在多種處理器上,如x86、ARM、SHX、MIPS等,優(yōu)點是授權費低,最低Core版標價¥30元。缺點是需要單獨開發(fā)應用軟件、定制內(nèi)核,甚至開發(fā)BSP、Driver。
wince下只是把調制解調器的驅動掛接在了com1,如何將器驅動掛接在com2上?
1、在HLM/drivers/buildin/com2/unimodem下復制和com1一樣的數(shù)據(jù)2、在HLM/ExtModems/HayesCompat下改寫Port為COM2:,再改寫FriendlyName為"HayesCompatible在COM2:"。
如何定制自己的外殼
1、先開發(fā)一個外殼軟件,假設名稱為MyShell.exe
2、刪除注冊表[HKEY_LOCAL_MACHINE/init]下如下一行:
"Launch50"="explorer.exe"
3、在注冊表[HKEY_LOCAL_MACHINE/init]下添加如下一行:
"Launch50"="MyShell.exe"

上述的“LaunchXX”中的XX為序列數(shù),內(nèi)核依據(jù)這個序列數(shù)按由小到大的順序來分別執(zhí)行所有子鍵列出的應用程序,具體數(shù)值應該為多少請參考幫助文檔的說明。
如果原來的內(nèi)核中添加了標準外殼(standardshell)組件,或者添加了其它組件而這些組件需要依賴標準外殼,那么在PB中是無法刪除標準外殼組件的,解決辦法一是保留explorer.exe在內(nèi)核中,二是刪除依賴標準外殼的組件。
我原來的工程是x86版本的,編譯選項只有x86,我如何能夠編譯ARM版本的
兩種辦法:
1、用EVC新建一個工程的時候,建議復選“CPUs”列表,這樣發(fā)生了這種事情也能夠輕易通過選擇“WCEConfiguration”工具欄中的CPU列表來編譯不同CPU版本的軟件
2、如果打開工程后CPU列表中只有x86,而此時已經(jīng)安裝了ARM版本的SDK,那么單擊EVC菜單“build”-“configurations”,然后單擊“add”按鈕來添加CPU。
通常情況下WINCE采用串口1作為調試時輸出信息用途,要正式出產(chǎn)品前如何去掉串口1的調試功能
正常情況下串口1只有在編譯debug版本的內(nèi)核時才在BootLoader中初始化串口1用于輸出信息,而編譯release版本會跳過此代碼。而有些BSP設計成沒有宏定義,也就是說無論什么版本都會在BootLoader中初始化串口1,這樣造成WINCE啟動后串口1無法被應用程序使用。對于這種情況只能在BootLoader源碼中刪除初始化代碼,如OEMInitDebugSerial。
基于wince的應用程序能建成consoleproject么?
不能
ARM系統(tǒng)外擴一片512KRAM,驅動程序經(jīng)過映射可以使用這一段RAM。1、應用系統(tǒng)如何使用這一段RAM?要加一層驅動嗎?2、如果要將這一段RAM當作RAM盤存儲系統(tǒng),該如何作呢?應該要加文件系統(tǒng)吧,如何加呢?
解答這個問題前,先要說一下WINCE的地址映射機制。對于包含MMU(存儲器管理單元)的處理器來說,如ARM和x86,WINCE要求OEM在定制內(nèi)核的時候填寫一個虛擬地址與物理地址映射關系的表,稱為OEMAddressTable,在這個表中定義了所有物理設備的起始物理地址,對應的起始虛擬地址,地址空間大小,RAM就包括在其中(如果是x86平臺還要求RAM起始虛擬地址從0x80000000開始)。如果有多片RAM,應該在OEMAddressTable中將它們定義在一起,使之地址連續(xù)。對于非OEM的開發(fā)者來說,他們拿到的是定制好的內(nèi)核,不能做任何修改,如果在產(chǎn)品中外擴一片RAM,只能通過API函數(shù)通知操作系統(tǒng)增加一條虛擬地址與物理地址映射關系表項。相關API函數(shù)有兩個,分別是CreateStaticMapping和VirtualCopy。它們的相同之處是都用于建立物理地址和虛擬地址的映射關系。它們的不同之處是CreateStaticMapping映射的虛擬地址范圍在0xC4000000到0xE0000000之間,這個范圍只能由內(nèi)核訪問,一般用于ISR訪問,因為ISR只能訪問靜態(tài)映射的虛擬地址空間,不能用VirtualCopy。VirtualCopy通常和VirtualAlloc配合使用,映射的虛擬地址空間在0x80000000以下,一般用于驅動程序和應用程序訪問。
1、應用程序要訪問這片RAM,和驅動程序訪問方法一樣,調用VirtualAlloc和VirtualCopy。
2、可以做一個流驅動程序專門用于讀寫這片RAM,這樣所有應用程序就可以通過調用流驅動接口函數(shù)來訪問,非要加文件系統(tǒng)也是可行的,通過修改注冊表就可以做到,但是麻煩一些。
我怎么能在PB左邊的定制平臺加進我的驅動呢?
兩種辦法:
1、在platform.bib或者project.bib的MODULES部分添加一條語句,例如:
MyDriver.dllC:/Driver/MyDriver.dllNKSH
這樣編譯內(nèi)核的時候就會把你的驅動DLL文件添加到內(nèi)核中,如果有注冊表需要設置,在platform.reg或者project.reg中添加注冊表內(nèi)容。
2、通過制作.cec文件來添加驅動,制作.cec文件的優(yōu)點是只需制作一次,以后就可以通過將.cec文件導入到PB的Catalog中,象PB自帶的feature一樣通過菜單“AddtoOSDesign”添加到左邊的內(nèi)核工程中。
WINCE有沒有相對路徑概念?如果沒有如何得到當前模塊的路徑?
1、WINCE沒有相對路徑概念,只有絕對路徑,所以凡是涉及到路徑均為絕對路徑。
2、調用APIGetModuleFileName,傳遞一個模塊的實例句柄就能夠得到模塊的絕對路徑。
怎樣讓POCKETWORD打開*.dat格式(里面都是數(shù)據(jù))的文件?
兩種辦法:
1、調用APIShellExecuteEx,在結構體SHELLEXECUTEINFO中添加.dat文件的路徑。
2、調用APICreateProcess,在第二個參數(shù)中設置.dat文件的路徑。
x86RomBootLoader真的可以實現(xiàn)嗎?它確實能代替BIOS啟動計算機?
RomBoot被設計存放在Flash/EEPROM中,也就是原來BIOS的位置,這樣當上電后CPU到固定地址執(zhí)行代碼,也就是執(zhí)行了RomBoot的代碼,它對整個硬件系統(tǒng)進行初始化和檢測,并且支持通過網(wǎng)卡從遠程機器上下載nk.bin或者從本地IDE/ATA硬盤的活動分區(qū)中尋找nk.bin文件加載。RomBoot的優(yōu)點就是引導并且加載速度快,而且它自身完成了所有的操作,這樣就不用BIOS、MSDOS,更不用Loadcepc了。
對于x86RomBootLoader,如何Build得到Romboot.rom?
1、在PB中打開一個內(nèi)核工程(x86的)2、單擊PB菜單“Build”-“OpenBuildReleaseDirectory”3、用cd命令進入%_WINCEROOT%/Platform/Geode/Romboot4、build
如何設置、更改顯示分辨率
能否設置、更改顯示分辨率由顯示驅動程序決定,而沒有統(tǒng)一的標準。例如CEPC,在啟動的時候可以通過設置loadcepc.exe的參數(shù)/L來決定WINCE啟動后的顯示分辨率,這是由于顯示驅動“VGALinearFramebuffer”支持,而Geode可以通過在定制內(nèi)核時修改注冊表項來決定WINCE啟動后的顯示分辨率。
幾個硬件使用同一個IRQ,那么發(fā)生中斷的時候系統(tǒng)怎么判斷到底是哪一個硬件發(fā)生的中斷呢?ISR里面又應該怎么控制呢?
WindowsCE支持多個設備中斷共享一個IRQ,當一個共享IRQ發(fā)生時,CE內(nèi)核的異常處理程序檢測設備特定的寄存器,因為大多數(shù)設備都有一個單獨的寄存器用于表示設備的活動狀態(tài),所以通過遍歷共享這個IRQ的所有設備的寄存器就可以判斷哪個設備發(fā)生中斷。nk.exe加載一個giisr.dll,這個.dll是微軟提供的,它其實是第一個可安裝ISR。默認CE內(nèi)核就是調用這個dll來檢測寄存器狀態(tài)的,當然OEM可以編寫自己的.dll。
CE內(nèi)部有一個ISR鏈,也就是可安裝ISR。因為CE允許OEM添加自己的ISR處理程序,所以ISR被設計成一個鏈表。排在前面的ISR比后面的ISR優(yōu)先處理中斷,如果當前ISR能夠處理當前中斷,那就返回中斷ID由IST處理或者返回SYSINTR_NOP,如果當前ISR不能夠處理當前中斷,那就返回SYSINTR_CHAIN讓下一個ISR處理。
請問在wince中如何在內(nèi)核中增加一個與/windows同級的目錄?
在platform.dat或者project.dat中添加語句。例如要創(chuàng)建根目錄下子目錄ProgramFiles,語句如下:
root:-Directory("ProgramFiles")
文件格式如下所示,我想把每行的4個值讀到4個變量中,用EVC如何編程?
第一行:460.000,3384672.357342,521268.972763
第二行:475.117,3384663.772419,521281.415271
偽代碼如下:
FILE*stream;
stream=_wfopen(L"http://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不僅負責GDI、窗口、消息,還負責管理本機設備驅動程序,負責加載顯示、鍵盤鼠標、觸摸屏驅動程序,而且GWES本身包含電源、LED驅動程序。
如何在PB中預先設定好存儲內(nèi)存和程序內(nèi)存的大小,我想多劃分一些空間給程序內(nèi)存?
兩種辦法:
1、在定制內(nèi)核時在config.bib文件中設置FSRAMPERCENT=number,具體number可參考標題為“FSRAMPERCENT”的幫助文檔。這種辦法是修改內(nèi)核的設置,所有一直有效。
2、在應用程序中調用APISetSystemMemoryDivision,如果函數(shù)返回SYSMEM_CHANGED表示成功,如果返回SYSMEM_MUSTREBOOT表示需要熱啟動才能有效。這種辦法需要每次啟動后調用API才有效。
如何取消鼠標光標?
通過取消SYS變量來實現(xiàn)此目的,在PB命令行下鍵入“setSYSGEN_CURSOR=”,然后回車確認。
EVC下調用TextOut如何編譯會出錯?
類似這樣的問題很多,這是因為EVC的幫助文檔內(nèi)容有錯誤??赡蹺VC的幫助文檔內(nèi)容是從桌面Windows幫助文檔復制過來的,所以很多API函數(shù)還有例子代碼都有錯誤,例如幫助文檔中包含一個API函數(shù)的說明,但是實際編譯的時候提示沒有這個API,有的例子代碼采用ANSI字符串,而WINCE的API都是寬字符版本,造成直接復制過來編譯失敗。
因為MFCforWINCE的CDC類中沒有TextOut成員函數(shù),所以編譯會出錯,可以用其它類成員函數(shù)ExtTextOut或者DrawText替換。
我如何將我的dll軟件讓現(xiàn)有的ce系統(tǒng)認可?盡管我也知道應該使用signfile.exe程序進行簽名,但是我并不知道那個ce系統(tǒng)認可的簽名應該是啥
如果你說的WINCE系統(tǒng)內(nèi)核已經(jīng)加入了簽名認證機制,那么沒有私鑰對你的DLL文件簽名肯定是無法運行在此內(nèi)核中的,一般簽名密鑰的密鑰長度都是1024位,很難破解。
如果查看WINCE注冊表中的內(nèi)容?
兩種辦法:
1、建立同步后,用EVC自帶的工具“RemoteRegistryEditor”打開查看。
2、從網(wǎng)上下載注冊表查看工具,放到WINCE設備中。
調用directshow出現(xiàn)鏈接錯誤,如何解決?
player.obj:errorLNK2001:unresolvedexternalsymbol_IID_IVideoWindow
player.obj:errorLNK2001:unresolvedexternalsymbol_IID_IMediaControl
這是因為鏈接器沒有找到合適的.lib文件。兩種辦法:
1、在EVC菜單Tools—options—directories里把libraryfiles的路徑重新調整一下。如果你只安裝了EVC自帶的StandardSDK而沒有其它SDK,可以指定WINCE目錄中的.lib文件路徑,例如D:/WINCE500/PUBLIC/DIRECTX/OAK/LIB/X86/RETAIL。注意CPU的類型。
2、安裝SDK,前提是導出SDK的PB內(nèi)核工程必須包括DirectShow或者其它組件。
在PB的config.bib文件中,“IMGFLASH”表示什么意思呢?
表示能夠刷NK到ROM中,具體請查看標題為“IMGEnvironmentVariables”的幫助文檔。
x86平臺如何映射各種地址空間?如何編寫中斷服務例程?
如果是x86平臺,可以調用HalTranslateBusAddress轉換物理總線地址到物理系統(tǒng)地址,調用HalTranslateSystemAddress轉換物理系統(tǒng)地址到邏輯總線地址,也可以不調用這兩個函數(shù),因為x86平臺除32位物理地址外還有16位的IO地址空間,對于16位的IO地址空間,可以直接調用WRITE_PORT_UCHAR或者READ_PORT_UCHAR等函數(shù)直接讀寫端口。對于32位物理地址可以調用VirtualAlloc和VirtualCopy來映射。這樣做思路清晰,簡單明了。
在x86平臺要實現(xiàn)ISR,有如下幾個步驟(以GeodeBSP為例):
1、用SETUP_INTERRUPT_MAP宏關聯(lián)SYSINTR和IRQ。以“SYSINTR_”為前綴的常量由內(nèi)核使用,用于唯一標識發(fā)生中斷的硬件,又稱為中斷ID。在Nkintr.h文件中預定義了一些SYSINTR,OEM可以在Oalintr.h文件中自定義SYSINTR。
2、用HookInterrupt函數(shù)關聯(lián)硬件中斷號和ISR。這里提到的硬件中斷號為物理中斷號,IRQ為邏輯中斷號。在InitPICs函數(shù)的最后調用了HookInterrupt函數(shù),如下:
for(i=64;i<80;i++)
HookInterrupt(i,(void*)PeRPISR);///用ISR關聯(lián)16個中斷號
3、調用InterruptInitialize函數(shù)關聯(lián)SYSINTR和IST創(chuàng)建的事件對象,也是IST等待的事件對象。詳細內(nèi)容請參考GeodeBSP源碼。
在x86平臺要實現(xiàn)可安裝ISR,先調用LoadIntChainHandler函數(shù)注冊在注冊表中指定的ISRDLL,然后填充GIISR_INFO結構體并調用KernelLibIoControl函數(shù)將此結構體傳遞給可安裝ISR。詳細內(nèi)容請參考WINCE幫助文檔或者我著的《WindowsCE下驅動開發(fā)基礎》。
修改了WINCE自帶的驅動程序后如何編譯?如果是自己開發(fā)的驅動程序如何編譯?
1、分為IDE方式和命令行方式。
IDE方式的編譯很簡單,以PB5.0為例,打開定制內(nèi)核的工程,在左邊的“workspace”—“FileView”中找到你已經(jīng)修改了的目錄,然后單擊右鍵彈出菜單,在菜單中選擇“BuildandSysgenCurrentProject”,這樣PB就會編譯指定的目錄中的項目源碼文件,然后執(zhí)行sysgen命令根據(jù)source文件中的內(nèi)容生成目標文件并復制到當前內(nèi)核工程目錄下。
命令行方式的編譯需要打開“BuildOS”—“OpenReleaseDirectory”,以cd命令進入你已經(jīng)修改的驅動程序目錄中,然后鍵入“build–cfs”,然后鍵入“sysgen–p項目名稱”,一般項目名稱為source文件中的“TARGETNAME”。
2、如果想完全自己開發(fā)驅動程序,建議直接采用EVC或者PB來編寫編譯。
開發(fā)PCI設備驅動時,InterruptInitialize函數(shù)的第一參數(shù)是否是PCI卡配置空間信息中的InterruptLine參數(shù)?是否需要在HKLM/Drivers/BuiltIn/PCI/Template加一個自己的subkey,并填寫相應內(nèi)容?如何填?
1、InterruptInitialize的第一參數(shù)是IRQ,也就是邏輯中斷號,而不是物理中斷號,InterruptLine是指物理中斷號
2、需要在template下加自己的PCI設備的信息,例如:
[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"
而這些信息就來自于你執(zhí)行pcienum.exe的結果。
編譯器報錯:errorC2065:''''CFileFind'''':undeclaredidentifier,如何解決?
MFCforWINCE版本沒有CFileFind類,所以要查找文件只能調用APIFindFirstFile和FindNextFile。
如何設置WINCE系統(tǒng)字體、字號?如何設置自己開發(fā)的軟件的字體、字號?
1、系統(tǒng)字體通過注冊表設置。如下:
[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ù)設置大點就可以了。如CFont::CreateFont(nHeight,...),也可以在LOGFONT結構中設置字體高度或者字體種類。如果是控件,調用控件的SetFont成員函數(shù)。如果是直接畫,在OnPaint響應函數(shù)中調用SelectObject選字體到DC。
nk.bin和nk.nb0有什么區(qū)別?
這里提到的bin是一種二進制鏡像格式,以片斷(section)為單位組織數(shù)據(jù),每個片斷都包括一個頭,頭里指定了起始地址,長度,校驗值。PlatformBuilder調用工具將WINCE內(nèi)核所有文件以bin格式合并成一個文件,默認文件名為nk.bin。BootLoader又以同樣的格式將nk.bin分解成多個文件放到RAM中。可以在命令行中鍵入“viewbinnk.bin”來查看bin文件中具體包括了哪些內(nèi)容。鍵入Cvrtbin命令轉換.bin格式文件為.sre格式或者.abx格式。
nb0格式是原始的二進制鏡像,它不包括頭,一般情況下將內(nèi)核下載到設備的RAM中運行都采用nb0格式。要生成nbx格式的文件,需要在相關.bib文件中確定如下值:ROMSTART、ROMWIDTH、ROMSIZE。
在不采用硬件計時器的情況下如何創(chuàng)建更精確的計時器?最精確周期能否達到1毫秒?
對于精確值的要求不同,所采用的辦法不同。以下闡述幾種辦法。
1、在單線程中循環(huán)調用APISleep函數(shù),Sleep函數(shù)精確程度為如果Sleep(N),那么實際睡眠時間在N到N+1毫秒之間。而且還要注意調用Sleep的線程優(yōu)先級的問題。如果任務過多并且此線程優(yōu)先級低,那誤差就更大些。
2、調用APIQueryPerformanceCounter函數(shù),舉例如下:
LARGE_INTEGERliFrequency;
if(QueryPerformanceFrequency(&liFrequency))//查詢系統(tǒng)時鐘的頻率,這里將返回1000
{
liFrequency.QuadPart/=1000;
LARGE_INTEGERliTimeOut;
if(QueryPerformanceCounter(&liTimeOut))//得到截至到當前累計發(fā)生的系統(tǒng)時鐘中斷次數(shù)
{
liTimeOut.QuadPart+=liFrequency.QuadPart;///計算下一秒到來時總的中斷次數(shù)是多少
LARGE_INTEGERliCurrent;
do
{
QueryPerformanceCounter(&liCurrent);//循環(huán)查詢累計的的中斷次數(shù)
}while(liCurrent.QuadPart<liTimeOut.QuadPart);///到達下一秒
}
}
調用QueryPerformanceCounter同調用Sleep在本質上都是一樣的,都是在單線程中無限循環(huán)等到周期一到執(zhí)行任務,相比較QueryPerformanceCounter要比Sleep更精確些,越精確就越要求線程的優(yōu)先級,保障線程能夠正常得到處理器。
3、以上辦法難以保證周期精確到1毫秒并且WINCE系統(tǒng)穩(wěn)定地運行,所以要從中斷入手。以x86平臺為例,先在Timer.c中將默認的SetTimer0(TIMER_COUNT)中的TIMER_COUNT/=2,SetTimer0函數(shù)負責設置系統(tǒng)時鐘的頻率,默認1毫秒發(fā)生一次中斷,如果除以2就是0.5毫秒發(fā)生一次中斷。然后在fwpc.c文件中修改ISR函數(shù)PeRPISR,因為原來默認是1毫秒發(fā)生一次中斷,在處理INTR_TIMER0時系統(tǒng)負責累計計數(shù)、管理線程的調度,返回相應的SYSINTR值,而我們沒有辦法再添加代碼返回自己定義的SYSINTR值,所以現(xiàn)在要修改原來的處理代碼,例如設置一個BOOL型變量,TRUE就執(zhí)行原來默認的代碼,而FALSE就返回我們自己定義的SYSINTR值,這樣即不影響原來的ISR處理,又加入了我們的中斷響應代碼。ISR返回我們定義的SYSINTR后WINCE內(nèi)核激活相對應的EVENT事件,我們就可以在我們編寫的IST里處理任務了。
flash中存放了BootLoader和內(nèi)核鏡像,如何把剩余flash部分劃分為一個存儲區(qū)域供應用程序讀寫?
以WINCE提供的驅動(FAT文件系統(tǒng)和MSFLASH驅動)來舉例說明。如果采用默認common.reg中的注冊表設置,那么MSFLASH驅動默認把整個flash作為存儲區(qū)域來讀寫,這不符合問題的要求,所以必須告訴MSFLASH驅動程序可供讀寫的區(qū)域的起始地址和長度。以下是一個注冊表例子:
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/FASLD]
"Dll"="fasld.dll"http:///實際Flash存儲器的驅動程序
"Order"=dword:2///該驅動程序相對于其它驅動程序的加載順序
"Prefix"="DSK"http:///前綴
"Ioctl"=dword:4///IOCTL碼,設備管理器加載驅動的時候調用IOControl函數(shù),傳遞這個IOCTL碼。
"Profile"="MSFlash"http:///Profile名稱,也就是[HLM/System/StorageManager/Profiles/MSFlash]
///當設備管理器加載此驅動程序的同時發(fā)送通知給系統(tǒng),IClass(GUID)的值表明這是一個存儲設備的驅動程序。
"IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
"MemBase"=dword:00000000///Flash中可供讀寫區(qū)域的起始物理地址,也就是Flash的首地址+偏移量
"MemLen"=dword:00000000///Flash中可供讀寫區(qū)域的長度
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/MSFlash]
"DefaultFileSystem"="FATFS"http:///MSFlash驅動默認采用的文件系統(tǒng)
"PartitionDriver"="mspart.dll"http:///采用的分區(qū)驅動程序
"MountAsRoot"=dword:1///此目錄作為文件系統(tǒng)的根目錄
"Folder"="NORFlash"http:///目錄名稱
"Name"="FLASHDiskBlockDevice"http:///Flash驅動名稱
"PartitionDriverName"="MSPART"http:///分區(qū)驅動名稱
"AutoMount"=dword:1///自動裝載檢測到的分區(qū)
"AutoPart"=dword:1///自動分區(qū)
"AutoFormat"=dword:1///自動格式化分區(qū)
[HKEY_LOCAL_MACHINE/System/StorageManager/AutoLoad/MSFlash]
"DriverPath"="Drivers//BuiltIn//FASLD"http:///Flash驅動在注冊表中的位置
"LoadFlags"=dword:1///這個值可以被設置為0、1、2。1表示同步加載,其它表示異步加載
"Order"=dword:0
[HKEY_LOCAL_MACHINE/System/StorageManager/FATFS]
"FriendlyName"="FATFileSystem"http:///文件系統(tǒng)名稱
"Dll"="fatfsd.dll"http:///文件系統(tǒng)驅動程序
"Flags"=dword:00000064///標志,詳見幫助文檔
"Paging"=dword:1///是否分頁
"EnableCache"=dword:1///是否允許緩存數(shù)據(jù)
"CacheSize"=dword:0///指定緩存大小,0表示默認
驅動程序如何發(fā)通知給應用程序?
這里介紹一下常見的兩種辦法。
1、驅動程序調用APISendNotifyMessage,發(fā)送特定的消息給應用程序,這就要求應用程序要有消息循環(huán)機制并且要事先做好消息的處理。參數(shù)1為窗口句柄,可以設置HWND_BROADCAST表示廣播消息。要注意的是不要在參數(shù)中傳遞指針(虛擬地址),因為執(zhí)行驅動程序的線程和應用程序并不在同一個進程空間中。解決辦法可以利用內(nèi)存映射文件技術,比如在驅動程序中創(chuàng)建一個內(nèi)存映射文件對象,申請一塊物理內(nèi)存,然后把對象名稱和內(nèi)存長度傳遞給應用程序,應用程序打開同名的內(nèi)存映射文件對象,讀取里面的數(shù)據(jù)。對象名稱可以事先協(xié)定好,也可以通過注冊表來傳遞,內(nèi)存長度是32位值,通過消息參數(shù)就可以傳遞,也可以通過注冊表來傳遞。另外一種解決辦法是在定制內(nèi)核時候預留一塊物理內(nèi)存,這樣驅動程序和應用程序都可以通過VirtualAlloc和VirtualCopy來映射到同一塊物理內(nèi)存,其原理同內(nèi)存映射文件技術一樣,但是這塊物理內(nèi)存不具備通用性。最后一個辦法是應用程序事先將一個緩沖區(qū)地址傳遞給驅動程序,驅動程序調用MapPtrToProcess映射應用程序傳遞過來的地址,當驅動程序調用SendNotifyMessage后應用程序可以直接到該地址中讀取數(shù)據(jù)。
設備管理器就是調用此函數(shù)廣播WM_DEVICECHANGE消息的。另外WINCE的一個例子程序RNAApp在撥號連接建立的時候也是調用這個函數(shù)廣播WM_NETCONNECT消息的。
2、驅動程序調用APICeEventHasOccurred指明一個事件A發(fā)生,在此之前應用程序調用APICeRunAppAtEvent將驅動程序指明的A事件和一個應用程序名稱相關聯(lián),或者和一個事件B相關聯(lián)。這樣當A事件發(fā)生時,如果指明和一個應用程序名稱關聯(lián),那這個應用程序就會被啟動。如果指明了和一個事件B相關聯(lián),那么等待事件B的線程將被激活。如果想了解當前系統(tǒng)內(nèi)部所有驅動程序支持哪些類似事件A的事件,調用APICeNotifyPublic_FilterEvent,在該API的幫助文檔里也列舉了常見的事件,例如NOTIFICATION_EVENT_NET_CONNECT和NOTIFICATION_EVENT_NET_DISCONNECT。
EVC創(chuàng)建的工程名稱如果用中文就出錯,該怎么辦?
用EVC創(chuàng)建的工程名稱如果為中文將導致資源文件打不開和編譯出錯,可以改資源文件名稱為英文,再編輯.rc文件中的資源文件名稱。但建議盡量不要用中文為工程名稱。
作為習慣,應該在EVC創(chuàng)建一個工程后,立刻在“project”—“settings”中設置資源的語言屬性,然后在“resourceview”中設置每個資源的語言屬性,這些工作做完后再修改資源就沒有問題了。有人詢問對話框的標題為亂碼,其原因就是在沒有修改語言屬性的情況下設置標題為中文。
WinCE下如何讀寫幾百兆的大文件呢?使用內(nèi)存映射文件嗎?
一般嵌入式設備配備128MB物理內(nèi)存就算頂級的了,所以要讀寫幾百MB的文件用內(nèi)存映射文件技術是最好的選擇了。映射文件之后讀數(shù)據(jù)是非常容易的,要注意的是寫數(shù)據(jù),內(nèi)存映射方面的API沒有提供改變文件長度的功能,所以要在關閉映射文件對象后用文件API改變文件長度。
請問如何改系統(tǒng)調度的默認時間片值?
更改schedule.c文件中的dwDefaultThreadQuantum變量,然后重新編譯該文件并SYSGEN。調用APICeGetThreadQuantum就知道更改是否生效。
如何讓系統(tǒng)加載自己寫的驅動程序?
兩種辦法:
1、在[HKEY_LOCAL_MACHINE/Drivers/BuiltIn]下添加注冊鍵。
2、在應用程序中調用ActivateDeviceEx。
在一些文件中用分號來表示注釋,例如下面的內(nèi)容
;@CESYSGENIFSERVERS_MODULES_HTTPD
;@CESYSGENENDIF
在“CESYSGEN...”前加了“@”,有沒有什么特別的含義?
在WINCE的一些文件中,用“;”作為注釋并在注釋文字中用@CESYSGEN作為標記,后面接條件語句。Cefilter.exe工具負責按照條件來篩選文件內(nèi)容,所以不要輕易地刪除包含@CESYSGEN的注釋語句。
通過串口建立ActiveSync聯(lián)接,串口線用三線的可以嗎?
不可以,因為用串口同步時要用到其余口的狀態(tài)。
WINCE是否支持MAPI?
不支持。WINCE自帶的pmail.exe軟件也不是很好用。建議自開發(fā)郵件收發(fā)軟件。如果需要購買WINCE下郵件收發(fā)軟件可以聯(lián)系我。
如何旋轉屏幕顯示的內(nèi)容?
例子代碼如下(前提是顯示驅動程序支持旋轉):
DEVMODEdevmode={0};
devmode.dmSize=sizeof(DEVMODE);
devmode.dmDisplayOrientation=DMDO_90;///垂直模式
devmode.dmFields=DM_DISPLAYORIENTATION;
ChangeDisplaySettingsEx(NULL,&devmode,NULL,0,NULL);///改變顯示的設置
CRectrcWorkArea(0,0,320,240);///整個屏幕尺寸
///設置客戶區(qū)大小并廣播消息,這樣所有軟件也就隨之更改顯示
SystemParametersInfo(SPI_SETWORKAREA,0,(void*)&rcWorkArea,SPIF_SENDCHANGE);
請問如何修改字形緩存的容量?
[HKEY_LOCAL_MACHINE/System/GDI/GLYPHCACHE]
"limit"=dword:0400
如何得到從WINCE啟動開始到現(xiàn)在的時間?
調用APIGetTickCount,得到的值為32位整數(shù),單位為毫秒。
如何調用WINCE的軟鍵盤?
調用APISipShowIM(SIPF_ON),前提是內(nèi)核加入了軟鍵盤組件。
基于HIVE的注冊表,如何在系統(tǒng)關閉前保存注冊表的數(shù)據(jù)到文件system.hv?
調用APIRegFlushKey函數(shù)。
使用VirtualAlloc和VirtualCopy的時候需要注意哪些事項?
1、VirtualAlloc的作用是申請?zhí)摂M地址空間,這肯定不是最終的目的,最終目的可能是申請物理內(nèi)存、映射寄存器、提交文件等。沒有一個目的會在意虛擬地址空間的位置,所以盡量傳遞參數(shù)1為0,也就是讓WINCE自動分配虛擬地址空間。VirtualAlloc分配地址空間實際上是以64KB為單位,所以要指定申請的虛擬空間的首地址的話,參數(shù)1應該為64KB的整數(shù)倍,申請的長度也應該為64KB的整數(shù)倍,即使你不需要那么大。
2、VirtualCopy的主要作用是映射物理地址空間,如果參數(shù)2為物理地址,那么最后一個參數(shù)要添加PAGE_PHYSICAL,參數(shù)2必須是256的整數(shù)倍。如果參數(shù)2為虛擬地址(0x80000000以上),那么最后一個參數(shù)就不要添加PAGE_PHYSICAL,WINCE內(nèi)核會根據(jù)這個虛擬地址找到對應的物理地址。
驅動程序和應用程序之間傳遞數(shù)據(jù)時何時調用MapPtrToProcess?
因為設備管理器負責加載驅動程序DLL,這意味著當應用程序調用驅動程序接口函數(shù)的時候,WINCE內(nèi)核會將調用驅動程序接口函數(shù)的線程轉移到設備管理器的進程空間然后執(zhí)行具體的驅動程序代碼,應用程序和設備管理器處于兩個進程空間,這就造成設備管理器無法訪問應用程序傳遞的指針(虛擬地址),所以當我們在應用程序中傳遞指針給流驅動程序接口函數(shù)時,WINCE內(nèi)核從中作了一個地址映射,例如ReadFile、WriteFile、DeviceIoControl函數(shù)的參數(shù)凡是指針都經(jīng)過了映射才傳遞給驅動程序,所以很多驅動程序開發(fā)者并不了解其中的奧秘就可以編程了。但是如果參數(shù)是一個指向一個結構體的指針,而結構體里包括一個或多個指針,那么WINCE內(nèi)核并不負責映射,所以就需要開發(fā)者在驅動程序接口函數(shù)中調用API函數(shù)MapPtrToProcess來映射地址。例如:pPointer_retval=MapPtrToProcess(pPointer,GetCallerProcess());
如何判斷可插拔的設備是否存在?
1、通過查找注冊表的值。凡是由APIActivateDeviceEx加載的驅動程序都在[HKEY_LOCAL_MACHINE/Drivers/Active]鍵下有注冊鍵,通過查找“name”或者其它鍵值就能夠找到。設備管理器就調用這個API。如果是PCI設備,在注冊表[HLM/Drivers/BuiltIn/PCI/Instance]下查找關鍵字,例如[HLM/Drivers/BuiltIn/PCI/Instance/WaveDev1],說明音頻驅動已經(jīng)加載。
2、調用驅動程序接口函數(shù),根據(jù)返回值或者執(zhí)行結果來判斷。
如何做到通過串口過來的一個信號啟動自己開發(fā)的應用程序?
創(chuàng)建一個線程負責等待串口過來的信號,調用APISetCommMask設置要等待的信號種類,具體可以等待的信號種類參見參數(shù)2的說明。然后再調用APIWaitCommEvent函數(shù)等待這個信號,接收之后再調用APICreateProcess啟動應用程序。
在WINCE中如何只能啟動應用程序的一個實例?
常用的兩種辦法:
1、如果應用程序實例創(chuàng)建了窗口,可通過APIFindWindow函數(shù)通過窗口類名和窗口標題名稱來查找,前提是系統(tǒng)內(nèi)不會出現(xiàn)窗口名稱重復的情況。
2、應用程序初始化的時候創(chuàng)建一個事件或互斥等內(nèi)核對象,因為內(nèi)核對象是由內(nèi)核創(chuàng)建,名稱在系統(tǒng)內(nèi)唯一。
能不能自己編輯一個數(shù)字簽名文件導入到手機上,這樣就可以用這個簽名簽自己的程序了?
WINCE的內(nèi)核簽名機制的用途是限制非法的可執(zhí)行模塊EXE、DLL等在設備上運行。要求內(nèi)核的加載模塊用公鑰驗證請求加載的EXE、DLL的簽名是否合法,而這個公鑰是在定制內(nèi)核的時候加進去的,所以除內(nèi)核的定制者以外的人無法修改這個驗證機制。
我按照版主的文章《加密WINCE系統(tǒng)》里操作,提示錯誤如下:
Error80090016duringCryptSignHash1!
Errorsigninghash
這是因為傳遞了無效的鑰容器名稱,使CryptoAPI調用失敗。應該在使用signfile工具之前創(chuàng)建一個鑰容器,在桌面Windows中調用APICryptAcquireContext創(chuàng)建一個指定名稱的鑰容器,接著再創(chuàng)建一個簽名密鑰對,這時再使用signfile工具就可以了。我在文章里寫成-kfulinlin是因為我創(chuàng)建鑰容器的時候沒有指定名稱,系統(tǒng)就采用當前登錄的用戶名為容器名。
編譯錯誤:CVTRES:fatalerrorCVT1102:outofmemory;42bytesrequired?
多數(shù)情況下出現(xiàn)這種錯誤是因EVC的bug而起,應該在安裝EVC之后就立刻安裝EVC的SP補丁。另外為了避開BUG,使用EVC編程應該養(yǎng)成一些習慣,比如定期備份工程所有文件,每次編譯時采用Clean+RebuildAll,正調試時不要關閉模擬器等等。
在WINCE下是否能夠得到某一進程使用的物理內(nèi)存總量?
目前沒發(fā)現(xiàn)有這樣一個API能夠得到指定進程使用的物理內(nèi)存總量。只有GlobalMemoryStatus能夠得到整個系統(tǒng)使用的物理內(nèi)存總量。
應用程序如何控制lcd的亮度?如何獲得電池的電量?
從常見的平臺如Geode、三星ARM系列來看,的確在驅動方面沒有統(tǒng)一的控制LCD或者其它種類屏幕亮度的接口函數(shù),所以只能根據(jù)具體平臺提供的接口來做。從幫助文檔來看微軟的帶有DirectDraw功能的顯示驅動程序的確有標準的增加亮度的接口函數(shù),關于背景光參見標題為“EnablingaBacklight”的幫助文檔。
獲得電池電量有標準的接口函數(shù)GetSystemPowerStatusEx,前提是驅動程序和硬件都要支持。
WINCE的socket函數(shù)好像不支持發(fā)送/接收超時?
是的,最早版本的WINCE支持選項SO_RCVTIMEO、SO_SNDTIMEO,后來卻不支持了。
WINCE下如何設置窗口最大化和最小化?
WINCE的幫助文檔在介紹APIShowWindow函數(shù)的參數(shù)時指出SW_MAXIMIZE,SW_MINIMIZE,SW_RESTORE,SW_SHOWDEFAULT,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED,SW_SHOWMINNOACTIVE都不被支持,但實際上并不完全是這樣,具體來說:
SW_MAXIMIZE比原來窗口大,但不是最大化
SW_MINIMIZE編譯成功,但是不起作用
SW_SHOWMAXIMIZED最大化
SW_SHOWMINIMIZED編譯出錯
SW_RESTORE能恢復
SW_SHOWDEFAULT編譯出錯
SW_SHOWMINNOACTIVE編譯出錯
SW_HIDE能夠隱藏
如何用程序調用控制面板的觸摸屏校對程序?
兩種辦法:
1、調用APITouchCalibrate函數(shù)
2、調用CreateProcess,參數(shù)1為L"http://windows//ctlpnl.exe",參數(shù)2為L"cplmain.cpl,9"。
如何獲得U盤或者其它類型的存儲器總容量和剩余可用容量?
調用APIGetStoreInfo得到扇區(qū)數(shù)、每扇區(qū)字節(jié)數(shù),相乘即是總容量。調用APIGetDiskFreeSpaceEx得到剩余可用容量。
三星2440頭文件定義#defineIIC_BASE0xB1400000//54000000,datasheet是54000000,那么怎么轉成0xB1400000?
物理地址映射方法分為兩種,一種靜態(tài)映射另一種為動態(tài)映射。在OEMAddressTable中定義了物理地址與虛擬地址的映射關系屬于靜態(tài)映射,用VirtualCopy映射屬于動態(tài)映射,采用哪種辦法都可以。問題中提到的屬于靜態(tài)映射,2440的BSP在map.a文件中定義了IIC控制寄存器的物理起始地址和對應的虛擬地址如下:
DCD0x91400000,0x54000000,1;
在OEMAddressTable中定義的虛擬地址范圍在0x80000000—0x9FFFFFFF,這部分可緩存,適合內(nèi)核程序和應用程序使用,同時WINCE內(nèi)核在0xA0000000—0xBFFFFFFF中映射了另一份,指向了同樣的物理地址,這部分不可緩存,適合驅動程序使用。三星ARM處理器帶有L1級高速緩存,可緩存會提高執(zhí)行效率。對于特殊的設備寄存器適合映射到不可緩存的虛擬地址。
當驅動程序調用VirtualCopy對0xB1400000地址讀寫時,WINCE自動將這個地址減去0x20000000,也就是0x91400000,對應的物理地址就是0x54000000,也就是IIC控制寄存器的物理起始地址。
基于RAM的注冊表如何保存數(shù)據(jù)?
調用APIRegCopyFile備份注冊表。調用APIRegRestoreFile恢復注冊表,然后調用KernelIoControl熱啟動使恢復生效。
如何隱藏和顯示winCE下標準外殼的任務欄?
HANDLEhTaskBar=FindWindow(L"HHTaskBar",NULL);
ShowWindow(hTaskBar,SW_HIDE);
ShowWindow(hTaskBar,SW_SHOWNORMAL);
如果能讓WINCE的IE瀏覽器播放flash動畫?
播放flash需要MacromediaFlashPlayerSDK,參見http://www.adobe.com/products/flashplayer_sdk/。這和realplayer相似,都需要WINCE平臺的SDK,都需要申請。
WINCE下內(nèi)核模式和用戶模式有什么區(qū)別?
為了使讀者能夠詳細了解WINCE的地址映射原理還有兩種模式,在這里我分幾個部分說明:
1、WINCE內(nèi)核nk.exe的任務是管理操作系統(tǒng)核心功能。按照OEMAddressTable的映射要求,所有物理地址都映射到0x80000000以上,所以對于內(nèi)核程序nk.exe和內(nèi)核模式下的線程來說,只要訪問0x80000000以上的有效虛擬地址經(jīng)MMU就能夠訪問物理地址,無需再映射是內(nèi)核模式的一個特點。內(nèi)核模式的第二個特點是沒有地址訪問限制,內(nèi)核模式線程可以訪問任何有效虛擬地址,所謂有效虛擬地址是指有實際事物對應。
2、用戶模式線程只能訪問0x80000000以下的虛擬地址空間,WINCE6.0之前版本的內(nèi)核為每個進程劃分32MB的地址空間,在不調用特殊函數(shù)的情況下不能相互訪問,這樣的設計使得WINCE系統(tǒng)更安全、更穩(wěn)定,限制訪問地址是用戶模式的第一個特點。第二個特點就是需要多一層映射,如果線程要訪問物理內(nèi)存的話需要先映射到0x80000000以上,再經(jīng)MMU訪問物理內(nèi)存地址。
WINCE的線程具有轉移性(參考APIGetCallerProcess的說明,有一個很好的例子),當應用程序的線程調用API或者調用驅動程序接口函數(shù)時,該線程會轉移到gwes.exe、device.exe、filesys.exe等進程中執(zhí)行,轉移是由WINCE內(nèi)核操作的,它會修改線程的上下文,記錄線程的當前進程、調用者進程、擁有者進程三個值。
3、如果在定制內(nèi)核的時候選擇了“FullKernelMode”,那么在這個內(nèi)核上運行的所有線程都處于內(nèi)核模式,即使調用SetKMode(FALSE)后線程仍然具有內(nèi)核模式的特點,能夠訪問任何有效的虛擬地址。假設現(xiàn)有一個64MBRAM的WINCE產(chǎn)品,RAM映射從0x80000000到0x84000000,如果線程處于內(nèi)核模式,它就直接可以訪問這個范圍的虛擬地址:
在OnButton1()中編寫
DWORDoldMode=SetKMode(FALSE);
volatileint*piTemp=(volatileint*)(0x20000000+0x84000000-0x00019000);///或者(0x84000000-0x00019000)
*piTemp=12345;
在OnButton2()中編寫
DWORDoldMode=SetKMode(FALSE);
volatileint*piTemp=(volatileint*)(0x20000000+0x84000000-0x00019000);///或者(0x84000000-0x00019000)
intiTemp=*piTemp;
先只執(zhí)行OnButton1()然后關閉程序,再重啟程序然后執(zhí)行OnButton2(),iTemp仍然等于12345。結果說明了兩點:內(nèi)核模式線程可以直接訪問0x80000000以上的有效虛擬地址;我們寫到RAM中的數(shù)據(jù)沒有丟失,說明虛擬地址有效。
如果在定制內(nèi)核的時候沒有選擇“FullKernelMode”,那么在這個內(nèi)核上運行的所有線程都處于用戶模式??梢哉{用SetKMode(TRUE)使調用線程暫時處于內(nèi)核模式,還是原來的假設環(huán)境,我再舉個例子:
在OnButton1()中編寫
DWORDoldMode=SetKMode(TRUE);
volatileint*piTemp=(volatileint*)(0x20000000+0x84000000-0x00019000);///或者(0x84000000-0x00019000)
*piTemp=12345;
在用戶模式下,如果不調用SetKMode(TRUE),那么執(zhí)行*piTemp=12345一定會彈出對話框,提示地址訪問非法,如果調用SetKMode(TRUE)就不會提示地址訪問非法,而且在OnButton2()中仍然能得到12345這個值。
通過這兩個例子我相信讀者能夠完全了解兩種模式的區(qū)別了。
4、WINCE提供了兩個函數(shù)SetKMode和SetProcPermissions,其中SetKMode能夠把調用線程切換到內(nèi)核模式,還可以切換回用戶模式。SetProcPermissions+GetCurrentPermissions添加當前進程訪問權限給調用線程,SetProcPermissions(0xFFFFFFFF)能讓調用線程訪問所有進程空間,但是調用線程仍然處于用戶模式。SetKMode和SetProcPermissions函數(shù)使得用戶模式的特點不那么明晰。
如上所說一個應用程序的線程可能轉移到其它兩個進程地址空間中讀寫數(shù)據(jù),而每一個線程在被創(chuàng)建的時候只有訪問創(chuàng)建它的進程地址空間的權限,所以驅動程序開發(fā)者必須在驅動程序讀寫數(shù)據(jù)前調用SetKMode或者SetProcPermissions增加調用此函數(shù)的線程訪問其它進程空間的權限。如果一個應用程序的線程只轉移到一個進程地址空間,一般為設備管理器進程device.exe,這種情況下不必增加線程訪問其它進程空間的權限,但如果驅動程序本身創(chuàng)建了一個線程,那還是要調用SetKMode或者SetProcPermissions增加新的線程訪問其它進程的權限的,因為驅動程序創(chuàng)建線程時,當前進程為設備管理器,所以新線程只具有訪問設備管理器進程空間的權限,而不具備訪問應用程序進程空間的權限。
5、可能一個編寫過簡單的流驅動的初學者會很疑惑,因為開發(fā)一個簡單的流驅動程序根本不需要調用這些函數(shù),也沒有調用過MapPtrToProcess,那是因為如果標準流驅動接口函數(shù)的參數(shù)為指針(ReadFile、WriteFile、DeviceIoControl參數(shù)都有指針),WINCE內(nèi)核會自動映射指針包含的地址,但僅此而已,其余任何情況都要求開發(fā)者自行處理,比如流接口函數(shù)的參數(shù)是一個指向結構體的指針PA,而結構體中包括指針PB,PB指針就必須在流接口函數(shù)中映射,映射后才能訪問,否則就會造成地址訪問非法。所以結構體中每個指針都要映射。
為了讓讀者能了解其中的原因,我舉個例子:
假設設備管理器被加載到Slot4,應用程序A被加載到Slot8,A只有一個主線程T,T開始執(zhí)行,按照WINCE的規(guī)定,正獲得CPU的進程必須映射到Slot0,那么在執(zhí)行代碼的時候A的所有虛擬地址都被減去一個偏移值,也就是8×0x02000000,A調用DeviceIoControl,傳遞一個指向一個結構體的指針B,而這個結構體中包含一個指針C,指針C包含的地址假設為0x00030000,當執(zhí)行DeviceIoControl時WINCE把設備管理器的進程地址空間映射到Slot0,因為放在注冊表[HKLM/Drivers/BuiltIn]下的驅動程序是由設備管理器加載的,自然驅動程序的代碼段被加載到設備管理器進程空間,但是線程仍然是T,此時T的當前所在進程為設備管理器(CurrentProcess),A變成了T的調用者進程(CallerProcess),T自動具有了訪問調用者進程空間的權限。這時訪問Slot0中的虛擬地址其實質就是訪問設備管理器的進程地址空間,要把地址加上一個偏移值,也就是4×0x02000000,所以DeviceIoControl訪問指針C包含的地址時本應該加上8×0x02000000,卻加上4×0x02000000,結果地址并不是設備管理器的合法區(qū)域,系統(tǒng)就會提示地址訪問非法。而如果做了一個映射,指針C包含的地址就會被加一個正確的偏移值,使地址處于A的地址空間Slot8中,T此時具有訪問A進程空間的權限,訪問到正確的虛擬地址當然會得到正確的數(shù)據(jù)了。
為什么WINCE目錄下的例子用build+sysgen能夠編譯成EXE文件,而我添加的例子就不能編譯呢?
如果這個例子是一個應用程序,那么肯定包括代碼文件(.h.c.cpp)和資源文件(.rc和其它資源文件),build工具根據(jù)source文件內(nèi)容把代碼文件編譯成lib文件,資源文件編譯成.res文件,sysgen工具根據(jù)makefile文件內(nèi)容將source文件中列出的需要鏈接的各個庫文件合并成一個EXE文件。所以說關鍵在于makefile文件,WINCE目錄下凡是能夠用build+sysgen編譯的都在makefile中有如何鏈接的設置,而我們添加的例子當然沒有在makefile中找到如何鏈接的設置,nmake工具就會提示不知道如何創(chuàng)建。
pcienum.exe干什么用的?
如果你要開發(fā)某一個PCI設備的驅動程序,首先要知道這個PCI設備的信息(如VendorID、DeviceID、BaseClass、SubClass)和PCI總線的信息。運行這個pcienum.exe就能得到相關信息。pcienum.exe提供了源碼,位置/Public/Common/Oak/Drivers/Ceddk/Test/Pcienum。
wince下如何讓操作系統(tǒng)進入待機模式?又如何把它激活?
通過注冊表就可以設置,前提是你的驅動和硬件都支持。注冊表項參見標題為“GWESSuspendTime-outs”的幫助文檔。
[HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power]
"BattPowerOff"=dword:300
"ExtPowerOff"=dword:0
"WakeupPowerOff"=dword:60
"ScreenPowerOff"=dword:0
現(xiàn)有一個GPRS模塊,如何通過GPRS連接到Internet?
1、先在內(nèi)核中加入WAN下面的幾個組件,如RAS/PPP、TAPI。WINCE采用unimodem驅動,所以不必擔心沒有Modem驅動的支持。
2、WINCE啟動后新建一個撥號連接,比如名稱叫“gprs1”,輸入用戶名、密碼、電話號碼。電話號碼不同,所采用的模式不一樣,例如“*99#”是GPRS模式,“17201”是普通的數(shù)據(jù)模式,速度差很多,價錢也差很多。
3、開始連接,連接過程會在對話框中顯示,直到顯示“連接成功”。
4、打開瀏覽器或者自己開發(fā)的通訊軟件測試網(wǎng)絡連接情況。
5、關閉連接。
6、保存[HKEY_CURRENT_USER/Comm/RasBook/gprs1]下的所有數(shù)據(jù),添加到project.reg中,重新編譯后內(nèi)核中就有了一個撥號連接“gprs1”。
7、調用RAS函數(shù)可以修改撥號連接“gprs1”的參數(shù),如用戶名、密碼、電話號碼,但是不能修改硬件設置,如波特率、串口、數(shù)據(jù)位、停止位等。RAS函數(shù)還能夠撥號、掛斷。為了修改波特率可以多保存幾個撥號連接,也可以直接調用TAPI開發(fā)撥號軟件,另外WINCE自帶的撥號連接是有源碼的,位置在/PUBLIC/COMMON/OAK/DRIVERS/NETSAMP/CONNMC。
采用基于HIVE的注冊表如何刪除用戶保存在注冊表中的數(shù)據(jù),恢復到出廠時的注冊表?
用戶修改的數(shù)據(jù)保存在user.hv文件中,直接刪除一定失敗,所以不能通過刪除文件實現(xiàn)恢復出廠設置。微軟考慮到了這個問題,在WINCE啟動過程中filesys.exe加載注冊表時會調用OEMIoControl函數(shù)并傳遞一個IOCTL,這個IOCTL在pkfuncs.h中定義如下:
#defineIOCTL_HAL_GET_HIVE_CLEAN_FLAGCTL_CODE(FILE_DEVICE_HAL,49,METHOD_BUFFERED,FILE_ANY_ACCESS)
filesys.exe會分別傳遞參數(shù)HIVECLEANFLAG_SYSTEM和HIVECLEANFLAG_USERS,如果返回值為TRUE那么filesys.exe清除原來的注冊表文件,如果返回值為FALSE那么filesys.exe保留原來的注冊表文件。默認WINCE并沒有實現(xiàn)這個IOCTL,所以OEM要刪除注冊表文件就必須先編寫這個IOCTL代碼。代碼的例子可參考標題為“IOCTL_HAL_GET_HIVE_CLEAN_FLAG”的幫助文檔。另外必須在ioctl.h和ioctl.c兩個文件中編寫該代碼。在ioctl.c文件中找到constOAL_IOCTL_HANDLERg_oalIoCtlTable[],添加IOCTL和對應的處理函數(shù)。要進一步了解這個全局數(shù)組,參見標題為“IOCTLLibrary”的幫助文檔。
如何在不刪除必要組件的前提下減小內(nèi)核文件長度?
要減小內(nèi)核文件長度首先要在使用PB的定制內(nèi)核向導中選擇自定義,也就是說對于每個組件都由自己來選擇,而不是選擇PB的標準配置。但減小內(nèi)核文件長度最有效最直接的辦法是縮小字體,尤其對于東亞字體,采用字體壓縮技術并且選擇合理的字庫文件將明顯縮小文件長度。
1、在定制內(nèi)核時選擇AGFAAC3FontCompression組件。SYSGEN變量為SYSGEN_AGFA_FONT。
2、參考標題為“EastAsianFontVersions”的幫助文檔,從中選擇你需要的字庫文件加到內(nèi)核中,從文檔可以看出加AC3壓縮比不加壓縮在文件長度方面差距很大。
如何得到WAV文件播放的總時間?
1、直接讀取wav文件頭信息,從文件起始地址偏移28個字節(jié)長度為4個字節(jié)保存的是每秒鐘播放的字節(jié)數(shù),從文件起始地址偏移40個字節(jié)長度為4個字節(jié)保存的是聲音數(shù)據(jù)的總的字節(jié)數(shù),相除就是播放時間。
2、調用IGraphBuilder::RenderFile打開一個wav文件,然后通過IGraphBuilder得到IMediaSeeking指針,再調用IMediaSeeking::GetDuration得到總的時間(結果要除以10000000),IMediaSeeking::GetCurrentPosition得到當前播放時間。
如何在Dialog-Based程序中加入menubar?
先調用CommandBar_Create再調用CommandBar_InsertMenubar。
請問MultiByteToWideChar與_T、L、TEXT的區(qū)別?
MultiByteToWideChar函數(shù)轉換的對象可以是常量也可以是變量。其它只能轉換常量。_T和TEXT會根據(jù)當前系統(tǒng)是否定義_UNICODE宏來決定是否轉換,而L就是轉換成寬字符,當然也包括其他類型常量的轉換。
在用UBS線纜通過ActiveSync同步有效的情況下,如何插上USB線纜后WINCE自動與PC同步?
1、新建一個撥號連接,假設名稱為“usb1”,選擇連接類型為“直接連接”,并在連接設備里選擇通過USB線纜連接。
2、將注冊表[HKEY_CURRENT_USER/Comm/RasBook/usb1]下的數(shù)據(jù)添加到project.reg或者platform.reg中。
3、在[HKEY_CURRENT_USER/ControlPanel/Comm]下添加如下:
"AutoCnct"=dword:1///直接連接
"Cnct"="usb1"http:///連接名稱
4、重新編譯內(nèi)核。為了節(jié)省編譯時間也可以在內(nèi)核工程下搜索*.reg文件,將2、3步驟中的注冊表數(shù)據(jù)添加其中,然后直接makeimage。
如何通過進程句柄來獲得該進程的主窗口句柄?
好像沒有API能夠通過進程句柄直接獲得主窗口的句柄,因為并非每個應用程序都帶UI。但是可以反過來,先枚舉當前系統(tǒng)所有主窗口,然后根據(jù)每個窗口的句柄調用GetWindowThreadProcessId函數(shù)得到進程的ID,再調用OpenProcess得到進程句柄,與現(xiàn)有的進程句柄比較。
我做的顯示驅動DLL已經(jīng)編譯成功了,但是在加載顯示驅動的過程中彈出話框,提示如下:
unhandledexceptioningwes.exe(0xc0000005accessviolation)
提示的錯誤——地址訪問非法,表明你的驅動程序代碼并沒有在讀寫數(shù)據(jù)前添加SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函數(shù)讓線程能夠訪問任何進程的地址空間。你可以調用IsBadReadPtr和IsBadWritePtr函數(shù)檢測地址是否能夠合法訪問。編寫和gwes有關的驅動程序應該首先調用SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函數(shù),這是一個好習慣。
請問在嵌入式系統(tǒng)中如何設置GPRS拔號用的APN?
對一個撥號連接比如“我的連接”單擊鼠標右鍵,在彈出的菜單中選擇“屬性”,然后單擊“配置”—“撥號選項”,在“附加設置”中添加AT命令如“+cgdcont=1,"ip","cmnet"”?!癱mnet”位置即為APN。
WINCE的IPPhone功能如何?
WINCE的voip需要c-s-c結構,既需要服務器的中轉,而skype采用第三代p2p技術就不需要中轉,但是在gprs下也做不到語音流暢。skype有pocketpc版本,但是無線方面需要wlan或者cdma。
三星ARM平臺如何定義自己的中斷ID?
以S3C2410為例,在oalintr.h文件中定義中斷ID,也稱SYSINTR,例如#defineSYSINTR_MYINT(SYSINTR_FIRMWARE+20),最大值不能超過SYSINTR_FIRMWARE+23。然后在armint.c文件中找到OEMInterruptHandler函數(shù),用if(IntPendVal==INTSRC_XXX)判斷當前發(fā)生的中斷源號,然后返回SYSINTR_MYINT。內(nèi)核分別調用OEMInterruptDisable(禁止當前中斷)、OEMInterruptDone(中斷處理結束)、OEMInterruptEnable(當前中斷有效)三個函數(shù),參數(shù)都為中斷ID,在這三個函數(shù)中用caseSYSINTR_MYINT判斷當前要處理的中斷。
如何開發(fā)軟件從PC端復制文件到基于WINCE的設備?
調用RAPI(RemoteApplicationProgrammingInterface)函數(shù),此函數(shù)集由桌面計算機調用,由基于WINCE的設備執(zhí)行。一旦連接上就可以在桌面計算機端調用RAPI。通過注冊表還可以限制RAPI能夠訪問目錄的范圍。具體參考RAPI和RDP(遠程桌面協(xié)議)。
請問如何對NandFlash分區(qū)、格式化?
你看看WINCE420/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BOOTPART/bootpart.cpp,在Eboot中先要調用BP_LowLevelFormat(
DWORDdwStartBlock,DWORDdwNumBlocks,DWORDdwFlags)再flash的一個區(qū)域建立空的MBR,然后連續(xù)兩次調用BP_OpenPartition(DWORDdwStartSector,DWORDdwNumSectors,DWORDdwPartType,BOOLfActive,DWORDdwCreationFlags)函數(shù)來建立BINFS和FAT分區(qū)。建好后,將nk.bin燒入binfs分區(qū)中。
要做個彈出對話框具有alwaysontop屬性,如何實現(xiàn)?
調用SetWindowPos(..,HWND_TOPMOST,....,SWP_NOACTIVATE)。
s3c2410+WINCE下網(wǎng)絡PING一會就斷,如何解決?
原因在于中斷處理程序把已經(jīng)產(chǎn)生的中斷標志清除掉了,這樣就丟失一次中斷。因為原驅動里配置中斷為上升沿觸發(fā),一次中斷丟失就導致不會再產(chǎn)生中斷信號跳變,因為只有在中斷服務中讀取了cs8900的Interruptstatusqueue寄存器后,才會產(chǎn)生下一次中斷!解決辦法:
1、在cfw.c文件中全局定義BOOLInited=FALSE
2、修改OEMInterruptEnable()中caseSYSINTR_ETHER:下面的語句為:
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;
注:本解決辦法轉載于http://stoned.blogchina.com/stoned/3083045.html,非我本人研究成果。
已經(jīng)搜索到文件,如何用CListBox以圖標形式顯示出來?
CListCtrlListCtrl;
CImageListImageList;
ImageList.Create(IDB_BITMAP,48,2,RGB(0,0,0));
ListCtrl.SetImageList(&ImageList,LVSIL_NORMAL);
ListCtrl.InsertItem(iListIndex,strItem,1);
如何改變控制面板中電源屬性對話框的尺寸?
1、需要修改對話框的尺寸是因為對話框是以資源方式加載的,不會根據(jù)當前系統(tǒng)顯示分辨率而自我調節(jié)尺寸。
2、安裝WINCE后有一些組件(feature)的資源文件*.res就已經(jīng)有了,如果你不改變,那么build內(nèi)核的時候PB只是把這些.res復制到工程目錄下,然后與*.obj合并成EXE、DLL、CPL。所以修改了.rc文件里面的對話框尺寸后要重新編譯.rc文件為.res文件,然后再覆蓋原來WINCE自帶的.res文件。
3、改變對話框尺寸有兩種辦法:一種方法是更改系統(tǒng)字體字號,系統(tǒng)字體的字號變化會影響對話框的尺寸,但是缺點是所有系統(tǒng)字體有關的UI都會改變。另一種是在.rc文件中調整對話框尺寸,然后編譯成.res文件,再將.res復制到對應的語言目錄里,比如目錄名為0804(中文),再執(zhí)行Rebuild命令重新編譯內(nèi)核,或者執(zhí)行sysgen+build。在研究中我發(fā)現(xiàn).res文件雖然能夠直接用EVC打開、修改、保存,但是和其它Obj鏈接成EXE、DLL、CPL后并不能運行,所以還是建議讀者用CE自帶的rc工具編譯最好。讀者可在PB的命令行中鍵入“rc/?”了解rc.exe工具的用途和參數(shù)。
使用EVCbuild之后連接模擬器的時候,提示downloadfile等了一會又出現(xiàn)downloadfailed?
一般這樣的問題從下面幾個步驟解決:
1、如果之前能啟動模擬器而現(xiàn)在不能,那么先clean然后重啟計算機再build。
2、如果開發(fā)的主機為WINXP+SP2,可能存在與EVC模擬器不兼容的情況,檢查C:/boot.ini,將/noexecute=optin改為/execute=optin。
3、檢查你的模擬器是否能運行,假設你正用的SDK名稱為MYSDK,單擊菜單tools—configureplatformmanager,選擇MYSDK—MYSDKemulator,再單擊properties—test,看看模擬器是否能夠啟動,如果能啟動那問題就不大。
4、單擊菜單build—updateremoteoutputfiles,看看模擬器是否能夠啟動。
5、如果上述辦法均不行,關閉EVC然后重新建立一個新的工程,編譯,看看模擬器是否能夠啟動,如果能啟動說明原來工程出了問題,最好恢復原工程的備份。
如何設置能夠自動撥號、禁止自動撥號?
在[HKEY_LOCAL_MACHINE/Comm/Autodial]下是自動撥號的注冊表設置。
Enabled=DWORD:1///是否能夠自動撥號
FailRetryWaitMS=DWORD///如果失敗再次撥號的等待時間
RasEntryName1=REG_SZ///自動撥號采用的撥號連接名稱
更多細節(jié)請參考標題為“AutoDialRegistrySettings”的幫助文檔。
(###)
愛華網(wǎng)



