大,爲何要在規定的小空間裏和本身過不去呢!開發板上也同樣,以前一直在一個4K大的Stepping stone裏打轉轉,
惋惜了那64MB的內存了。那麼,今天就到擁有更廣闊的天地裏折騰一番吧。
s3c2440對外引出了27根地址線ADDR0~ADDR26,最多能尋址2的27次方,也就是128MB,但實際上s3c2440可以
尋址1G的地址空間,這是由於它還有8根片選信號線nGCS0~nGCS7,每根信號線對應一個128MB地址空間,這個空間被稱做
BANK,因此s3c2440共有8個BANK -- BANK0~BANK7,當訪問某個BANK時,其對應的nGCS信號引腳電平拉低,這和單
片機上的擴展IO的操做類同。s3c2440是32位的芯片,理論上支持2的32次方,即4GB的地址空間,除去上面8個BANK用掉的
1GB地址空間外,特殊功能寄存器佔用了0x48000000~0x5b00001c這段地址空間,其它的地址空間沒有被使用。
BANK0~BANK5能夠鏈接ROM和SRAM類型的存儲器,BANK6~BANK7能夠鏈接ROM、SRAM、SDRAM類型的存儲器,
最大支持256MB,mini2440將兩片32MB,16bits位寬的SDRAM鏈接在了BANK6和BANK7上,並聯構成64MB、32位寬的
內存。
在處理SDRAM內部的數據時須要先指定行,再指定列,便可訪問到須要的數據,由行和列構成的矩陣稱爲存儲陣列,
你們通常會把它叫做"L-BANK",但SDRAM裏面不會只有一個存儲陣列,這是由於若是隻作一個存儲陣列會形成嚴重的尋址
衝突並大幅度下降內存效率。因此通常人們都將內存分爲4個存儲陣列(這也是SDRAM規範中的最高L-BANK數量),訪問時
每次只能訪問一個,具體訪問那個L-BANK能夠經過內存的兩個外接引腳BA0和BA1來決定,mini2440將addr24鏈接BA0、
addr25鏈接BA1,經過地址線24和地址線25來選擇存儲單元的4個L-BANK。
SDRAM只有13根地址線A0~A12,只能尋址8MB(2的13次方)的內存空間,因爲每一個內存內部劃分紅四個L-BANK,因此
經過addr24和addr25的配合,就能夠尋址一個內存芯片的所有空間。開發板上一共有兩片並聯的32MB的SDRAM,每發送一次
地址信號,兩片芯片均可以同時接收到,以後其中一片返回低16bits的數據,另外一片返回高16bits的數據。下面是內存芯片和
cpu的引腳的鏈接表:linux
--------------------------------------------------------------------------------------------------------------------cpu引腳 內存芯片引腳 描述--------------------------------------------------------------------------------------------------------------------A2~A14 A0~A12 地址線--------------------------------------------------------------------------------------------------------------------D0~D31 DQ0~DQ31 數據線,其中一片的DQ0~DQ15鏈接D0~D15,另外一片的DQ0~DQ15鏈接D16~D31--------------------------------------------------------------------------------------------------------------------A24,A25 BA0,BA1 L-BANK選擇信號--------------------------------------------------------------------------------------------------------------------DQM0~DQM3 LDQM,UDQM 高低字節數據掩碼信號--------------------------------------------------------------------------------------------------------------------SCKE SCKE 輸入時鐘有效信號--------------------------------------------------------------------------------------------------------------------SCLK SCLK 輸入時鐘--------------------------------------------------------------------------------------------------------------------nSCS0 nSCS 片選信號(和nGCS6是同一個引腳,只是功能不一樣)--------------------------------------------------------------------------------------------------------------------nSRAS nSRAS 行地址選通訊號--------------------------------------------------------------------------------------------------------------------nSCAS nSCAS 列地址選通訊號--------------------------------------------------------------------------------------------------------------------nWE nWE 寫入有效信號--------------------------------------------------------------------------------------------------------------------
存儲控制器的寄存器部分這裏略過。
下面是啓動代碼:
ide
@*************************************************************************@ File:head.S@ 功能:關閉看門狗,初始化時鐘,初始化內存,將Stepping stone的數據@複製到SDRAM, 而後跳到內存中繼續運行main函數,循環點亮led燈。@************************************************************************* @看門狗寄存器.equ WTCON, 0x53000000 @看門狗控制寄存器.equ WTDAT, 0x53000004 @看門狗數據寄存器.equ WTCNT, 0x53000008 @看門狗計數寄存器@系統時鐘寄存器.equ LOCKTIME, 0x4c000000 @變頻鎖定時間寄存器.equ MPLLCON, 0x4c000004 @MPLL寄存器.equ CLKDIVN, 0x4c000014 @分頻比寄存器@內存寄存器.equ MEM_CTL_BASE, 0x48000000.equ SDRAM_BASE, 0x30000000 @定義64MB內存開始的地址.equ SDRAM_END, 0x34000000 @定義64MB內存結束的地址.text.global _start_start: bl disable_watch_dog @ 關閉WATCHDOG,不然CPU會不斷重啓 bl init_clock @初始化系統時鐘 bl memsetup @ 設置存儲控制器 bl copy2sdram @ 複製代碼到SDRAM中 ldr pc, =on_sdram @ 跳到SDRAM中繼續執行on_sdram: ldr sp, =SDRAM_END @ 設置堆棧,堆棧由高地址向低地址生長 bl mainhalt_loop: b halt_loopdisable_watch_dog: mov r1, #WTCON mov r2, #0x0 @ 往WATCHDOG寄存器寫0便可 str r2, [r1] mov pc, lr @ 返回init_clock: @ 設置鎖頻時間 ldr r0, =LOCKTIME @取得LOCKTIME寄存器地址 ldr r1, =0x00ffffff @設置鎖定時間 str r1, [r0] @將r1中的數據寫入r0 @設置FCLK,HCLK,PCLK三者之間的比例,原本還須要設置CAMDIVN寄存器, @但這裏設置成1:4:8,因此CAMDIVN使用默認值就能夠了! ldr r0, =CLKDIVN @取得CLKDIVN寄存器地址 mov r1, #0x05 @設定比例 str r1, [r0] @修改CPU總線模式 mrc p15, 0, r1, c1, c0, 0 orr r1, r1, #0xc0000000 mcr p15, 0, r1, c1, c0, 0 @倍頻到400MHz ldr r0, =MPLLCON @MPLL控制寄存器 ldr r1, =0x0005c011 str r1, [r0] mov pc, lr @ 返回copy2sdram: @ 將Steppingstone的4K數據所有複製到SDRAM中去 @ Steppingstone起始地址爲0x00000000,SDRAM中起始地址爲0x30000000 mov r1, #0 ldr r2, =SDRAM_BASE mov r3, #4*1024copyloop: ldr r4, [r1],#4 @ 從Steppingstone讀取4字節的數據,並讓源地址加4 str r4, [r2],#4 @ 將此4字節的數據複製到SDRAM中,並讓目地地址加4 cmp r1, r3 @ 判斷是否完成:源地址等於Steppingstone的未地址? bne copyloop @ 若沒有複製完,繼續 mov pc, lr @ 返回memsetup: @ 設置存儲控制器以便使用SDRAM等外設 mov r1, #MEM_CTL_BASE @ 存儲控制器的13個寄存器的開始地址 adrl r2, mem_cfg_val @ 這13個值的起始存儲地址 add r3, r1, #52 @ 13*4 = 54initmemloop: ldr r4, [r2], #4 @ 讀取設置值,並讓r2加4 str r4, [r1], #4 @ 將此值寫入寄存器,並讓r1加4 cmp r1, r3 @ 判斷是否設置完全部13個寄存器 bne initmemloop @ 若沒有寫成,繼續 mov pc, lr @ 返回@4字節對齊.align 4 mem_cfg_val: @ 存儲控制器13個寄存器的設置值 .long 0x22000000 @ BWSCON .long 0x00000700 @ BANKCON0 .long 0x00000700 @ BANKCON1 .long 0x00000700 @ BANKCON2 .long 0x00000700 @ BANKCON3 .long 0x00000700 @ BANKCON4 .long 0x00000700 @ BANKCON5 .long 0x00018005 @ BANKCON6 .long 0x00018005 @ BANKCON7 .long 0x008E04F5 @ REFRESH .long 0x000000B1 @ BANKSIZE .long 0x00000030 @ MRSRB6 .long 0x00000030 @ MRSRB7@******************************************************************************
C程序仍是使用上次那個leds.c程序,這裏就再也不列出代碼了!
而後是編譯用的Makefile.函數
#******************************************************************************#Makefile#******************************************************************************sdram.bin : head.S leds.c arm-linux-gcc -c -o head.o head.S arm-linux-gcc -c -o leds.o leds.c arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf arm-linux-objcopy -O binary -S sdram_elf sdram.bin arm-linux-objdump -D -m arm sdram_elf > sdram.disclean: rm -f sdram.dis sdram.bin sdram_elf *.o#******************************************************************************
編譯以後獲得sdram.bin,下載到開發板上運行。能夠看到led閃爍的速度比上次慢了不少,oop
這是由於外部的SDRAM的性能比內部的SRAM差不少。但內部的SRAM只有4k,若是程序大於4k,性能
就須要想辦法將存儲在NAND中的代碼複製到SDRAM中去運行。spa
注意:上面的代碼只是把SRAM中的代碼複製到SDRAM中運行,並非將NAND Flash中的code