STM32マイコンのペリフェラル機能の1つ、QSPIがあります。今回はQSPIでNOR Flashではなく、SRAM(IS62WVS5128FB)を読み書きする方法を紹介します。データ削除等が必要なNOR FlashよりもSRAMは処理がシンプルで、読み書きのみです。
SPIは4つの信号線 (CS:Cable Select、SCK:Serial Clock、MISO:Master In Slave Out、MOSI:Master Out Slave In) で構成されています。一方、QSPIは6つの信号線(CS、SIO0、SIO1、SIO2、SIO3、SCK)で構成されています。SPIはMISO、MOSIの2本の通信バスに対して、QSPIはSIO0、SIO1、SIO2、SIO3の4本の通信バスに拡張されています。そのため、1クロックで送受信できるデータが2倍となり、より高速に通信できるようになっています。QSPIは主にNOR Flash、SRAM等のメモリ向けのインタフェースとして多く採用されています。
QSPI通信はSPI通信と互換があり、多くのQSPI対応デバイスは起動直後はSPIデバイスとして動作します。初期化や設定が完了してからQSPIモードに切り替えて高速に通信します。また、SPIのMISO、MOSIの2本のバスは通信方向が固定されていますが、QSPIは通信状態に応じて通信方向が変化します。通信状態をやり取りするためにSPIと異なり、インストラクションを送ってからアドレスやデータのやり取りを行います。多くの場合はインストラクション+アドレス+データの3つで構成されています。
STM32マイコンのHALライブラリでは、HAL_QSPI_Commandでインストラクション+アドレス+データ設定を行い、送信の場合のデータはHAL_QSPI_Transmitで送信し、受信の場合はHAL_QSPI_Receiveで受信します。
具体的にデータをメモリから読み込む場合は下記のような流れで設定します。
QSPI_CommandTypeDef sCommand;
HAL_StatusTypeDef res=0;
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;//インストラクションのバス数 1~4
sCommand.Instruction = READ_CMD;//インストラクション
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;//アドレスのバス数 1~4
sCommand.Address = address;//アドレス
sCommand.AddressSize = QSPI_ADDRESS_24_BITS;//アドレス長
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;//オルタネイトバイト(拡張用、通常は未使用)
sCommand.DataMode = QSPI_DATA_1_LINE;//データのバス数 1~4
sCommand.DummyCycles = 0;//アドレスを設定してからデータの送受信までに待機が必要な場合に設定
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;//DDRモード設定
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;//DDRモード時遅延設定
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;//コマンドモード
sCommand.NbData = read_length;//データ長さ
HAL_StatusTypeDef res=0;
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;//インストラクションのバス数 1~4
sCommand.Instruction = READ_CMD;//インストラクション
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;//アドレスのバス数 1~4
sCommand.Address = address;//アドレス
sCommand.AddressSize = QSPI_ADDRESS_24_BITS;//アドレス長
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;//オルタネイトバイト(拡張用、通常は未使用)
sCommand.DataMode = QSPI_DATA_1_LINE;//データのバス数 1~4
sCommand.DummyCycles = 0;//アドレスを設定してからデータの送受信までに待機が必要な場合に設定
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;//DDRモード設定
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;//DDRモード時遅延設定
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;//コマンドモード
sCommand.NbData = read_length;//データ長さ
res+=HAL_QSPI_Command(&QSPIHandle, &sCommand, 0xFFF);//インストラクション+アドレス+データ設定
res+=HAL_QSPI_Receive(&QSPIHandle, read_data, 0xFFF);//受信処理
res+=HAL_QSPI_Receive(&QSPIHandle, read_data, 0xFFF);//受信処理
上記の例では一般的なインダイレクトモードの例を紹介しました。STM32マイコンのQSPIではインダイレクトモード、ステータスポーリングモード、メモリマップモードの3種類あります。
インダイレクトモード:インストラクション+アドレス+データで送受信する一般的処理モードです。
ステータスポーリングモード:メモリのフォーマット等、時間を要する処理の場合に処理の完了有無を定期的に自動で確認することができます。
メモリマップモード:アドレスで直接、データを読み込み可能なモードです。ポイントは読み込み専用で書き込み不可。フォントや画像といった固定のデータを読み出す場合に向いています。
SRAM(IS62WVS5128FB)はDDRモードに対応していませんが、DDRモードに対応しているメモリの場合、クロックの立上がりと立下りの両方でデータのやり取りができるため、さらに倍のデータをやり取りできます。今回は読み込みのみ紹介しましたが、SRAM(IS62WVS5128FB)とQSPIで読み書きする全体コードはこちらにアップしました。
最近のSTM32L5等ではQSPIの代わりにOctalSPIが搭載されています。OctalSPIはバスが8本となりさらに高速に通信することが可能です。残念ながらQSPIのメモリマップモードは読み込み専用ですが、OctalSPIのメモリマップモードはFMCやFSMCのメモリマップモード同様に読み書き可能です。OctalSPIも今後紹介したいと思います。