Boot来DIY自己的arm11(6410)的bootloader(5)

/*
 * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND)
 * r0: size to be compared
 * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size
 */
 .globl copy_from_nand
 //从NANDflash中拷贝8K以后的代码值DRAM
copy_from_nand:
 mov r10, lr  /* save return address */

mov r9, r0
 /* get ready to call C functions */
 ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */
 sub sp, sp, #12
 mov fp, #0  /* no previous frame, so fp=0 */
 mov r9, #0x1000
 bl copy_uboot_to_ram

3: tst  r0, #0x0
 bne copy_failed

ldr r0, =0x0c000000
 ldr r1, _TEXT_PHY_BASE
1: ldr r3, [r0], #4
 ldr r4, [r1], #4
 teq r3, r4
 bne compare_failed /* not matched */
 subs r9, r9, #4
 bne 1b

4: mov lr, r10  /* all is OK */
 mov pc, lr

copy_failed:
 nop  /* copy from nand failed */
 b copy_failed

compare_failed:
 nop  /* compare failed */
 b compare_failed

/*
 * we assume that cache operation is done before. (eg. cleanup_before_linux())
 * actually, we don't need to do anything about cache if not use d-cache in U-Boot
 * So, in this function we clean only MMU. by scsuh
 *
 * void theLastJump(void *kernel, int arch_num, uint boot_params);
 */
#ifdef CONFIG_ENABLE_MMU
 .globl theLastJump
theLastJump:
 mov r9, r0
 ldr r3, =0xfff00000
 ldr r4, _TEXT_PHY_BASE
 adr r5, phy_last_jump
 bic r5, r5, r3
 orr r5, r5, r4
 mov pc, r5
phy_last_jump:
 /*
  * disable MMU stuff
  */
 mrc p15, 0, r0, c1, c0, 0
 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
 mcr p15, 0, r0, c1, c0, 0

mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

mov r0, #0
 mov pc, r9
#endif
/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */
 //中断处理
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72

#define S_OLD_R0 68
#define S_PSR  64
#define S_PC  60
#define S_LR  56
#define S_SP  52

#define S_IP  48
#define S_FP  44
#define S_R10  40
#define S_R9  36
#define S_R8  32
#define S_R7  28
#define S_R6  24
#define S_R5  20
#define S_R4  16
#define S_R3  12
#define S_R2  8
#define S_R1  4
#define S_R0  0

#define MODE_SVC 0x13
#define I_BIT  0x80

/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */

.macro bad_save_user_regs
 sub sp, sp, #S_FRAME_SIZE  @ carve out a frame on current user stack
 stmia sp, {r0 - r12}  @ Save user registers (now in svc mode) r0-r12

ldr r2, _armboot_start
 sub r2, r2, #(CFG_MALLOC_LEN)
 sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
 ldmia r2, {r2 - r3}  @ get values for "aborted" pc and cpsr (into parm regs)
 add r0, sp, #S_FRAME_SIZE  @ grab pointer to old stack

add r5, sp, #S_SP
 mov r1, lr
 stmia r5, {r0 - r3}  @ save sp_SVC, lr_SVC, pc, cpsr
 mov r0, sp    @ save current stack into r0 (param register)
 .endm

.macro irq_save_user_regs
 sub sp, sp, #S_FRAME_SIZE
 stmia sp, {r0 - r12}  @ Calling r0-r12
 add r8, sp, #S_PC  @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
 stmdb r8, {sp, lr}^  @ Calling SP, LR
 str lr, [r8, #0]  @ Save calling PC
 mrs r6, spsr
 str r6, [r8, #4]  @ Save CPSR
 str r0, [r8, #8]  @ Save OLD_R0
 mov r0, sp
 .endm

.macro irq_restore_user_regs
 ldmia sp, {r0 - lr}^  @ Calling r0 - lr
 mov r0, r0
 ldr lr, [sp, #S_PC]  @ Get PC
 add sp, sp, #S_FRAME_SIZE
 subs pc, lr, #4  @ return & move spsr_svc into cpsr
 .endm

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/2c4b5a376011f5a91a566a097dc0a659.html