- VxWorks設備驅動開發詳解
- 曹桂平等編著
- 125字
- 2019-01-09 15:53:26
第3章 VxWorks操作系統啟動過程詳解
本章將著重分析VxWorks的啟動過程,首先,簡單介紹VxWorks操作系統支持的幾種啟動方式,每種啟動方式下映像的組成和基本啟動流程;其次,詳細介紹下載啟動方式下bootrom的組成和執行流程;再次,詳細介紹VxWorks本身的啟動過程;最后,詳細介紹BSP下的文件組成。
3.1 VxWorks操作系統啟動
3.1.1 VxWorks基本啟動方式
按VxWorks內核的下載形式,VxWorks啟動總體上分為兩種方式:下載型和ROM型。
● 下載型啟動方式:bootrom+VxWorks。此時bootrom被燒入ROM中,而VxWorks內核映像通過串口或者網口下載到系統RAM中。
● ROM型啟動方式:VxWorks直接從ROM中運行,不借助于bootrom引導程序。此時VxWorks內核映像被燒入ROM中,無bootrom程序。
對于不同的啟動方式,VxWorks操作系統內核映像的組成也略有不同。
bootrom引導程序一般稱為VxWorks boot Image。該程序由如下文件創建而成:romInit.s、bootInit.c、sysALib.s、sysLib.c、bootConfig.c、設備驅動程序。
注意
雖然bootrom中包含sysALib.s文件,但是并未使用其中定義的任何函數,這與ROM形式的VxWorks內核映像類似。
VxWorks內核映像一般被稱為VxWorks Application Image。VxWorks內核映像是系統啟動后實際運行的程序(操作系統本身)。對于下載形式的VxWorks內核映像,由于需要對硬件環境進行重新初始化(即不依賴于romInit函數所做的初始化工作),所以最先需要運行sysInit函數進行重新初始化,這些初始化工作與romInit函數基本相同,但是不再需要對內存控制器進行重新初始化,這是sysInit區別于romInit函數之處。sysInit最后跳轉到usrInit函數。而對于ROM方式直接運行的VxWorks內核映像,由于romInit.s函數此時是作為內核映像的一部分,所以就省去了對sysInit函數的調用。下載型和ROM型在VxWorks內核文件的構成上有一些差別。
● 下載形式的VxWorks內核映像組成:sysALib.s、sysLib.c、usrConfig.c、設備驅動程序文件。
● ROM形式的VxWorks內核映像組成:romInit.s、bootInit.c、sysALib.s、sysLib.c、usrConfig.c、設備驅動程序文件。
注意
雖然ROM形式的VxWorks內核映像并未使用sysALib.s文件中的函數(sysInit),但是該文件仍然作為一部分存在于該VxWorks內核映像中。當然用戶可以修改defs.bsp文件中的MACH_DEP宏定義,將sysALib.o從如下形式定義中去掉即可。
MACH_DEP =|sysLib.o| sysLib.o $(MACH_EXTRA) $(ADDED_MODULES)
3.1.2 VxWorks操作系統內存布局
在VxWorks操作系統過程中可能使用到的BootRom和VxWorks內核映像本身都可以存在兩種方式:壓縮的和非壓縮的。
1.非壓縮形式
如果沒有進行壓縮,則只有一次重定位,即從ROM到RAM只存在一次代碼復制過程,所有ROM中存儲的代碼都被一次性復制到RAM中。
① 對于BootRom而言,所有的代碼被一次性復制到RAM_HIGH_ADRS指定地址處,如圖3-1所示。

圖3-1 非壓縮版BootRom引導程序ROM及載入RAM后分布圖
② 對于VxWorks_rom而言,所有的代碼被一次性復制到RAM_LOW_ADRS指定地址處,如圖3-2所示。

圖3-2 非壓縮版VxWorks_rom內核映像類型ROM及載入RAM后布局圖
2.壓縮形式
如果有進行壓縮,則代碼復制過程將分為兩次,一次是非壓縮代碼,另一次是壓縮代碼,且二者復制到內存不同的位置處。
① 對于BootRom而言,非壓縮代碼(romInit.s、bootInit.c)被直接復制到RAM_LOW_ADRS處;壓縮代碼復制到RAM_HIGH_ADRS處,并在復制過程中完成解壓縮,如圖3-3所示。

圖3-3 壓縮版BootRom引導程序ROM及載入RAM后分布圖
② 對于VxWorks_rom而言,非壓縮代碼(romInit.s、bootInit.c)被直接復制到RAM_HIGH_ADRS處;壓縮代碼復制到RAM_LOW_ADRS處,并在復制過程中完成解壓縮,如圖3-4所示。

圖3-4 壓縮版VxWorks_rom內核映像類型ROM及載入RAM后分布圖
事實上,對于壓縮版本,在進行編譯時,進行了兩次代碼鏈接:一次是針對壓縮代碼的鏈接,另一次是將非壓縮代碼和壓縮代碼整合在一起時的鏈接。注意,在進行非壓縮代碼和壓縮代碼的整合時,壓縮代碼部分是作為數據進入整個映像的,所以不會對其進行重新鏈接。對壓縮代碼的鏈接,實際上是在代碼被壓縮之前完成的,完成代碼的鏈接后,生成特定格式的目標文件(如ELF或者COFF),為了在解壓縮后可以直接執行,首先必須將其轉成二進制可執行文件,通過objcopy函數完成此項功能,此后對生成的二進制可執行文件調用deflate函數進行壓縮,由于需要將壓縮后的代碼最后整合到整個映像中,故壓縮后的文件還需要通過binToAsm工具進行轉換,轉成一個匯編源文件,該文件將壓縮后的二進制代碼作為數據部分進行保存,從而避免在與非壓縮代碼最后進行二次鏈接時被修改。
兩步鏈接過程中各自指定了不同的鏈接地址,對于壓縮代碼而言,其分為兩種情況,對于BootRom,壓縮代碼被鏈接到了RAM_HIGH_ADRS地址處,而對于VxWorks_rom,則被鏈接到了RAM_LOW_ADRS地址處,在與非壓縮代碼進行整合鏈接時指定的鏈接地址(即_romInit函數地址)與壓縮代碼鏈接時指定的地址相對應:如果壓縮代碼為RAM_HIGH_ADRS,則最后整合時就為RAM_LOW_ADRS;如果壓縮代碼為RAM_LOW _ADRS,則整合時就為RAM_HIGH_ADRS。
3.1.3 下載型啟動方式概述
下載形式的VxWorks啟動方式需要bootrom引導程序,該程序將被燒錄到開發板的ROM或者Flash中,在上電時,系統將自動跳轉到ROM或者Flash起始地址處運行該bootrom引導程序,該引導程序進行必要的系統初始化,從而為下載VxWorks內核映像做準備,如通過網口下載時,則需要先調用網口驅動程序進行網口初始化。
由于bootrom的主要工作是下載真正的VxWorks內核映像到系統RAM中,所以其進行的初始化工作也是為這一目的,在文件組織上,雖然從上文中可以看到其與VxWorks內核映像的文件組成非常相似,但其使用bootConfig.c文件,而VxWorks內核映像則使用usrConfig.c文件。這兩個文件中雖然定義有相同的函數名(如usrInit、usrRoot),但在實現上存在很大的差異:bootConfig.c文件實現完成從某個服務器下載真正的VxWorks內核映像到系統RAM中(由變量RAM_LOW_ADRS指向的內存地址處),并跳轉到sysInit函數(定義在sysALib.s文件中第一個且必須是第一個函數,該函數即被裝載到變量RAM_LOW_ADRS指向的內存地址處)執行;usrConfig.c文件實現完成一個操作系統正常運行所需要的所有初始化工作。簡言之,bootConfig.c文件完成VxWorks內核映像的下載,而usrConfig.c完成初始化VxWorks操作系統的所有工作。
按bootrom執行方式的不同,bootrom文件存在如下三種文件類型。
(1)bootrom.bin
它為壓縮bootrom文件形式,此種文件形式主要為解決開發板上ROM或者Flash的空間限制。注意:壓縮并非對所有的文件進行壓縮,而是除了romInit.s和bootInit.c文件的其他所有文件,因為解壓縮程序必須是非壓縮形式的。
bootrom執行流程如下(以下采用“文件名:函數名:初始是否被壓縮”形式進行說明)。
① romInit.s:romInit:非壓縮。
romInit函數完成系統硬件環境下必要的初始化工作,如從系統角度禁止中斷,初始化相關寄存器到可知狀態,初始化內存控制器,初始化函數調用所需的棧,最后跳轉到romStart函數執行。
② bootInit.c:romStart:非壓縮。
romStart函數主要完成如下任務:
首先將romInit函數及其自身復制到RAM_LOW_ADRS變量指向的RAM區,以便從RAM執行。注意,此后在下載VxWorks內核映像時,內核映像也被下載到RAM_LOW_ADRS變量指向的內存處,所以這部分代碼此后將被覆蓋,同樣,bootrom占用的所有其他內存最后也將被VxWorks內核回收(如由RAM_HIGH_ADRS指向的內核空間)。
● 將bootrom程序其他部分(壓縮部分)從ROM區復制到RAM區(由RAM_HIGH_ADRS變量指向的內存地址處),并解壓縮。
● 對于cold boot(冷啟動)方式,將其復制到RAM區清零。
● 最后跳轉到usrInit(注意:是bootConfig.c文件中定義的)函數進行執行。
③ bootConfig.c:usrInit:壓縮。
usrInit函數此處主要進行外圍硬件初始化,為下載VxWorks內核映像做初始準備,而后創建tUsrBoot進程調用usrRoot程序進一步完成驅動程序初始化工作,為下載VxWorks內核映像做進一步工作,最后創建tBoot進程調用bootCmdLoop函數完成VxWorks的內核映像下載。在下載完成后,調轉到下載起始地址處執行,此時下載型VxWorks內核入口函數sysInit將被調用執行,真正開始VxWorks操作系統的啟動過程。最終在usrConfig.c:usrRoot函數執行完畢后,VxWorks操作系統即完成啟動,系統進入正常運行狀態。函數執行流程如下:(采用“映像類型:文件名:函數名”形式)
bootrom:romInit.s:romInit→bootrom:bootInit.c:romStart→bootrom:bootConfig.c:usrInit→bootrom:bootConfig.c:usrRoot→bootrom:bootConfig.c:bootCmdLoop→完成VxWorks內核映像下載,并跳轉到VxWorks內核入口函數(sysInit)執行代碼→VxWorks:sysALib.s:sysInit→VxWorks:usrConfig.c:usrInit→VxWorks:usrConfig.c:usrRoot→VxWorks操作系統完成啟動。
如圖3-5所示為bootrom完成下載VxWorks內核映像后的RAM布局,此時,之前bootrom占用的所有區域均被VxWorks操作系統回收。

圖3-5 VxWorks操作系統啟動后內存分布圖
(2)bootrom_uncmp.bin和bootrom_res.bin
上述兩種形式的bootrom執行流程基本與bootrom.bin相同。差別在于:
① bootrom_uncmp.bin。
該文件類型為非壓縮類型,所以區別以上壓縮形式的地方在于romStart函數將bootrom從ROM移動到RAM中時,無須進行解壓縮工作,移動到的RAM區地址仍然由RAM_HIGH_ADRS變量指定。注意,對于非壓縮bootrom,所有的代碼(包括已經執行的romInit函數、當前執行的romStart函數、構成bootrom的其他所有函數)都一次性從ROM復制到RAM中,RAM中目的地址由RAM_HIGH_ADRS變量指定,如圖3-1所示。函數執行流程同壓縮版本。
② bootrom_res.bin。
res全稱為resident,此處的意思為程序代碼部分將駐留在ROM中,所以不同于上文中的地方,即romStart函數只復制bootrom引導程序的數據段到RAM_HIGH_ADRS變量指向的RAM區。代碼執行還是從ROM區中取,此種方式一般在開發板ROM區較大時采用,但會增加執行時間,另外,由于需要從ROM中直接執行,故也不能采用代碼壓縮方式。
下載方式中使用的VxWorks內核映像一般命名為“VxWorks”(不包含內核符號表,此時創建一個獨立的內核符號表文件VxWorks.sym,如果需要將內核符號表包含其中,則在config.h文件中定義INCLUDE_STANDALONE_SYM_TBL組件)或者“VxWorks_st”(內含內核符號表),而其他啟動方式(一般就為ROM啟動方式)下的VxWorks內核映像名都具有一個后綴,如VxWorks_rom表示從ROM直接啟動,VxWorks_res_rom表示代碼部分駐留在ROM中,當然也是從ROM直接啟動。下載方式下,VxWorks內核映像文件構成以及完成下載后VxWorks內核函數的調用流程在前文已有介紹,此處不再贅述。
3.1.4 ROM型啟動方式概述
所有的VxWorks內核映像類型中,只有VxWorks類型使用上文中介紹的bootrom引導程序進行啟動,此時VxWorks內核映像放置在主機端,由目標板bootrom完成VxWorks的下載,一般通過網口(或串口)方式進行。其他類型(文件名中帶有rom字樣的)無須bootrom的配合,也即不需要bootrom。因為這些VxWorks類型的內核映像自身(而非bootrom)被燒入開發板系統ROM或者Flash中,均無須進行下載,系統上電時,將直接跳轉到VxWorks內核映像入口函數執行操作系統的初始化工作。
ROM型啟動方式下的VxWorks內核映像類型有以下幾類。
① VxWorks_rom.bin:非壓縮版VxWorks內核映像類型不含內核符號表。如果需要包含內核符號表,則在config.h文件中定義INCLUDE_STANDALONE_SYM_TBL組件。
② VxWorks.res_rom.bin:非壓縮版代碼駐留ROM中執行的VxWorks內核映像類型(含內核符號表)。
③ VxWorks.res_rom_nosym.bin:非壓縮版代碼駐留ROM中執行的,不包含內核符號表的VxWorks內核映像類型。
④ VxWorks.st_rom.bin:壓縮版本的內含內核符號表的VxWorks內核映像類型。
⑤ VxWorks_romCompress.bin:壓縮版的不含內核符號表的VxWorks內核映像類型。
不同的VxWorks內核版本下,在內核映像名稱上會有所變化,但一般都包含在以上類型中。從這些映像類型來看,主要有以下區分:
● 是否為ROM駐留方式,即代碼是否被復制到RAM中執行。
● 是否進行了壓縮。
● 是否包含符號表。
注意
VxWorks內核映像是否包含內核符號表對于后續函數的調用非常重要,如在串口命令行下輸入一個函數名稱,如果內核映像不包含內核符號表,即使在內核中包含該函數定義,在終端也會給出“undefined symbol”錯誤。
以下從三個不同角度介紹它們的不同點,首先以VxWorks_rom.bin文件類型介紹執行的基本流程(采用“文件名:函數名”方式)。
1)romInit.s:romInit。
此處romInit函數完成的工作同bootrom,實際上,二者使用相同的romInit函數實現。
2)bootInit.c:romStart。
首先將其自身復制到RAM_HIGH_ADRS變量指向的RAM區,以便從RAM執行。注意與上文中bootrom的區別,雖然使用的是相同的romStart函數實現,但在RAM地址上存在差別,關鍵點在于VxWorks內核映像被復制到RAM_LOW_ADRS指向的內存地址處。
romStart函數完成如下任務:
● 由于是非壓縮版本的VxWorks內核映像,故所有的代碼一次性從ROM復制到由RAM_LOW_ADRS變量指向的RAM內存處。
● 對于cold boot(冷啟動)方式,將其他BSS區清零。
● 最后跳轉到usrInit(注意:是usrConfig.c文件中定義的)函數進行執行。
3)此后的執行流程為:usrConfig.c:usrInit→usrConfig.c:usrRoot。usrConfig.c:usrRoot函數執行完畢后,VxWorks操作系統即已完成啟動,系統進入正常運行狀態。
其他ROM型VxWorks內核映像啟動流程差別如下:
1)是否為ROM駐留方式。
對于ROM駐留方式而言,在以上第一步中只將數據部分從ROM載入到由RAM_LOW_ADRS指向的內存區域,代碼仍然滯留在ROM中,此后一直從ROM中讀取代碼執行,此種執行方式造成效率的部分損失,一般也較少使用。涉及的文件類型為:
VxWorks.res_rom.bin和VxWorks.res_rom_nosym.bin。
2)是否進行了壓縮。
對于壓縮的VxWorks內核映像,在以上第一步復制中,將分兩個階段完成:第一階段完成非壓縮代碼(romInit函數、romStart函數)的復制,這部分代碼被復制到RAM_HIGH_ADRS指向的RAM內存處;第二階段完成壓縮代碼的解壓縮和復制過程,這部分代碼被解壓縮到RAM_LOW_ADRS指向的RAM內存處。
3)是否包含了符號表。
所謂符號表,是內核中定義的所有函數與其(虛擬)地址的對應關系表。符號表與VxWorks內核映像一般是分離的,為了調試方便,一般需要獨立的載入符號表,當然也可以將符號表納入VxWorks內核映像中作為一個整體。VxWorks.st_rom.bin文件類型即將符號表作為了內核映像的一部分。
符號表最大的作用是在命令行直接輸入函數名即可運行該函數,內核查詢符號表獲得對應的地址并轉到該地址處執行。另外,在調試時,也可以對地址進行函數名標注,從而方便調試,符號表與VxWorks內核通常是獨立的,所以無論是否包含符號表,都不會對內核初始化流程造成影響。當VxWorks內核映像被載入RAM后,進入usrInit函數執行時,最終分布圖如圖3-5所示。
ROM型VxWorks內核映像類型啟動流程總結如下(由于其中只涉及VxWorks內核,故采用“文件名:函數名”方式)。
romInit.s:romInit→bootInit.c:romStart→完成VxWorks內核從ROM到RAM的復制(和解壓縮)→usrConfig.c:usrInit→usrConfig.c:usrRoot→VxWorks操作系統啟動完成。