WinCE驅動開發問題精華集錦

1、在應用程序中,如何向修改本機的ip 地址等網絡參數,並使之立即生效?   
       網絡設置保存在註冊表中,位置[HKEY_LOCAL_MACHINE/Comm/網卡名稱/Parms/TcpIp],例如常見的CS8900網卡設置:  
[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),熱啓動時間很短暫;另外一種調用DevieceIoControl API,傳遞IOCTL=IOCTL_NDIS_REBIND_ADAPTER。  
  
2、如何向控制面板中那樣,修改系統聲音的音量  
     調用API waveOutSetVolume(HWAVEOUT, dwVolume ),一般參數1爲0。在[HKEY_CURRENT_USER/ControlPanel/Volume]下是系統聲音的註冊表設置。  
  
3、在應用程序中如何實現jpg、gif圖片的顯示   
有幾種辦法:  
1)、在MSDN中搜索標題爲“Windows CE .NET Technical Frequently Asked Questions”的文檔,其中有一個問題“How can I display JPEG, GIF, and other graphics files?”,下面就是答案。  
2)、如果安裝了Windows CE 5.0,一個例子源碼位於WINCE500/PUBLIC/GDIEX/SDK/SAMPLES/SIMPLE。  
3)、用IWebBrowser組件實現。  

4、 在應用程序中如何實現系統待機  
void GwesPowerOffSystem(void);  

5、   在WINCE中如何得到網卡MAC地址   
     事實證明,獲得物理網卡的MAC地址並沒有被統一成一個API或者IOCTL,如果網卡驅動程序沒有提供接口的話只能直接訪問寄存器獲得。讀者可以參考目錄WINCE500/PUBLIC/COMMON/OAK/DRIVERS/NETCARD裏的一些驅動源碼。  
  
6、Windows XP Embedded 和Windows CE有何區別  
     簡單地說Windows XP Embedded採用Windows XP內核,只能運行在x86處理器上,優點是能夠運行PC上現有的應用軟件,缺點是授權費太高,標價¥900元;Windows CE採用Windows CE內核,能夠運行在多種處理器上,如x86、ARM、SHX、MIPS等,優點是授權費低,最低Core版標價¥30元。缺點是需要單獨開發應用軟件、定製內核,甚至開發BSP、Driver。  

7、 wince下只是把調制解調器的驅動掛接在了com1,如何將器驅動掛接在com2上?   
     1)、在HLM/drivers/buildin/com2/unimodem下複製和com1一樣的數據
     2)、在HLM/ExtModems/HayesCompat下改寫Port爲COM2:,再改寫FriendlyName爲"Hayes Compatible 在 COM2:"。  
  
8、如何定製自己的外殼   
   1)、先開發一個外殼軟件,假設名稱爲MyShell.exe  
   2)、刪除註冊表[HKEY_LOCAL_MACHINE/init]下如下一行:  
           "Launch50"="explorer.exe"  
     3)、在註冊表[HKEY_LOCAL_MACHINE/init]下添加如下一行:  
           "Launch50"="MyShell.exe"  
     上述的“LaunchXX”中的XX爲序列數,內核依據這個序列數按由小到大的順序來分別執行所有子鍵列出的應用程序,具體數值應該爲多少請參考幫助文檔的說明。  
     如果原來的內核中添加了標準外殼(standard shell)組件,或者添加了其它組件而這些組件需要依賴標準外殼,那麼在PB中是無法刪除標準外殼組件的,解決辦法一是保留explorer.exe在內核中,二是刪除依賴標準外殼的組件。  

9、我原來的工程是x86版本的,編譯選項只有x86,我如何能夠編譯ARM版本的   
兩種辦法:  
   1)、用EVC新建一個工程的時候,建議複選“CPUs”列表,這樣發生了這種事情也能夠輕易通過選擇“WCE Configuration”工具欄中的CPU列表來編譯不同CPU版本的軟件  
     2)、如果打開工程後CPU列表中只有x86,而此時已經安裝了ARM版本的SDK,那麼單擊EVC菜單“build”-“configurations”,然後單擊“add”按鈕來添加CPU。  

  
10、通常情況下WINCE採用串口1作爲調試時輸出信息用途,要正式出產品前如何去掉串口1的調試功能,正常情況下串口1只有在編譯debug版本的內核時纔在BootLoader中初始化串口1用於輸出信息,而編譯release版本會跳過此代碼。而有些BSP設計成沒有宏定義,也就是說無論什麼版本都會在BootLoader中初始化串口1,這樣造成WINCE啓動後串口1無法被應用程序使用。對於這種情況只能在BootLoader源碼中刪除初始化代碼,如OEMInitDebugSerial。  
  
11、基於wince的應用程序能建成console project麼?   
       不能  

12、ARM系統外擴一片512K RAM,驅動程序經過映射可以使用這一段RAM。1、應用系統如何使用這一段RAM?要加一層驅動嗎?2、如果要將這一段RAM當作RAM盤存儲系統,該如何作呢?應該要加文件系統吧,如何加呢?
   解答這個問題前,先要說一下WINCE的地址映射機制。對於包含MMU(存儲器管理單元)的處理器來說,如ARM和x86,WINCE要求OEM在定製內核的時候填寫一個虛擬地址與物理地址映射關係的表,稱爲OEMAddressTable,在這個表中定義了所有物理設備的起始物理地址,對應的起始虛擬地址,地址空間大小,RAM就包括在其中(如果是x86平臺還要求RAM起始虛擬地址從0x80000000開始)。如果有多片RAM,應該在 OEMAddressTable中將它們定義在一起,使之地址連續。對於非OEM的開發者來說,他們拿到的是定製好的內核,不能做任何修改,如果在產品中外擴一片RAM,只能通過API函數通知操作系統增加一條虛擬地址與物理地址映射關係表項。相關API函數有兩個,分別是 CreateStaticMapping和VirtualCopy。它們的相同之處是都用於建立物理地址和虛擬地址的映射關係。它們的不同之處是 CreateStaticMapping映射的虛擬地址範圍在0xC400 0000 到 0xE000 0000之間,這個範圍只能由內核訪問,一般用於ISR訪問,因爲ISR只能訪問靜態映射的虛擬地址空間,不能用VirtualCopy。 VirtualCopy通常和VirtualAlloc配合使用,映射的虛擬地址空間在0x8000 0000以下,一般用於驅動程序和應用程序訪問。  
1)、應用程序要訪問這片RAM,和驅動程序訪問方法一樣,調用VirtualAlloc和VirtualCopy。  
2)、可以做一個流驅動程序專門用於讀寫這片RAM,這樣所有應用程序就可以通過調用流驅動接口函數來訪問,非要加文件系統也是可行的,通過修改註冊表就可以做到,但是麻煩一些。  

13、我怎麼能在PB左邊的定製平臺加進我的驅動呢?   
兩種辦法:  
1)、在platform.bib或者project.bib的MODULES部分添加一條語句,例如:  
MyDriver.dll       C:/Driver/MyDriver.dll                     NK SH  
這樣編譯內核的時候就會把你的驅動DLL文件添加到內核中,如果有註冊表需要設置,在platform.reg或者project.reg中添加註冊表內容。  
2)、通過製作.cec文件來添加驅動,製作.cec文件的優點是隻需製作一次,以後就可以通過將.cec文件導入到PB的Catalog中,象PB自帶的feature一樣通過菜單“Add to OS Design”添加到左邊的內核工程中。  

14、 WINCE有沒有相對路徑概念?如果沒有如何得到當前模塊的路徑?  
     1) 、WINCE沒有相對路徑概念,只有絕對路徑,所以凡是涉及到路徑均爲絕對路徑。  
     2)、調用API GetModuleFileName,傳遞一個模塊的實例句柄就能夠得到模塊的絕對路徑。  

15、   怎樣讓 POCKET WORD打開*.dat格式(裏面都是數據)的文件?
     兩種辦法:  
     1)、調用API ShellExecuteEx,在結構體SHELLEXECUTEINFO中添加.dat文件的路徑。  
     2)、調用API CreateProcess,在第二個參數中設置.dat文件的路徑。  

16、 x86 Rom Boot Loader真的可以實現嗎?它確實能代替BIOS啓動計算機?   
   Rom Boot 被設計存放在Flash/EEPROM中,也就是原來BIOS的位置,這樣當上電後CPU到固定地址執行代碼,也就是執行了Rom Boot的代碼,它對整個硬件系統進行初始化和檢測,並且支持通過網卡從遠程機器上下載nk.bin或者從本地IDE/ATA 硬盤的活動分區中尋找nk.bin文件加載。Rom Boot的優點就是引導並且加載速度快,而且它自身完成了所有的操作,這樣就不用BIOS、MSDOS,更不用Loadcepc了。  
  
17、 對於x86 Rom Boot Loader,如何Build得到Romboot.rom?   
   1)、在PB中打開一個內核工程(x86的)
   2)、單擊PB菜單“Build”-“Open Build Release Directory”
   30 、用cd命令進入 %_WINCEROOT%/Platform/Geode/Romboot 4、build  
  
18、如何設置、更改顯示分辨率  
     能否設置、更改顯示分辨率由顯示驅動程序決定,而沒有統一的標準。例如CEPC,在啓動的時候可以通過設置loadcepc.exe的參數 /L來決定WINCE啓動後的顯示分辨率,這是由於顯示驅動“VGA Linear Framebuffer”支持,而Geode可以通過在定製內核時修改註冊表項來決定WINCE啓動後的顯示分辨率。  
  
19、 幾個硬件使用同一個IRQ,那麼發生中斷的時候系統怎麼判斷到底是哪一個硬件發生的中斷呢?ISR裏面又應該怎麼控制呢?   
     Windows CE支持多個設備中斷共享一個IRQ,當一個共享IRQ發生時,CE內核的異常處理程序檢測設備特定的寄存器,因爲大多數設備都有一個單獨的寄存器用於表示設備的活動狀態,所以通過遍歷共享這個IRQ的所有設備的寄存器就可以判斷哪個設備發生中斷。nk.exe加載一個giisr.dll,這個.dll是微軟提供的,它其實是第一個可安裝ISR。默認CE內核就是調用這個dll來檢測寄存器狀態的,當然OEM可以編寫自己的.dll。  
     CE內部有一個ISR鏈,也就是可安裝ISR。因爲CE允許OEM添加自己的ISR處理程序,所以ISR被設計成一個鏈表。排在前面的ISR比後面的 ISR優先處理中斷,如果當前ISR能夠處理當前中斷,那就返回中斷ID由IST處理或者返回SYSINTR_NOP,如果當前ISR不能夠處理當前中斷,那就返回SYSINTR_CHAIN讓下一個ISR處理。  
  
20、請問在wince中如何在內核中增加一個與/windows同級的目錄?   
     在platform.dat或者project.dat中添加語句。例如要創建根目錄下子目錄Program Files,語句如下:  
     root:-Directory("Program Files")
21、 文件格式如下所示,我想把每行的4個值讀到4個變量中,用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 );  
  
22、GWES組件的功能有哪些?  
     GWES不僅負責GDI、窗口、消息,還負責管理本機設備驅動程序,負責加載顯示、鍵盤鼠標、觸摸屏驅動程序,而且GWES本身包含電源、LED驅動程序。  
  
23、如何在PB中預先設定好存儲內存和程序內存的大小,我想多劃分一些空間給程序內存?  
   兩種辦法:  
   1)、在定製內核時在config.bib文件中設置FSRAMPERCENT = number,具體number可參考標題爲“FSRAMPERCENT ”的幫助文檔。這種辦法是修改內核的設置,所有一直有效。  
   2)、在應用程序中調用API SetSystemMemoryDivision,如果函數返回SYSMEM_CHANGED表示成功,如果返回SYSMEM_MUSTREBOOT表示需要熱啓動纔能有效。這種辦法需要每次啓動後調用API纔有效。  
  
24、 如何取消鼠標光標?  
   通過取消SYS變量來實現此目的,在PB命令行下鍵入“set SYSGEN_CURSOR=”,然後回車確認。  
  
25、EVC下調用TextOut如何編譯會出錯?  
     類似這樣的問題很多,這是因爲EVC的幫助文檔內容有錯誤。可能EVC的幫助文檔內容是從桌面Windows幫助文檔複製過來的,所以很多API函數還有例子代碼都有錯誤,例如幫助文檔中包含一個API函數的說明,但是實際編譯的時候提示沒有這個API,有的例子代碼採用ANSI字符串,而WINCE的 API都是寬字符版本,造成直接複製過來編譯失敗。  
     因爲MFC for WINCE的CDC類中沒有TextOut成員函數,所以編譯會出錯,可以用其它類成員函數ExtTextOut或者DrawText替換。  
  
26、我如何將我的dll軟件讓現有的ce系統認可?儘管我也知道應該使用signfile.exe程序進行簽名,但是我並不知道那個ce系統認可的簽名應該是啥  
     如果你說的WINCE系統內核已經加入了簽名認證機制,那麼沒有私鑰對你的DLL文件簽名肯定是無法運行在此內核中的,一般簽名密鑰的密鑰長度都是1024位,很難破解。  
  
27、如果查看WINCE註冊表中的內容?  
   兩種辦法:  
   1)、建立同步後,用EVC自帶的工具“Remote Registry Editor”打開查看。  
   2)、從網上下載註冊表查看工具,放到WINCE設備中。  
  
28、調用directshow出現鏈接錯誤,如何解決?  
player.obj : error LNK2001: unresolved external symbol _IID_IVideoWindow  
player.obj : error LNK2001: unresolved external symbol _IID_IMediaControl  

這是因爲鏈接器沒有找到合適的.lib文件。兩種辦法:  
1)、在EVC菜單Tools—options—directories 裏把library files的路徑重新調整一下。如果你只安裝了EVC自帶的Standard SDK而沒有其它SDK,可以指定WINCE目錄中的.lib文件路徑,例如D:/WINCE500/PUBLIC/DIRECTX/OAK/LIB /X86/RETAIL。注意CPU的類型。  
2)、安裝SDK,前提是導出SDK的PB內核工程必須包括DirectShow或者其它組件。  
  
29、在PB的config.bib文件中,“IMGFLASH”表示什麼意思呢?  
     表示能夠刷NK到ROM中,具體請查看標題爲“IMG Environment Variables”的幫助文檔。  
  
30、x86平臺如何映射各種地址空間?如何編寫中斷服務例程?  
如果是x86平臺,可以調用HalTranslateBusAddress轉換物理總線地址到物理系統地址,調用 HalTranslateSystemAddress轉換物理系統地址到邏輯總線地址,也可以不調用這兩個函數,因爲x86平臺除32位物理地址外還有 16位的IO地址空間,對於16位的IO地址空間,可以直接調用WRITE_PORT_UCHAR或者READ_PORT_UCHAR等函數直接讀寫端口。對於32位物理地址可以調用VirtualAlloc和VirtualCopy來映射。這樣做思路清晰,簡單明瞭。  
在x86平臺要實現ISR,有如下幾個步驟(以Geode BSP爲例):  
1)、用SETUP_INTERRUPT_MAP宏關聯SYSINTR和IRQ。以“SYSINTR_”爲前綴的常量由內核使用,用於唯一標識發生中斷的硬件,又稱爲中斷ID。在Nkintr.h文件中預定義了一些SYSINTR,OEM可以在Oalintr.h文件中自定義SYSINTR。  
2)、用HookInterrupt函數關聯硬件中斷號和ISR。這裏提到的硬件中斷號爲物理中斷號,IRQ爲邏輯中斷號。在InitPICs函數的最後調用了HookInterrupt函數,如下:  
for (i = 64; i < 80; i++)  
HookInterrupt(i, (void *)PeRPISR);   ///用ISR關聯16箇中斷號  
3)、調用InterruptInitialize函數關聯SYSINTR和IST創建的事件對象,也是IST等待的事件對象。詳細內容請參考Geode BSP源碼。  
   在x86平臺要實現可安裝ISR,先調用LoadIntChainHandler函數註冊在註冊表中指定的ISR DLL,然後填充GIISR_INFO結構體並調用KernelLibIoControl函數將此結構體傳遞給可安裝ISR。詳細內容請參考WINCE幫助文檔或者我著的《Windows CE下驅動開發基礎》。  
  
31、修改了WINCE自帶的驅動程序後如何編譯?如果是自己開發的驅動程序如何編譯?  
1)、分爲IDE方式和命令行方式。  
IDE方式的編譯很簡單,以PB5.0爲例,打開定製內核的工程,在左邊的“workspace”—“FileView”中找到你已經修改了的目錄,然後單擊右鍵彈出菜單,在菜單中選擇“Build and Sysgen Current Project”,這樣PB就會編譯指定的目錄中的項目源碼文件,然後執行sysgen命令根據source文件中的內容生成目標文件並複製到當前內核工程目錄下。  
命令行方式的編譯需要打開“Build OS”—“Open Release Directory”,以cd命令進入你已經修改的驅動程序目錄中,然後鍵入“build –cfs”,然後鍵入“sysgen –p 項目名稱”,一般項目名稱爲source文件中的“TARGETNAME”。  
2)、如果想完全自己開發驅動程序,建議直接採用EVC或者PB來編寫編譯。  
  
32、開發PCI設備驅動時,InterruptInitialize函數的第一參數是否是PCI卡配置空間信息中的InterruptLine 參數?是否需要在HKLM/Drivers/BuiltIn/PCI/Template 加一個自己的 subkey,並填寫相應內容?如何填?  
1)、InterruptInitialize的第一參數是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"  
而這些信息就來自於你執行pcienum.exe的結果。  
  
33、編譯器報錯:error C2065: 'CFileFind' : undeclared identifier,如何解決?  
   MFC for WINCE版本沒有CFileFind類,所以要查找文件只能調用API FindFirstFile 和FindNextFile。  
  
34、如何設置WINCE系統字體、字號?如何設置自己開發的軟件的字體、字號?  
1)、系統字體通過註冊表設置。如下:  
[HKEY_LOCAL_MACHINE/System/GDI/SysFnt]   ///系統字體  
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)、創建字體時把字體高度參數設置大點就可以了。如CFont::CreateFont(nHeight,...),也可以在LOGFONT結構中設置字體高度或者字體種類。如果是控件,調用控件的SetFont成員函數。如果是直接畫,在OnPaint響應函數中調用SelectObject選字體到 DC。  
  
35、 nk.bin和nk.nb0有什麼區別?  
   這裏提到的bin是一種二進制鏡像格式,以片斷(section)爲單位組織數據,每個片斷都包括一個頭,頭裏指定了起始地址,長度,校驗值。 Platform Builder調用工具將WINCE內核所有文件以bin格式合併成一個文件,默認文件名爲nk.bin。BootLoader又以同樣的格式將 nk.bin分解成多個文件放到RAM中。可以在命令行中鍵入“viewbin nk.bin”來查看bin文件中具體包括了哪些內容。鍵入Cvrtbin命令轉換.bin格式文件爲.sre格式或者.abx格式。  
   nb0格式是原始的二進制鏡像,它不包括頭,一般情況下將內核下載到設備的RAM中運行都採用nb0格式。要生成nbx格式的文件,需要在相關.bib文件中確定如下值:ROMSTART、ROMWIDTH、ROMSIZE。  
  
36、在不採用硬件計時器的情況下如何創建更精確的計時器?最精確週期能否達到1毫秒?  
對於精確值的要求不同,所採用的辦法不同。以下闡述幾種辦法。  
1)、在單線程中循環調用API Sleep函數,Sleep函數精確程度爲如果Sleep(N),那麼實際睡眠時間在N到N+1毫秒之間。而且還要注意調用Sleep的線程優先級的問題。如果任務過多並且此線程優先級低,那誤差就更大些。  
2)、調用API QueryPerformanceCounter函數,舉例如下:  
LARGE_INTEGER   liFrequency;  
if (QueryPerformanceFrequency(&liFrequency))   // 查詢系統時鐘的頻率,這裏將返回1000  
{  
   liFrequency.QuadPart /= 1000;    
   LARGE_INTEGER   liTimeOut;    
   if (QueryPerformanceCounter(&liTimeOut))   //得到截至到當前累計發生的系統時鐘中斷次數  
   {  
       liTimeOut.QuadPart += liFrequency.QuadPart;   ///計算下一秒到來時總的中斷次數是多少  
       LARGE_INTEGER   liCurrent;  
       do  
       {          
         QueryPerformanceCounter(&liCurrent);     // 循環查詢累計的的中斷次數  
       } while (liCurrent.QuadPart < liTimeOut.QuadPart); ///到達下一秒  
   }  
}  
調用QueryPerformanceCounter同調用Sleep在本質上都是一樣的,都是在單線程中無限循環等到週期一到執行任務,相比較 QueryPerformanceCounter要比Sleep更精確些,越精確就越要求線程的優先級,保障線程能夠正常得到處理器。  
3)、以上辦法難以保證週期精確到1毫秒並且WINCE系統穩定地運行,所以要從中斷入手。以x86平臺爲例,先在Timer.c中將默認的 SetTimer0(TIMER_COUNT)中的TIMER_COUNT /=2,SetTimer0函數負責設置系統時鐘的頻率,默認1毫秒發生一次中斷,如果除以2就是0.5毫秒發生一次中斷。然後在fwpc.c文件中修改 ISR函數PeRPISR,因爲原來默認是1毫秒發生一次中斷,在處理INTR_TIMER0時系統負責累計計數、管理線程的調度,返回相應的 SYSINTR值,而我們沒有辦法再添加代碼返回自己定義的SYSINTR值,所以現在要修改原來的處理代碼,例如設置一個BOOL型變量,TRUE就執行原來默認的代碼,而FALSE就返回我們自己定義的SYSINTR值,這樣即不影響原來的ISR處理,又加入了我們的中斷響應代碼。ISR返回我們定義的SYSINTR後WINCE內核激活相對應的EVENT事件,我們就可以在我們編寫的IST裏處理任務了。  
  
37、flash中存放了BootLoader和內核鏡像,如何把剩餘flash部分劃分爲一個存儲區域供應用程序讀寫?  
   以WINCE提供的驅動(FAT文件系統和MSFLASH驅動)來舉例說明。如果採用默認common.reg中的註冊表設置,那麼MSFLASH驅動默認把整個flash作爲存儲區域來讀寫,這不符合問題的要求,所以必須告訴MSFLASH驅動程序可供讀寫的區域的起始地址和長度。以下是一個註冊表例子:  
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/FASLD]  
     "Dll"="fasld.dll"         ///實際Flash存儲器的驅動程序  
     "Order"=dword:2       ///該驅動程序相對於其它驅動程序的加載順序  
     "Prefix"="DSK"         ///前綴  
     "Ioctl"=dword:4         ///IOCTL碼,設備管理器加載驅動的時候調用IOControl函數,傳遞這個IOCTL碼。  
"Profile"="MSFlash"     ///Profile名稱,也就是[HLM/System/StorageManager/Profiles/MSFlash]  
///當設備管理器加載此驅動程序的同時發送通知給系統,IClass(GUID)的值表明這是一個存儲設備的驅動程序。  
"IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"    
     "MemBase"=dword:00000000     ///Flash中可供讀寫區域的起始物理地址,也就是Flash的首地址+偏移量  
     "MemLen"=dword:00000000     ///Flash中可供讀寫區域的長度  
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/MSFlash]  
     "DefaultFileSystem"="FATFS"   ///MSFlash驅動默認採用的文件系統  
     "PartitionDriver"="mspart.dll"     ///採用的分區驅動程序  
     "MountAsRoot"=dword:1         ///此目錄作爲文件系統的根目錄  
     "Folder"="NOR Flash"           ///目錄名稱  
     "Name"="FLASH Disk Block Device"   ///Flash驅動名稱  
"PartitionDriverName"="MSPART" ///分區驅動名稱  
"AutoMount"=dword:1         ///自動裝載檢測到的分區  
     "AutoPart"=dword:1             ///自動分區  
     "AutoFormat"=dword:1           ///自動格式化分區  
[HKEY_LOCAL_MACHINE/System/StorageManager/AutoLoad/MSFlash]  
     "DriverPath"="Drivers//BuiltIn//FASLD"     ///Flash驅動在註冊表中的位置  
     "LoadFlags"=dword:1                 ///這個值可以被設置爲0、1、2。1表示同步加載,其它表示異步加載  
     "Order"=dword:0  
[HKEY_LOCAL_MACHINE/System/StorageManager/FATFS]  
     "FriendlyName"="FAT FileSystem"     ///文件系統名稱  
     "Dll"="fatfsd.dll"                   ///文件系統驅動程序  
     "Flags"=dword:00000064             ///標誌,詳見幫助文檔  
     "Paging"=dword:1                   ///是否分頁  
     "EnableCache"=dword:1               ///是否允許緩存數據  
     "CacheSize"=dword:0                 ///指定緩存大小,0表示默認  

38、驅動程序如何發通知給應用程序?  
   這裏介紹一下常見的兩種辦法。  
   1)、驅動程序調用API SendNotifyMessage,發送特定的消息給應用程序,這就要求應用程序要有消息循環機制並且要事先做好消息的處理。參數1爲窗口句柄,可以設置HWND_BROADCAST表示廣播消息。要注意的是不要在參數中傳遞指針(虛擬地址),因爲執行驅動程序的線程和應用程序並不在同一個進程空間中。解決辦法可以利用內存映射文件技術,比如在驅動程序中創建一個內存映射文件對象,申請一塊物理內存,然後把對象名稱和內存長度傳遞給應用程序,應用程序打開同名的內存映射文件對象,讀取裏面的數據。對象名稱可以事先協定好,也可以通過註冊表來傳遞,內存長度是32位值,通過消息參數就可以傳遞,也可以通過註冊表來傳遞。另外一種解決辦法是在定製內核時候預留一塊物理內存,這樣驅動程序和應用程序都可以通過VirtualAlloc和VirtualCopy 來映射到同一塊物理內存,其原理同內存映射文件技術一樣,但是這塊物理內存不具備通用性。最後一個辦法是應用程序事先將一個緩衝區地址傳遞給驅動程序,驅動程序調用MapPtrToProcess映射應用程序傳遞過來的地址,當驅動程序調用SendNotifyMessage後應用程序可以直接到該地址中讀取數據。  
   設備管理器就是調用此函數廣播WM_DEVICECHANGE消息的。另外WINCE的一個例子程序RNAApp在撥號連接建立的時候也是調用這個函數廣播WM_NETCONNECT消息的。  
   2)、驅動程序調用API CeEventHasOccurred指明一個事件A發生,在此之前應用程序調用API CeRunAppAtEvent將驅動程序指明的A事件和一個應用程序名稱相關聯,或者和一個事件B相關聯。這樣當A事件發生時,如果指明和一個應用程序名稱關聯,那這個應用程序就會被啓動。如果指明瞭和一個事件B相關聯,那麼等待事件B的線程將被激活。如果想了解當前系統內部所有驅動程序支持哪些類似事件A的事件,調用API CeNotifyPublic_FilterEvent,在該API的幫助文檔裏也列舉了常見的事件,例如 NOTIFICATION_EVENT_NET_CONNECT和 NOTIFICATION_EVENT_NET_DISCONNECT。  
  
40、 EVC創建的工程名稱如果用中文就出錯,該怎麼辦?  
   用EVC創建的工程名稱如果爲中文將導致資源文件打不開和編譯出錯,可以改資源文件名稱爲英文,再編輯.rc文件中的資源文件名稱。但建議儘量不要用中文爲工程名稱。  
   作爲習慣,應該在EVC創建一個工程後,立刻在“project”—“settings”中設置資源的語言屬性,然後在“resource view”中設置每個資源的語言屬性,這些工作做完後再修改資源就沒有問題了。有人詢問對話框的標題爲亂碼,其原因就是在沒有修改語言屬性的情況下設置標題爲中文。

41、WinCE下如何讀寫幾百兆的大文件呢? 使用內存映射文件嗎?  
   一般嵌入式設備配備128MB物理內存就算頂級的了,所以要讀寫幾百MB的文件用內存映射文件技術是最好的選擇了。映射文件之後讀數據是非常容易的,要注意的是寫數據,內存映射方面的API沒有提供改變文件長度的功能,所以要在關閉映射文件對象後用文件API改變文件長度。  

42、請問如何改系統調度的默認時間片值?  
   更改schedule.c文件中的dwDefaultThreadQuantum 變量,然後重新編譯該文件並SYSGEN。調用API CeGetThreadQuantum就知道更改是否生效。  
  
43、如何讓系統加載自己寫的驅動程序?  
兩種辦法:  
1)、在[HKEY_LOCAL_MACHINE/Drivers/BuiltIn]下添加註冊鍵。  
2)、在應用程序中調用ActivateDeviceEx。  
  
44、在一些文件中用分號來表示註釋,例如下面的內容  
; @CESYSGEN IF SERVERS_MODULES_HTTPD  
; @CESYSGEN ENDIF  
在“CESYSGEN...”前加了“@”,有沒有什麼特別的含義?  
     在WINCE的一些文件中,用“;”作爲註釋並在註釋文字中用@CESYSGEN作爲標記,後面接條件語句。Cefilter.exe工具負責按照條件來篩選文件內容,所以不要輕易地刪除包含@CESYSGEN的註釋語句。  
  
45、通過串口建立ActiveSync聯接,串口線用三線的可以嗎?  
   不可以,因爲用串口同步時要用到其餘口的狀態。  

46、 WINCE是否支持MAPI?  
   不支持。

47、如何旋轉屏幕顯示的內容?  
   例子代碼如下(前提是顯示驅動程序支持旋轉):  
DEVMODE   devmode = {0};  
devmode.dmSize = sizeof(DEVMODE);  
devmode.dmDisplayOrientation = DMDO_90;       ///垂直模式  
devmode.dmFields = DM_DISPLAYORIENTATION;  
ChangeDisplaySettingsEx(NULL, &devmode, NULL, 0, NULL);   ///改變顯示的設置  
CRect   rcWorkArea(0, 0, 320, 240);     ///整個屏幕尺寸  
///設置客戶區大小並廣播消息,這樣所有軟件也就隨之更改顯示  
SystemParametersInfo(SPI_SETWORKAREA, 0, (void*)&rcWorkArea, SPIF_SENDCHANGE);  
  
48、請問如何修改字形緩存的容量?  
[HKEY_LOCAL_MACHINE/System/GDI/GLYPHCACHE]  
"limit"=dword:0400  
  
49、 如何得到從WINCE啓動開始到現在的時間?  
   調用API GetTickCount,得到的值爲32位整數,單位爲毫秒。  
  
50、如何調用WINCE的軟鍵盤?  
調用API SipShowIM(SIPF_ON),前提是內核加入了軟鍵盤組件。  
  
51、 基於HIVE的註冊表,如何在系統關閉前保存註冊表的數據到文件system.hv?  
調用API RegFlushKey函數。  
  
52、使用VirtualAlloc和VirtualCopy的時候需要注意哪些事項?  
   1)、VirtualAlloc的作用是申請虛擬地址空間,這肯定不是最終的目的,最終目的可能是申請物理內存、映射寄存器、提交文件等。沒有一個目的會在意虛擬地址空間的位置,所以儘量傳遞參數1爲0,也就是讓WINCE自動分配虛擬地址空間。VirtualAlloc分配地址空間實際上是以64KB爲單位,所以要指定申請的虛擬空間的首地址的話,參數1應該爲64KB的整數倍,申請的長度也應該爲64KB的整數倍,即使你不需要那麼大。  
   2)、VirtualCopy的主要作用是映射物理地址空間,如果參數2爲物理地址,那麼最後一個參數要添加PAGE_PHYSICAL,參數2必須是 256的整數倍。如果參數2爲虛擬地址(0x80000000以上),那麼最後一個參數就不要添加PAGE_PHYSICAL,WINCE內核會根據這個虛擬地址找到對應的物理地址。  
  
53、驅動程序和應用程序之間傳遞數據時何時調用MapPtrToProcess?  
   因爲設備管理器負責加載驅動程序DLL,這意味着當應用程序調用驅動程序接口函數的時候,WINCE內核會將調用驅動程序接口函數的線程轉移到設備管理器的進程空間然後執行具體的驅動程序代碼,應用程序和設備管理器處於兩個進程空間,這就造成設備管理器無法訪問應用程序傳遞的指針(虛擬地址),所以當我們在應用程序中傳遞指針給流驅動程序接口函數時,WINCE內核從中作了一個地址映射,例如ReadFile、WriteFile、 DeviceIoControl函數的參數凡是指針都經過了映射才傳遞給驅動程序,所以很多驅動程序開發者並不瞭解其中的奧祕就可以編程了。但是如果參數是一個指向一個結構體的指針,而結構體裏包括一個或多個指針,那麼WINCE內核並不負責映射,所以就需要開發者在驅動程序接口函數中調用API函數 MapPtrToProcess來映射地址。例如:pPointer_retval = MapPtrToProcess(pPointer, GetCallerProcess());  
  
55、 如何判斷可插拔的設備是否存在?  
   1)、通過查找註冊表的值。凡是由API ActivateDeviceEx加載的驅動程序都在[HKEY_LOCAL_MACHINE/Drivers/Active]鍵下有註冊鍵,通過查找 “name”或者其它鍵值就能夠找到。設備管理器就調用這個API。如果是PCI設備,在註冊表[HLM/Drivers/BuiltIn/PCI /Instance]下查找關鍵字,例如[HLM/Drivers/BuiltIn/PCI/Instance/WaveDev1],說明音頻驅動已經加載。  
   2)、調用驅動程序接口函數,根據返回值或者執行結果來判斷。  

56、如何做到通過串口過來的一個信號啓動自己開發的應用程序?  
   創建一個線程負責等待串口過來的信號,調用API SetCommMask設置要等待的信號種類,具體可以等待的信號種類參見參數2的說明。然後再調用API WaitCommEvent函數等待這個信號,接收之後再調用API CreateProcess啓動應用程序。  
  
57、在WINCE中如何只能啓動應用程序的一個實例?  
   常用的兩種辦法:  
1)、如果應用程序實例創建了窗口,可通過API FindWindow函數通過窗口類名和窗口標題名稱來查找,前提是系統內不會出現窗口名稱重複的情況。  
2)、應用程序初始化的時候創建一個事件或互斥等內核對象,因爲內核對象是由內核創建,名稱在系統內唯一。  
  
58、能不能自己編輯一個數字簽名文件導入到手機上,這樣就可以用這個簽名籤自己的程序了?  
   WINCE的內核簽名機制的用途是限制非法的可執行模塊EXE、DLL等在設備上運行。要求內核的加載模塊用公鑰驗證請求加載的EXE、DLL的簽名是否合法,而這個公鑰是在定製內核的時候加進去的,所以除內核的定製者以外的人無法修改這個驗證機制。  
  
59、 在WINCE下是否能夠得到某一進程使用的物理內存總量?  
   目前沒發現有這樣一個API能夠得到指定進程使用的物理內存總量。只有GlobalMemoryStatus能夠得到整個系統使用的物理內存總量。  
  
60、 應用程序如何控制lcd的亮度?如何獲得電池的電量?  
   從常見的平臺如Geode、三星ARM系列來看,的確在驅動方面沒有統一的控制LCD或者其它種類屏幕亮度的接口函數,所以只能根據具體平臺提供的接口來做。從幫助文檔來看微軟的帶有DirectDraw功能的顯示驅動程序的確有標準的增加亮度的接口函數,關於背景光參見標題爲“Enabling a Backlight”的幫助文檔。  
獲得電池電量有標準的接口函數GetSystemPowerStatusEx,前提是驅動程序和硬件都要支持


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/cfanlwn/archive/2009/10/28/4739141.aspx

本人也是WINCE的初學者,在此放在這裏供以後再看,也爲同樣的初學者提供方便,大家一起學習!加油!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章