硬件平台:tq2440
开发环境:Ubuntu-3.11
u-boot版本:2014.10
本文允许转载,请注明出处:http://blog.csdn.net/fulinus
现在从代码的角度来分析启动的流程:
从u-boot.lds文件知:
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
*(.__image_copy_start)
*(.vectors)
CPUDIR/start.o (.text*)
*(.text*)
}
文件中__image_copy_start位映像文件复制起始地址,它在文件arch/arm/lib/sections.c中如下定义:
char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
char __image_copy_end[0] __attribute__((section(".__image_copy_end")));
这个__image_copy_start在文件common/board_r.c中被调用,
static int initr_reloc_global_data(void)
{
#ifdef __ARM__
monitor_flash_len = _end - __image_copy_start;
.section ".vectors", "x"
参考:http://blog.sina.com.cn/s/blog_59b189220100au1k.html
所以x表示可执行段
该段下面就是可执行代码的起始位置:
_start:
b reset
b汇编指令见:http://blog.chinaunix.net/uid-20799298-id-99633.html
先不跳入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
ldr汇编指令见:http://blog.chinaunix.net/uid-28458801-id-4084264.html
举其中一个存储器地址“_undefined_instruction”为例,它定义如下:
.globl _undefined_instruction
.globl _software_interrupt
.globl _prefetch_abort
.globl _data_abort
.globl _not_used
.globl _irq
.globl _fiq
_undefined_instruction: .word undefined_instruction
undefined_instruction定义如下:
undefined_instruction:
get_bad_stack
bad_save_user_regs
bl do_undefined_instruction
下面我们再来看看reset代码段,reset定义在:arch/arm/cpu/arm920t/start.S文件中,reset(英文复位),系统复位时也会从这里开始,处理硬件上的复位,软件复位命令时通过看门狗操作实现。reset开始的代码段实现切换到超级用户模式(SVC 模式),接着是异常重定位异常表:
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
/*
* relocate exception table
*/
ldr r0, =_start
ldr r1, =0x0
mov r2, #16
copyex:
subs r2, r2, #1
ldr r3, [r0], #4
str r3, [r1], #4
bne copyex
#endif
LDR r0,=label
如果label是立即数,就把数值赋给r0, 如果lable是标识符,就把label地址的值赋给r0
r0保存了_start表示的地址,r1保存0,r2保存16,r2 = r2-1, subs中的s可以影响CPSR中的条件标志位,将r0地址处的内容读到r3中,再r0 = r0+4,str这条指令将R3中的字数据写入以R1为地址的存储器中,并将新地址R1+4写入R1,bne指令根据CPSR中的条件标志位判断是否跳转,如果subs指令中r2初值为16减为0时即影响了条件标志位,没有影响就跳转到copyex。所以异常重定位就是将__start开始的16个字拷贝到0地址开始的位置中去。
异常重定位结束后就是我们常说的关看门狗、屏蔽中断、设置系统时钟,
# if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interrupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#else
# define pWTCON 0x53000000
# define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
# endif
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, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C24X0 */
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
从它的注释我们看到只在重启就进行系统临界初始化,我们计入cpu_init_curit查看。
明天再看。