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

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》是從官網下的無修改代碼


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章