一、sdram的介紹SDRAM(Synchronous Dynamic Random Access Memory),同步動態(tài)隨機存儲器,同步是指 Memory工作需要同步時鐘,內(nèi)部的命令的發(fā)送與數(shù)據(jù)的傳輸都以它為基準;動態(tài)是指存儲陣列需要不斷的刷新來保證數(shù)據(jù)不丟失;隨機是指數(shù)據(jù)不是線性依次存儲,而是自由指定地址進行數(shù)據(jù)讀寫。
二、s3c2410內(nèi)部存儲器
上面的圖是我個人對存儲器的理解。
我們知道,市面上內(nèi)存的類型很多,那一款cpu是如何來識別如此多的RAM呢?這一切都是內(nèi)存控制器來做的,我們就需要對內(nèi)存控制器進行配置。當然內(nèi)存控制器支持的 RAM類型也是有限的。其實cpu在取數(shù)據(jù)的時候,只是執(zhí)行一條指令,例如:ldr r0,[r2];關于數(shù)據(jù)怎么來,cpu并不關心。整個數(shù)據(jù)的讀取和寫入全部由內(nèi)存控制器完成。
三、s3c2410的地址空間
s3c2410的"存儲控制器"提供了訪問外部設備所需的信號,它有如下特性:
A.支持小字節(jié) 、大字節(jié)序(通過軟件選擇)
B.每個BANK的地址空間為128M,總共1GB(8BANKS)
C.可編程控制的總線位寬(8/16/32-bit),不過BANK0只能選擇兩種位寬(16/32-bit)
D.總共8個BANK,BANK0-BANK5可以支持外接ROM,SRAM等,BANK6-BANK7 除可以支持ROM、SRAM外,還支持SDRAM等
E.BANK0-BANK6共7個BANK的起始地址是固定的
F.BANK7的起始地址可編程選擇
G.BANK6、BANK7的地址空間大小是可編程控制的
H.每個BANK的訪問周期均可編程控制
I.可以通過外部的"wait"信號延長總線的訪問周期 <
J.在外接SDRAM時,支持自刷新(self-refresh)和省電模式(power down mode)
S3C2410對外引出的27根地址線ADDR0-ADDR26的訪問范圍只有128MB,那么如何達到上面所說的1GB的訪問空間呢?CPU對外還引出了8根片選信號nGCS0-nGCS7,對應于BANK0-BANK7,當訪問BANKx的地址空間時,nGCSx引腳輸出低電平用來選中外接的設備。這樣,每個nGCSx對應128MB地址空間,8個nGCSx信號總共就對應了1GB的地址空間。8個BANK如下圖所示:
如上圖所示,左邊對應不使用NAND FLASH作為啟動設備,右邊對應使用NAND FLASH作為啟動設備
在fs2410上,BANK0接了NOR FLASH,也就說它既支持從NOR FALSH啟動,也支持從NAND FLASH 啟動。
接線如下
注意:
把跳線帽拔了是從NOR FLASH啟動,此時零地址在NOR FLASH上,S3C2410片內(nèi)的4k SRAM被映射到高地址0x40000000。
把跳線帽插上是NAND FLASH啟動,此時SRAM被映射到零地址。此時,硬件上會自動把NAND FLASH前4k拷貝到SRAM中去。
S3C2410作為32位的CPU,可以使用的地址范圍理論上可以達到4G。除了上述用于連接外設的1GB地址空間外,還有一部分是cpu內(nèi)部寄存器的地址,剩下的地址空間沒有使用。
四、SDRAM的工作原理
SDRAM的內(nèi)部是一個存儲陣列。陣列就如同表格一樣,將數(shù)據(jù)"填"進去。在數(shù)據(jù)讀寫時和表格的檢索原理一樣,先指定一個行(Row),再指定一個列(Column),我們就可以準確地找到所需要的單元格,這就是內(nèi)存芯片尋址的基本原理。
先來看看fs2410上面內(nèi)存的接線原理圖
內(nèi)存的芯片是:K4S561632D-TC75
關鍵特性如下:
1.4M x 16bit x 4BANK = 32 M
2.64ms refresh period (8K Cycle)
(一個bank刷新完所需時間64ms,總共8 k = 8192個行,每一行刷新的間隔時間為64ms / 8192 = 7.8125us)
3.MAX 主頻133MHz(CL=3)
注意:CL,就是在CAS發(fā)出之后,仍要經(jīng)過一定的時間才能有數(shù)據(jù)輸出,從CAS與讀取命令發(fā)出到第一筆數(shù)據(jù)輸出的這段時間,被定義為CL(CAS Latency,CAS潛伏期)。
這里只是簡單羅列了一些重要特性,其他特性讀者可以查看其datasheet。
引腳功能:
下面我們再來看看sdram 是如何尋址
1.通過ADDR24,ADDR25,確定bank地址
2.通過RA0~RA12,確定行地址(8192個行)
3.通過CA0~CA8,確定列地址(512個列)
選定bank后,通過行地址和列地址就可以定位在那個單元格,在結合原理圖我們知道,fs2310接了兩個sdram,地址線復用,數(shù)據(jù)線分開。這樣一個4字節(jié)的數(shù)據(jù),前兩個字節(jié)存放在第一個sdram,后兩個字節(jié)存放在第二個sdram。
注意:先發(fā)bank地址,在發(fā)行地址,在發(fā)列地址
此時你也許有一個疑問,如果按照上面的描述,對于一個給定的地址進行讀寫都是4byte,但是有我們知道,有些時候我們讀取或?qū)懭胫皇悄骋粋€字節(jié)。對于1byte的讀寫是通過LDQM、UDQM。分別稱為低字節(jié)屏蔽、高字節(jié)屏蔽。
在來看看sdram的時序圖
Trp(Row precharge time):行預充電時間(min : 20 ns)
Trcd(/RAS to /CAS delay):行無效到列有效的時間(min : 20 ns)
呵呵,要想得到這樣的時序,我們只需要配置內(nèi)存控制器就可以了。
我們接的是nGCS6
27、26都是對于SRAM 的,我們是SDRAM使用默認的就可以.[25:24] 10,有人也許會問,我們的sdram不是16bit的嗎?
不要忘記了我們接了2塊sdram,用了32根數(shù)據(jù)線。
我們的sdram,[16:15] 使用11
Trcd的值 datasheet給出的最少是20ns,默認是10 = 4 clocks 對于 100MHZ,也就是40ns,個人覺得此處可以使用默認值
SCAN 10=9bit
刷新控制器配置如下:
REFEN : 1
TREFMD : 0
Trp : 00
Trc : [datasheet: min 65ns]這里我們選擇10 = 6clocks
Refresh Counter
我在板子上設置HCLK = 101.4MHZ,Refresh count = 2^11 + 1 - 101.4 x 7.8125 = 1256
這里我們主要關注BK76MAP,其他的使用默認值
BANK6/7對應的地址空間與BANK0-5不同。BANK0~5的地址空間大小都是固定的128MB,地址范圍是(x * 128M)到(x +1 )*128M -1,x表示0到5。BANK6/7的大小是可以邊的,以保持這兩個空間的地址連續(xù),即BANK7的起始地址會隨他們的大小變化。 <
fs2410BANK6接的是2塊32M sdram,大小為64M,BANK7沒用,所以[2:0] 000=64MB/64MB
這里我們只需要設置CL就可以,其他都是fixed(固定),不需要設置。
CL : 011 = 3clocks.
SMRDATA:
.word (2 << 24) + (1 << 26) @BWSCON
.word 0x0700 @BANKCON0
.word 0x700 @BANKCON1
.word 0x700 @BANKCON2
.word 0x700 @BANKCON3
.word 0x700 @BANKCON4
.word 0x700 @BANKCON5
.word (3 << 15) + (1 << 0) @BANKCON6
.word 0x18001 @BANKCON7
.word (1 << 23) + (2 << 18) + ( 1256 << 0) @REFRESH
.word (1 << 7) + (1 << 0) @BANKSIZE
.word (3 << 4) @MRSRB6
.word (3 << 4) @MRSRB7
案例:從 nand 啟動,然后將 sram的代碼拷貝到sdram,然后跳到sdram中去執(zhí)行代碼
start.S
.extern main
.text
.global _start
_start:
#define pWTCON 0x53000000
#define CLKDIVN 0x4c000014
#define MPLLCON 0x4c000004
#define MEMBASE 0x48000000
bl disable_watchdog
bl init_sys_clock
bl init_sdrm
bl copy_sram_to_sdram
ldr pc,=on_sdram @pc指針指向內(nèi)存執(zhí)行代碼
on_sdram:
@此時內(nèi)存已經(jīng)初始化好,設置棧指針
ldr sp,=0x33000000
bl main
mainloop:
b mainloop
disable_watchdog:
@關看門狗,不然cpu會不斷重啟
ldr r0,=pWTCON
mov r1,#0
str r1,[r0]
mov pc,lr init_sys_clock:
@目前為止,cpu工作在12MHZ頻率下
@提升cpu工作頻率FCLK:HCLK:PCLK=1:2:4
ldr r0,=CLKDIVN
mov r1,#3
str r1,[r0] @ifHDIVN=1,must asynchronous buf mode
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000
mcr p15,0,r0,c1,c0,0
@設置MPLL,使cpu工作在202.80MHZ
ldr r0,=MPLLCON
ldr r1,=0x000a1031
str r1,[r0]
mov pc,lr
copy_sram_to_sdram:
@將sram的4k數(shù)據(jù)全部復制到sdram中去
@sram的起始地址為0x00000000,sdram中的起始地址為0x30000000
mov r1,#0
ldr r2,=0x30000000
mov r3,#4096 @4 * 1024
1:
ldr r4,[r1],#4
str r4,[r2],#4
cmp r1,r3
bne 1b
mov pc,lr
init_sdrm:
@初始化sdram
ldr r0,=MEMBASE @13個寄存器的首地址
adrl r1,SMRDATA @13個寄存器值存放的地址
mov r2,#52 @13 * 4 = 52 add r2,r2,r1
1:
ldr r3,[r1],#4
str r3,[r0],#4
cmp r1,r2
bne 1b /*every thing is fine now*/
mov pc,lr @ .ltorg @聲明一個數(shù)據(jù)緩沖池的開始
SMRDATA:
.word (2 << 24) + (1 << 26) @BWSCON
.word 0x0700 @BANKCON0
.word 0x700 @BANKCON1
.word 0x700 @BANKCON2
.word 0x700 @BANKCON3
.word 0x700 @BANKCON4
.word 0x700 @BANKCON5
.word (3 << 15) + (1 << 0) @BANKCON6
.word 0x18001 @BANKCON7
.word (1 << 23) + (2 << 18) + (1256 << 0) @REFRESH
.word (1 << 7) + (1 << 0) @BANKSIZE
.word (3 << 4) @MRSRB6
.word (3 << 4) @MRSRB7
led.c
#include "s3c2410.h"
//初始化
int led_init()
{
//GPFCON -> [8:15]清零
GPFCON &= ~(0xff << 8);
//GPF4 GPF5 GPF6 GPF7設為輸出模式
GPFCON |= 0x55 << 8;
//輸出高低平,關閉四路LED燈
GPFDAT |= 0xf << 4;
return 0;
}
//關閉LED
int led_off()
{
GPFDAT |= 0xf << 4; return 0;
}
//延時函數(shù)
int delay_time(int time)
{
int i,j; //讓兩個for循環(huán)作為延時
for(i = 0;i < time;i ++)
for(j = 0;j < time;j ++);
return 0;
}
//流水燈
int run_water_led(int count)
{
int i = 0; while(count --)
{
led_off();
delay_time(1000);
for(i = 4;i < 8;i ++)
{
GPFDAT &= ~(0x1 << i);
delay_time(1000);
}
}
return 0;
}
int main()
{
int i;
led_init(); run_water_led(5);
led_off();
return 0;
}
Makefile:
led.bin:start.S led.c
arm-none-linux-gnueabi-gcc -c -g start.S -o start.o
arm-none-linux-gnueabi-gcc -c -g led.c -o led.o
# arm-none-linux-gnueabi-ld -Ttext 0x00000000 start.o led.o -o led_elf
arm-none-linux-gnueabi-ld -Ttext 0x30000000 start.o led.o -o led_elf
arm-none-linux-gnueabi-objcopy -O binary -S led_elf led.bin
cp led.bin /tftpboot
clean:
rm -rf *.o led_elf led.bin
轉(zhuǎn)自:http://www.embedu.org/Column/Column543.htm