u-boot启动代码分析

研发板上电后,执行U-Boot的第一条指令,然后顺序执行U-Boot启动函数。函数调用顺序如图6.3所示。
看一下board/smsk2410/u-boot.lds这个链接脚本,能够知道目标程式的各部分链接顺序。第一个要链接的是cpu/arm920t /start.o,那么U-Boot的入口指令一定位于这个程式中。下面周详分析一下程式跳转和函数的调用关系连同函数实现。
1
cpu/arm920t/start.S
这个汇编程式是U-Boot的入口程式,开头就是复位向量的代码。

6.3   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:       //
复位启动子程式
   /*
配置CPUSVC32模式 */
   mrs r0,cpsr
   bic r0,r0,#0x1f
   orr r0,r0,#0xd3
   msr cpsr,r0
/*
关闭看门狗 */

/*
这些初始化代码在系统重起的时候执行,运行时热复位从RAM中启动不执行 */
#ifdef CONFIG_INIT_CRITICAL
   bl cpu_init_crit
#endif

relocate:                       /*
U-Boot重新定位到RAM */
   adr r0, _start       /* r0
是代码的当前位置 */
   ldr r1, _TEXT_BASE    /*
测试判断是从Flash启动,还是RAM */
   cmp     r0, r1       /*
比较r0r1,调试的时候不要执行重定位 */
   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结构体地址空间   */
#ifdef CONFIG_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中实现
/*
关键的初始化子程式 */
cpu_init_crit:
……   //
初始化CACHE,关闭MMU等操作指令
   /*
初始化RAM时钟。
   *
因为内存时钟是依赖研发板硬件的,所以在board的相应目录下能够找到memsetup.S文档。
   */
   mov ip, lr
   bl memsetup       //memsetup
子程式在board/smdk2410/memsetup.S中实现
   mov lr, ip
   mov pc, lr

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


void start_armboot (void)
{
   DECLARE_GLOBAL_DATA_PTR;
   ulong size;
   init_fnc_t **init_fnc_ptr;
   char *s;
   /* Pointer is writable since we allocated a register for it */
   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;
   /*
顺序执行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 */
   }
   /* NOTREACHED - no way out of command loop except booting */
}

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,
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值