使用.Net Micro Framework 模擬器 – 基本原理
摘要:虛擬儀器(VI)技術在很多高成本的工業項目中扮演著越來越重要的角色,在電子產品的開發中,各種模擬器也為廣大開發人員方提供了便利,提高了生產力。本文介紹了微軟最新的嵌入式開發架構.Net Micro Framework的模擬器。闡述了模擬器的啟動過程,連結組件和註冊資訊等基本工作過程和原理。
Keywords
.Net Micro Framework, Hardware Emulator, Start Up, Component, Registry
.Net MF模擬器簡介
.Net MF模擬器是一個.Net MF CLR的Windows 版的運行環境。運行時的核心部分(執行引擎,類型系統和GC等)和基礎類庫都和在實際裝置上跑的MF一樣。兩者不同之處在於HAL層(Hardware Abstract Layer)。模擬器的HAL層並不是實際的硬體裝置驅動,而是由Windows提供的驅動代替。這裡充分體現了MF的架構中層與層之間高度分離的作用,為類比的真實性和準確性提供了基礎。
說明了.Net Micro Framework模擬器的邏輯結構
模擬器組件(Emulator Components)是模擬器的組成元素,通過它們你可以開發出自訂的硬體模擬器,這裡MVP劉洪峰有些不錯的自訂模擬器的例子:
Ø .Net Micro Framework研究—模擬器改造
http://blog.csdn.net/yefanqiu/archive/2007/10/31/1860020.aspx
Ø .Net Micro Framework研究—帶IO的模擬器
http://blog.csdn.net/yefanqiu/archive/2007/12/30/2005462.aspx
Ø .Net Micro Framework研究—帶AD的模擬器
http://blog.csdn.net/yefanqiu/archive/2007/12/31/2006197.aspx
Ø .Net Micro Framework研究—帶I2C匯流排的模擬器
http://blog.csdn.net/yefanqiu/archive/2007/12/31/2006370.aspx
配置引擎(Configuration Engine)用於在運行時把組件裝配在一起。它使用XML來描述硬體模型的各種配置參數。
啟動過程
在調試的時候,我們只需要在項目屬性中選擇模擬器作為部署目標。在部署的時候,模擬器會自動被調用並運行我們的程式,但是這個過程掩蓋了模擬器啟動的細節。.Net Micro Framework的模擬器也就是一個.Net(通常是Windows Form)應用程式,只不過模擬器加入了組件(Component)和XML設定檔(Emulator.config)的內容。當模擬器啟動的時候:
1. 載入預設組件
模擬器的LoadDefaultComponents()虛方法被調用,它通過調用一系列的RegisterComponent方法來建立模擬器預設的基本組件。您也通過設定檔(Emulator.config)對這些預設組建進行配置,替換或者刪除。在代碼裡面我們也可以通過Emulator類的一系列屬性來訪問這些預設組件。
2.讀取設定檔
預設的組件被構造完畢之後,Emulator的配置引擎會去讀取XML設定檔(Emulator.config)。設定檔中描述的組件會被按要求建立並註冊。此時調用了Emulator類的Configure(System.Xml.XmlReader reader)方法來從XML設定檔中解析類型。
3.安裝組件
經過前兩步,所有組件都已經配置完畢了。這時候系統會去調用Emulator和自訂群組件類的SetupComponent方法來組裝之前建立好的組件。
4.初始化組件
在所有組件安裝完畢以後,Emulator類和EmulatorComponent類的InitializeComponent方法會被調用,來對各個組件進行初始化。
5.載入.Net Micro Framework的程式集
6.運行模擬器
在實際的開發過程中,一般來說,除非是要開發自己的模擬器組件,否則Configure, SetupComponent和InitializeComponent是不需要程式員在代碼裡面調用的。
註冊組件
通過編程註冊模擬器組件需要調用RegisterComponent方法。前面已經提到,模擬器的配置引擎在會在config階段調用該方法。實際上在調用LoadDefaultComponents()的時候實際上就是在內部調用了RegisterComponent方法。使用reflector我們可以看到它的內容如下:
protected virtual void LoadDefaultComponents()
{
this.RegisterComponent(new Hal());
this.RegisterComponent(new ComPortCollection());
this.RegisterComponent(new GpioCollection());
this.RegisterComponent(new SpiBus());
this.RegisterComponent(new MemoryManager());
this.RegisterComponent(new TimingServices());
this.RegisterComponent(new I2cBus());
this.RegisterComponent(new SerialPortCollection());
this.RegisterComponent(new NamedPipeServer());
}
實際上LoadDefaultComponents()就是在為預設的組件進行註冊。
如果是手動註冊,需要注意的是,如果一個組件包含於另一個組件那麼子組件註冊的同時需要提供父組件給RegisterComponent的一個重載方法。在調用UnregisterComponent移除組件的時候,所有連結到它的子組件都會被自動刪除。例如MemoryManager組件,它有兩個子組件RamManager 和 FlashManager。當我們移除MemoryManager時,RamManager 和 FlashManager也會被移除。
訪問登入組件
登入的模擬器組件可以通過Emulator類的FindComponentById方法來訪問。我們經常會調用這個函數來對指定的組件進行初始化。例如在SDK提供的SampleEmulator中我們可以看到這樣一個函數:
/**//// <summary>
/// Helper method to initialize buttons.
/// </summary>
/// <param name="button">The button to be initialized.</param>
/// <param name="componentId">
/// The string identifying the button,
/// found in the config file
/// </param>
/// <param name="key">The key that this button should respond to.</param>
private void InitializeButton(Button button, string componentId, Keys key)
{
button.Port = _emulator.FindComponentById(componentId) as Gpio.GpioPort;
button.Key = key;
}
FindComponentById還有一個比較常用的用途就是用於在初始化的時候檢查必備的組件。例如以下代碼所示:
public override void InitializeComponent()
{
base.InitializeComponent();
//以下兩行代碼即檢查了模擬器是否有名為“Pin_Down”的組件
//同時也檢查了該組件的類型是不是GpioPort
if (FindComponentById("Pin_Down") as GpioPort == null)
throw new Exception("The component 'Pin_Down' is required by the emulator.");
// 啟動UI線程
Thread uiThread = new Thread(StartForm);
uiThread.Start();
}
好了,今天暫且寫到這裡,關於模擬器還有很多值得探討的地方,歡迎有興趣的朋友與我交流。
參考資料:
MS .Net Micro Framework team
Windows Embedded blog From china
MVP 劉洪峰的blog
.Net MF國內的資來源站點點Winbile.Net(正在改版)
Windows Embedded 在部落格園的團隊blog
[書籍]Embedded Programming with the .Net Micro Framework
[書籍]Expert .Net Micro Framework
Enjoy !
黃季冬