聲明:本文為原創作品,著作權歸本博文作者
所有,如需轉載,請註明出處
http://www.cnblogs.com/kingst/
一、簡介
這一節,我們來聊聊SDRAM吧。作為NIOS系統中最重要的一個外部器件,它擔任著重要的角色,大家對它也應該很熟悉。每次上電的時候,FPGA都會把FLASH中的程式送到SDRAM中運行,之所以這樣來做就是因為它的速度很快,但它掉電是要遺失資料的,所以要把資料存到FLASH中。
有關SDRAM的理論知識我在這裡不說了,不知道的百度google一下都可以。其實在NIOS II開發過程中,就算你對SDRAM的理論知識不瞭解,也不耽誤你對它的使用。SOPC builder都已經完美的將它驅動起來,我們只要知道怎麼使用它就可以了。下面,我們就來講講他的使用方法,其實真的很簡單。
在我們講第一節的時候,我們就已經講了如何構建SDRAM的控制器了,我在這裡不再重複了,假設你已經構建好了,我主要講一下有關軟體的部分。
二、軟體開發
首先開啟NIOS II 9.0 IDE軟體,開啟後,我們來看看system.h檔案,確定一下SDRAM控制器模組是否已經加入進來。如果加入,有下面的內容出現
#define SDRAM_NAME "/dev/sdram"#define SDRAM_TYPE "altera_avalon_new_sdram_controller"#define SDRAM_BASE 0x01000000……
接下來,我們開始編寫有關SDRAM的軟體代碼,代碼很簡單,如下所示
/* * ==================================================================* Filename: main.c* Description: SDRAM讀寫實驗 * Version: 1.0.0 * Created: 2010.4.16 * Revision: none * Compiler: Nios II 9.0 IDE * Author: 馬瑞 (AVIC) * Email: avic633@gmail.com * ================================================================= *//*---------------------------------------------------------------- * Include *----------------------------------------------------------------*/#include <stdio.h>#include "../inc/sopc.h"#include "system.h"#include "string.h"/*--------------------------------------------------------------- * Variable *---------------------------------------------------------------*/unsigned short * ram = (unsigned short *)(SDRAM_BASE+0x10000); //SDRAM地址/* * === FUNCTION =================================================== * Name: main * Description: 函數主程式 * ================================================================= */int main(void){ int i; memset(ram,0,100); //向ram中寫資料,當ram寫完以後,ram的地址已經變為(SDRAM_BASE+0x10100) for(i=0;i<100;i++){ *(ram++) = i; } //逆向讀取ram中的資料 for(i=0;i<100;i++){ printf("%d\n",*(--ram)); } return 0;}
程式很簡單,就是向指定的SDRAM中賦值。在這個程式裡面有幾個地方需要說明一下。首先,我在程式前面定義了一個unsigned short類型的指標變數ram,並將其指向SDRAM+0x10000這個位置。之所以設定為unsigned short資料類型,是因為我們用的SDRAM是16位元據匯流排的。而將其指向SDRAM+0x10000是因為在NIOS II運行時會用到SDRAM的部分空間,我們必須避開這部分空間,以免運行錯誤。0x10000這個值不是固定的,只要避開SDRAM的那部分空間就可以了。除此之外還有一個地方需要注意,就是當我們對sdram賦值以後,指標就會向後移動,指向下一個地址空間,每加一次,地址都會向後面移動16位。假如我們現在是在SDRAM+0X10000這個位置,當指標向後移動一次以後,地址就變為了SDRAM+0X10002,再加一次就變為了SDRAM+0X10004,以此類推。這些都是內部自動處理的,不需要我們來參與,我們只要知道就可以了。
其實我講這部分內容是想告訴大家,SDRAM控制器一旦構建好以後,我們對SDRAM的處理就像對內部地址一樣,我們可以隨意的進行賦值和讀取。對於開發板上的64Mbit的SDRAM其實有很少一部分用給NIOS系統,其餘部分都在空閑,大家是不是覺得很浪費呢。其實在有些情況下,我們就可以利用起這部分資源,比如在某個系統中,我們需要將外設接收到的資料緩衝一下,我們就可以用這部分閒置SDRAM空間來處理。
在C語言中,如果我們要接收比較大的資料,還有另一種處理方法,那就是藉助堆(heap)。可能有些人對堆和棧還分不清楚,我在這簡單解釋一下。棧(stack) 由系統自動分配。 例如,聲明在函數中一個局部變數 int b,系統自動在棧中為b開闢空間。而堆(heap)需要程式員自己申請,並指明大小。有人用這樣一個比喻來解釋堆和棧的區別,非常形象貼切:使用棧就象我們去飯館裡吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。使用堆就象是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大,這個人真是太有才了。下面我來寫一個堆的代碼,這部分代碼是節選的,並不完全,功能是通過xmodem協議接收資料,並將其內容放到堆裡面。如下所示
/* * === FUNCTION ================================================== * Name: main * Description: 主函數 * ================================================================= */int main(){ char *ram = (char *)malloc ( sizeof(char)* 500000 ); if ( ram==NULL ) { fprintf ( stderr, "\ndynamic memory allocation failed\n" ); exit (EXIT_FAILURE); } uart.init(); /*------------------- FLASH -----------------------------*/ while(1){ if(uart.mode_flag){ xmodem.xmodem_rx(); printf("ram_cnt:%d\n",ram_cnt); parse_srecord_buf(ram,ram_cnt); printf("successful!"); ram_cnt = 0; uart.mode_flag = 0; } } free (ram); return 0;}
看了上面的代碼大家應該瞭解了堆的用法了吧,它是通過malloc向系統中申請空間的。申請成功以後,就會返回申請地址的首地址,失敗則返回NULL。到底申請在什麼地方,我們可以通過列印指標來得知,但並沒這個必要,因為這些都是系統來處理的,我們得到了首地址然後用就可以了。需要注意一點,我們申請完的地址用完以後需要釋放,用free來釋放就可以了。如果不釋放,可能會出現記憶體泄露問題,到時候麻煩就大了,具體大到什麼程度我也不知道,呵呵。
可能有人會問,為什麼不用棧來處理這個問題呢?這就跟編譯有關係了,在編譯過程中,系統會將棧需要的空間加到代碼中,也就是說如果你在代碼中用棧來處理大的資料,那麼你編譯以後的代碼會非常大,你下載到flash以後,載入到sdram中的時間也會非常之長。而堆這不會,系統對堆的處理方式是何時用合適分配,並不佔代碼空間。
說到這,有關SDRAM部分的內容講完了。總結一下,使用SDRAM有兩種方法,第一種是直接對SDRAM地址處理;第二種方法就是利用堆來處理。好了,這部分內容就講到這吧,如果大家對此有疑問,或者發現我講的內容有問題可以直接跟我聯絡,郵箱:avic633@gmail.com;qq:984597569。