Chinaunix首页 | 论坛 | 博客
  • 博客访问: 810792
  • 博文数量: 118
  • 博客积分: 2067
  • 博客等级: 大尉
  • 技术积分: 1751
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-17 14:27
文章存档

2016年(1)

2013年(1)

2012年(3)

2011年(26)

2010年(47)

2009年(40)

分类: LINUX

2009-08-18 13:10:13

尽管有了调试跟踪手段,甚至也可以通过串口打印信息了,但是不一定能够判断出错原因。如果能够充分理解代码的启动流程,那么对准确地解决和分析问题很有帮助。

开发板上电后,执行U-Boot的第一条指令,然后顺序执行U-Boot启动函数。函数调用顺序如图6.3所示。

看一下board/smsk2410/u-boot.lds这个链接脚本,可以知道目标程序的各部分链接顺序。第一个要链接的是cpu/arm920t/start.o,那么U-Boot的入口指令一定位于这个程序中。下面详细分析一下程序跳转和函数的调用关系以及函数实现。

1cpu/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      //中断向量

 

reset:          //复位启动子程序

      

       mrs   r0,cpsr

       bic   r0,r0,#0x1f

       orr   r0,r0,#0xd3

       msr   cpsr,r0

 

 

 

#ifdef CONFIG_INIT_CRITICAL

       bl    cpu_init_crit

#endif

 

relocate                     

       adr   r0, _start         

       ldr   r1, _TEXT_BASE     

       cmp     r0, r1         

       beq     stack_setup   

      

       ldr   r2, _armboot_start

       ldr   r3, _bss_start

       sub   r2, r3, r2         

       add   r2, r0, r2         

copy_loop:

       ldmia r0!, {r3-r10}  

       stmia r1!, {r3-r10}  

       cmp   r0, r2         

       ble   copy_loop

 

      

stack_setup:

       ldr   r0, _TEXT_BASE             

       sub   r0, r0, #CFG_MALLOC_LEN    

       sub   r0, r0, #CFG_GBL_DATA_SIZE

#ifdef CONFIG_USE_IRQ

       sub   r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

       sub   sp, r0, #12    

clear_bss:

       ldr   r0, _bss_start     

       ldr   r1, _bss_end       

       mov   r2, #0x00000000    

clbss_l:str r2, [r0]       

       add   r0, r0, #4

       cmp   r0, r1

       bne   clbss_l

      

       ldr   pc, _start_armboot

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

 

cpu_init_crit:

……  //初始化CACHE,关闭MMU等操作指令

      

       mov   ip, lr

       bl    memsetup        //memsetup子程序在board/smdk2410/memsetup.S中实现

       mov   lr, ip

       mov   pc, lr

 

2lib_arm/board.c

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

 

 

void start_armboot (void)

{

       DECLARE_GLOBAL_DATA_PTR;

       ulong size;

       init_fnc_t **init_fnc_ptr;

       char *s;

      

       gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

      

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

              }

       }

      

       size = flash_init ();

       display_flash_config (size);

      

       mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);

      

       env_relocate ();

      

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

      

       ……

       devices_init ();     

       jumptable_init ();

       console_init_r ();   

       enable_interrupts ();

      

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

               load_addr = simple_strtoul (s, NULL, 16);

       }

      

       for (;;) {

               main_loop ();     

       }

      

}

 

3init_sequence[]

init_sequence[]数组保存着基本的初始化函数指针。这些函数名称和实现的程序文件在下列注释中。

 

init_fnc_t *init_sequence[] = {

       cpu_init,            

       board_init,          

       interrupt_init,      

       env_init,            

       init_baudrate,       

       serial_init,         

       console_init_f,      

       display_banner,      

       dram_init,           

       display_dram_config,  

       NULL,

};

阅读(1004) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~