[LPC54608] SDRAMを使ってみた。〜備忘録〜


今回は、SDRAMを使ってみました。いくつか設定が必要なのですが、簡単にSDRAM領域を拡張して使用することができます。

では、早速行ってみます。

要点

  • ピン配でEMCピンを設定しておく。
  • EMCドライバーを使用する
  • リンカー設定にSDRAM領域を追加
  • 初期化設定する

では、一つずつ見ていきます。

ボードの準備

ボードは、OM13092 LPCXpresso54608を使用しました。このボードは、現在クロックアップグレード版LPC54628用のOM13098に置き換えられています。

LPC54628は、100%ソフトウェアコンパチで、クロックのみ220MHzにクロックアップされています。

なので、どちらでも同じです。

LPC546xx ブロック図
出典:NXP https://www.nxp.com/products/processors-and-microcontrollers/arm-based-processors-and-mcus/lpc-cortex-m-mcus/lpc54000-series-cortex-m4-mcus/power-efficient-microcontrollers-mcus-with-advanced-peripherals-based-on-arm-cortex-m4-core:LPC546XX
LPC54628
出典:NXP https://www.nxp.com/products/processors-and-microcontrollers/arm-based-processors-and-mcus/lpc-cortex-m-mcus/lpc54000-series-cortex-m4-mcus/lpcxpresso54628-development-board:OM13098

ピン配設定

ピンコンフィグ
ピンコンフィグ

まずは、SDRAMに繋がるピンを設定しないと接続できませんので、ピンを一つずつ設定していきます。

必要なピン

SDRAMを使用するのに、必要なピンは以下になります。この全てのピンをMUX設定する必要があります。

データバス アドレスバス 制御ピン
D0 E9 A0 C14 EMC_CAS K6
D1 A10 A1 C6 EMC_CKE0 A11
D2 C8 A2 D13 EMC_CLK0 B4
D3 E7 A3 C13 EMC_DQM0 G10
D4 A5 A4 E4 EMC_DQM1 C12
D5 H12 A5 G4 EMC_DYCS0 K9
D6 H10 A6 N1 EMC_RAS N9
D7 G12 A7 P8 EMC_WE L4
D8 L1 A8 J10
D9 M1 A9 F10
D10 N8 A10 B7
D11 D4 A11 M10
D12 E12 A12 N14
D13 C11 A13 M12
D14 A8 A14 P9
D15 C5

MCUXpresso Pin Config

pin_mux.cのCソースに自分で書き足していってもいいのですが、MCUXpresso Config toolでは、MCUXpresso IDEに既に組み込まれていて、設定した内容もクリック一発でプロジェクトに設定を反映してくれるので、非常に便利です。

昔は、マニュアルのレジスタ設定などを睨んで、コーデイングしたもんですが、今はクリックだけで設定ができてしまうなんて。。。便利すぎます。

必要なピンをクリックして、緑のチェックマークを付けていくだけです。

そして、Pull-upやPull-down設定を、inactiveに設定していきます。Slewレートは、fastを選んでおきます。

コンフィグツールの起動方法は、ちょっと分かりづらい場所にあります。

Config Toolの起動
Config Toolの起動
ピンコンフィグの必要なピンをクリックで選択
ピンコンフィグの必要なピンをクリックで選択
各ピン設定
各ピン設定

プロジェクトへの反映

設定した後は、プロジェクトへクリック一発で反映させることができます。

プロジェクトへの反映
プロジェクトへの反映

EMCドライバーの準備

次に、EMCのドライバーを組み込みます。

プロジェクトの「drivers」フォルダーに「fsl_emc.c(h)」があれば、特別な設定は必要がありません。

組み込まれていなければ、SDKからfsl_emcドライバーを組み込む必要があります。

簡単に、組み込むことができます。

リンカー設定にSDRAM領域を追加

リンカーの設定は、MCUXpresso IDEを使用していれば、非常に簡単に行えます。

このように編集してOKをクリックして完了です。これで、自動的にリンカースクリプトへの記述が完了しています。

初期化設定する

最後に、main関数内でsdramの初期化関数をコールして完了です。

#define SDRAM_BASE_ADDR 0xa0000000
#define SDRAM_SIZE_BYTES (8 * 1024 * 1024)
#define SDRAM_EXAMPLE_DATALEN (SDRAM_SIZE_BYTES / 4)
#define SDRAM_TEST_PATTERN (2)

int main(void)
{
    char ch;
    uint32_t *sdram = (uint32_t*)SDRAM_BASE_ADDR;

    /* Init board hardware. */
    /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
    CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);


    BOARD_InitPins();
    //BOARD_BootClockFROHF48M();
    BOARD_BootClockFROHF96M();
    BOARD_InitSDRAM();
    BOARD_InitDebugConsole();

    if (SDRAM_DataBusCheck(sdram) != kStatus_Success)
       {
           PRINTF("\r\n SDRAM data bus check is failure.\r\n");
       }

       if (SDRAM_AddressBusCheck(sdram, SDRAM_SIZE_BYTES) != kStatus_Success)
       {
           PRINTF("\r\n SDRAM address bus check is failure.\r\n");
       }
       if (SDRAM_AddressBusCheck(sdram, SDRAM_SIZE_BYTES) != kStatus_Success)
          {
              PRINTF("\r\n SDRAM address bus check is failure.\r\n");
          }
    PRINTF("hello world.\r\n");

    while (1)
    {
        ch = GETCHAR();
        PUTCHAR(ch);
    }
}
注意点
__attribute__ を使って変数(.bss)をSDRAMに配置しようとすると、スタートアップ時に初期化しようとしてSDRAMへアクセスしてしまいます。 SDRAMのセットアップは終わっていないので、当然アクセス出来ずhardfaultしてしまうか、さもなくばmainにまで飛んできません。 その時は、.noinit領域に配置することも考えてみましょう。