Bootloader通常稱為系統引導加載程序,是系統加電或復位后執行第一段代碼。一般它只在系統啟動時運行非常短時間,但對于嵌入式系統來說,這是一個非常重要系統組成部分。通過這段小程序,可以初始化硬件設備、建立內存空間映射圖,從而將系統軟硬件環境帶到一個合適狀態,以便為調用操作系統內核準備好正確環境,并同時提供基本輸入、輸出系統監控功能和程序調試功能。 Bootloader是嚴重地依賴于硬件而實現。每種不同體系結構處理器都有不同Bootloader。除了依賴于處理器體系結構以外,Bootloader實際上也依賴于具體嵌入式板級設備配置,也就是說,對于兩塊不同嵌入式板而言,即使它們是基于同一種處理器而構建,要想讓運行在一塊板子上Bootloader程序也能運行在另一塊板子上,通常也都需要修改與目標硬件相關代碼。因此有必要分析Bootloader,并理解和找出其中原理和規律,就其特定嵌入式系統,移植或開發屬于自己Bootloader。 1 系統硬件平臺簡介 本系統采用是SamSung公司S3C2410處理器,它是專門為移動手持設備提供高性價比和高性能嵌入式微處理器解決方案。其內核是ARM920T,最高能工作在202.8MHz,為了減少系統總成本和減少外圍器件,它集成了如下部件:分別為16KB指令和數據Cahce、1個LCD控制器、SDRAM控制器、NANDFLASH控制器、3通道UART、4通道DMA、4個具有PWM功能計時器和1個內部時鐘、8通道10位ADC、觸摸屏接口、I2S總線接口,2個USB主機接口、1個USB設備接口,2個SPI接口、SD和MMC卡接口、看門狗定時器、117位通用IO口、24位外部中斷源、8通道10位AD控制器等。本文涉及S3C2410開發板硬件結構如圖1所示,本文主要闡述從Nandflash引導操作系統要完成主要任務和實現方法,至于從Norflash引導操作系統,不打算具體實現。 圖1 S3C2410硬件結構圖 2 存儲空間分布和映射圖 硬件平臺Nandflash(型號是:K9F1208U0M)空間為64MB,SDRAM(型號是:HY57V561620,32Mx2)空間為64M(0x30000000-0x33ffffff),采用如圖2所示存儲空間分布圖,因為Nandflash只能存儲程序,無法運行程序。為了能夠從Nandflash啟動,上電復位時,S3C2410通過硬件邏輯把Nandflash前4KB內容復制到片內SRAM中,而片內SRAM被映射到地址0x0,這樣就可以從地址0x0處取到有效指令,開始執行bootloader,完成把Nandflash中內核代碼復制到sdram中等工作。 圖2 引導代碼和操作系統內核在Nandflash和存儲空間中分布情況 3 Bootloader設計流程 Bootloader引導程序是硬件上電復位后首先運行代碼,由它來加載嵌入式操作系統。然后由操作系統接管整個系統,進行進程管理、內存管理、磁盤管理和各個外設管理等工作。 BootLoader是操作系統內核運行之前一段自舉程序,用來初始化硬件設備、改變處理器運行模式和重組中斷向量,建立內存空間映射圖,將系統軟硬件環境帶到一個由用戶定制特定狀態,然后加載操作系統內核。從操作系統角度來看,Bootloader總目標就是正確地調用內核來執行。Bootloader一般分為stage1和stage2兩大部分,對于依賴于CPU體系結構代碼,比如設備初始化代碼等,通常都放在stage1中,而且通常都用匯編語言來實現,以達到短小精悍目,也就是前面說啟動代碼。而stage2則通常用C語言來實現,這樣可以實現復雜功能,而且代碼會具有更好可讀性和可移植性。 3.1 Bootloaderstage1 這部分代碼必須首先完成一些基本硬件初始化。為stage2 執行以及隨后內核執行準備好一些基本硬件環境。Bootloader stage1 一般通用內容包括: (1)設置中斷和異常向量;(2)禁止看門狗;(3) 屏蔽所有中斷, 在Boot Loader 執行全過程中可以不必響應任何中斷, 中斷屏蔽可以通過寫CPU 中斷屏蔽寄存器或狀態寄存器CPSR 寄存器來完成;(4) 設置CPU 速度和時鐘頻率;(5) 對RAM進行初始化, 包括正確設置系統內存控制器功能寄存器等;(6)初始化LED或UART,就是通過GPIO來驅動LED,也可以通過初始化UART向串口打印Bootloader調試信息來表明系統狀態是OK還是ERROR,以便跟蹤系統運行情況;(7)關閉CPU 內部指令/數據高速緩存(cache);(8)為加載Bootloaderstage2準備RAM空間;(9)設置好堆棧;(10)跳轉到stage2C入口點;其流程圖如圖3所示。 圖3 Bootloaderstage1實現 3.2 Bootloaderstage2 為了讓程序跳入C 語言“main”函數, 我們采用直接跳轉到“main”函數方法, 實現代碼如下: b Main 進入main 函數后即可以開始本階段stage2 初始化任務, 這包括: (1) 如果在stage1沒有初始化UART,這時候至少初始化一個串口, 以便和終端用戶進行交互,當然也可以繼續點亮或熄滅LED來判斷程序執行情況; (2) 修改時鐘頻率; (3) 使能指令Cache; (5) 從串口中打印一些必要交互信息,了解系統狀態; (6) 初始化中斷, 包括屏蔽中斷, 清除中斷懸掛標志, 初始化中斷向量表, 注冊需要中斷處理函數等; (8)打印版本、時間等信息,并從Nandflash復制內核到SDRAM中; (9)修改指針,直接跳到內核在SDRAM中首地址處,至此,完成了Bootloader全部運行加載工作; 下面是main()函數和從Nandflash復制內核到SDRAM中ReadImageFromNandflash()函數具體實現,但省略了一些具體細節,包括從串口打印啟動、交互、調試信息和一些具體函數實現。一些具體函數實現可以參考三星評估版源代碼。 void Main(void) { JumpAddr=0x30200000; //拷貝內核到sdram中起始地址,也是內核開始執行地址 ChangeClockDivider(1,1); //1:2:4 ChangeMPllValue(0x5c,0x1,0x1); // FCLK=202.8MHz MMU_EnableICache(); //使能指令Cache Uart_Init(); // 初始化串口 Port_Init(); //初始化I/O口 NF_Init(); //初始化Nandflash控制器 NF_ReadID(); //讀取Nandflash存儲器ID號 ReadImageFromNandflash();//把存儲在Nandflash中內核拷貝到SDRAM中 rINTMSK=BIT_ALLMSK; //屏蔽所有中斷 Launch(JumpAddr); //跳轉到sdram中內核開始處,并運行內核 } 從Nandflash(Flash是K9F1208U0M)拷貝內核到SDRAM函數具體實現如下: void ReadImageFromNandflash(void) { U8 Image_Buf[512]; U32 Sram_Space=0; U32 j,k, numberblock; static U32 i, SECTOR_SIZE=512; static U8 isbad; volatile U32 IMAGE_BASE=0x30200000; //內核在sdram中運行開始地址 rINTMSK = BIT_ALLMSK; //屏蔽所有中斷 i=2; //從第2個block開始拷貝內核,第0個用于存儲本文bootloader,第1個沒用到 numberblock=2047; //拷貝多少個block到sdram中,視內核大小設置此值 while(1) { nextblock: isbad=0; isbad=NF_IsBadBlock(i); //判斷正在拷貝block是否是壞block if (isbad) //是壞block,就進行相應處理;否則就忽略此處,進行下面拷貝 { i=i 1; //調整,指向下一個block isbad=0; if(i>= numberblock) //判斷是否拷貝完了所需block { Launch(JumpAddr); //拷貝完了所需block,就跳到sdram中內核開始處 } goto nextblock; } for(k=0;k<32;k ) //1 block=32 pages { // FMD_ReadSector()函數實現從Nandflash存儲器中讀取數據到數據緩沖區中 FMD_ReadSector(i, (U8 *)&Image_Buf, k); for (j=0;j<SECTOR_SIZE;j ) //1 page=512 bytes { //從數據緩沖區中拷貝到sdram中 *((U8 *)(IMAGE_BASE Sram_Space j))=Image_Buf[j]; } Sram_Space=Sram_Space SECTOR_SIZE; //調整sdram中偏移地址 } i=i 1; //調整,指向下一個block if(i>= numberblock) //判斷是否拷貝完了所需block { Launch(JumpAddr); //拷貝完了所需block,就跳到sdram中內核開始處 } } } 4 試驗結果 由于三星公司S3C2410集成了Nandflash控制器,它通過硬件邏輯把Nandflash前4KB內容,即把Bootloader復制到片內sram中,并被映射到地址0x0處。通過跳線設置默認從nandflash啟動,那么,系統每次上電或復位后,首先開始運行就是Bootloader。使用ADS1.2集成開發環境建立Bootloader應用工程,添加必需文件并設置好編譯環境,如BootloaderRO_Base設置為0x0,RW_Base設置為0x33ff0000等,調試并最后生成可執行二進制文件,通過JTAG接口把Bootloader燒寫到Nandflash第0個block地址開始處,通過usb下載工具把操作系統燒寫到第2個block地址開始處,復位啟動系統運行后結果如圖4所示,該程序用于基于uCOS操作系統圖像采集系統引導。用同樣方法燒寫不同操作系統內核應用程序,試驗結果每一次表明:Bootloader運行良好,啟動加載內核快,且簡單、實用、可靠。 圖4 Bootloader引導運行系統 5 結論 Bootloader設計與實現是一個非常復雜過程,因此要根據具體硬件和軟件需求分析來進行移植或設計。本文設計Bootloader完成主要功能包括:試驗板硬件初始化、串口初始化、時鐘頻率修改以及從Nandflash復制操作系統到SDRAM中運行等,并通過PC機上超級終端顯示了正確啟動運行信息,且可執行代碼只有3K左右。因此,本文所詳細描述Bootloader啟動運行全過程,對理解、設計和移植Bootloader具有一定參考意義。 |