技術約6分で読めます

M5Stack CoreS3でmicroSDが認識しないのでカード相性とSPIクロックを切り分けた

いけさん目次

M5Stack CoreS3にmicroSDカードを挿したら、工場出荷ファームの時点で「SD Card initialization failed!」と言われた。
PCでは普通に読めるカードなのにCoreS3では何をしてもダメで、最終的にカード相性とSPIクロックの2段構えの問題だと分かるまでの切り分けを記録しておく。

検証環境は以下の通り。

項目内容
本体M5Stack CoreS3 Development Kit (K128)
チップESP32-S3 (QFN56) rev v0.2、フラッシュ16MB
microSDLAZOS 16GB(FAT32)/ LAZOS 32GB
開発環境Windows 11 + arduino-cli 1.5.1
コア/ライブラリesp32:esp32 3.3.10 / M5Unified 0.2.17

開封と最初のつまずき

アキバのマルツでCoreS3 Development Kitを買ってきた。

開封したところ

CoreS3のDevelopment KitはDIN BASEという台座付き構成で、DC 9〜24V入力・電源スイッチ・スピーカーが台座側に付いている。
microSDスロットは本体左側面のプッシュ式(押し込むとカチッとロック、ロック状態でさらに押すと出てくる)。

本体側面のmicroSDスロットとDIN BASEのDC入力

USBで電源を入れると、工場出荷ファーム(UserDemo)がハードウェア構成のマップを表示する。
ESP32-S3、16Mフラッシュ、8M PSRAM、2インチIPS液晶(ILI9342D 320x240)、microSDスロットの存在もここに描かれている。

UserDemoのハードウェアマップ画面

このUserDemoにはSD-CARDメニューがあり、カードの中身を表示できる。
未挿入だと「Please insert SD card…」と出る。

SD-CARDメニュー。カード未挿入時

ここに手持ちのLAZOS 32GBを挿すと、こうなった。

SD Card initialization failed! と表示される

「SD Card initialization failed! Please try reinsert SD card…」。
言われた通り抜き差ししても変わらない。
この時点ではコードを1行も書いていない。買ってきたままの状態で挿しただけなので、原因はカードかハードの側にある。

CoreS3の公式スペックはmicroSD最大16GBなので、互換性を考えてスペックに収まるLAZOS 16GB(FAT32フォーマット済み、PCでは正常に読み書きできる)を後日買ってきた。
それでも同じ画面だった。

自前のコードで試す

原因の切り分けにはシリアルログが欲しいので、まずarduino-cliで開発環境を作った。

winget install --id ArduinoSA.CLI
arduino-cli core update-index
arduino-cli core install esp32:esp32
arduino-cli lib install M5Unified

CoreS3のボード定義はEspressif公式のesp32コアに入っている。
FQBNは esp32:esp32:m5stack_cores3

arduino-cli compile --fqbn esp32:esp32:m5stack_cores3 .\sdtest
arduino-cli upload -p COM5 --fqbn esp32:esp32:m5stack_cores3 .\sdtest

CoreS3のmicroSDはSPI接続で、ピンは以下の通り。液晶とSPIバスを共有していて、CSだけ別に持っている。

信号GPIO
CS4
SCK36
MISO35
MOSI37

最小のマウント確認コードはこうなる。

#include <M5Unified.h>
#include <SD.h>

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);
  Serial.begin(115200);
  delay(2000);

  SPI.begin(36, 35, 37, 4);
  if (!SD.begin(4, SPI, 25000000)) {
    Serial.println("SD.begin() FAILED");
    return;
  }
  Serial.printf("Size: %u MB\n", (uint32_t)(SD.cardSize() / 1024 / 1024));
}

void loop() { M5.update(); delay(100); }

結果は工場出荷ファームと同じで SD.begin() FAILED

自前のコードでもFAILED

ここからクロックを疑って、25MHz→15MHz→4MHz→400kHzと段階的に落として全部試したが、LAZOS 16GBは全滅だった。
さらに2秒おきにSD.begin()をリトライし続けるループに変えて、動作中に抜き差しもしてみた。
111回目まで回しても一度もマウントされない。

リトライループでattempt 111。一度も認識されない

  • クロックを400kHzまで落としてもダメ
  • 抜き差し・挿し直してもダメ
  • でもPCのカードリーダーでは正常に読める

ここまでやってカード自体を疑い始めた。

LAZOS 32GBに交換したらマウントは通った

開封日に初期化失敗していたLAZOS 32GBに差し替えたところ、リトライループが即座に反応してマウントされた。
工場出荷デモでダメだったカードが、自作コードだとあっさり通る。
互換性を考えてあえてスペック内の16GBを買い足したのに、そっちが全滅で「スペック外」の32GBが動くというオチ。

マウントは通ったが、ファイル書き込みテストを足すと今度は書き込みで失敗した。

マウントは成功、書き込みはFAILED

SD.open("/hello.txt", FILE_WRITE) がファイルハンドルを返さない。
マウントと容量読み取り(30000MB / Total 29985MB)は通っているので、読み出し系は25MHzで動くが書き込みは通らない、という状態。

そこで書き込みテストもクロックを落としながら再試行するようにした。

// 25MHzで開けなければ10MHz→4MHzで再マウントして書き込みを試す
const uint32_t freqs[] = {25000000, 10000000, 4000000};
for (uint32_t f : freqs) {
  if (f != 25000000) {
    SD.end();
    delay(200);
    if (!SD.begin(4, SPI, f)) continue;
  }
  File w = SD.open("/hello.txt", FILE_WRITE);
  if (!w) continue;
  w.println("hello from CoreS3");
  w.close();
  // 読み返して検証...
}

結果、10MHzで書き込み成功。

10MHzで書き込み成功。hello.txtが見える

open(W) fail @25MHz
write OK @10MHz: hello from CoreS3
--- root files ---
[D] System Volume Information
    hello.txt

ソフトリセット後に再マウントできなくなる

切り分けの途中でもう1つ別の挙動を踏んだ。
一度マウントに成功した後、プログラムの書き込みやシリアルモニタ切断でソフトリセット(ログ上は rst:0x15 (USB_UART_CHIP_RESET))がかかると、次の起動では同じカードなのにSD.begin()が失敗し続ける。

カードが直前のセッションの通信状態を引きずったままになるのが原因のようで、ソフト側からの回復も試したが、このカードでは効かなかった。

  • CS無効のままダミークロックを8192クロック送る → 効果なし
  • CS有効でクロックを送って読みかけデータを吐き出させ、CMD12(転送停止)を直接発行 → 効果なし
  • USBケーブルを抜いて完全に電源を切る → 次の起動で1回目に即マウント

結局、電源断だけが確実な回復手段だった。
開発中はプログラムを書き込むたびにこの状態になるので、「書き込み→USB抜き差し」がワンセットになる。

切り分けの結果

カードPC工場出荷デモ自前コード(マウント)書き込み
LAZOS 16GB (FAT32)✕(全クロック・抜き差しも)-
LAZOS 32GB-25MHz ✕ / 10MHz ○

調べてみると、CoreS3でmicroSDが認識されずカードを変えたら解決したという事例は他にもあった。
M5Stack CoreS3 UIFlow2でmicroSDカードが認識しない原因がSDカード相性だった話では、ESP_ERR_INVALID_RESPONSEで初期化に失敗し続け、キオクシア製に交換して解決している。

CoreS3でSDカードを使うなら、認識しないときにフォーマットやコードを疑う前に、別メーカーのカードを1枚試すのが早い。
動いた後も、書き込みが必要な用途ならSPIクロックは10MHz程度に落としておいたほうが安全。