Uboot启动流程分析(基于u-boot1.1.4).doc

上传人:聆听****声音 文档编号:610129 上传时间:2023-04-29 格式:DOC 页数:15 大小:142KB
下载 相关 举报
Uboot启动流程分析(基于u-boot1.1.4).doc_第1页
第1页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第2页
第2页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第3页
第3页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第4页
第4页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第5页
第5页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第6页
第6页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第7页
第7页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第8页
第8页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第9页
第9页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第10页
第10页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第11页
第11页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第12页
第12页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第13页
第13页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第14页
第14页 / 共15页
Uboot启动流程分析(基于u-boot1.1.4).doc_第15页
第15页 / 共15页
亲,该文档总共15页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Uboot启动流程分析(基于u-boot1.1.4).doc

《Uboot启动流程分析(基于u-boot1.1.4).doc》由会员分享,可在线阅读,更多相关《Uboot启动流程分析(基于u-boot1.1.4).doc(15页珍藏版)》请在冰点文库上搜索。

Uboot启动流程分析(基于u-boot1.1.4).doc

Uboot启动流程分析(基于u-boot1.1.4)

   先分析一下u-boot启动的两个阶段,分别对应start.S和board.c这两个文件。

   先看board/smsk2410/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;/*指定可执行image文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。

必须使编译器知道这个地址,通常都是修改此处来完成*/

    .=ALIGN(4);

    .text:

    {

     cpu/arm920t/start.o(.text)

     *(.text)

    }

    .=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:

{*(.bss)}

    _end=.;

}

   第一个要链接的是cpu/arm920t/start.o,那么U-Boot的入口指令一定位于这个程序中。

下面详细分析一下程序跳转和函数的调用关系以及函数实现。

1.Stage1:

cpu/arm920t/start.S

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

U-Boot启动代码流程图

_start:

breset//复位向量;;设置异常向量表

       ldrpc,_undefined_instruction

       ldrpc,_software_interrupt

       ldrpc,_prefetch_abort

       ldrpc,_data_abort

       ldrpc,_not_used

       ldrpc,_irq//中断向量

       ldrpc,_fiq//中断向量

 /*theactualresetcode*/

reset:

//复位启动子程序

       /*设置CPU为SVC32模式*/

       mrsr0,cpsr

       bicr0,r0,#0x1f;;位清除,将某些位的值置0:

r0=r0AND(!

0x1f)

       orrr0,r0,#0xd3;;逻辑或,将r0与立即数进行逻辑或,放在r0中(第一个)

       msrcpsr,r0

/*关闭看门狗*/

 /*turnoffthewatchdog*/

#ifdefined(CONFIG_S3C2400)

#definepWTCON0x15300000

#defineINTMSK0x14400008/*Interupt-Controllerbaseaddresses*/

#defineCLKDIVN0x14800014/*clockdivisorregister*/

#elifdefined(CONFIG_S3C2410)

#definepWTCON0x53000000

#defineINTMSK0x4A000008/*Interupt-Controllerbaseaddresses*/

#defineINTSUBMSK0x4A00001C

#defineCLKDIVN0x4C000014/*clockdivisorregister*/

#endif

#ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)

    ldrr0,=pWTCON

    movr1,#0x0

    strr1,[r0]

/*禁止所有中断和设置CPU频率*/

    /*

     *maskallIRQsbysettingallbitsintheINTMR-default

     */

    movr1,#0xffffffff

    ldrr0,=INTMSK

    strr1,[r0]

#ifdefined(CONFIG_S3C2410)

    ldrr1,=0x3ff

    ldrr0,=INTSUBMSK

    strr1,[r0]

#endif

    /*FCLK:

HCLK:

PCLK=1:

2:

4*/;;FCLK用于CPU,HCLK用于AHB,PCLK用于APB

    /*defaultFCLKis120MHz!

*/

    ldrr0,=CLKDIVN;;根据硬件手册来设置CLKDIVN寄存器

    movr1,#3;;用户手册的推荐值

    strr1,[r0]

#endif/*CONFIG_S3C2400||CONFIG_S3C2410*/

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

    /*

     *wedosys-criticalinitsonlyatreboot,

     *notwhenbootingfrom

     */

#ifndefCONFIG_SKIP_LOWLEVEL_INIT

    blcpu_init_crit;;跳转去初始化CPU

#endif

;;#ifdefCONFIG_INIT_CRITICAL原文中的,估计是1.1.16版本的

;;blcpu_init_crit

;;#endif

/*CPU和RAM两个关键的初始化子程序*/

/*初始化CPU*/

cpu_init_crit:

    /*

     *flushv4I/Dcaches设置CP15

     */

    movr0,#0

    mcrp15,0,r0,c7,c7,0/*flushv3/v4cache*/;;使I/Dcache失效:

将寄存器r0的数据传送到协处理器p15的c7中。

C7寄存器位对应cp15中的cache控制寄存器

    mcrp15,0,r0,c8,c7,0/*flushv4TLB*/;;使TLB操作寄存器失效:

将r0数据送到cp15的c8、c7中。

C8对应TLB操作寄存器

    /*

     *disableMMUstuffandcaches禁止MMU和caches

     */

    mrcp15,0,r0,c1,c0,0;;先把c1和c0寄存器的各位置0(r0=0)

    bicr0,r0,#0x00002300@clearbits13,9:

8(--V---RS)

    bicr0,r0,#0x00000087@clearbits7,2:

0(B----CAM);;这里我本来有个疑问:

为什么要分开设置。

因为arm汇编要求的立即数格式所决定的

    orrr0,r0,#0x00000002@setbit2(?

?

)(A)Align;;上一条已经设置bit1为0,这一条又设置为1?

    orrr0,r0,#0x00001000@setbit12(I)I-Cache

    mcrp15,0,r0,c1,c0,0;;用上面(见下面)设定的r0的值设置c1?

(cache类型寄存器)和c0(control字寄存器),以下为c0的位定义

;;bit8:

0=DisableSystemprotection

;;bit9:

0=DisableROMprotection

;;bit0:

0=MMUdisabled

;;bit1:

0=Faultcheckingdisabled禁止纠错

;;bit2:

0=Datacachedisabled

;;bit7:

0=Little-endianoperation

;;bit12:

1=Instructioncacheenabled

    /*配置内存区控制寄存器?

有待分析,是1.1.4版本的

     *beforerelocating,wehavetosetupRAMtiming

     *becausememorytimingisboard-dependend,youwill

     *findalowlevel_init.Sinyourboarddirectory.

     */

    movip,lr

    bllowlevel_init;;位于board/smdk2410/lowlevel_init.S:

用于完成芯片存储器的初始化,执行完成后返回

    movlr,ip

    movpc,lr

relocate:

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

       adrr0,_start/*r0是代码的当前位置*/;;adr伪指令,汇编器自动通过当前PC的值算出如果执行到_start时PC的值,放到r0中:

当此段在flash中执行时r0=_start=0;当此段在RAM中执行时_start=_TEXT_BASE(在board/smdk2410/config.mk中指定的值为0x33F80000,即u-boot在把代码拷贝到RAM中去执行的代码段的开始)

       ldrr1,_TEXT_BASE/*测试判断是从Flash启动,还是RAM*/;;此句执行的结果r1始终是0x33FF80000,因为此值是又编译器指定的(ads中设置,或-D设置编译器参数)

       cmpr0,r1/*比较r0和r1,调试的时候不要执行重定位*/

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

       /*准备重新定位代码*/;;以上确定了复位启动代码是在flash中执行的(是系统重启,而不是软复位),就需要把代码拷贝到RAM中去执行,以下为计算即将拷贝的代码的长度

       ldrr2,_armboot_start;;前面定义了,就是_start

       ldrr3,_bss_start;;所谓bss段,就是未被初始化的静态变量存放的地方,这个地址是如何的出来的?

根据board/smsk2410/u-boot.lds内容?

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

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

copy_loop:

/*重新定位代码*/;;开始循环拷贝启动的代码到RAM中

       ldmia{r3-r10}/*从源地址[r0]复制*/;;r0指向_start(=0)

       stmia{r3-r10}/*复制到目的地址[r1]*/;;r1指向_TEXT_BASE(=0x33F80000)

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

       blecopy_loop

 ;;这里附上u-boot各存储区域的映射图,从网上找的,这下对于这几个地址的位置就一目了然了,对于我这种菜鸟真的是好图啊!

 

/*初始化堆栈等*/

stack_setup:

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

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

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

#ifdefCONFIG_USE_IRQ

       subr0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif        ;;这些宏定义在/include/configs/smdk2410.h中:

#defineCFG_MALLOC_LEN    (CFG_ENV_SIZE+128*1024)        ;;64K+128K=0xC0

#defineCFG_ENV_SIZE    0x10000        /*TotalSizeofEnvironmentSector64k*/

#defineCONFIG_STACKSIZE    (128*1024)    /*regularstack128k*/

#defineCFG_GBL_DATA_SIZE    128    /*sizeinbytesreservedforinitialdata*/

用0x33F8000–0xC0–0x80得到_TEXT_BASE向下(低地址)的堆栈指针sp的起点地址

       subsp,r0,#12/*为abort-stack预留3个字*/    ;;得到最终sp指针初始值

clear_bss:

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

       ldrr1,_bss_end/*bss段末尾地址*/

       movr2,#0x00000000/*清零*/

clbss_l:

strr2,[r0]/*bss段地址空间清零循环...*/

       addr0,r0,#4

       cmpr0,r1

       bneclbss_l

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

       ldrpc,_start_armboot

_start_armboot:

.wordstart_armboot;;start_armboot函数在lib_arm/board.c中实现

 

2.Stage2:

lib_arm/board.c

   此文件是u-bootStage2部分,入口为Stage1最后调用的start_armboot函数。

注意上面最后ldr到pc的是_start_armboot这个地址,而非start_armboot变量。

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

 

voidstart_armboot(void)

{

       DECLARE_GLOBAL_DATA_PTR;

//此宏定义了一个gd_t类型的指针*gd,并指名用r8寄存器来存储:

#defineDECLARE_GLOBAL_DATA_PTRregistervolatilegd_t*gdasm("r8")

       ulongsize;

       init_fnc_t**init_fnc_ptr;

       char*s;

       /*Pointeriswritablesinceweallocatedaregisterforit    上面那个宏的作用*/

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

//此C语句引用的是start.S中的地址标号_armboot_start,但是得到的却是其中所指的变量_start的值(在RAM中,_start=0x33F80000)。

    Ps:

    _armboot_start:

    .word_start

//gd是全局变量,位置在堆栈区以下(低地址):

typedefstructglobal_data{

    bd_t*bd;

    unsignedlongflags;

    unsignedlongbaudrate;

    unsignedlonghave_console;/*serial_init()wascalled*/

    unsignedlongreloc_off;/*RelocationOffset*/        //此变量有什么用?

    unsignedlongenv_addr;/*AddressofEnvironmentstruct*/

    unsignedlongenv_valid;/*ChecksumofEnvironmentvalid?

*/

    unsignedlongfb_base;/*baseaddressofframebuffer*/

#ifdefCONFIG_VFD

    unsignedcharvfd_type;/*displaytype*/

#endif

#if0

    unsignedlongcpu_clk;/*CPUclockinHz!

*/

    unsignedlongbus_clk;

    unsignedlongram_size;/*RAMsize*/

    unsignedlongreset_status;/*resetstatusregisteratboot*/

#endif

    void**jt;/*jumptable*/

}gd_t;

       /*compileroptimizationbarrierneededforGCC>=3.4*/

       __asm____volatile__("":

:

:

"memory");

       memset((void*)gd,0,sizeof(gd_t));

       gd->bd=(bd_t*)((char*)gd-sizeof(bd_t));    //得到bd的起点

       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();        //初始化Norflash的函数,函数实现在下面

       display_flash_config(size);    //打印到控制台:

Flash:

512kB

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

       mem_malloc_init(_armboot_start-CFG_MALLOC_LEN);        //将CFG_MALLOC_LEN区域用memset函数清零(直接往目的地址写0)

       /*配置环境变量,重新定位*/

       env_relocate();        //刚才的初始化函数中有一个是env_init(),根据CRC校验来初始化gd->env_addr变量(自己设定的还是初始值),此函数是作用是将环境变量值从某个flash和RAM之间的拷贝。

下图描述了ENV的初始化过程:

 

/*从环境变量中获取IP地址,放到全局变量gd中*/

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

       /*以太网接口MAC地址,放到全局变量gd中,实现过程有待研究*/

          {

        inti;

        ulongreg;

        char*s,*e;

        uchartmp[64];

        i=getenv_r("ethaddr",tmp,sizeof(tmp));

        s=(i>0)?

tmp:

NULL;

        for(reg=0;reg<6;++reg){

            gd->bd->bi_enetaddr[reg]=s?

simple_strtoul(s,&e,16):

0;

            if(s)

                s=(*e)?

e+1:

e;

        }

    }

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

       jumptable_init();

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

       enable_interrupts();/*使能例外处理*/

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

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

=NULL){

               load_addr=simple_strtoul(s,NULL,16);

       }

//以上几个初始化函数有待研究

       /*main_loop()总是试图自动

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2