FPGAでSDカードと通信してみる。(4)
というわけで前回たしかBPBまで読んだはずだが何を思ったかここで回路に新たなコマンドを追加し、FAT32(というかSDHCカード?)に対応させた。
やったことはCMD0を送った後にCMD8を送るだけ。けどCMD8はCRCが必要なのでそこだけ注意が必要。これは固定値にしてしまって0x48000001AA87を送信する。そしてR7が返ってくるので受信したらACMD41を送って0x00が帰ってくると初期化が完了する。ここらへんは調べれば出てくるので説明は割愛。
そしてSDカードを8GBのものに交換し実験を再開した。
とりあえずまたセクタ0を読んでBPBのセクタナンバを調べたところ0x2000だったのでそこを読んでみる。
とりあえず必要なデータのところだけ。
- EB 00 90
- 20 20 20 20 20 20 20 20
- 00 02 -----------------セクタバイト数
- 40 ----------------------クラスタのセクタ数
- FC 10 -----------------予約セクタの数(BPBが0x2000でそこから0x10FC足した0x30FCがFAT1)
- 02 ----------------------FATの数
- 00 00 00 00 F8 00 00 3F 00 FF 00
- 00 20 00 00 ---------MBRからBPBまでのセクタ数
- 00 58 F0 00 ---------パーティションブロックのセクタ数
- 82 07 00 00 ---------FATエリアのセクタ数0x0782
これらの内容から各開始セクタを計算する。
FAT1 0x30FC
FAT2 0x30FC + 0x0782 = 0x387E
DIR 0x387E + 0x0782 = 0x4000
ここでSDカードに保存しているデータを確認
SDカードの直下にHELLO.TXTというファイルを作成し、そこに
ABCDEFG
1234
と書き込んだ。
ではまずDIR(クラスタ2)を見てみる。
1ファイルにつき32byteが割り当てられていて目的のHELLO.TXTは234byte目から
48 45 4C 4C 4F 20 20 20 54 58 54 20 00 BC 72 4B ------ファイル名HELLO TXT
2E 4B 2F 4B 00 00 88 4B 2E 4B 05 00 1C 00 00 00 ------開始クラスタ0x00000005
クラスタ5のアドレスを計算すると0x40C0になったので次にそこを読むと
なんかそれっぽいのが出てきた。
これを文字コードで受信すると
きた!!!
と、いうわけでFPGAでSDカードからファイルが読めた。
今回作成したモジュールをもう少し設計し直して簡単にSDへアクセスできるようにしていきたい。
ここまでの作業で実際の作業時間で考えると一週間も使っていないので結構簡単にアクセスできることが分かった。そしてマイコンでもこれと同じアルゴリズムを実装してみたが明らかにFPGAで通信した方がデータが早く持ってこれる。
が、ChaNさんのサイトが無かったら全く手付かずだっただろう。。。感謝
ひとまずFPGAとSDの通信についてはここまで。
結構雑に書いたので間違いだらけかもしれないがそこは察してほしい。
次はどんなネタで進めていこうか。。。
また何か思いついたら更新されるかもしれない。
FPGAでSDカードと通信してみる。(3)
すこし日にちが経ってしまったが読み込んだデータの解析を再開した。
SDカードから512バイト読み出してその内容を何かしらの方法で確認しなければいけないのでとりあえずUARTで吐き出すことにした。データの保持は最初SRAMにしようと思ったが512バイトなので4096bitのレジスタに保持しておいた方が楽という結論になりSDから読んだデータをレジスタに保持し、読み終わったらUARTでPCに送るという方法にした。
とりあえずセクタ0を読んでみたデータがこれである。
セクタ0にはパーテーショニングの情報がかかれているらしく446byte目から16byte分がエントリ1の区画テーブルらしい。順番に見てみる
- 00 ------------------------ブート不可
- 02 06 00
- 06 ------------------------FAT16
- 04 C4 C4
- 83 00 00 00 -----------パーティションの開始物理セクタ番号
- 7D 4F 3B 00 ----------パーティションのサイズ
これでちゃんとFAT16でフォーマットされていることが分かった。
次に開始セクタの番号だがデータはリトルエンディアンなので開始セクタは83になる。
83を読んでみた。
これを文字表示にしてみると
NO NAME FAT16という文字が読めた。
このセクタはBPB(BIOS Parameter Block)と言うらしくFATボリュームのパラメータが記録されているらしい。
とりあえず疲れたのでここまで切り上げる。
おそらく次の記事ではSDに保存されたファイルが読めていることだろう(希望的観測)
FPGAでSDカードと通信してみる。(2)
前回SPIの回路が出来たので今回は初期化の動作をしてみる。
といってももうSPIの送受信が完成してしまっているので後は決められたコマンドをひたすら送っていくだけなので何も難しいことはなかった。(SPIの回路のバグになかなか気づけずそこに少し時間を取られた)
流れとしてはまずCSをHighにしてからクロックを74クロック以上入れる。
これはSPIのモジュールで0xFFを10回送信している。
次にCSをLowにしてCMD0(SPIモードに移行させるためのコマンド)を送信する。コマンドは6バイト(48bit)で転送される。
下位8bitはCRCチェックの値が入るがSPIモードでは必要ない。しかし、CMD0を送信するときだけはSPIモードではないのでCRCの値もちゃんと入れる必要がある。
CMD0のCRCは0x95なので0x400000000095を上位バイトから順に送る。
これで0x01が返信されれば移行準備が出来たので次にCMD1を送信して初期化を開始させる。ちなみにCMD1は0x4100000000FF。CMD1は0x00が返信されるまで繰り返す。
0x00が来たら初期化完了。
このへんの話はここのサイトを熟読したほうが良い。
FPGAで動作をさせたが7セグなどに返信された値を表示しても画像では伝わりにくいのでとりあえずロジアナで波形を観測してみた。
まずこれが80クロック入れている部分の信号
そしてこっちがCMD0を送信している部分。
ちゃんと0x400000000095を送った後に0x00が返信されているのが分かる。
シミュレーションを通しているので動くだろうというのは分かってはいたが実際に動くとなんか嬉しい。ダラダラと作業していたのもあるが初期化までの動作に2日かかってしまったので早くデータの読み出しをしてアウトプットするというところまで持っていきたい。
ちなみに開発ボードはDE0CVを使って開発している。
本当はSDコネクタの接続状態スイッチなどで初期化動作などをさせたいのだが回路図を見てもつながってそうなところがない。実はつながっているピンがあるなどの情報があれば欲しいところだ。
次はデータの読み出しや情報が読めたら記事にしておきたい。
FPGAでSDカードと通信してみる。(1)
FPGAで液晶を制御していたらデータ読み出し用のROMが欲しかったのでSDカードのコントローラを作ってみることにした。
高校時代にマイコンでSDカードにアクセスしたことはあったがライブラリを使っていたので実際にどういう動作が行われているのかはあまり理解していなかった。
とりあえずChaNさんのサイトを見てみたらどうも簡単な方法だとSPIでデータのやり取りをしているっぽかったのでまずSPIの回路を設計した。
とりあえず適当に回路を書いてシミュレーションをしてみる。
SPIで0x95を送っているシミュレーションだがうまく動いてるっぽい。
勢いで受信側の動作まで作った。
これをSDカードの初期化コマンドのデータにして流せば多分初期化まではできる。(というかできた)
SDの初期化については次の記事にしよう。