2012年06月08日

使えないSDカード

 PC-6001F に使っているSDカードですが、SDHC は今の所サポートしていません(FAT32に対応するのが面倒くさい)。

 それ以外の最近のSDカードなら大体動くと思うんですが...


 「Silicon Power」社の2G のSDカードは、ナゼか動きません(1G とかは持っていないので不明)。


 ちょっと調べましたが、起動直後の動作が他のSDカードは明らかに違います。

 対処方法が分かれば対応するつもりですが、今のところは避けた方がいいかと思います。


posted by えすび at 23:50| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

2011年10月30日

ファイル選択機能の設計(1)

 CMT からロードをする部分の再設計中です。

 CMT のデータは、〜.p6 フォーマットで SDカードに格納しているとして、このファイルを開いて8049 に読み込ませるだけの作業なんですが...

 実際にエミュレータを使う時になると、ファイルの選択などが必須になってくるかと思います。


 最初の非公開バージョンでは、とりあえず動作確認のために、内蔵ROMとして直接回路に書き込んでいましたが、これだと、ファイルの交換のたびに、Quartus からデータを書き込む必要があります。

 これだとさすがにアレなんで、ファイル選択を作っています。


 いろいろ悩んだ結果、

・SD カードを直接アクセスする部分はハード(今までの設計資産)
・SD カードにコマンドを発行して、アクセスを指示するのはソフト

 という風にしました。


 ソフトとなった時にプロセッサを何にするか、ですが、面倒だったので、T80(Z80)にしました。


 本当はC言語とかで書きたかったんですが、立ち上げるのに時間が掛かりそうなのと、コードサイズを出来るだけ小さくしたかったので、アセンブラ1本で済ませるつもりです。

 アセンブラは、以前にインストールしていた『AS』を使っています。


 久々に Z80 のアセンブラ(機械語?)を使っていますが、慣れないとうまく書けませんねぇ。
 さらにまともなデバッグ環境がないため、デバッグが大変です。

 今は、HDLのシミュレータでデバッグしていますが、実行に時間が掛かるのが難点です。


posted by えすび at 15:00| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

2011年10月07日

SDカード読み出し部の設計(8)

 今までのことから、SDカードからファイルの読み出しを行う回路を作成する。

 HDL では、シーケンサみたいなのはかなり面倒なので、かなり手こずりました。こういうのはプロセッサにやらせるべきですねぇ。

 制限付きで、とりあえずのルーチンを作る。今の所の制限は次の通り。

 ・SDHD はサポートしない
 ・FAT16 のみ対応
 ・1セクタのバイト数が512バイトのみ対応
 ・ルートディレクトリのファイル数が512のみ対応
 ・1クラスタのセクタ数は、16、32、64、のみ対応

 ・ファイルはルートディレクトリに置く必要がある。

 ・今の所、「CGROM60.60」「BASICROM.60」のみしか読まない。
 ・今の所、1クラスタまでのファイルサイズしか読み込めない(FAT にアクセスしない)。


 後半2つは、テープファイルを読み出す必要がありますので、修正するつもりです。


 やーっと出来上がって、SDカードのファイルから、キャラクタROMにデータを転送するのを確認できました。

 とりあえず、SDカード対応の設計は一度中止して、SDRAM周りの設計に移りたいと思います。


posted by えすび at 22:28| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

2011年10月05日

SDカード読み出し部の設計(7)

 SDの読み出しの続き。

10)ファイルの先頭クラスタから読み出す。
10−1)ファイルの先頭クラスタの位置から物理アドレスを計算する。
 →クラスタの先頭は、ルートディレクトリのすぐ後にあります。また、クラスタの先頭番号は#2です。
  (#0は未使用、#1は予約)

  クラスタの論理先頭セクタ番号は、以下の通りです。

  クラスタ論理先頭セクタ番号 = ルートディレクトリの論理セクタ開始番号 + ルートディレクトリのエントリ数×32/1セクタのバイト数

  ルートディレクトリのエントリ数は、BPB の 0x11、0x12、1セクタのバイト数は、BPB の 0x0B、0x0C です。


  結局、ファイルの先頭クラスタの番号から、論理セクタ番号への変換は以下のようになります。

  論理セクタ番号 = (ファイルの先頭クラスタ番号 - 2 )× 1クラスタのセクタ数 + クラスタ論理先頭セクタ番号

  1クラスタのセクタ数は、BPB の 0x0D です。


  これを、物理アドレスに変換して、やっとデータにアクセス出来ます。


  先ほどの「BASICROM.60」を例にすると、ファイルの先頭クラスタ番号は、0x0004 なので、

  論理セクタ番号 = (0x0004 - 2)× 0x20 + (0x1ED + 0x0200 × 32 / 0x0200 ) = 0x24D
  物理セクタ番号 = (0x024D + 0x00F3)× 512 = 0x68000

  となります。ふぅ。


11)ファイルの次のクラスタを読み出す。
11−1)FAT の位置を調べる。
 →1ファイルが1クラスタ以下のサイズの場合は、1クラスタ分を読んで終わりですが、それ以上の場合は、次のクラスタ番号を知る必要があります。

  クラスタ番号が連続していないことがあるので、FAT にアクセスして次のクラスタ番号を調べます。

  FAT の先頭位置は、BPB の 0x0E、0x0F から、先頭論理セクタ番号を読み出し、物理アドレスに変換します。FAT16 なので、16ビット毎に1クラスタのデータが書いています。

  ですので、FAT の先頭2バイトは、クラスタ#0、その次の2バイトはクラスタ#1、・・・、となります。



posted by えすび at 19:47| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

SDカード読み出し部の設計(6)

 SDの読み出しの続き。

 ちなみにこの辺りの情報は、以下を参考にしています。

http://www.geocities.co.jp/SiliconValley-PaloAlto/2038/fat.html
http://www.mars.dti.ne.jp/~m7030/yellow_hos/fat.html


8)論理セクタ#0の読み出す。
8−1)論理セクタの位置を計算する。
 → (セクタ番号+オフセット値)×512 が物理アドレスらしい。

  オフセット値は、7)で読み出した値で、以降のセクタの読み出しは、常に上の式が適用される。

  ちなみに、今回使用したSDカードのオフセット値は、0x000000F3 でした。

8−2)論理セクタ#0を読み出す。
 →読み出しアドレスには、上記の計算式を使います。今回使用したSDカードでは、

  (0 + 0x00F3)×512 = 0x1E600

 になります。この値をそのまま読み出しアドレスに指定して、CMD17 で読み出します。


 論理セクタ#0には、BPB と呼ばれる、さまざまなデータが格納されています。

 ちなみに読み出した結果は、こんな感じ。

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
000 eb 00 90 20 20 20 20 20 20 20 20 00 02 20 01 00
010 02 00 02 00 00 f8 f6 00 3f 00 20 00 f3 00 00 00
020 0d b3 1e 00 80 00 29 31 8f ce 3d 4e 4f 20 4e 41
030 4d 45 20 20 20 20 46 41 54 31 36 20 20 20 00 00

 重要な(というか使用する)パラメータは、次の通り。

 +0x0B,0x0C:1セクタのバイト数
 +0x0D :1クラスタのセクタ数
 +0x0E,0x0F:FATの開始セクタ番号
 +0x10 :FATの数
 +0x11,0x12:ルートディレクトリのエントリ数
 +0x16,0x17:FATが使用しているセクタ数
 +0x3A :0x36 なら FAT16。0x32 なら FAT12。

 通常のファイルにアクセスする時は、クラスタで指定します。

 今回使っているSDカードは、1セクタ数 = 0x0200、1クラスタのセクタ数 = 0x20 なので、
 クラスタのサイズは、0x0200 × 0x20 = 0x4000 (16Kバイト)です。

 1つのファイルがクラスタのサイズより大きい場合は、FAT を辿っていく必要があります。


9)ルートディレクトリを読み出す。
9−1)ルートディレクトリの位置を計算する。
 ここでは、8)で読み出した値を使います。

 ルートディレクトリは、FAT の次に格納されています。

 ルートディレクトリの論理セクタ開始番号 = FATの開始セクタ番号 + FATの数 × FATが使用しているセクタ数
 = 0x0001 + 0x02 × 0x00F6 = 0x1ED

 となります。

 ルートディレクトリ物理セクタ開始番号は

 (ルートディレクトリの論理セクタ開始番号 + オフセット値)×512 = (0x1ED + 0x00F3)× 512 = 0x5C000

 になります。


 今回は、FAT16 のみ対応する事にします。
 また、PC-6001のROMファイルはルートディレクトリに置いているものとします。
 手抜きですが、凝る所ではないと思いますので。


9−2)ルートディレクトリを読み出す。
 →読み出しアドレスは、上記で算出したアドレス(今回は、0x5C000)を使います。

  読み出した結果がこちら。


+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
000 e5 4d 00 50 00 00 00 ff ff ff ff 0f 00 2a ff ff
010 ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff
020 e5 30 00 35 00 5f 00 31 00 30 00 0f 00 2a 32 00
030 34 00 5f 00 37 00 36 00 38 00 00 00 2e 00 42 00
040 e5 35 5f 31 30 32 7e 31 42 4d 50 20 00 7e 52 ba
050 99 35 43 3f 00 00 f5 b3 34 31 02 00 36 04 0c 00
060 41 70 00 72 00 69 00 76 00 61 00 0f 00 67 74 00
070 65 00 00 00 ff ff ff ff ff ff 00 00 ff ff ff ff
080 50 52 49 56 41 54 45 20 20 20 20 10 00 68 33 9d
090 9a 39 9a 39 00 00 33 9d 9a 39 33 00 00 00 00 00
0A0 e5 41 53 49 43 52 4f 4d 36 30 20 20 00 bb a9 71
0B0 43 3f 44 3f 00 00 00 00 21 2a 02 00 00 40 00 00
0C0 43 47 52 4f 4d 36 30 20 36 30 20 20 00 70 c3 71
0D0 43 3f 43 3f 00 00 00 00 21 2a 03 00 00 10 00 00
0E0 52 41 4d 44 4d 59 34 20 42 49 4e 20 18 b8 a1 6c
0F0 44 3f 44 3f 00 00 66 86 42 3f 02 00 00 20 00 00
100 42 41 53 49 43 52 4f 4d 36 30 20 20 00 70 a5 6c
110 44 3f 44 3f 00 00 00 00 21 2a 04 00 00 40 00 00
120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00


 1つのファイルに付き、32バイト単位で情報があります。
 必要な情報は次の通り。

 +0x00 :0x05、0xE5 なら、ファイルが削除されている。0x00 なら、ディレクトリのファイルは終了。
 +0x00-0x0A:ファイル名(8文字+3文字)。短い場合は0x20 で埋める。
 +0x0B :ファイル属性。0x0F の場合は、ロングファイル名。0x20 が通常ファイル。0x10 がディレクトリ。
       下位4ビットは、read only などの属性があるが、省略。
 +0x1A-0x0B:ファイルの先頭クラスタ番号。
 +0x1C-0x1F:ファイル長。


 例えば、0x100〜0x11F に書かれているのは、「BASICROM.60」というファイルで、ファイル長は、0x4000(16Kバイト)。
 先頭クラスタ番号は、0x0004 です。





posted by えすび at 19:46| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

2011年10月04日

SDカード読み出し部の設計(5)

 SDカードが全く動かない件、わかりました。

 SPI でシリアル通信するんですが、

 FPGAボード → SDカード
 SDカード  → FPGAボード

 のそれぞれ1本ずつ信号線があるんですが、これが逆でした...

 そら、動かんわな。


 とりあえず、物理セクタ0からデータが読める所まで確認しました。


posted by えすび at 23:31| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

SDカード読み出し部の設計(4)

 初期化から読み出しまでの回路を作って、実機で試してみる。

 全く動かない。

 ロジアナでは、ちゃんと波形が出ているように見えるんだけど、SDカードから全くデータが返って来ない。

 アクセス周波数を1MHz から100KHz に変更してもダメだった。


 うーん。何が原因なんだろう。


posted by えすび at 22:24| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

SDカード読み出し部の設計(3)

 SDの読み出しの続き。

7)物理セクタ0の読み出して、オフセット値を読み出す。
7−1)CMD17 を送信する。
 → CMD17 は、ブロック読み出しのコマンドで、"0x51" "0x00" "0x00" "0x00" "0x00" "0x00"
   "0x51" に続く4バイトは、読み出しアドレスになります。物理セクタ0(=アドレス0)なので、ALL0を指定。

7−2)SD_DI にデータが来るのを待つ(0xFF 以外の値)。
 → CMD17 に対するレスポンスは、R1
   R1 が 0x00 以外の場合はエラー処理。

7−3)SD_DI にデータが来るのを待つ(0xFF 以外の値)。
 → R1 を受信したちょっと後に、データが送信されてくる。

   受信したデータを先頭からD[0]、D[1]、・・・、とすると

   D[0]     :0xFE(先頭の目印)、もしくはエラーがあった場合に、エラートークン
   D[1]〜D[512] :読み出しデータ
   D[513]、D[514]:CRCデータ(CRC-16)

   エラートークンは、次の通り。

   bit7-5:0固定
   bit4 :カードがロックされている
   bit3 :範囲外
   bit2 :ECC 訂正が出来なかった
   bit1 :カードコントローラのエラー
   bit0 :1固定


   CRCのチェックをしてもいいのだが、面倒なのでチェックしないことにする。

   オフセット値は、D[454]〜D[457] の32ビットで、D[457] が最上位。

7−4)データ受信後、SD_CS ="L" 、SD_DO ="H"、のままで、1バイト分クロックを送信する。
 → これでCMD17 が終了。

 データの読み出し手順に関しては、アドレスの変更のみなので、以下は省略。


8)論理セクタ0の読み出す。
8−1)論理セクタの位置を計算する。
 → (セクタ番号+オフセット値)×512 が物理アドレスらしい。



posted by えすび at 22:24| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

SDカード読み出し部の設計(2)

 SDカードへのアクセスの方法をまとめます。HDL に落とすための自分用のメモですが...

1)電源立ち上げ後、1ms 待つ

 → これは、SDカード読み出し部として、最初に1ms 待つ事にする。


2)SD_CS = "H" 、SD_DO = "H" にして、SD_CLK を74クロック送信する

 → 他のブロックの関係上、1バイト送信を使い、データ0xFF を10バイト送信する。
   SD_CS に関しては、1バイト送信の送付の有無に関わらず、直接出力できるようにしておく。


3)CMD0送信
3−1)SD_CS = "L" にして、1バイト分の時間だけ待つ。この間はSD_CLK は出力しない。

3−2)SD_CS = "L" のままで、CMD0 を送信する。
 → CMD0 は、ソフトウエアリセットのコマンドで、"0x40" "0x00" "0x00" "0x00" "0x00" "0x95"
   最後の1バイトは CRC-7 を計算済。この後、SPI モードに移行するため、CRC-7 は何でもよい。
   また、MSB 先送り。

3−3)SD_CS = "L" のままで、SD_DI にデータが来るのを待つ。
 → 通常は、0xFF で、SDカードがレスポンスを返してくると、0xFF 以外の値が返ってくる。
   CMD0 に対するレスポンスは、R1 。R1 は1バイト長。
   CMD0 に対するレスポンスは、エラーがない通常の場合は、0x01 が返ってくる。

   R1-bit7:0固定
   R1-bit6:パラメータエラー
   R1-bit5:アドレスエラー
   R1-bit4:消去シーケンス中にエラー発生
   R1-bit3:CRCエラー
   R1-bit2:コマンドが違うよエラー
   R1-bit1:消去中にリセットが実行された
   R1-bit0:アイドル状態


3−4)SD_DI がずっと0xFF の場合は、タイムアウトを設けて、タイムアウトエラーなら、読み出しを中止する。
3−5)SD_DI が0x01 以外の場合もエラーとして、読み出しを中止する。

3−6)SD_CS = "L" のままで、1バイト分の時間だけ待つ。この間はSD_CLK は出力しない。
3−7)SD_CS = "H" にして、1バイト分の時間だけ待つ。この間はSD_CLK は出力しない。
3−8)SD_CS = "H" 、SD_DO = "H" にして、SD_CLK を1バイト分送信する。
 →本来はクロックを送信しなくてもいいんですが、こうしないと駄目なSDカードがあるらしいです。

3−9)SD_CS = "H" にして、1バイト分の時間だけ待つ。この間はSD_CLK は出力しない。これでCMD0 が完了。


 SD_CS やSD_CLK の送信方法は、他のコマンドも同様なので、以下は省略。また、タイムアウトやエラーの処理も同様。


4)CMD1送信
4−1)CMD1 を送信する。
 → CMD1 は、初期化のコマンドで、"0x41" "0x00" "0x00" "0x00" "0x00" "0x00"

4−2)SD_DI にデータが来るのを待つ(0xFF 以外の値)。
 → CMD1 に対するレスポンスは、R1。CMD1 に対するレスポンスは、最初、0x01。
   SDカードの準備が完了すると、0x00 になる。

   ブロックの動作としては、0x00、0x01 で正常終了。それ以外の値でエラーとする。

4−3)CMD1 が終了。


5)上記、4)CMD1送信で、0x01 が返ってきたときは、再度CMD1送信を繰り返す。0x00 になったら、次の6)に進む。


6)CMD16送信
6−1)CMD16 を送信する。
 → CMD16 は、アクセスのブロック長で、512バイトを指定する。"0x50" "0x00" "0x00" "0x02" "0x00" "0x00"

  ブロック長は、SDに読み書きする時の単位で、512バイトがデフォルトの事が多いようです。

6−2)SD_DI にデータが来るのを待つ(0xFF 以外の値)。
 → CMD16 に対するレスポンスは、R1。CMD16 に対するレスポンスは、0x00が正常。それ以外はエラーとして処理。

6−3)CMD16 が完了。


 これでやっとSDカードからデータを読み出せます。

 他にもSDカードの情報を読み出して、アクセス周波数を変更したりなどをする必要があるんですが、あまり必要がなさそうなので、今回はパスです。




posted by えすび at 22:23| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする

SDカード読み出し部の設計(1)

 SDカードの読み出し部を設計し始めました。

 SPI でデータのやり取りと書いているので、そんなに難しくないと思ったら...
 アクセス方法などをいろいろ調べても、結構まちまちだったりする。

 参考になりそうなページを総合して読んである程度方向を決めても、詳細なデータがないとちょっとアレかなーと思って、データブックを探しても、全然出てこない。

 どうも正式な資料は、SDカードを作ったメーカから有償で買わないといけないようだ。うーん。


 もうちょっと探すと、こんなのがありました。

 http://alumni.cs.ucr.edu/~amitra/sdcard/ProdManualSDCardv1.9.pdf

 何で、正式に公開しないんでしょうねー。


 やっとSDカードの読み出しに取れかかれます。


posted by えすび at 22:23| Comment(0) | FPGA化:SDカード | このブログの読者になる | 更新情報をチェックする