稼働中

マイクロビット(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」