通用的EBOOT概念可參考“Windows CE 5.0 Boot Loader的流程分析”,本文僅通過抽象i.MX21平臺上Windows CE 5.0 Eboot代碼來說明從板子上電到WinCE跑起來的幕后故事以及各段代碼所發揮的作用。對照源代碼閱讀本文會有更好的效果。
相關代碼目錄如下:
%WINCE\Platform\iMX21ADS\Src\Bootloader\eboot
%WINCE\PLATFORM\COMMON\SRC\ARM\Freescale\MX21\Startup
%WINCE\PLATFORM\Imx21ads\Src\Kernel\Oal
%WINCE\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BLCOMMON\blcommon.c
(一)%WINCE\PLATFORM\COMMON\SRC\ARM\Freescale\MX21\Startup\startup.s
功能:在OEM板級初始化前先初始化i.MX21處理器的核心模塊
主要的函數功能及流程分析如下:
1.StartUp()---這部分代碼是Boot Loader和OAL共享的。
在板子上電后,第一步是將處理器設置為特權模式,跳轉到MMUCacheDisable( ),使TLB和cache、寫緩沖無效,并關閉 MMU、cache。接著設置AIPI寄存器,跳轉到OALSetUpSystemControl 和OALSetUpFrequencies,初始化系統控制模式和時鐘頻率。程序接下來的工作是啟用I Cache,并跳轉到OALIsImageInRAM、OALSetUpExtMemories以初始化外部存儲設備。隨后是設置MAX寄存器、配置AITC中斷控制器、屏蔽和清中斷的一段代碼。接下來程序先后跳轉到OALSetUpGpio、OALSetUpKeypad,即初始化系統GPIO和鍵盤設備。最后程序跳轉到OALStartUp(),加載g_oalAddressTable地址,再跳轉到KernelStart(),完成代碼重定位和從RAM中啟動Eboot等功能。
上述KernelStart()函數,先跳轉到OALIsImageInRAM程序段判斷Image是否正跑在RAM里。如果不是,則在接下來的RelocateEBOOT程序段里進行代碼重定位;如果已經在RAM里,則跳轉到RamStart程序段,設置連接寄存器LR、加載OEMAddressTable和頁表的地址,然后跳轉到MMUSetup函數,根據OEMAddressTable設置MMU,并使能MMU、啟用cache。在完成了MMU的設置后,程序跳轉到blcommon.c中的BootloaderMain(),這個Eboot主控函數將調用main.c中的一系列OEM函數實現CE系統在板子上的啟動。
上面提到的函數所在文件如下: OALSetUpSystemControl 、OALSetUpFrequencies、OALSetUpExtMemories、OALSetUpGpio、OALSetUpKeypad這幾個函數位于 %WINCE\PLATFORM \iMX21\ Imx21ads\Src\Kernel\Oal\oal_startup.c中;OALIsImageInRAM和OALStartUp位于%WINCE\PLATFORM\Imx21ads\Src\Kernel\Oal\startup.s中。KernelStart則位于%WINCE\PLATFORM\Imx21ads\Src\Bootloader\Eboot\startup.s中。
2. MMUCacheDisable( ) --- 使TLB和cache、寫緩沖無效,并關閉 MMU、cache。
3. MMUSetup()---這個函數將被%Eboot\startup.s調用,它根據OEMAddressTable設置MMU,并使能MMU、啟用cache。
(二) main.c
基本流程:
初始化調試端口---初始化平臺基本設備---打印用戶菜單---初始化網絡參數---下載內核---啟動OS
主要函數及功能:
OEMReportError()----用于點亮LED,并打印出錯誤提示
OEMMultiBINNotify()---- 當系統具有多個BIN文件時用來提示用戶下載的是哪一個BIN
OEMDebugInit( )------- 調用了OEMInitDebugSerial( ),初始化調試串口
OEMPlatformInit( )----- 初始化板上設備
① 通過調試串口打印出Eboot的版本信息
② 調用InitEthDevice(),初始化以太網控制器
③ 設置MAC地址,初始化OAL與eboot共享參數,RTC
④ 調用MainMenu( ),通過串口與用戶交互,設置啟動選項及參數
OEMPreDownload( )--- 判斷是否下載,調用OALKitlCreateName()設置設備名,初始化IP參數,調用EbootInitEtherTransport()初始化TFTP參數
OEMReadData()----- 內部是通過OEMEthGetFrame( )來傳輸數據的
OEMLaunch( )----------- 根據PB里的設置來更新OAL與eboot共享參數,并判斷是否需要將NK燒到Nand Flash中,最后調用Eboot\startup.s 里的Launch( )啟動WinCE內核
在main.c中還有一個重要的函數,那就是ManiMenu( )。它提供了以下啟動選項菜單:
0)MAC地址設置
1)靜態IP設置
2)靜態掩碼設置
3)啟用DHCP
4)恢復到出廠設置
5)保存目前Eboot的設置
D)下載
E)擦除Nor Flash
L)從Nor Flash啟動
R)從RAM中啟動
總的來說,在i.MX21平臺上WinCE EBoot就是在以下幾個文件間不斷跳轉的過程:
%Startup\startup.s --- oal_startup.c --- %Oal\startup.s --- %Eboot\startup.s--- blcommon.c---main.c
PS: 如果對i.MX21上電最初階段系統初始化的匯編代碼有興趣的,可以看看“i.MX21平臺上Startup.s代碼分析”。