MIPS uboot代码注释

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MIPS U-Boot

——by M.C

Uboot启动流程

关中断

设置kseg0no cache

初始化gp指针

lowlevel_init mips_cache_reset 设置kseg0cache mips_cache_lock

Board_init_f relocate_code Board_init_r

启动内核根据CPU rate初始化外部时钟、内存初始化cache

cache未初始化前不能用

cache已初始化

设置临时cache栈

把uboot程序从flash搬到ram执行

start.S

mtc0zero, CP0_WATCHLO mtc0zero, CP0_WATCHHI 清除硬件数据断点,防止产生调试断点,导致程序停止。

芯片在复位后,某些寄存器的内容也许是你想要的结果,但是谁知道呢,为了保证准确无误,最好还是重新进行手动初始化

mfc0k0, CP0_STATUS

li k1, ~ST0_IE

and k0, k1

mtc0k0, CP0_STATUS

禁止全局中断

mtc0zero, CP0_CAUSE初始化异常寄存器,清除异常原因指示

mtc0zero, CP0_COUNT

mtc0zero, CP0_COMPARE

初始化时钟寄存器,防止产生计数器中断

li t0, CONF_CM_UNCACHED

mtc0t0, CP0_CONFIG

设置kseg0区不经过cache。cache需要先初始化才能使用。

bal1f

nop

.word_gp

1:

lw gp, 0(ra)bal分支调用,ra返回地址指向下下一条指令,即.word _gp

把.word_gp的存储位置载入gp寄存器,即设置GOT表的起始位置

la t9, lowlevel_init jalr t9

nop 根据CPU rate初始化外部时钟、内存。lowlevel_init函数定义见lowlevel_init.S

la t9, mips_cache_reset jalr t9

nop 初始化高速缓存cache。

mips_cache_reset函数定义见cache.S

li t0, CONF_CM_CACHABLE_NONCOHERENT

mtc0t0, CP0_CONFIG

设置kseg0区经过cache

li a0, CFG_INIT_SP_OFFSET la t9, mips_cache_lock

jalr t9

nop

li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET

la sp, 0(t0)C语言程序(接下来的函数board_init_f)调用需要栈,而ram还没有初始化不能使用,所以用CACHE_LOCK_SIZE大小的L1 D-cache锁定作为临时栈使用

#define CFG_INIT_SP_OFFSET 0x400000

以sp开始,CACHE_LOCK_SIZE大小的堆栈,使用

D-cache临时替代

la t9, board_init_f j t9

nop 初始化。

board_init_f函数定义见board.c

kseg0CACHE_LOCK_SIZE

CFG_INIT_SP_OFFSET

sp

start.S

relocate_code:对应board.c里的relocate_code(addr_sp, id, addr),此时a0=addr_sp,a1=id,a3=addr。

move sp, a0设置新的sp= addr_sp

li t0, CFG_MONITOR_BASE la t3, in_ram

lw t2, -12(t3)

move t1, a2board/xxx/config.mk #define CFG_MONITOR_BASE TEXT_BASE

t0= uboot程序在flash的超始地址,t1 = 准备把uboot程序移到ram中的起始地址t2 = uboot程序的结束地址

move t6, gp

sub gp, CFG_MONITOR_BASE add gp, a2

sub t6, gp, t6t6 = 旧gp

计算旧的gp与相对于TEXT_BASE的偏移

计算新的gp在移动目的地内存中的地址

t6 = 新gp(内存中)与旧gp(flash中)的地址偏移量,这个值也是整个uboot从flash移到内存的偏移量。等同于(Destination Address -CFG_MONITOR_BASE)

1:

lw t3, 0(t0)

sw t3, 0(t1) addu t0, 4

ble t0, t2, 1b addu t1, 4按字拷贝,把uboot bin的内容从源地址(flash)拷贝到目的地址(内存),拷贝的长度是从uboot开始到uboot_end_data为止,uboot_end_data后面是bss段,详见u-boot.lds

addi t0, a2, in_ram-_start

j t0

nop

计算in_ram在内存中的新地址保存到t0,然后跳转到内存中运行in_ram。从此开始,uboot的代码将在ram中运行了

.gpword_GLOBAL_OFFSET_TABLE

.word uboot_end_data

.word uboot_end

.word num_got_entries

in_ram:

t3 = num_got_entries,t4 = 新的GOT[2]

li t2, 2

1:

lw t1, 0(t4)

beqz t1, 2f

add t1, t6

sw t1, 0(t4) 2:

addi t2, 1

blt t2, t3, 1b

addi t4, 4这里是一个循环,从GOT[2]开始,判断如果GOT表项有内容,则把内容从旧的GOT表拷贝到新的GOT表里。为什么要做拷贝呢?上面的程序已经把uboot整个程序从flash拷贝到了ram里,注意,只是内容拷贝,GOT里的地址还是老地址,所以要做重定位(如果是静态编译且属于模块内相对偏移,就不需要这个步骤了)。手工重定位的方法就是把旧GOT里的内容读取,然后加上偏移(uboot在flash与ram的偏移)赋值给新GOT里的对应表项

程序构建过程(编译和生成程序时的链接)为每个链接单元(构成动态链接程序的二进制文件,如.o、.a、.so)至少定义一个GOT,每个函数都可以找到自己的GOT,因为GOT的位置离链接单元的入口点的偏移量是固定已知的。链接单元作为一个整体载入内存,所以GOT的内部偏移量与编译时是一样的。

u-boot在编译时使用-fpic,会生成一个.got段来存储绝对地址符号。

lw t1, -12(t0) lw t2, -8(t0) add t1, t6

add t2, t6

sub t1, 4

1:

addi t1, 4

bltl t1, t2, 1b

sw zero, 0(t1)t1 = uboot_end_data,t2 = uboot_end

进行BSS段的清零,此时还没有操作系统,动态链接器,加载器等这些东东都还没有,所以要手动执行清零

move a0, a1

la t9, board_init_r j t9

move a1, a2跳转到ram中的board_init_r执行,根据MIPS ABI规范,a0、a1分别是board_init_r的第一个、第二个参数,即board_init_r(gd_t*id, ulong dest_addr)中id = a0,dest_addr= a2

相关文档
最新文档