U-boot在开发板上移植过程详解(2)---U-boot实现源码分析(第一阶段)
时间:2011-05-22 来源:☆&寒 烟☆
前边,我们说了,一般的bootloader都分为两个阶段。我在讲U-boot实现源码分析时,也是按照这连个阶段来分析,如果对这两个阶段不清楚,请看前边的博客。好了,开始今天的主题:U-boot在开发板上移植过程详解(2)---U-boot实现源码分析(start.S分析)
第一阶段:
1)一些基本的硬件初始化工作
u-boot对应的第一阶段代码放在cpu/arm920t/start.S文件中,入口代码如下:
.globl _start ;global声明一个符号可被其它文件引用,相当于声明了一个全局变量,.globl与.global相同
;.word伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并用伪操作中的expr初始化。 _undefined_instruction: .word undefined_instruction ;就是在当前地址,即_undefined_instruction 处存放 undefined_instruction
_software_interrupt: .word software_interrupt |
这部分就是异常向量表。当系统上电或复位后,将执行第一条指令,即跳转到标签为reset的代码处执行,具体如下:
reset: ;设置CPU为SVC32管理模式
#if defined(CONFIG_S3C2400) ;关闭看门狗
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
mov r1, #0xffffffff ;屏蔽所有中断
#ifndef CONFIG_SKIP_LOWLEVEL_INIT |
上面的代码将CPU设为管理模式,关闭看门狗,屏蔽中断并设置中断,最后调用cpu_init_crit函数进行cpu的初始化,代码如下:
cpu_init_crit: ;清除指令和数据缓存 mcr p15, 0, r0, c8, c7, 0 ;mcr指令用于将ARM处理器寄存器的数据传送到协处理器寄存器中,若协处理器不能成功完成操作,则 ;产生未定义指令异常。其中协处理器操作码1和协处理器操作码2为协处理器将要执行的操作,目的寄存器 ;为ARM处理器的寄存器,源寄存器1和源寄存器2均为协处理器的寄存器。
mrc p15, 0, r0, c1, c0, 0 ;mrc 协处理器寄存器到ARM处理器寄存器的数据传送指令
mov ip, lr ;设置SDRAM控制器,与具体的目标板相关 |
在这个函数中做了一下工作:清除指令与数据缓存,禁用MMU与数据指令缓存,最后调用lowlevel_init函数设置SDRAM控制器。该函数的实现与具体的目标板有关的。
2)准备RAM空间
所谓准备RAM空间,就是初始化内存芯片,使它可用。 在board/smdk2410/lowlevel.init.S就是这个作用,要注意这时的代码,数据都保存在NOR Flash上,内存中还没有,所以读取数据时要变换地址,如下:
_TEXT_BASE:
.globl lowlevel_init
;现在起三行进行地址变化,因为这时候内存中还没有数据,不能使用连接程序时确定的地址来读取数据 mov pc, lr
.ltorg
SMRDATA: ;13个寄存器的值 .word … … |
这里做完以后,就要将整个U-boot的代码都复制到SDRAM中,这些又都在start.S中实现,如下:
relocate: ;将u-boot复制到RAM中
ldr r2, _armboot_start ;_armboot_start在前边已经定义,是第一条指令的运行地址
copy_loop: |
接下来,就要设置栈,栈的设置灵活性很大,只要让sp寄存器指向一段没有使用的内存即可。
stack_setup: |
3)跳转到第二阶段代码的C入口点
在跳转之前,还要清除BSS段(初始值为0,无初始值的全局变量,静态变量放在BSS段),代码如下:
clear_bss:
clbss_l:str r2, [r0] ;往BSS段中写入0值 |
现在,c函数的运行环境已经完全准备好了,通过如下命令直接跳转(这之后,程序才在内存中执行),它将调用lib_arm/board.c中的start_armboot函数(这是一个C语言函数),这是第二阶段的入口点:
ldr pc, _start_armboot _start_armboot: .word start_armboot |
在第二阶段代码中,将进行更多的初始化工作,如对各种设备和接口的初始化,串口终端的初始化等。如果没有设置自动运行,则最终将进入一个循环,在循环内读取用户输入的命令并执行,这些会在下一节详细介绍。