在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,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è)計應(yīng)用 > 基于ARM的嵌入式Linux移植真實體驗(2)――BootLoader

            基于ARM的嵌入式Linux移植真實體驗(2)――BootLoader

            作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
            BootLoader指系統(tǒng)啟動后,在操作系統(tǒng)內(nèi)核運行之前運行的一段小程序。通過BootLoader,我們可以初始化硬件設(shè)備、建立內(nèi)存空間的映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個合適的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的環(huán)境。通常,BootLoader是嚴(yán)重地依賴于硬件而實現(xiàn)的,特別是在嵌入式世界。因此,在嵌入式世界里建立一個通用的 BootLoader 幾乎是不可能的。盡管如此,我們?nèi)匀豢梢詫ootLoader歸納出一些通用的概念來,以指導(dǎo)用戶特定的BootLoader設(shè)計與實現(xiàn)。
            BootLoader 的實現(xiàn)依賴于CPU的體系結(jié)構(gòu),因此大多數(shù) BootLoader 都分為stage1 和stage2 兩大部分。依賴于CPU體系結(jié)構(gòu)的代碼,比如設(shè)備初始化代碼等,通常都放在 stage1中,而且通常都用匯編語言來實現(xiàn),以達(dá)到短小精悍的目的。而stage2 則通常用C 語言來實現(xiàn),這樣可以實現(xiàn)更復(fù)雜的功能,而且代碼會具有更好的可讀性和可移植性。
            BootLoader 的 stage1 通常包括以下步驟:
            Ø 硬件設(shè)備初始化;
            Ø 為加載Boot Loader的stage2準(zhǔn)備 RAM 空間;
            Ø 拷貝Boot Loader的stage2 到RAM空間中;
            Ø 設(shè)置好堆棧;
            Ø 跳轉(zhuǎn)到 stage2 的 C 入口點。
            Boot Loader的stage2通常包括以下步驟:
            Ø 初始化本階段要使用到的硬件設(shè)備;
            Ø 檢測系統(tǒng)內(nèi)存映射(memory map);
            Ø 將kernel 映像和根文件系統(tǒng)映像從flash上讀到 RAM 空間中;
            Ø 為內(nèi)核設(shè)置啟動參數(shù);
            Ø 調(diào)用內(nèi)核。
            本系統(tǒng)中的BootLoader參照韓國mizi公司的vivi進(jìn)行修改。
            1.開發(fā)環(huán)境
            我們購買了武漢創(chuàng)維特信息技術(shù)有限公司開發(fā)的具有自主知識產(chǎn)權(quán)的應(yīng)用于嵌入式軟件開發(fā)的集成軟、硬件開發(fā)平臺ADT(ARM Development Tools)它為基于ARM 核的嵌入式應(yīng)用提供了一整套完備的開發(fā)方案,包括程序編輯、工程管理和設(shè)置、程序編譯、程序調(diào)試等。
            ADT嵌入式開發(fā)環(huán)境由ADT Emulator for ARM 和ADT IDE for ARM組成。ADT Emulator for ARM 通過JTAG 實現(xiàn)主機(jī)和目標(biāo)機(jī)之間的調(diào)試支持功能。它無需目標(biāo)存儲器,不占用目標(biāo)系統(tǒng)的任何端口資源。目標(biāo)程序直接在目標(biāo)板上運行,通過ARM 芯片的JTAG 邊界掃描口進(jìn)行調(diào)試,屬于完全非插入式調(diào)試,其仿真效果接近真實系統(tǒng)。
            ADT IDE for ARM 為用戶提供高效明晰的圖形化嵌入式應(yīng)用軟件開發(fā)環(huán)境,包括一整套完備的面向嵌入式系統(tǒng)的開發(fā)和調(diào)試工具:源碼編輯器、工程管理器、工程編譯器(編譯器、匯編器和連接器)、集成調(diào)試環(huán)境、ADT Emulator for ARM 調(diào)試接口等。其界面同Microsoft Visual Studio 環(huán)境相似,用戶可以在ADT IDE for ARM 集成開發(fā)環(huán)境中創(chuàng)建工程、打開工程,建立、打開和編輯文件,編譯、連接、設(shè)置、運行、調(diào)試嵌入式應(yīng)用程序。
            ADT嵌入式軟件開發(fā)環(huán)境采用主機(jī)-目標(biāo)機(jī)交叉開發(fā)模型。ADT IDE for ARM 運行于主機(jī)端,而ADT Emulator for ARM 實現(xiàn)ADT IDE for ARM 與目標(biāo)機(jī)之間的連接。開發(fā)時,首先由ADT IDE for ARM 編譯連接生成目標(biāo)代碼,然后建立與ADT Emulator for ARM 之間的調(diào)試通道,調(diào)試通道建立成功后,就可以在ADT IDE for ARM 中通過ADT Emulator for ARM 控制目標(biāo)板實現(xiàn)目標(biāo)程序的調(diào)試,包括將目標(biāo)代碼下載到目標(biāo)機(jī)中,控制程序運行,調(diào)試信息觀察等等。

            2.ARM匯編
            ARM本身屬于RISC指令系統(tǒng),指令條數(shù)就很少,而其編程又以C等高級語言為主,我們僅需要在Bootloader的第一階段用到少量匯編指令
            (1)+-運算
            ADD r0, r1, r2
            ―― r0 := r1 + r2
            SUB r0, r1, r2
            ―― r0 := r1 - r2
            其中的第二個操作數(shù)可以是一個立即數(shù):
            ADD r3, r3, #1
            ―― r3 := r3 + 1
            第二個操作數(shù)還可以是位移操作后的結(jié)果:
            ADD r3, r2, r1, LSL #3
            ―― r3 := r2 + 8.r1
            (2)位運算
            AND r0, r1, r2
            ―― r0 := r1 and r2
            ORR r0, r1, r2
            ―― r0 := r1 or r2
            EOR r0, r1, r2
            ―― r0 := r1 xor r2
            BIC r0, r1, r2
            ―― r0 := r1 and not r2
            (3)寄存器搬移
            MOV r0, r2
            ―― r0 := r2
            MVN r0, r2
            ―― r0 := not r2
            (4)比較
            CMP r1, r2
            ―― set cc on r1 - r2
            CMN r1, r2
            ―― set cc on r1 + r2
            TST r1, r2
            ―― set cc on r1 and r2
            TEQ r1, r2
            ―― set cc on r1 or r2
            這些指令影響CPSR寄存器中的 (N, Z, C, V) 位
            (5)內(nèi)存操作
            LDR r0, [r1]
            ―― r0 := mem [r1]
            STR r0, [r1]
            ―― mem [r1] := r0
            LDR r0, [r1, #4]
            ―― r0 := mem [r1+4]
            LDR r0, [r1, #4] !
            ―― r0 := mem [r1+4] r1 := r1 + 4
            LDR r0, [r1], #4
            ―― r0 := mem [r1] r1 := r1 +4
            LDRB r0 , [r1]
            ―― r0 := mem8 [r1]
            LDMIA r1, {r0, r2, r5}
            ―― r0 := mem [r1] r2 := mem [r1+4] r5 := mem [r1+8]
            {..} 可以包括r0~r15中的所有寄存器,若包括r15 (PC)將導(dǎo)致程序的跳轉(zhuǎn)。
            (6)控制流
            例1:
            MOV r0, #0 ; initialize counter
            LOOP:
            ADD r0, r0, #1 ; increment counter
            CMP r0, #10 ; compare with limit
            BNE LOOP ; repeat if not equal
            例2:
            CMP r0, #5
            ADDNE r1, r1, r0
            SUBNE r1, r1, r2
            ――
            if (r0 != 5) {
            r1 := r1 + r0 - r2
            }
            3.BootLoader第一階段
            3.1硬件設(shè)備初始化
            基本的硬件初始化工作包括:
            Ø 屏蔽所有的中斷;
            Ø 設(shè)置CPU的速度和時鐘頻率;
            Ø RAM初始化;
            Ø 初始化LED
            ARM的中斷向量表設(shè)置在0地址開始的8個字空間中,如下表:
            每當(dāng)其中的某個異常發(fā)生后即將PC值置到相應(yīng)的中斷向量處,每個中斷向量處放置一個跳轉(zhuǎn)指令到相應(yīng)的中斷服務(wù)程序去進(jìn)行處理,中斷向量表的程序如下:
            @ 0x00: Reset
            b Reset
            @ 0x04: Undefined instruction exception
            UndefEntryPoint:
            b HandleUndef
            @ 0x08: Software interrupt exception
            SWIEntryPoint:
            b HandleSWI
            @ 0x0c: Prefetch Abort (Instruction Fetch Memory Abort)
            PrefetchAbortEnteryPoint:
            b HandlePrefetchAbort
            @ 0x10: Data Access Memory Abort
            DataAbortEntryPoint:
            b HandleDataAbort
            @ 0x14: Not used
            NotUsedEntryPoint:
            b HandleNotUsed
            @ 0x18: IRQ(Interrupt Request) exception
            IRQEntryPoint:
            b HandleIRQ
            @ 0x1c: FIQ(Fast Interrupt Request) exception
            FIQEntryPoint:
            b HandleFIQ
            復(fù)位時關(guān)閉看門狗定時器、屏蔽所有中斷:
            Reset:
            @ disable watch dog timer
            mov r1, #0x53000000
            mov r2, #0x0
            str r2, [r1]
            @ disable all interrupts
            mov r1, #INT_CTL_BASE
            mov r2, #0xffffffff
            str r2, [r1, #oINTMSK]
            ldr r2, =0x7ff
            str r2, [r1, #oINTSUBMSK]
            設(shè)置系統(tǒng)時鐘:
            @init clk
            @ 1:2:4
            mov r1, #CLK_CTL_BASE
            mov r2, #0x3
            str r2, [r1, #oCLKDIVN]
            mrc p15, 0, r1, c1, c0, 0 @ read ctrl register
            orr r1, r1, #0xc0000000 @ Asynchronous
            mcr p15, 0, r1, c1, c0, 0 @ write ctrl register
            @ now, CPU clock is 200 Mhz
            mov r1, #CLK_CTL_BASE
            ldr r2, mpll_200mhz
            str r2, [r1, #oMPLLCON]
            點亮所有的用戶LED:
            @ All LED on
            mov r1, #GPIO_CTL_BASE
            add r1, r1, #oGPIO_F
            ldr r2,=0x55aa
            str r2, [r1, #oGPIO_CON]
            mov r2, #0xff
            str r2, [r1, #oGPIO_UP]
            mov r2, #0x00
            str r2, [r1, #oGPIO_DAT]
            設(shè)置(初始化)內(nèi)存映射:
            ENTRY(memsetup)
            @ initialise the static memory
            @ set memory control registers
            mov r1, #MEM_CTL_BASE
            adrl r2, mem_cfg_val
            add r3, r1, #52
            1: ldr r4, [r2], #4
            str r4, [r1], #4
            cmp r1, r3
            bne 1b
            mov pc, lr
            設(shè)置(初始化)UART:
            @ set GPIO for UART
            mov r1, #GPIO_CTL_BASE
            add r1, r1, #oGPIO_H
            ldr r2, gpio_con_uart
            str r2, [r1, #oGPIO_CON]
            ldr r2, gpio_up_uart
            str r2, [r1, #oGPIO_UP]
            bl InitUART
            @ Initialize UART
            @
            @ r0 = number of UART port
            InitUART:
            ldr r1, SerBase
            mov r2, #0x0
            str r2, [r1, #oUFCON]
            str r2, [r1, #oUMCON]
            mov r2, #0x3
            str r2, [r1, #oULCON]
            ldr r2, =0x245
            str r2, [r1, #oUCON]
            #define UART_BRD ((50000000 / (UART_BAUD_RATE * 16)) - 1)
            mov r2, #UART_BRD
            str r2, [r1, #oUBRDIV]
            mov r3, #100
            mov r2, #0x0
            1: sub r3, r3, #0x1
            tst r2, r3
            bne 1b
            #if 0
            mov r2, #U
            str r2, [r1, #oUTXHL]
            1: ldr r3, [r1, #oUTRSTAT]
            and r3, r3, #UTRSTAT_TX_EMPTY
            tst r3, #UTRSTAT_TX_EMPTY
            bne 1b
            mov r2, #0
            str r2, [r1, #oUTXHL]
            1: ldr r3, [r1, #oUTRSTAT]
            and r3, r3, #UTRSTAT_TX_EMPTY
            tst r3, #UTRSTAT_TX_EMPTY
            bne 1b
            #endif
            mov pc, lr
            此外,vivi還提供了幾個匯編情況下通過串口打印字符的函數(shù)PrintChar、PrintWord和PrintHexWord:
            @ PrintChar : prints the character in R0
            @ r0 contains the character
            @ r1 contains base of serial port
            @ writes ro with XXX, modifies r0,r1,r2
            @ TODO : write ro with XXX reg to error handling
            PrintChar:
            TXBusy:
            ldr r2, [r1, #oUTRSTAT]
            and r2, r2, #UTRSTAT_TX_EMPTY
            tst r2, #UTRSTAT_TX_EMPTY
            beq TXBusy
            str r0, [r1, #oUTXHL]
            mov pc, lr
            @ PrintWord : prints the 4 characters in R0
            @ r0 contains the binary word
            @ r1 contains the base of the serial port
            @ writes ro with XXX, modifies r0,r1,r2
            @ TODO : write ro with XXX reg to error handling
            PrintWord:
            mov r3, r0
            mov r4, lr
            bl PrintChar
            mov r0, r3, LSR #8 /* shift word right 8 bits */
            bl PrintChar
            mov r0, r3, LSR #16 /* shift word right 16 bits */
            bl PrintChar
            mov r0, r3, LSR #24 /* shift word right 24 bits */
            bl PrintChar
            mov r0, #r
            bl PrintChar
            mov r0, #n
            bl PrintChar
            mov pc, r4
            @ PrintHexWord : prints the 4 bytes in R0 as 8 hex ascii characters
            @ followed by a newline
            @ r0 contains the binary word
            @ r1 contains the base of the serial port
            @ writes ro with XXX, modifies r0,r1,r2
            @ TODO : write ro with XXX reg to error handling
            PrintHexWord:
            mov r4, lr
            mov r3, r0
            mov r0, r3, LSR #28
            bl PrintHexNibble
            mov r0, r3, LSR #24
            bl PrintHexNibble
            mov r0, r3, LSR #20
            bl PrintHexNibble
            mov r0, r3, LSR #16
            bl PrintHexNibble
            mov r0, r3, LSR #12
            bl PrintHexNibble
            mov r0, r3, LSR #8
            bl PrintHexNibble
            mov r0, r3, LSR #4
            bl PrintHexNibble
            mov r0, r3
            bl PrintHexNibble
            mov r0, #r
            bl PrintChar
            mov r0, #n
            bl PrintChar
            mov pc, r4
            3.2Bootloader拷貝
            配置為從NAND FLASH啟動,需要將NAND FLASH中的vivi代碼copy到RAM中:
            #ifdef CONFIG_S3C2410_NAND_BOOT
            bl copy_myself
            @ jump to ram
            ldr r1, =on_the_ram
            add pc, r1, #0
            nop
            nop
            1: b 1b @ infinite loop
            #ifdef CONFIG_S3C2410_NAND_BOOT
            @
            @ copy_myself: copy vivi to ram
            @
            copy_myself:
            mov r10, lr
            @ reset NAND
            mov r1, #NAND_CTL_BASE
            ldr r2, =0xf830 @ initial value
            str r2, [r1, #oNFCONF]
            ldr r2, [r1, #oNFCONF]
            bic r2, r2, #0x800 @ enable chip
            str r2, [r1, #oNFCONF]
            mov r2, #0xff @ RESET command
            strb r2, [r1, #oNFCMD]
            mov r3, #0 @ wait
            1: add r3, r3, #0x1
            cmp r3, #0xa
            blt 1b
            2: ldr r2, [r1, #oNFSTAT] @ wait ready
            tst r2, #0x1
            beq 2b
            ldr r2, [r1, #oNFCONF]
            orr r2, r2, #0x800 @ disable chip
            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 previous frame, so fp=0
            @ copy vivi to RAM
            ldr r0, =VIVI_RAM_BASE
            mov r1, #0x0
            mov r2, #0x20000
            bl nand_read_ll
            tst r0, #0x0
            beq ok_nand_read
            #ifdef CONFIG_DEBUG_LL
            bad_nand_read:
            ldr 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
            @ verify
            mov r0, #0
            ldr r1, =0x33f00000
            mov r2, #0x400 @ 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_nand_read:
            #ifdef CONFIG_DEBUG_LL
            ldr r0, STR_OK
            ldr r1, SerBase
            bl PrintWord
            #endif
            mov pc, r10
            @ clear memory
            @ r0: start address
            @ r1: length
            mem_clear:
            mov r2, #0
            mov r3, r2
            mov r4, r2
            mov r5, r2
            mov r6, r2
            mov r7, r2
            mov r8, r2
            mov r9, r2
            clear_loop:
            stmia r0!, {r2-r9}
            subs r1, r1, #(8 * 4)
            bne clear_loop
            mov pc, lr
            #endif @ CONFIG_S3C2410_NAND_BOOT
            3.3進(jìn)入C代碼
            首先要設(shè)置堆棧指針sp,堆棧指針的設(shè)置是為了執(zhí)行C語言代碼作好準(zhǔn)備。設(shè)置好堆棧后,調(diào)用C語言的main函數(shù):
            @ 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
            4. BootLoader第二階段
            vivi Bootloader的第二階段又分成了八個小階段,在main函數(shù)中分別調(diào)用這幾個小階段的相關(guān)函數(shù):
            int main(int argc, char *argv[])
            {
            int ret;
            /*
            * Step 1:
            */
            putstr("rn");
            putstr(vivi_banner);
            reset_handler();
            /*
            * Step 2:
            */
            ret = board_init();
            if (ret) {
            putstr("Failed a board_init() procedurern");
            error();
            }
            /*
            * Step 3:
            */
            mem_map_init();
            mmu_init();
            putstr("Succeed memory mapping.rn");
            /*
            * Now, vivi is running on the ram. MMU is enabled.
            */
            /*
            * Step 4:
            */
            /* initialize the heap area*/
            ret = heap_init();
            if (ret) {
            putstr("Failed initailizing heap regionrn");
            error();
            }
            /* Step 5:
            */
            ret = mtd_dev_init();
            /* Step 6:
            */
            init_priv_data();
            /* Step 7:
            */
            misc();
            init_builtin_cmds();
            /* Step 8:
            */
            boot_or_vivi();
            return 0;
            }
            STEP1的putstr(vivi_banner)語句在串口輸出一段字符說明vivi的版本、作者等信息,vivi_banner定義為:
            const char *vivi_banner =
            "VIVI version " VIVI_RELEASE " (" VIVI_COMPILE_BY "@"
            VIVI_COMPILE_HOST ") (" VIVI_COMPILER ") " UTS_VERSION "rn";
            reset_handler進(jìn)行相應(yīng)的復(fù)位處理:
            void
            reset_handler(void)
            {
            int pressed;
            pressed = is_pressed_pw_btn();
            if (pressed == PWBT_PRESS_LEVEL) {
            DPRINTK("HARD RESETrn");
            hard_reset_handle();
            } else {
            DPRINTK("SOFT RESETrn");
            soft_reset_handle();
            }
            }
            hard_reset_handle會clear內(nèi)存,而軟件復(fù)位處理則什么都不做:
            static void
            hard_reset_handle(void)
            {
            clear_mem((unsigned long)USER_RAM_BASE, (unsigned long)USER_RAM_SIZE);
            }
            STEP2進(jìn)行板初始化,設(shè)置時間和可編程I/O口:
            int board_init(void)
            {
            init_time();
            set_gpios();
            return 0;
            }
            STEP3進(jìn)行內(nèi)存映射及MMU初始化:
            void mem_map_init(void)
            {
            #ifdef CONFIG_S3C2410_NAND_BOOT
            mem_map_nand_boot();
            #else
            mem_map_nor();
            #endif
            cache_clean_invalidate();
            tlb_invalidate();
            }
            S3C2410A的MMU初始化只需要調(diào)用通用的arm920 MMU初始化函數(shù):
            static inline void arm920_setup(void)
            {
            unsigned long ttb = MMU_TABLE_BASE;
            __asm__(
            /* Invalidate caches */
            "mov r0, #0n"
            "mcr p15, 0, r0, c7, c7, 0n" /* invalidate I,D caches on v4 */
            "mcr p15, 0, r0, c7, c10, 4n" /* drain write buffer on v4 */
            "mcr p15, 0, r0, c8, c7, 0n" /* invalidate I,D TLBs on v4 */
            /* Load page table pointer */
            "mov r4, %0n"
            "mcr p15, 0, r4, c2, c0, 0n" /* load page table pointer */
            /* Write domain id (cp15_r3) */
            "mvn r0, #0n" /* Domains 0, 1 = client */
            "mcr p15, 0, r0, c3, c0, 0n" /* load domain access register */
            /* Set control register v4 */
            "mrc p15, 0, r0, c1, c0, 0n" /* get control register v4 */
            /* Clear out unwanted bits (then put them in if we need them) */
            /* .RVI ..RS B... .CAM */
            "bic r0, r0, #0x3000n" /* ..11 .... .... .... */
            "bic r0, r0, #0x0300n" /* .... ..11 .... .... */
            "bic r0, r0, #0x0087n" /* .... .... 1... .111 */
            /* Turn on what we want */
            /* Fault checking enabled */
            "orr r0, r0, #0x0002n" /* .... .... .... ..1. */
            #ifdef CONFIG_CPU_D_CACHE_ON
            "orr r0, r0, #0x0004n" /* .... .... .... .1.. */
            #endif
            #ifdef CONFIG_CPU_I_CACHE_ON
            "orr r0, r0, #0x1000n" /* ...1 .... .... .... */
            #endif
            /* MMU enabled */
            "orr r0, r0, #0x0001n" /* .... .... .... ...1 */
            "mcr p15, 0, r0, c1, c0, 0n" /* write control register */
            : /* no outputs */
            : "r" (ttb) );
            }
            STEP4設(shè)置堆棧;STEP5進(jìn)行mtd設(shè)備的初始化,記錄MTD分區(qū)信息;STEP6設(shè)置私有數(shù)據(jù);STEP7初始化內(nèi)建命令。
            STEP8啟動一個SHELL,等待用戶輸出命令并進(jìn)行相應(yīng)處理。在SHELL退出的情況下,啟動操作系統(tǒng):
            #define DEFAULT_BOOT_DELAY 0x30000000
            void boot_or_vivi(void)
            {
            char c;
            int ret;
            ulong boot_delay;
            boot_delay = get_param_value("boot_delay", &ret);
            if (ret) boot_delay = DEFAULT_BOOT_DELAY;
            /* If a value of boot_delay is zero,
            * unconditionally call vivi shell */
            if (boot_delay == 0) vivi_shell();
            /*
            * wait for a keystroke (or a button press if you want.)
            */
            printk("Press Return to start the LINUX now, any other key for vivin");
            c = awaitkey(boot_delay, NULL);
            if (((c != r) && (c != n) && (c != ))) {
            printk("type "help" for help.n");
            vivi_shell();
            }
            run_autoboot();
            return;
            }
            SHELL中讀取用戶從串口輸出的命令字符串,執(zhí)行該命令:
            void
            vivi_shell(void)
            {
            #ifdef CONFIG_SERIAL_TERM
            serial_term();
            #else
            #error there is no terminal.
            #endif
            }
            void serial_term(void)
            {
            char cmd_buf[MAX_CMDBUF_SIZE];
            for (;;) {
            printk("%s> ", prompt);
            getcmd(cmd_buf, MAX_CMDBUF_SIZE);
            /* execute a user command */
            if (cmd_buf[0])
            exec_string(cmd_buf);
            }
            }
            5.電路板調(diào)試
            在電路板的調(diào)試過程中,我們首先要在ADT新建的工程中添加第一階段的匯編代碼head.S文件,修改Link腳本,將代碼和數(shù)據(jù)映射到S3C2410A自帶的0x40000000開始的4KB內(nèi)存空間內(nèi):
            SECTIONS
            {
            . = 0x40000000;
            .text : { *(.text) }
            Image_RO_Limit = .;
            Image_RW_Base = .;
            .data : { *(.data) }
            .rodata : { *(.rodata) }
            Image_ZI_Base = .;
            .bss : { *(.bss) }
            Image_ZI_Limit = .;
            __bss_start__ = .;
            __bss_end__ = .;
            __EH_FRAME_BEGIN__ = .;
            __EH_FRAME_END__ = .;
            PROVIDE (__stack = .);
            end = .;
            _end = .;
            .debug_info 0 : { *(.debug_info) }
            .debug_line 0 : { *(.debug_line) }
            .debug_abbrev 0 : { *(.debug_abbrev)}
            .debug_frame 0 : { *(.debug_frame) }
            }
            借助萬用表、示波器等儀器儀表,調(diào)通SDRAM,并將vivi中自帶的串口、NAND FLASH驅(qū)動添加到工程中,調(diào)試通過板上的串口和FLASH。如果板電路的原理與三星公司DEMO板有差距,則vivi中硬件的操作要進(jìn)行相應(yīng)的修改。全部調(diào)試通過后,修改vivi源代碼,重新編譯vivi,將其燒錄入NAND FLASH就可以在復(fù)位后啟動這個Bootloader了。
            調(diào)試板上的新增硬件時,宜在ADT中添加相應(yīng)的代碼,在不加載操作系統(tǒng)的情況下,單純地操作這些硬件。如果電路板設(shè)計有誤,要進(jìn)行飛線和割線等處理。
            6.小結(jié)
            本章講解了ARM匯編、Bootloader的功能,Bootloader的調(diào)試環(huán)境及ARM電路板的調(diào)試方法。



            關(guān)鍵詞: ARMLinux移植BootLoade

            評論


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

            關(guān)閉