瞭解S3C2410/S3C2440地址空間的佈局 掌握如何通過匯流排形式訪問擴展的外設,比如記憶體、NOR Flash、網卡等 ...
本章目標: 瞭解S3C2410/S3C2440地址空間的佈局 掌握如何通過匯流排形式訪問擴展的外設,比如記憶體、NOR Flash、網卡等 ···································································································· 匯流排的使用方法是嵌入式低層開發的基礎,瞭解它之後,再根據外設的具體特性,就可以驅動外設了。 6.1 使用存儲控制器訪問外設的原理 6.1.1 S3C2410/S3C2440的地址空間 S3C2410/S3C2440的“存儲控制器”提供了訪問外部設備所需要的信息,它有如下特性: ① 支持小位元組序、大位元組序(通過軟體選擇); ② 每個BANK的地址空間為128MB,總共1GB(8 BANKs); ③ 可編程式控制制的匯流排位寬(8/16/32-bit),不過BANK0只能選擇兩種位寬(16/32-bit); ④ 總共8個BANK,BANK0~BANK5可以支持外接ROM、SRAM等,BANK6~BANK7除了可以支持 ROM、SRAM外,還支持SDRAM等; ⑤ BANK0~BANK6共7個BANK的起始地址是固定的; ⑥ BANK7的起始地址可編程選擇; ⑦ BANK6、BANK7的地址空間大小是可編程式控制制的; ⑧ 每個的訪問周期均可編程式控制制; ⑨ 可以通過外部的“wait”信號延長匯流排的訪問周期; ⑩ 在外接SDRAM時,支持自刷新(self-refresh)和省電模式(power down mode)。 S3C2410/S3C2440對外引出的27根地址線ADDR0~ADDR26的訪問範圍只有128MB,CPU對外 還引出了8根片選信號nGCS0~nGCS7,對應於BANK0~BANK7,當訪問BANKx的地址空間時, nGCSx引腳輸出低電平用來選中外接的設備。這8個BANK的地址空間如下圖6.1所示: S3C2410/S3C2440作為32位的CPU,可以使用的地址範圍理論上達到4GB。除去上述用於連接外設 的1GB地址空間外,還有一部分是CPU內部寄存器的地址,剩下的地址空間沒有使用。 S3C2410/S3C2440的寄存器地址範圍都處於0x480 0000~0x5ff ffff,各功能部件的寄存器大體相同, 如下表所示: 6.1.2 存儲控制器與外設的關係 本書所用開發板使用了存儲控制器的BANK0~BANK6,分別外接瞭如下設備: NOR Flash、IDE介面、10M網卡CS8900A、100M網卡DM9000、擴展串口晶元16C2550、 SDRAM,連線方式如下圖6.2所示。 外設的訪問地址 = 地址線確定的地址 + BANK的起始地址。 比如:擴展串口。 (1)它使用nGCS5,起始地址為0x2800 0000。 (2)nCSA=ADDR24||nGCS5,nCSB=!ADDR24||nGCS5。當ADDR24和nGCS5均為低電平 時選中擴展串口A;當ADDR24為高電平、nGCS5為低電平時,選中擴展串口B。 (3)CPU的ADDR0~ADDR2連接到擴展串口的A0~A2,所以訪問空間為8位元組。 綜上所述,擴展串口A的訪問空間為:0x2800 0000~0x2800 0007;擴展串口B的 訪問空間為:0x2900 0000~0x2900 0007(bit24為1)。 圖4.2: BANK0~BANK5的連接方式都是類似的,BANK6連接SDRAM時複雜一點,CPU提供了一 組用於SDRAM的信號。 ① SDRAM時鐘有效信號SCKE; ② SDRAM時鐘信號SCLK0/SCLK1; ③ 數據掩碼信號DQM0/DQM1/DQM2/DQM3; ④ SDRAM片選信號nSCS0(它與nGCS6是同一引腳的兩個功能); ⑤ SDRAM行地址選通脈衝信號nSRAS; ⑥ SDRAM列地址選通脈衝信號nSCAS; ⑦ 寫允許信號nWE(它不是專用於SDRAM的)。 SDRAM的內部是一個存儲陣列,如同表格一樣,將數據填進去。 SDRAM的定址基本原理:先指定一個行,在指定一個列,就可以準確地找到所需要的單元格。 這個單元格被稱為存儲單元。這個表格(存儲陣列)就是邏輯Bank(簡稱L-Bank),SDRAM一般含有 4個L-BANK。 SDRAM的邏輯結構如圖6.3所示。 可以想象,對SDRAM的訪問可以分為如下4個步驟: (1)CPU發出的片選信號nSCS0有效,它選中SDRAM晶元; (2)SDRAM中有4個L-Bank,需要兩根地址信號來選中其中一個,從圖6.2可知使用ADDR24、 ADDR25作為L-Bank的選擇信號; (3)對被選中的晶元進行統一行、列(存儲單元)定址; 根據SDRAM晶元的列地址線數目設置CPU的相關寄存器後,CPU就會從32位地址中自動分出 L-Bank選擇信號、行地址信號、列地址信號,然後先後發出行地址信號、列地址信號。L-Bank選 擇信號在發出行地址信號的同時發出,並維持到列地址信號結束。 在圖6.2中,行地址、列地址公用地址線ADDR2~ADDR14(BANK6位寬為32,ADDR0/1沒有使 用),使用nSRAS、nSCAS兩個信號來區分它們。比如本開發板中,使用兩根地址線ADDR24、 ADDR25作為L-Bank的選擇信號;SDRAM晶元K4S561632的行地址數為13,列地址數為9,所以 當nSRAS信號有效時,ADDR2~ADDR14上發出的是行地址信號,它對應32位地址空間的bit[23:11]; 當nSCAS信號有效時,ADDR2~ADDR10上發出的是列地址信號,它對應32位地址空間的bit[10:2]。 由於圖6.2中BANK6以32位的寬度連接SDRAM,ADDR0、ADDR1恆為0,不參與解碼。 (4)找到存儲單元後,被選中的晶元就要進行統一的數據傳輸了。 開發板中使用兩片16位的SDRAM晶元並聯組成32位的位寬,與CPU的32根數據線(DATA0~DATA31)相連。 BANK6的起始地址為0x3000 0000,所以SDRAM的訪問地址為0x3000 0000~0x33ff ffff,共64MB。 對圖6.2中連接的外設,它們的訪問地址(物理地址)如表6.2所示。 6.1.3 存儲控制器的寄存器使用方法 存儲控制器共有13個寄存器,BANK0~BANK5只需要設置BWSCON和BANKCONx(x為0~5)兩個 寄存器:BANK6和BANK7外接SDRAM時,除BWSCON和BANKCONx(x為6、7)外,還要設置REFRESH、 BANKSIZE、MRSRB6、MRSRB7等4個寄存器。下麵分類說明: 1.位寬和等待控制寄存器BWSCON 每4位控制一個BANK,最高4位對應BANK7、接下來4位對應BANK6,以此類推。 (1)STx:啟動/禁止SDRAM的數據掩碼引腳,對於SDRAM, 此位為0;對於SRAM,此位為1; (2)WSx:是否使用存儲器的WAIT信號,通常設為0;
(3)DWx:使用兩位來設置相應BANK的位寬: 0b00:8位,0b01:16位,0b10:32位,0b11:保留; BANK0比較特殊,只支持16和32位兩種位寬,它沒有ST0和WS0,DW0([2:1])只讀——由硬體跳線決定: 0b01:16位,0b10:32位; 對於本開發板,沒有使用BANK7,根據表6.1可以確定BWSCON的值為:0x2201 1110。 2.BANK控制寄存器BANKCONx(x為0~5) 這幾個寄存器用來控制BANK0~BANK5外接設備的訪問時序,使用預設的0x0700即可滿足 本開發板所接各外設的要求。 3.BANK控制寄存器BANKCONx(x為6~7)
在8個BANK中,只有BANK6和BANK7可以外接SRAM或SDRAM,所以BANKCON6~ BANKCON7與BANKCON0~BANKCON5有點不同。 (1)MT([16:15]):用於設置本BANK外接的是ROM/SRAM還是SDRAM。 當MT = 0b00:時,接SRAM,此寄存器與BANKCON0~BANKOCN5類似; 當MT = 0b11:時,接SDRAM,此寄存器其他值如下設置。 (2)Trcd([3:2]):RAS to CAS delay,設為推薦值0b01。 (3)SCAN([1:0]):SDRAM的列地址位數,對於本開發板使用的SDRAM K4S561632, 列地址位數為9,所以SCAN = 0b01。如果使用其他型號的SDRAM,需要查看數據手冊來 決定SCAN的取值。0b00:8位;0b01:9位;0b10:10位。 綜上所述,本開發板中BANKCON6、7均設為0x0001 8005。 4.刷新控制寄存器REFRESH:設為0x008c 0000 + R_CNT
(1)REFEN([23]):0 = 禁止SDRAM的刷新功能,1 = 開啟SDRAM的刷新功能。 (2)TREFMD([22]):SDRAM的刷新模式,0 = CBR/Auto Refresh,1 = Self Refresh(一般在系統休眠時使用)。 (3)Trp([21:20]):設為0即可。 (4)Tsrc([19:18]):設為預設值0b11即可。 (5)Refresh Counter([10:0]):即上述的R_CNT, R_CNT = 2^11 + 1 - SDRAM時鐘頻率(MHz) * SDRAM刷新周期(us); 其中SDRAM時鐘頻率就是HCLK,SDRAM的刷新周期在SDRAM數據手冊上有標明, 在本開發板所使用的SDRAM 數據手冊上,可以看見“ 64ms refresh period(8K Cycle)”。所以, 刷新周期 = 64ms/8192 = 7.8125us。 在未使用PLl時,SDRAM時鐘頻率等於晶振頻率12MHz。 現在可以計算:R_CNT = 2^11 + 1 - 12*7.8125 = 1955。 所以,在未使用PLL時,REFRESH = 0x008c 0000 + 195 = 0x008C 07A3。 5.BANKSIZE寄存器BANKSIZE
(1)BURST_EN([7])。 0 = ARM核禁止突發傳輸,1 = ARM核支持突發傳輸。 (2)SCKE_EN([5])。 0 = 不使用SCKE信號令SDRAM進入省電模式,1 = 使用SCKEN信號令SDRAM進入省電模式。 (3)SCLK_EN([4])。 0 = 時刻發出SCLK信號,1 = 僅在訪問SDRAM期間發出SCLK信號(推薦)。 (4)BK76MAP([2:0]):設置BANK6/7的大小。 BANK6/7對應的地址空間與BANK0~5不同: BANK0~5的地址空間大小都是固定的128MB,地址範圍是(x * 128M)到(x+1)*128M -1,x表示0~5。 BANK6/7的大小是可變的,以保持這兩個空間的地址連續,即BANK7的起始地址會隨著 它們的大小變化。 BK76MAP的取值意義如下: 0b010 = 128MB/128MB,0b001 = 64MB/64MB,0b000 = 32M/M, 0b111 = 16M/16M,0b110 = 8M/8M,0b101 = 4M/4M,0b100 = 2M/2M 本開發板BANK6外接64MB的SDRAM,令[2:0] = 0b001,表示BANK6/7的容量都是64MB, 雖然BANK7沒使用。 綜上所述,開發板的BANKSIZE寄存器的值可算得0xB1。 6.SDRAM模式設置寄存器MRSRBx(x為6~7)
能修改的只有位CL([6:4]),這是SDRAM時序的一個時間參數: [work] 0b000 = 1 clock,0b010 = 2 clocks,0b011 = 3 clocks SDRAM K4S561632不支持CL = 1的情況,所以此位取值0b010(CL = 2)或0b011(CL = 3)。 本開發板取最保守值0b011,所以MRSRB6/7的值為0x30。 6.2 存儲控制器操作實例:使用SDRAM 6.2.1 代碼詳解及程式的複製、跳轉過程 從NAND Flash啟動CPU時,CPU會通過內部的硬體將NAND Flash開始的4KB數據復 制到稱為“Steppingstone”的4KB的內部RAM中(起始地址為0),然後跳到地址0開始執行。 本實例先使用彙編語言設置好存儲控制器,使外接的SDRAM可用;然後把程式從 Steppingstone複製到SDRAM處;最後跳到SDRAM中執行。 源代碼在/work/hardware/sdram目錄中,包含兩個文件head.S和leds.c。其中leds.c和第5 章中的leds的代碼完全一樣,也是讓3個led從0~7輪流計數。 重點在head.S,它的作用是設置SDRAM,將程式複製到SDRAM,然後跳到SDRAM 繼續執行。head.S的代碼如下:
1 @**************************************** 2 @ File:head.S 3 @ 功能:設置SDRAM,將程式複製到SDRAM,然後跳到SDRAM繼續執行 4 @**************************************** 5 6 .equ MEM_CTL_BASE, 0x48000000 7 .equ SDRAM_BASE, 0x30000000 8 9 .text 10 .global _start 11 _start: 12 bl disable_watch_dog @關閉WATCHDOG 13 bl memsetup @設置存儲控制器 14 bl copy_steppingston_to_sdram @複製代碼到SDRAM中 15 ldr pc, =on_sdram @跳到SDRAM中繼續執行 16 on_sdram: 17 ldr sp, =0x34000000 @設置棧 18 bl main 19 halt_loop: 20 b halt_loop 21 22 disable_watch_dog: 23 @往WATCHDOG寄存器寫0即可 24 mov r1, #0x53000000 25 mov r2, #0x0 26 str r2, [r1] 27 mov pc, lr @返回 28 29 copy_steppingstone_to_sdram: 30 @將Steppingstone的4KB數據全部複製到SDRAM中去 31 @Steppingstone起始地址為0x0000 0000,SDRAM中起始地址為0x3000 0000 32 33 mov r1, #0 34 ldr r2, =SDRAM_BASE 35 mov r3, #4*1024 36 1: 37 ldr r4, [r1], #4 @從Steppingstone(0x0000 0000)讀取4位元組的數據,並讓源地址加4 38 str r4, [r2], #4 @將此4位元組數據複製到SDRAM中,並讓目的地址加4 39 cmp r1, r3 @判斷是否完成:源地址是否等於Steppingstone的末地址? 40 bne 1b @若沒有複製完,繼續 41 mov pc, lr @返回 42 43 memsetup: 44 @設置存儲控制器以便使用SDRAM等外設 45 46 mov r1, #MEM_CTL_BASE @存儲控制器的13個寄存器的開始地址 47 adr1 r2, mem_cfg_val @這13個值的起始存儲地址 48 add r3, r1, #52 @13*4 = 52 49 1: 50 ldr r4, [r2], #4 @讀取“待設置值”,並讓r2加4 51 str r4, [r1], #4 @將此值寫入寄存器,並讓r1加4 52 cmp r1, r3 @判斷是否設置完所有13個寄存器 53 bne 1b @若沒有寫完,繼續 54 mov pc, lr @返回 55 56 57 .align 4 58 mem_cfg_val: 59 @存儲控制器13個寄存器的設置值 60 .long 0x22011110 @BWSCON 61 .long 0x00000700 @BANKCON0 62 .long 0x00000700 @BANKCON1 63 .long 0x00000700 @BANKCON2 64 .long 0x00000700 @BANKCON3 65 .long 0x00000700 @BANKCON4 66 .long 0x00000700 @BANKCON5 67 .long 0x00018005 @BANKCON6 68 .long 0x00018005 @BANKCON7 69 .long 0x008c07a3 @REFRESH 70 .long 0x000000b1 @BANKSIZE 71 .long 0x00000030 @MRSRB6 72 .long 0x00000030 @MRSRB7head.S 程式是如何通過第15行的“ ldr pc, =on_sdram”指令來完成的? 程式標號“on_sdram”這個地址值在連接程式時被確定為0x3000 0010(這個是SDRAM的 地址),執行“ldr pc, =on_sdram”後,程式一下子就跳到SDRAM中去了。 “on_sdram”這個地址值為什麼等於0x3000 0010? Makefile中連接程式的命令為“arm-linux-ld -Ttext 0x30000000 head.o sdram.o -o sdram_elf”,意思就是代碼段的起始地址為0x3000 0000,即程式的第一條指令(第12行)的 連接地址為0x3000 0000,第二條指令(第13行)的連接地址為0x3000 0004,...,第5條指 令(第17行)的連接地址為0x3000 0010,其程式標號“on_sdram”的值就是0x3000 0010。 雖然第12~14行指令的連接地址都在SDRAM中,但是由於他們都是位置無關的相對 跳轉指令,所以可以在Steppingstone里執行。 Makefile如下(註意第4行,“-Ttext 0x30000000”指定了代碼段的起始地址):
1 sdram.bin : head.S leds.c 2 arm-linux-gcc -c -o head.o head.S 3 arm-linux-gcc -c -o leds.o leds.c 4 arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf 5 arm-linux-objcopy -O binary -S sdram_elf sdram.bin 6 arm-linux-objdump -D -m arm sdram_elf > sdram.dis 7 clean: 8 rm -f sdram.dis sdram.bin sdram_elf *.oMakefile 為了更形象地瞭解本程式,下麵用圖6.4來演示程式的複製、跳轉過程。 6.2.2 實例測試 在sdram目錄中執行make指令生成可執行文件sdram.bin後,下載到板子上運行。可以 發現與leds程式相比,LED閃爍得更慢,原因是外部SDRAM的性能比內部SRAM差一些。 把程式從性能更好的內部SRAM移到外部SDRAM中去,是否多此一舉呢?內部SRAM 只有4KB大小,如果程式大於4KB,那麼就不能指望完全利用內部SRAM來運行了,得想 辦法把存儲在NAND Flash中的代碼複製到SDRAM中去。對於NAND Flash中的前4KB, 晶元自動把它複製到內部SRAM中,可以很輕鬆地再把它複製到SDRAM中(實驗代碼中的 函數copy_steppingston_to_sdram就有此功能),要複製4KB後面的代碼需要使用NAND Flash 控制器來讀取NAND Flash,這就是第8章的內容。 附:代碼: 鏈接: https://pan.baidu.com/s/1kV24a9L 密碼: tfab