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

笔者有块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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
u-boot-2016.11.tar.bz2是一个开源软件项目的压缩文件。该压缩文件是u-boot引导加载程序的源代码和相关文件的打包形式。u-boot(Universal Bootloader)是一款用于嵌入式系统的开源引导加载程序,用于初始化硬件并启动操作系统。 u-boot-2016.11.tar.bz2文件的扩展名.tar.bz2表示它是使用tar和bzip2两种工具进行压缩的。.tar是一个常用的文件打包工具,它可以将多个文件和目录打包成一个文件。.bz2是一个压缩工具,可以将文件进行高效压缩。 要使用u-boot-2016.11.tar.bz2文件,首先需要将其解压缩。可以使用tar命令进行解压缩,命令为tar -xjf u-boot-2016.11.tar.bz2。这将解压缩文件,并将源代码和其他相关文件提取到当前目录下。 解压缩后,可以在提取出的文件中找到u-boot引导加载程序的源代码和相关文件。可以根据需要进行定制和编译,生成适合特定硬件平台的引导加载程序。u-boot支持多种处理器架构和开发板,可以根据需要进行配置。 根据u-boot-2016.11.tar.bz2文件的版本号来看,它是2016年11月发布的版本。这意味着该版本已经存在一段时间,并可能具有稳定性和经过验证的特性。对于需要使用u-boot的开发者和嵌入式系统制造商,这个版本可以作为一个可靠的基础进行开发和定制。 总之,u-boot-2016.11.tar.bz2是u-boot引导加载程序的源代码和相关文件的压缩包。解压缩后,可以通过定制和编译源代码,生成适合特定硬件平台的引导加载程序。这个版本已经存在一段时间,并可能具有可靠的特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值