Bootloader/u-boot的啓動模式

Bootloader/u-boot的啓動模式

對於計算機系統來說,從計算機開機上電的到操作系統的啓動需要一個引導過程。嵌入式Linux同樣也需要一個引導的過程,及引導程序就叫做Bootloader。Bootloader是在操作系統啓動之前執行的一小段程序,通過這段小程序,我們可以初始化硬件設備、建立內存空間映射表,從而建立適當系統軟硬件環境,爲最終調用操作系統內核做好準備。 對於嵌入式系統,Bootloader是基於特定平臺來實現的,因此幾乎不可能爲所有的計算機操作系統建立一個通用的Bootloader,不同的處理器架構都有不同的Bootloader,Bootloader不但依賴於CPU的體系結構,而且依賴於嵌入式系統板級的設備的配置。對於兩塊不同的嵌入式開發板,即使他們使用同一種處理器,要想讓運行於一塊板子上的Bootloader運行在另一塊板子上,一般都需要修改Bootloader源程序。 反過來大多數的Bootloader都具有很多的共性,某些Bootloader也能夠支持多種體系結構的嵌入式系統。例如:u-boot就同時支持Powerpc、ARm、MIPS和X86等等的體系結構,支持的板子有上百種,通常他們都能夠自動從存儲介質上啓動,都能夠引導操作系統啓動,並且大部分都可以支持串口和網口的操作。 系統加電或者復位後,cpu通常都會從某個地址開始執行,這是由處理器決定的,對於ARM處理器而言會從0x00000000取第一條指令,嵌入式系統的開發板都要把ROM和FLASH映射到這個地址上,因此必須將Bootloader的程序存儲在相應的FLASH位置,這樣系統加電後就會首先執行它。 u-boot的啓動一般流程:第一階段:依賴cpu初始化外圍硬件代碼,通常用匯編代碼實現 1、設置cpu的工作模式; 2、關中斷,以防止意外發生; /************************************************* * set the cpu to SVC32 mode,設置cpu工作模式爲11010011, * 後五位表示cpu的工作模式設置爲”管理”,並且關閉中斷 * 110則表示IRQ(普通中斷)和FIQ(快速中斷)都爲禁止 **************************************************/ mrs r0,cpsr//讀取cpsr中的數據到r0中 bic r0,r0,#0x1f//將寄存器r0的值和0x1f的反碼安位與之後將結果存儲在r0中相當於清零 orr r0,r0,#0xd3//將寄存器r0的值和0xd3 安位或之後將結果保存在r0寄存器之中,關閉中斷 msr cpsr,r0//將cpsr中的數值寫到r0寄存器中 3、關閉看門狗,避免系統重啓; #ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440) /* turn off the watchdog ,關閉開門狗*/ # if defined(CONFIG_S3C2400) # define pWTCON 0x15300000 # define INTMSK 0x14400008 /* Interupt-Controller base addresses */ # define CLKDIVN 0x14800014 /* clock divisor register */ #else # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* clock divisor register */ # endif 4、設置back初始化,設置cpu的工作頻率; #if defined(CONFIG_S3C2440) /*FCLK HCLK PCLK = 1: 4: 8*/ ldr r0, =CLKDIVN mov r1,#5 str r1,[r0] mrc p15,0,r1,c1,c0,0 orr r1, r1,#0xc0000000 mcr p15,0,r1,c1,c0,0 mov r1,#CLK_CTL_BASE mov r2,#MDIV_405 add r2,r2,#PSDIV_405 str r2,[r1,#0x4] #else /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] #endif /* CONFIG_S3C2400 || CONFIG_S3C2410 * 5、從FLASH拷貝到RAM; #ifndef CONFIG_SKIP_RELOCATE_UBOOT relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code *///adr是讀取地址的僞指令,表示將_start標示的運行地址給r0 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */// 表示將_TEXT_BASE 指向的地址中的數據拷貝到r1中 cmp r0, r1 /* don't reloc during debug *///比較是否相同 beq stack_setup //相同跳轉出去 /*****************不同 則執行以下代碼***********************/ ldr r2, _armboot_start //start起始地址,包含RO代碼段+RW 數據段+ZI全局變量 ldr r3, _bss_start //全局變量的地址 sub r2, r3, r2 /* r2 <- size of armboot *///相減之後得到的是代碼段+數據段的總大小 add r2, r0 r2, /* r2 <- source end address *///r0是要燒錄的內容,表示的是燒錄的代碼段+數據段的結束地址 copy_loop: ldmia r0!, {r3-r10} /* copy from source address [r0] *///ldmia批量的拷貝,向後拷貝32位到r3-r10(將r0中的數據讀出到r3-r10的,r0自動加一) stmia r1!, {r3-r10} /* copy to target address [r1] *///stmia批量的存儲到r1上也就是目標運行的地址上(將r3-r10中的數據保存到r1指向的地址上,r1自動加一) cmp r0, r2 /* until source end addreee [r2] *///r0 燒錄的起始地址,r2燒錄的結束地址,相等則說明拷貝完成 ble copy_loop #endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 6、設置建立堆棧; 7、執行內存地址上的程序,該工作可以使ldr pc來完成; start.s是u-boot啓動所執行的第一個文件,它說做的是設置系統堆棧和cpu的工作方式,爲進入c程序奠定基礎。第二階段:用c語言完成,以實現更復雜的命令 1、 調用系統一系列的初始化函數; 2、 初始化Flash設備; 3、 初始化系統內存分配函數; 4、 如果目標系統有NAND設備,則初始化NAND設備; 5、 如果系統擁有顯示設備,則初始化該類設備; 6、 初始化相關網絡設備,填寫IP、MAC地址等; 7、 進去命令循環(即整個boot的工作循環),接收用戶從串口輸入的相關命令,然後進行相應的工作;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章