mips架構u-boot 啟動流程

來源:互聯網
上載者:User
流程分析
********************************************************
1.最開始系統上電後
 ENTRY(_start)程式進入點是 _start      board/mingddie/u-boot.lds

2._start:                          cpu/mips/start.S

3. la      t9, board_init_f          將函數board_init_f地址賦予t9
   j       t9                     跳轉到t9寄存器中儲存的地址指向的指令
                            即跳轉到RAM 中執行 C 代碼
                    這裡會列印一些資訊。
        
  3.1  board_init_f()             lib_mips/board.c
                         初始化外部記憶體
       relocate_code()            回到cpu/mips/start.S中繼續執行

4.la t9,board_init_r                cpu/mips/start.S
  j  t9                    將函數board_init_r地址賦予t9
                                   跳轉到t9寄存器中儲存的地址指向的指令
                                   即跳轉到RAM 中執行 C 代碼
                     這裡會列印一些資訊

  4.1  board_init_r() 函數                  lib_mips/board.c

  4.2  main_loop()                   common/main.c  
    s=getenv ("bootcmd")          取得環境變數中的啟動命令列,如bootcmd=bootm 0xbf020000
    run_command (s, 0);          //執行這個命令列 ,即bootm        
        

  4.3  do_bootm()                        common/cmd_bootm.c
      // printf ("## Booting image at %08lx .../n", addr);   //比如

5. bootm 啟動核心
   5.1 do_bootm_linux()    lib_mips/mips_linux.c

函數解析
***************************************************
1.board_init_f()

 1.1
void board_init_f(ulong bootflag)
{

    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
        if ((*init_fnc_ptr)() != 0) {
            hang ();
        }
    }
        //調用init_sequence 函數隊列,對板子進行一些初始化,詳細見後面
    
         初始化external memory,初始化堆棧用cache作堆棧,為

    relocate_code (addr_sp, id, addr);   //回到cpu/mips/start.S 中   

    /* NOTREACHED - relocate_code() does not return */
}

 1.2
typedef int (init_fnc_t) (void);

init_fnc_t *init_sequence[] = {

    clx_board_init,        //初始化GPIO,CPU速度,PLL,SDRAM 等
    timer_init,             //時鐘初始化
    env_init,        //環境變臉初始化
    incaip_set_cpuclk,    //根據環境變數設定CPU 時鐘
    init_baudrate,        //初始化串口傳輸速率
    serial_init,        /* serial communications setup */
    console_init_f,         //串口初始化,後面才能顯示
    display_banner,        //在螢幕上輸出一些顯示資訊
    checkboard,
    init_func_ram,
    NULL,
};

2.board_init_r()
(1)調用一系列的初始化函數。
(2)初始化Flash裝置。
(3)初始化系統記憶體配置函數。
(4)如果目標系統擁有NAND裝置,則初始化NAND裝置。
(5)如果目標系統有顯示裝置,則初始化該類裝置。
(6)初始化相關網路裝置,填寫IP、MAC地址等。
(7)進去命令迴圈(即整個boot的工作迴圈),接受使用者從串口輸入的命令,然後進行相應的工作
void board_init_r (gd_t *id, ulong dest_addr)
{

    /* configure available FLASH banks */   //配置可用的flash單元
    size = flash_init();                 //初始化flash
    display_flash_config (size);        //顯示flash 的大小

    /* initialize malloc() area */
    mem_malloc_init();
    malloc_bin_reloc();

    puts ("NAND:");
    nand_init();        /* go init the NAND */  //NAND初始化

    /* relocate environment function pointers etc. */
    env_relocate();                //初始化環境變數

    /* board MAC address */
    s = getenv ("ethaddr");        //乙太網路MAC地址
    for (i = 0; i < 6; ++i) {
        bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
        if (s)
            s = (*e) ? e + 1 : e;
    }

    /* IP Address */
    bd->bi_ip_addr = getenv_IPaddr("ipaddr");

    pci_init();         //pci初始化配置

/** leave this here (after malloc(), environment and PCI are working) **/
    /* Initialize devices */
    devices_init ();
    
    jumptable_init ();

    /* Initialize the console (after the relocation and devices init) */
    console_init_r ();              //串口初始化

    /* miscellaneous platform dependent initialisations */
    misc_init_r ();

    puts ("Net:   ");
    eth_initialize(gd->bd);

    /* main_loop() can return to retry autoboot, if so just run it again. */
    for (;;) {
        main_loop ();  //迴圈執行,試圖自動啟動,接受使用者從串口輸入的命令,
                                                                   然後進行相應的工作,設定延時時間,確定目標板是進入下載模式還是啟動載入模式
    }

    /* NOTREACHED - no way out of command loop except booting */
}

 
3.main_loop()

void main_loop (void)
{

    s = getenv ("bootdelay");  //從環境變數中取得bootdelay 核心等待延時
    bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

    debug ("### main_loop entered: bootdelay=%d/n/n", bootdelay);

        s = getenv ("bootcmd");  //從環境變數中取得bootcmd 啟動命令列
                       如bootcmd=tftp;bootm 或者 bootcmd=bootm 0xbf020000
        char *s1 = getenv ("bootargs"); //從環境變數中取得bootargs 啟動參數

    debug ("### main_loop: bootcmd=/"%s/"/n", s ? s : "<UNDEFINED>");

        run_command (s, 0);    //執行啟動命令

    //手動輸入命令

    for (;;) {

        len = readline (CFG_PROMPT); //讀取鍵入的命令到CFG_PROMPT 中

        rc = run_command (lastcommand, flag);  //執行這個命令

        
    }
#endif /*CFG_HUSH_PARSER*/
}

4.do_bootm()

int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
這個函數看著挺長的,其實無非就是將核心解壓縮,然後調用do_bootm_linux引導核心

5.do_bootm_linux()    lib_mips/mips_linux.c

列印資訊Starting kernel ...

void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
             ulong addr, ulong * len_ptr, int verify)
{
    
    char *commandline = getenv ("bootargs");
    

    theKernel =
        (void (*)(int, char **, char **, int *)) ntohl (hdr->ih_ep);

          //hdr為指向image header的指標,hdr->ih_ep就是我們用mkimage建立image時-e選項的參數:核心的入口地址

    linux_params_init (UNCACHED_SDRAM (gd->bd->bi_boot_params), commandline);

    /* we assume that the kernel is in place */
    printf ("/nStarting kernel .../n/n");

    theKernel (linux_argc, linux_argv, linux_env, 0);          //啟動核心

}

u-boot向核心傳遞啟動參數由一系列在include/configs/.h中的宏控制,啟動參數傳遞的地址在board_init中初始化

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.