30前から

FPGAでいろいろ頑張ってみています

FPGAでSDカード内のWAVEファイルを再生する~その2

”SDカードをSPIモードにするまでのフローチャートを見てみる”

http://elm-chan.org/docs/mmc/gfx1/sdinit.png
引用元:http://elm-chan.org/docs/mmc/gfx1/sdinit.png:image=http://elm-chan.org/docs/mmc/gfx1/sdinit.png

1)ダミークロック送信
電源を入れた後1ms以上待ち、74クロック以上のダミークロックを送る

2)CMD0の送信(MMC・リセット)
この時点ではSDモードの為、CRC必須

3)CMD8の送信(電源電圧の確認).
動作電圧をサポートしているか、ファイルシステムのバージョンチェック.
19~16bitで対応電圧を入れる"0001":2.7~3.6Vで、その他は未定義or予約.
15~8bitでチェックパターン"10101010"を推奨.
以上より、"0x48 000001AA 87"がCMD8.
レスポンスR7を確認.下12bitが"0x1AA"で帰ってきていればOK.


4)ACMD41の送信(SDカード初期化)
ACMDはアプリケーションスペシフィックコマンドの略.
CMD55を送信後にR1を受け取った後、CMD41を送信
CMD55:0x77 0000 0000 65
CMD44:0x69 4000 0000 77
下8bitはCCRで、CMD8後なので実際は不要.FFでもOK
CMD44の38bit目はSDHC(SD ハイキャパシティ)を有効にするビット

ACMD41で帰ってくるR3の38bit目がCCS(カードキャパシティステータス)のレスポンスビット.
CCSが1ならSDXC,SDHC,0なら2GByte以下のSDカードとわかる.


5)CMD9の送信
SDカードからの情報を読み書きする前に、セクタサイズ、SD容量などの必要情報(CSD)を調べ、
SPIモードへのイニシャル操作完了とする.
レスポンス(CSD情報)は、8byteで構成されている.
詳細は下記リンク.

”CSDについて”

ここでは必要と思われる項目のみ抜粋.

レジスタ 役割 SD(SC)bit位置 SDHCbit位置
READ_BL_LEN セクタサイズ 83~80 83~80
C_SIZE 容量計算用の係数 73~62 69~48
C_SIZE_MULT 容量計算用の係数 49~47 無し
SD(SC)の容量計算方法

カード容量 = セクタ数(BLOCKNR) × セクタサイズ(BLOCK_LN)
セクタ数(BLOCKNR) = (C_SIZE+1)×MULT
MULT = 2^(C_SIZE_MULT+2)
セクタサイズ(BLOCK_LN) = 2^(READ_BL_LEN)
以上より

SD(SC)カード容量 = (C_SIZE+1)×2^(C_SIZE_MULT+2) × 2^(READ_BL_LEN)
SDXCの容量計算方法

カード容量 = セクタ数(BLOCKNR) × セクタサイズ(BLOCK_LN)
セクタ数(BLOCKNR) = (C_SIZE+1)
セクタサイズ(BLOCK_LN) = 2^(READ_BL_LEN)

SDHCカード容量 = (C_SIZE+1) × 2^(READ_BL_LEN)
CSD内のERASE SECTORサイズとは

削除する際のセクタサイズ.ちなみREAD_BL_LENの計算方法と異なる"0"で512byte
読み込み(READ_BL_LN)と異なる場合がある??

○参考文献
http://bluefish.orz.hm/sdoc/j203536_hb288032mm1.pdf:9ページ目にCSDレスポンスの一覧


”コマンド(CMD)とレスポンスの成り立ち”

コマンド一覧

初期化に使用するコマンドのみ抜粋

コマンドインデックス 引数 応答 省略形 役割
CMD0 00 00 00 00 R1 GO_IDLE_STATE ソフトウェアリセット
ACMD41 40 00 00 00 R1※1 APP_SEND_OP_COND SDカード初期化
CMD8 00 00 01 AA R7 SEND_IF_COND 電源電圧の確認
CMD9 00 00 00 00 R1 SEND_CSD CSD読み出し
CMD55 00 00 00 00 R1 APP_CMD アプリケーションコマンド

※1.SPIモードではR1,SDモードではR3

コマンド構成

ホスト(マイコンなど)から送信するデータ.6Byteから構成されている.
スタートbit(1bit) + トランスミッションbit(1bit) + CMD(6bit) + 引数(4Byte) + CRC(7bit) + ストップbit(1bit)

47 46 45~40 39~8 7~1 0
0 1 x(CMD) x(引数) x(CRC) 1

47:スタートbit
46:トランスミッションbit(ホスト→カード:"1",カード→ホスト:"0")
45~40:CMD.CMD41であれば"101001"
39~8:引数
7~1:CRC-7
0:ストップbit

レスポンス構成

SDカードからの応答.対応するレスポンスによって、データ長も異なる.

○R1(1Byte)
エラーチェックのレスポンス.0x00でエラー無し

7 6 5 4 3 2 1 0
0 x x x x x x x

7:0
6:Parameter error(引数エラー)
5:Address error(アドレスエラー)
4:Erase sequence error(イレース中にエラー)
3:Communication CRC error(CRCがエラー)
2:Illegal command(コマンドが正しくない)
1:Erase Reset(イレース前のエラー)
0:In idle state(カードがアイドル状態.初期化中など)


○R3(5Byte)
R1 + OCR(4Byte).SDモードの場合、ACMD41のレスポンスとなる.
もしくはCMD58によって取得可能.CRはSDカード電源電圧を示す.

文献によって、5Byte、6Byteと異なる.システムVerで異なる?(後で調べる)


○R7(5Byte)
R1 + 4Byte.R7
チェックパターンは、CMD8で設定したチェックパターンがそのまま返ってくる.
対応電圧もCMD8で送信する0x01が返ってくればOK.

39~32 31~28 27~12 11~8 7~0
R1 CMDバージョン reserve 対応電圧 チェックパターン


○参考文献
http://elm-chan.org/docs/mmc/mmc.html
SDカードの構造と内部レジスタ(その1) | ミームス(MEMEs)のサポートページ
SDカードの初期化について - C・C++ 解決済 | 教えて!goo
SDカードを使ってみよう
SDカード


CRC-7の計算方法”

MMC/SDカードはCRC-7を使用.
送信側と受信側で同じ計算を行い、合っていればデータに問題がないと判定.

計算方法は、先頭の"1"のビットに揃えて、CRC多項式のXORを取っていく.
SDカードで使用するCRC-7多項式:x^7 + x^3 + x^0 = 1000 1001
計算はパリティ分のビットも入れた47bit分で計算.(ストップビットは除く)

Cプログラムでの計算例は多数載っていますが、
実際に計算過程は載っていなくいまいちピンと来なかったので、一度手計算してみました.

下記CMD0の計算

CMD0:0x40 00 00 00 00, CRC[7:0],STOPbit(1) 
CRC-7多項式:x^7 + x^3 + x^0 = 1000 1001

	0100 0000  0000 0000  0000 0000  0000 0000  0000 0000 0000 000
XOR)	0100 0100  1000 0000  0000 0000  0000 0000  0000 0000 0000 000

	      10  0100 00000  0000 0000  0000 0000  0000 0000 0000 000
XOR)	      10  0010 01000  0000 0000  0000 0000  0000 0000 0000 000

	           1100 1000  0000 0000  0000 0000  0000 0000 0000 000
XOR)        	   1000 1001  0000 0000  0000 0000  0000 0000 0000 000

	            100 0001  0000 0000  0000 0000  0000 0000 0000 000
XOR)        	    100 0100  1000 0000  0000 0000  0000 0000 0000 000
	
        	         101  1000 0000  0000 0000  0000 0000 0000 000
XOR)                	 100  0100 1000  0000 0000  0000 0000 0000 000

	                   1  1100 1000  0000 0000  0000 0000 0000 000
XOR)        	           1  0001 0010  0000 0000  0000 0000 0000 000

	                      1101 1010  0000 0000  0000 0000 0000 000
XOR)        	              1000 1001  0000 0000  0000 0000 0000 000

	                       101 0011  0000 0000  0000 0000 0000 000
XOR)        	               100 0100  1000 0000  0000 0000 0000 000

	                         1 0111  1000 0000  0000 0000 0000 000
XOR)        	                 1 0001  0010 0000  0000 0000 0000 000

	                            110  1010 0000  0000 0000 0000 000
XOR)        	                    100  0100 1000  0000 0000 0000 000

	                             10  1110 1000  0000 0000 0000 000
XOR)        	                     10  0010 0100  0000 0000 0000 000

	                                 1100 1100  0000 0000 0000 000
XOR)        	                         1000 1001  0000 0000 0000 000

	                                  100 0101  0000 0000 0000 000
XOR)        	                          100 0100  1000 0000 0000 000

	                                         1  1000 0000 0000 000
XOR)        	                                 1  0001 0010 0000 000

	                                            1001 0010 0000 000
XOR)        	                                    1000 1001 0000 000

	                                              1 1011  0000 000
XOR)        	                                      1 0001  0010 000

	                                                1010  0010 000
XOR)        	                                        1000  1001 000

	                                                   10 1011 000
XOR)        	                                           10 0010 010

	                                                 CRC= 1001 010(1)
							 CRC= 0x95


下記リンクを参考に,Cプログラムの復習がてら作りました.


*****************************************************************************************

プログラム
CMD用CRCデータ計算(Stopbit込み)

*****************************************************************************************
#include<stdio.h>

char crc7(char d[6]) {
	int crc, crc_prev;
	int i,j;
	crc = d[0];
	for(i=1; i<6; i++) {
		for(j=7; j>=0; j--) {
			crc <<= 1;				//左へ1bitシフト
			crc_prev = crc;				//1bitシフトしたデータをコピー
			if (i<5) crc |= (d[i]>>j) & 1;	//1bitシフトさせたデータへ次のデータを入れ込む(&1で)
			if (crc & 0x80) { crc ^= 0x89; }	//先頭bitが1の場合、(1000 1001)をXOR演算
		}
	}
	return crc_prev | 1;					//Stopbitを入れ込む
}

int main(void)
{
	char data[6];
	char c;
		printf("CRCを計算する値を16進数で入力(CRCを除く1byte毎にEnter 5byte入力)\n");
		//scanf("%x,%x,%x,%x,%x\n", &data[0],&data[1],&data[2],&data[3],&data[4]);
		scanf("%x\n", &data[0]);
		scanf("%x\n", &data[1]);
		scanf("%x\n", &data[2]);
		scanf("%x\n", &data[3]);
		scanf("%x\n", &data[4]);
		
		printf("入力データ=%02x %02x %02x %02x %02x\n", data[0] & 0x000000FF,data[1] & 0x000000FF,data[2] & 0x000000FF,data[3] & 0x000000FF,data[4] & 0x000000FF);
		
		c = crc7(data);
		printf("CRC = %02xです\n",c & 0x000000FF);//

	return 0;
}

○参考文献
SDのCRC7計算ルーチン - nabeの雑記帳
wishid.hatenablog.com
CRC ‐ 通信用語の基礎知識

FPGAでSDカード内のWAVEファイルを再生する~その1

”SDカードの種類とモード”

SD,SDHC,SDXCの違い
SD種類 容量 ファイルシステム ファイルシステム規定   
SD(SC) ≦2048MB FAT12/FAT16 V1.01
SDHC 2048MB<,≦32768MB FAT32 V2.00
SDXC 32768MB<,≦2048GB exFAT V3.00



FAT種類と容量の関係

FATとは"File allocation Tabel"の略.
ファイルの保存位置を示した地図の役割を持つ、FATと呼ぶテーブルを持ったシステムの事.
この”地図”は"クラスタ"と呼ばれる単位で管理されていており、地図にはクラスタ毎のアドレスが書いてある.

FAT16とは"クラスタ"を16bitで管理すること.FAT32であれば32bitで管理している.

更に"クラスタ"とは,最小データ単位のセクタを持っている.一般的に1セクタ512byte.
(もっと多いシステムもある?)
1クラスタが持てるセクタ量は、変更できるが、それぞれのファイルシステムで、管理できるクラスタ数は決まってる。
その為、大容量の記憶媒体を使用する際は、適したファイルシステムを選択していないと使用できない領域を作ることになる.

また、1クラスタ単位でデータは管理されている為、小さなファイルを保存しても、1クラスタ分の容量し無駄を作ることになる.
いずれも適切なファイルシステムを選択することが大事.

○参考文献
File Allocation Table - Wikipedia
http://elm-chan.org/docs/fat.html
https://msdn.microsoft.com/en-us/windows/hardware/gg463080.aspx


SDモードとSPIモード

○SDモード:
MMCモードなどとも呼ばれる.
複数端子でデータのやり取りしており、ハードウェアの制約が増えるが高速動作が可能.
また、使用するにはライセンスが必要(個人以外?)
世間の家電等で耳にするClass10、Class4等の読み書き速度は、このSDモードを使用した場合の速度を指す.

○SPIモード
マイコン等でも良く利用されているSPI通信を利用し、SDカードからデータの読み書きをする方法.
SDモードとは異なり、ノンライセンスだったり、電子工作者には身近なSPIを利用することから、
ネット上にも情報が多数置いてある.

SDモードについては、自作組み込み等で使用されるケースも少なく、情報もSPIモードの解説に比べ少ない.
今回もSPIモードの使用を目標とする為、SDモードについては省略.


端子の配列を確認(SPIモードとSDモードでの違い)

f:id:hy30:20160430093857p:plain

ピン番号 MMCモード SPIモード
1 Data3 CS
2 CMD Din
3 Vss Vss
4 Vdd Vdd
5 CLK CLK
6 Vss Vss
7 Data0 Dout
8 Data1
9 Data2
時間があれば簡易版SD規格書を読み理解するのがベスト

SDカードの仕様は、パナソニック、サンディスク、東芝の三社が立ち上げた、
SDアソシエーションという団体が取りまとめている.
SPIモードで使用するまでの過程も、記載されているのこれを読むのがベストと思う.
https://www.sdcard.org/downloads/pls/index.html

”SPI通信”

SPIとは、Serial Peripheral Interface.
直訳のままで、周辺機器(ペリフェラル)をシリアルで通信する入出力方式を指す.
クロック/データ入力/データ出力と、CS(チップセレクタ)の4本の線で通信を行います.
複数の周辺機器と通信をする場合、クロック/クロック/データ入力/データ出力は共用でき、
CSで使用したい周辺機器を選択できる.

CSは周辺機器によってCS(カードセレクタ),SS(スレーブセレクタ)、
また、ホスト側からのデータ出力/周辺機器へのデータ入力はMOSI(マスターアウト・スレーブイン)、
ホスト側へのデータ入力/周辺機器からのデータ出力はMISO(マスターイン・スレーブアウト)と表現する.

MODE(CPOL,CPHA)について

SをLOWにすることで、通信が有効(アサート)になる.
そこにクロックのトリガでデータが送受信が行われる.

そのクロックのトリガをタイミングを表現するのに、
CPOL(クロック極性),CPHA(クロック位相)という言葉で表現されることがある.

CPOL:クロックのアイドル時のレベルを示している.CPOL=0であれば、
アイドル時がHIGH.CPOL=1であれば、アイドル時がLOW.
CPHA:CPHA=0であればクロックが0→1(立ち上がり),CPHA=1であればクロックが1→0(立下り)

SDカードをSPIで使用する際は基本的にMODE0(CPOL=0,CPHA=0).
MODE3(CPOL=1,CPHA=1)で動作するものもある??


○参考文献
SPI