LogiClover開発ブログ

LogiCloverは、趣味でFPGAを使った電子工作をしているサークルです。主に開発中の出来事や技術メモを投稿します

SPI Flashの使い方

組み込み工作でデータを格納したいときはFlashメモリを使うと便利です。

Flashメモリと言っても様々な種類があり、ざっくり以下のような分類ができます。

各社*1開発を行っており、微妙な違いで様々な製品があります。 例外もありますが型番の多くがメーカー名+数字で構成されておりカッコ内の示してあります。

  • NAND Flash
    • Parallel (_29)
      • Address/Data組み合わせのコマンド方式
  • NOR Flash
    • Parallel (_29)
      • Address/Data組み合わせのコマンド方式
    • Serial
      • SPI/QSPI/DSPI (_25)
      • I2C (_24)

大容量のNAND Flashはお馴染みのUSBメモリなど、本当に大容量なデータの格納に使われています。 中・小規模なその他のFlashはプログラムの格納(外付けの場合)やFPGAのコンフィグデータの格納、ログデータやリソースの格納などに使われています。

LogiCloverでは

  • FPGA(Xilinx社 Spartan6)のコンフィグデータの格納
  • マイコン(NXP社 LPC4330)を使ったボードのプログラム格納先
  • SPDIF出力する音声データの格納先

などで使用しました。

f:id:logiclover:20170402023957j:plain

FPGAのコンフィグROMをPCから書き換える実験。

今回はSPIで制御するSerial NOR Flash(以下SPI Flash)の最低限の使い方について、FPGAのコンフィグで使用しているMicron社M25P40を例に説明します。 用意されているコマンドの種類やニーモニックが異なるだけで、基本的な使い方は各社同じです。

パッケージ

殆どのSPI FlashはSOIC8かSOIC16のようです。(1.27mmピッチ)

ピンアサイン

SOIC8のピンアサインは以下のとおりです (M25P40は対応していませんが、QSPIも含めた解説もしておきます。)

f:id:logiclover:20170402000153p:plain

ピン名 方向 SPI時 QSPI時
S# 入力 チップセレクト(CS) チップセレクト(CS)
C 入力 クロック入力(SCK) クロック入力(SCK)
DQ0 双方向 データ入力(MOSI) データ線0
DQ1 双方向 データ出力(MISO) データ線1
W#/DQ2 双方向 書き込み保護(使わなければH固定) データ線2
HOLD#/DQ3 双方向 通信一時停止(使わなければH固定) データ線3

SPIで使うときはW#/HOLD#はHigh固定で問題ないです。 QSPI時は帯域を増やすためにこの2つの信号線も通信に使用します。

インターフェース

電圧 : 2.3V ~ 3.6V

バイスによっては1.8Vなど低い電圧までサポートしているものがありますが、5Vはほぼサポートしていないと見ていいでしょう。

もしArduinoの5V I/Oなどから使用する場合は必ずレベル変換してください。

通信周波数 : コマンドと電源電圧による

これがSPI Flashの厄介なところで、殆どのデバイスがコマンドと電源電圧によって最大周波数が異なります。 多くの場合Read命令とRead Fast命令が別れています。

Read Fastはダミーサイクルを挿入する代わりに(コマンドについては後述)最大周波数を上げています。 最近のデバイスでは100MHz超えも当たり前になっています。

M25P40を3.3Vで使った場合、下の表のとおりになります。

条件 周波数[MHz]
Read 33
Read Fast 75
それ以外 75

通信フォーマット

Master側のペリフェラル設定については割愛します。特殊なことは必要ありません。

クロック極性

立ち上がりエッジでキャプチャできるようにしてあれば大丈夫です。

CPHA,CPOLが(0, 0)か(1, 1)

ビットオーダー

MSBファーストで転送します。([D7, D6, D5, D4 … D0]の順に送る。)

送り方

命令によってデータの付け方が異なります。殆どの場合、データシートにまとめた表がだいたいあります。

送る順としては命令 + アドレス + モード + ダミー + データになっています。*2

アドレス、モード、ダミーなどは命令によって省略されるのでデータシートを確認してください。また最近のデバイスではアドレスに32bit指定可能なもの、ダミーサイクル数が指定可能なものなどもあります。

f:id:logiclover:20170402010527p:plain

命令のみの場合

Write Enable, Write Disable, Bulk Erase, Deep Power-down など

命令1byte

例えば書き込み有効化のWrite Enableは、0x06を1byte送れば実行できます。

f:id:logiclover:20170402011235p:plain

ステータス読み出しの場合

Read Identification, Read Status Register, Release from Deep Power-downなど

命令1byte + 読み出すデータ(IO1に出力される)

Masterから送るデータは最初の1byteに命令、あとは適当なダミーデータを送り、IO1のデータを読み取れば大丈夫です。

f:id:logiclover:20170402023207p:plain

データ書き込みの場合

Page Programなど

命令1byte + 読み出しアドレス3byte + 書き込むデータ

指定したアドレスから順にデータを書き込んでいきます。

注意すべき点としては読み出しが一度に全部読み出せるのに対し、書き込みはページ単位(256byte)ごとに処理する必要があります。

f:id:logiclover:20170402012114p:plain

データ読み出しの場合

Read Data Bytes, Read Data Bytes at Higher Speed など

命令1byte + 読み出しアドレス3byte + 読み出されたデータ(IO1に出力される。)

読み出したいデータ分だけ転送バイト数を増やすだけで大丈夫です。

通信速度を上げたい場合、代わりにat Higher Speed命令を送り、アドレスの後1byteは適当なデータを送っておけば大丈夫です。

f:id:logiclover:20170402011553p:plain


制御方法

あとはコマンドをどう使うかだけ確認します。ここまでくれば後は送るだけです。

データ読み出し

Read Data Bytesで読み取りたい長さ分のSPI転送を行えば大丈夫です。

アドレス指定が出来るので任意アドレスのデータを読み出せます。

データ消去

消去命令は全領域消去を行うBulk Eraseと、特定セクター*3の消去を行うSector Eraseがあります。

Erase/Program系の命令他の命令と異なり別のコマンドと組み合わせが必要です。

  • 実行前にWrite Enableを行う必要があります
  • コマンド発行から完了まで時間がかかるためRead Status Registerでステータスを1byte読み出し、最下位ビットのWrite in Progress(WIP)が0になるまで待つ必要があります。

以下にフローを示します。

f:id:logiclover:20170402021200p:plain

データ書き込み

PROGRAM命令を使って書き込み先を指定して書き込みます。

読み出しと異なりデータ長はページごと(M25P40の場合は256byteごと)に行います。

データ消去同様、Write Enableを事前に実行し書き込み後にWIPを待つ必要があります。

これは補足ですが一般的に書き込む前に事前にデータ消去を行います。

既にデータが書かれている場所にもう一度書き込んだ場合に正しく書き込めるかは保証されません。


終わりに

今回はSPI Flashの基本的な使い方についてまとめました。

PCからFlashFPGAのコンフィグを行う実験のまとめになります。

後々需要があればツールは公開予定ですが、ご要望があれば優先度は考えます。

Arduinoでの制御例

2017/08/15 書きました、とりあえず動かしたい方はどうぞ。

logiclover.hatenablog.jp

※ Micron社 M25P40データシートより引用 https://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p40.pdf

*1:2017年4月時点だとCypress/Micron/Macronix/Winbond/ESMT/Microchipなど

*2:モードはM25P40には実装されていない

*3:M25P40の場合 0x10000ごとセクターが別れている