SDカード制御について

こんにちは、NAKAといいます。

もしSDカードの制御にお詳しい方、アドバイスねがえませんでしょうか?
RL78/I1EのCSIをSDカードコネクタに接続してデータのログを行っています

2GBの昔のMicroSDカードの扱いは何とかなりました。⇒思ったようになりました。

4GB以上のSDHC規格のSDカードの場合、CMD0 と CMD1では初期化できないので
CMD8、CMD58、CMD55、ACMD41、CMD9などを使い 初期化はうまくいきました。

SDHC規格のブロック書込み(CMD24)や読込み(CMD17)のADRESSはセクター単位らしいので


初期化の後

【1】
CMD16(512Byte)
※1ブロックを512Byteに設定

次に

CMD24(ADRESS)
ADRESS = ADRESS + 1;   ※1セクター分ADRESSを進めた
DATA_X(X=X+1)
を繰り返し、ブロック書き込み

CMD17(ADRESS)
ADRESS = ADRESS + 1;
で1セクタごと読み出すと


①ブロック  0byte~ DATA_1 ~512byte

②ブロック  0byte~ DATA_1 ~512byte

③ブロック  0byte~ DATA_3 ~512byte

④ブロック  0byte~ DATA_3 ~512byte

※のように

※DATA_2が書かれない
※DATA_1やDATA_3が2ブロックづつ書かれる


【2】
CMD24(ADRESS)
ADRESS = ADRESS + 2;   ※2セクター分ADRESSを進めた
DATA_X(X=X+1)
を繰り返し

CMD17(ADRESS)
ADRESS = ADRESS + 1;
で1セクタごと読み出すと


①ブロック  0byte~ DATA_1 ~512byte

②ブロック  0byte~ DATA_1 ~512byte

③ブロック  0byte~ DATA_2 ~512byte

④ブロック  0byte~ DATA_2 ~512byte

⑤ブロック  0byte~ DATA_3 ~512byte

⑥ブロック  0byte~ DATA_3 ~512byte

※DATA_1⇒DATA_2⇒DATA_3が2ブロックづつ書かれる


となります。

【質問】
ブロックもセクタも同じ512Byteの理解ですが、間違っていますでしょうか?

書込みを2セクタ送り、読込みを1セクタ毎に余分に空読込み(【2】の②④⑥を無視)することで、それらしく動きますがスッキリしません。

どう表現して良いのかわからず、非常にわかりにくい表現になっていますが、よろしくお願いします。

Parents
  • SDには全然詳しくないですが、ArduinoのSDライブラリはSDHCまで対応してまして、KURUMI(RL78G13)用にポーティングしたソースはこちらにあります。

    GPL3ですのでそのままの転用は考慮が必要ですが、一応ご参考として紹介いたします。

    bitbucket.org/.../libraries

  • Okamiya Yuukiさま、ありがとうございます。NAKAです。

    ソースほとんど理解出来てませんが、ちょちょっと拝見いたしました。

    何となく Sd2Card.cpp の、

    uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src)

    のブロック書き込みで

    if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;

     if (cardCommand(CMD24, blockNumber)) {

       error(SD_CARD_ERROR_CMD24);

       goto fail;

     }

    とあるので、SDHCじゃない場合は blockNumberを9bitシフト(512倍)して実アドレスと使って

    CMD24コマンドに引数としてわたしており、”<<=9”は固定なので、ブロック=セクタの理解でいいような気がするんだけどなぁ~

    なんかセクタっていうのが1024っぽい感じがしたんですけど...............ん~~謎)!!

    そもそも、ブロック書き込みで

    ①0x58,0x00,0x00,0x00,0x00,0xFF とCSIで送って
    ②レスポンスが正しいか確認して
    ③0xFE(データトークンスタートバイト)を送って

    for (i=0; i<512; i++)
    {
       WriteSPI0(d_SD_WR_BUF[i]);
    }
    とデータを書き込んで
    ⑤ダミーのCRC2byte送って
    ⑥レスポンスの確認

    ってやってますが

    ※④で512個しかCSIでデータ送信してないのに何故1024個書き込まれてしまうのだろう?.......ん~~謎)謎)謎)!

  • おはようございます。NAKAです。

    昨日、web上の情報を探していたら、ある人のブログに

    SDカードのブロックサイズは512Bが標準だとインターネット上の

    情報から得ていました。ただ、CMD16で自由にブロックサイズを変えられる

    らしいので、CMD16で256Bに変えて、SASI HDDとセクタサイズを合わせておけば

    コマンド変換のみで行けるだろうとたかをくくっていました。

    ですが、メーカのSD/MMCカードのデータシート等を見ると、読み書きのブロックサイズを

    CMD16で変更できるものと、出来ないものが有るようです。特に、書き込みブロックサイズは

    固定な物も多いようです。試しにSDカードのCSDレジスタを読み出す回路を作成し、読みだしてみたところ

    手持の2GB MicroSDは2枚とも(同じメーカの同じ型番だったかもしれないが)

    bit21 WRITE_BLK_PARTIALが'0'であり、書き込みブロックサイズは変更が

    出来ないようです。bit79のREAD_BLK_PARTIALは'1'でしたので読み出しブロックサイズは

    自由に変えられるようです。

    同時に、bit80-83のREAD_BLK_LENとbit22-25のWRITE_BLK_LENが10(x"a")になっていることも

    確認しました。つまり、ブロックサイズは512Bではなく1024Bということです。

    って内容がありました。

    ブロックサイズがデフォルトで1024BでCMD16でブロックサイズ変更禁止のSDカードもあるの????

    RL78/I1EのRAMは3Kしかないので、そんなにバッファ持てないよぉ~~~!

    SDカードメーカによって様々な仕様があるような気もします。本当かどうかもよくわかりませんが。

    初期設定でしっかりCSDレジスタを確認して、それに合わせた制御をしないといけないのかな?

    1000円くらいのお安いカードリーダでもそんな複雑に制御してるのかな?

    そこらへんの作り込みが甘い機器でごくまれに読めないカードがあったりするのかな?

    もっと勉強が必要かもしれません。

    P.S.

    そういえば、

    >GPL3ですのでそのままの転用は考慮が必要ですが

    ⇒とありましたが、無知ですみませんGPL3ってなんでしたでしょう?

     転用に考慮というのは、①コンプライアンス的に?それとも②機能的に動作しないということ?

     ①でしたら、またやっちゃいました!前回の書き込みは消してください...........汗)

  • 今晩はNAKAです。疑問解消しました!!

    2ブロック分書かれてしまうと思い込んでいたのは、書込み側でなく、読込みに問題がありました。

    読み込ブロックアドレスを進め、ブロック読込みコマンド(CMD17)を発行し、SDカードはまだ読込

    めない状態のレスポンスコードを返していたのに、レスポンスコードを1bit勘違いしていたため、ブロック

    読込み関数の中で受信バッファにデータを書き込まずに関数を抜けていたのが原因でした。

    新しいデータが入ったと思い込んだデータは実は前のデータだったため、もう一度同じデータを読み出した

    ことになり、2ブロック同じデータを書かれていると思い込んでました。

    更に読み込ブロックアドレスを進め今度は読み込める状態になっているため、一つ飛ばした次のブロック

    のデータが読み込まれ、一つ前のブロックデータは消失してしまうという動作になっていました。

    ちゃんと読込めたことをレスポンスで確認して、読み込めてない場合は再度ブロック読込みコマンド(CMD17)を

    発行するように変更して、思い通りの動作となりました。

    デフォルトの書き込みブロックが1024Bでブロック長が変更できないSDカードが実在するという

    web情報を鵜呑みにしてしまったのが今回の反省です。

    あぁ~ 苦しかった!!!

    でも、SDHCに対応できたぞーぉ!

Reply
  • 今晩はNAKAです。疑問解消しました!!

    2ブロック分書かれてしまうと思い込んでいたのは、書込み側でなく、読込みに問題がありました。

    読み込ブロックアドレスを進め、ブロック読込みコマンド(CMD17)を発行し、SDカードはまだ読込

    めない状態のレスポンスコードを返していたのに、レスポンスコードを1bit勘違いしていたため、ブロック

    読込み関数の中で受信バッファにデータを書き込まずに関数を抜けていたのが原因でした。

    新しいデータが入ったと思い込んだデータは実は前のデータだったため、もう一度同じデータを読み出した

    ことになり、2ブロック同じデータを書かれていると思い込んでました。

    更に読み込ブロックアドレスを進め今度は読み込める状態になっているため、一つ飛ばした次のブロック

    のデータが読み込まれ、一つ前のブロックデータは消失してしまうという動作になっていました。

    ちゃんと読込めたことをレスポンスで確認して、読み込めてない場合は再度ブロック読込みコマンド(CMD17)を

    発行するように変更して、思い通りの動作となりました。

    デフォルトの書き込みブロックが1024Bでブロック長が変更できないSDカードが実在するという

    web情報を鵜呑みにしてしまったのが今回の反省です。

    あぁ~ 苦しかった!!!

    でも、SDHCに対応できたぞーぉ!

Children
No Data