Part9: 記憶體控制器與SDRAM硬體程式設計
-
-
-
-
- 1 記憶體接口的概念
- 2 不同位寬晶片的位址連接配接
- 3 記憶體通路時序圖
- 4 SDRAM原理及硬體程式設計
-
-
-
1 記憶體接口的概念
以s3c2440為例,看下面該開發闆的記憶體接口圖
竟然Nor Flash、網卡、SDRAM(記憶體)、GPIO、UART這些是統一編址,那有沒有“獨立編址”的呢?
答:有的,nand flash就是一個典例,它不參與CPU的統一編址,看下圖
此外,由第一張圖可觀察到,這些接口是由CPU發給記憶體控制器32位addr選擇的
那問題來了,對于以上接口,記憶體控制器怎麼根據32位的Addr選擇不同的晶片/子產品呢?
備注:片選名稱、addr範圍都是查S3C2440晶片手冊和原理圖擷取的
由上圖可觀察注意到,一個片選信号選通的位址範圍是0x0800,0000,即128M範圍。128M=2^(27),即需要27根位址總線
但是S3C2440是32位的,有32根位址線,那為隻用到了27根位址線呢?
答:CPU發出32位位址,而實際記憶體控制器隻用27根位址線而已,其餘位址線另有他用,
而這涉及到不同位寬晶片的連接配接問題,看下面的第2點分析
2 不同位寬晶片的位址連接配接
檢視S3C2440的原理圖,可發現像SDRAM/DM9000/Nor Flash它們并不是都有27根位址線,而隻是其中一部分。
是以,這涉及到記憶體控制怎樣尋址不同晶片,或者說,不同位寬的晶片/裝置位址連接配接關系是怎樣的?看下圖
備注:上面8/16/32bit RAM晶片的連法可檢視S3C2440晶片手冊,裡面有舉例說明。限于篇幅,在此就不貼出了
但是,當讀取4位元組時,8bit/16bit的RAM怎麼讀取呢?
答:對應8bitRAM,需發出4次通路,如通路位址是0x4,第一次通路0x4,接着位址自動+1,通路0x5,依次類推
同理,對于16bitRAM,需要發出兩次位址信号。第二次會在第一次位址基礎上+1再通路,最終記憶體控制器
會組裝好4位元組資料給CPU。
可見,正如教程說的。CPU是大爺,不關心記憶體控制器怎麼操作。大爺動動嘴,就讓記憶體控制器跑斷腿 :)
最後一個問題,怎麼根據确定晶片通路位址
答:1)根據片選信号确定基址
2)根據晶片所接位址線确定範圍
例如,SDRAM(記憶體)、DM900(網卡)、Nor Flash的通路位址範圍如下表
備注一下:SDRAM的位址通路較複雜,下面第4點SDRAM原理和程式設計時才介紹
3 記憶體通路時序圖
除了位址總線/資料總線,還有其它資料線。例如怎麼确定是CPU向SDRAM讀資料還是寫資料呢?
答:這涉及記憶體控制時序的問題,還是看圖,如下,以可程式設計通路周期——讀時序圖為例
補充:1)從左往右了解值,信号的發出順序。如上面需要讀資料時,先發出A[24:0]位址信号,再發出nGCS片選信号,
最後才發出nOE讀使能信号,并等待Tacc時長資料方可讀取,而釋放信号順序反過來了解即可。
2)s3c2440可接不同性能的晶片,這些時間參數就是為滿足不同性能晶片可程式設計設定。
上面時間參數如何選擇呢?以s3c2440所接的Nor Flash晶片的讀時序為例講解,如下所示
是以,結合Nor Flash和s3c2440的讀時序圖,可同時發出片選信号、位址信号和讀信号,并等待Tacc=70ns即可滿足
Nor Flash這款晶片的讀要求。
基于前面檔案HCLK=100mHZ,查詢s3c2440手冊,隻需設定BANKCON0裡的tacc(即[10:8])即可,如下所示
因為要>=70ns,且HCLK=100mHZ的周期為10ns,故BANKCON0的[10:8]最少為0b101,即5≤val≤7
實驗效果:我這邊測試時,在[4,7]範圍内都是有效的,且流水燈速度越來越慢。至于為啥4時有效,不太清楚,
可能有些誤差(我用的是S3C2440的V3版本,Nor Flash型号是MX29LV160DBTI-70G(NOR FLASH))
4 SDRAM原理及硬體程式設計
對于怎麼根據addr通路SDRAM,可看下圖的簡要解釋(注:這裡偷個懶,直接截取自韋東山老師的課堂筆記,哈哈)
總的來說,要檢視SDRAM晶片手冊确定行列位址線數後,再配置s3c2440有關記憶體控制的寄存器以正确比對位址拆分,
為此才能正确通路SDRAM,下面根據S3C2440接的EM63A165TS(SDRAM)這款晶片為例,講解如何配置寄存器
對于EM63A165TS(SDRAM)這款晶片查詢可知,列位址需9條列位址線(A0-A8),BANK位址2條(64M,需Bank0~Bank3)、
行位址線13條(A0-A12)
對于nGCS6這條SDRAM的片選信号,需要設定5個相關的記憶體控制寄存器,如下所示
OK,隻需設定上面5個寄存器即可,代碼如下
sdram_init函數
void sdram_init(void)
{
BWSCON = 0x22000000;
BANKCON6 = 0x18001;
BANKCON7 = 0x18001; //可不設定
REFRESH = 0x8404f5;
BANKSIZE = 0xb1;
MRSRB6 = 0x20;
MRSRB7 = 0x20; //可不設定
}
sdram_test函數
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++)
if (p[i] != 0x55)
return -1;
return 0;
}
main.c函數
int main(void)
{
uart0_init();
sdram_init();
if (sdram_test() == 0)//測試成功,才執行流水燈
led_test();
return 0;
}
備注:我并沒有貼出完整代碼,一方面官網有(www.100ask.net),沒必要這裡占據篇幅。
另一方面,重在了解即可。
實驗效果:我這裡示範是OK的,即測試成功,有流水燈。
總結:
以上就是這篇文章的所有内容,雖然篇幅有點長,但我盡量以圖的方式展示了。
主要講解了記憶體接口概念、不同位寬晶片的位址連接配接、記憶體通路時序圖如何看、SDRAM位址拆分和硬體程式設計。
這些知識很重要,望重視 : )
說明一下,以上内容是基于韋東山老師新1期的“記憶體控制器及SDRAM”教程裡的筆記。
我這裡隻是重新整理并加以注釋總結。更詳細的可檢視視訊教程 (我不做廣告,隻是尊重版權: )