Windows CE內(nèi)核啟動分析
Windows CE內(nèi)核啟動分析
移植或者創(chuàng)建一個BSP,也許需要先熟悉Windows CE的內(nèi)核啟動過程.
目錄
基于ARM的Windows CE內(nèi)核啟動分析1
1.startup.s2
2.KernelStart2
2.1 ARMInit()3
2.1.1 OALIntrInit3
2.1.2 OALTimerInit4
2.1.2.1 Variable Tick Scheduler4
2.2 KernelInit()4
2.3 FirstSchedule5
1.startup.s
內(nèi)核入口點startup.S,內(nèi)核從這里啟動.因為內(nèi)核經(jīng)過bootloader加載,內(nèi)核運行時候,已經(jīng)由bootloader完成了硬件的基本初始化(關閉watchdog, pll設置等等)所以,startup.S的任務比較簡單,只是將oemaddrtab_cfg.inc里面的g_oalAddressTable數(shù)組地址作為參數(shù),傳遞給KernelStart,這個數(shù)組用來描述和實現(xiàn)物理地址到虛擬地址的映射.
(. + 8)是流水線處理.KernelStart()位于
PRIVATEWINCEOSCOREOSNKKERNELARMarmtrap.s
2.KernelStart
ARMInit()位于本目錄的mdram.c文件.
KernelInit()位于PRIVATEWINCEOSCOREOSNKKERNELkwin32.c中.
FirstSchedule()位于armtrap.s的一個label.
主要關注ARMInit()和KernelInit(),前一個進行目標板的初始化,后一個負責內(nèi)核的初始化.FirstSchdule()開始調度第一個程序.
2.1 ARMInit()
先看看ARMInit()它的幾個關鍵性動作如下:
KernelRelocate()是進行重定位.KernelFindMemory()是查找系統(tǒng)可用內(nèi)存,并分成應用內(nèi)存和object store兩部分.這2個函數(shù)都已由MS自己實現(xiàn).我們需要添加的函數(shù)是名字以OEM開頭的函數(shù).
OEMInitDebugSerial()初始化一個調試口,我們一般使用一個串口來作為調試口,這個函數(shù)需要自己實現(xiàn),在 PLATFORMSMDK2440ASrcKernelOaldebug.c中定義這個函數(shù).比如可以將串口0設置為調試口,在這個函數(shù)中對串口0進行初始化.
OEMInit()是一個比較重要的函數(shù),
OALCacheGlobalsInit()在PLATFORMCOMMONSRCARMCOMMONCACHEinit.s中實現(xiàn),這部分代碼以PQOAL的形式提供.
OALIntrInit()初始化中斷.
OALTimerInit()初始化定時器TIMER4,作為系統(tǒng)時鐘(tick),
configGPIO()初始化gpio口,設置相關寄存器.
InitDisplay()初始化LCD.有時候,我們希望在oal啟動和內(nèi)核加載期間顯示一副等待圖片或者顯示LOGO,為達到這個目的,需要先初始化LCD.
OALKitlStart()準備啟動KITL.
此外,在ARMInit還會通過調試口打印一些基本信息,開始時候打印”Windows CE Kernel for ARM….”字樣, 中間打印處理器類型等等信息.結束時候打印” ARMInit done.”
2.1.1 OALIntrInit
調用OALIntrMapInit()初始化2個數(shù)組g_oalSysIntr2Irq,g_oalIrq2SysIntr,這2個數(shù)組表征irq和邏輯中斷SysIntr的映射關系.
然后初始化中斷寄存器,
最后,留一個接口給oem: BSPIntrInit(),如果oem需要在這個階段初始化一些中斷,可以定義這個函數(shù)并實現(xiàn).
2.1.2 OALTimerInit
這個函數(shù)比較重要. 都知道所有WinCE系統(tǒng)都需要一個定時器來提供一個heartbeat,
g_oalTimer包含各種系統(tǒng)時鐘相關的變量.
curridlehigh, curridlelow,這2個32位的DWORD變量合起來實現(xiàn)一個64位的計數(shù)器,反映了系統(tǒng)處于空閑模式(Idle mode)的時間。一般在OEMIdle()函數(shù)內(nèi)更新。用戶程序通過調用GetIdleTime()函數(shù)可以得到這個值。
初始化內(nèi)核函數(shù)指針:pQueryPerformanceFrequency, pQueryPerformanceCounter.通過這兩個函數(shù)實現(xiàn)高精度的計時器. 這兩個函數(shù)的原型也已經(jīng)由PQOAL實現(xiàn).
初始化TIMER4作為系統(tǒng)時鐘.TIMER4是一個16bit的定時器.此函數(shù)將TIMER4設置成為自動轉載模式.
2.1.2.1 Variable Tick Scheduler
可變的系統(tǒng)時鐘節(jié)拍,這個是WinCE5.0中增加的新的性能.
每一次定時器中斷時候,內(nèi)核分析所有線程后決定切換到哪個線程運行.假如所有線程都在等待狀態(tài),系統(tǒng)將進入idle狀態(tài).在這個狀態(tài)的時候,任何中斷都會喚醒系統(tǒng)重新開始調度.一般系統(tǒng)大部分時間是處于idle狀態(tài)的,內(nèi)核會調用OEMIdle()進入idle狀態(tài),我們已經(jīng)知道這個狀態(tài)會被任何中斷喚醒. 在以前的版本中,系統(tǒng)中斷(即上面的TIMER4中斷)每毫秒產(chǎn)生一次,查看系統(tǒng)是否需要重新調度. 為了節(jié)電,不希望中斷那么頻繁.于是WinCE5.0中,在調用OEMIdle()之前會先調用pOEMUpdateRescheduleTime().通過這個函數(shù)重新設置俠義次系統(tǒng)時鐘中斷的時間.
2.2 KernelInit()
再看看KernelInit()函數(shù)
不過多關注KernelInit().
2.3 FirstSchedule
位于armtrap.s的一個label.開始第一個線程調度.整個內(nèi)核開始運行.
評論