センスチャンとは?
SPRESENSEマイコンを搭載したスタックチャン派生のロボットです。
センスチャン基板とは?
センスチャン専用に設計した、SPRESENSEの拡張ボードです。
→ 詳細はコチラ
SDカードまわりの不具合
センスチャン基板にはSDカードまわりに不具合がありました。
症状
電源オン時はSDカードを認識できるが、リセットをかけるとSDカードを認識できなくなります。SPRESENSEはUSBケーブルを接続するとリセットがかかる仕組みなので、そうするとSDカードが使えなくなります。ただし、SDカードを抜いて挿入しなおすと正常に認識します。
当然ながら、SPRESENSEの純正拡張ボードではこのような不具合は起こりません。
原因
マイコンのリセット時にSDカードがリセットされずに中途半端な状態になっているのではないかと思われます。機序は明確には特定できていないものの、レベル変換ICが原因ではないかと思われます。SPRESENSEのIO電圧は1.8V、SDカードのIO電圧は3.3Vなので、SDIOにレベル変換が必要であり、純正ボードではSDIO専用のレベル変換IC TXS02612 を使用しています。いっぽう、センスチャン基板では基板サイズと手実装の都合で汎用のレベル変換IC LSF0108 を使用しています。両者を比較すると CLK ラインの等価回路に違いがあります。リセット時にCLKラインが不安定になり、意図しない動作になっている可能性があります。
対策
基板の改修は難しいので、とりあえずソフトウェアでSDIOを明示的にリセットすることにします。
ただし、SPRESENSE のArduino環境は NuttX上で動作しており、SD.begin() は NuttX が SDカードを認識しているかどうかを確認するだけです。そこで、NuttX のコードを漁り、SDIOをリセットする方法を調べました。
nuttx\arch\chip\cxd56_sdhci.h に以下のような関数がありました。
// SDIOを初期化する // 引数 : 未使用 // 戻り値 : SDIO制御構造体への参照 struct sdio_dev_s *cxd56_sdhci_initialize(int slotno); // SDIO状態のリセット // 引数 : SDIO制御構造体 void cxd56_sdio_resetstatus(struct sdio_dev_s *dev); // ボード挿抜時にドライバに通知する // 引数 : SDIO制御構造体 void cxd56_sdhci_mediachange(struct sdio_dev_s *dev);
コード
// SDカードのリセット処理 // 戻り値: 結果 (0:未挿入, 正:リセット成功, 負:リセット失敗) int sdcard_reset() { // Sense-chan基板の設計ミスによる不具合回避のため。 // SPRESENSEをH/WリセットするとSDカードが認識されなくなることがあるため // SDカードのS/Wリセット処理を行う。 // CDピンをチェック (挿入時 LOW (false) ) bool cd = cxd56_gpio_read(PIN_SDIO_CD); if(cd == true) return 0; // SDカード未挿入 const char *DEV_FILE = "/dev/mmcsd0"; // SDカードのデバイスファイル const char *MNT_DIR = "/mnt/sd0"; // SDカードのマウントポイント // /mnt/sd0 が正常にマウントされていれば何もしない struct stat st; int ret = stat(MNT_DIR, &st); if (ret == 0) return 1; // すでにマウントされている // SDIOを初期化し、OSのデバイスドライバに知らせる struct sdio_dev_s *sdio = cxd56_sdhci_initialize(0); cxd56_sdio_resetstatus(sdio); cxd56_sdhci_mediachange(sdio); if (stat(DEV_FILE, &st) != 0) return -1; // デバイスファイルが無い if (stat(MNT_DIR, &st) == 0) return 2; // すでにマウントされている // マウントする ret = mount(DEV_FILE, MNT_DIR, "vfat", 0, NULL); if (ret < 0) { perror("mount failed"); return -2; // マウント失敗 }else{ return 3; // マウント成功 } }

