mips架构u-boot 启动流程

流程分析
********************************************************
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中初始化

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值