新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 基于cortex-A8的Bootloader設(shè)計(jì)

        基于cortex-A8的Bootloader設(shè)計(jì)

        作者: 時(shí)間:2016-09-12 來源:網(wǎng)絡(luò) 收藏

        圖2  U-Boot第一階段啟動(dòng)流程

        圖2 U-Boot第一階段啟動(dòng)流程

        U-Boot上電后首先會(huì)設(shè)置cpu為管理模式,禁用L1緩存,關(guān)閉MMU和清除caches。之后會(huì)調(diào)用底層初始化函數(shù)lowlevel_init()。該函數(shù)實(shí)現(xiàn)如下:

        .globl lowlevel_init

        lowlevel_init:

        push {lr}

        #if defined(CONFIG_SPL_BUILD)

        /* 初始化時(shí)鐘 */

        bl system_clock_init

        /* 初始化內(nèi)存 */

        bl mem_ctrl_asm_init

        /* 初始化串口 */

        bl uart_asm_init

        #endif

        pop {pc}

        上述代碼中system_clock_init(), mem_ctrl_asm_init(),uart_asm_init()這三個(gè)函數(shù)需要開發(fā)者結(jié)合具體硬件環(huán)境進(jìn)行修改和實(shí)現(xiàn)。

        初始化完成之后,U-Boot會(huì)調(diào)用一個(gè)拷貝函數(shù)將BL2拷貝到內(nèi)存地址為0x3FF00000處,然后跳轉(zhuǎn)到該位置執(zhí)行BL2。在U-Boot中,BL1 和BL2是基于相同的一些源文件編譯生成的。開發(fā)者在編寫代碼時(shí)需要使用預(yù)編譯宏CONFIG_SPL_BUILD來實(shí)現(xiàn)BL1和BL2不同的功能。其拷貝函數(shù)實(shí)現(xiàn)如下:

        void copy_code_2_sdram_and_run(void)

        {

        unsigned long ch;

        void (*u_boot)(void);

        ch = *(volatile unsigned int *)(0xD0037488); /* 根據(jù)該地址的值判斷傳輸通道 */

        /* copy_bl2()函數(shù)不需要開發(fā)者去實(shí)現(xiàn),在出廠時(shí)已經(jīng)固化在了0xD0037F98地址處 */

        copy_sd_mmc_to_mem copy_bl2 = (copy_sd_mmc_to_mem) (*(unsigned int *) (0xD0037F98));

        unsigned int ret;

        if (ch == 0xEB000000) { /* CONFIG_SYS_TEXT_BASE = 0x3FF00000 */

        ret = copy_bl2(0, 49, 1024,(unsigned int *)CONFIG_SYS_TEXT_BASE, 0);

        } else if (ch == 0xEB200000) {

        ret = copy_bl2(2, 49, 1024,(unsigned int *)CONFIG_SYS_TEXT_BASE, 0);

        } else {

        return;

        }

        u_boot = (void *)CONFIG_SYS_TEXT_BASE;

        (*u_boot)(); /* 跳轉(zhuǎn)到該地址執(zhí)行 */

        }

        值得注意的是以上代碼中,copy_bl2()函數(shù)不需要開發(fā)者去實(shí)現(xiàn),在出廠時(shí)已經(jīng)將該函數(shù)固化在了0xD0037F98地址處。其函數(shù)原型如下:

        u32 (*copy_sd_mmc_to_mem)(u32 channel, u32 start_block, u16 block_size, u32 *trg, u32 init);

        /*

        參數(shù)介紹:

        channel:通道數(shù)2或0,該值通過讀取0xD0037488地址上的值判斷。

        start_block:從第幾個(gè)扇區(qū)開始拷貝,一個(gè)扇區(qū)為512byte。

        block_size:拷貝多少個(gè)扇區(qū),這里拷貝512K

        trg:目的地址:0x3FF00000, 即離內(nèi)存頂部1M的位置

        init:是否需要初始化sd卡,寫0即可。

        */

        2.3.2 第二階段初始化

        U-Boot進(jìn)入第二階段后會(huì)首先聲明一個(gè)gd_t結(jié)構(gòu)體類型的指針指向內(nèi)存地址(0x40000000 - GD_SIZE)處。0x40000000為內(nèi)存結(jié)束地址,GD_SIZE為結(jié)構(gòu)體gd_t的大小。這樣相當(dāng)于在內(nèi)存最頂端分配了一段空間用于存放一個(gè)臨時(shí)結(jié)構(gòu)體gd_t。該結(jié)構(gòu)體在global_data.h中被定義,U-Boot用它來存儲(chǔ)所有的全局變量。之后U-Boot會(huì)調(diào)用 board_init_f()和board_init_r()兩個(gè)函數(shù)進(jìn)一步對(duì)底板進(jìn)行初始化。

        (1)board_init_f()

        進(jìn)入board_init_f()之后,U-Boot首先設(shè)置之前分配的臨時(shí)結(jié)構(gòu)體,然后開始劃分內(nèi)存空間,其內(nèi)存分配示意圖如下:

        圖3  U-Boot內(nèi)存分配狀態(tài)

        圖3 U-Boot內(nèi)存分配狀態(tài)

        從內(nèi)存分配狀態(tài)圖中我們可以看到,gd指針指向的臨時(shí)結(jié)構(gòu)體存放在內(nèi)存的最頂部。BL2代碼存放在內(nèi)存地址0x3ff00000處,即距離內(nèi)存頂部1M空間的位置。接下來依次分配malloc空間,bd_t結(jié)構(gòu)體空間和gd_t結(jié)構(gòu)體空間,并且重新設(shè)置棧。最后將臨時(shí)結(jié)構(gòu)體拷貝到id指針?biāo)赶虻奈恢谩? board_init_f()實(shí)現(xiàn)過程大致如下:

        unsigned int board_init_f(ulong bootflag)

        {

        memset((void *)gd, 0, sizeof(gd_t));

        ...

        設(shè)置gd結(jié)構(gòu)體;

        ...

        addr = CONFIG_SYS_TEXT_BASE; /* CONFIG_SYS_TEXT_BASE = 0x3ff00000000 */

        addr_sp = addr - TOTAL_MALLOC_LEN;

        addr_sp -= sizeof (bd_t);

        bd = (bd_t *) addr_sp;

        gd->bd = bd;

        addr_sp -= sizeof (gd_t);

        id = (gd_t *) addr_sp;

        ...

        memcpy(id, (void *)gd, sizeof(gd_t));

        base_sp = addr_sp;

        return (unsigned int)id;

        }

        (2)board_init_r()

        board_init_r()負(fù)責(zé)對(duì)其他硬件資源進(jìn)行初始化。如網(wǎng)卡、Flash、MMC、中斷等。最后調(diào)用main_loop(),等待用戶輸入命令。

        3 設(shè)計(jì)實(shí)現(xiàn)

        3.1 支持Nand Flash讀寫

        Nand Flash是嵌入式系統(tǒng)中重要的存儲(chǔ)設(shè)備,其儲(chǔ)存對(duì)象包括Bootloader本身,操作系統(tǒng)內(nèi)核,環(huán)境變量,根文件系統(tǒng)等,所以使能Nand Flash讀寫是U-Boot移植過程中必須完成的一個(gè)步驟。U-Boot中Nand Flash初始化函數(shù)調(diào)用關(guān)系為:

        board_init_r()->nand_init()->nand_init_chip()->board_nand_init()。

        board_nand_init() 完成兩件事:(1)對(duì)關(guān)于Nand Flash控制器的相關(guān)寄存器進(jìn)行設(shè)置。(2)對(duì)nand_chip結(jié)構(gòu)體進(jìn)行設(shè)置。我們需要設(shè)置的成員項(xiàng)有IO_ADDR_R,IO_ADDR_W,這兩個(gè)成員都指向地址0xB0E00010,即 Nand Flash控制器的數(shù)據(jù)寄存器的地址。另外還需要實(shí)現(xiàn)以下三個(gè)成員函數(shù):

        ① void (*select_chip)(struct mtd_info *mtd, int chip);

        該函數(shù)實(shí)現(xiàn)Nand Flash設(shè)備選中或取消選中。

        ② void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);



        評(píng)論


        相關(guān)推薦

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

        關(guān)閉
        主站蜘蛛池模板: 宁河县| 靖远县| 焦作市| 宜昌市| 柘城县| 青海省| 辽中县| 海阳市| 临武县| 大悟县| 梅州市| 虞城县| 凌源市| 旬邑县| 绵竹市| 福建省| 监利县| 迁安市| 宁南县| 克东县| 雅安市| 建昌县| 老河口市| 文成县| 沙雅县| 根河市| 孝昌县| 西充县| 普洱| 康平县| 霍邱县| 西丰县| 德州市| 义马市| 万源市| 吉水县| 宝应县| 新营市| 吴堡县| 金溪县| 山阴县|