跳轉到主要內容

4. 外部RAM

動機

在此步驟中,我們將使能致能外部SDRAM。 圖形應用通常需要外部RAM,因為在許多解析度下影像緩衝區會過大導致而導致無法使用內部RAM。 某些應用可能使用兩到三個影像緩衝區,因此更加需要外部RAM。

Note
如果所用開發板不對外擴充RAM,請跳過此步。

當影像緩衝區要放在外部RAM時,確保外部RAM

  • 可讀可寫。
  • 以所需的速度(通常為最大速度)運行。

目標

本節目的在啟用外部RAM,並從中讀取和寫入數據。

驗證

以下是本節的驗證點:

驗證點基本原理
外部RAM可讀外部RAM可用於影像緩衝區位置
外部RAM可寫外部RAM可用於影像緩衝區位置
外部RAM效能使用外部RAM為影像緩衝區時,圖形處理效能可接受

先決條件

以下是此步驟的先決條件:

  • 有關RAM的資訊,通常為資料手冊
  • 有關MCU與外部RAM之間的連接的資訊

執行

外部SDRAM控制器設定於 連線 -> FMC -> SDRAM1下的STM32CubeMX:

設定SDRAM

AHB時鐘(HCLK)是FMC記憶體控制器的參考時鐘。 檢查「時鐘設定」下的時鐘頻率,並使用該頻率計算各種SDRAM時鐘週期。

請記得設定所有用於SDRAM的GPIO:

設定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後的第一個測試為經由調試器訪問它。 這樣就可以輕鬆確認是否可以讀寫記憶體。 只需使用記憶體讀取器開啟以下位址:

使用除錯器中0xD0000000的儲存區段以測試儲存區域2

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時鐘過快,則可能在讀取或寫入操作期間導致錯誤。 通過這些較簡單的測試可能很難看到這一點,但這在顯示器上可以直觀地感受到。