MicrosoftWindows CE是緊湊的、高效的和可升級的作業系統,它被廣泛的應用在各種嵌入式式的產品中,從手持電腦到專門的工業控制器和消費用電子產品中。Windows CE已經通過了其自身的能力證明:它能夠滿足32位嵌入式式程式開發的需求。同樣重要的是: Windows CE使嵌入式式系統的設計者得以充分利用Microsoft的32位基於Windows的開發工具的全部的函數。
嵌入式的應用軟體選擇Windows CE的首要原因之一是Microsoft Win32應用編程介面(API)的廣泛應用。從運行在Microsoft WindowsNT作業系統下的高端伺服器到最小的台式機和內嵌式的應用中,WIN32 API幾乎是所有為面向Windows開發32位應用軟體的核心。
本文的目的是向那些開發基於Windows CE的新的嵌入式式系統的開發人員介紹WIN32 事件驅動編寫程式。 本文將:
概述32位Windows作業系統和WIN32編程模型。
介紹線程,事件和訊息是如何操作的。
給出Win32如何管理Windows CE的記憶體。
解釋 Win32意外操作的概念。
比較同步和不同步裝置的介面的不同的方法。
總結明確定義的API的優位。
本文並不是刻意要完全做Win32的編程指南,而是要介紹用Win32作為嵌入式式應用程式的開發工具。
簡介
對於全世界的成千上萬的程式開發人員來說,Win32程式模式很常見。WIN32是台式機或企業廣泛應用的強大目標,而且隨著Windows CE的湧現,它也成了嵌入式式系統的理想的程式介面形式。WIN32為Windows CE作業系統提供了一致的,文檔完備的並且函數強大的程式介面。
用WIN32在Windows CE平台開發的程式同其他的WIN32程式差不多;這意味著程式開發人員在開發新的面向Windows CE作業系統的應用程式的時候,能夠應用這些大量的WIN32的程式資源、第三代工具和外部的專門的技術。具有WIN32編程經驗的程式員會發現建立新的(維護已有的)面向Windows CE裝置(如手持電腦)的應用程式遠比建立類似的面向特殊的平台或其他應用不廣的嵌入式式的作業系統的應用程式簡單。
嵌入式式系統的設計者們很快意識到Windows CE的強大,並且以驚人的快速使這個作業系統與它們的新產品一體化。可是,許多嵌入式式軟體的開發人員對Windows的事件驅動程式的一般技術不熟悉。對於這些軟體開發人員來說,在他們開始他們第一次的基於Windows CE的項目之前,瞭解一些WIN32的基礎的知識是有好處的。
什麼是WIN32?
“WIN32”表示對於所有的Microsoft 32位平台的一種普通的應用編程介面(API)。這些平台通常指:
Windows 95, Windows 98
Windows NT
Windows CE
本文我們主要關注Windows CE作業系統,可是需要弄清楚的是大多數 Win32的應用編程介面對上面所有三種平台都適用。這種同用的應用編程介面的優位有很多:容易登入到應用程式中,有大量的已有程式的知識,範例和第三代軟體的資源。
平台的差別
WIN32的應用編程介面定義了你作為一個程式員有用的Windows平台。WIN32應用編程介面的目的是提供了一個常用的介面的設定,可是虛擬,不同的平台由於不同的特性及硬體的約束,其應用編程介面也不同。WIN32平台家族的一些成員支援全部的WIN32的應用編程介面(下簡稱API),而其他的只支援一部分的API。 為緊湊的、嵌入式式的應用軟體和小型裝置而設計的Windows CE,WIN32的API最受限制。儘管如此, Windows CE 的API也是足夠完善的,能夠處理實際的大量的進階的嵌入式式應用程式。
WIN32與Microsoft基本類庫(MFC)
用WIN32介面設計並不是建立32位基於 Windows的應用程式的唯一的途徑。另一種重要的途徑是可在WIN32與 Microsoft Visual C++開發環境使用的Microsoft基本類庫(MFC)。MFC為許多(不是所有)的WIN32的API進行了高度的封裝(圖1)。通常,MFC提供了代表重要的WINDOWS的使用介面物件的類,象視窗,對話方塊,畫刷,畫筆,和字型。MFC也為沒有任何使用者介面要求的嵌入式式應用軟體提供了相應的類。MFC類的成員函數調用WIN32API的函數,可以使複雜的應用程式的設計巧妙的簡化。
作為WIN32的程式員,你可以自由的選取使用C或C++和WIN32 API, 或者用C++與MFC。VISUAL C++開發系統對於所有的,包括 Windows CE 的WIN32的目標作業系統都支援以上的兩種開發系統。
本文直接介紹WIN32 API。應用 Windows CE下的MFC的詳細的訊息,參閱 Windows CE SDK文檔。
WIN32程式模型
WIN32是超越所有32位WINDOWS平台的常用和一致的(儘管並不全部相同)API。為了對WIN32 API有一個透徹的瞭解,以便高效的使用它的函數,瞭解一些底層作業系統的基礎十分重要。本節總結了32位作業系統和 Win32 API的最重要的概念,為你更深入的學習提供基礎。要得到更多更詳細的關於32位WINDOWS的體繫結構、 Win32 API、以及其他的程式設計的主題,你可以讀一本關於那個主題出版的書。Microsoft出版社能提供一些這樣的書籍;在本文的最後,列著部分這些書的條目。
Windows CE的核心和 Win32 API
那些對WINDOWS CE的人可能會有一個錯覺,認為它僅僅是現有的作業系統(如WINDOWS95)降級版。但事實上Windows CE是以小型的、高度使用者化的面向嵌入式式應用程式的作業系統開發起來的。在WINDOWS CE排除(或代替)了一些基於WINDOWS CE的應用軟體所不需要的作業系統特性的同時,它的核心也具有大量的其他Microsoft 32位的作業系統的最精華的東西。例如在Windows NT下, 所有的在Windows CE下運行所應用軟體都運行在有優先權的多任務處理環境下,在被全保護的記憶體空間裡。還有,象 Windows NT一樣,Windows CE支援本地統一的字元編碼標準碼字串,使它更適於國際推廣。可是,不象其他的32位WINDOWS平台,, Windows CE是十分緊湊和使用者化的,僅僅佔用小於200K的記憶體。
Windows CE的WIN32 API比其他的32位的Windows作業系統的WIN32 API要小;它只包括大約相當於Windows NT的半數的API。但是 Windows CE的WIN32 API也有其他系統所沒有的特性。例如:通知API,它能夠作業系統的層次,而不是在啟動並執行應用程式的層次上處理通知事件(如時鐘)。觸屏的API和對Windows CE的資料庫的內建的支援是其他的作業系統所沒有的。觸屏的API使用於觸覺敏感顯示器的螢幕校正和使用者互動的管理容易實現,而資料庫的API提供了快速簡捷的訪問緊湊的、一般用途的資料庫的工具。另一個關於Windows CE的鮮為人知的方面是它的高度的模組化;嵌入式式系統開發人員(用Microsoft Windows CE內含的面向Visual C++的軟體包)能夠建立一個對於它們的獨特的硬體平台和應用軟體使用者化了的Windows CE的版本。
Windows CE作業系統為設計提供了全新的設計環境。Windows CE的開發人員幾乎不需要支援原有的應用程式或裝置,所以作業系統在設計時可以考慮到應用一些最新的思想和應用程式,並且應用最先進的嵌入式式的32位微處理器產品作為它的硬體目標平台。
這對於一個使用Windows CE平台的WIN32 API的使用者來說意味著什麼呢?這意味著對於現代的、32位的嵌入式式系統,它是一種更簡單的API,更加最佳化的目標作業系統。下面,我們將研究一些重要 的WIN32 API和Windows CE作業系統的內部的內容。
程式和線索
瞭解WIN32 API和Windows CE作業系統的底層內容的第一步就是瞭解多任務和多線索索應用程式是如何組織的。WIN32術語中,程式被定義成一個正在運行中的程式執行個體。象其他的32位Windows 平台一樣,Windows CE是一個多任務的作業系統,在一個運行中的程式裡,它支援執行多個線索所。
對於嵌入式式的應用程式,Windows CE的多線索索執行能力是它函數的重要的體現。這樣就使WIN32嵌入式式程式開發人員優先考慮WIN32的線索索的創立與同步。
WIN32的線索索的處理同其他常用的嵌入式式的作業系統是有區別的。不象Unix或其派生的系統,32位Windows平台從一開始設計就支援多線索索應用程式。線索索管理(時序安排,同步和資源管理)由核心來完成,程式開發人員利用函數裝入核心(通過WIN32 API訪問)來建立和管理他們應用程式中的線索索。
例如,如果一個嵌入式式應用程式必須監視多個輸入裝置並且在監視到一個或多個裝置上不同步發生的事件的時候要作出恰當的反映。更進一步,如果這樣一個程式也需要更新一些共用的資源(如全域資料結構,磁碟上的檔案,或其他裝置)來作為與相關裝置事件的反映。象這樣的一個程式需要一個可靠的線索索管理系統。這恰恰是WIN32 API能夠提供的函數:多個線索索能夠快捷並且容易的用WIN32 API線索索建立介面建立;同步線索索(多個線索索同時訪問一個資料)可以通過不同的方式完成,包括關鍵的段,有名稱和沒有名稱事件,以及互斥的目標。
Windows CE 被設計成在執行這些同步時佔用最少的程式資源。這位對那些函數不強大的開發人員來說十分重要;因為核心來負責線索索的管理,不需要使用另外的處理器來迴圈檢測程式或線索索完成,以及執行其他的無用的應用程式層次上的線索索管理。核心已構建好如何管理若干的線索索並且使程式高效地進行的程式。
對於包括若干個程式的應用程式,WIN32 向用於線索索、程式管理和同步提供了一套的完備的處理方法。這些線索索管理特性非常適於嵌入式式應用程式軟體,並且對Windows CE開發人員是容易得到的。
訊息
在32位windows平台上啟動並執行程式更專門化,程式的線索依賴於訊息來初始化程式,控制系統資源並且與作業系統和使用者通訊。 windows訊息有各種各樣來源 ,包括作業系統,使用者活動諸如鍵盤輸入、滑鼠、觸到螢幕,以及其它啟動並執行程式或者線索。
當訊息被送到線索時,這條訊息被放置在訊息佇列中等待最後處理(圖3)。每一條線索擁有完全不獨立於其它線索所擁有的訊息佇列的訊息佇列。線索一般有不斷啟動並執行訊息迴圈,恢複和處理訊息。當隊列地沒有訊息,並且線索不從事於其它任何活動,系統掛起線索,以節省中央控制器資源。
訊息也能用於控制目的,初始化你的應用程式中各種類型的程式,並且他們能利用訊息參數傳遞資料。例如,線索可能收到觸屏被啟用的訊息,訊息參數可以表明X和Y為使用者行動的座標。 在另一種類型的訊息中,參數可以包括指標或者指向資料結構、視窗或其他對象的控制代碼。
中斷處理
作為一嵌入式的的軟體開發人員,你可能最關心windows CE訊息的處理規則是如何影響你的外部系統介面的時序的。windows CE通過細心設計和準確的衡量以保證其中斷時序以及其它相關的特位與嵌入式式的系統設計是適用的。
嵌入式應用程式經常有時間臨界的裝置介面需要,需要發現並且在一最小的規定的時間之內對裝置和系統事件作出反應。 為了支援這樣應用程式, windows CE包括高度最佳化中斷傳送,優先順序和服務系統。
在windows CE核心中 ,中斷處理分成兩個明顯的部分:中斷服務程式(ISR )以及中斷服務線索(IST )。這個系統的目的是使ISR 儘可能小和快。在硬體的層次上,每一中斷要求(IRQ )線索路與一特定的軟體ISR聯絡。當被觸發時,給定的ISR除了通知核心IST的位置外,還做少量的工作。一旦IST 被初始化(儘管沒必要完成),系統便準備好接受下一中斷並且處理下一中斷。
每一個中斷有一個優先順序與他們相聯絡。 windows CE為確定的線索時時序,利用基於優先順序的時間片段演算法。與每一ISR 被聯絡的IST 是正常的線索,因此為IST設定優先權以滿足應用程式的時序需要是應用程式軟體開發人員的責任。
這種將ISR 和IST在中斷程式中分開處理最終結果是,典型的中斷等待時間被大大地減少了,在中斷程式中發生不可接受的延遲的可能性也大大減少。此外, 嵌入式式軟體包 和windows CE核心的特性使有可能按習慣定製中斷時序和優先順序,以滿足特定應用程式的需要。 Windows CE和其使用的時間臨界、即時應用程式在另一篇文章中包括比本文更詳細的內容,文章名為《 Real-time Systems with Microsoft Windows CE》。
記憶體管理
WIN32 API為向開發人員提供了一套完備的和一致的介面。 當開發絕大部分應用程式的時候,軟體開發人員不需要考慮特定記憶體結構。 然而對於許多嵌入式應用程式,特別是那些有嚴格的記憶體資源約束或者臨界時序的要求的,對記憶體被管理的方法有好的理解是重要的。
Windows的記憶體的一般結構對於不同的32 位Windows平台是不同的,並且特殊的細節結構在同一32 位Windows作業系統下不同的處理機之間也不同。 (例如,Windows NT的記憶體結構在X86 平台上與在DEC Alpha 平台上的用法十分不同 。) 對於這段的討論,我們將專門集中在Windows CE作業系統的部分中進行。
Windows CE的儲存結構
像其它的32 位Windows平台一樣,Windows CE作業系統也有虛擬記憶體的特性。記憶體總在某一時間被分配給應用程式一頁,頁的大小由系統設計者決定(並在作業系統為目標硬體平台建立時被指定)。例如 在手持電腦,記憶體頁大小是典型的1KB 或者4KB 。
在初始化期間(匯入),Windows CE創造一個獨立的被所有程式共用的4GB 虛擬位址空間。當程式引用一個虛擬地址時,它被核心記錄在物理的記憶體上。 這使得應用程式軟體開發人員不必去考慮目標系統記憶體的物理的布局。雖然所有程式共用單一地址空間,應用程式仍然可避免相互誤用。Windows CE 通過改變每頁的保護來保護程式記憶體,而不是分配給每一程式不同地址空間。 作為應用程式開發人員,你可能不會太在乎目標系統的記憶體的物理的結構。 記憶體可以全部是隨機存取記憶體,或者它可能包括快閃記憶卡或者硬碟。Windows CE作業系統為你管理記憶體資源,同時WIN32 API 向你提供必要的分配、使用和釋放的記憶體的介面。
然而,作為一個嵌入式的系統的設計者,你將需要細心考慮將在你新的硬體平台上執行的應用程式的記憶體需要,並且全面考慮成本、速度和可靠性,平衡各種目標的衝突。 如果你為使用Windows CE開發一個新的硬體平台 ,Windows CE的面向Visual C++ 的嵌入式軟體包包括資源可以協助你做出這些決策,並且從而構成作業系統。
無論你的系統記憶體的配置如何,ROM(唯讀記憶體)將佔用十分重要的地位。不同於其它的32位Windows作業系統,Windows CE作業系統的代碼在唯讀記憶體中,並且在那個唯讀記憶體中原地執行。 依據你的產品需要,你也能選擇在唯讀記憶體中放置應用程式代碼。 例如,Pocket Word,Pocket Excel和其它應用程式程式,包括在手持電腦唯讀記憶體中被提供的。
儲存在ROM中的程式組在Windows CE下當地執行,所以嵌入式系統的設計者能夠只佔用很少的RAM用於堆棧儲存的需要。相應地,你的嵌入式應用程式可以利用RAM既作為程式的記憶體又可作臨時儲存空間。
為了進一步的增加應用程式軟體的效能, Windows CE採用按需求將記憶體分葉;作業系統僅僅需要解壓縮並且裝入基於RAM的一小部分程式準備執行。ROM和 基於RAM的程式的靈活性與速度意味著基於Windows CE的裝置能夠被構造成各種記憶體結構形式。
手持電腦的記憶體結構
典型的Windows CE的硬體平台的記憶體結構是與基於 Windows系統的台式電腦的記憶體結構十分不同的。 為了知道記憶體通常如何在Windows中被處理的 ,考查基於Windows CE的最普通的代表性的裝置-手持電腦,是很有用的。
在手持電腦中,RAM被分割成兩個主要的部分:儲存記憶體和程式記憶體。 向兩部分分配的RAM的量能被手持電腦使用者修改(在限制範圍內)。 這個RAM的劃分圖4所示。
在手持電腦中的儲存記憶體類似於台式電腦的硬碟RAM。 它被用來儲存資料和非系統應用程式。它的三段中每一段被不同的一套WIN32 API 訪問函數:
Windows CE系統寄存器類似於Windows NT和Windows 95的作業系統的寄存器。你能利用WIN32 寄存器函數來操縱寄存器中鍵和數值。
被使用者安裝的應用程式和資料在一般檔案儲存體段中。Windows CE檔案系統API 是標準WIN32 檔案系統的子集合函式。
對於資料庫應用程式,由Windows CE 資料庫API來儲存被管理儲存。這API 對Windows CE是唯一的 ,並且在其它的WIN32 平台中沒有。
程式記憶體被用於系統和非系統程式的堆棧儲存。 非系統應用程式從儲存記憶體(或者或許PC卡)被取得,非壓縮的並且被裝入要執行程式記憶體中。
意外情況處理
的意外情況處理是強大的編程技術,相應一套的WIN32 API 起函數能容易的發現未預料到的錯誤狀況,並且使之恢複。結構化的意外情況處理,允許危險的段的代碼可能由於硬體資源的問題、裝置的衝突和微小的編碼錯誤而導致失敗,以使這部分程式與其餘的應用程式分開。這保護了應用程式,使之免於過早的終止或者產生敏感的系統問題。
結構化的意外情況處理包括定義一系列聲明作為保護,並且為第一套的聲明定義了另一個套聲明作為意外情況控制代碼。 意外情況控制代碼定義了一個或多個聲明來保障系統的運行,而不管保護聲明的現有的狀態。
在大多數32 位Windows平台上應用WIN32 API 的程式員在運用意外情況控制代碼的時候通常有兩種選擇,用C或 C++ 編寫應用程式,並且利用WIN32提供的處理意外情況的宏,或者利用C++ 編寫應用程式,並且使用C++ 語言定義的意外情況處理函數。
對於這種程式的編寫,Windows CE的開發人員因無法訪問C++的(面向Windows CE的Visual C++ 目前還不支援意外情況處理,所以必須使用WIN32 API的意外情況處理宏。
為了應用WIN32意外情況處理,你將使用一套在WIN32 API 中被定義的宏。 下面一段代碼顯示其基本概念:
__try {
// The statements in here have a possibility of failure
// and so are guarded.
}
__finally {
// This is the exception handler. This code will execute
// after the guarded statements, no matter what happened
// in the guarded block of code above.
}
// This code will execute normally if the program flow allows
// it (no goto, exit, etc.)
__try 以及__finally 宏產生了使用意外情況控制代碼的所必要的底層代碼。
意外情況的處理對諸如在嵌入式的應用程式中的那些普通的多線程式是有用的。WIN32結構化意外情況處理宏 是一種容易並且強大的保護應用程式使之免受未預料到的失敗的方法。
裝置處理
有無數硬體裝置(外圍裝置)與應用Windows的平台(Windows NT以及 Windows 95)台式機是相容的,並且每一年都有更多的東西在市場上湧現。而Windows CE的平台,通常不支援台式電腦支援的裝置的很多品種的外圍硬體。 然而,為一嵌入式的的系統創造可靠的裝置介面在嵌入式的程式設計的過程中,是比較富有挑戰性的部分。 這部分地因為典型的嵌入式的系統介面的時序與其它可操作性的需要遠比台式電腦計算系統和應用程式的更難。
幸運地,WIN32 API 提供了一套豐富使裝置介面方法,使得裝置介面程式寫起來更容易並適合於特定嵌入式的系統的需要。
WIN32 API是如何協助的 WIN32 API在你的硬體平台為你提供一套一致的基於流的介面。 為了使用裝置,你首先利用適合於裝置類型的函數開啟它。 對於大多數裝置,你利用的函數是在下列例子中的CreateFile 函數:
HANDLE hPort = CreateFile("COM1"); // Open the serial port
CreateFile函數開啟規定的裝置(串口)並且返回用於以後在該種裝置上的操作(例如讀和寫)的控制代碼。 各種各樣函數的(包括ReadFile ,WriteFile ,LockFile 和其他)接受這個控制代碼為參數,並且允許你(例如)讀寫資料,檢查裝置狀態,並且將從其它程式的存取被鎖住的裝置或者檔案列入清單。 檔案輸入輸出操作被處理成與其它裝置類型利用同樣的API 函數,並且在檔案之內包括隨機的訪問的函數。 被若干程式或線索同時訪問的裝置和檔案可以分地區地利用LockFile 函數鎖定。
在你的應用程式已完成裝置或者檔案之後,它將調用CloseFile 函數關閉裝置,並且進行必要的清除裝置的工作。
同步和非同步裝置的處理
嵌入式系統的經常有關鍵的裝置有時序需要。 對於這個理由,對底層的作業系統的軟體介面必須能夠在軟體層次上管理同時(或者幾乎同時)的系統中不同類型的裝置的事件。 WIN32 API 支援對裝置的同步和非同步訪問,並且用複雜的裝置介面設計。
同步的介面是那些在軟體需要從裝置得到動作的要求,然後等候結果。在同步的裝置介面中,最常用的是前面已經提到的ReadFile 以及WriteFile函數。當在同步I/O中使用的時候,不論你與磁碟上的檔案、並口或是串口、一個通道或其它類型的裝置介面時,都是公用的並且是相容的。
非同步介面是那些裝置要求應用程式為之服務的介面。一個非同步裝置的好的例子是鍵盤。適當和適時的處理非同步事件,對於許多嵌入式應用程式是至關緊要的。幸運的是,為Windows CE編寫的裝置驅動程式能支援同時的多線索訪問磁碟機。這大大地簡化非同步輸入裝置的處理。
你所訪問的給定的裝置的方法,取決於那個裝置的特性和你開發的特定的應用程式的要求。如果你在基於你的Windows CE的硬體平台上建立一個全新的裝置(和裝置驅動程式),你可以既從你的硬體裝置和磁碟機的層次,又可以從應用程式的層次有許多選擇。
定製裝置和WIN32
儘管嵌入式系統可以支援較小數量的裝置,嵌入式系統能形成唯一的和挑戰型的裝置介面問題。當你開發一個新的硬體平台並且它支援輸入輸出裝置,在模你設計的不同層次上,你將不得不作出決策和折衷方案。例如,除非你只使用通常的off-the-shelf硬體,你必然套寫使用者裝置驅動程式支援你的新外圍裝置。 你也能需要配置你的Windows CE來包含一些裝置處理必要的組件。同時從應用程式的層次,為滿足新的裝置的需要,你將需要寫介面代碼。在有如此多變數的情況下,你如何保持你的裝置的一定程度的一致行呢?答案就在WIN32 API 中。在WIN32 API環境下,寫你的目標驅動程式,你有理由自信的認為那些新裝置的介面的應用程式開發人員能夠創造可信的,可檢驗和可維護的基本代碼。Windows CE裝置驅動程式開發套件,或者簡稱DDK ,提供了如何創造WIN32功能強大的裝置驅動程式資訊和範例。
裝置的類型
Windows CE支援兩種基本類型的裝置驅動程式,內建固化的驅動程式和可安裝的驅動程式。 如同名字所暗示的,內建固化的驅動程式是被指定用於一個給定的Windows CE的硬體平台的裝置。Windows CE的嵌入式系統設計者有責任提供一個內建固化的驅動程式來驅動系統所包括的裝置。例如,許多Windows CE平台有一個LCD 觸控螢幕。這些平台的製造廠為他們的裝置提供裝置驅動程式,使此硬體可以用於Windows CE作業系統。在完備的系統中,這些內建固化的驅動程式位於Windows CE唯讀記憶體中核心的周圍。
可安裝的裝置驅動程式是被設定為為了任何與Windows CE 硬體平台臨時串連的外圍的裝置。這個類型的裝置包括:數據機,印表機,數位照相機,PC卡,以及任何數量的其它外部的裝置。 可安裝的裝置驅動程式可能位於唯讀記憶體中,但是更典型與臨時性的裝置的介面的應用程式軟體一同裝載。
總結
本文已為概略地介紹了面向Windows CE的WIN32 API,其目的是為了突出這種被廣廣泛應用的並且十分重要的API的一般的特點和優點。有許多其它的細節你需要在第一次使用Windows CE嵌入式產品之前來學習掌握;幸運的是,有很多的WIN32 API 的資訊的資源。
這些資源套件括Microsoft開發網路(MSDN ),文章(諸如本文)和報紙,以及大量出版的書