Bus pirate(2018/9/3)で先割れスプーン的だと書いたけど、便利だったのでSPIモードでSDカードを読んでみた。 uSDカードアダプタはAmazonで買った安物。 3.3VのLDOとレベルシフタが載っている。
昔SDカード/MMCカードで遊んでいたころはまだSDHC規格は無かったので知識が古い。
調べてみると、MMCカード規格を作っていたMultiMediaCard AssociationはJDECと合併したらしい。 最近MMCカードは見かけないけど組み込み業界では eMMCとしてチップが基板に張り付けてある。
MMCカードの規格はRenesas(旧日立)の「マルチメディアカードユーザーズマニュアル(j603002_mmc.pdf)」があるのだが、Renesasのサイトでは見つからないようだ。 ネット上では奇特な人が保存してくれているようだ。
ここを参考にBus pirateでSDカードのデータを読んでみた。
SDカードはSanDiskの2G microSDcard。
【初期化】
CMD1で初期化してみた。 初期化手順は、
- SPIモードにする
- CMD0:GO_IDLE_STATE:(要CRC)
- CMD1:SEND_OP_COND R1レスポンスが00hになるまで
- CMD2:ALL_SEND_CID
- CMD3:ET_RELATIVE_ADDR
これはMMCの初期化方法。 ユーザマニュアルに説明がある。 今回は、CMD2,CMD3は省略して先頭セクタを読んでみる。
SPIモードにするには、CSをHにしてダミークロックを74クロック以上発行する。 74クロックはキリが悪いので80クロックとする。
BusPirateでは、"]"←CS=H、r:10←10byte(80clock)、
コマンドレスポンスの先頭ビットは0なので0xFF以外のデータを読み出すまで待つ。ところが、BusPireteでは待つことができないのでとりあえず8byte読む。 0xFFでないデータがコマンドレスポンスだ。 (scriptを使うと待つことができる。)
【セクタ読み出し】
読みだし手順は、
- CMD16:SEND_BKICKLEN
- CMD17:READ_SINGLE_BLK
まずCMD16でブロックサイズを指定する。次にCMD17を送ると、コマンドレスポンスに続いてデータを読み出すことができる。 読み出す回数はコマンドレスポンス:5byte、データトークン(0xFE):1byte、ブロックデータ:512byte、CRC:2byteで520byteを指定している。
6byte以内にデータトークン(0xFE)が読み出せないとすべてのデータが読めない。 そのときは読み取るデータを多くする。 (r:530とか)
HiZ>m 5 1 1 2 1 2 2 ←SPIモード SPI (spd ckp ske smp csl hiz)=( 1 0 1 0 1 0 ) Ready SPI>Wv ←電源ON ピンステータス表示 Power supplies ON Pinstates: 1.(BR) 2.(RD) 3.(OR) 4.(YW) 5.(GN) 6.(BL) 7.(PU) 8.(GR) 9.(WT) 0.(Blk) GND 3.3V 5.0V ADC VPU AUX CLK MOSI CS MISO P P P I I I O O O I GND 3.29V 5.02V 0.00V 0.00V H L H H L
SPI>]r:10 ←SPImode /CS DISABLED READ: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
SPI>[0x40 0x00 0x00 0x00 0x00 0x95 r:8] ←CMD0 GO_IDLE_STA /CS ENABLED WRITE: 0x40 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x95 READ: 0xFF 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF ←R1=0x01 "In Idle State" /CS DISABLED
SPI>[0x41 0x00 0x00 0x00 0x00 0xff r:8] ←CMD1 SEND_OP_COND /CS ENABLED WRITE: 0x41 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0xFF READ: 0xFF 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF ←R1=0x01 "In Idle State" /CS DISABLED
SPI>[0x41 0x00 0x00 0x00 0x00 0xff r:8] ←CMD1 SEND_OP_COND /CS ENABLED WRITE: 0x41 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0xFF READ: 0xFF 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF ←R1=0x00 成功 /CS DISABLED
SPI>[0x50 0x00 0x00 0x02 0x00 0xff r:8] ←CMD16 SET_BLOCK_LEN /CS ENABLED WRITE: 0x50 WRITE: 0x00 WRITE: 0x00 WRITE: 0x02 WRITE: 0x00 WRITE: 0xFF READ: 0xFF 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF ←R1 Response=0x00 成功
SPI>[0x51 0x00 0x00 0x00 0x00 0xff r:520] ←CMD17 READ_SINGLE_BLOCK /CS ENABLED WRITE: 0x51 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0xFF READ: 0xFF 0xFF 0x00 0xFF 0xFF 0xFE 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ( ) 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x03 0x3D 0x00 0x06 0x3F 0xFF 0xD7 0xF9 0x00 0x00 0x00 0x07 0x89 0x3C 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x55 0xAA 0x5D 0xE1 /CS DISABLED
|
↑先頭から3byte目がR1レスポンス(0x00)。続いてデータトークン(0xFE)、SDカードの先頭セクタ。パーティションテーブル(下線部分)と末尾に55h、AAhがある。 最後の2byteはCRC(0x5D,0xE1)。
【SDHCカード】
SanDisk SDHC 8GBも読んでみる。
このカードはCMD1で初期化する方法は使えない。 初期化手順は、SD AssociationからDLできる [Physical Layer Simplified Specification]に解説がある。
- SPIモードにする
- CMD0: GO_IDLE_STATE:(要CRC)
- CMD8: SEND_IF_COND:(要CRC)
- ACMD41:SD_APP_OP_COND (CMD55+CMD41) R1レスポンスが00hになるまで
- CMD58: READ_OCR
CMD8のパラメータは、0x00、0x00、電圧、チェックパターン(レスポンスで同じ値が返る)。 電圧は3.3vで使うので0x01、チェックパターンは0xAAを使う。 なぜって、ネット上にCRC(0x87)を計算した人がいるから。 ここは決め打ちでよさそう。
CMD58は省略。データ読み出しはCMD16とCMD17上の例と同じ。
HiZ>m 5 1 1 2 1 2 2 SPI (spd ckp ske smp csl hiz)=( 1 0 1 0 1 0 ) Ready
SPI>Wv Power supplies ON Pinstates: 1.(BR) 2.(RD) 3.(OR) 4.(YW) 5.(GN) 6.(BL) 7.(PU) 8.(GR) 9.(WT) 0.(Blk) GND 3.3V 5.0V ADC VPU AUX CLK MOSI CS MISO P P P I I I O O O I GND 3.29V 5.02V 0.00V 0.00V H L H H L
SPI>]r:10 ←SPImode /CS DISABLED
READ: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
SPI>[0x40 0x00 0x00 0x00 0x00 0x95 r:8] ←CMD1 GO_IDLE_STATE /CS DISABLED READ: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF /CS ENABLED WRITE: 0x40 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x95 READ: 0xFF 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
/CS DISABLED SPI>[0x48 0x00 0x00 0x01 0xAA 0x87 r:8] ←CMD8 SEND_IF_COND /CS ENABLED WRITE: 0x48 WRITE: 0x00 WRITE: 0x00 WRITE: 0x01 WRITE: 0xAA WRITE: 0x86 WRITE: 0x87 READ: 0x01 0x00 0x00 0x01 0xAA 0xFF 0xFF 0xFF ←R1:Idle R7: /CS DISABLED
SPI>[0x77 0x00 0x00 0x00 0x01 0xff r:8] ←CMD55 APP_CMD /CS ENABLED WRITE: 0x77 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x01 WRITE: 0xFF READ: 0xFF 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF /CS DISABLED
SPI>[0x69 0x40 0x00 0x00 0x01 0xff r:8] ←CMD41 PP_SEND_OP_COND /CS ENABLED WRITE: 0x69 WRITE: 0x40 WRITE: 0x00 WRITE: 0x00 WRITE: 0x01 WRITE: 0xFF READ: 0xFF 0x05 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF /CS DISABLED
SPI>[0x77 0x00 0x00 0x00 0x01 0xff r:8] ←CMD55 APP_CMD /CS ENABLED WRITE: 0x77 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x01 WRITE: 0xFF READ: 0xFF 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF /CS DISABLED
SPI>[0x69 0x40 0x00 0x00 0x01 0xff r:8] ←CMD41 PP_SEND_OP_COND /CS ENABLED WRITE: 0x69 WRITE: 0x40 WRITE: 0x00 WRITE: 0x00 WRITE: 0x01 WRITE: 0xFF READ: 0xFF 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF /CS DISABLED
SPI>[0x50 0x00 0x00 0x02 0x00 0xff r:8] ←CMD16 SET_BLOCK_LEN len=512byte /CS ENABLED WRITE: 0x50 WRITE: 0x00 WRITE: 0x00 WRITE: 0x02 WRITE: 0x00 WRITE: 0xFF READ: 0xFF 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF /CS DISABLED
SPI>[0x51 0x00 0x00 0x00 0x00 0xff r:520] ←CMD17 READ_SINGLE_BLK /CS ENABLED WRITE: 0x51 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0x00 WRITE: 0xFF READ: 0xFF 0xFF 0x00 0xFF 0xFF 0xFE 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ( ) 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x82 0x03 0x00 0x0B 0x50 0xCA 0xC6 0x00 0x20 0x00 0x00 0x00 0xC0 0xEC 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x55 0xAA 0x68 0xC0 /CS DISABLED
|
CMD8は PhysicalSpec Ver2.0から使えるらしい。 CMD8→ACMD41→CMD1の順に初期化するとどのカードでも使える。
昔AVRでSD/MMCにアクセスするプログラムを作ったときは、初期化で苦労した記憶がある。 いまほど情報もなかったし、Arduinoも無かったから。
今時は情報も多いし、Bus pirateのようなツールで試すと、F/Wレベルでの試行錯誤を減らせる。
###
SDカードのライセンスにまつわるエトセトラは。Chanさんやねむさいんの、
が参考になる。
【最近の投稿】【最近のCPUボード】【2017の投稿】【2016の投稿】【2015の投稿】
コメント