/*Name:uboot之start.S分析
Data:2015-3-3
Author:suj_un
*/

之start.S

多数的bootloader都分为stage1和stage2两部分。依赖于cpu体系结构的代码通常都放在stage1中并且用汇编语言来实现,而stage2则通常

用c语言实现。这样就可以实现复杂的功能,并具有良好的移植性。

1.stage1代码结构

a,定义入口。一个可执行的Image必须有一个入口通常这个入口放在ROM的0x0地址,因此,必告诉编译器这个地址。这部分工作可以通过修改链接脚本来完成。

b,设置异常向量表

c,设置CPU的速度,时钟频率和终端控制器

d,初始化内存

e,将ROM中的程序复制到RAM中

f,初始化堆栈,为C函数调用做准备

g,转到RAM中执行,这部分工作使用指令ldr PC来完成。

2.stage2 C语言代码部分

lib_arm/board.c中的start_arm_boot是C语言开始的函数,也是整个启动代码中C语言的主函数同时也是整个uboot的主函数,其主要工作有:

a,调用一系列的初始化函数

b,初始化Flash设备

c,初始化系统内存分配函数

d,初始化启动设备,如nand等

e,如果目标系统有显示设备,则初始化该类设备

f,初始化网络相关设备

g,进入命令循环等待串口输入命令并执行相关函数

 

代码分析及注释:

.globl _start              //系统复位位置,整个程序的入口
_start: breset             //跳转到reset所在位置并不会返回,此处代码位置是0x00000000
ldrpc, _undefined_instruction       //0x4
ldrpc, _software_interrupt       //0x8
ldrpc, _prefetch_abort        //0xc
ldrpc, _data_abort          //0x10
ldrpc, _not_used            //0x14
ldrpc, _irq              //0x18
ldrpc, _fiq              //0x1c
/*以上7个就是异常中断的初始地址,把每个地址对应的标号写入异常向量跳转表,每条指令占4个字节所以异常向量表的地址范围为0x00000000 - 0x00000020共32个字节
ARM体系结构规定在上电复位的起始位置必须有8条连续的跳转指令,通过硬件来实现。它们就是异常向量表。ARM在上电复位后是从0x0开始启动,如果bootloader存在,则是从_start开始执行上面的跳转没有执行。设置异常向量表的作用是识别bootloader,以后每当系统有异常出现时,cpu会根据异常号从内存0x0处开始查找并做相应的处理*/
/*
当有异常出现ARM会自动执行以下步骤:
1 将下一条指令的地址存放在连接寄存器LR中,
2 将相应的CPSR复制到SPSR中
3 根据异常类型,强制设置CPSR运行模式位
4 强制PC从相应异常向量地址取出下一条指令执行,从而跳转到异常处理函数中执行
*/
_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
_pad:
.word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef
 
_TEXT_BASE:
.wordTEXT_BASE                  //这个变量在文件/board/cotexa9/config.mk中定义
 
.globl _armboot_start
_armboot_start: 
.word _start                  //用_start定义_armboot_start
.globl _bss_start
_bss_start:
.word __bss_start                //用__bss_start定义_bss_start,其中__bss_start在链接脚本u-boot.lds中定义
 
.globl _bss_end
_bss_end:
.word _end                     //同start
 
    .macro  cache_invalidate_dcache_v7
    MRC     p15, 1, r0, c0, c0, 1      @ read Cache Level ID register (clidr)
    ANDS    r3, r0, #0x7000000         @ extract level of coherency from clidr
    MOV     r3, r3, lsr #23            @ left align level of coherency bit field
    BEQ     finished_inval             @ if loc is 0, then no need to clean
 
    MOV     r10, #0                    @ start clean at cache level 0 (in r10)
loop_1:
    ADD     r2, r10, r10, lsr #1       @ work out 3x current cache level
    MOV     r1, r0, lsr r2             @ extract cache type bits from clidr
    AND     r1, r1, #7                 @ mask of the bits for current cache only
    CMP     r1, #2                     @ see what cache we have at this level
    BLT     skip_inval                 @ skip if no cache, or just i-cache
    MCR     p15, 2, r10, c0, c0, 0     @ select current cache level in cssr
    MOV     r1, #0
    MCR     p15, 0, r1, c7, c5, 4      @ prefetchflush to synch the new cssr&csidr
    MRC     p15, 1, r1, c0, c0, 0      @ read the new csidr
    AND     r2, r1, #7                 @ extract the length of the cache lines
    ADD     r2, r2, #4                 @ add 4 (line length offset)
    LDR     r6, =0x3ff
    ANDS    r6, r6, r1, lsr #3         @ find maximum number on the way size
    CLZ     r5,r6                       @ DCI 0xE16F5F16 , find bit position of way size increment
    LDR     r7, =0x7fff
    ANDS    r7, r7, r1, lsr #13        @ extract max number of the index size
loop_2:
    MOV     r8, r6                     @ create working copy of max way size
loop_3:
    ORR     r11, r10, r8, lsl r5       @ factor way and cache number into r11
    ORR     r11, r11, r7, lsl r2       @ factor index number into r11
    MCR     p15, 0, r11, c7, c6, 2     @ invalidate by set/way
    SUBS    r8, r8, #1                 @ decrement the way
    BGE     loop_3
 
    SUBS    r7, r7, #1                 @ decrement the index
    BGE     loop_2
skip_inval:
    ADD     r10, r10, #2               @ increment cache number
    CMP     r3, r10
    BGT     loop_1
finished_inval:
    .endm
/* 上面这一段是讯为4412开发板添加,用.marco声明了一个宏汇编,作用就是将一组常用的代码写成宏,在程序调用的时候直接使用这个宏而是代码清晰。具体什么功能没有看懂。。。。。。。貌似和cache有关*/
 
#if defined(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
/*       中断堆栈设置     */
reset:          //真正的上电执行的地方
#if 0
/*
 * set the cpu to SVC32 mode and IRQ & FIQ disable
 */
mrs r0, cpsr
bic r0, r0, #0x3f
orr r0, r0, #0xd3
msr cpsr, r0
#else
mrs r0, cpsr          //保存CPSP到r0
bic r0, r0, #0x1f        //清除程序状态字低5位
orr r0, r0, #0xd3        //设置cpu进入svc模式并屏蔽irq和fiq 0x11010011
msr cpsr,r0           //将设置好的值写入到CPSR
#endif
/*ARM体系中的CPSR各个位的含义:32bit 长度的 CPSR 寄存器,其中最低 8bit 的用作控制位,最高4bit  的用作运算状态标志位,其它的24bit 保留,不可随意改写。主要介绍下低8位即CPSR_c(控制域)
 7  6   5   4     3    2      1    0  
 I   F   T  M4  M3  M2   M1  M0
:模式位 10000 - 0x0010 用户模式
快速中断
中断
管理
未定义
系统
T:状态位 1/0   Thumb/ARM
F:FIQ     1/0   disable/enable
I:IRQ     1/0   disable/enable
*/

接下来一段是讯为自己加的缓存初始化的汇编。略过。。。。。。

关MMU和缓存