SDカードの構造と内部レジスタ(その2)
SDカードの内部レジスタ
SDカードには、いくつかの内部レジスタがある。
レジスタ名 | 内容 | 使用コマンド | ||
CSD | カード特性データレジスタ | アクセスタイム、カード容量など | CMD9 | データ・トークン |
CID | カード識別レジスタ | 製造者情報やシリアル番号 | CMD10 | データ・トークン |
Status | カードステータスレジスタ | カードのステータス | CMD13 | フォーマットR2 |
OCR | 動作条件レジスタ | カードの動作電圧 | CMD58 | フォーマットR3 |
※このほかにもRCA, DSRというレジスタが存在するが、SPIモードではアクセスすることができない。
・CSD(カード特性データレジスタ)
CSDレジスタは、CMD9に対するデータ・トークンで読むことができる。
非常に多くの情報を含んでいるが、ここでは主なものを抜粋して掲載する。
略称 | 意味 | ビット位置 | データ内の位置 |
CSD_STRUCTURE | CSD structure | 127-126 | data0[7:6] |
SPEC_VERS | Spec version | 125-122 | data0[5:2] |
TRAN_SPEED | Max data transfer rate | 103-96 | data3[7:0] |
READ_BL_LEN | Max read data block length | 83-80 | data5[3:0] |
C_SIZE | device size | 73-62 | data6[1:0]-data7-data8[7:6] |
C_SIZE_MULT | device size multiplier | 49-47 | data9[1:0]-data10[7] |
FILE_FORMAT | File format | 11-10 | data14[3:2] |
ECC | ECC code | 9-8 | data14[1:0] |
CRC | CRC | 7-1 | data15[7:1] |
always 1 | 0 | data15[0] |
これら情報のC_SIZEとC_SIZE_MULT、READ_BL_LENの値から、カードの容量を計算することができる。
・CID(カード識別レジスタ)
CIDレジスタはCMD10のデータ・トークンとして読むことができ、カードの製造元などの情報が含まれている。
名称 | バイト数 | データ内の位置 |
Manufacture ID | 1 | data0 |
OEM/Application ID | 2 | data1-data2 |
Product Name | 6 | data3-data8 |
Product Revision | 1 | data9 |
Pruduct Serial Number | 4 | data10-data13 |
Manufacturing Date | 1 | data14 |
CRC | 1 | data15 |
・Manufacture IDは、01(Matsushita)、02(Toshiba)、03(Sandisk)などとなっている。
・Statusレジスタ
Statusレジスタは本来32bitのレジスタであるが、SPIモードでは16bitだけを読み出すことができる。
CMD13(Statusレジスタ取得)を発行し、コマンド・レスポンスのフォーマットR2で送られる2バイトの情報である。先頭の1バイトはフォーマットR1と同じである。
フォーマットR1を次に示す。
エラーがない状態では、16bitがすべて0になる。
SDカード内のデータ
SDカード内のデータは、通常のメモリと同様に、アドレスで管理されている。(単純にメモリカードとして使用することも可能であるが、通常は何らかのファイルシステムにより管理される)
SDカードでは、データの読み書きはブロック単位で行われる。ブロックの大きさ(Block Length)は、CSDレジスタのREAD_BLK_LENである。またCMD16で変更可能である。
ここでは、後に解説するファイルシステムとの整合性を重視し、1ブロックは512バイトであることを前提に進める。
・ブロックサイズ設定
ブロックサイズ(Block Length)の指定はCMD16で行う。
CMD16の引数として、ブロックサイズをバイト単位で与える。512バイトにする場合のコマンド・トークンは
[0x50, 0x00, 0x00, 0x02, 0x00, CRC]となる。
・データリード(1ブロック)
データリードはCMD17で行う。CMD17の引数としてアドレス(4バイト)を与える。
コマンド・レスポンス(フォーマットR1)の後、データ・トークンを受信する。リードデータは、Block Lengthバイト分送られる。
0x10000000番地を指定する場合のコマンド・トークンは
[0x51, 0x10, 0x00, 0x00, 0x00, CRC]となる。
・データライト(1ブロック)
データライトはCMD24で行う。引数として書き込み先頭アドレスを与える。
当然であるが、誤った書き込みを行うと、カード内のデータを破壊する。注意が必要である。
演習問題
次のワークスペースをダウンロード・展開し、次の演習を行う。
sd2.zip
演習1:カード容量の計算
プロジェクト[sd2_1]を使用する。SDカードからCSDレジスタを読み出して、表示するプログラムを作成せよ。得られたCSDレジスタの値から、カードの容量を計算せよ。
べき乗の計算には一般的にはpow()関数を使用する。例えば2の5乗はpow(2, 5);で得られる。
この演習でのべき乗の計算は、2のxx乗という計算である。この場合はシフト演算を使ったほうがメモリサイズ、計算速度の両面から有利である。
例) A*(2^3)は、A<<3で得られる。
演習2:1ブロックリード
プロジェクト[sd2_2]を使用する。SDカードの先頭から1ブロック読み出して、表示するプログラムを作成せよ。
表示は16進数と、印字可能であれば(isprint()で判断)、文字としての表示も行う。
この領域は、FATファイルシステムの一部(Master Boot Record)であり、パーティション情報などが記録されている。
次のような手順で行う。
- CMD17を発行し、データ・トークン・スタートバイトを待つ
- 1ブロック(512バイト)分のデータを読み込み、配列に格納する
- 配列の先頭のデータから、16進表示と文字表示を行う(1行あたり16バイト)
※ この表示例は、SDカードの先頭に記録されている情報ではありません
演習3:第一パーティション
演習2で読み出したデータの、data[454:457]の4バイトは、第一パーティションのセクタ番号(ブロック番号)を示している。第一パーティションの先頭部分を1ブロック読み出して、表示せよ。
演習2と同様に、表示は16進数表示と文字表示を行う。
1セクタの容量は512バイトであるので、目的とするアドレスはセクタ番号*512である。
※SDカードはFATファイルシステムでフォーマットされており、リトルエンディアンである。data[454:457]の4バイトのセクタ番号はリトルエンディアンで記録されている