开始start.s分析,根据S3C2410来跟踪代码,参考了S3C2410的datasheet和网上各个帖子

一般来说,大家都是从start.s来分析UBOOT,但是事实是流程是从makefile中来的,也就是说是在敲入make smdk2410_config和make all后才进入start.s中,makefile在这里不做分析,韦东山的那本书有详细的说明,这里要提到的是makefile传进来的,我们在UBOOT中所设计到的LDFLAGS,这个标志确定了连接方式,其中的-T board/smd2410/U-Boot.lds -Ttext 0x33F8000(展开后的)指定了程序的布局和地址,U-Boot.lds如下(参考martree的专栏):

/*******************************************************/

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm"")
    ;指定输出可执行文件是elf格式,32位ARM指令,小端
OUTPUT_ARCH(arm)
    ;指定输出可执行文件的平台为ARM
ENTRY(_start)
    ;指定输出可执行文件的起始代码段为_start.
SECTIONS
{
        . = 0x00000000 ; 指明目标代码的起始地址从0x0位置开始,"."代表的是当前位置
        . = ALIGN(4)   ; 代码以4字节对齐
        .text : ;指定代码段
        {
          cpu/arm920t/start.o (.text) ; 代码的第一个代码部分,指明start.s是入口程序代码,被放到代码段的开头
          *(.text) ;其它代码部分
        }
        . = ALIGN(4)
        .rodata : { *(.rodata) } ;指定只读数据段,RO段
        . = ALIGN(4);
        .data : { *(.data) }     ;指定读/写数据段,RW段
        . = ALIGN(4);
        .got : { *(.got) }       ;指定got段, got段式是uboot自定义的一个段, 非标准段
        __u_boot_cmd_start = .   ;把__u_boot_cmd_start赋值为当前位置, 即起始位置
        .u_boot_cmd : { *(.u_boot_cmd) } ;指定u_boot_cmd段, uboot把所有的uboot命令放在该段.
        __u_boot_cmd_end = .;把__u_boot_cmd_end赋值为当前位置,即结束位置
        . = ALIGN(4);
        __bss_start = .; 把__bss_start赋值为当前位置,即bss段的开始位置
        .bss : { *(.bss) }; 指定bss段
        _end = .; 把_end赋值为当前位置,即bss段的结束位置
}

/****************************************/

从这里可以看出start.s是程序的入口点,下面是start.s代码

//global声明一个符号可被其它文件引用,相当于声明了一个全局变量,.globl与.global相同。
//该部分为处理器的异常处理向量表。地址范围为0x0000 0000 ~ 0x0000 0020,刚好8条指令。

.globl _start
_start:    b       reset     /*跳转到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

// .word伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并用伪操作中的expr初始化。.long与.int作用与之//相同。
_undefined_instruction:    .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:        .word not_used
_irq:            .word irq
_fiq:            .word fiq

.balignl 16,0xdeadbeef

/*
* Startup Code (reset vector)
*
* do important init only if we don't start from RAM!
* - relocate armboot to ram
* - setup stack
* - jump to second stage
*/

// TEXT_BASE在开发板相关的目录中的config.mk文件中定义, 它定义了
// 代码在运行时所在的地址, 那么_TEXT_BASE中保存了这个地址
_TEXT_BASE:
    .word    TEXT_BASE

// 声明 _armboot_start 并用 _start 来进行初始化,在board/u-boot.lds中定义。
.globl _armboot_start
_armboot_start:
    .word _start

/*
* These are defined in the board-specific linker script.
*/

// 声明_bss_start并用__bss_start来初始化,其中__bss_start定义在与板相关的u-boot.lds中。
// _bss_start保存的是__bss_start这个标号所在的地址, 这里涉及到当前代码所在
// 的地址不是编译时的地址的情况, 这里直接取得该标号对应的地址, 不受编译时
// 地址的影响. _bss_end也是同样的道理.
.globl _bss_start
_bss_start:
    .word __bss_start
// 同上
.globl _bss_end
_bss_end:
    .word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
    .word    0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
    .word 0x0badc0de
#endif

//  MRS {<cond>} Rd,CPSR|SPSR 将CPSR|SPSR传送到Rd
//  使用这两条指令将状态寄存器传送到一般寄存器,只修改必要的位,再将结果传送回状态寄存器,这样可以最好地完成对CRSP或者SPSR的修改
//  MSR {<cond>} CPSR_<field>|SPSR_<field>,Rm 或者是 MSR {<cond>} CPSR_f|SPSR_f,#<32-bit immediate>
//  MRS与MSR配合使用,作为更新PSR的“读取--修改--写回”序列的一部分
//   bic r0,r1,r2  ;r0:=r1 and not r2
//   orr ro,r1,r2  ;r0:=r1 or r2
//  这几条指令执行完毕后,进入SVC模式,该模式主要用来处理软件中断(SWI)
reset:
    mrs    r0,cpsr        /* set the cpu to SVC32 mode        */
    bic    r0,r0,#0x1f        /* (superviser mode, M=10011)        */
    orr    r0,r0,#0xb3    /*disable irq and frq SVC mode*/
    msr    cpsr,r0

/* 关闭看门狗,S3C2410手则 */
#if defined(CONFIG_S3C2400)
# define pWTCON        0x15300000
# define INTMSK        0x14400008    /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014    /* clock divisor register */
#elif defined(CONFIG_S3C2410)
# define pWTCON        0x53000000
# define INTMSK        0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK    0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */
#endif

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
    ldr     r0, =pWTCON
    mov     r1, #0x0
    str     r1, [r0]

/*
     * 屏蔽所有中断
     */
    mov    r1, #0xffffffff
    ldr    r0, =INTMSK
    str    r1, [r0]
# if defined(CONFIG_S3C2410)
    ldr    r1, =0x3ff
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif

/* 设置FCLK:HCLK:PCLK = 1:2:4 */
    /*FCLK默认为120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */

/*该语句首先调用cpu_init_crit进行CPU的初始化,并把下一条指令的地址保存在LR中,以使得执行完后能够正常返回。后面会分析*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
#endif

//调试阶段的代码是直接在RAM中运行的,而最后需要把这些代码固化到Flash中,因此U-Boot需要自己从Flash转移到
//RAM中运行,这也是重定向的目的所在。
//通过adr指令得到当前代码的地址信息:如果U-boot是从RAM开始运行,则从adr,r0,_start得到的地址信息为
//r0=_start=_TEXT_BASE=TEXT_BASE=0xa3000000;如果U-boot从Flash开始运行,即从处理器对应的地址运行,
//则r0=0x0000,这时将会执行copy_loop标识的那段代码了。
// _TEXT_BASE 定义在board/pxa255_idp/config.mk中

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
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     stack_setup

ldr    r2, _armboot_start
    ldr    r3, _bss_start
    sub    r2, r3, r2        /* r2 <- size of armboot            */
    add    r2, r0, r2        /* r2 <- source end address         */

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
#endif    /* CONFIG_SKIP_RELOCATE_UBOOT */

/* Set up the stack                            */
stack_setup:
    ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */
    sub    r0, r0, #CFG_MALLOC_LEN    /* malloc area                      */
    sub    r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */

// 这里如果需要使用IRQ, 还有给IRQ保留堆栈空间

#ifdef CONFIG_USE_IRQ
    sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif

//这里是直接减去12,但是在后面board.c中的cpu_init中代码是减8再减4的(如下),大家看到后面再反过来看看,会觉得很有意//思
/*

int cpu_init (void)
{
    /*
     * setup up stacks if necessary
     */
#ifdef CONFIG_USE_IRQ
    IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;
    FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
#endif
    return 0;
}

*/

sub    sp, r0, #12        /* leave 3 words for abort-stack    */

//该部分将未初始化数据段_bss_start----_bss_end中的数据清零。

clear_bss:
    ldr    r0, _bss_start        /* find start of bss segment        */
    ldr    r1, _bss_end        /* stop here                        */
    mov     r2, #0x00000000        /* clear                            */

clbss_l:str    r2, [r0]        /* clear loop...                    */
    add    r0, r0, #4
    cmp    r0, r1
    ble    clbss_l

#if 0
    /* try doing this stuff after the relocation */
    ldr     r0, =pWTCON
    mov     r1, #0x0
    str     r1, [r0]

/*
     * mask all IRQs by setting all bits in the INTMR - default
     */
    mov    r1, #0xffffffff
    ldr    r0, =INTMR
    str    r1, [r0]

/* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
    /* END stuff after relocation */
#endif
// 通过该语句跳转到C代码执行,stage1的使命也算完成。
    ldr    pc, _start_armboot

_start_armboot:    .word start_armboot

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
    /*
     * flush v4 I/D caches
     */
    mov    r0, #0
    mcr    p15, 0, r0, c7, c7, 0    /* flush v3/v4 cache */
    mcr    p15, 0, r0, c8, c7, 0    /* flush v4 TLB */

/*
     * 关闭MMU和缓存,这里用到了协处理器P15,参看手则,哈哈,这里有的很多看了
     */
    mrc    p15, 0, r0, c1, c0, 0
    bic    r0, r0, #0x00002300    @ clear bits 13, 9:8 (--V- --RS)
    bic    r0, r0, #0x00000087    @ clear bits 7, 2:0 (B--- -CAM)
    orr    r0, r0, #0x00000002    @ set bit 2 (A) Align
    orr    r0, r0, #0x00001000    @ set bit 12 (I) I-Cache
    mcr    p15, 0, r0, c1, c0, 0

/*进入lowlevel_init,这里主要是初始化存储控制器,S3C2410的是Bank0-bank6,比如位宽等,这个要根据自己的板子来进行相应的配置,比如网卡放在第几个bank,位宽多少,SDRAM放在哪里,多大等,移植UBOOT的时候就有的学了*/
    mov    ip, lr
    bl    lowlevel_init
    mov    lr, ip
    mov    pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

//程序后面的都是中断的处理,定义了一系列的宏,然后就是中断的处理函数,篇幅太长不列出

uboot之start.s分析相关推荐

  1. U-Boot启动过程完全分析

    1.1       U-Boot工作过程 U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶段的功能 Ø  硬件设备初始化 Ø  加载U-Boot第二阶段代码到RAM空间 ...

  2. 16.U-boot的工作流程分析-2440

    16.U-boot的工作流程分析-2440 分析的流程: 程序入口 第一阶段程序分析 第二阶段程序分析 2440开发板: 1.uboot的入口: 要看uboot工程的入口,首先打开顶层目录的Makef ...

  3. uboot第一阶段详细分析

    uboot第一阶段详细分析 作者:程姚根,华清远见嵌入式学院讲师. uboot的第一阶段设计的非常巧妙,几乎都是用汇编语言实现的,下面我们一起来看看它的精妙之处吧! 首先我们来看一下它的链接脚本,通过 ...

  4. U-BOOT启动流程详细分析[转]

    http://www.cnblogs.com/heaad/archive/2010/07/17/1779829.html U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶 ...

  5. U-Boot启动过程完全分析(转)

    1.1 U-Boot工作过程 U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶段的功能 Ø 硬件设备初始化 Ø 加载U-Boot第二阶段代码到RAM空间 Ø 设置好栈 Ø ...

  6. ARMv8架构u-boot启动流程详细分析(一)

    文章目录 1 概述 2 armv8 u-boot的启动 3 u-boot源码整体结构和一些编译配置方式 3.1 编译配置方式 3.2 u-boot源码结构 4 u-boot armv8链接脚本 4.1 ...

  7. U-Boot启动过程完全分析转

    转载自:http://www.cnblogs.com/heaad/archive/2010/07/17/1779829.html 1.1       U-Boot工作过程 U-Boot启动内核的过程可 ...

  8. 开发板与虚拟机组网、uboot源码makefile分析、uboot安全启动与非安全启动方式、uboot源码配置与编译流程、制作TF启动盘

    开发板与虚拟机组网. 局面:开发板.PC(Ubuntu系统).网线直连PC:设置Ubuntu系统:1.设置桥接模式,桥接到PC的有线网卡上:2.手动配置IP V4的地址信息,注意和开发板保持在同一网段 ...

  9. ARMv8架构u-boot启动流程详细分析(二)

    文章目录 1 u-boot在汇编启动阶段对系统的一些初始化 1.1 启动前为后续流程做的一些平台相关操作 1.2 开启地址无关后的重定位地址操作 1.3 进入_main之前系统寄存器初始化和从核的引导 ...

  10. u-boot的启动流程分析(一)

    这周翻了翻u-boot-Xilinx的源码,结合着网上看的对cortexA8.A9的u-boot的源码分析,再结合自己在Xilinx上下的u-boot源码,试着对u-boot的启动流程进行一下分析,也 ...

最新文章

  1. AI化身监工,上班还能摸鱼吗?
  2. URI, URL, URN
  3. RAC Failover三种方式
  4. 刀片服务器显示连接线,通过浏览器对刀片服务器进行管理
  5. 汇编语言语句及其格式
  6. 集成方法(随机森林)
  7. 【OpenCV】OpenCV函数精讲之 -- 格式化输出方法
  8. 解决 python中 使用tesserocr,File tesserocr.pyx, line 2401, in tesserocr._tesserocr.image_to_text 报错问题...
  9. docker registry push 覆盖_原创 | 全网最实在的docker入门教程四
  10. Launch Image Source
  11. 二叉树节点为某一值的路径
  12. python标准库学习笔记
  13. MySQL学习记录 (三) ----- SQL数据定义语句(DDL)
  14. SQL Server(三):Select语句
  15. PageHelper.startPage的作用
  16. 3种竞争力分析的简单途径
  17. 【IoT】CC2541 BLE 4.0 底层协议栈广播连接过程解析
  18. 家有经济适用男牛仔很忙
  19. 怎么做新闻软文推广?故事性新闻稿写作技巧_云媒易
  20. 【math】Hiden Markov Model 隐马尔可夫模型了解

热门文章

  1. Pin码重复出现死循环解决之道
  2. hal系统命令 android,转换 HAL 模块  |  Android 开源项目  |  Android Open Source Project...
  3. 在IDEA中运行Floodlight
  4. 如何成为一名优秀的老师?
  5. 500款LOGO素材PSD源码
  6. sql 中的sysdate使用
  7. 云贝餐饮连锁V2 v2.5.6 外卖/店内/预定/排号 餐饮外卖扫码点餐 智慧新零售
  8. fastapi_No.23_事件_启动和关闭事件
  9. 搭建基于springboot的FTP服务器
  10. 不会编程怎样进行个人建站