Bootloader基礎知識.ppt_第1頁
Bootloader基礎知識.ppt_第2頁
Bootloader基礎知識.ppt_第3頁
Bootloader基礎知識.ppt_第4頁
Bootloader基礎知識.ppt_第5頁
已閱讀5頁,還剩64頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第六章 Bootloader,一個嵌入式 Linux 系統(tǒng)從軟件的角度看通??梢苑譃槲鍌€層次:,引導加載程序 包括固化在固件中的 boot 代碼(可選),和 Bootloader 兩大部分。 2. Linux 內核 特定于嵌入式板子的定制內核(包括驅動程序)以及內核的 啟動參數(shù)。 3. 文件系統(tǒng) 建立于 Flash 設備之上文件系統(tǒng)。 4.驅動程序編寫(移植) 5. 用戶應用程序 特定于用戶的應用程序。有時在用戶應用程序和內核層之間 可能還會包括一個嵌入式圖形用戶界面。常用的嵌入式 GUI 有:QT 和 MiniGUI 。,固態(tài)存儲設備的典型空間分配結構,引導加載程序是系統(tǒng)加電后運行的第一段軟

2、件代碼。 在 PC 機中: PC 機中的引導加載程序由 BIOS(其本質就是一段固 件程序)和位于硬盤中的OS Boot Loader(比如,LILO 和 GRUB 等)一起組成。 BIOS: 在完成硬件檢測和資源分配后,將硬盤中的 Boot Loader 讀到系統(tǒng)的 RAM 中,然后將控制權交給 OS Boot Loader。 Boot Loader: 主要運行任務就是將內核映象從硬盤上讀到 RAM 中,然后跳轉到內核的入口點去運行,也即開始啟動 操作系統(tǒng)。,在嵌入式系統(tǒng)中: 通常并沒有像 BIOS 那樣的固件程序 (有的嵌入式 CPU 也會內嵌一段短小的啟動程序) ,因此整個系統(tǒng)的加載啟動

3、任務就完全由 Boot Loader 來完成。 比如在一個基于 ARM7TDMI core 的嵌入式系統(tǒng) 中,系統(tǒng)在上電或復位時通常都從地址 0 x00000000 處 開始執(zhí)行,而在這個地址處安排的通常就是系統(tǒng)的 Boot Loader 程序。,系統(tǒng)加電或復位后,所有的處理器通常都從某個預先 安排的地址上取指令。 比如,ARM在復位時從地址0 x0取指。 嵌入式系統(tǒng)中通常都有某種類型的固態(tài)存儲設備(比 如:ROM、EEPROM 或FLASH 等)被映射到這個預先安 排的地址上。因此在系統(tǒng)加電后,處理器將首先執(zhí)行 Bootloader 程序。 Bootloader是最先被系統(tǒng)執(zhí)行的程序。,每種

4、不同的 CPU 體系結構都有不同的 Boot Loader。 有些 Boot Loader 也支持多種體系結構的 CPU,比如 U-Boot 就同時支持 ARM 體系結構和MIPS體系結構。 Boot Loader 實際上也依賴于具體的嵌入式板級 設備的配置。對于兩塊不同的嵌入式板而言,即使 它們是基于同一種 CPU 而構建的,要想讓運行在一 塊板子上的 Boot Loader 程序也能運行在另一塊 板子上,通常也都需要修改 Boot Loader 的源程序。,一、 bootloader的基本概念 1、什么是bootloader(引導加載程序) 簡單地說BootLoader就是在操作系統(tǒng)內核或

5、用戶應用程序運行之前運行的一段小程序。通過這段小程序,我們可以初始化硬件設備、建立內存空間的映射圖(有的CPU沒有內存映射功能如S3C44B0),從而將系統(tǒng)的軟硬件環(huán)境帶到一個合適的狀態(tài),以便為最終調用操作系統(tǒng)內核或用戶應用程序準備好正確的環(huán)境。,2、 BootLoader的操作模式 多數(shù)BootLoader都包含兩種不同的操作模式。“啟動加載”模式和“下載”模式,這種區(qū)別僅對于開發(fā)人員才有意義。但從最終用戶的角度看,BootLoader的作用就是用來加載操作系統(tǒng),而并不存在所謂的啟動加載模式與下載工作模式的區(qū)別。 啟動加載(Boot loading)模式:這種模式也稱為“自主”(Autono

6、mous)模式,也即BootLoader從目標機上的某個固態(tài)存儲設備上將操作系統(tǒng)加載到RAM中運行,整個過程并沒有用戶的介入。這種模式是BootLoader的正常工作模式。因此在嵌入式產品發(fā)布的時候, BootLoader顯然必須工作在這種模式下。,下載(Down loading)模式: 在這種模式下 目標機上的BootLoader 將通過串口連接或網絡連接等通信手段從主機下載文件,比如:下載應用程序、數(shù)據文件、內核映像等。從主機下載的文件通常首先被BootLoader保存到目標機的RAM中,然后再被BootLoader寫到目標機上的固態(tài)存儲設備中。BootLoader的這種模式通常在系統(tǒng)更新

7、時使用。工作于這種模式下的 BootLoader通常都會向它的終端用戶提供一個簡單的命令行接口。,最常見的情況是,目標機上的BootLoader通過串口與主機之間進行文件傳輸,傳輸協(xié)議通常xmodem/ymodem/zmodem協(xié)議中的一種。但是,由于串口傳輸?shù)乃俣仁怯邢薜?,因此通過以太網連接并借助TFTP協(xié)議來下載文件是個更好的選擇。但是,在通過以太網連接和TFTP協(xié)議來下載文件時,因為主機方必須有一個軟件用來的提供TFTP服務,所以操作相對復雜。,3、BootLoader的啟動過程 由于 Boot Loader 的實現(xiàn)依賴于 CPU 的體系結構,因此大多數(shù) Boot Loader 的啟動都

8、分為 stage1 和 stage2兩大部分。依賴于 CPU 體系結構的代碼,比如設備初始化代碼等,通常都放在 stage1中,而且通常都用匯編語言來實現(xiàn),以達到短小精悍的目的。而 stage2則通常用C語言來實現(xiàn),這樣可以實現(xiàn)更復雜的功能,而且代碼會具有更好的可讀性和可移植性。,通常包括以下步驟(以執(zhí)行的先后順序): 硬件設備初始化 1 屏蔽所有的中斷。為中斷提供服務通常是 OS 設備驅動程序的責任,因此在 Boot Loader 的執(zhí)行全過程中可以不必響應任何中斷。中斷屏蔽可以通過寫 CPU 的中斷屏蔽寄存器或狀態(tài)寄存器(比如 ARM 的 CPSR 寄存器)來完成。 2 設置 CPU 的速

9、度和時鐘頻率。 3 RAM 初始化。包括正確地設置系統(tǒng)的內存控制器的功能寄存器以及各內存庫控制寄存器等。 4 初始化 LED。典型地,通過 GPIO 來驅動 LED,其目的是表明系統(tǒng)的狀態(tài)是 OK 還是 Error。如果板子上沒有 LED,那么也可以通過初始化 UART 向串口打印 Boot Loader 的 Logo 字符信息來完成這一點。 5 關閉 CPU 內部指令數(shù)據 cache。,Boot Loader 的 stage1,為加載 Boot Loader 的 stage2 準備 RAM 空間。 為了獲得更快的執(zhí)行速度,通常把 stage2 加載到 RAM 空間中來執(zhí)行,因此必須為加載 B

10、oot Loader 的 stage2 準備好一段可用的 RAM 空間范圍。 空間大小最好是 memory page 大小(通常是4KB)的倍數(shù)。一般而言,1M 的 RAM 空間已經足夠了。具體的地址范圍可以任意安排。 比如 blob 就將它的 stage2 可執(zhí)行映像安排到從系統(tǒng) RAM 起始地址 0 xc0200000 開始的 1M 空間內執(zhí)行。 拷貝 Boot Loader 的 stage2 到 RAM 空間中。 拷貝時要確定兩點:(1) stage2 的可執(zhí)行映象在固態(tài)存儲設備的存放起始地址和終止地址;(2) RAM 空間的起始地址。 設置好堆棧。 堆棧指針的設置是為了執(zhí)行 C 語言代

11、碼作好準備。 通常我們可以把 sp 的值設置為(stage2_end-4),也即在前面所安排的那個1MB的RAM 空間的最頂端(堆棧向下生長)。 此外,在設置堆棧指針 sp 之前,也可以關閉 LED ,以提示用戶準備跳轉到 stage2。,跳轉到 stage2 的 C 入口點。 在上述一切都就緒后,就可以跳轉到 Boot Loader 的 stage2 去執(zhí)行了。在ARM系統(tǒng)中,可以通過修改PC寄存器為合適的地址來實現(xiàn)。,比如,用以下代碼來實現(xiàn)兩個階段的交接工作。 如(U-Boot中可以用以下兩行代碼實現(xiàn)) ldr pc _start_armboot _start_armboot:.word

12、start_armboot 在vivi中是通過以下實現(xiàn)的: bl main mov pc,#FLASH_BASE,stage2 的代碼通常用 C 語言來實現(xiàn),以便于實現(xiàn)更復雜的功能和取得更好的代碼可讀性和可移植性。 Boot Loader 的 stage2 通常包括以下步驟(以執(zhí)行的先后順序): 初始化本階段要使用到的硬件設備。 通常包括:(1)初始化至少一個串口,以便和終端用戶進行 I/O 輸出信息;(2)初始化計時器等。設備初始化完成后,可以輸出一些打印信息,程序名字字符串、版本號等。 檢測系統(tǒng)內存映射(memory map)。 所謂內存映射就是指在整個 4GB 物理地址空間中有哪些地址范

13、圍被分配用來尋址系統(tǒng)的 RAM 單元。比如,在 SA-1100 CPU 中,從0 xC000,0000 開始的 512M 地址空間被用作系統(tǒng)的 RAM 地址空間,而在 Samsung S3C44B0X CPU 中,從0 x0c00,0000 到 0 x1000,0000 之間的 64M 地址空間被用作系統(tǒng)的 RAM 地址空間。,Bootloader 的stage2,將 kernel 映像和根文件系統(tǒng)映像從 flash 上讀到 RAM 空間中。 (1)規(guī)劃內存占用的布局這里包括兩個方面:內核映像所占用的內存范圍;根文件系統(tǒng)所占用的內存范圍。在規(guī)劃內存占用的布局時,主要考慮基地址和映像的大小兩個方

14、面。 (2)從 Flash 上拷貝數(shù)據 為內核設置啟動參數(shù)。 在將內核映像和根文件系統(tǒng)映像拷貝到 RAM 空間中后,就可以準備啟動 Linux 內核了。但是在調用內核之前,應該作一步準備工作,即:設置 Linux 內核的啟動參數(shù)。 調用內核。,VIVI簡介,VIVI是韓國Mizi公司開發(fā)的BootLoader,可用于ARM9處理器的引導。VIVI利用串行通信為用戶提供接口。為連接VIVI,首先利用串口電纜連接宿主機和目標板,然后在主機上運行串口通信程序(minicom),并在目標板上正確設置VIVI以支持串口。正確連接后,就可以由串口通信程序顯示提示信息,提示信息的最后一行如下所示: Pres

15、s Return to start the LINUX now, any other key for vivi. VIVI也有前面說過的兩種工作模式,啟動模式可以在一段時間后自行啟動Linux內核,這是VIVI的默認方式。出現(xiàn)上述信息后,如果按除回車鍵外的任意鍵,即可進入下載模式,出現(xiàn)“vivi”提示符。在下載模式下,VIVI為用戶提供了一個命令行接口,通過該接口可以使用VIVI提供的一些命令。,二、常用BootLoader代碼分析,1load命令 將二進制文件載入到Flash或者RAM,命令格式: load | 其中命令行參數(shù)描述裝載位置,有flash和ram兩種選項;參數(shù) 或 描述裝載的地

16、址,如果有提前定義的MTD分區(qū)信息,可以只輸入分區(qū)名稱,否則需要指定地址和大??;參數(shù) 確定文件的傳輸協(xié)議,常采用的選項“x”用來指定采用xmodem協(xié)議。 例如:vivi load flash kernel x,裝載壓縮映像文件zImage到flash存儲器中,地址是kernel分區(qū),并采用xmodem傳輸協(xié)議。 也可以指定地址和大小,例如:vivi load flash 0 x80000 0 xc0000 x。,2part命令 操作MTD分區(qū)信息,比如,顯示、增加、刪除、復位、保存MTD分區(qū)等。 part show:顯示mtd分區(qū)信息。 part add :增加新的mtd分區(qū),其中為新mtd

17、分區(qū)名稱,是mtd器件的偏移,表示mtd分區(qū)的大小,表示分區(qū)類型,可選項有JFFS2、LOCKED和BONFS。 part del :刪除一個mtd分區(qū)。 part reset:恢復mtd 分區(qū)為默認值。 part save:在flash中永久保存參數(shù)值和分區(qū)信息。 3param命令 用來設置或者察看參數(shù)。例如:改變“l(fā)inux command line”,使用 vivi param set linux_cmd_line “you wish.”。 也可以改變引導程序啟動的時間,使用vivi param set boot_delay 100000實現(xiàn)。,4boot命令 用來引導存儲在flash存

18、儲器或者RAM中的linux內核。命令格式: boot | 參數(shù) 設定存儲linux內核映像的位置,可選項有ram、nor和smc。 參數(shù) 或 描述存儲內核的地址,如果有提前定義的MTD分區(qū)信息,可以只輸入分區(qū)名稱,否則需要指定地址和大小。 例如:vivi boot nor 0 x80000表示從flash存儲器中讀出linux內核,偏移是0 x80000。 5flash命令 存儲器管理命令,例如:flash erase | ,表示擦除flash存儲器。,VIVI的代碼分析與移植,1arch 此目錄包括了所有VIVI支持的目標板的子目錄,例如s3c2410目錄 。 2Documentation

19、 存放了許多文檔,非常詳細,主要是VIVI的使用指南。 3drivers 其中包括了引導內核所需的MTD設備(mtd)和串口驅動程序(serial)。MTD目錄下分maps、nand和nor三個目錄,實現(xiàn)對Nand Flash和Nor Flash的讀寫控制。Serial目錄下的文件實現(xiàn)對串口的控制,并支持xmodem和ymodem協(xié)議。 4include 頭文件的公共目錄,其中的S3C2410.h定義了處理器的一些寄存器,以及NAND Flash的一些寄存器等。Platform/smdk2410.h定義了與目標板相關的資源配置參數(shù),修改波特率、引導參數(shù)和物理內存映射等參數(shù)就可適用于自己的目標板

20、。,5Init 這個目錄只有main.c和version.c兩個文件。與普通的C程序一樣,VIVI將從main函數(shù)開始執(zhí)行。 6Lib 一些平臺公共的接口代碼,比如,time.c里的udelay()和mdelay()。 7scripts 主要在配置時用到,存放了配置所需的腳本文件,如Menuconfig和Configure文件,以方便對VIVI的配置。,VIVI的運行也可以分為兩個階段。 在第一階段完成含有依賴于CPU體系結構硬件初始化的代碼,利用匯編語言完成。 第二階段是用C語言完成的。在跳轉進main()函數(shù)之前,利用匯編語言編寫了一段trampoline程序(彈簧床)作為階段2可執(zhí)行鏡像

21、的執(zhí)行入口點。之后可以在trampoline中用處理器的跳轉指令進入main()函數(shù)中去執(zhí)行。 當main()函數(shù)返回時,CPU就進行復位。,vivi的第一階段,完成含依賴于CPU的體系結構硬件初始化的代碼,包括禁止中斷、初始化串口、復制自身到RAM等。相關代碼集中在head.S(viviarchs3c2410目錄下):,Head.S: #include config.h #include linkage.h #include machine.h Start of executable code ENTRY(_start) ;程序入口點 ENTRY(ResetEntryPoint) , Exc

22、eption vector table (physical address = 0 x00000000) ;異常向量表物理地址 0 x00: Reset ;復位異常 b Reset 0 x04: Undefined instruction exception ;未定義的指令異常 UndefEntryPoint: b HandleUndef 0 x08: Software interrupt exception ;軟件中斷異常,SWIEntryPoint: b HandleSWI 0 x0c: Prefetch Abort (Instruction Fetch Memory Abort) ;內存

23、操作異常 PrefetchAbortEnteryPoint: b HandlePrefetchAbort 0 x10: Data Access Memory Abort ;數(shù)據異常 DataAbortEntryPoint: b HandleDataAbort 0 x14: Not used ;未使用 NotUsedEntryPoint: b HandleNotUsed 0 x18: IRQ(Interrupt Request) exception ;普通中斷異常,IRQEntryPoint: b HandleIRQ 0 x1c: FIQ(Fast Interrupt Request) exce

24、ption ;快速中斷異常 FIQEntryPoint: b HandleFIQ VIVI magics ,ARM規(guī)定,在起始必須有8條跳轉指令,可以用b,也可以用ldr pc,文件名。這樣的8條規(guī)則的標志被arm定義為bootloader的識別標志,檢測到這樣的標志后,就可以從該位置啟動。這樣的做法是因為開始的時候不一定有bootloader,必須有一種識別機制,如果識別到bootloader,那么就從bootloader啟動。,下面是固定位置存放環(huán)境變量 對vivi的這些magic number,雖然設計在這里,不過大部分沒有使用。其中0 x20和0 x24沒有使用,在0 x2C處,設計了

25、一個magic number,組成的格式如下:bit31:24為platform,bit23:16為cpu type,bit15:0為machine id。關于ARCHITECTURE_MAGIC的定義,在【include/platform/smdk2410.h】, 0 x20: magic number so we can verify that we only put .long 0 0 x24: .long 0 0 x28: where this vivi was linked, so we can put it in memory in the right place .long _s

26、tart 0 x2C: this contains the platform, cpu and machine id .long ARCHITECTURE_MAGIC 0 x30: vivi capabilities .long 0 #ifdef CONFIG_PM ;vivi沒有使用電源管理 0 x34: b SleepRamProc #endif #ifdef CONFIG_TEST 0 x38: b hmi #endif Start VIVI head Reset:, disable watch dog timer ;禁止看門狗計時器 mov r1, #0 x53000000 ;WTCO

27、N寄存器地址是 0 x53000000,清0 mov r2, #0 x0 str r2, r1 #ifdef CONFIG_S3C2410_MPORT3 ;不符合條件,跳到下面的關中斷 /* 在/vivi/include/autoconf.h中#undef CONFIG_S3C2410_MPORT3*/ mov r1, #0 x56000000 ;GPACON寄存器地址是 0 x56000000 mov r2, #0 x00000005 str r2, r1, #0 x70 ;配置GPHCON控制寄存器 mov r2, #0 x00000001 str r2, r1, #0 x78 ;配置GP

28、HUP上拉寄存器 mov r2, #0 x00000001 str r2, r1, #0 x74 ;配置GPHDAT數(shù)據寄存器,#endif disable all interrupts ;禁止全部中斷 mov r1, #INT_CTL_BASE mov r2, #0 xffffffff str r2, r1, #oINTMSK ;掩碼關閉所有中斷 ldr r2, =0 x7ff str r2, r1, #oINTSUBMSK, initialise system clocks ;初始化系統(tǒng)時鐘 mov r1, #CLK_CTL_BASE ;定義CLK_CTL_BASE ox4C000000

29、mvn r2, #0 xff000000 str r2, r1, #oLOCKTIME ldr r2, mpll_50mhz ;CPU的頻率是50MHz str r2, r1, #oMPLLCON #ifndef CONFIG_S3C2410_MPORT1 ;滿足條件,向下執(zhí)行 /* 在/vivi/include/autoconf.h中#undef CONFIG_S3C2410_MPORT1*/ 1:2:4 mov r1, #CLK_CTL_BASE mov r2, #0 x3 str r2, r1, #oCLKDIVN mrc p15, 0, r1, c1, c0, 0 read ctrl

30、register orr r1, r1, #0 xc0000000 Asynchronous mcr p15, 0, r1, c1, c0, 0 write ctrl register now, CPU clock is 200 Mhz ;CPU的頻率是200MHz mov r1, #CLK_CTL_BASE ldr r2, mpll_200mhz str r2, r1, #oMPLLCON,#else 1:2:2 mov r1, #CLK_CTL_BASE ldr r2, clock_clkdivn str r2, r1, #oCLKDIVN mrc p15, 0, r1, c1, c0,

31、0 read ctrl register orr r1, r1, #0 xc0000000 Asynchronous mcr p15, 0, r1, c1, c0, 0 write ctrl register now, CPU clock is 100 Mhz ;CPU的頻率是100MHz mov r1, #CLK_CTL_BASE ldr r2, mpll_100mhz str r2, r1, #oMPLLCON #endif bl memsetup ;跳轉到memsetup函數(shù),/* Memsetup函數(shù)的實現(xiàn): ENTRY(memsetup) initialise the static

32、memory set memory control registers ;設置內存控制寄存器的初值 mov r1, #MEM_CTL_BASE adrl r2, mem_cfg_val /* Data Area Memory configuration values .align 4 mem_cfg_val: ;定義好的13*4=52個字節(jié)初值,.long vBWSCON ;總線寬度和等待控制寄存器 在/vivi/include/platform/smdk2410.h中賦值 /* SDRAM從32位變成16位,需要修改vBWSCON的值 */ .long vBANKCON0 .long vBA

33、NKCON1 .long vBANKCON2 .long vBANKCON3,/* 網卡控制器vBANKCON3的值可能需要修改 */ .long vBANKCON4 .long vBANKCON5 .long vBANKCON6 /* SDRAM從32位變成16位,可能需要修改vBANKCON6的值 */ .long vBANKCON7 .long vREFRESH ;SDRAM刷新控制寄存器 .long vBANKSIZE ;可變的組大小寄存器 /* SDRAM從64MB變成32MB,需要修改vBANKSIZE的值 */ .long vMRSRB6 ;BANK6的模式設置寄存器 .long

34、 vMRSRB7 ;BANK7的模式設置寄存器 */ add r3, r1, #52 1: ldr r4, r2, #4 str r4, r1, #4 cmp r1, r3 bne 1b ;循環(huán)操作,直到13個寄存器賦值完成 mov pc, lr,*/ #ifdef CONFIG_PM ;vivi考慮不需要使用電源管理 Check if this is a wake-up from sleep ldr r1, PMST_ADDR ldr r0, r1 tst r0, #(PMST_SMR) bne WakeupStart ;查看狀態(tài),判斷是否需要跳轉到WakeupStart #endif #i

35、fdef CONFIG_S3C2410_SMDK ;SMDK開發(fā)板使用 All LED on ;點亮開發(fā)板上的LED mov r1, #GPIO_CTL_BASE add r1, r1, #oGPIO_F ;LED使用GPIOF組的管腳 ldr r2,=0 x55aa ;使能EINT0,EINT1,EINT2,EINT3, ;另四個管腳配置成輸出,屏蔽EINT4,5,6,7 str r2, r1, #oGPIO_CON ;配置管腳 mov r2, #0 xff str r2, r1, #oGPIO_UP ;禁止上拉功能 mov r2, #0 x00 str r2, r1, #oGPIO_DAT

36、 ;PORT H 數(shù)據寄存器,#endif #if 0 SVC ;進入系統(tǒng)管理模式 mrs r0, cpsr bic r0, r0, #0 xdf orr r1, r0, #0 xd3 msr cpsr_all, r1 #endif set GPIO for UART ;設置串口 mov r1, #GPIO_CTL_BASE add r1, r1, #oGPIO_H ;設置GPIO_H組管腳為串口 ldr r2, gpio_con_uart str r2, r1, #oGPIO_CON ldr r2, gpio_up_uart str r2, r1, #oGPIO_UP /* initial

37、values for GPIO gpio_con_uart: .long vGPHCON ;vGPHCON在/vivi/include/platform/smdk2410.h中賦值 ;#define vGPHCON 0 x0016faaa ;GPIO_H配置為nCTS0,nRTS0, RXD0,TXD0, RXD1, ,TXD1,nCTS1,nRTS1,/* 三個串口都使能,可能需要修改#define vGPHCON 0 x0016aaaa */ gpio_up_uart: .long Vgphup ;同上 #define vGPHUP 0 x000007ff ;The pull-up fun

38、ction is disabled. */ bl InitUART ;跳轉到InitUART串口初始化函數(shù) Initialize UART r0 = number of UART port InitUART: ldr r1, SerBase /* .align 4 ;缺省情況下在vivi中只初始化了UART0 SerBase: #if defined(CONFIG_SERIAL_UART0) .long UART0_CTL_BASE ;基地址在/vivi/include/s3c2410.h中定義 #elif defined(CONFIG_SERIAL_UART1) .long UART1_CT

39、L_BASE #elif defined(CONFIG_SERIAL_UART2) .long UART2_CTL_BASE #else #error not defined base address of serial #endif,*/ mov r2, #0 x0 str r2, r1, #oUFCON ; UART FIFO控制寄存器 str r2, r1, #oUMCON ; UART MODEM控制寄存器 mov r2, #0 x3 str r2, r1, #oULCON ; UART 列控制寄存器 ldr r2, =0 x245 str r2, r1, #oUCON ; UART控

40、制寄存器 #define UART_BRD (50000000 / (UART_BAUD_RATE * 16) - 1) mov r2, #UART_BRD; 波特率設置 str r2, r1, #oUBRDIV ;波特率約數(shù)寄存器 mov r3, #100 mov r2, #0 x0 1: sub r3, r3, #0 x1 tst r2, r3 bne 1b #if 0 mov r2, #U str r2, r1, #oUTXHL ; UART 傳輸緩沖區(qū)寄存器 1: ldr r3, r1, #oUTRSTAT ;UART 錯誤寄存器,and r3, r3, #UTRSTAT_TX_EMP

41、TY tst r3, #UTRSTAT_TX_EMPTY bne 1b mov r2, #0 str r2, r1, #oUTXHL 1: ldr r3, r1, #oUTRSTAT ;UART TX/RX狀態(tài)寄存器 and r3, r3, #UTRSTAT_TX_EMPTY tst r3, #UTRSTAT_TX_EMPTY bne 1b #endif mov pc, lr */ #ifdef CONFIG_DEBUG_LL ;打印調試信息,缺省未定義 Print current Program Counter ldr r1, SerBase mov r0, #r bl PrintChar

42、mov r0, #n bl PrintChar mov r0, #,bl PrintChar mov r0, pc bl PrintHexWord #endif #ifdef CONFIG_BOOTUP_MEMTEST simple memory test to find some DRAM flaults. bl memtest #endif #ifdef CONFIG_S3C2410_NAND_BOOT ;從NAND Flash啟動 bl copy_myself ;跳轉到copy_myself函數(shù) , /* copy_myself: copy vivi to ram;復制到RAM copy

43、_myself: mov r10, lr reset NAND; 復位NAND FLASH mov r1, #NAND_CTL_BASE ldr r2, =0 xf830 initial value,str r2, r1, #oNFCONF ;配置NAND FLASH ldr r2, r1, #oNFCONF bic r2, r2, #0 x800 ;芯片使能,Bit11為0,使能,即允許訪問 str r2, r1, #oNFCONF mov r2, #0 xff RESET command strb r2, r1, #oNFCMD ;設置NAND FLASH命令 mov r3, #0 wai

44、t 1: add r3, r3, #0 x1 cmp r3, #0 xa blt 1b 2: ldr r2, r1, #oNFSTAT wait ready ; NAND FLASH操作狀態(tài)寄存器 tst r2, #0 x1 beq 2b ldr r2, r1, #oNFCONF orr r2, r2, #0 x800 ;禁止芯片,不允許訪問 str r2, r1, #oNFCONF get read to call C functions (for nand_read() ldr sp, DW_STACK_START setup stack pointer mov fp, #0 no pre

45、vious frame, so fp=0 copy vivi to RAM ldr r0, =VIVI_RAM_BASE,*/ mov r1, #0 x0 mov r2, #0 x20000 ;0 x20000-128k字節(jié) bl nand_read_ll ;nand_read_ll在/vivi/arch/s3c2410/nand_read.c中定義 ;r0,r1,r2分別為函數(shù)的三個參數(shù) ;從NANDFlash的0地址拷貝128k到SDRAM指定處 tst r0, #0 x0 beq ok_nand_read #ifdef CONFIG_DEBUG_LL bad_nand_read: ldr

46、 r0, STR_FAIL ldr r1, SerBase bl PrintWord 1: b 1b infinite loop #endif ok_nand_read: #ifdef CONFIG_DEBUG_LL ldr r0, STR_OK ldr r1, SerBase bl PrintWord #endif,/*在/vivi/linux/platform/smdk2410.h中定義 #define VIVI_RAM_BASE (DRAM_BASE + DRAM_SIZE - VIVI_RAM_SIZE), verify mov r0, #0 ldr r1, =0 x33f00000

47、mov r2, #0 x400 4 bytes * 1024 = 4K-bytes go_next: ldr r3, r0, #4 ldr r4, r1, #4 teq r3, r4 bne notmatch subs r2, r2, #4 beq done_nand_read bne go_next notmatch: #ifdef CONFIG_DEBUG_LL sub r0, r0, #4 ldr r1, SerBase bl PrintHexWord ldr r0, STR_FAIL ldr r1, SerBase bl PrintWord #endif,1: b 1b done_na

48、nd_read: #ifdef CONFIG_DEBUG_LL ldr r0, STR_OK ldr r1, SerBase bl PrintWord #endif mov pc, r10 ;vivi拷貝到SDRAM完成,函數(shù)返回 */ jump to ram ldr r1, =on_the_ram add pc, r1, #0 nop nop 1: b 1b infinite loop on_the_ram: #endif #ifdef CONFIG_DEBUG_LL ldr r1, SerBase ldr r0, STR_STACK bl PrintWord ldr r0, DW_STAC

49、K_START bl PrintHexWord #endif, get read to call C functions ldr sp, DW_STACK_START setup stack pointer mov fp, #0 no previous frame, so fp=0 mov a2, #0 set argv to NULL bl main call main mov pc, #FLASH_BASE otherwise, reboot End VIVI head ,Bootloader的第二階段是用C語言完成的,但是與普通 C語言應用程序不同的是,在編譯和鏈接Bootloader時

50、,不能使用glibc庫中的任何支持函數(shù),從哪里跳轉進 main() 函數(shù)呢? 直接把 main() 函數(shù)的起始地址作為整個 stage2 執(zhí)行映像的入口點或許是最直接的想法。 但是這樣做有兩個缺點: 1)無法通過main() 函數(shù)傳遞函數(shù)參數(shù); 2)無法處理 main() 函數(shù)返回的情況。 一種較為巧妙的方法是利用彈簧床的概念,也就是用匯編語言寫一段trampoline 小程序,并將這段程序作為stage2可執(zhí)行映象的執(zhí)行入口點,然后在trampoline匯編小程序中用CPU跳轉指令跳入main()函數(shù)中去執(zhí)行。當main()函數(shù)返回時,CPU執(zhí)行路徑再次回到trampoline程序。簡而言之

51、,這種方法的思想就是:用這段 trampoline小程序來作為main()函數(shù)的外部包裹。,vivi的第二階段,Trampoline程序的源代碼如下: ldrsp,DW_STACK_START;設置堆棧指針 movfp,#0 ;no previous frame,so fp=0 mova2,#0 ;set argv to NULL blmain ;call main movpc,#FLASH_BASE ;否則,reboot,vivi的第二階段是從main()函數(shù)開始,同一般的C語言程序一樣,該函數(shù)在/init/main.c文件中,總共可以分為8個步驟。 (1) 函數(shù)開始,通過putstr(vi

52、vi_banner)打印出vivi的版本。 Vivi_banner在/init/version.c文件中定義 (2) 對開發(fā)板進行初始化(board_init函數(shù)),board_init是與開發(fā)板緊密相關的,這個函數(shù)在/arch/s3c2410/smdk.c文件中。開發(fā)板初始化主要完成兩個功能,時鐘初始化(init_time())和通用IO口設置(set_gpios())。,void set_gpios(void) GPACON = vGPACON; GPBCON = vGPBCON; GPBUP = vGPBUP; GPCCON = vGPCCON; GPCUP = vGPCUP; GPDC

53、ON = vGPDCON; GPDUP = vGPDUP; GPECON = vGPECON; GPEUP = vGPEUP; GPFCON = vGPFCON; GPFUP = vGPFUP; GPGCON = vGPGCON; GPGUP = vGPGUP; GPHCON = vGPHCON; GPHUP = vGPHUP; EXTINT0 = vEXTINT0; EXTINT1 = vEXTINT1; EXTINT2 = vEXTINT2; GPIO口在smdk2410.h(viviincludeplatform目錄下)文件中定義。 這里vGPxCON中的v表示value,oGPxCON

54、中的o表示offset,(3) 內存映射初始化和內存管理單元的初始化工作: mem_map_init(); mmu_init(); 這兩個函數(shù)都在/arch/s3c2410/mmu.c文件中。 void mem_map_init(void) #ifdef CONFIG_S3C2410_NAND_BOOT mem_map_nand_boot(); #else mem_map_nor(); #endif cache_clean_invalidate(); tlb_invalidate(); 如果配置vivi時使用了NAND作為啟動設備,則執(zhí)行mem_map_nand_boot(),否則執(zhí)行mem_

55、map_nor()。這里要注意的是,如果使用NOR啟動,則必須先把vivi代碼復制到RAM中。這個過程是由copy_vivi_to_ram()函數(shù)來完成的。代碼如下: static void copy_vivi_to_ram(void) putstr_hex(Evacuating 1MB of Flash to DRAM at 0 x, VIVI_RAM_BASE); memcpy(void *)VIVI_RAM_BASE, (void *)VIVI_ROM_BASE,VIVI_RAM_SIZE); ,VIVI_RAM_BASE、VIVI_ROM_BASE、VIVI_RAM_SIZE這些值都可以在smdk2410.h中查到,并且這些值必須根據自己開發(fā)板的RAM實際大小修改。這也是在移植vivi的過程中需要注意的一個地方。 mmu_init()函數(shù)中執(zhí)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論