小乖 发表于 2014-9-16 20:59:19

u-boot第二阶段启动流程

u-boot 第一阶段启动流程:http://www.amobbs.com/thread-5595629-1-1.html
详细请看:http://m18271260665.blog.163.com/
首先还是来一张图片大致看一下第二阶段完成的任务:

在第一阶段start.S的最后有这样一句代码:

        ldr        pc, _start_armboot        @ jump to C code

当第一阶段的全部任务完成之后,就会调到_start_armboot 处开始执行第二阶段的代码,这里的_start_armboot        是一个标签,是函数void start_armboot (void)的首地址。这个函数在/lib_arm/board.c中。接下来就是按照上图中的步骤开始一步一步进行。
        同样,board.c中,也用到了很多的条件编译,这里把没用编译的都去掉了,方便阅读,精简后的代码如下:
typedef        struct environment_s {
        uint32_t        crc;                /* CRC32 over data bytes        */
        unsigned char        flags;                /* active/obsolete flags        */
        unsigned char        data; /* Environment data                */

} env_t;

typedef struct bd_info {
        //串口通讯波特率
    int                        bi_baudrate;        /* serial console baudrate */
    //IP 地址
        unsigned long        bi_ip_addr;        /* IP Address */
    //环境变量起始地址
        struct environment_s             *bi_env;
    //开发板的机器码
        ulong                bi_arch_number;        /* unique id for this board */
    //uboot传递给内核参数的起始地址
        ulong                bi_boot_params;        /* where this board expects params */
    //内存信息
        struct                                /* RAM configuration */
    {
           ulong start;//内存的起始地址
           ulong size;//内存大小
    }bi_dram;
} bd_t;

typedef        struct        global_data {
        bd_t                *bd;
        unsigned long        flags; //uboot是否重定向的标志
        //串口波特率
        unsigned long        baudrate;
        //是否有一个控制台标志
        unsigned long        have_console;        /* serial_init() was called */
        //环境变量所在的地址
        unsigned long        env_addr;        /* Addressof Environment struct */
        //环境变量是否有效
        unsigned long        env_valid;        /* Checksum of Environment valid? */
        unsigned long        fb_base;        /* base address of frame buffer */
        void                **jt;                /* jump table */
} gd_t;


typedef int (init_fnc_t) (void);
register volatile gd_t *gd asm ("r8");
ulong monitor_flash_len;

init_fnc_t *init_sequence[] = {
        //初始化CPU相关设置:系统时钟操作函数
        arch_cpu_init,                /* basic arch cpu dependent setup */
        //初始化开发板相关设置:开发板的机器码
        board_init,                /* basic board dependent setup */
        //初始化定时器
        timer_init,                /* initialize timer */
        //初始化环境变量
        env_init,                /* initialize environment */
        //初始化波特率
        init_baudrate,                /* initialze baudrate settings */
        //串口初始化
        serial_init,                /* serial communications setup */
        //控制台设备一级初始化
        console_init_f,                /* stage 1 init of console */
        //打印u-boot版本、编译时间
        display_banner,                /* say that we are here */
       
        //打印CPU类型和当前运行频率
        print_cpuinfo,                /* display cpu info (and speed) */
       
        //打印开发板名称
        checkboard,                   /* display board info */
       
        //配置可用的内存
        dram_init,                   /* configure available RAM banks */
        //显示当前内存大小
        display_dram_config,
        NULL,
};

void start_armboot (void)
{
        init_fnc_t **init_fnc_ptr;
        char *s;


        /* Pointer is writable since we allocated a register for it
       * _armboot_start :0x20f00044
       * CONFIG_SYS_MALLOC_LEN:0x120000
       * sizeof(gd_t)   :0x40
       *
       * gd : 0x20de0004
       */
        gd = (gd_t*)(_armboot_start - CONFIG_SYS_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 :0x20de0004 -0x38 = 0x20ddffcc
        gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
        memset (gd->bd, 0, sizeof (bd_t));

        gd->flags |= GD_FLG_RELOC;
       
        //uboot去掉bss段的大小
        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 ();
                }
        }
       
        //将堆区初始化为0
        /* armboot_start is defined in the board-specific linker script */
        mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
                        CONFIG_SYS_MALLOC_LEN);


        puts ("NAND:");

        //NAND FALSH 初始化
        nand_init();                /* go init the NAND */

        /*读取Nand Flash的环境变量,然后做CRC校验,如果错误则使用默认的环境变量*/
        env_relocate ();

        /*获得IP 地址*/
        gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
       
        //初始化输入、输出设备列表
        stdio_init ();        /* get the devices list going. */
       

        jumptable_init ();
       
        //初始化标准输入、输出、出错
        console_init_r ();        /* fully init console as a device */

        /* 使能IRQ异常 */
        enable_interrupts ();

        /* Initialize from environment */
        if ((s = getenv ("loadaddr")) != NULL) {
                load_addr = simple_strtoul (s, NULL, 16);
        }
       
        //初始化网卡设备
        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 */
}


void hang (void)
{
        puts ("### ERROR ### Please RESET the board ###\n");
        for (;;);
}
相关的初始化完成之后,会进入到main_loop ();

void main_loop (void)
{
        char *s;
        int bootdelay;

        u_boot_hush_start ();

        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);

        /*
       * Main Loop for Monitor Command Processing
       */       
        parse_file_outer();
        /* This point is never reached */
        for (;;);
}

static __inline__ int abortboot(int bootdelay)
{
        int abort = 0;

        printf("Hit any key to stop autoboot: %2d ", bootdelay);

        /*
       * Check if key already pressed
       * Don't check if bootdelay < 0
       */
        if (bootdelay >= 0) {
                if (tstc()) {        /* we got a key press        */
                        (void) getc();/* consume input        */
                        puts ("\b\b\b 0");
                        abort = 1;        /* don't auto boot        */
                }
        }

        while ((bootdelay > 0) && (!abort)) {
                int i;

                --bootdelay;
                /* delay 100 * 10ms */
                for (i=0; !abort && i<100; ++i) {
                        if (tstc()) {        /* we got a key press        */
                                abort= 1;        /* don't auto boot        */
                                bootdelay = 0;        /* no more delay        */
                                (void) getc();/* consume input        */
                                break;
                        }
                        udelay(10000);
                }

                printf("\b\b\b%2d ", bootdelay);
        }

        putc('\n');

        return abort;
}


最后bootcmd这条命令设置为引导内核气动就OK了。。。


u-boot 第一阶段启动流程:http://www.amobbs.com/thread-5595629-1-1.html
详细请看:http://m18271260665.blog.163.com/

ZDHCKJS 发表于 2014-9-16 21:30:09

谢谢分享,讲的真详细

deny 发表于 2014-9-16 22:05:38

还不错哦

yuntianrenren 发表于 2014-9-16 22:06:20

图文并茂,把整个流程都很清楚画出来了,容易看懂。谢谢!

pensty 发表于 2014-9-16 22:06:29

讲的真详细,谢谢

CharlesLu 发表于 2014-9-16 23:01:43

学习一下

guyong2012 发表于 2014-9-17 15:46:58

很详细,正在读

litop 发表于 2014-9-17 16:07:05

大哥,出个PDF的文档吧,,方便收藏。。{:lol:}{:lol:}{:lol:}

abutter 发表于 2014-9-23 11:14:16

不错,呵呵。

lizhaoxx 发表于 2014-9-23 11:20:58

多谢了楼主共享啊,赞。。。

CharlesLu 发表于 2014-9-23 13:47:13

感谢楼主分享

远去的记忆 发表于 2018-2-28 16:52:43

多谢分享……
页: [1]
查看完整版本: u-boot第二阶段启动流程