Windows CE內(nèi)核啟動(dòng)分解解析
出處:互聯(lián)網(wǎng) 發(fā)布于:2011-09-04 15:05:08
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()位于
PRIVATE\WINCEOS\COREOS\NK\KERNEL\ARM\armtrap.s
2.KernelStart
ARMInit()位于本目錄的mdram.c文件。
KernelInit()位于PRIVATE\WINCEOS\COREOS\NK\KERNEL\kwin32.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),在 PLATFORM\SMDK2440A\Src\Kernel\Oal\debug.c中定義這個(gè)函數(shù)。比如可以將串口0設(shè)置為調(diào)試口,在這個(gè)函數(shù)中對(duì)串口0進(jìn)行初始化。
OEMInit()是一個(gè)比較重要的函數(shù),
OALCacheGlobalsInit()在PLATFORM\COMMON\SRC\ARM\COMMON\CACHE\init.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)行。
wince多線程調(diào)度
這兩天收獲還是挺大,一來wince下的多線程終于加深了理解,二來linux終于初涉內(nèi)核編程,有了點(diǎn)小體會(huì)。linux內(nèi)核的東西比較麻煩,有空再總結(jié)總結(jié)。今天抽空先寫寫wince的多線程協(xié)作。
上寫了一點(diǎn)critical section的用法,實(shí)際上還是比較膚淺,本來做得就不多。這兩天主要是研究wince的線程調(diào)度。
wince調(diào)度的基本單位應(yīng)該是線程,而且對(duì)每一個(gè)線程都有一個(gè)優(yōu)先級(jí)。wince的優(yōu)先級(jí)是0~255,其中0~247是實(shí)時(shí)優(yōu)先級(jí),248~255一般為應(yīng)用程序的優(yōu)先級(jí)。一個(gè)應(yīng)用程序的優(yōu)先級(jí)默認(rèn)是251。創(chuàng)建線程的時(shí)候沒有辦法直接設(shè)置優(yōu)先級(jí),但是應(yīng)用程序可以動(dòng)態(tài)提升自己的線程的優(yōu)先級(jí),有兩個(gè)API可用SetThreadPriority和CeSetThreadPriority。前者可在248~255范圍內(nèi)調(diào)節(jié),后者可提升至實(shí)時(shí)線程。對(duì)于提升優(yōu)先級(jí),應(yīng)用程序的優(yōu)先級(jí)不要高于設(shè)備驅(qū)動(dòng),否則可能會(huì)有問題。
線程調(diào)度和時(shí)間片大小有很大關(guān)系,時(shí)間片大小一般在OEMinit()中初始化,也可以通過SetThreadQuantum來修改,當(dāng)然也有對(duì)應(yīng)的Get函數(shù)。一般默認(rèn)是100ms。
wince的調(diào)度原則是高優(yōu)先級(jí)線程可以實(shí)時(shí)搶占低優(yōu)先級(jí)線程的cpu資源。所以在調(diào)用SetThreadPriority的時(shí)候需要多加注意。因?yàn)橐坏┨嵘说木€程的優(yōu)先級(jí)高于本線程,本線程將無法得到執(zhí)行。而把SetThreadPriority放入被提升的線程中也是會(huì)引發(fā)難以想象的問題。我用的一種辦法是主調(diào)線程先提升自己的優(yōu)先級(jí),然后再創(chuàng)建新線程,并設(shè)CREATE_SUSPENDED,SetThreadPriority之后再ResumeThread。但是有些場(chǎng)合不太適合這樣用。
對(duì)于同等級(jí)的線程,會(huì)輪流使用時(shí)間片。同一個(gè)進(jìn)程的多個(gè)線程也會(huì)參與公平競(jìng)爭(zhēng)。
對(duì)于windows的微內(nèi)核結(jié)構(gòu),驅(qū)動(dòng)程序都不是內(nèi)核進(jìn)程,device.exe會(huì)用一個(gè)線程執(zhí)行驅(qū)動(dòng)程序的函數(shù)。而線程的默認(rèn)優(yōu)先級(jí)就是251,不爽。呵。
版權(quán)與免責(zé)聲明
凡本網(wǎng)注明“出處:維庫(kù)電子市場(chǎng)網(wǎng)”的所有作品,版權(quán)均屬于維庫(kù)電子市場(chǎng)網(wǎng),轉(zhuǎn)載請(qǐng)必須注明維庫(kù)電子市場(chǎng)網(wǎng),http://m.58mhw.cn,違反者本網(wǎng)將追究相關(guān)法律責(zé)任。
本網(wǎng)轉(zhuǎn)載并注明自其它出處的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)或證實(shí)其內(nèi)容的真實(shí)性,不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個(gè)人從本網(wǎng)轉(zhuǎn)載時(shí),必須保留本網(wǎng)注明的作品出處,并自負(fù)版權(quán)等法律責(zé)任。
如涉及作品內(nèi)容、版權(quán)等問題,請(qǐng)?jiān)谧髌钒l(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。
- ARM技術(shù)架構(gòu)與應(yīng)用開發(fā)實(shí)踐指南2026/1/6 10:40:19
- 嵌入式實(shí)時(shí)操作系統(tǒng)(RTOS)選型與移植技術(shù)指南2025/12/31 10:42:31
- 工業(yè)嵌入式系統(tǒng):通信接口技術(shù)選型與抗干擾設(shè)計(jì)實(shí)踐2025/12/15 14:36:53
- 深入解析嵌入式 OPENAMP 框架:開啟異核通信新時(shí)代2025/7/22 16:27:29
- 一文快速了解OPENWRT基礎(chǔ)知識(shí)2025/7/14 16:59:04









