/* * 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 */
/****************************************************************************/ /* */ /* the actual reset code */ /* */ /****************************************************************************/
// MRS {} Rd,CPSR|SPSR 将CPSR|SPSR传送到Rd // 使用这两条指令将状态寄存器传送到一般寄存器,只修改必要的位,再将结果传送回状态寄存器,这样可以最好地完成对CRSP或者SPSR的修改 // MSR {} CPSR_|SPSR_,Rm 或者是 MSR {} CPSR_f|SPSR_f,#<32-bit immediate> // MRS与MSR配合使用,作为更新PSR的“读取--修改--写回”序列的一部分 // bic r0,r1,r2 ;r0:=r1 and not r2 // orr ro,r1,r2 ;r0:=r1 or r2 // 这几条指令执行完毕后,进入SVC模式,该模式主要用来处理软件中断(SWI) reset: 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! */ // // B----转移指令,跳转到指令中指定的目的地址 // BL---带链接的转移指令,像B一样跳转并把转移后面紧接的一条指令地址保存到链接寄存器LR(R14)中,以此来完成子程序的调用 // 该语句首先调用cpu_init_crit进行CPU的初始化,并把下一条指令的地址保存在LR中,以使得执行完后能够正常返回。 // #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit /* we do sys-critical inits */ #endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT //调试阶段的代码是直接在RAM中运行的,而最后需要把这些代码固化到Flash中,因此U-Boot需要自己从Flash转移到 //RAM中运行,这也是重定向的目的所在。 //通过adr指令得到当前代码的地址信息:如果U-boot是从RAM开始运行,则从adr,r0,_start得到的地址信息为 //r0=_start=_TEXT_BASE=TEXT_BASE=0xa3000000;如果U-boot从Flash开始运行,即从处理器对应的地址运行, //则r0=0x0000,这时将会执行copy_loop标识的那段代码了。 // _TEXT_BASE 定义在board/pxa255_idp/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 /* 如果是从RAM启动,则开始设置堆栈 */
// 如果不是从RAM运行的话,则将代码拷贝到_TEXT_BASE标识的RAM中。 ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ add r2, r0, r2 /* r2 <- source end address */
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 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
/* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CFG_MALLOC_LEN /* malloc area CFG_MALLOC_LEN----(CFG_ENV_SIZE(256K) + 128*1024) */ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo CFG_GBL_DATA_SIZE 128---size in bytes reserved for initial data */ // 这里如果需要使用IRQ, 还有给IRQ保留堆栈空间, 一般不使用. #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) //二者均为4K #endif sub sp, r0, #12 /* leave 3 words for abort-stack */
/* * before relocating, we have to setup RAM timing * because memory timing is board-dependend, you will * find a lowlevel_init.S in your board directory. */ mov ip, lr bl lowlevel_init mov lr, ip
/* Memory interfaces are working. Disable MMU and enable I-cache. */ /* mk: hmm, this is not in the monahans docs, leave it now but * check here if it doesn't work :-) */
ldr r0, =0x2001 /* enable access to all coproc. */ mcr p15, 0, r0, c15, c1, 0 CPWAIT r0
mcr p15, 0, r0, c7, c10, 4 /* drain the write & fill buffers */ CPWAIT r0
/****************************************************************************/ /* */ /* Reset function: the PXA250 doesn't have a reset function, so we have to */ /* perform a watchdog timeout for a soft reset. */ /* The processor contains a 32-bits OS timer that is clocked by the 3.864 MHZ oscillator.The Operating System Count register(OSCR) is a free running up-counter.The OS timer also contains four 32-bit match registers (OSMR3, OSMR2,OSMR1,OSMR0).Developers can read and write to each register. When the value in the OSCR is equal to the value within any of the match register,and the interrupt enable bit is set,the corresponding bit in the OSSR is set.These bits are also routed to the interrupt controller where they can be programmed to cause an interrupt. OSMR3 also serves as a watchdog match register that resets the processor when a match occurs provided the OS Timer Watchdog Match Enable Register(OWER) is set.You must initialize the OSCR and OSMR registers and clear any set status bits before the FIQ and IRQ interrupts are enabled within the CPU /****************************************************************************/
.align 5 .globl reset_cpu
/* FIXME: this code is PXA250 specific. How is this handled on */ /* other XScale processors? */
reset_cpu: /*************************************************************************** * This bit is set by writing a one to it and can only be cleared by * one of the reset functions such as,hardware reset,sleep reset,watchdog * reset,and GPIO reset * 只有最低位可进行设置<31:1>不能设置 * 0-----OSMR3 match will not cause a reset of the processor * 1-----OSMR3 match will cause a reset of the processor ****************************************************************************/
/* We set OWE:WME (watchdog enable) and wait until timeout happens */