Windows下u-boot-2011.03在Mini2440移植详解(6)

7 篇文章 0 订阅

Nor Flash启动

Nor Flash:SST39VF1601 ---2MB

SDRAM: HY57V561620FTP-H,容量:256Mb(16M×16bit)=32MB,频率:133MHZ,开发板带2片* 32MB=64MB

前记:

关于这一步的移植花费了很大的时间。我们知道,在gdb调试时,是直接load代码到CONFIG_SYS_TEXT_BASE 所对应的SDRAM地址处,CONFIG_SYS_TEXT_BASE 在文件u-boot-2011.03\board\samsung\mini2440\config.mk中定义。假设CONFIG_SYS_TEXT_BASE=0x33000000,那么调试时就将uboot的所有内容加载到0x33000000 SDRAM地址处。运行时设置CPU模式à关中断à设置时钟à调用函数board_init_f (u-boot-2011.03\arch\arm\lib\board.c),在board_init_f计算出uboot要拷贝的地址addr,在start.S(u-boot-2011.03\arch\arm\cpu\arm920t\start.S)文件的relocate_code处将_start(_start=CONFIG_SYS_TEXT_BASE=_TEXT_BASE)地址处的uboot内容拷贝到addr地址处,比如addr=0x33f00000。如下图所示。


其中,__bss_end__,_end都是在u-boot-2011.03\arch\arm\cpu\arm920t\u-boot.lds文件中定义的。

同样,如果把目标代码烧写到Nor flash中,那么从Nor flash启动时,从地址0处运行,同样是设置CPU模式à关中断à设置时钟à调用函数board_init_f,在board_init_f计算出uboot要拷贝的地址。虽然过程应该是这样走的,但是却不能正常运行。因为在board_init_f函数里,调用了一些其他的函数,而这些函数都是在地址0x33000000之后的,是SDRAM的地址。而此时如果去调用这些函数,直接跳转过去是无法运行的,因为此时0x33000000地址处是没有任何代码的(调试时可以是因为调试时是直接load到此处的),也就是现在SDRAM里面是没有任何代码的。那么为什么board_init_f可以调用,这就涉及到了绝对跳转指令和相对跳转指令。可参考http://www.cnblogs.com/myblesh/archive/2012/04/17/2454162.html。虽然board_init_f的编译地址在SDRAM的0x33000000之后,但调用board_init_f (board_init_f函数是在uboot的最前4kB)是在start.S里以相对跳转指令调用的,所以可以成功调用board_init_f,但里面的函数就无法正常运行了。网上有些人说将board_init_f作为第一阶段可以启动,但目前还没有发现怎么让它去运行。因为在board_init_f函数调用了编译地址在SDRAM 0x33000000之后的函数,而且这些函数不是位于uboot的前4kB,而且目前还不知道怎么在C语言里面实现相对跳转。因此在start.S里,在board_init_f之前加入如下代码:

/*copy uboot to CONFIG_SYS_TEXT_BASE address*/
relocate_run_at_stage_1:
	adr r0, _start
	ldr r1, _TEXT_BASE /*if in ram, no copy*/
	cmp r0, r1
	beq call_board_init_f
    
	ldr	r2, _end_ofs /*copy all uboot data, so, use _end_ofs(=_end-_start)*/
	add	r2, r0, r2

copy_from_flash_to_TEXT_BASE:
	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
	cmp	r0, r2			/* until source end address [r2]    */
	blo	copy_from_flash_to_TEXT_BASE
/*copy uboot to CONFIG_SYS_TEXT_BASE address*/

/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
	ldr	r0,=0x00000000
	ldr pc, =board_init_f /*jump ram use command ldr*/

从Nor flash启动时,_start=0,_TEXT_BASE=0x33000000不等就开始copy,copy的大小是_end_ofs,即uboot所有内容大小。这一步copy相当于调试时load步骤。Copy完之后,设置堆栈,以绝对跳转指令跳转到board_init_f处执行,此时0x33000000地址处就有uboot代码存在了。board_init_f此时作为第二阶段代码运行。

当调试时_start和_TEXT_BASE都等于0x33000000,所以不运行此代码,直接跳转到board_init_f。

大致的过程如下图所示。


但是,我们会发现在relocate_code处又会将代码copy一遍,即第二步copy。目前是这样实现的,需要两步copy,有点多余。如果在board_init_f函数中,将addr的地址和_TEXT_BASE设置成一样,应该就不需要第二步copy了。当然这需要做一些修改。

需要说明一点的是,uboot不仅可以在SDRAM的CONFIG_SYS_TEXT_BASE地址处运行,同样也可以在SDRAM的其它地址处运行,这应该归功于start.S的下面部分代码:

#ifndef CONFIG_PRELOADER
	/*
	 * fix .rel.dyn relocations
	 */
	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
	sub	r9, r6, r0		/* r9 <- relocation offset */
	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
	add	r10, r10, r0		/* r10 <- sym table in FLASH */
	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
fixloop:
	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
	ldr	r1, [r2, #4]
	and	r7, r1, #0xff
	cmp	r7, #23			/* relative fixup? */
	beq	fixrel
	cmp	r7, #2			/* absolute fixup? */
	beq	fixabs
	/* ignore unknown type of fixup */
	b	fixnext
fixabs:
	/* absolute fix: set location to (offset) symbol value */
	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
	add	r1, r10, r1		/* r1 <- address of symbol in table */
	ldr	r1, [r1, #4]		/* r1 <- symbol value */
	add	r1, r1, r9		/* r1 <- relocated sym addr */
	b	fixnext
fixrel:
	/* relative fix: increase location by offset */
	ldr	r1, [r0]
	add	r1, r1, r9
fixnext:
	str	r1, [r0]
	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
	cmp	r2, r3
	blo	fixloop
#endif

这段代码实现的具体意义目前不清楚,应该是将每个函数所对应的RAM地址进行重定向,以便在SDRAM的哪个基地址处都可以正确调用基于CONFIG_SYS_TEXT_BASE地址编译出来的函数。

 

Nor Flash 启动

参考网址:

http://blog.csdn.net/atower_boy/article/details/6290817

http://www.cnblogs.com/heaad/archive/2010/07/17/1779829.html

关于怎么去调用函数board_init_r,可以参考:http://blog.chinaunix.net/uid-29284763-id-3969667.html

 

修改相关文件:

1.      u-boot-2011.03\board\samsung\mini2440\lowlevel_init.S

2.      u-boot-2011.03\board\samsung\mini2440\Makefile

3.      u-boot-2011.03\arch\arm\cpu\arm920t\u-boot.lds

4.      u-boot-2011.03\board\samsung\mini2440\config.mk

5.      u-boot-2011.03\arch\arm\lib\board.c

6.      u-boot-2011.03\arch\arm\cpu\arm920t\start.S

7.      u-boot-2011.03\board\samsung\mini2440\config.mk

 

前面的所有调试,对于uboot来说大部分都是第2阶段的代码。如果将uboot烧写到Nor flash内,第1阶段的代码也必须实现。我们知道,第1阶段的代码就是从Norflash 0地址处运行,将uboot代码copy到SDRAM中,然后转到SDRAM,后面的步骤就和之前调试时的一样了。我们还知道,在之前的仿真调试过程中,Eclipse里面加了些初始化代码,这些初始化代码做了第1阶段的一些功能,像初始化SDRAM等等,数据cache或指令cache的关闭。因此,要想在Nor flash里运行uboot,还需要实现一些功能,

编译生成的代码烧写到Nor flash的0地址处。开机,运行,ARM从0地址处开始运行,0地址处的前4kB一定要是与地址无关的代码。

 

在我们根据上面的网址修改后,编译会发现:

board/samsung/mini2440/libmini2440.o:In function `lowlevel_init':

d:\Program\Eclipse\u-boot-2011.03\board\samsung\mini2440/lowlevel_init.S:145:multiple definition of `lowlevel_init'

board/samsung/mini2440/lowlevel_init.o:d:\Program\Eclipse\u-boot-2011.03\board\samsung\mini2440/lowlevel_init.S:145:first defined here

Make:*** [u-boot] Error 1

错误报的是说lowlevel_init有多处定义,其实我们只在u-boot.lds里面加上了lowlevel_init.o,怎么就多处定义了。上网查找,根据网址http://blog.csdn.net/lihancheng/article/details/4063408

http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=3749526提供的信息,对makefile做了如下修改:

针对board\samsung\mini2440\Makefile的修改如下表格:

修改后修改前

LIB  = $(obj)lib$(BOARD).o

 

COBJS    := mini2440.o flash.o

SOBJS    := lowlevel_init.o

 

SRCS      := $(SOBJS:.o=.S) $(COBJS:.o=.c)

OBJS      := $(addprefix $(obj),$(COBJS))

SOBJS    := $(addprefix $(obj),$(SOBJS))

 

$(LIB):    $(obj).depend $(OBJS) $(SOBJS)

       $(callcmd_link_o_target, $(OBJS))

LIB  = $(obj)lib$(BOARD).o

 

COBJS    := mini2440.o flash.o

SOBJS    := lowlevel_init.o

 

SRCS      := $(SOBJS:.o=.S) $(COBJS:.o=.c)

OBJS      := $(addprefix $(obj),$(COBJS))

SOBJS    := $(addprefix $(obj),$(SOBJS))

 

$(LIB):    $(obj).depend $(OBJS) $(SOBJS)

       $(call cmd_link_o_target, $(OBJS) $(SOBJS))

在这个文件夹下只产生lowlevel_init.o文件,不将lowlevel_init.o链接到libmini2440.o文件里。由于u-boot.lds里面包含了lowlevel_init.o,猜测上面只所以报lowlevel_init多处定义,可能是因为libmini2440.o和lowlevel_init.o里各有一份lowlevel_init。没有具体看makefile的细节。我们在链接前4kB的代码时,把该链接到前4kB的代码必须链接到前4kB,多余的空间再放些其他的代码。

 

其它的文件修改可以download下来与之前的比较。

编译,然后下载到Nor Flash里就可以运行了。关于下载到Nor Flash,可参考:http://blog.chinaunix.net/uid-25100840-id-349517.html

本文的J-Flash其中CPU设置如下图:、



本部分代码下载地址:360云盘http://yunpan.360.cn/,在《Uboot相关代码》文件夹里的《u-boot-2011.03_NorFlash启动.zip》文件。

《u-boot-2011.03源码无修改.tar.bz2》是从官网下的无修改代码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值