CPU相关的代码部分:
本系统使用的是PXA处理器,PXA处理器为一个系列,Uboot中使用的是PXA25X的处理器,由于新的开发板使用的是PXA270处理器,与PXA25X处理器不太相同,这里我们就要根据自己的处理器更改相应的start.S文件的代码,给文件位于cpu/pxa目录中。
// _start为当前的地址
.globl _start
_start: b 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
_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
.balignl 16,0xdeadbeef
/*
* Startup Code (reset vector)
*
* do important init only if we don't start from RAM!
* - relocate armboot to ram
* - setup stack
* - jump to second stage
*/
// TEXT_BASE在开发板相关的目录中的config.mk文件中定义, 它定义了
// 代码在运行时所在的地址, 那么_TEXT_BASE中保存了这个地址
_TEXT_BASE:
.word TEXT_BASE
// 见下面_bss_start的说明
.globl _armboot_start
_armboot_start:
.word _start
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
// _bss_start保存的是__bss_start这个标号所在的地址, 这里涉及到当前代码所在
// 的地址不是编译时的地址的情况, 这里直接取得该标号对应的地址, 不受编译时
// 地址的影响. _bss_end也是同样的道理.
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
// 系统中不使用IRQ, 故下面的代码不用关心.
#ifdef 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
/*********************************************************************/
/* */
/* the actual reset code */
/* */
/*********************************************************************/
// 这里是CPU启动后执行的第一条指令.
reset:
// 设置CPU进入管理模式
mrs r0,cpsr /* set the cpu to SVC32 mode */
bic r0,r0,#0x1f /* (superviser mode, M=10011) */
orr r0,r0,#0x13
msr cpsr,r0
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
// 重新启动时是否进行初始化, 这个宏要定义在用户的目标板配置头文件中
// 一般情况下是需要的, 不过, 在移植到其它开发板时可就要注意了!!
// 在我们的系统中定义了这个宏, 同时我们也是靠这个函数实现了硬件
// 相关的代码的初始化.
#ifdef CONFIG_INIT_CRITICAL
bl cpu_init_crit /* we do sys-critical inits */
#endif
// 进行重新定位, 原来在flash中, 现在要拷贝到ram中去运行. .
// _start为当前代码的起始地址
// TEXT_BASE为要拷贝到的ram地址, 定义在board/xxx/config.mk文件中
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
// 如果代码就在当前位置, 那么就不用拷贝了, 跳转过去对堆栈进行初始化
beq stack_setup
// 如果说不相等, 就要执行下面的代码进行数据大搬迁.
ldr r2, _armboot_start // 得到编译时_start的运行时地址, 其实就是TEXT_BASE ldr r3, _bss_start // 代码中的bss段起始地址,编译时定下来的运行地址!
// 他们之间的差值就是代码段数据长度.
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
// 到这里, r2中保存了代码的结束地址.
// 下面进行代码段的拷贝
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
// 接下来设置堆栈, 这里需要注意的是堆栈在代码段的下方, 不是上方!!
// 宏CFG_MALLOC_LEN和CFG_GBL_DATA_SIZE在目标板的头文件中定义.
/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
// 这里如果需要使用IRQ, 还有给IRQ保留堆栈空间, 一般不使用.
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
// 下面用于清除bss段数据, 这个本来就应当为0, 现在没有C库的支持
// 只好手动清除了.
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
ldr pc, _start_armboot // 直接加载绝对地址, 不能使用b指令
// _start_armboot的值就是start_armboot函数运行时对应的地址, 因为代码已经进行了
// 重新定位, 执行自然不会有问题了.
_start_armboot: .word start_armboot
// 下面就是关键的初始化函数的实现.
cpu_init_crit:
/* mask all IRQs */
ldr r0, IC_BASE
mov r1, #0x00
str r1, [r0, #ICMR]
// 我们没有在这个函数中实现太多的东西, 这个本身就是CPU相关的代码,
// 这里跳转到board/xxx/memsetup.S中去执行, 在这个文件中实现了所有的
// 开发板相关的代码的初始化.
mov ip, lr
bl memsetup
mov lr, ip
(本文章发表于psbec的个人blog,未经本人许可,不得用于商业用途。任何个人、媒体、其他网站不得私自抄袭;网络媒体转载请注明出处,增加原文链接,否则属于侵权行为。如有任何问题,请留言或者发邮件给psbec,地址)