UBOOT启动流程分析

UBOOT特点:

用于多种CPU

用于多种操作系统


查看一下board/smdk2410/u-boot.lds这个链接脚本,可以知道目标程序的各部分链接顺序

 

OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm", "elf32-littlearm")

/*OUTPUT_FORMAT("elf32-arm","elf32-arm", "elf32-arm")*/

OUTPUT_ARCH(arm)

ENTRY(_start)                                                                            //脚本命令,指定程序入口点

SECTIONS

{

                  . = 0x00000000;

 

                  . = ALIGN(4);                                                            //伪操作,4字节对齐

                  .text      :

                  {

                    cpu/arm920t/start.o   (.text)                          //指定程序的执行代码段,即start.o文件,

                    *(.text)                                                                           //则在最先执行的程序应该是start.s

                  }

 

                  . = ALIGN(4);

                  .rodata : { *(.rodata) }

 

                  . = ALIGN(4);

                  .data : { *(.data) }

 

                  . = ALIGN(4);

                  .got : { *(.got) }

 

                  . = .;

                  __u_boot_cmd_start = .;

                  .u_boot_cmd : { *(.u_boot_cmd)}

                  __u_boot_cmd_end = .;

 

                  . = ALIGN(4);

                  __bss_start = .;

                  .bss (NOLOAD) : { *(.bss) }

                  _end = .;

}

 

下面分析cpu/arm920t/start.s文件:

ENTRY(_start)指定了从_start开始执行, 

这个汇编程序是U-Boot的入口程序,开头就是复位向量的代码。

_start: b       reset        //复位向量

       ldr  pc, _undefined_instruction

       ldr  pc, _software_interrupt

       ldr  pc, _prefetch_abort

       ldr  pc, _data_abort

       ldr  pc, _not_used

       ldr  pc, _irq      //中断向量

       ldr  pc, _fiq      //中断向量

 /* the actual reset code  */

reset:          //复位启动子程序

       /* 设置CPU为SVC32模式 */

       mrs  r0,cpsr                               /*修改cpsr时,通过将其拷贝到通用寄存器修改*/

       bic  r0,r0,#0x1f

       orr  r0,r0,#0xd3

       msr  cpsr,r0

 

/* 关闭看门狗 */

……      ……

relocate:                  /* 把U-Boot重新定位到RAM */

adr   r0, _start          /* r0是代码的当前位置 */

ldr   r1, _TEXT_BASE      /*_TEXT_BASE是RAM中的地址 */

cmp     r0, r1          /* 比较r0和r1,判断当前是从Flash启动,还是RAM */

beq     stack_setup  /* 如果r0等于r1,跳过重定位代码 */

 

/* 准备重新定位代码 */

ldr   r2, _armboot_start

ldr   r3, _bss_start

sub   r2, r3, r2       /* r2 得到armboot的大小   */

add   r2, r0, r2      /* r2 得到要复制代码的末尾地址 */

copy_loop: /* 重新定位代码 */

ldmia r0!,{r3-r10}   /*从源地址[r0]复制 */

stmia r1!,{r3-r10}   /* 复制到目的地址[r1]*/

cmp   r0, r2   /* 复制数据块直到源数据末尾地址[r2] */

ble   copy_loop

 

/* 初始化堆栈等    */

stack_setup:

ldr   r0, _TEXT_BASE  /* 上面是128 KiB重定位的u-boot */

sub   r0, r0, #CFG_MALLOC_LEN  /* 向下是内存分配空间 */

sub   r0, r0, #CFG_GBL_DATA_SIZE /* 然后是bdinfo结构体地址空间  */

#ifdefCONFIG_USE_IRQ

sub r0, r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

sub   sp, r0, #12     /* 为abort-stack预留3个字 */

clear_bss:

ldr   r0, _bss_start      /* 找到bss段起始地址 */

ldr   r1, _bss_end        /* bss段末尾地址   */

mov   r2, #0x00000000     /* 清零 */

clbss_l:str r2,[r0]  

/* bss段地址空间清零循环...  */

       add  r0, r0, #4

       cmp  r0, r1

bne   clbss_l

 

/* 跳转到start_armboot函数入口,_start_armboot字保存函数入口指针 */

ldr   pc, _start_armboot

_start_armboot:.word start_armboot     //start_armboot函数在lib_arm/board.c中实现

 

第二阶段

2.lib_arm/board.c

start_armboot是U-Boot执行的第一个C语言函数,完成系统初始化工作,进入主循环,处理用户输入的命令。

 

3.init_sequence[]

init_sequence[]数组保存着基本的初始化函数指针。

 

init_fnc_t*init_sequence[] = {

cpu_init,   /* 基本的处理器相关配置 --cpu/arm920t/cpu.c */

board_init, /* 基本的板级相关配置 --board/smdk2410/smdk2410.c */

interrupt_init,  /* 初始化中断处理 --cpu/arm920t/s3c24x0/interrupt.c */

env_init,      /* 初始化环境变量 --common/cmd_flash.c */

init_baudrate,  /* 初始化波特率设置 --lib_arm/board.c */

serial_init,  /* 串口通讯设置 --cpu/arm920t/s3c24x0/serial.c */

console_init_f,       /* 控制台初始化阶段1 --common/console.c */

display_banner,       /* 打印u-boot信息 --lib_arm/board.c */

dram_init,     /* 配置可用的RAM --board/smdk2410/smdk2410.c */

display_dram_config,  /* 显示RAM的配置大小 --lib_arm/board.c */

NULL,

};

voidstart_armboot (void)

{

/* 顺序执行init_sequence数组中的初始化函数 */

       for (init_fnc_ptr = init_sequence;*init_fnc_ptr; ++init_fnc_ptr) {

              if ((*init_fnc_ptr)() != 0) {

                      hang ();

              }

       }

/*配置可用的Flash */

       size = flash_init ();

       display_flash_config (size);

       /* _armboot_start 在u-boot.lds链接脚本中定义 */

       mem_malloc_init (_armboot_start -CFG_MALLOC_LEN);

 

/* 配置环境变量*/

env_relocate ();

 

/* 从环境变量中获取IP地址 */

gd->bd->bi_ip_addr= getenv_IPaddr ("ipaddr");

/* 以太网接口MAC 地址 */

       ……

       devices_init ();      /* 获取列表中的设备 */

       jumptable_init ();

       console_init_r ();    /* 完整地初始化控制台设备 */

       enable_interrupts (); /* 使能中断处理 */

/* 通过环境变量初始化 */

       if ((s = getenv ("loadaddr"))!= NULL) {

               load_addr = simple_strtoul (s,NULL, 16);

       }

/* main_loop()循环不断执行 */

for (;;)

{

     main_loop ();      /* 主循环函数处理执行用户命令-- common/main.c */

}


注:参考国嵌视频




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值