reference: https://blog.csdn.net/ruby97/article/details/7539151
DSP6455的EMIFA模塊
之前介紹了DSP6455的GPIO和中斷部分。今天,繼續介紹EMIFA模塊。
關於C6000系列的GPIO,請參考:C6000系列DSP的GPIO模塊
關於C6000系列的中斷系統,請參考:C6000系列DSP的中斷系統
背景
使用FPGA系統進行視頻采集,DSP進行視頻處理需要了解以下知識:
- 1. DSP-C6000系列的中斷與GPIO系統
- 2. DSP-C6000系列的EMIFA模塊
- 3. DSP-C6000系列的EDMA模塊
- 4. FPGA的乒乓RAM
- 5. 一種視頻格式(例如VGA,PAL等)
- 6. 視頻處理算法
之前已經介紹了第一部分,今天介紹第二部分。
主題
EMIF是External Memory Interface的簡稱。個人認為它是DSP比較強大的地方之一。通過EMIF接口,使得DSP可以和FPGA很方便地進行大數據量的數據傳輸。
C6455的EMIFA可以訪問多種外部存儲器,比如:SRAM,ROM,FLASH等等。當然,也包括FPGA。本文的重點就是介紹使用EMIFA接口與FPGA建立無縫連接。
--------------------------------------------華麗分割------------------------------------------------
EMIFA
根據習慣,還是先貼圖,框圖總給人一目了然的感覺。

這是官方文檔給出的EMIFA模塊的接口示意圖,乍一看,復雜的很。好多引腳而且還有好多復用。沒關系,我們再貼一張,你就會感覺輕松很多了。

這一張圖首先是把EMIFA模塊的接口分了類,然和呢,我把在與FPGA通信場合下所需要使用的管腳使用紅色框框標注了出來。是不是少了很多呢。歸納一下標注的管腳,如下:
- AED[63:0] 64位數據總線
- AEA[19:0] 20位地址總線(Optional)
- ACE2 片選信號(低有效)
- AECLKOUT 時鍾信號
- ASWE 寫使能(低有效)
- ASRE 讀使能(低有效)
(注:應用場合是DSP讀FPGA內部RAM中的圖像數據,其他場合續根據情況調整)
由於FPGA的可編程性,使得一切從DSP看來簡單了許多。因為DSP面對的“存儲器”顯得格外智能。甚至連地址線都可以不需要。
下面,我們來一一分析上述的信號。
- 首先,應該是片選信號CE。這里不得不提到DSP的地址空間。下圖是DSP6455的EMIFA映射情況
- EMIFA共支持4個外部存儲器,比如可以把CE2分配給FPGA,CE3分配給SRAM,CE4分配給FLASH等。
- 每個外部存儲器的尋址空間大小是8MB。20根地址線即2的20次方,也就是1MB,此外由於數據總線是64位的,故對應的尋址空間是8MB
由於FPGA內部時序邏輯可以產生地址,所以我們可以不使用地址線。這樣,下面的事情就簡單了。只要把CE2管腳和FPGA的某一個通用IO口連上即可。
在讀取FPGA內部RAM數據時告訴EDMA要讀取的數據的基地址是0xA0000000,以及讀取的數據的長度即可。
- 第二個信號,ECLKOUT,即時鍾信號的。因為FPGA工作是需要時鍾激勵的,沒有時鍾信號怎么產生地址邏輯呢?此外,時鍾頻率不能過高,要考慮到FPGA芯片的能力。OK,因為有了同步時鍾,所以EMIFA模塊的工作模式也就確定了,即同步工作模式。
- 第三個信號,包括2個,即ASRE,ASWE。更熟悉的叫法是RE,WE。讀使能和寫使能。這個就不贅述了。
- 第四個信號,數據總線&地址總線。也不贅述了。
經過上面的分析,我們可以簡要的畫出FPGA與DSP的連接圖:
其實也就只有1個比較重要的寄存器,即CEnCFG。該寄存器有兩套完全不同的配置。分別對應於同步存儲器模式和異步存儲器模式。由於FPGA內部RAM工作於同步模式,故我們來看一下同步模式下該寄存器的配置。
| R_ENABLE | 設置SRE/SADS管腳功能 |
| 值為 1 | 管腳功能為SRE,即Read Enable |
| 值為 0 | 管腳功能為SADS |
| W_LTNCY | 寫延時周期 |
| 值為 00 | 0周期延時 |
| 值為 01 | 1周期延時 |
| 值為 10 | 2周期延時 |
| 值為 11 | 3周期延時 |
| R_LTNCY | 讀延時周期 |
| 值為 01 | 1周期延時 |
| 值為 10 | 2周期延時 |
| 值為 11 | 3周期延時 |
讀延時:當CE和RE同時為低電平后,表示DSP開始讀FPGA的RAM,經過R_LTNCY個ECLKOUT周期后第一個數據出現在數據總線上
| SBSIZE | 數據位寬 |
| 值為 00 | 8位數據總線 |
| 值為 01 | 16位數據總線 |
| 值為 10 | 32位數據總線 |
| 值為 11 | 64位數據總線 |
EMIFA之CSL
使用CSL配置EMIFA模塊時,主要的步驟如下:
- l 1. 使能設備EMIFA模塊
- l 2. 配置CEnCFG寄存器
- l 3. 初始化EMIFA模塊
- l 4. 打開EMIFA模塊
- l 5. 把2中配置的參數設置到打開的EMIFA模塊中
完整配置代碼:(把EMIFA的CE2配置為以FPGA作為外部存儲器,64位數據線,2個周期的讀延時)
/*-----------------------------------------------------------------------------------
*
* 初始化EMIFA
*
-----------------------------------------------------------------------------------*/
#define EMIFA_MEMTYPE_ASYNC 0
#define EMIFA_MEMTYPE_SYNC 1
#define EMIFA_CE2_BASE_ADDR (0xA0000000)//地址空間基地址
#define CSL_EMIFA_SYNCCFG_RLTNCY_PARAMETER 2//讀延時2周期
#define CSL_EMIFA_SYNCCFG_SBSIZE_PARAMETER 3//64位數據總線
#define CSL_EMIFA_SYNCCFG_READEN_PARAMETER 1//SRE
//CEnCFG寄存器參數宏
#define CSL_EMIFA_SYNCCFG_PARAMETER {\
(Uint8)CSL_EMIFA_SYNCCFG_READBYTEEN_DEFAULT, \
(Uint8)CSL_EMIFA_SYNCCFG_CHIPENEXT_DEFAULT, \
(Uint8)CSL_EMIFA_SYNCCFG_READEN_PARAMETER, \
(Uint8)CSL_EMIFA_SYNCCFG_WLTNCY_DEFAULT, \
(Uint8)CSL_EMIFA_SYNCCFG_RLTNCY_PARAMETER, \
(Uint8)CSL_EMIFA_SYNCCFG_SBSIZE_PARAMETER \
}
void Init_EMIF()
{
CSL_EmifaObj emifaObj;
CSL_Status status;
CSL_EmifaHwSetup hwSetup;
CSL_EmifaHandle hEmifa;
CSL_EmifaMemType syncVal;
CSL_EmifaSync syncMem = CSL_EMIFA_SYNCCFG_PARAMETER;
memset(&emifaObj, 0, sizeof(CSL_EmifaObj));
memset(&hwSetup, 0, sizeof(CSL_EmifaHwSetup));
//步驟1: 使能設備的EMIFA功能(不用先解鎖外設寄存器)
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG1, DEV_PERCFG1_EMIFACTL, ENABLE);
//步驟2:配置CE2CFG寄存器
syncVal.ssel = EMIFA_MEMTYPE_SYNC;
syncVal.async = NULL;
syncVal.sync = &syncMem;
hwSetup.ceCfg[0] = &syncVal;
hwSetup.ceCfg[1] = NULL;
hwSetup.ceCfg[2] = NULL;
hwSetup.ceCfg[3] = NULL;
//步驟3:初始化EMIFA模塊
status = CSL_emifaInit(NULL);
#ifdef SHOW_PRINTF
if (status != CSL_SOK) {
printf("EMIFA: Initialization error.\n");
printf("\tReason: CSL_emifaInit [status = 0x%x].\n", status);
return;
}
else {
printf("EMIFA: Module Initialized.\n");
}
#endif
//步驟4:打開EMIFA模塊
hEmifa = CSL_emifaOpen(&emifaObj,CSL_EMIFA,NULL,&status);
#ifdef SHOW_PRINTF
if ((status != CSL_SOK) || (hEmifa == NULL)) {
printf("EMIFA: Error opening the instance. [status = 0x%x, hEmifa \
= 0x%x]\n", status, hEmifa);
return;
}
else {
printf("EMIFA: Module instance opened.\n");
}
#endif
//步驟5:把步驟2中配置的參數設置到打開的EMIFA模塊中
status = CSL_emifaHwSetup(hEmifa,&hwSetup);
#ifdef SHOW_PRINTF
if (status != CSL_SOK) {
printf("EMIFA: Error in HW Setup.\n");
printf("Read write operation fails\n");
return;
}
else {
printf("EMIFA: Module Hardware setup is successful.\n");
}
#endif
}
