マイクロビット(e_23)SDカード モジュール(2)初期化 CMD1 読出し CMD17
SDカードの初期化CMD1 、シングルブロック読み取り CMD17
前回に続いてmicro:bitを使ったSDカードの初期化とシングルブロック読み取りについて記載します。
※thonny-microbitのMicroPythonを使っています。
CDM1 SEND_OP_CND
ACMD41で初期化できなかった標準SD 1GB(MMC ~2GB)をCDM1で初期化します。
CMD0>CMD1の順番でコマンドを送ります。
スクリプト
CMD1で初期化するスクリプトを以下のようにしました。※関数部分は先と同じなので省略して記載しています。
# SPI init bps=100kHz
spi.init(baudrate=100000, bits=8, mode=0, sclk=pin13, mosi=pin15, miso=pin14)
sleep(10)
# command
cmd0=0x40 #GO_IDLE_STATE (コマンド番号|0x40)の値
cmd1=0x41 #SEND_OP_CND
print('CLK >= 80 out')
CS(1)
for i in range(10): # CS=H ダミークロックを80個送信
spi_ff()
## MMC INIT START
# ---------------------------------------------------------- CMD00
CS(0)
spi_ff()
spi_cmd(cmd0,0x00,0x00,0x00,0x00,0x95)
while True:
spi_ff()
res=spi_res()
if res== b'\x01':
print('cmd0 OK resp=0x01')
break
# ---------------------------------------------------- CMD01 SEND_OP_CND
while True:
spi_ff()
spi_cmd(cmd1,0x00,0x00,0x00,0x00,0x01)
spi_ff()
res=spi_res()
if res== b'\x00': # 正常ならレスポンス0x00が返る
print('cmd1 OK resp=0x00')
break
#END
spi_ff()
CS(1)
spi_ff()
実行結果
実行結果です。※Thonnyのshell枠に表示されます。
SDカードモジュールのソケットに標準SD 1GBをさして実行しました。無事に初期化できたようです。
ちなみにパソコンでフォーマットしたカードでは66回の繰返し後にレスポンス0x00が戻り初期化されました。一度、初期化したカードなら以下のように6回くらいで初期化されました。
>>> %Run 220113_sd_b01_cmd01_init.py
CLK >= 80 out
resp= b'\x01'
cmd0 OK resp=0x01
resp= b'\xff' # 0xffなので繰り返す
resp= b'\xff'
resp= b'\x01' # IDLE状態なので繰り返す
resp= b'\xff'
resp= b'\xff'
resp= b'\x00'
cmd1 OK resp=0x00 # 0x00が戻ったので正常に初期化了
>>>
ちなみにCMD1で初期化した状態でSD 1GBのOCR情報を先のCMD58で見てみます。
CMD58を実行するとR3の値はb’\x00\x80\xff\x80\x00’になりました。OCR情報はCCS=’0’になっており標準SDカードを示しています。power up=’0’はCMD8を通過していないためだと思います。電源電圧は2.7~3.6Vをサポートしています。※前回のOCRのレジスタ表を参照ください。
>>> %Run 220114_sd_b01_cmd58_ocr.py
START CLK>80
CMD58 ***
cmd58 >>>
R1(1byte)+OCR(4bytes)= b'\x00\x80\xff\x80\x00'
>>>
ちなみに先のACMD41のスクリプトを実行するとCMD8でエラーになります。
>>> %Run 220113_sd_b01_acmd41_init.py
CLK>80
CMD0
b'\x01'
b'\x01' cmd0 OK x01
CMD8
b'\xff\xff\xff\xff\xfe'
R7-5bytes >> b'\xff\xff\xff\xff\xfe'
SDC-CARD ERROR >>> MMC
CDM17 READ_SINGLE_BLOCK
CMD17(READ_SINGLE_BLOCK)でシングルブロック読み取りをします。単一ブロックは512バイトです。ブロックサイズはCMD16(SET_BLOCKLEN)で変更が可能です。
CMD16に関しては特にスクリプトは記載していません。仮にブロック長1024バイトに設定する場合は、hex(1024)=’0x400’なので、
spi_cmd(cmd16,0x00,0x00,0x04,0x00,0x01)
を送信すれば良いと思います。
ちなみに
High Capacity SD Cards(2GB<)の32bitアドレスは512バイトのブロックを示します。
0~ spi_cmd(cmd17,0x00,0x00,0x00,0x00,0x01) 512~ spi_cmd(cmd17,0x00,0x00,0x00,0x01,0x01) 1024~ spi_cmd(cmd17,0x00,0x00,0x00,0x02,0x01)
Standard Capacity Cards(<=2GB)では32bitアドレスはbytes単位です。512バイトのブロック単位で読み書きするので、以下のように512バイトの倍数で指定します。
0~ spi_cmd(cmd17,0x00,0x00,0x00,0x00,0x01) 512~ spi_cmd(cmd17,0x00,0x00,0x02,0x00,0x01) 1024~ spi_cmd(cmd17,0x00,0x00,0x04,0x00,0x01) 2560~ spi_cmd(cmd17,0x00,0x00,0x0a,0x00,0x01)
CMD17を送った後のレスポンス’0x00’に続いてトークン’0xfe’を得た後に512バイトを読込む必要があります。また、512バイトの後に2バイトのCRCが続きます。
スクリプト
以下のようなスクリプトにしました。ここでは512番から読込みます。初期化したSDHC 16GBカードを使用しました。※関数部分は先と同じなので省略して記載しています。
# SPI init bps=100kHz
spi.init(baudrate=100000, bits=8, mode=0, sclk=pin13, mosi=pin15, miso=pin14)
sleep(10)
# command
cmd17=0x51 # READ_SINGLE_BLOCK
##-------------------------------------------CMD17
print('cmd17 READ_SINGLE_BLOCK START')
CS(1)
spi_ff()
CS(0)
spi_ff()
#
radr=spi_cmd(cmd17,0x00,0x00,0x02,0x00,0xfd)
b_add=radr[1:5] # readaddress
while True:
spi_ff()
res=spi_res()
if res== b'\x00': # R1 エラー無まで0xffを送る
print('cmd17 through')
break
while True:
spi_ff()
res=spi_res()
if res== b'\xfe': # トークン'0xfe'が戻るまで0xffを送る
print('token OK 0xfe')
break
block_buf=spi.read(512) # '0xfe'が戻ったので512バイトを読む
#crc 2byte read
crc_buf=spi.read(2) # データに続くCRC 2バイトを読む
# 読込むアドレス、512バイトデータ、CRC2バイトの表示
print('read_block_address=',b_add, '512bytes=',block_buf,' CRC2=',crc_buf)
#END
spi_ff()
CS(1)
spi_ff()
実行結果
実行結果です。※Thonnyのshell枠に表示されます。
SDカードに何も書込んでいないので’0x00’ばかりのデータが表示されました。読み込みはできているようです。
ちなみに初期化した標準SD 1GBカードも同様に動作しました。
>>> %Run 220113_sd_b01_cmd17.py
cmd17 READ_SINGLE_BLOCK START
b'\x00' # CMD17 エラー無し
cmd17 pass >>
b'\xff' # 0xffなので待機
b'\xfe' # 0xfe(トークン)なので読み込み開始
token OK 0xfe
read_block_address= bytearray(b'\x00\x00\x02\x00') 512bytes= b'\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
(省略)
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' CRC2= b'\x00\x00'
まとめ
micro:bitで標準SD 1GBカードをCMD1コマンドによる初期化ができたと思います。また、CMD17でシングルブロック読み取りを試しました。
※参考にしたサイト
AVRCチュートリアル「http://www.rjhcoding.com/avrc-tutorials-home.php」
PICを使ってSDカードを操作「http://bitcraft.web.fc2.com/embedded/microchip/microchip.html#sdhcinit」
A33FでMicroSDカードにアクセスしてみる「http://www.robotsfx.com/robot/robohow/RoboHow91/RoboHow91.html」