uboot 读书笔记【1】

UBoot user-customization 过程 ( for a certain medical system)

-u中基本变量和其展开过程

  • 输入make smdk2416_config
  • 跳转到目标位置
    smd2416_config: unconfig
        $(MKCONFIG) $(@:_config=) arm xxx xx xxx
        #跳入makeconfig
  • mkconfig 确定基本变量 ARCH,CPU,BOARD 【建立必要链接】,
    export出相关变量;变量导入到config.mk.基本配置完成
  • 输入make启动编译

以上是UBOOT的基本流程


链接和运行过程.
  • 根据运行的过程来看UBOOT是怎么完成它的功能的。
Created with Raphaël 2.1.2 start.S start_armboot()(lib_arm/board.c) init_sequence() mainloop() dobootm(),liuxdobootm()
  • start.S ()一般在cpu目录下。 体系结构相关的代码里面。为上电后前期布局使用。注意代码跳转的地方:
    relocate:                               
        adr     r0, _start   
        ldr     r1, _TEXT_BASE
        ldr     r1, _TEXT_PHY_BASE 
        ldr     r2, _armboot_start
        ldr     r3, _bss_start
        sub     r2, r3, r2     
        add     r2, r0, r2     
  • start_armboot() 与板载内容相关,一般为初始化板载设备的,如串口,USB,LCD,NAND等之类的设备。位于lib_arm目录下board.c中。核心部分代码如下: gd参考这里;
void start_armboot (void)
{
    init_fnc_t **init_fnc_ptr;//初始化的函数表
    char *s;
    gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);
    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

    /* compiler optimization barrier needed for GCC >= 3.4 */
    __asm__ __volatile__("": : :"memory");

    memset ((void*)gd, 0, sizeof (gd_t));
    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
    memset (gd->bd, 0, sizeof (bd_t));
    monitor_flash_len = _bss_start - _armboot_start;

    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
        if ((*init_fnc_ptr)() != 0) {
            hang ();
        }
    }//各种初始化函数的执行, init_fnc_ptr 就在board.c中

    mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
    nand_init();//nand 初始化

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

    /* MAC Address */
    {
        int i;
        ulong reg;
        char *s, *e;
        char tmp[64];

        i = getenv_r ("ethaddr", tmp, sizeof (tmp));
        s = (i > 0) ? tmp : NULL;

        for (reg = 0; reg < 6; ++reg) {
            gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
            if (s)
                s = (*e) ? e + 1 : e;
        }

#ifdef CONFIG_HAS_ETH1
        i = getenv_r ("eth1addr", tmp, sizeof (tmp));
        s = (i > 0) ? tmp : NULL;

        for (reg = 0; reg < 6; ++reg) {
            gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
            if (s)
                s = (*e) ? e + 1 : e;
        }
#endif//网络初始化

    devices_init ();    /* get the devices list going. */ //设备初始化   
    jumptable_init ();  //跳转表初始化
    console_init_r ();  /* fully init console as a device */ //terminal
    /* enable exceptions */
    enable_interrupts (); //中断
    /* 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 */
}
  • init_sequence 函数
    init_sequence就是指的上面的那个init_fnc_ptr的初始化过程,init_fnc_ptr的列表如下(ARM的)
init_fnc_t *init_sequence[] = {
    cpu_init,       /* basic cpu dependent setup */
    board_init,     /* basic board dependent setup */
    interrupt_init,     /* set up exceptions */
    env_init,       /* initialize environment */
    init_baudrate,      /* initialze baudrate settings */
    serial_init,        /* serial communications setup */
    console_init_f,     /* stage 1 init of console */
    display_banner,     /* say that we are here */
    dram_init,      /* configure available RAM banks */
    display_dram_config,
    NULL,
};
  • main_loop()
    前期一系列的初始化之后,进入main_loop主循环,main_loop只有两件事,一是 如果没什么事儿uboot进入内核启动,如果需要在uboot下配置,那就进入uboot的命令行。main_loop函数位于:/common/main.c中 As follows: ( 更细致的分析可以参考这里)
void main_loop (void)
{
    run_command (p, 0);
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
    s = getenv ("bootdelay");
    bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

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

    s = getenv ("bootcmd");

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

    if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
        parse_string_outer(s, FLAG_PARSE_SEMICOLON |
                    FLAG_EXIT_FROM_LOOP);
    }
#endif  /* CONFIG_BOOTDELAY */
    for (;;) {
        len = readline (CFG_PROMPT);

        flag = 0;   /* assume no special flags for now */
        if (len > 0)
            strcpy (lastcommand, console_buffer);
        else if (len == 0)
            flag |= CMD_FLAG_REPEAT;
        if (len == -1)
            puts ("<INTERRUPT>\n");
        else
            rc = run_command (lastcommand, flag);
        if (rc <= 0) {
            /* invalid command or not repeatable, forget it */
            lastcommand[0] = 0;
        }
    }
#endif /*CFG_HUSH_PARSER*/
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值