在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > u-boot 啟動(dòng)過程 —— 基于S3C2410

            u-boot 啟動(dòng)過程 —— 基于S3C2410

            作者: 時(shí)間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
            本文以流行的Samsung公司的S3C2410,openmoko平臺和u-boot-1.3.2(2008.5 發(fā)布)為例,介紹如何在ZIX嵌入式開發(fā)環(huán)境下探索u-boot啟動(dòng)過程。

            雖然u-boot已經(jīng)廣泛應(yīng)用,由于其相對的復(fù)雜性使用戶在了解其內(nèi)部機(jī)理和進(jìn)行u-boot的移植工作時(shí)還是會(huì)碰到困難。u-boot已有一些分析文檔,但多數(shù)和真正的代碼不能同步或者版本老舊,難以將概念和現(xiàn)實(shí)的代碼匹配——即硬件板上跑的代碼在文檔資料中卻看不到,更無法緊密的跟蹤。本文涉及的代碼基于在s3c2410硬件運(yùn)行的成熟u-boot-1.3.2代碼,版本較新,提供的特性非常豐富,而且在forum.linuxbj.com可以自由瀏覽和下載。此u-boot代表了業(yè)界的較高水平,可以直接構(gòu)建新版的嵌入式產(chǎn)品設(shè)計(jì),有較高的應(yīng)用價(jià)值。

            本文引用地址:http://www.biyoush.com/article/201611/317161.htm

            u-boot總的啟動(dòng)流程如下
            ->reset
            -> 設(shè)置CPU模式
            -> 關(guān)閉看門狗/中斷
            -> 設(shè)置處理器時(shí)鐘/片上總線
            -> 初始化調(diào)試串口
            -> MMU/外部總線/SDRAM等初始化
            -> rom代碼/數(shù)據(jù)搬移到ram
            -> 初始化函數(shù)調(diào)用棧
            -> 初始化外圍設(shè)備/參數(shù)
            ->啟動(dòng)完畢,進(jìn)入main_loop循環(huán)

            嵌入式系統(tǒng)離不開bootloader初始化硬件以及引導(dǎo)操作系統(tǒng)。
            現(xiàn)在,專用的嵌入式板子運(yùn)行嵌入式Linux系統(tǒng)已經(jīng)變得非常流行,u-boot是一種非常適合此類系統(tǒng)的bootloader。

            u-boot主要提供以下功能:

            • 設(shè)置目標(biāo)板硬件參數(shù)并初始化;
            • 為操作系統(tǒng)傳遞必要信息;
            • 執(zhí)行交互式的底層操作;
            • 智能化裝載操作系統(tǒng);
            • 引導(dǎo)和運(yùn)行的固件程序;
            • 支持大容量存儲(chǔ)和USB接口

            利用ZIX開發(fā)環(huán)境,能夠通過比較直觀的方式觀察u-boot內(nèi)部,而且可以將代碼調(diào)試和分析同時(shí)進(jìn)行,是一種了解、移植u-boot的強(qiáng)大工具。

            使用arm工具鏈編譯u-boot源代碼,得到可以燒錄的u-boot.bin文件。
            在ZIX開發(fā)環(huán)境里,可以將u-boot.bin載入s3c2410板運(yùn)行,并利用gdb調(diào)試。

            gdb能通過JTAG接口訪問硬件,也可以通過TCP/IP訪問虛擬硬件。 建立好調(diào)試連接,即可通過gdb操縱u-boot啟動(dòng)過程,下面可以跟隨代碼的執(zhí)行順序,了解從上點(diǎn)開始,究竟哪些操作被執(zhí)行。

            s3c2410復(fù)位之后,pc指針會(huì)指向0x0地址。在u-boot代碼中,該0x0地址是一個(gè)向量表,
            第一條指令跳轉(zhuǎn)branch到復(fù)位代碼start_code。 位于cpu/arm920t/start.S匯編語言文件第53行:

            DE>.globl _start  _start: DE> DE>b start_code DE> DE>    DE>ldr pc, _undefined_instruction DE>    DE>ldr pc, _software_interrupt DE>    DE>ldr pc, _prefetch_abort DE>    DE>ldr pc, _data_abort DE>    DE>ldr pc, _not_used DE>    DE>ldr pc, _irq DE>    DE>ldr pc, _fiq

            復(fù)位指令跳轉(zhuǎn)之后來到第154行,開始執(zhí)行arm920t處理器的基本初始化。
            首先修改當(dāng)前程序狀態(tài)寄存器CPSR,使處理器進(jìn)入Supervisor|32 bit ARM模式,
            并關(guān)閉ARM9TDMI中斷和快速中斷,這是通過設(shè)置CPSR相應(yīng)掩碼實(shí)現(xiàn)的:

            DE>start_code: DE>DE>    DE>DE>/* DE>DE>    DE>DE> * set the cpu to SVC32 mode DE>DE>    DE>DE> */  DE>DE>    DE>DE>mrs r0,cpsr DE>DE>    DE>DE>bic r0,r0,#0x1f DE>DE>    DE>DE>orr r0,r0,#0xd3 DE>DE>    DE>DE>msr cpsr,r0 DE> 

            緊接著,將S3C2410特有的WTCON寄存器清零,此舉僅為關(guān)閉看門狗,代碼位置是234行:

            DE>    DE>DE>ldr r0, =pWTCON DE>DE>    DE>DE>mov r1, #0x0 DE>DE>    DE>DE>str r1, [r0] DE>

            然后在241行,將S3C2410中斷控制器INTMSK寄存器置為全1,
            INTSUBMSK置為0x7ff,禁止全部中斷源。S3C2410手冊358頁起對此有詳細(xì)描述:

            DE>    DE>DE>mov r1, #0xffffffff  DE>DE>    DE>DE>ldr r0, =INTMSK DE>DE>    DE>DE>str r1, [r0]  # if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) ||   DE>DE>  DE>DE>defined(CONFIG_S3C2443)  DE>DE>    DE>DE>ldr r1, =INTSUBMSK_val  DE>DE>    DE>DE>ldr r0, =INTSUBMSK  DE>DE>    DE>DE>str r1, [r0]  # endif DE> 

            接下來在259行,訪問arm920t控制寄存器CP15,并置位最高兩位〔31,30〕。
            此兩位置為0b11后,處理器時(shí)鐘被設(shè)置為異步模式,允許處理器異步訪問總線:

            DE>    DE>DE>mrc p15, 0, r1, c1, c0, 0 DE>DE>    DE>DE>orr r1, r1, #0xc0000000 DE>DE>    DE>DE>mcr p15, 0, r1, c1, c0, 0 DE>

            至此arm920t相關(guān)的配置完成,后面開始設(shè)定S3C2410時(shí)鐘合成參數(shù)。
            通過設(shè)置UPLL,MPLL和CLKDIVN三個(gè)寄存器(在S3C2410手冊237頁起講述),
            得到需要的處理器工作頻率,分別在308行:

            DE>    DE>DE>ldr r0, =UPLLCON  DE>DE>    DE>DE>ldr r1, =UPLLCON_val DE>DE>    DE>DE>str r1, [r0] DE>

            321行:

            DE>    DE>DE>ldr r1, =MPLLCON_val  DE>DE>    DE>DE>str r1, [r0, #-4]DE>DE>    DE>DE>/* MPLLCON */DE>DE>DE>DE>    DE>DE>/* FCLK:HCLK:PCLK = 1:2:4 */ DE>DE>    DE>DE>ldr r0, =CLKDIVN DE>DE>    DE>DE>mov r1, #CLKDIVN_val DE>DE>    DE>DE>str r1, [r0] DE>

            S3C2410的UART0得到初始化,以便于盡早通過UART0打印信息。
            此段代碼從332行開始,其中涉及到的寄存器讀者可參考S3C2410手冊293頁起:

            DE>    DE>DE>/* enable uart */DE>DE>    DE>DE>ldr r0, =0x4c00000c /* clkcon */ DE>DE>    DE>DE>ldr r1, =0x7fff0 /* all clocks on */ DE>DE>    DE>DE>str r1, [r0] DE>DE>DE>DE>    DE>DE>/* gpio UART0 init */ DE>DE>    DE>DE>ldr r0, =0x56000070 DE>DE>    DE>DE>mov r1, #0xaa DE>DE>    DE>DE>str r1, [r0] DE>DE>DE>DE>    DE>DE>/* init uart */ DE>DE>    DE>DE>ldr r0, =0x50000000 DE>DE>    DE>DE>mov r1, #0x03 DE>DE>    DE>DE>str r1, [r0] DE>DE>    DE>DE>ldr r1, =0x245 DE>DE>    DE>DE>str r1, [r0, #0x04] DE>DE>    DE>DE>mov r1, #0x01 DE>DE>    DE>DE>str r1, [r0, #0x08] DE>DE>    DE>DE>mov r1, #0x00 DE>DE>    DE>DE>str r1, [r0, #0x0c] DE>DE>    DE>DE>mov r1, #0x1a DE>DE>    DE>DE>str r1, [r0, #0x28] DE>

            完成UART0設(shè)置之后,根據(jù)不同的編譯時(shí)選項(xiàng)和運(yùn)行時(shí)參數(shù),代碼會(huì)在360行進(jìn)入相應(yīng)的分支,分別是

            1. 從nand啟動(dòng),代碼執(zhí)行l(wèi)owlevel_init,主要是清除cpu cache,以及關(guān)閉mmu和i-cache,
              并且根據(jù)板極硬件配置初始化外部存儲(chǔ)器總線和GPIO,最后把代碼從nandflash中拷貝到ram中并繼續(xù)執(zhí)行。
            2. 從nor啟動(dòng),與第1種情況相比,僅僅把代碼拷貝部分簡化,將DATA段從flash中拷貝到ram中,其余相同
            3. 從ram啟動(dòng),因?yàn)閡-boot已經(jīng)處于配置好的ram中,
              所以會(huì)跳過所有cache,mmu,sdram,nand和nor相關(guān)代碼,跳轉(zhuǎn)到done_relocate執(zhí)行

            下面以最復(fù)雜的nand啟動(dòng)情況為例分析。首先會(huì)跳轉(zhuǎn)到572行執(zhí)行cpu_init_crit,
            通過操作CP15完成flush處理器arm920t的cache和tlb,并關(guān)閉mmu和i-cache:

            DE>cpu_init_crit:DE>DE>    DE>DE>/*DE>DE>    DE>DE> * flush v4 I/D caches DE>DE>     DE>DE>*/  DE>DE>    DE>DE>mov r0, #0 DE>DE>    DE>DE>mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ DE>DE>    DE>DE>mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ DE>DE>  DE>DE>    DE>DE>/*DE>DE>    DE>DE> * disable MMU stuff and cachesDE>DE>    DE>DE>*/ DE>DE>    DE>DE>mrc p15, 0, r0, c1, c0, 0 DE>DE>    DE>DE>bic r0, r0, #0x00002300DE>DE>     DE>DE>@ clear bits 13, 9:8 (--V- --RS) DE>DE>    DE>DE>bic r0, r0, #0x00000087 DE>DE>    DE>DE>@ clear bits 7, 2:0 (B--- -CAM) DE>DE>    DE>DE>orr r0, r0, #0x00000002 DE>DE>    DE>DE>@ set bit 2 (A) Align DE>DE>    DE>DE>orr r0, r0, #0x00001000 DE>DE>    DE>DE>@ set bit 12 (I) I-Cache DE>DE>    DE>DE>mcr p15, 0, r0, c1, c0, 0 DE>

            然后跳轉(zhuǎn)到board/neo1973/common/lowlevel_init.S文件的139行執(zhí)行,
            進(jìn)行總線數(shù)據(jù)寬度、時(shí)序、SDRAM控制、GPIO等配置,配置完畢后會(huì)返回start.S繼續(xù)執(zhí)行。
            因?yàn)樵摯a是與板相關(guān),故放在board目錄里面。由于代碼較多,只粘貼開始部分:

            DE>    DE>DE>/* memory control configuration */  DE>DE>    DE>DE>/* make r0 relative the current location so that it */  DE>DE>    DE>DE>/* reads SMRDATA out of FLASH rather than memory ! */ DE>DE>    DE>DE>adr r0, SMRDATA  DE>DE>    DE>DE>ldr r1, =BWSCON /* Bus Width Status Controller */ DE>DE>    DE>DE>add r2, r0, #13*4 DE>

            完成板級設(shè)置后,在cpu/arm920t/start.S的373行判斷代碼自身的執(zhí)行位置。如果從stepping stone內(nèi)執(zhí)行,
            并且u-boot配置為nandboot模式,則跳轉(zhuǎn)到nand_load拷貝代碼:

            DE>    DE>DE>ldr r1, =BWSCON /* Z = CPU booted from NAND */ DE>DE>    DE>DE>ldr r1, [r1] DE>DE>    DE>DE>tst r1, #6 /* BWSCON[2:1] = OM[1:0] */ DE>DE>    DE>DE>teqeq r0, #0 /* Z &= running at address 0 */ DE>DE>    DE>DE>beq nand_load DE>

            在417行是nand_load代碼,首先會(huì)跳轉(zhuǎn)到614行執(zhí)行may_resume
            以檢測系統(tǒng)是從待機(jī)模式喚醒還是上電啟動(dòng)。如果喚醒,則會(huì)根據(jù)之前保存的現(xiàn)場進(jìn)行相應(yīng)處理,
            本文不做更多敘述;如果是啟動(dòng),則會(huì)返回nand_load繼續(xù)執(zhí)行。在nand_load里初始化s3c2410的nandcontroller,
            涉及存儲(chǔ)器映射和寄存器NFCONF等,參見S3C2410手冊215頁起。同樣,僅粘貼開始部分的代碼:

            DE>    DE>DE>mov r1, #S3C2410_NAND_BASE DE>DE>    DE>DE>ldr r2, =0xf842 @ initial value enable tacls=3,rph0=6,rph1=0 DE>DE>    DE>DE>str r2, [r1, #oNFCONF] DE>DE>    DE>DE>ldr r2, [r1, #oNFCONF] DE>DE>    DE>DE>bic r2, r2, #0x800 @ enable chip DE>

            在451行繼續(xù)根據(jù)配置設(shè)定棧指針,為后面調(diào)用C函數(shù)執(zhí)行拷貝作準(zhǔn)備:

            DE>    DE>DE>ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ DE>DE>    DE>DE>sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ DE>DE>    DE>DE>sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ DE>DE>    DE>DE>sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif DE>DE>    DE>DE>sub sp, r0, #12 /* leave 3 words for abort-stack */ DE>

            然后在460行,將SDRAM中的目標(biāo)地址存入r0,0x0地址存入r1,u-boot長度存入r2,
            跳入cpu/arm920t/s3c24x0/nand_read.c文件第154行執(zhí)行nand_read_ll函數(shù),該函數(shù)接受前面3個(gè)寄存器中的值作為參數(shù),并將返回值放回r0:

            DE>    DE>DE>ldr r0, _TEXT_BASE DE>DE>    DE>DE>mov r1, #0x0 DE>DE>    DE>DE>mov r2, #CFG_UBOOT_SIZE DE>DE>    DE>DE>bl nand_read_ll DE>

            在nand_read_ll函數(shù)中實(shí)現(xiàn)了nandflash訪問代碼,并且支持自動(dòng)跳過壞塊的特性,函數(shù)循環(huán)執(zhí)行nand頁面讀取并存入SDRAM,直到u-boot全部拷貝完,并返回0,該C代碼留給讀者自己閱讀。nand_read_ll返回0后,會(huì)跳轉(zhuǎn)到ok_nand_read,并482行對拷貝的頭4K字節(jié)進(jìn)行校驗(yàn):

            DE>    @ verify mov r0, #0 @ldr r1, =0x33f00000 ldr r1, _TEXT_BASE mov r2, #0x400 DE>DE>    DE>DE>@ 4 bytes * 1024 = 4K-bytes go_next: DE>DE>    DE>DE>ldr r3, [r0], #4 DE>DE>    DE>DE>ldr r4, [r1], #4 DE>DE>    DE>DE>teq r3, r4 DE>DE>    DE>DE>bne notmatch DE>DE>    DE>DE>subs r2, r2, #4 DE>DE>    DE>DE>beq done_nand_read DE>DE>    DE>DE>bne go_next DE>

            校驗(yàn)通過后代碼506行,在地址為_booted_from_nand的SDRAM位置保存1,以便告訴上層軟件本次啟動(dòng)是從nand引導(dǎo):

            DE>done_nand_read: DE>DE>    DE>DE>ldr r0, _booted_from_nand DE>DE>    DE>DE>mov r1, #1 DE>DE>    DE>DE>strb r1, [r0] DE>

            然后在518行,將中斷向量表拷貝到0x0:

            DE>    DE>DE>mov r0, #0 DE>DE>    DE>DE>ldr r1, _TEXT_BASE DE>DE>    DE>DE>mov r2, #0x40 irqvec_cpy_next: DE>DE>    DE>DE>ldr r3, [r1], #4 DE>DE>    DE>DE>str r3, [r0], #4 DE>DE>    DE>DE>subs r2, r2, #4 DE>DE>    DE>DE>bne irqvec_cpy_next DE>

            在532行,設(shè)置棧指針:

            DE>    DE>DE>ldr r0, _TEXT_BASEDE>DE>    DE>DE>/* upper 128 KiB: relocated uboot */ DE>DE>    DE>DE>sub r0, r0, #CFG_MALLOC_LENDE>DE>    DE>DE>/* malloc area */ DE>DE>    DE>DE>sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ DE>DE>    DE>DE>sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif DE>DE>    DE>DE>sub sp, r0, #12DE>DE>    DE>DE>/* leave 3 words for abort-stack */ DE>

            在541行,清除bss段并跳轉(zhuǎn)到真正的C函數(shù)start_armboot,進(jìn)入更高級的硬件初始化代碼,匯編初始化部分也全部完成使命:

            DE>    DE>DE>ldr r0, _bss_start /* find start of bss segment */ DE>DE>    DE>DE>ldr r1, _bss_end /* stop here */ DE>DE>    DE>DE>mov r2, #0x00000000 /* clear */ DE>DE> clbss_l:DE>DE>    DE>DE>str r2, [r0] /* clear loop... */ DE>DE>    DE>DE>add r0, r0, #4 DE>DE>    DE>DE>cmp r0, r1 DE>DE>    DE>DE>ble clbss_l DE>DE> DE>DE>    DE>DE>ldr pc, _start_armboot DE>

            start_armboot函數(shù)位于lib_arm/board.c文件第277行,首先初始化globel_data類型的變量gd。該變量是一個(gè)結(jié)構(gòu),其成員大多是板子的一些基本設(shè)置,如序列號、ip地址、mac地址等(欲知結(jié)構(gòu)的原型可參考include/asm-arm/globel_data.h和include/asm-arm/u-boot.h):

            DE>         DE>DE>gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));DE>DE>         DE>DE>/* compiler optimization barrier needed for GCC >= 3.4 */__asm__ __volatile__("": : :"memory");DE>DE>         DE>DE>memset ((void*)gd, 0, sizeof (gd_t));gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));DE>DE>         DE>DE>memset (gd->bd, 0, sizeof (bd_t)); DE>

            然后在一個(gè)for循環(huán)中從init_sequence地址開始,逐個(gè)調(diào)用初始化C函數(shù)至NULL為止。這些routine函數(shù)按調(diào)用順序分別是

            1. cpu_init() ——在common/main.c文件,執(zhí)行初始化中斷棧操作
            2. board_init() ——在board/neo1973/gta01/gta01.c文件中,執(zhí)行板級初始化,主要是更新GPIO和PLL設(shè)置
            3. interrupt_init() ——在/cpu/arm920t/s3c24x0/interrupts.c文件中,執(zhí)行時(shí)鐘中斷初始化
            4. env_init() ——在common/env_nand.c文件中,設(shè)置缺省環(huán)境變量
            5. init_baudrate() ——在lib_arm/board.c文件中,將環(huán)境變量中的baudrate存入bd_info結(jié)構(gòu)bd
            6. serial_init() ——在common/serial.c文件中,調(diào)用驅(qū)動(dòng)中真正的init()初始化串口
            7. console_init_f() ——在common/console.c文件中,更新global_data結(jié)構(gòu)gd的have_console標(biāo)記為1
            8. display_banner() ——在lib_arm/board.c文件中,打印u-boot banner,輸出版本、運(yùn)行地址等信息。比如在控制臺看到的
            9. init_func_i2c() ——在lib_arm/board.c文件中,初始化i2c總線
            10. dram_init() ——在board/neo1973/gta01/gta01.c文件中,填充bd->bi_dram[0]的start和size成員,用來描述u-boot可用的ram
            11. display_dram_config() ——在board/neo1973/gta01/gta01.c文件中,打印當(dāng)前ram配置。在控制臺能夠看到相應(yīng)的 DRAM: 128 MB

            利用gdb可以清晰的看到調(diào)用過程:

            DE>         DE>DE>for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { DE>DE>         DE>DE>         DE>DE>if ((*init_fnc_ptr)() != 0) { DE>DE>         DE>DE>         DE>DE>         DE>DE>hang (); DE>DE>         DE>DE>         DE>DE>} DE>DE>         DE>DE>} DE>

            接著是一些可選外設(shè)的初始化,如顯示屏、nor、nand、dataflash、網(wǎng)卡等,此過程執(zhí)行后全部初始化工作完成。下面僅粘貼nor代碼:

            DE>#ifndef CFG_NO_FLASH DE>DE>         DE>DE>/* configure available FLASH banks */ DE>DE>         DE>DE>size = flash_init (); DE>DE>         DE>DE>display_flash_config (size); #endif /* CFG_NO_FLASH */ DE>

            之后在457行進(jìn)入無限循環(huán),調(diào)用common/main.c文件的278行main_loop()函數(shù),u-boot完成啟動(dòng)過程。main_loop提供一個(gè)交互式命令行,可通過串口或usb控制臺操作,也可以進(jìn)一步引導(dǎo)操作系統(tǒng):

            DE>         DE>DE>for (;;) { DE>DE>         DE>DE>         DE>DE>main_loop (); DE>DE>         DE>DE>} DE>


            關(guān)鍵詞: u-boot啟動(dòng)過程S3C241

            評論


            相關(guān)推薦

            技術(shù)專區(qū)

            關(guān)閉