🛠️
SDカードのSPIモードの初期化に関する諸々
SDカードのSPIモードの実装を、自分で書いてみて試行錯誤した点のまとめです。多くは、正式な仕様によるものではなく、あくまで、実験に基づいた情報です。
SDカードのSPIモード
SDカードは一般的に4ビット幅のバス接続で使用されますが、マイコンなどのリソースの少ないホスト向けに、4線式のSPIでアクセスするモードとして提供されています。なお、SDUC(2TB以上)ではサポートされません。
SPIモードの初期化
SDカードの仕様書に書いてある通りに行えば問題ないはず、ですが、わりと嵌ります。特に、製品によって相性問題が生じやすいです。ここでは、電源ONからACMD41を実行するまでの諸々についてとりあげます。基本的な流れは以下の図のようになります。
ダミークロック
仕様では、74クロック以上と規定されています。8ビットのSPIで74クロックなんて半端な数は送れないので、80クロックで問題ありません。
ダミークロックを送るときは、CSとDI両方ともHレベルであることが必須条件です。なお、サンプリングタイミング(クロックが立ち上がる瞬間)以外でDIがLレベルになることには問題がない模様です。
CMD0が異常な値を返す場合
- 電源ONからダミークロックまでの時間が短すぎる可能性。最低1ms待つように規定されています。
- ダミークロックが正しく送れていない可能性。詳細は前項を参照。
- DOのプルアップ忘れ。仕様上、DOは10kΩでプルアップする必要があります。
プルアップしていない場合、エラーコード(0x3fなど)を返すカードが結構ありますが、2回繰り返すとうまくいく場合もあります。
CMD0が失敗するけど、2回目以降は成功する場合
- DOのプルアップ忘れ。前項を参照。
CMD8が異常な値を返す場合
- クロック(SCLK)の立ち上がり、立下り時間が許容範囲外の可能性。この場合、ほかのコマンドは実行できるのに、CMD8だけ失敗し、SDカードが特徴的なバイト列(例えば 00 00 00 02 1F)を返すという、不可解な現象が起きます。
仕様上、クロックの立ち上がり、立下り時間は10ns以下と規定されていて、これは、クロックの周波数やDIとのタイミングには関係ありません。どんなにタイミング的に余裕があってもダメです。そして何故か、CMD8を実行するときだけ、この条件がシビアに影響するようです。
実験では、100kHzのクロックにおいて、100nsでは1割、300nsでは3割、500nsでは9割のカードで、CMD8が失敗しました。電圧レベル変換回路を介して接続する場合や、マイコンのポートの出力ドライブ強度が低い場合は要注意です。 - 稀に、コマンドの前に1バイト分のダミー読み出しが必要なカードがあります。この場合、先頭バイトの最上位ビットが立った、特徴的なバイト列(例えば C1 7F FF FF FF)を返します。
コマンドを送る前に、Busy状態のチェックを兼ねて、1バイトの0xffを送るようにすれば、この問題を回避できます。(実際にBusyであるか否かに関係なく)
ACMD41が終わらない場合
- 根気良く回しましょう。仕様上、最大で1秒と規定されています。実験では、最大250msかかるカードがありました。
まとめ
以上の実験を踏まえ、以下の点を考慮することで、サンプルとして使用したSDカード(SD/SDHC/SDXC)すべてにおいて、正常にSPIモードの初期化ができるようになりました。
- DOに10kΩのプルアップをつけること。
- 電源ONから最低1ms待つこと。
- クロック(SCLK)の立ち上がり、立下り時間を10ns以下にすること。5V回路から抵抗で分圧して接続、はダメ。
- ダミークロックを送るときはCSとDIをHレベルに保つこと。
- CMD8、ACMD41などコマンドを送る前に、1バイトのダミー読み出し(0xffを送る)をすること。
- ACMD41のループは最大1秒まで待つこと。
ところで・・・
SDUCがSPIモード非対応なのは仕様ですが、それ以外でもSPIモード非対応のカードが存在する、という噂を時々聞きます。そういう実物を見たことがないのですが、どなたか、実物を確認した方いますか?
Discussion