天天看點

005 sdram裸機程式設計

前面我們使用過uart來列印輸出資訊。

今天我們來學習一下sdram的使用。

sdram的功能相當我們在使用PC機的時候裡面插的ram,當然我們S3C2440在晶片内部會有一個自帶的SRAM(大小為4K),

當這個自帶的sram不夠用的時候,就會需要使用我們外接的sdram了。

缺點是sdram在使用的時候,需要先把資料搬進去,處理好以後再搬出來給到cpu使用,與内部sram相比降低了運作速度。

但我們在配置的時候,把性能配置好,依然很快。

這裡建議大家看一篇關于sdram的文章,講的很深很好。

《SDRAM參考文檔: 高手進階,終極記憶體技術指南——完整/進階版》百度一下這篇文章即可。

然後我們來學習一下本節sdram的一些知識和使用。不足之處希望大家指出,謝謝。

首先我們了解一下原理圖,看下硬體構成。

005 sdram裸機程式設計

我們使用的是16bits * 2  兩塊sdram。

那麼我們由原理圖可以看出,addr線是并接的,且從addr2開始接sdram的addr0線。

其原因有二:

1、并接的原因是因為我們s3c2440是32bit,是以把兩個16bit的sdram組合成32bit來處理cpu的一個帶寬資料。

2、addr2接sdram的addr0是因為如下圖:

005 sdram裸機程式設計

當我們cpu想通路的位址為A0A1A2A3 = 0010時,則sdram收到的位址是A2A3也就是SDRAM(A0A1)=10。

也就是我們兩塊sdram的第二個word。然後把兩個sdram的③④組裝成一個32bit的資料data,傳回給記憶體控制器,再由記憶體控制器根據上s3c2440的A0A1位址資料,取出data中對應的那個byte資料給到cpu。

這裡的原理和2440的spec寫的一樣:

005 sdram裸機程式設計

接下來我們要看cpu是如何選中sdram的。原理圖中可以看到,有一個片選引腳LnGS6, 由2440 spec可以看到這塊記憶體接口是專門用來外接sdram的。

005 sdram裸機程式設計

我們可以看到sdram是可程式設計記憶體空間的,2MB~128MB,我們用的是2個32MB的sdram組成一個64MB的sdram供cpu使用。

接下來我們講一下sdram的内部結構和尋址方式:

005 sdram裸機程式設計

目前我們的sdram内部采用的是邏輯分區為4個,然後是行列位址。

比如要寫一個資料到sdram,那麼我們需要先選中L_BANKx,然後行位址,再列位址。找到對應位址後再把資料寫入目的位址。

再bank中的尋址方式類似于excel的單元格查找。

由原理圖可以看到我們使用LADDR24/25來選中邏輯bank,再由laddr2~laddr14來寫入行列位址。

行位址為laddr2~laddr14,列位址為9bit, laddr2~laddr1(sdram spec得到)

005 sdram裸機程式設計

2440和sdram之間的通信時序如下圖:

005 sdram裸機程式設計

要注意的地方是,要根據sdram的時間要求來修改位址和資料之間的時間差。

到這裡我們原理分析完畢。然後配置寄存器。

我們直接借用韋東山老師的講課圖。

005 sdram裸機程式設計
005 sdram裸機程式設計
005 sdram裸機程式設計
005 sdram裸機程式設計
005 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裡面就列印不出來。根源未知。

繼續閱讀