WinCE啟動失敗原因與解決辦法
?、貽AL初始化硬件時失敗
oal.exe是通過Startup函數(shù)來完成硬件的初始化。一般來說,OAL的啟動代碼(Startup.s)與該硬件平臺的Bootloader的啟動代碼(Startup.s)是可以共享的。例如,其中PreInit 函數(shù)主要完成將arm處理器工作模式切換到管理員模式,同時關(guān)閉MMU,并檢測系統(tǒng)啟動原因。如果是熱啟動,即在該函數(shù)調(diào)用之前已經(jīng)啟動過 Bootloader的啟動代碼(Startup.s),相當基本硬件初始化已經(jīng)完成,則可直接跳轉(zhuǎn)到OALStartUp函數(shù)中;否則需要進行硬件中斷屏蔽、內(nèi)存、系統(tǒng)時鐘頻率、電源管理等硬件的基本初始化過程。
在StartUp 函數(shù)初始化CPU等核心硬件并跳轉(zhuǎn)到Main函數(shù)后,系統(tǒng)就會轉(zhuǎn)入C語言代碼執(zhí)行環(huán)境。這時Main函數(shù)分為3個模塊:BLCOMMON、Download Function、FLASH Function。其中BLCOMMON模塊是由微軟提供的,執(zhí)行一些邏輯上的功能。而Download Function、FLASH Function中的函數(shù)與硬件平臺息息相關(guān)。因此,對于每種硬件平臺都要將函數(shù)的實現(xiàn)進行適當修改,這種修改是需要對硬件非常熟悉的。當修改出現(xiàn)錯誤時,就會導致系統(tǒng)啟動失敗了。
在硬件平臺初始化完成后,oal.exe的啟動任務基本完成,余下的啟動工作由內(nèi)核相關(guān)且獨立于內(nèi)核的OAL層實現(xiàn)體kernel.dll接管。也就是說,這時Startup會調(diào)用OALStartUp函數(shù),OALStartUp函數(shù)主要完成將OEMAddressTable表傳遞給內(nèi)核,然后調(diào)用KernelStart函數(shù)跳轉(zhuǎn)到內(nèi)核。因此,如果此時OAL的啟動Startup函數(shù)調(diào)用失敗的話,就也會導致系統(tǒng)的啟動失敗了。
這里需要特別注意的是,Bootloader和OAL中均包含啟動Startup函數(shù)。它的功能大致相同,都是要初始化最小硬件環(huán)境。Bootloader的啟動Startup函數(shù)是在為自己的執(zhí)行準備硬件環(huán)境,OAL的啟動Startup函數(shù)則是為kernel的執(zhí)行準備硬件環(huán)境。由于這兩種硬件環(huán)境要求基本相同,所以它們的代碼也有很大部分可以相互借鑒。但應該明白Bootloader與OAL在物理上是獨立的,它們并不是同一段代碼。當然,如果可以確定這一部分在Bootloader已經(jīng)初始化過如熱啟動,則在OAL中不必重復執(zhí)行。
?、贠AL入口位置定位失誤導致的失敗
從上述WinCE啟動流程可知,在OAL初始化硬件后而在內(nèi)核啟動前,系統(tǒng)是需要調(diào)用KernelStart函數(shù)來跳轉(zhuǎn)到內(nèi)核。因此,這里有一個要點,就是WinCE需要找到OAL的入口位置,然后才能調(diào)用入口函數(shù)與全局塊進行指針交換,這樣內(nèi)核才能使用OAL層中的信息,同樣OAL層也才能訪問內(nèi)核(kernel)導出的函數(shù)。
OAL入口位置函數(shù)的調(diào)用實際上是通過OEMGLOBAL結(jié)構(gòu)體實現(xiàn)的,實際調(diào)用位置為OEMInitDebugSerial和OEMInit。也就是說,OEMGLOBAL結(jié)構(gòu)體構(gòu)建了內(nèi)核和OAL層之間進行通信的橋梁。OEMGLOBAL結(jié)構(gòu)體定義了OAL層所有必須的函數(shù),該結(jié)構(gòu)體在oemglobal.c文件中被初始化,并會被編譯在OEMMain.lib和 OEMMain_StaticKITL.lib兩個庫中。如果OAL鏈接這兩個庫,則必須要有正確的該結(jié)構(gòu)體的函數(shù)實現(xiàn)體,同時還需要調(diào)用ARMSetup來設置物理地址和非緩沖的虛擬內(nèi)存地址的映像、arm中斷向量以及內(nèi)核模式所需要的堆棧、調(diào)用OEMInitDebugSerial函數(shù)初始化調(diào)試串口、調(diào)用OEMInit進行平臺初始化等。否則,如果OAL入口位置函數(shù)有誤,則內(nèi)核和OAL層之間的訪問就會失敗,也就會導致系統(tǒng)在啟動時出錯和失敗。
三.導致的WinCE啟動失敗的其它相關(guān)因素
(1)驅(qū)動程序加載錯誤導致的失敗
在調(diào)試中,我們還發(fā)現(xiàn)系統(tǒng)在啟動時執(zhí)行到OEMInit時也經(jīng)常會出現(xiàn)錯誤。一般來說,系統(tǒng)調(diào)用OEMInit運行完成之后,就會跳回Private或Public下的代碼繼續(xù)運行,然后再啟動device.exe加載各個驅(qū)動程序。由于這一段代碼是微軟提供的default代碼,基本上不會有問題。所以,我們就有理由懷疑如果加載的驅(qū)動程序出了問題,是也會造成系統(tǒng)啟動失敗的。一般來說,這些加載的驅(qū)動程序主要是 BSP中的Audio、Display、SDMMC、Serial、USB等。
(2)啟動時加載配置有誤的注冊表導致的失敗
在WinCE中注冊表在啟動過程中也扮演著非常重要的角色。與桌面Windows一樣,WinCE注冊表(Registry)也是一個系統(tǒng)數(shù)據(jù)庫,用來保存應用程序、驅(qū)動程序、用戶的設定以及其它一些系統(tǒng)的配置信息,通常還存儲著操作系統(tǒng)運作和調(diào)用程序的狀態(tài)信息。例如,每個用戶的配置文件、安裝的應用程序以及每個應用程序可以創(chuàng)建的文檔類型、文件夾和應用程序圖標的屬性表設置、系統(tǒng)上存在哪些硬件以及正在使用哪些端口等。
因此,對于硬件外設來說注冊表是一個記錄驅(qū)動程序設置和位置的數(shù)據(jù)庫。當WinCE系統(tǒng)在啟動時需要啟動某些必要的硬件設備時,就會需要使用外設驅(qū)動程序。但如果在WinCE中這個外設驅(qū)動是獨立于操作系統(tǒng)的,WinCE系統(tǒng)就需要知道從哪里找到它們,例如文件名、版本號、其它設置和信息。因此,注冊表上沒有此設備的記錄時,它們就不能被使用。所以,當注冊表在啟動時加載錯誤或者注冊表配置有錯誤時,也是會導致WinCE系統(tǒng)啟動失敗的。
評論