• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > 基于cortex-A8的Bootloader設計

    基于cortex-A8的Bootloader設計

    作者: 時間:2016-09-12 來源:網絡 收藏

    圖2  U-Boot第一階段啟動流程

    圖2 U-Boot第一階段啟動流程

    U-Boot上電后首先會設置cpu為管理模式,禁用L1緩存,關閉MMU和清除caches。之后會調用底層初始化函數lowlevel_init()。該函數實現如下:

    .globl lowlevel_init

    lowlevel_init:

    push {lr}

    #if defined(CONFIG_SPL_BUILD)

    /* 初始化時鐘 */

    bl system_clock_init

    /* 初始化內存 */

    bl mem_ctrl_asm_init

    /* 初始化串口 */

    bl uart_asm_init

    #endif

    pop {pc}

    上述代碼中system_clock_init(), mem_ctrl_asm_init(),uart_asm_init()這三個函數需要開發者結合具體硬件環境進行修改和實現。

    初始化完成之后,U-Boot會調用一個拷貝函數將BL2拷貝到內存地址為0x3FF00000處,然后跳轉到該位置執行BL2。在U-Boot中,BL1 和BL2是基于相同的一些源文件編譯生成的。開發者在編寫代碼時需要使用預編譯宏CONFIG_SPL_BUILD來實現BL1和BL2不同的功能。其拷貝函數實現如下:

    void copy_code_2_sdram_and_run(void)

    {

    unsigned long ch;

    void (*u_boot)(void);

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

    /* copy_bl2()函數不需要開發者去實現,在出廠時已經固化在了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)(); /* 跳轉到該地址執行 */

    }

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

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

    /*

    參數介紹:

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

    start_block:從第幾個扇區開始拷貝,一個扇區為512byte。

    block_size:拷貝多少個扇區,這里拷貝512K

    trg:目的地址:0x3FF00000, 即離內存頂部1M的位置

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

    */

    2.3.2 第二階段初始化

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

    (1)board_init_f()

    進入board_init_f()之后,U-Boot首先設置之前分配的臨時結構體,然后開始劃分內存空間,其內存分配示意圖如下:

    圖3  U-Boot內存分配狀態

    圖3 U-Boot內存分配狀態

    從內存分配狀態圖中我們可以看到,gd指針指向的臨時結構體存放在內存的最頂部。BL2代碼存放在內存地址0x3ff00000處,即距離內存頂部1M空間的位置。接下來依次分配malloc空間,bd_t結構體空間和gd_t結構體空間,并且重新設置棧。最后將臨時結構體拷貝到id指針所指向的位置。 board_init_f()實現過程大致如下:

    unsigned int board_init_f(ulong bootflag)

    {

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

    ...

    設置gd結構體;

    ...

    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()負責對其他硬件資源進行初始化。如網卡、Flash、MMC、中斷等。最后調用main_loop(),等待用戶輸入命令。

    3 設計實現

    3.1 支持Nand Flash讀寫

    Nand Flash是嵌入式系統中重要的存儲設備,其儲存對象包括Bootloader本身,操作系統內核,環境變量,根文件系統等,所以使能Nand Flash讀寫是U-Boot移植過程中必須完成的一個步驟。U-Boot中Nand Flash初始化函數調用關系為:

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

    board_nand_init() 完成兩件事:(1)對關于Nand Flash控制器的相關寄存器進行設置。(2)對nand_chip結構體進行設置。我們需要設置的成員項有IO_ADDR_R,IO_ADDR_W,這兩個成員都指向地址0xB0E00010,即 Nand Flash控制器的數據寄存器的地址。另外還需要實現以下三個成員函數:

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

    該函數實現Nand Flash設備選中或取消選中。

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



    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 卓尼县| 南江县| 乌苏市| 牡丹江市| 鸡西市| 老河口市| 桃园市| 新绛县| 论坛| 长沙市| 津南区| 雷山县| 文山县| 北安市| 东台市| 陆良县| 青川县| 怀化市| 屯门区| 岳阳县| 中宁县| 海淀区| 大庆市| 巫山县| 涿州市| 遵义县| 洞口县| 明光市| 历史| 沧源| 莆田市| 台南市| 华容县| 罗江县| 石家庄市| 金沙县| 固原市| 若羌县| 怀来县| 新营市| 临高县|