Bootloader的启动流程(一)

来源:互联网 发布:大数据研发岗位 编辑:程序博客网 时间:2024/05/16 13:40

Bootloader的启动流程(mini2440vboot为例):

 

*        系统启动的入口点。

*        程序的入口点是在/board/QQ2440/u-boot.lds中指定的,其中ENTRY(_start)说明程序从_start开始运行,而他指向的是cpu/arm920t/start.o文件。

*        我们用的是ARM920cpu架构,在复位后从地址0x00000000取它的第一条指令,所以我们将Flash映射到这个地址上,这样在系统加电后,cpu将首先执行u-boot程序。

 

vboot里的mem.lds

 

SECTIONS {

  . = 000000;

  .myhead ALIGN(0): {*(.text.FirstSector)}

  .text ALIGN(512): { *(.text) }

  .bss ALIGN(4)  : { *(.bss*)  *(COMMON) }

  .data ALIGN(4) : { *(.data*) *(.rodata*) }

}

 

指定程序从地址0x00开始取指执行。在mem.lds里还指定了代码段.text512字节对齐,.bbs.data……

 

系统启动后最开始执行的一些指令在head.S里:

 

0x00开始放的是异常向量表,即是异常向量的入口:

 

       .section .text.FirstSector

       .globl first_sector

 

first_sector:

@ 0x00: Reset            (复位异常)

       b     Reset

 

@ 0x04: Undefined instruction exception  (未定义指令异常)

UndefEntryPoint:

       b     UndefEntryPoint

 

@ 0x08: Software interrupt exception      (软件中断)

SWIEntryPoint:

       b     SWIEntryPoint

 

@ 0x0c: Prefetch Abort (Instruction Fetch Memory Abort )  (指令预取异常)

PrefetchAbortEnteryPoint:

       b     PrefetchAbortEnteryPoint

 

@ 0x10: Data Access Memory Abort   (数据访问异常)

DataAbortEntryPoint:

       b     DataAbortEntryPoint

 

@ 0x14: Not used

NotUsedEntryPoint:

       b     NotUsedEntryPoint

 

@ 0x18: IRQ(Interrupt Request) exception  IRQ

IRQEntryPoint:

       b     IRQHandle

 

@ 0x1c: FIQ(Fast Interrupt Request) exception FIQ

FIQEntryPoint:

       b     FIQEntryPoint

 

从上面可以看出定义了arm中的7中异常向量的入口(0x14 未使用),都是跳转指令。系统启动属于复位异常,所以启动后的就进入该入口

@0x00 Reset

       b Reset

跳转到Reset的位置开始执行:

 

.section .text

Reset:

       @ disable watch dog timer

       mov r1, #0x53000000

       mov r2, #0x0

       str   r2, [r1]

 

       @ disable all interrupts

       mov r1, #INT_CTL_BASE

@mov    r2, #0xffffffff

       mvn r2, #0x0

       str   r2, [r1, #oINTMSK]

       ldr   r2, =0x7ff

       str   r2, [r1, #oINTSUBMSK]    

 

       @ initialise system clocks

      ………………

       @ set GPIO for UART

       ………………

       @@ get read to call C functions

 

       进入Reset之后,开始做一些硬件的初始化工作:

       vboot的里:关闭看门狗,禁止所有中断,初始化系统时钟,初始化UART(可以从串口输出信息),设置栈指针(要执行C程序一定要设置栈指针R14(sp)),等其他一些初始化,调用C程序……

 

       head.S里的初始化做完的最后有这样一段代码:

       @ get read to call C functions

       mov fp, #0                   @ no previous frame, so fp=0

       mov a2, #0                  @ set argv to NULL

 

       bl    Main                     @C函数Main里执行

 

1:    b     1b                       @失败,死循环

 

 

Main函数在vboot的目录Main.c文件里:

void Main(void)

{

       MMU_EnableICache();      //enable指令cache,设置cp15c1寄存器的12

       MMU_EnableDCache();     //enable数据cache,设置cp15c1寄存器的2

 

       Port_Init();    //初始化GPIO,在244x_lib.c

                            //244x_lib.c里还实现了Uart_SendStringmemcpymemset函数

       NandInit();     //初始化nand flash,在初始化nand flash主要在Nand.c文件里实现

 

       if (g_page_type == PAGE_UNKNOWN) {      //初始化nandflash失败

              Uart_SendString("/r/nunsupport NAND/r/n");

              for(;;);

       }

 

       GetParameters(); //获得kernel执行的参数,

//g_os_type,g_os_strat,g_os_length,g_os_ram_start,linux_cmd_line

              //……

 

       Uart_SendString("load Image of Linux.../n/r");

       ReadImageFromNand();    //nand flash里加载内核镜像到RAM,并执行kernel

}

             

原创粉丝点击