,
(1.西南交通大學(xué) 信息科學(xué)與技術(shù)學(xué)院,成都 611756;2.西南交通大學(xué) 交通與運(yùn)輸學(xué)院)
ldrpc, _start_armboot
_start_armboot:
.word start_armboot
董君,倪少權(quán)2
(1.西南交通大學(xué) 信息科學(xué)與技術(shù)學(xué)院,成都 611756;2.西南交通大學(xué) 交通與運(yùn)輸學(xué)院)
詳細(xì)分析基于S3C6410的嵌入式平臺的U-Boot源代碼和啟動(dòng)過程。在此基礎(chǔ)上成功移植了U-Boot軟件,實(shí)現(xiàn)了S3C6410處理器時(shí)鐘初始化、串口通信、內(nèi)存初始化、MMU初始化、NAND Flash初始化。通過移植NAND Flash驅(qū)動(dòng),實(shí)現(xiàn)讀寫NAND Flash和從NAND Flash啟動(dòng)的功能,使得整個(gè)系統(tǒng)能夠正常運(yùn)行。
U-Boot;分析;移植;NAND Flash驅(qū)動(dòng)
U-Boot全稱 Universal BootLoader,是遵循GPL條款的開放源碼項(xiàng)目。U-Boot在嵌入式設(shè)備中起著初始化硬件、引導(dǎo)系統(tǒng)、為操作系統(tǒng)做準(zhǔn)備的作用,因此分析與移植U-Boot有著重要的意義。
首先找到board/samsung/smdk6410/的u-boot.lds(連接器腳本),連接器腳本的作用主要是配置U-Boot程序的布局,由其中的.text部分可知,第一部分代碼從cpu/s3c64xx/start.S開始執(zhí)行。因此分析start.S是U-Boot分析的第一階段。
(1)建立異常向量表
由于ARM處理器有7種異常,分別是:復(fù)位、未定義指令、軟中斷、指令預(yù)取終止、數(shù)據(jù)終止、外部中斷請求、快速中斷請求,所以有7個(gè)異常向量。
(2)設(shè)置處理器工作模式
設(shè)置ARM的運(yùn)行模式為32位管理模式。
(3)CPU初始化
首先沖洗指令/數(shù)據(jù)緩存、關(guān)閉MMU和cache、設(shè)置外設(shè)基地址。接著通過bl lowlevel_init指令跳轉(zhuǎn)到標(biāo)號 lowlevel_init處執(zhí)行,其位于boardsamsungsmdk6410下。
(4)點(diǎn)亮LED/關(guān)閉看門狗/關(guān)閉中斷
點(diǎn)亮LED能夠檢驗(yàn)之前的步驟是否正確,關(guān)閉看門狗/中斷能夠讓系統(tǒng)不受外界的影響正常啟動(dòng)。S3C6410中斷控制器有64個(gè)中斷源,其中有VIC0和VIC1兩個(gè)中斷矢量控制器。
(5)S3C6410時(shí)鐘初始化
S3C6410系統(tǒng)控制器主要包含系統(tǒng)時(shí)鐘控制單元和系統(tǒng)電源管理單元,其中時(shí)鐘控制單元主要包括APLL、 MPLL、 EPLL三個(gè)鎖相環(huán)。
APLL主要供給S3C6410核心ARM1176使用,最大能達(dá)到667 MHz,一般為533 MHz。MPLL主要給系統(tǒng)時(shí)鐘使用,主要用在AXI、AHB和 APB總線,在AXI/AHB上時(shí)鐘最大能達(dá)133 MHz,在APB上能達(dá)到66 MHz。EPLL主要給外圍的設(shè)備提供時(shí)鐘。三星提供了可供選擇的時(shí)鐘配置參數(shù):APLL=533 MHz,MPLL=266 MHz,HCLKX2=266 MHz,HCLK=133 MHz,PCLK=66 MHz。
S3C6410時(shí)鐘配置步驟如下:
① 首先配置APLL_CON/MPLL_CON寄存器,根據(jù)三星提供的配置參數(shù),當(dāng)FIN=12 MHz,輸出為533 MHz時(shí),MDIV=266,PDIV=3, SDIV=1。
② 設(shè)置分頻系數(shù),S3C6410主要有三個(gè)控制器存器CLK_DIV0、CLK_DIV1、CLK_DIV2。APLL 和MPLL 輸出的頻率由CLK_DIV0中的ARM_RATIO、MPLL_RATIO決定。HCLKX2、HCLK、PCLK頻率分別由CLK_DIV0中的HCLKX2_RATIO、HCLK_RATIO、PCLK_RATIO決定。參考值:ARM_RATIO =0,MPLL_RATIO=1,HCLKX2_RATIO=1,HCLK_RATIO=1,PCLK_RATIO=3。
(6)串口初始化
S3C6410串口控制器主要是UART(通用異步接收發(fā)送器)。S3C6410的UART提供了4路獨(dú)立的異步串行I/O端口,每個(gè)UART主要包含控制單元、波特率發(fā)生器、發(fā)送器、接收器。波特率需要的時(shí)鐘源可以是PCLK, EXT_UCLK0 或者EXT_UCLK1。
S3C6410寄存器主要包括:ULCONn(線控制寄存器),控制數(shù)據(jù)傳輸格式,主要包含一個(gè)起始位、5~8個(gè)數(shù)據(jù)位、1個(gè)奇偶校驗(yàn)位和1~2個(gè)停止位;UCONn(UART控制寄存器),選擇產(chǎn)生UART波特率的時(shí)鐘,控制數(shù)據(jù)傳輸/接收方式(中斷/輪詢)等;UFCONn(UART FIFO控制器寄存器),選擇是否啟用FIFO(主要是用來存儲(chǔ)發(fā)送/接收的數(shù)據(jù));UTRSTATn(UART 發(fā)送/接收寄存器),第0位和第1位分別表示接收和發(fā)送數(shù)據(jù)的緩沖的狀態(tài);UTXHn/URXHn,8位發(fā)送/接收數(shù)據(jù)寄存器;UBRDIVn,波特率配置器存器。
波特率計(jì)算公式:
DIV_VAL=(PCLK /(bps×16 ))-1
DIV_VAL=(EXT_UCLKn/(bps×16))-1(n=0/1)
UBRDIVn=DIV_VAL的整數(shù)部分
UDIVSLOTn= DIV_VAL的小數(shù)部分×16
(7)NANDFlash初始化
NAND Flash時(shí)序初始化,主要配置寄存器NFCONF中的TACLS=7、TWRPH0=7、WRPH1=7。使能NAND Flash,主要寄存器NFCONT中的MODE=1、Reg_nCE0=0。
(8)內(nèi)存初始化
內(nèi)存初始化主要是配置其中的寄存器,主要包括P1REFRESH、P1CASLAT、P1T_DQSS、P1T_MRD、P1T_RAS、P1T_RC、P1T_RCD等一系列寄存器,對應(yīng)的U-Boot源碼在cpu_init.S文件中。
(9)U-Boot將代碼從NANDFlash拷貝到內(nèi)存中
本次移植使用的開發(fā)板CPU是S3C6410, 其steppingstone(0xc00 0000~0xc00 1fff)。
ldr r0, =0xff00 0fff
bic r1, pc, r0
ldr r2, _TEXT_BASE
bic r2, r2, r0
cmp r1, r2
mov r0, #0x1000
bl copy_from_nand
當(dāng)前的PC值是在0xc00 0000~0xc00 1fff之間,執(zhí)行bic r1, pc, r0 將PC高8位和低12位清零,得到0x0~0x1000(這是在steppingstone中運(yùn)行r1的值)。_TEXT_BASE = 0xc7e0 0000 ,執(zhí)行bic r2, r2, r0后 r2的范圍為0xe0 0000~0xef f000),因?yàn)殚_啟了MMU。經(jīng)過比較后執(zhí)行bl copy_from_nand 指令(主要是拷貝4 KB大小的數(shù)據(jù)到內(nèi)存中0x57e0 0000)。
(10)開啟MMU
首先建立映射表(從虛擬地址到物理地址的映射,主要是段映射)。由lowlevel_init.S(mmu_table)可知:第一段主要是用來調(diào)試,可讀(0~0xa000 0000)(2560 MB);第二段保留(0xa000 0000~0xc000 0000)-->(512 MB);第三段是主要用來映射的(128 MB)-->將虛擬基地址0xc000 0000 映射到物理基地址0x5000 0000;第三段沒法訪問(896 MB)。
然后設(shè)置TTB寄存器,將建立的映射表的基地址寫入到TTB寄存器中:mcrp15, 0, r1, c2, c0, 0。
接著使能MMU:mcrp15, 0, r0, c1, c0, 0。
(11)設(shè)置棧
因?yàn)殚_啟了MMU,所以棧的大小為:ldrsp=(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0xc),其中CFG_UBOOT_BASE=0xc7e0 0000、CFG_UBOOT_SIZE=2 MB。
(12)清除BSS段
主要是為后面的數(shù)據(jù)使用。
(13)跳轉(zhuǎn)到start_armboot
ldrpc, _start_armboot
_start_armboot:
.word start_armboot
當(dāng)執(zhí)行了上面的指令后,PC執(zhí)行絕對跳轉(zhuǎn)到內(nèi)存中,PC的值應(yīng)該是0xc7e0 0000 之后的某個(gè)值(開啟了MMU)。
關(guān)于bl指令和ldr指令:bl指令是相對跳轉(zhuǎn)指令,只是相對當(dāng)前PC的值跳轉(zhuǎn),跳轉(zhuǎn)大小編譯器編譯時(shí)就已確定。ldr指令是絕對跳轉(zhuǎn)指令,PC的值會(huì)變成賦給的值。這也是這里用ldr的原因。
(1)設(shè)置結(jié)構(gòu)體gd_t和bd_t
gd_t主要用來存儲(chǔ)全局?jǐn)?shù)據(jù)區(qū)的數(shù)據(jù)。bd_t主要用來存放板級相關(guān)的全局?jǐn)?shù)據(jù)。U-Boot啟動(dòng)內(nèi)核時(shí)要給內(nèi)核傳遞參數(shù),需要用gd_t和bd_t中的數(shù)據(jù)來設(shè)置標(biāo)記列表。
(2)執(zhí)行init_sequence數(shù)組中的函數(shù)
通過調(diào)用在init_sequence指針數(shù)組中的函數(shù)指針,從而執(zhí)行相應(yīng)的函數(shù),接下來分析主要的函數(shù)。
? board_init( )
主要配置開發(fā)板的信息,初始化網(wǎng)卡,設(shè)置GPIO寄存器,設(shè)置U-Boot機(jī)器碼和內(nèi)核啟動(dòng)參數(shù)地址。
? interrupt_init( )
該函數(shù)主要是配置定時(shí)器,為系統(tǒng)運(yùn)行提供相應(yīng)的時(shí)間。
? env_init( )
初始化gd_t中環(huán)境變量,這里是系統(tǒng)默認(rèn)的環(huán)境變量default_environment[0]。
? init_baudrate( )
初始化波特率,即gd->baudrate = 115200。
? dram_init( )
填充gd_t的內(nèi)存信息,start = 0x5000 0000; size = 256M
? flash_init( )
初始化Flash的起始地址、bank數(shù)目,主要是放在flash_info[ ]中。
? nand_init( )
取得Nandflash的信息,放在nand_chip和nand_dev_desc結(jié)構(gòu)體中。
? env_relocate()
將環(huán)境變量地址重新定位,將新的地址賦值給gd->env_addr(主要涉及到數(shù)據(jù)的搬移Nandflash->Dram)。
? 填充gd_t中bd的IP地址/MAC地址
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0。
? devices_init()
初始化設(shè)備列表,作者這里為空。
○k jumptable_init()
初始化跳轉(zhuǎn)表,填充gd_t中的jt指針數(shù)組里面的元素(函數(shù)),后面可以快速執(zhí)行里面的函數(shù)。
○l console_init_r( )
初始化控制臺,初始化標(biāo)準(zhǔn)輸入、輸出、和錯(cuò)誤設(shè)備。
使能中斷。
填充硬件MAC地址。
進(jìn)入main_loop循環(huán),執(zhí)行第三階段的代碼(實(shí)際上是兩階段),在mian_loop循環(huán)中主要執(zhí)行的主要代碼是:
s = GETenv ("bootcmd");
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
run_command (s, 0); }
首先獲取bootcmd環(huán)境變量,然后調(diào)用run_command( )函數(shù)來執(zhí)行相應(yīng)的命令。bootm命令執(zhí)行的路線:bootm->do_bootm()->do_bootm_Linux()->theKernel( )。最后通過調(diào)用theKernel函數(shù)從而執(zhí)行Linux內(nèi)核代碼,U-Boot引導(dǎo)功能完成,將控制權(quán)交給內(nèi)核。
NAND Flash是嵌入式設(shè)備中最常用的存儲(chǔ)設(shè)備。通常將移植好的U-Boot燒寫到NAND Flash中,直接從NAND Flash里面啟動(dòng)U-Boot。
首先要配置NAND Flash的控制時(shí)序位和使能位(之前),通過CONFIG_NAND來控制。然后在Nand_ids.c文件中找到結(jié)構(gòu)體nand_flash_ids,添加相應(yīng)的NAND Flash設(shè)備信息——{“NAND 1GiB 3,3V 8-bit”,0xD3, 0, 1024, 0, LP_OPTIONS},其已經(jīng)在U-Boot中存在。最后重新編譯U-Boot,然后燒寫到NAND Flash中,從NAND Flash啟動(dòng)開發(fā)板,U-Boot順利啟動(dòng),啟動(dòng)頁面如圖1所示。
圖1 U-Boot順利啟動(dòng)后顯示情況
[1] 田澤.嵌入式系統(tǒng)開發(fā)與應(yīng)用[M].北京:北京航空航天大學(xué)出版社,2005.
[2] 鄭靈翔.嵌入式Linux系統(tǒng)設(shè)計(jì)[M].北京:北京航空航天大學(xué)出版社,2008.
[3] 范展源,劉韜.深度實(shí)踐嵌入式Linux系統(tǒng)移植[M].北京:機(jī)械工業(yè)出版社,2015.
[4] 韋東山.嵌入式Linux應(yīng)用開發(fā)完全手冊[M].北京:人民郵電出版社,2008.
[5] 何景波,孫運(yùn)強(qiáng),姚愛琴.U-Boot在嵌入式系統(tǒng)上的移植分析與實(shí)現(xiàn)[J].機(jī)械工程與自動(dòng)化,2009(4).
[6] 黃薦渠,秦東興,趙曦,等.U-Boot的啟動(dòng)及移植分析[J].微計(jì)算機(jī)信息,2008(11).
[7] 楊帆,顧亞平,彭翔,等.一種小型嵌入式Linux Boot Loader的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)應(yīng)用與軟件,2008(1):225-226.
[8] Sumsuang Electronics.S3C6410x User’s Manual,2008.
[9] Sumsuang Electronics.K9F2G08UXA Datasheet,2007.
董君(碩士研究生),主要研究方向?yàn)榻煌ㄟ\(yùn)輸信息技術(shù);倪少權(quán)(博士),主要研究方向?yàn)橛?jì)算機(jī)編制列車運(yùn)行圖、交通運(yùn)輸信息技術(shù)、鐵路行車組織、物流信息技術(shù)。
AnalysisandPortingofU-BootinEmbeddedPlatformS3C6410
DongJun1,NiShaoquan2
(1.School of Information Science and Technology,Southwest Jiaotong University,Chengdu 611756,China;2.School of Transportation and Logistics,Southwest Jiaotong University)
In the paper,the U-Boot source code and start process based on S3C6410 embedded platform are analyzed.On the basis, the U-Boot software is successfully ported and S3C6410 processor clock initialization,serial communication,memory initialization,MMU initialization and NAND Flash initialization are realized.Through the porting of NAND Flash driver,the read and write NAND Flash and start from NAND Flash are realized. So that the whole system can operate normally.
U-Boot;analysis;porting;NAND Flash driver
國家自然基金項(xiàng)目(61403317,61273242,60776826);中國鐵路總公司科技研究計(jì)劃項(xiàng)目(2016X006-D);四川省科技計(jì)劃項(xiàng)目(2017ZR0149,2017RZ0007);中央高?;究蒲袠I(yè)務(wù)費(fèi)專項(xiàng)資金資助(2682017ZDPY04,2682017CX022)。
TP368.1
A
2017-08-15)