Skip to main content

4. 外部RAM

Motivation#

このステップでは、外部SDRAMを有効化します。 多くの解像度ではフレームバッファが大きすぎて内部RAMに収まりきらないため、グラフィカル・アプリケーションでは外部RAMが必要になることがよくあります。 アプリケーションによっては、2つまたは3つのフレームバッファを使用するため、外部RAMがさらに必要になります。

Note
外付けRAMがご使用のボードに関係ない場合は、このステップをスキップしてください。

フレームバッファを外部RAMに配置する場合、外部RAMが下記の条件を満たすことが重要です。

  • 読出し / 書込みが可能であること。
  • 目的の速度(通常は最大) で動作すること。

目標#

本セクションの目標は、外部RAMを有効化し、データの読出し / 書込みを行うことです。

検証#

次の表に、このセクションの検証ポイントを示します。

検証ポイント検証内容
外部RAMを読み出せる外部RAMをフレームバッファの格納場所として使用できること。
外部RAMに書き込める外部RAMをフレームバッファの格納場所として使用できること。
外部RAMの性能外部RAM内のフレームバッファで許容できるグラフィック性能が得られること。

Prerequisites#

以下に、このステップの前提条件を示します

  • RAMに関する情報(通常はデータシート)
  • マイクロコントローラと外部RAMの接続に関する情報

作業内容#

The external SDRAM controller is configured in STM32CubeMX under Connectivity -> FMC -> SDRAM1:

SDRAMの設定

AHBクロック(HCLK) は、FMCメモリ・コントローラのリファレンス・クロックです。 [Clock Configuration]でクロック周波数を確認し、その値を各種SDRAMのクロック・サイクルの計算に使用します。

SDRAMで使用するGPIOをすべて設定してください。

SDRAMのGPIOの設定

詳細設定#

RAMチップの中には、さらにデバイス固有の設定が必要になるものがあります。 This cannot be configured in STM32CubeMX, but must be done in the C code. The STM32Cube HAL contains functions to send commands to the device. 以下に例を示します。

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を有効化して最初に行うテストはデバッガからのアクセスです。 これで、メモリに対する読出し / 書込みが可能かどうかが簡単にわかります。 メモリ・ビューアを開き、該当するアドレスを表示します。

デバッガにおけるバンク2、0xD0000000のメモリのテスト

RAMのすべての範囲に対して読出し / 書込みが可能であること#

次のテストでは、外部メモリにより多くのデータを書き込む小さなプログラムを作成します。 なるべく、メモリ全体をテストしてください。 手始めに、次のようなコードを使用できます。

uint32_t *externalRAM = 0xC000000;const uint32_t size = 1000;
//write external RAMfor(int i = 0; i < size; i++){    externalRAM[i] = i;}

デバッガで再度メモリを確認します。 ここで、アドレス・ピンの一部が未接続だったり、入れ替わったりしているなど、いくつかの種類ののエラーが明らかになる場合があります。 値のパターンを変更したテストも必要です。 また、0、1、2、3などの小さな値しか書き込まないと、データ・ピンの一部に不具合があっても検出できません。

次のような、小さなプログラムによってメモリの読出しも可能です。

uint32_t *externalRAM = 0xC000000;const uint32_t size = 1000;
//read external RAMfor(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 RAMfor(int i = 0; i < size; i++){    externalRAM[i] = sourcedata[i];}int end = HAL_GetTick();
int begin = HAL_GetTick();//Read external RAMfor(int i = 0; i < size; i++){    sourcedata[i] = externalRAM[i];}int end = HAL_GetTick();

グラフィック・ソフトウェアは、バックグラウンドの画像をブレンドする場合などに、フレームバッファに対してデータを読み書きします。

//Time modifying external RAMint begin = HAL_GetTick();for(int i = 0; i < size; i++){    externalRAM[i] += 2;}int end = HAL_GetTick();

メモリの速度および必要な精度に応じて、テストをたとえば100回ループさせることで、結果の信頼性を高めることができます。

外部RAMに供給されるクロックが高速すぎると、読出しまたは書込み動作中に誤った値が得られる場合があります。 こうしたエラーは、上記のような単純なテストでは検出が困難な可能性がありますが、ディスプレイでは確認できます。