您的位置:首页 > 编程语言

使用u-boot_2016_01启动mini2440(一)启动代码

2016-04-03 19:52 363 查看
笔者有块mini2440开发板,最近又拿出来玩了下,所以想写个总结而已。网上之前成熟的mini2440 uboot代码好像都是用u-boot_2013以前的版本,2013以后的版本启动代码做了相当的修改,所以这里移植起来花了点力气。

相关代码已经上传到https://github.com/13xiaobang/mini2440-uboot_2016.01.git

mini2440的soc用的是s3c2440,因为板子买回来烧写过NOR,而且NOR启动也过于简单,所以我主要记录下NAND启动。s3c2440的NAND启动原理,是硬件通过引脚判断NAND启动后,会搬运NAND从0地址开始的前4K内容到SRAM上,然后在SRAM上运行起来,这段4K的代码,必须至少要初始化DDR,并且搬运bootloader到DDR,才能运行接下来的代码。普通的arm bootloader的启动流程来看,board_init_f应该在relocate_code之前运行,用来计算将要搬运的目的地址和栈寄存器地址等等,但是因为board_init_f代码段太大,编译不进前4K,所以,网上通用的做法好像是先预设relocate的目标地址以及堆栈,直接relocate,然后再执行board_init_f。而笔者因为想要让board_init_f真正发挥作用,所以想执行两次relocate
code,第一次也是预设目的地址以及堆栈,执行第一次relocate后,再调用board_init_f,再执行第二次relocate,也就是说,第一次relocate后,就相当于在NOR上执行了,第二次relocate就可以完全重用从NOR的启动代码。这里主要修改arch/arm/lib/crt0.S的代码:

ENTRY(_main)

/*
* Set up initial C runtime environment and call board_init_f(0).
*/

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldr sp, =(CONFIG_SPL_STACK)
#else
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
mov r3, sp
bic r3, r3, #7
mov sp, r3
#else
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
#endif
mov r0, sp
bl board_init_f_mem
mov sp, r0
#ifndef CONFIG_S3C2440_NAND_BOOT
mov r0, #0
bl board_init_f
#endif

#if ! defined(CONFIG_SPL_BUILD)
#ifndef CONFIG_S3C2440_NAND_BOOT
/*
* Set up intermediate environment (new sp and gd) and call
* relocate_code(addr_moni). Trick here is that we'll return
* 'here' but relocated.
*/

ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
mov r3, sp
bic r3, r3, #7
mov sp, r3
#else
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
#endif
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */

adr lr, here
#ifndef CONFIG_S3C2440_NAND_BOOT
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
#else
ldr r0, =(CONFIG_SYS_TEXT_BASE)
#endif
add lr, lr, r0
#if defined(CONFIG_CPU_V7M)
orr lr, #1 /* As required by Thumb-only */
#endif
#ifndef CONFIG_S3C2440_NAND_BOOT
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
#endif

#endif
#ifdef CONFIG_S3C2440_NAND_BOOT
ldr r0, =(CONFIG_SYS_TEXT_BASE)
adr lr, here
add lr, lr, r0
#endif
b first_relocate_code
here:
#ifdef CONFIG_S3C2440_NAND_BOOT
mov r0, #0
bl board_init_f
ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */
adr lr, second_here
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
second_here:
#endif
/*
* now relocate vectors
*/

bl relocate_vectors

/* Set up final (full) environment */

bl c_runtime_cpu_setup /* we still call old routine here */
#endif
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
# ifdef CONFIG_SPL_BUILD
/* Use a DRAM stack for the rest of SPL, if requested */
bl spl_relocate_stack_gd
cmp r0, #0
movne sp, r0
# endif
ldr r0, =__bss_start /* this is auto-relocated! */

#ifdef CONFIG_USE_ARCH_MEMSET
ldr r3, =__bss_end /* this is auto-relocated! */
mov r1, #0x00000000 /* prepare zero to clear BSS */

subs r2, r3, r0 /* r2 = memset len */
bl memset
#else
ldr r1, =__bss_end /* this is auto-relocated! */
mov r2, #0x00000000 /* prepare zero to clear BSS */

clbss_l:cmp r0, r1 /* while not at end of BSS */
#if defined(CONFIG_CPU_V7M)
itt lo
#endif
strlo r2, [r0] /* clear 32-bit BSS word */
addlo r0, r0, #4 /* move to next */
blo clbss_l
#endif

#if ! defined(CONFIG_SPL_BUILD)
bl coloured_LED_init
bl red_led_on
#endif
/* call board_init_r(gd_t *id, ulong dest_addr) */
mov r0, r9 /* gd_t */
ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */
/* call board_init_r */
ldr pc, =board_init_r /* this is auto-relocated! */

/* we should not return here. */
#endif

ENDPROC(_main)
代码第10行强设SP,第62行,将relocate地址设置成CONFIG_SYS_TEXT_BASE,也就是0x33A00000, 然后执行第一次first_relocate_code。由于使者过lr,所以relocate后,会跳转到here:执行。然后直接运行board_init_f,并且执行剩余标准的relocate动作(这里是从内存搬运代码,而不是nor,但执行的代码完全一样),first_relocate_code的代码如下:
ENTRY(first_relocate_code)
#ifdef CONFIG_S3C2440_NAND_BOOT
ldr r0, = __image_copy_start
ldr r1, =__image_copy_end
sub r1, r1, r0
mov r1, r1, LSR #11
add r1, r1, #1
ldr r0, =0x0;
ldr r2, =(CONFIG_SYS_TEXT_BASE)

push {lr} // save the temp reg
push {r2}

bl nand_read
pop {r4}
pop {lr}
ldr pc, =relocations
#endif

relocations:
/*
* fix .rel.dyn relocations
*/
ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */
ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */
fixloop:
ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */
and r1, r1, #0xff
cmp r1, #23 /* relative fixup? */
bne fixnext

/* relative fix: increase location by offset */
add r0, r0, r4
ldr r1, [r0]
add r1, r1, r4
str r1, [r0]
fixnext:
cmp r2, r3
blo fixloop

relocate_done:

#ifdef __XSCALE__
/*
* On xscale, icache must be invalidated and write buffers drained,
* even with cache disabled - 4.2.7 of xscale core developer's manual
*/
mcr p15, 0, r0, c7, c7, 0 /* invalidate icache */
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
#endif

/* ARMv4- don't know bx lr but the assembler fails to see that */

#ifdef __ARM_ARCH_4__
mov pc, lr
#else
bx lr
#endif

ENDPROC(first_relocate_code)
这里需要注意的是,由于要执行bl,所以第12行我把lr入栈了,之后再出栈。具体nand_read就是通过nand搬运的动作,r0是nand起始地址,r1是搬运长度,r2是搬运的DDR目的地址,具体nand_read实现是我网上找到的,代码库里有。

另外我还有些疑惑的是lowlevel_init.s里关于DDR参数的配置,我后来发现这段标红的(0x32|0x80),网上有两种配置法,一种是0x32,一种是0xB2,我发现0x32会有DDR问题,bootkernel会挂掉。这个bit7手册上写是ARM核突发操作,但我懂为什么不使能为什么不行。。。

/* the literal pools origin */

/*we should enable burst operation to fix unexpect DDR error*/

SMRDATA:

    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))

    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))

    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))

    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))

    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))

    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))

    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))

    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))

    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))

    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

    .word (0x32|0x80)

    .word 0x30

    .word 0x30
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  arm u-boot