STM32H7を使ってみる8 〜SDカードの初期化で大バグを仕込み、しかも6年間放置してた件〜

←前回 


北神雄太さんのZennの記事を読んでてねむいさんも少し気を付けようと
思いました。ソースコードの確認ミスや仕様の見落としで誤った結果を
世に出してしまわないようにと・・・。


…と気を引き締めた矢先、自身が公開しているソースコードに
とんでもない爆弾を発見してしまいましたorz


罪状
STM32H7のFatFs移植例(SDMMCインターフェース)で、
 "CMD6発行によるHigh Speed Modeへの移行処理"を
 せずにSDカードのクロックを25->50MHzに上げていた。
 それをソースコード公開時から約6年間放置した上
 さらにSTM32L5,STM32H5に同じバグを拡大させた。



ねむいさんの公開しているSTM32H7(STM32H747I-Disco)向けのFatFs
実装例
はSDMMCインターフェースを使ってSDカード/MMCとデータの
読み書きをするようにしております。

その初期化の部分でSDカードのクロックをデフォルトスピードの
25MHzから50MHzに引き上げる操作を行っているつもりでした。

本来はCMD6コマンドを発行し、SDカードがハイスピードモードに
切り替わったことを確認して初めて50MHzに引き上げることができるの
ですがその操作を行わないままいきなり50MHzにクロックを上げて
しまっておりましたorz


SDXCの初期化の例をとると本来の初期化は下記を想定してました。
CMD0発行、カードリセット

CMD8発行、SDv2初期化

CMD55+ACMD41をレスポンスが有効になるまで実行

CMD2発行、CID取得

CMD3発行、RCA取得

CMD9発行、CSD取得

CMD7発行、RCA設定

CMD55+ACMD13発行、SCR取得

CMD55+ACMD6発行、4bitバスモード移行
(ここで4bitバスアクセスに変更)

CMD6発行、ハイスピードモード移行
(ここで供給クロックを50MHzに変更)

CMD16発行、ブロックサイズを512バイトに設定
(ここで読み書きのための全部の準備が完了)

以後CMD17/CMD18とかCMD24/CMD25でデータ読み書き

☝バグのコードでは上記のCMD55+ACMD6とCMD16の間でCMD6の発行を
せず、ACMD6発行後に4bitに切り替えと同時に50MHzにクロックを上げて
しまっていました。


なお、"SDカード"を使用した際のみこのバグが発動し、MMC/eMMCの
初期化の際はCMD6が正しい順序で発行したうえでクロック周波数を
引きあげていたので問題はありません。



●何が起こる?
➡読み書きの操作(CMD17/CMD18やCMD24/CMD25実行)
 を行った時に以後の応答を一切しなくなる可能性がある


"可能性がある"というのはすべてのSDカードで発生するのではなく、
ごく一部のカードで起こっているからです。
ていうか私の持ってるカードの中では1枚のカードだけが操作不能に
なることに気づきました…!


それがこのカード、TranscendのTS20GUSG240Iです…。
SLCモードを搭載し、230Iと比較し書き込み耐量がさらに上昇した
カードとなります。2024年の秋に購入していました。

最初にSTM32H5-Nucleoで使った際に"認識"できず、STM32H7-Discoで
使っても"認識"できなかったのでこのカードはハイスピードモードでは
使用できない"個体不良"なのだろうと思い込みソースコードレベルの
デバッグも行わないまま捨ておきましたが…

冒頭の北神さんの記事を読んでこのカードのことを思い返して
改めてソースコードレベルのデバッグにて初期化の流れを一から
追ったら自身の大チョンボを発見してしまった次第ですorz


ちなみに発覚前はCMD17/18とかCMD24/25の発行時に10uSecくらいの
待ち時間を突っ込むとなんでか読み書きできるのを発見したので
それで茶を濁しておりました…今思えばなんて愚かしいことを…

最初にSTM32H7を触ってSDMMCを使い始めた時にデバッガでソース
コードレベルでプログラムの流れ追っかけて確認するの面倒くさがって
やっておらず、当時の手持ちのカード全部認識できてるし"動いたから
これでよし"と思い込んだのがすべての原因です…すべては私の責…!!
ただねむいさんが悪い!ただねむいさんが悪い!



●バグの影響範囲は?
➡ねむいさんのおきぱで紹介しているFatFsの移植例の中で、
 STM32H7,STM32L5,STM32H5のものが対象。


何でこうなったかというと最初にSTM32H7で作成したバグ入りのSDMMCの
アクセスライブラリをSTM32L5,STM32H5にスライド移植させてしまったが
ためにバグまで仲良くスライド移植してしまったからですorz

STM32F7のSDMMCについては正しい手順でCMD6を発行してハイスピード
モードに移行した上でクロックを上げているため問題はありません。

STM32F1,F4についてはSDIOにエラッタが存在し、ハイスピードモードの
速度でクロックが実質使用できないのでDefaultSpeed(25MHz)までとして
います。(実験的にハイスピードモードにできるようにはしています。)

LPC4088はMCIのクロック上限が25MHzまでなのでこれも問題はありません。

LPC4357についてはSDカードのクロック上限はソフトウエアで25MHzまでと
しているのでこちらも問題はありません(MMCv4は50MHz)。

その他、SPIモードで読み書きするものについても、そもそもSDの仕様上で
SPIモードではハイスピードモードは使用できないのでこちらも問題は
ありません。(※SPIモードでもハイスピードモードが存在する説があり)


●実際の被害は?
➡現状私一人だけが被弾している状態です。

私の知る限りでは他の方が私の作例を使用し、SDカードの
読み書きができないという報告や記事はありませんでした。

しかしSTM32H7/L5/H5の私の対策前の作例をもとにTS20GUSD240Iを
使うと、確実に被弾します。再現率100%です。


●対策は?
➡"CMD6発行によるHigh Speed Mode移行"を確認してから
 SDカードへのクロックを50MHzに上げるよう修正します。


本来ならばこの記事を書く前にいち早く修正コード上げるべきですが
検証に使用するカードの種類や対応マイコンの範囲が広いので時間かけて
慎重に再検討しております…。完了したら追記で連絡いたします。

20250328追:
バグを修正し、全体的に動作を見直し大幅更新いたしました!
20250328追:




古のハイスピードモードが無いSDV1.01カードとか4bitモードが無い
MMCv3カードからはじめて最新のA2対応のSDXCとかeMMCに至るまで、
洗いざらい今一度!とにもかくにも全部動作確認!


STM32H7で問題ないことを確認したらSTM32L5(更新停止してますが
今回だけ)とSTM32H5にも今回の修正を反映します。

また、STM32F1,F4,F7,LPC4000系の実装例についてもSTM32H7の修正で
気づいた点についてはフィードバックして最新化させる予定です。

多分夏いっぱいくらいかかるかと思いますが焦らずに対処いたします。



●ところでTranscendのTS20GUSD240Iですが…

このカード、UHS-2ではないのですがなんでかSDR104の限界を超えて
100MB/sec超の読み書き性能を誇っております…

UHS-2には勝てないですがコストパフォーマンス考えたらすごいです。
おそらくこれは規格外規格のDDR200ってやつですね…
検証に使ったUGREENのUHS-2対応カードリーダー(CM265)も何気にDDR200に
対応してるのが分かったので掘り出し物だったのわかってラッキーです…♥


なお、今年初頭に紹介したUltraPerformanceのカードもぶっちふぎりの
性能見せてくれてます…
もうUHS-2じゃなくてもこれらでいいかも…!

Go to top of page