天天看點

zz vivi開發筆記(九):SDRAM實驗

文章說明:calmarrow(lqm)參考thisway.diy的《S3C2410完全開發》

文章引自:http://piaoxiang.cublog.cn

    現在基本熟悉了GNU as、ld、objdump、objcopy。可以進行後續的基本實驗了。今天把s3c2410的memory controller看了,結合《s3c2410完全開發》實驗五,實作了一個sdram的簡單實驗。源代碼如下,下面重點分析s3c2410複位後的記憶體映射,及其應用。

一、基本配置

    EDUKIT-III采用核心子闆加擴充闆的設計方式,我學習ARM9,是以采用s3c2410的核心子闆。核心子闆資源如下:

    MCU      : S3C2410A

    SDRAM    : 兩片HY57V561620CT-H

    NOR FLASH: AM29LV160DB-90EC

    擴充闆資源:

    NAND FLASH: K9F5608UOC

二、nand flash boot分析

    S3C2410支援從nor/nand flash、eeprom等rom類型的媒體啟動。現在我想做的是從外部nand flash啟動,首先看datasheet第一部分:

NAND Flash Boot Loader · Supports booting from NAND flash memory · 4KB internal buffer for booting · Supports storage memory for NAND flash memory after booting

    可以明确,首先,s3c2410支援從nand flash存儲媒體啟動,其次,在硬體上,s3c2410除了提供相應的邏輯外,還提供了一個4K的sram作為buffer用于nand啟動。最後,s3c2410支援從nand flash啟動之後的記憶體配置設定形式(也就是說,從nand flash啟動之後和從nor flash啟動之後的記憶體配置設定形式是不同的。s3c2410支援這兩種形式,可以說是相對于其他的MCU不同的地方。)

    然後看datasheet的第六部分:nand flash controller。overview中首先講述了用nand flash代替nor flash作為啟動媒體的原因(成本低)。

    S3C2410X boot code can be executed on an external NAND flash memory. In order to support NAND flash boot loader, the S3C2410X is equipped with an internal SRAM buffer called ‘Steppingstone’. When booting, the first 4 KBytes of the NAND flash memory will be loaded into Steppingstone and the boot code loaded into Steppingstone will be executed.     Generally, the boot code will copy NAND flash content to SDRAM. Using hardware ECC, the NAND flash data validity will be checked. Upon the completion of the copy, the main program will be executed on the SDRAM.

    可以很明顯的看出,s3c2410x啟動代碼從外部nand flash啟動的流程:上電複位後,s3c2410自動讀取nand flash的前4KBytes的資料到内部sram buffer中,這個硬體的sram buffer被稱為“Steppingstone”。然後執行下載下傳到steppingstone的代碼,這部分代碼完成将nand flash的内容複制到sdram中,在複制時,利用硬體的ECC驗證資料有效性。完成複制後,主程式就開始從sdram執行。

    過程應該是很清晰。但是首先懷疑的是,s3c2410如何實作自動讀取nand flash的前4KBytes資料到内部sram buffer當中。網上為什麼沒人就這點産生疑問,并深入分析呢?我分析可能有兩種方法:一是像at91rm9200一樣,内部內建一個小的rom,固化代碼,這部分代碼的作用就是完成自動讀取功能;二是完全用硬體實作。仔細看了框圖,發現s3c2410隻有internal sram buffer,并沒有rom,是以最大可能就是硬體實作。看一下硬體框圖figure6-1,可以發現hardware ECC編解碼器,可以看到internal buffer(4KB),另外注意的一個地方是,存在着control state machine和buffer control,而且之間有粗體線連結。也就是說明了用一個控制狀态機實作了自動讀取4KB資料的過程,完全的硬體實作。如下圖所示:

zz vivi開發筆記(九):SDRAM實驗

明确了這個問題之後,對從硬體上電到nand flash啟動就比較清晰了。而且,也就了解為什麼vivi的stage1的head.S必須要小于4KB,因為internal sram buffer隻有4KB。如果要完成一個比較複雜的bootloader,那也應該盡量簡化stage1,完成基本的初始化之後,把剩餘的工作量都放到将nand flash的代碼搬移到sdram之後進行。

三 memory controller分析

    看datasheet第五部分。s3c2410比較特殊,支援1G的記憶體空間,分為8個bank,每個bank128MBytes,128MB×8=1GB。但是在這8個bank中,又有所不同,并且nand flash不對應任何bank,它是通過一組寄存器來通路的,可看上面框圖的register bank。

— Total 8 memory banks    Six memory banks for ROM, SRAM, etc.    Remaining two memory banks for ROM, SRAM, SDRAM, etc . — Seven fixed memory bank start address — One flexible memory bank start address and programmable bank size

    可以推斷出,sdram應該在bank6,起始位址固定為128M*6=0x30000000,在此之後,就要根據sdram的大小和位寬來決定了,而且有個注意的地方是,bank7必須和bank6一樣大小。參考figure5-1和table 5-1就非常清晰了。現在EDUKIT-III上用了兩片SDRAM,型号是HY57V561620CT-H,檢視datasheet,它是4banks×4M×16bit=256Mbits=32Mbytes,那麼兩片組合起來就是64MBytes,位寬是32bit,是以bank6的位址範圍是[0x30000000-0x33ffffff],bank7的位址範圍是[0x34000000-0x37ffffff]。檢視s3c2410 table 5-2,可以知道bank選擇位址線為A[25:24]--->BA[1:0]。

    關于sdram,還應該知道重新整理頻率和列寬度。HY57V561620CT-H datasheet中,有:

· Auto refresh and self refresh · 8192 refresh cycles / 64ms · Programmable Burst Length and Burst Type   - 1, 2, 4, 8 or Full page for Sequential Burst   - 1, 2, 4 or 8 for Interleave Burst · Programmable CAS Latency ; 2, 3 Clocks

    是以重新整理頻率為64ms/8192=7.8125us。

    檢視PIN DESCRIPTION,可以看出A0-A12為位址,其中ROW Address為RA[0:12],Column Address為CA[0-8],顯然CAS的位數為9bits。

四、實驗内容分析

    實驗内容很簡單,就是完成基本的初始化之後,把steppingstone的4K資料搬移到sdram中。然後在sdram中執行燈循環點亮程式。結合這個實驗,也可以很清晰的明白,前面幾個基本實驗,從nand flash啟動後,所有代碼隻是搬移到了steppingstone中,也就是實際執行時是在steppingstone中,也就是boot internal sram(4KB)中執行的,是以運作時域和加載時域都是0x00000000,設定的堆棧可以是1024,也可以是4096,但是注意一是最大為4096,二是保證不與可執行代碼發生沖突。在這個程式中,運作時域和加載時域是不相同的。加載時域是0x00000000,但是運作時域是0x30000000。《s3c2410完全開發》對這個地方講解不是太詳細。經過實驗,和王老師的幫助,弄清楚了到底怎麼回事。現在關于運作時域和加載時域的具體分析如下:

    根據nand flash的特點,初始代碼的加載時域為0x00000000,也就是目前PC的值為0x00000000,兩種跳轉指令b(l)等隻能相對尋址,最大範圍是+/-32MBytes,是以如果不改變PC的話,不可能能利用b或者bl跳轉到sdram的空間中。跳轉指令ldr則不受此尋址空間的限制,可以進行絕對尋址。需要了解的一個細節就是,連結後所有的标号都是基于運作位址的,比如運作位址為0x30000000,那麼第一個标号_start位址就是0x30000000,是以可以利用ldr的絕對尋址來完成到sdram的跳轉。下面根據編寫的sdram的反彙編來進行分析:

    首先看在不去除符号資訊的前提下:

sdram: $(OBJS)         $(LD) $(LDFLAGS) $^ -o [email protected]         $(OBJDUMP) -D [email protected] >$@_s         $(OBJCOPY) -O binary -S [email protected] $@

    這裡是反彙編的結果:

Disassembly of section .text:

30000000 <_start>: 30000000:       e3a00453        mov     r0, #1392508928 ; 0x53000000 30000004:       e3a01000        mov     r1, #0  ; 0x0 30000008:       e5801000        str     r1, [r0] 3000000c:       eb00000c        bl      30000044 30000010:       eb000003        bl      30000024 30000014:       e59ff088        ldr     pc, [pc, #88]   ; 300000a4

30000018 : 30000018:       e3a0d30d        mov     sp, #872415232  ; 0x34000000 3000001c:       eb000023        bl      300000b0

30000020 : 30000020:       eafffffe        b       30000020

    可以很明顯的看出,_start為0x30000000,stop為0x30000020。也就是說,經過連結之後,symbol table中的存放位置都是基于運作起始位址0x30000000的。但是需要注意的是,開始運作是PC的值為0x00000000,雖然bl 30000040 是30000040,但是要注意,此處指令為bl,是以隻能相對尋址,而不能夠絕對尋址,也就是說,它隻能跳轉到距離0x30000000為0x40的位置,這點檢視bl的彙編指令說明就比較清晰了。

        ldr pc, =setup_stack setup_stack:         ldr sp, =stack_top bl main

    利用上面的技巧,就可以把PC的值裝載到sdram的空間,因為之前代碼搬移已經完成了,是以,後續的工作都已經工作在sdram的空間中了。

    如果在利用objcopy去除了符号資訊之後,反彙編之後的結果隻能是以0開始的相對位址,也就看不出上面的東西了,是以,要了解還應該是采用上面的分析方法。這點在《s3c2410完全開發》上是沒有詳細說明的。寫到這裡,自己已經比較清晰了。關于其他的分析,《s3c2410完全開發》已經比較詳細了,可以參考。

繼續閱讀