arm linux 启动代码分析uboot

今天晚上总算把自己的arm linux启动部分讲座讲了第一部分和第二部分了,明天还要讲第三部分和第四部分,今天主要讲了下uboot的启动流程和linux的编译链接过程,明天接着讲linux汇编的启动部分,下面我把uboot的部分介绍下

一、U-boot的启动流程

Uboot的启动流程如下:

1)第一阶段的功能

  Ø  硬件设备初始化

  Ø  加载U-Boot第二阶段代码到RAM空间

  Ø  设置好栈

  Ø  跳转到第二阶段代码入口

(2)第二阶段的功能

  Ø  初始化本阶段使用的硬件设备

  Ø  检测系统内存映射

 Ø  将内核从Flash读取到RAM中

 Ø  为内核设置启动参数

 Ø  调用内核

二、U-boot链接脚本的介绍

1 uboot的链接脚本的内容及分析如下

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

OUTPUT_ARCH(arm)

ENTRY(_start)  //指定启动时的函数入口地址,_start在每个CPUstart.S中定义

                 //真正的启动运行地址段由TEXT_BASE宏定义在编译时由config.mk中定义

SECTIONS

{

  . = 0;                             //指定系统启动从偏移地址 0开始

  . = ALIGN(4);                     //地址进行4字节对其调整,确保低 2bit地址线为 0

  .text      :                       //定义.text段空间

        {

    cpu/sep4020/start.o  (.text)   //指定 start.o目标文件首先从.text段分配

     *(.text)                         //后续.text段内容的分配

  }

 

  . = ALIGN(4);   //.text段处理后,进行4字节地址对其调整,然后分配.rodata段空间

  .rodata : { *(.rodata) }

 

  . = ALIGN(4);    //4字节地址调整,然后分配.data段空间

  .data : { *(.data) }

 

  . = ALIGN(4);    //4字节地址调整,然后分配.got段空间

  .got : { *(.got) }

__u_boot_cmd_start = .;             //定义.u_boot_cmd的段空间,

  .u_boot_cmd : { *(.u_boot_cmd) }  //并且__u_boot_cmd_start符号指向段空间开始

  __u_boot_cmd_end = .;               //__u_boot_cmd_end符号指向该段空间结束

 

  armboot_end_data = .;             // armboot_end_data符号指向之前所有分配完段的结束, 

//后续将开始.bss段的分配

 

  . = ALIGN(4);                       //地址 4字节调整,开始分配.bss段空间

  __bss_start = .;                   //.bss段空间开始地址

  .bss : { *(.bss) }

  _end = .;                            //.bss段空间结束地址

}

说明1:标准应用程序包括 3 类标准段空间:.text 运行代段;.data 全局变量等具有初始值的数据空间;.bss暂态变量,堆栈等数据空间;

说明 2.rodata.got.u_boot_cmd 等段空间由程序员设计需要而自行定义的段空间;

说明 3:本PPT采用 ARM720T CPU 进行分析,其指令字长为 4字节,所以地址调整为 4 字节;

2 U-boot起始地址的指定

1)在配置文件config.mk154定义了CPPFLAGS 变量,其中指定了程序的链接基址为       TEXT_BASE

       CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS)  -D__KERNEL__

       ifneq ($(TEXT_BASE),)

       CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)

       Endif

2)在其后又在172CFLAGS 包含了CPPFLAGS变量

       CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes

3)然后在主Makefile中将config.mk进来了,这样其中的大部分变量都在编译过程中有固定的值了

       # load other configuration

       include $(TOPDIR)/config.mk

4)在生成elf可执行文件u-boot的命令中就指定了链接标志LDFLAGS

$(obj)u-boot:    depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT)

        cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \

               --start-group $(__LIBS) --end-group $(PLATFORM_LIBS)

               -Map u-boot.map -o u-boot

 

三、U-boot的相关代码分析

1cpu/sep4020/start.S启动分析

.globl _start

_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   //快速中断向量

 

_TEXT_BASE: //程序在SDRAM中运行的起始地址,即链接的起始地址

.word      TEXT_BASE  // TEXT_BASE是链接时候的起始地址,在/board/prochip/UB4020/config.mk中定义的

 

.globl _armboot_start

_armboot_start:       //程序运行起始地址,实际上是FLASH中程序的起始运行地址

.word _start

 

.globl _bss_start

_bss_start:       //bss段的起始链接地址

.word __bss_start

 

.globl _bss_end

_bss_end: //bss段的链接结束地址

.word _end

/*

 * 实际的启动复位代码

 */

reset://复位启动子程序

/*stack setup for each mode*/

/* SVC32 mode*/  

mrs  r0,cpsr    //设置 CPU SVC32模式

bic   r0,r0,#0x1f

orr   r0,r0,#0x13

msr  cpsr,r0

ldr   r0, _TEXT_BASE//配置SVC模式的堆栈空间(在sdram中)

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     

 

 

#ifdef CONFIG_USE_IRQ

/* IRQ mode*/

mov R4, #0xD2             //切换 CPU IRQ模式

    msr  cpsr, R4  

ldr   r0, _TEXT_BASE //配置IRQ模式的堆栈空间(在sdram中)

sub  r0, r0, #CFG_MALLOC_LEN

sub  r0, r0, #CFG_GBL_DATA_SIZE

sub  r0, r0, #(CONFIG_STACKSIZE_FIQ)

sub  sp, r0, #12

。。。。。。。。。。其他模式配置堆栈省略。。。。。。。。。。。。。

/*返回 SVC 模式*/      

mov R4, #0xD3             //关闭系统的中断

    msr  cpsr, R4       

bl      cpu_init_crit

/*********************进入cpu_init_crit 函数******************************************/

cpu_init_crit://cpu的初始化

/* 配置SEP4020的主频 */

ldr   r0, =0x10001004    /*96M*/

ldr   r1, =0x400B         

str   r1, [r0]

 

ldr   r0, =0x10001014    /*Normal*/

ldr   r1, =0x1

str   r1, [r0]

ldr   r0, =0x10001004    /*96M*/

ldr   r1, =0xC00B         

str   r1, [r0]

 

ldr   r0, =0x1000100C   /*open all*/

ldr   r1, =0xFFFFFFFF

str   r1, [r0]

 

/*配置SEP4020的串口参数*/

#if 1

ldr   r0, =0x1000500C   /*databit:8*/

ldr   r1, =0x83

str   r1, [r0]

 

ldr   r0, =0x10005004    /*baud=9600*/

ldr   r1, =0x0

str   r1, [r0]

 

ldr   r0, =0x10005000

ldr   r1, =0x2F

str   r1, [r0]

 

ldr   r0, =0x1000500C

ldr   r1, =0x3

str   r1, [r0]

#endif

mov pc, lr

/*********************cpu_init_crit 函数返回**************************************/

 

/*

 *U-BOOT重定位之前我们需要配置好SDRAM的相应参数,这个是在borad目录的lowlevel_init.S中完成的

 */

bl     lowlevel_init

/*******进入lowlevel_init函数*******/

/*

* lowlevel_init主要配置4020EMI模块相应的参数

*/

.globl lowlevel_init

lowlevel_init:

    ldr    r4,    =EMI_CSECONF

    ldr    r5,    =0x8ca6a6a1                

    str    r5,    [ r4 ]

 

    ldr    r4,    =EMI_SDCONF1

    ldr    r5,    =0x1E184177

    str    r5,    [ r4 ]

 

    ldr    r4,    =EMI_SDCONF2

    ldr    r5,    =0x80001860

    str    r5,    [ r4 ]

/*******lowlevel_init函数返回*******/

 

/*将系统的0地址remapsdram中去*/

 

remap:

mov r0, pc

add  r0,   r0,   #0x20000000

add  r0,   r0,   #0x08

mov pc,   r0

 

mov r0,   r0

mov r0,   r0

mov r0,   r0

mov r0,   r0

 

    ldr   r4,   =0x11000020

     ldr   r5,   =0xb    //remapsdram

str   r5,   [ r4 ]

/*

清系统的BSS

*/

ldr r0, = 0

ldr r1, _bss_start

ldr r2, _bss_end

bss_init:

str r0, [r1]

add r1,r1,#4

cmp r1,r2

blt bss_init

 

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

 

/*比较系统的运行地址和链接地址判断是否需要将u-boot搬运到sdram中去,在我们的SEP4020中我们是将U-BOOT重新搬运到SDRAM0x30700000地址处*/

relocate:                        /* relocate U-Boot to RAM        */

adr   r0, _start        /* r0 <- current position of code   */

ldr   r1, _TEXT_BASE         /* test if we run from flash or RAM */

cmp     r0, r1                  /* don't reloc during debug         */

beq    vector_copy     //如果相等则说明已经在sdram中,这时候只需要搬运中断向量表

 

ldr   r2, _armboot_start

ldr   r3, _bss_start

sub  r2, r3, r2        /* r2 <- size of armboot            */

add  r2, r0, r2        /* 将源码的结束地址赋值给r2 */

 

copy_loop:       //正真的代码搬运过程

ldmia       r0!, {r3-r10}         /* copy from source address [r0]    */

stmia       r1!, {r3-r10}         /* copy to   target address [r1]    */

cmp r0, r2                    /* until source end addreee [r2]    */

ble   copy_loop

/*

搬运中断向量表到sdram0地址去

*/

vector_copy:

ldr   r0, _TEXT_BASE

add  r2, r0, #128

ldr   r1, =0x30000000 /*modified by shixq from 0x0c000000 to 0x30000000*/

/*     add  r1, r1, #0x08 *//*deleted by shixq*/

vector_copy_loop://搬运中断向量表的循环

ldmia       r0!, {r3-r10}

stmia       r1!, {r3-r10}

cmp r0, r2

ble   vector_copy_loop

#endif      /* CONFIG_SKIP_RELOCATE_UBOOT */

 

/*使能4020的中断*/

mrs  R4, cpsr

    bic   R4, R4, #0x80

    msr  cpsr, R4 

 

/*跳转到系统的c语言初始化函数start_armboot 中去,开始初始化系统的各种外设*/

ldr   pc, _start_armboot

 

_start_armboot:       .word start_armboot



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值