学习 ARM 开发(8) 上一次看了数据区,这次要看从引导那里跳到这里执行时,运行什么东西了。
/* * 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。
*/
reset:
/*
* 设置 cpu 运行在 SVC32 模式。
*/
mrs
r0,cpsr
bic
r0,r0,#0x1f
orr
r0,r0,#0x13
msr
cpsr,r0
具体分析如下:
/* * 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。
*/
reset:
/*
* 设置 cpu 运行在 SVC32 模式。S3C44B0 共有 7 种模式。
*/
mrs
r0,cpsr 取得当前程序状态寄存器 cpsr 到 r0。
bic
r0,r0,#0x1f 这里使用位清除指令,把中断全部清除,只置位模式控制位。
orr
r0,r0,#0x13 计算为超级保护模式。
msr
cpsr,r0 设置 cpsr 为超级保护模式。
通过设置 ARM 的 CPSR 寄存器,让 CPU 运行在操作系统模式,为后面进行其它操作作好准备了。后面的代码如下:
/*
当是从 FLASH 启动时,就要进行内存测试,当
是从 RAM 启动时,一般就是开发本源程序时,就
可以跳过。
*
*/
#ifdef CONFIG_INIT_CRITICAL
bl
cpu_init_crit
/*
在重新定位之前,要进行 RAM 访问时间测试,因为每个开发
都是不一样的。
* 可以在文件 memsetup.S 里看到它的说明。
*/
bl
memsetup #endif
/* 进行重定位 */ relocate:
/* 重定位 Boot 代码到 RAM 内存,比如从 FLASH 移到RAM
*/
adr
r0, _start
/* 把_start 的相对地址移到 r0
*/
ldr
r1, _TEXT_BASE
/* 把_TEXT_BASE 地址,就是 BOOT 在 RAM 中运行地址 */
cmp
r0, r1
/*
比较两个地址是否相同,如果相同,就已经在 RAM 运行,否则就是 FLASH 中运行。
*/
beq
stack_setup
/* 是在 FLASH 中运行,要把 FLASH 中的 BOOT 代码移到 RAM 中,然后再运行. */
2armboot_start
ldr
r3, _bss_start
sub
r2, r3, r2
/* 大小
*/
add
r2, r0, r2
/* r2 保存引导代码最后地址
*/
copy_loop:
ldmia
r0!, {r3-r10}
/* 从源地址[r0]读取 8 个字节到寄存器,每读一个就更新一次 r0 地址 */
stmia
r1!, {r3-r10}
/* 拷贝寄存器 r3-r10 的值保存到 [r1]指明的地址,每写一个字节,就增加 1.
*/
cmp
r0, r2
/* 判断是否拷贝到[r2]地址,就是引导代码结束位置。
*/
ble
copy_loop
/* 循环拷贝 */
/*
拷贝中断向量表,实际是建立起二级中断向量表,当 CPU 中断时,先运行FLASH 中断,接着就转移到实际中向表执行中断程序。
*/
r
r0, real_vectors
add
r2, r0, #1024
ldr
r1, =0x0c000000
add
r1, r1, #0x08 vector_copy_loop:
ld
r0!, }
stmia
r1!, {r3-r10}
cmp
r0, r2
ble
vector_copy_loop
/* 建立起堆栈
*/ stack_setup:
ldr
r0, _TEXT_BASE
/* upper 128 KiB: located uboot
*/
MALLOC_LEN
/* malloc area
*/
sub
r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo
*/ #ifdef CONFIG_USE_IRQ
sub
r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif
sub
sp, r0, #12
/* leave 3 words for abort-stack
*/
ldr
pc, _start_armboot /* 已经准备好了堆栈,就可跳到 C 写的代码里,
由于我的代码是 ARM,就是跳到
lib_arm/board.c(208):void start_armboot (void)中运行。
*/
_start_armboot:
.word start_armboot
/* ************************************************************************* CPU_init_critical 临界区寄存器 设置一些重要的寄存器,并进行内存测试。
* ************************************************************************* */
CON 0) /器 */ INTMSK (0x01c00+0x20000c) /* 中断控制屏蔽寄存器 */ LOCKTIME (0x01c00+0x180c) PLLCON (0x01c00000+0x180000) CLKCON (0x01c00000+0x180004) #defe WTCON (0x01c00000+0x130000) cpu_init_crit:
/* 关闭看门狗 */
ldr
r0, =WTCON
ldr
, =0x0
str
r1, [r0]
/*
* 清除所有中断位,设置 INTMRs 实现。
*/
1,=INTMSK
ldr
, =0x03fffeff
str
r0, [r1]
1INTCON
ldr
, =0x05
str
r0, [r1]
/* 设置时钟控制寄存器 */
r1, =LOCKTIME
ld
, =800
strb
r0, [r1]
/* 设置锁相环,控制 CPU 运行速度。
*/
ldr
r1, =PLLCON
#if CONFIG_S3C44B0_CLOCK_SPEED==66
ldr
r0, =0x34031
/* 66MHz (Quartz=11MHz) */ #elif CONFIG_S3C44B0_CLOCK_SPEED==75
ldr
r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz
*/ #else # error CONFIG_S3C44B0_CLOCK_SPEED undefined #endif
str
r0, [r1]
1,=CLKCON
ldr
, =0x7ff8
str
r0, [r1]
/* 调用子函数返回 */
mov
pc, lr
************************************************/
实际的中断向量表
*/ /*************************************************/ real_vectors:
b
reset
undefined_instruction
software_interrupt
prefetch_abort
data_abort
not_used
irq
b
fiq
/*************************************************/
undefined_instruction:
mov
r6, #3
b
reset
software_interrupt:
mov
r6, #4
b
reset
prefetch_abort:
mov
r6, #5
b
reset
data_abort:
mov
r6, #6
b
reset
not_used:
/* we *should* never reach this */
mov
r6, #7
b
reset
irq:
mov
r6, #8
b
reset
fiq:
mov
r6, #9
b
reset
相关热词搜索: 开发 学习 ARM