4. 外部RAM
動機
在此步驟中,我們將使能致能外部SDRAM。 圖形應用通常需要外部RAM,因為在許多解析度下影像緩衝區會過大導致而導致無法使用內部RAM。 某些應用可能使用兩到三個影像緩衝區,因此更加需要外部RAM。
Note
當影像緩衝區要放在外部RAM時,確保外部RAM
- 可讀可寫。
- 以所需的速度(通常為最大速度)運行。
目標
本節目的在啟用外部RAM,並從中讀取和寫入數據。
驗證
以下是本節的驗證點:
驗證點 | 基本原理 |
---|---|
外部RAM可讀 | 外部RAM可用於影像緩衝區位置 |
外部RAM可寫 | 外部RAM可用於影像緩衝區位置 |
外部RAM效能 | 使用外部RAM為影像緩衝區時,圖形處理效能可接受 |
先決條件
以下是此步驟的先決條件:
- 有關RAM的資訊,通常為資料手冊
- 有關MCU與外部RAM之間的連接的資訊
執行
外部SDRAM控制器設定於 連線 -> FMC -> SDRAM1下的STM32CubeMX:
AHB時鐘(HCLK)是FMC記憶體控制器的參考時鐘。 檢查「時鐘設定」下的時鐘頻率,並使用該頻率計算各種SDRAM時鐘週期。
請記得設定所有用於SDRAM的GPIO:
進一步設定
對於某些RAM晶片,還必須進行其他特定的配置。 這無法在STM32CubeMX中配置,但必須在C語言程式碼中完成。 STM32Cube HAL包含向設備發送指令的函數。 下面為一個範例:
main.c
FMC_SDRAM_CommandTypeDef Command;
/* Step 1: Configure a clock configuration enable command */
Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
測試RAM
配置外部RAM後,務必對其進行測試。 我們至少應測試以下內容:
- RAM可見於除錯器中
- RAM在整個範圍內可讀可寫
- 性能符合預期
記憶體控制器根據外部記憶體的類型使用其固定位址映射。 通過這些較簡單的測試可能很難看到這一點,但這在顯示器上可以直觀地感受到。 SDRAM通常映射到0xC0000000(存儲區域1)或0xD0000000(存儲區域2)。
測試RAM在除錯器中可見。
使能RAM後的第一個測試為經由調試器訪問它。 這樣就可以輕鬆確認是否可以讀寫記憶體。 只需使用記憶體讀取器開啟以下位址:
RAM在整個範圍內可讀可寫
下一個測試為編寫小程式,並將更多數據寫入外部記憶體。 最好測試整個記憶體。 以下是起點:
uint32_t *externalRAM = 0xC000000;
const uint32_t size = 1000;
//write external RAM
for(int i = 0; i < size; i++)
{
externalRAM[i] = i;
}
現在,在調試器中再次檢查記憶體。 這可以顯示某些類型的錯誤,例如,某些位址引腳是否未連接或未交換。 您還應嘗試不同大小的值。 僅僅寫入小數位(如0、1、2、3)往往無法顯示某些數據引腳是否正常連接或損壞。
我們可以透過簡單程式來讀取記憶體:
uint32_t *externalRAM = 0xC000000;
const uint32_t size = 1000;
//read external RAM
for(int i = 0; i < size; i++)
{
ASSERT(externalRAM[i] == i, "external RAM not as expected");
}
請記住,此類測試無法確定位址是否錯誤。
測試所有存儲單元。 要麼透過執行更長的迴圈,要麼更改起始位址。
性能符合預期
我們現在需要測試外部RAM的性能。 當影像緩衝區位於外部記憶體中時,性能很重要。 緩慢的記憶體會使系統的圖形處理性能降低。
測試讀取、寫入和修改RAM的速度。 通常,圖形應用會將大量的數據從一個記憶體複製到另一個記憶體。 在繪圖操作期間將大量寫入影像緩衝區,而在傳輸至顯示器時將執行大量讀取操作。 我們可通過測試程式來模擬這些操作:
volatile uint32_t *externalRAM = 0xC000000;
uint32_t sourcedata[10000];
const uint32_t size = 10000;
int begin = HAL_GetTick();
//write external RAM
for(int i = 0; i < size; i++)
{
externalRAM[i] = sourcedata[i];
}
int end = HAL_GetTick();
int begin = HAL_GetTick();
//Read external RAM
for(int i = 0; i < size; i++)
{
sourcedata[i] = externalRAM[i];
}
int end = HAL_GetTick();
當在背景上混合圖形時,圖形處理軟體可在影像緩衝區中讀取和寫入數據。
//Time modifying external RAM
int begin = HAL_GetTick();
for(int i = 0; i < size; i++)
{
externalRAM[i] += 2;
}
int end = HAL_GetTick();
根據您的記憶體速度和想要的精確度,您可能希望迴圈測試100次,以使結果更加可靠。
如果外部RAM時鐘過快,則可能在讀取或寫入操作期間導致錯誤。 通過這些較簡單的測試可能很難看到這一點,但這在顯示器上可以直觀地感受到。