uboot的lowlevel_init.s解析

uboot版本爲201103rc1.

看了一下lowlevel_init.s裏面的代碼,發現最難懂的地方當屬這裏了:

ldr     r0, =SMRDATA
ldr	r1, _TEXT_BASE
sub	r0, r0, r1
ldr	r1, =BWSCON	/* Bus Width Status Controller */
add     r2, r0, #13*4

 

 

第一條語句是獲取SMRDATA的地址,SMRDATA的定義在此文件的末尾。第二條語句是獲取_TEXT_BASE的值,在start.s中,這個值被定義爲CONFIG_SYS_TEXT_BASE。而CONFIG_SYS_TEXT_BASE在目標板目錄的config.mk中定義,然後在根目錄的config.mk中的以下語句中被包含進來。

LDFLAGS_u-boot += -Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS)
ifneq ($(CONFIG_SYS_TEXT_BASE),)
LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)
endif

 

然後查看u-boot.lds文件,就知道整個u-boot最後都被編譯到CONFIG_SYS_TEXT_BASE這個地址之後,包括代碼段、數據段等內容。所以SMRDATA也必定是在這個地址之後。而第三句話就是計算SMRDATA相對於CONFIG_SYS_TEXT_BASE的偏移量。接下來的兩句就是把控制寄存器的地址賦給r1,將SMRDATA的結束地址賦給r2。

計算好地址之後,後面的代碼是一個循環,按照預先的設計設定每個BANK的屬性。

 

剛開始看這個代碼的時候不理解爲什麼要計算偏移量,後來在網上查了一些資料才逐漸明白。這個涉及到芯片的啓動過程。現以上面的SDRDATA爲例進行說明。

首先使用objdump –d lowlevel_init.o進行反彙編,查看這一部分代碼被預編譯爲以下內容。

lowlevel_init.o:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_TEXT_BASE>:
   0:	33f80000 	.word	0x33f80000

00000004 :
   4:	e59f0020 	ldr	r0, [pc, #32]	; 2c 
   8:	e51f1010 	ldr	r1, [pc, #-16]	; 0 <_TEXT_BASE>
   c:	e0400001 	sub	r0, r0, r1
  10:	e3a01312 	mov	r1, #1207959552	; 0x48000000
  14:	e2802034 	add	r2, r0, #52	; 0x34
  18:	e4903004 	ldr	r3, [r0], #4
  1c:	e4813004 	str	r3, [r1], #4
  20:	e1520000 	cmp	r2, r0
  24:	1afffffb 	bne	18 
  28:	e1a0f00e 	mov	pc, lr
  2c:	00000030 	.word	0x00000030

00000030 :
  30:	2211d120 	.word	0x2211d120
  34:	00000700 	.word	0x00000700
  38:	00000700 	.word	0x00000700
  3c:	00000700 	.word	0x00000700
  40:	00001f4c 	.word	0x00001f4c
  44:	00000700 	.word	0x00000700
  48:	00000700 	.word	0x00000700
  4c:	00018005 	.word	0x00018005
  50:	00018005 	.word	0x00018005
  54:	008e0459 	.word	0x008e0459
  58:	00000032 	.word	0x00000032
  5c:	00000030 	.word	0x00000030
  60:	00000030 	.word	0x00000030

 

可知SMRDATA的地址就是當前PC值偏移32,在實際運行的時候就是lowlevel的入口地址加32。

再在根目錄下使用objdump –d u-boot就可以查到最終的生成文件中lowlevel_init的入口地址了,由於在鏈接的時候指定了代碼段的首地址爲0x33f80000,所以lowlevel的入口地址是代碼段的首址加上一個偏移量,這樣就可以算出SMRDATA的地址就是0x33f80000+lowlevel_init入口的偏移量+SMRDATA本身的段內偏移量。查看uboot根目錄底下的System.map文件可知lowlevel_init的地址是0x33f80bf0,SMRDATA的地址是0x33f80c1c。

 

弄清楚了這些地址之後再回到開頭的問題,arm9在上電的時候如果硬件跳線選擇的是從NAND FLASH啓動的話,會將NAND FLASH開頭的4K內容拷貝到一個叫“stepping stone”的空間中,其首地址是0x0。假設執行到了lowlevel_init裏面,還是按照原來的地址去尋找SMRDATA的話,那肯定就找不到了,因爲這個時候的代碼是運行在0x0~0x00001000這個地址內的,應該去找0x00000c1c這個地址纔是正確的。

發佈了25 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章