新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Windows CE內(nèi)核啟動(dòng)分析

Windows CE內(nèi)核啟動(dòng)分析

作者: 時(shí)間:2011-02-24 來源:網(wǎng)絡(luò) 收藏

Windows CE內(nèi)核啟動(dòng)分析

移植或者創(chuàng)建一個(gè)BSP,也許需要先熟悉Windows CE的內(nèi)核啟動(dòng)過程.

目錄

基于ARM的Windows CE內(nèi)核啟動(dòng)分析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)核入口點(diǎn)startup.S,內(nèi)核從這里啟動(dòng).因?yàn)閮?nèi)核經(jīng)過bootloader加載,內(nèi)核運(yùn)行時(shí)候,已經(jīng)由bootloader完成了硬件的基本初始化(關(guān)閉watchdog, pll設(shè)置等等)所以,startup.S的任務(wù)比較簡(jiǎn)單,只是將oemaddrtab_cfg.inc里面的g_oalAddressTable數(shù)組地址作為參數(shù),傳遞給KernelStart,這個(gè)數(shù)組用來描述和實(shí)現(xiàn)物理地址到虛擬地址的映射.

(. + 8)是流水線處理.KernelStart()位于

PRIVATEWINCEOSCOREOSNKKERNELARMarmtrap.s

2.KernelStart

ARMInit()位于本目錄的mdram.c文件.

KernelInit()位于PRIVATEWINCEOSCOREOSNKKERNELkwin32.c中.

FirstSchedule()位于armtrap.s的一個(gè)label.

主要關(guān)注ARMInit()和KernelInit(),前一個(gè)進(jìn)行目標(biāo)板的初始化,后一個(gè)負(fù)責(zé)內(nèi)核的初始化.FirstSchdule()開始調(diào)度第一個(gè)程序.

2.1 ARMInit()

先看看ARMInit()它的幾個(gè)關(guān)鍵性動(dòng)作如下:

KernelRelocate()是進(jìn)行重定位.KernelFindMemory()是查找系統(tǒng)可用內(nèi)存,并分成應(yīng)用內(nèi)存和object store兩部分.這2個(gè)函數(shù)都已由MS自己實(shí)現(xiàn).我們需要添加的函數(shù)是名字以O(shè)EM開頭的函數(shù).

OEMInitDebugSerial()初始化一個(gè)調(diào)試口,我們一般使用一個(gè)串口來作為調(diào)試口,這個(gè)函數(shù)需要自己實(shí)現(xiàn),在 PLATFORMSMDK2440ASrcKernelOaldebug.c中定義這個(gè)函數(shù).比如可以將串口0設(shè)置為調(diào)試口,在這個(gè)函數(shù)中對(duì)串口0進(jìn)行初始化.

OEMInit()是一個(gè)比較重要的函數(shù),

OALCacheGlobalsInit()在PLATFORMCOMMONSRCARMCOMMONCACHEinit.s中實(shí)現(xiàn),這部分代碼以PQOAL的形式提供.

OALIntrInit()初始化中斷.

OALTimerInit()初始化定時(shí)器TIMER4,作為系統(tǒng)時(shí)鐘(tick),

configGPIO()初始化gpio口,設(shè)置相關(guān)寄存器.

InitDisplay()初始化LCD.有時(shí)候,我們希望在oal啟動(dòng)和內(nèi)核加載期間顯示一副等待圖片或者顯示LOGO,為達(dá)到這個(gè)目的,需要先初始化LCD.

OALKitlStart()準(zhǔn)備啟動(dòng)KITL.

此外,在ARMInit還會(huì)通過調(diào)試口打印一些基本信息,開始時(shí)候打印”Windows CE Kernel for ARM….”字樣, 中間打印處理器類型等等信息.結(jié)束時(shí)候打印” ARMInit done.”

2.1.1 OALIntrInit

調(diào)用OALIntrMapInit()初始化2個(gè)數(shù)組g_oalSysIntr2Irq,g_oalIrq2SysIntr,這2個(gè)數(shù)組表征irq和邏輯中斷SysIntr的映射關(guān)系.

然后初始化中斷寄存器,

最后,留一個(gè)接口給oem: BSPIntrInit(),如果oem需要在這個(gè)階段初始化一些中斷,可以定義這個(gè)函數(shù)并實(shí)現(xiàn).

2.1.2 OALTimerInit

這個(gè)函數(shù)比較重要. 都知道所有WinCE系統(tǒng)都需要一個(gè)定時(shí)器來提供一個(gè)heartbeat,

g_oalTimer包含各種系統(tǒng)時(shí)鐘相關(guān)的變量.

curridlehigh, curridlelow,這2個(gè)32位的DWORD變量合起來實(shí)現(xiàn)一個(gè)64位的計(jì)數(shù)器,反映了系統(tǒng)處于空閑模式(Idle mode)的時(shí)間。一般在OEMIdle()函數(shù)內(nèi)更新。用戶程序通過調(diào)用GetIdleTime()函數(shù)可以得到這個(gè)值。

初始化內(nèi)核函數(shù)指針:pQueryPerformanceFrequency, pQueryPerformanceCounter.通過這兩個(gè)函數(shù)實(shí)現(xiàn)高精度的計(jì)時(shí)器. 這兩個(gè)函數(shù)的原型也已經(jīng)由PQOAL實(shí)現(xiàn).

初始化TIMER4作為系統(tǒng)時(shí)鐘.TIMER4是一個(gè)16bit的定時(shí)器.此函數(shù)將TIMER4設(shè)置成為自動(dòng)轉(zhuǎn)載模式.

2.1.2.1 Variable Tick Scheduler

可變的系統(tǒng)時(shí)鐘節(jié)拍,這個(gè)是WinCE5.0中增加的新的性能.

每一次定時(shí)器中斷時(shí)候,內(nèi)核分析所有線程后決定切換到哪個(gè)線程運(yùn)行.假如所有線程都在等待狀態(tài),系統(tǒng)將進(jìn)入idle狀態(tài).在這個(gè)狀態(tài)的時(shí)候,任何中斷都會(huì)喚醒系統(tǒng)重新開始調(diào)度.一般系統(tǒng)大部分時(shí)間是處于idle狀態(tài)的,內(nèi)核會(huì)調(diào)用OEMIdle()進(jìn)入idle狀態(tài),我們已經(jīng)知道這個(gè)狀態(tài)會(huì)被任何中斷喚醒. 在以前的版本中,系統(tǒng)中斷(即上面的TIMER4中斷)每毫秒產(chǎn)生一次,查看系統(tǒng)是否需要重新調(diào)度. 為了節(jié)電,不希望中斷那么頻繁.于是WinCE5.0中,在調(diào)用OEMIdle()之前會(huì)先調(diào)用pOEMUpdateRescheduleTime().通過這個(gè)函數(shù)重新設(shè)置俠義次系統(tǒng)時(shí)鐘中斷的時(shí)間.

2.2 KernelInit()

再看看KernelInit()函數(shù)

不過多關(guān)注KernelInit().

2.3 FirstSchedule

位于armtrap.s的一個(gè)label.開始第一個(gè)線程調(diào)度.整個(gè)內(nèi)核開始運(yùn)行.


linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)


評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉