MCI(Multimedai Card Interface)を使ってのSDカードへのアクセスの実験の続きです。ATMELの提供するソフトウェア・パッケージのコード(Basic SD Card)にちょっと手を入れたところ、初期化はすぐに動作の確認がとれました。トレースのレベルをデバッグ(5)に上げておくと、次のようにSDカードに対して発行しているコマンドを確認することができます。
ところが、続いてブロックの読み出しを試してみると、これがちゃんと動いてくれません。MCIのステータスとしては、読み出しコマンド(CMD18)が正常終了しているように見えるのですが、実際にはデータが読みこまれないのです。CMD18の代わりにCMD17を使って1ブロックだけ読んでみても、やはりデータが読み込まれません。ATMELが提供しているコードなので動かないわけはないと思われますが、念のためにコードを自分で追ってみても怪しげな部分は見つかりません。
ソフト的におかしいところがなければ、原因はハード側かもしれないと考え、データシートのErattaを確認してみるとMCIをPDCモードでDMAする場合のバグについての記述があります。提供されているコードはPDCを使ってDMAしているので、まさしくバグが発生する場合に該当するのですが、その対処は施されていないようです。さっそく、対処のための変更を入れてみたのですが、それでもまだちゃんとデータが読み込めません。PDCのレジスタを読み出してDMA転送先アドレス(MCI_RPR)と残りバイト数(MCI_RCR)を確認してみると、読み出しコマンド(CMD18)の実行後には変化していますので、PDCとしては正常にDMAができているかのように見えます。まったく不思議な症状に見えて、まるまる1日ハマリましたがようやくと原因がわかりました。
原因は読み出したデータを格納するバッファのアドレス境界でした。バッファはunsigned char[] でとっていましたが、この配列が16bit/2バイト境界に配置されていました。一方、MCIによる読み込み/書き込みは常に32bit/4バイト単位でおこなわれるようになっています。PDCによるDMAの際も32bit単位で行われるのであれば、バッファも4バイト境界にアラインする必要があるのではないかと考え、バッファの宣言に __attribute__((aligned(32))) を追加してやると、ちゃんと読み出せました!! 普通のメモリアクセスであれば、data abortのトラップがかかるようなアクセスでも、PDCによるDMAの場合には、DMA転送がカラ振りに終わるだけで例外は発生しないということのようです。
下図は、セクタ0を読み出してダンプしてみたところです。
ところが、続いてブロックの読み出しを試してみると、これがちゃんと動いてくれません。MCIのステータスとしては、読み出しコマンド(CMD18)が正常終了しているように見えるのですが、実際にはデータが読みこまれないのです。CMD18の代わりにCMD17を使って1ブロックだけ読んでみても、やはりデータが読み込まれません。ATMELが提供しているコードなので動かないわけはないと思われますが、念のためにコードを自分で追ってみても怪しげな部分は見つかりません。
ソフト的におかしいところがなければ、原因はハード側かもしれないと考え、データシートのErattaを確認してみるとMCIをPDCモードでDMAする場合のバグについての記述があります。提供されているコードはPDCを使ってDMAしているので、まさしくバグが発生する場合に該当するのですが、その対処は施されていないようです。さっそく、対処のための変更を入れてみたのですが、それでもまだちゃんとデータが読み込めません。PDCのレジスタを読み出してDMA転送先アドレス(MCI_RPR)と残りバイト数(MCI_RCR)を確認してみると、読み出しコマンド(CMD18)の実行後には変化していますので、PDCとしては正常にDMAができているかのように見えます。まったく不思議な症状に見えて、まるまる1日ハマリましたがようやくと原因がわかりました。
原因は読み出したデータを格納するバッファのアドレス境界でした。バッファはunsigned char[] でとっていましたが、この配列が16bit/2バイト境界に配置されていました。一方、MCIによる読み込み/書き込みは常に32bit/4バイト単位でおこなわれるようになっています。PDCによるDMAの際も32bit単位で行われるのであれば、バッファも4バイト境界にアラインする必要があるのではないかと考え、バッファの宣言に __attribute__((aligned(32))) を追加してやると、ちゃんと読み出せました!! 普通のメモリアクセスであれば、data abortのトラップがかかるようなアクセスでも、PDCによるDMAの場合には、DMA転送がカラ振りに終わるだけで例外は発生しないということのようです。
下図は、セクタ0を読み出してダンプしてみたところです。