WinCE啟動失敗原因與解決辦法
本文通過一個真實(shí)的嵌入式項目進(jìn)行說明。文中的嵌入式系統(tǒng)用的是arm處理器+WinCE平臺,項目的目的是要把WinCE平臺從舊版本移植到WinCE6.0平臺上。但結(jié)果是這個WinCE系統(tǒng)在啟動的時候經(jīng)常會出現(xiàn)失敗,而且每次失敗的原因都莫明其妙和不盡相同。這使到我們開發(fā)團(tuán)隊每個人在啟動WinCE系統(tǒng)時都心驚肉跳,非常擔(dān)心系統(tǒng)又再一次出現(xiàn)讓人意想不到的失敗。這種頻繁的啟動失敗對開發(fā)團(tuán)隊來說顯然是一種讓人難以忍受的折磨。
本文引用地址:http://butianyuan.cn/article/150995.htm為什么會出現(xiàn)這種情況呢?經(jīng)過幾個晚上通宵達(dá)旦的加班分析和研究,原來主因是系統(tǒng)的引導(dǎo)過程、內(nèi)核加載過程、OAL啟動過程和硬件驅(qū)動加載過程時都存在可能導(dǎo)致的失敗的隱憂。本文通過對以上因素進(jìn)行分析,并提出相應(yīng)的解決辦法。但由于WinCE啟動失敗會非常取決于硬件平臺,因此在具體應(yīng)用時需要綜合考慮和分析。
一.什么是WinCE啟動過程?
WinCE系統(tǒng)在啟動時一般需要三個基本元素:引導(dǎo)初始化、內(nèi)核加載和OAL初始化等。它們的作用是要完成引導(dǎo)過程的初始化和操作系統(tǒng)執(zhí)行環(huán)境的初始化。其中引導(dǎo)初始化是由引導(dǎo)工具BootLoader完成,主要是完成板級、片級的初始化。例如,通過設(shè)置寄存器來完成硬件的初始化,如設(shè)置時鐘、設(shè)置中斷控制寄存器、完成內(nèi)存映射和初始化MMU的工作方式等。內(nèi)核加載是指將操作系統(tǒng)內(nèi)核映像從只讀存儲器加載或者拷貝到系統(tǒng)的RAM中并執(zhí)行。OAL(OEM Adaption Layer,即原始設(shè)備制造商適配層)是位于操作系統(tǒng)的內(nèi)核與硬件之間的適配層,也是連接系統(tǒng)內(nèi)核與硬件的樞紐,它具有屏蔽硬件設(shè)備細(xì)節(jié)以及抽象硬件功能的作用。而OAL初始化則是指通過一組函數(shù)來體現(xiàn)出0AL屏蔽和抽象硬件設(shè)備的作用。
此外,如果要WinCE系統(tǒng)成為完整的操作系統(tǒng),還得加上硬件驅(qū)動程序、硬件接口程序和應(yīng)用程序組。因此,即使在一個簡單的嵌入式系統(tǒng)里,WinCE系統(tǒng)啟動時是需要加載內(nèi)核和加載許多組件或驅(qū)動程序。
現(xiàn)在讓我們來看看WinCE系統(tǒng)在啟動時調(diào)用函數(shù)的順序:①CPU執(zhí)行引導(dǎo)向量,跳轉(zhuǎn)到硬件初始化代碼,即Startup函數(shù)。②在start up函數(shù)完成最小硬件環(huán)境初始化后跳轉(zhuǎn)到KernelStart函數(shù),來對內(nèi)核進(jìn)行初始化。③Kernelstart函數(shù)調(diào)用OEMInitDebugSerial完成對調(diào)試串口的初始化;同時調(diào)用0EMInit函數(shù)來完成硬件初始化工作以及設(shè)置時鐘、中斷;最后,調(diào)用OEMGetExtensionDRAM函數(shù)來判斷是否還有另外一塊DRAM。至此,內(nèi)核加載完畢。由此可見,WinCE系統(tǒng)啟動的重中之重是Startup函數(shù)的正確加載,如果這個Startup函數(shù)調(diào)用失敗,則會使到系統(tǒng)在啟動頻繁出錯。WinCE啟動時調(diào)用函數(shù)順序如下圖所示:
因此,WinCE啟動失敗可能會存在于引導(dǎo)初始化失敗、內(nèi)核加載失敗、0AL函數(shù)初始化失敗、驅(qū)動程序加載失敗、組件加載失敗和應(yīng)用程序加載失敗。也就是說,WinCE啟動失敗一方面可能是在Startup函數(shù)的處理上,例如引導(dǎo)初始化和OAL初始化。另一方面還存在于驅(qū)動程序和組件自啟動的失敗上,例如基本的驅(qū)動程序、注冊表配置或自運(yùn)行的程序等。
就不能被使用。所以,當(dāng)注冊表在啟動時加載錯誤或者注冊表配置有錯誤時,也是會導(dǎo)致WinCE系統(tǒng)啟動失敗的。
二.導(dǎo)致WinCE啟動失敗的主因分析
Windows CE在啟動時為什么會失敗呢?這個問題也一直讓我頭痛。因為Windows CE啟動失敗既有軟件因素,也有硬件因素。例如,可能是WinCE的啟動引導(dǎo)過程有問題、也許是內(nèi)核加載時有問題、也許是OAL函數(shù)調(diào)用的隱性問題或者硬件設(shè)備本身的問題造成的。所以,解決起來比較麻煩和比較耗時間,也是最讓我們頭疼的事情。
一般來說,解決和分析WinCE啟動失敗有一個原則,就是先軟后硬的原則,也就是說要先分析軟件因素再到硬件因素。本文主要是在arm微處理器和Windows CE 6.0平臺上進(jìn)行分析軟件因素造成的失敗。
(1)引導(dǎo)程序BootLoader導(dǎo)致的失敗
在Windows CE系統(tǒng)中,整個系統(tǒng)的加載啟動任務(wù)由BootLoader來完成,BootLoader是在WinCE內(nèi)核運(yùn)行之前運(yùn)行的一段小程序。通過這段小程序,可以初始化硬件設(shè)備、建立內(nèi)存空間的映射圖和初始化MMU等。從而將系統(tǒng)的軟硬件環(huán)境帶到一個合適的狀態(tài),為調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好環(huán)境。因此,只有在引導(dǎo)程序正確的完成自己的任務(wù)后,才會將控制權(quán)移交給內(nèi)核。
在WinCE平臺上,引導(dǎo)裝載程序是在硬件上執(zhí)行的第一段代碼,通常將引導(dǎo)程序放置在不易丟失的存儲器的開始地址或者是系統(tǒng)冷啟動時PC寄存器的初始值。如果這段小程序代碼編寫錯誤,則系統(tǒng)無法完成第一步的引導(dǎo)操作,這是導(dǎo)致啟動系統(tǒng)失敗的第一個因素。
?、貰ootLoader初始化硬件失敗
BootLoader第一個功能是要實(shí)現(xiàn)板級和片級初始化硬件,主要是把CPU初始化到一已知狀態(tài)。在BootLoader目錄下,會發(fā)現(xiàn)一些.s文件,可能會是init.s或者是reset.s等,這樣的文件是CPU加電后最先執(zhí)行的代碼。StartUp 函數(shù)是BootLoader的入口函數(shù)。該函數(shù)一般是使用匯編語言編寫,與CPU關(guān)系非常緊密,能完成初始化CPU、內(nèi)存等核心硬件。然后,BootLoader在平臺初始化完畢后就可以在不用人工干預(yù)的情況下自動加載WinCE內(nèi)核了。但如果BootLoader在初始化硬件時失敗,就會直接導(dǎo)致系統(tǒng)的啟動失敗了。
?、贐ootLoader加載內(nèi)核時失敗
一般在平臺調(diào)試完畢后,BootLoader就會加載WinCE內(nèi)核映像,這也是BootLoader的功能之一。WinCE內(nèi)核映像文件通常叫做nk.bin,它是Windows CE二進(jìn)制數(shù)據(jù)格式文件,不僅包含了有效的程序代碼,還有按照一定規(guī)則加入的控制信息。
在系統(tǒng)啟動時BootLoader可以通過兩種不同的方式來加載WinCE內(nèi)核文件nk.bin。一種是下載模式,另一種是本地啟動模式。本地啟動模式也稱為自主模式,即 BootLoader 從目標(biāo)機(jī)上的某個固態(tài)存儲設(shè)備上將操作系統(tǒng)加載到 RAM 中運(yùn)行,整個過程并沒有用戶的介入。而下載模式則是目標(biāo)機(jī)上的 BootLoader 將通過串口連接或網(wǎng)絡(luò)連接等通信手段從主機(jī)(Host)下載文件。當(dāng)BootLoader正確的把nk.bin解壓到RAM后,就會把CPU控制權(quán)交給CE內(nèi)核。因此,如果Boot Loader處理不當(dāng),就可能會造成加載和解壓nk.bin文件的失敗,這樣自然也就會造成系統(tǒng)啟動的失敗了。
(2)OAL導(dǎo)致的啟動失敗
OAL(OEM Adaptation Layer)是指OEM 適配層,它是位于Windows CE內(nèi)核和硬件之間的一層適配層,是OAL各個模塊代碼被編譯后(.lib)和其它內(nèi)核庫鏈接到一起形成Windows CE的內(nèi)核可執(zhí)行文檔NK.EXE。OAL包括了和系統(tǒng)硬件通訊的最底層代碼,內(nèi)核是通過OAL跟硬件進(jìn)行交互。邏輯上,OAL是介于CE內(nèi)核和設(shè)備硬件之間的一個代碼層,是一個抽象的概念。物理上,OAL和其它一些庫一起鏈接成可執(zhí)行文件。
與以前的Win CE舊版本不同的是,在Win CE 6.0中內(nèi)核(Kenerl)和OEM代碼被分成oal.exe、kernel.dll和kitl.dll三個部分,其中啟動代碼(startup)和 OAL層的實(shí)現(xiàn)部分不再與內(nèi)核鏈接生成NK.exe,取而代之的是啟動代碼(startup)和硬件相關(guān)且獨(dú)立于內(nèi)核的OAL層的實(shí)現(xiàn)部分編譯成 oal.exe;而與內(nèi)核相關(guān)且獨(dú)立于硬件的OAL層代碼包含在kernel.dll中,內(nèi)核無關(guān)傳輸層(KITL)的支持代碼從OAL層分離出來編譯成 kitl.dll。因此,WinCE6.0的啟動只與oal.exe和kernel.dll有關(guān)。至于kitl.dll,只有將操作系統(tǒng)編譯成具有 KITL功能時才用到。這樣做的好處是可以單獨(dú)升級OAL,但整體的OAL結(jié)構(gòu)并沒有改變。
評論