JZ2440 裸機驅動 第6章 存儲控制器
阿新 • • 發佈:2017-10-22
logs display 裸機 包含 們的 不支持 sel watchdog inux
本章目標:
了解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的代碼如下:
(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
JZ2440 裸機驅動 第6章 存儲控制器