前面我們使用過uart來列印輸出資訊。
今天我們來學習一下sdram的使用。
sdram的功能相當我們在使用PC機的時候裡面插的ram,當然我們S3C2440在晶片内部會有一個自帶的SRAM(大小為4K),
當這個自帶的sram不夠用的時候,就會需要使用我們外接的sdram了。
缺點是sdram在使用的時候,需要先把資料搬進去,處理好以後再搬出來給到cpu使用,與内部sram相比降低了運作速度。
但我們在配置的時候,把性能配置好,依然很快。
這裡建議大家看一篇關于sdram的文章,講的很深很好。
《SDRAM參考文檔: 高手進階,終極記憶體技術指南——完整/進階版》百度一下這篇文章即可。
然後我們來學習一下本節sdram的一些知識和使用。不足之處希望大家指出,謝謝。
首先我們了解一下原理圖,看下硬體構成。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90zZNpXSU5Ee4cVWv50MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2cTNzQjNykDM2ATOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
我們使用的是16bits * 2 兩塊sdram。
那麼我們由原理圖可以看出,addr線是并接的,且從addr2開始接sdram的addr0線。
其原因有二:
1、并接的原因是因為我們s3c2440是32bit,是以把兩個16bit的sdram組合成32bit來處理cpu的一個帶寬資料。
2、addr2接sdram的addr0是因為如下圖:
當我們cpu想通路的位址為A0A1A2A3 = 0010時,則sdram收到的位址是A2A3也就是SDRAM(A0A1)=10。
也就是我們兩塊sdram的第二個word。然後把兩個sdram的③④組裝成一個32bit的資料data,傳回給記憶體控制器,再由記憶體控制器根據上s3c2440的A0A1位址資料,取出data中對應的那個byte資料給到cpu。
這裡的原理和2440的spec寫的一樣:
接下來我們要看cpu是如何選中sdram的。原理圖中可以看到,有一個片選引腳LnGS6, 由2440 spec可以看到這塊記憶體接口是專門用來外接sdram的。
我們可以看到sdram是可程式設計記憶體空間的,2MB~128MB,我們用的是2個32MB的sdram組成一個64MB的sdram供cpu使用。
接下來我們講一下sdram的内部結構和尋址方式:
目前我們的sdram内部采用的是邏輯分區為4個,然後是行列位址。
比如要寫一個資料到sdram,那麼我們需要先選中L_BANKx,然後行位址,再列位址。找到對應位址後再把資料寫入目的位址。
再bank中的尋址方式類似于excel的單元格查找。
由原理圖可以看到我們使用LADDR24/25來選中邏輯bank,再由laddr2~laddr14來寫入行列位址。
行位址為laddr2~laddr14,列位址為9bit, laddr2~laddr1(sdram spec得到)
2440和sdram之間的通信時序如下圖:
要注意的地方是,要根據sdram的時間要求來修改位址和資料之間的時間差。
到這裡我們原理分析完畢。然後配置寄存器。
我們直接借用韋東山老師的講課圖。
上面說那麼多原理,其實就是這幾個寄存器的配置。我們隻使用了基本的功能。一些busrt等等模式還沒有使用。
上代碼:
void sdram_init(void)
{
BWSCON = 0x22000000;
BANKCON6 = 0x18001;
BANKCON7 = 0x18001; //bank7 config same param also.
REFRESH = 0x8404F5;
BANKSIZE = 0xB1;
MRSRB6 = 0x20;
MRSRB7 = 0x20; //bank7 config same param also.
}
到這裡我們就可以使用sdram了。
下面加了一段sdram測試。
int sdram_test(void)
{
volatile unsigned char *p = (volatile unsigned char *)0x30000000;
int i;
//write sdram
for(i = 0; i < 1000; i++)
{
p[i] = 0x55;
}
//read sdram
for(i = 0; i < 1000; i++)
{
//printf("write data to sdram p[%d] = %d \r\n", i, p[i]);
if(p[i] != 0x55)
return -1;
}
return 0;
}
最後再做這個實驗的時候,有兩個問題搗鼓了一下午沒解開?
1、添加uart的時候,使用了printf函數,Makefile中把-Tdata段設定在0xe80和0xee0之間都可以正常列印。但是設定到0xef0以後就不能正常輸出%d %x等這些格式,都是空白輸出。 我查了代碼段和隻讀資料段最後位址都沒有覆寫到-Tdata。
2、printf函數放到sdram.c裡面就列印不出來。根源未知。