/*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和缓存