mirror of
https://github.com/ALLFATHER-BV/wadamesh.git
synced 2026-10-22 19:41:22 +00:00
feat: add universal microSD diagnostics
This commit is contained in:
1 parent
16d09696ca
commit
db11fcf2c5
6 files changed
+197
-40
No files matched your search
+29
-8
@@ -1028,11 +1028,19 @@ void setup() {
|
||||
// edge shows up as a mid-session "sdmmc_host_wait_for_event returned 0x107"
|
||||
// (ESP_ERR_TIMEOUT) that takes prefs, contacts and chat history down with it. The
|
||||
// T-Display P4 hot-insert path already drops to this rate for the same reason.
|
||||
sdMountDiagBegin();
|
||||
bool wio_l2_sd_begun = false;
|
||||
if (WioTrackerL2Io::ready() && WioTrackerL2Io::setSdPower(true) &&
|
||||
SD_MMC.setPins(2, 3, 1) &&
|
||||
(wio_l2_sd_begun = SD_MMC.begin("/sdcard", true, false, SDMMC_FREQ_DEFAULT)) &&
|
||||
SD_MMC.cardType() != CARD_NONE) {
|
||||
const bool wio_l2_sd_bus_ready = WioTrackerL2Io::ready() &&
|
||||
WioTrackerL2Io::setSdPower(true) &&
|
||||
SD_MMC.setPins(2, 3, 1);
|
||||
if (wio_l2_sd_bus_ready)
|
||||
wio_l2_sd_begun = SD_MMC.begin("/sdcard", true, false, SDMMC_FREQ_DEFAULT);
|
||||
const bool wio_l2_sd_ready = wio_l2_sd_begun && SD_MMC.cardType() != CARD_NONE;
|
||||
if (wio_l2_sd_bus_ready)
|
||||
sdMountDiagAttempt((uint32_t)SDMMC_FREQ_DEFAULT * 1000u, wio_l2_sd_begun, wio_l2_sd_ready);
|
||||
sdMountDiagSetMounted(wio_l2_sd_ready,
|
||||
wio_l2_sd_ready ? (uint32_t)SDMMC_FREQ_DEFAULT * 1000u : 0);
|
||||
if (wio_l2_sd_ready) {
|
||||
sd_storage = store.useSdMmcStorage();
|
||||
g_contacts_on_sd = sd_storage;
|
||||
g_full_data_on_sd = sd_storage;
|
||||
@@ -1087,6 +1095,7 @@ void setup() {
|
||||
#endif
|
||||
bool sd_mounted = false;
|
||||
#if defined(TLORA_PAGER)
|
||||
sdMountDiagBegin();
|
||||
if (!_spi) {
|
||||
Serial.println("[BOOT] SD: shared SPI unavailable");
|
||||
} else if (!board.sdCardPresent()) {
|
||||
@@ -1099,6 +1108,7 @@ void setup() {
|
||||
Serial.println("[BOOT] SD: card detected; mounting at 4 MHz");
|
||||
const bool sd_begin_ok = SD.begin(PIN_SD_CS, *_spi, 4000000, "/sd", 6);
|
||||
sd_mounted = sd_begin_ok && SD.cardType() != CARD_NONE;
|
||||
sdMountDiagAttempt(4000000, sd_begin_ok, sd_mounted);
|
||||
if (!sd_mounted) {
|
||||
if (sd_begin_ok) {
|
||||
// Release only the unusable mount created above. SD.end() unregisters
|
||||
@@ -1112,7 +1122,10 @@ void setup() {
|
||||
}
|
||||
Serial.printf("[BOOT] SD mount: %s\n", sd_mounted ? "ok" : "failed");
|
||||
}
|
||||
sdMountDiagSetMounted(sd_mounted, sd_mounted ? 4000000 : 0);
|
||||
#else
|
||||
sdMountDiagBegin();
|
||||
uint32_t mounted_hz = 0;
|
||||
if (_spi) {
|
||||
// Try to mount the card on EVERY boot: even a device that keeps identity on SPIFFS
|
||||
// wants its churn-heavy contacts/channels on the card.
|
||||
@@ -1131,11 +1144,13 @@ void setup() {
|
||||
{ 300, 1000000 }, { 450, 1000000 }, { 650, 400000 }, { 900, 400000 },
|
||||
};
|
||||
int tries = want_full_sd ? 7 : 3;
|
||||
uint32_t mounted_hz = 0;
|
||||
for (int a = 0; a < tries && !sd_mounted; ++a) {
|
||||
SD.end();
|
||||
delay(kBootMount[a].settle_ms);
|
||||
if (SD.begin(PIN_SD_CS, *_spi, kBootMount[a].hz, "/sd", 6) && SD.cardType() != CARD_NONE) {
|
||||
const bool begin_ok = SD.begin(PIN_SD_CS, *_spi, kBootMount[a].hz, "/sd", 6);
|
||||
const bool card_ready = begin_ok && SD.cardType() != CARD_NONE;
|
||||
sdMountDiagAttempt(kBootMount[a].hz, begin_ok, card_ready);
|
||||
if (card_ready) {
|
||||
sd_mounted = true;
|
||||
mounted_hz = kBootMount[a].hz;
|
||||
}
|
||||
@@ -1151,13 +1166,18 @@ void setup() {
|
||||
if (sd_mounted && mounted_hz < 4000000) {
|
||||
SD.end();
|
||||
delay(60);
|
||||
if (SD.begin(PIN_SD_CS, *_spi, 4000000, "/sd", 6) && SD.cardType() != CARD_NONE) {
|
||||
const bool fast_begin_ok = SD.begin(PIN_SD_CS, *_spi, 4000000, "/sd", 6);
|
||||
const bool fast_ready = fast_begin_ok && SD.cardType() != CARD_NONE;
|
||||
sdMountDiagAttempt(4000000, fast_begin_ok, fast_ready);
|
||||
if (fast_ready) {
|
||||
Serial.printf("[BOOT] SD renegotiated %lu -> 4000000 Hz\n", (unsigned long)mounted_hz);
|
||||
mounted_hz = 4000000;
|
||||
} else {
|
||||
SD.end();
|
||||
delay(120);
|
||||
sd_mounted = SD.begin(PIN_SD_CS, *_spi, mounted_hz, "/sd", 6) && SD.cardType() != CARD_NONE;
|
||||
const bool fallback_begin_ok = SD.begin(PIN_SD_CS, *_spi, mounted_hz, "/sd", 6);
|
||||
sd_mounted = fallback_begin_ok && SD.cardType() != CARD_NONE;
|
||||
sdMountDiagAttempt(mounted_hz, fallback_begin_ok, sd_mounted);
|
||||
if (sd_mounted) Serial.printf("[BOOT] SD stays at %lu Hz (4 MHz renegotiation failed)\n", (unsigned long)mounted_hz);
|
||||
}
|
||||
}
|
||||
@@ -1165,6 +1185,7 @@ void setup() {
|
||||
if (sd_mounted) { mounted_hz = sdTryFastClock(PIN_SD_CS, *_spi, mounted_hz, "BOOT"); sd_mounted = mounted_hz != 0; }
|
||||
if (sd_mounted) { extern uint32_t g_sd_operating_hz; g_sd_operating_hz = mounted_hz; } // About-page readout (UITask.cpp)
|
||||
}
|
||||
sdMountDiagSetMounted(sd_mounted, mounted_hz);
|
||||
#endif
|
||||
if (sd_mounted) {
|
||||
g_contacts_on_sd = true; // every branch below routes contacts/channels to the card
|
||||
|
||||
+143
-29
@@ -2484,6 +2484,49 @@ static lv_color_t* g_draw_buffer = nullptr;
|
||||
// every mount/remount site (main.cpp boot adoption + the two UITask mounts) because SD.begin's
|
||||
// clock is the session clock; Settings -> About reports it on the R8 (no serial console there).
|
||||
uint32_t g_sd_operating_hz = 0;
|
||||
// Most supported boards expose no card-detect GPIO, so a completed filesystem
|
||||
// mount is the only positive proof that a card is connected. Preserve existing
|
||||
// mount attempts for the on-device diagnostic instead of issuing extra probes.
|
||||
struct SdMountDiagState {
|
||||
bool checked = false;
|
||||
bool mounted = false;
|
||||
bool last_begin_ok = false;
|
||||
uint8_t attempts = 0;
|
||||
uint32_t last_attempt_hz = 0;
|
||||
uint32_t mounted_hz = 0;
|
||||
};
|
||||
static volatile SdMountDiagState s_sd_diag;
|
||||
|
||||
void sdMountDiagBegin() {
|
||||
s_sd_diag.checked = true;
|
||||
s_sd_diag.mounted = false;
|
||||
s_sd_diag.last_begin_ok = false;
|
||||
s_sd_diag.attempts = 0;
|
||||
s_sd_diag.last_attempt_hz = 0;
|
||||
s_sd_diag.mounted_hz = 0;
|
||||
}
|
||||
|
||||
void sdMountDiagAttempt(uint32_t hz, bool begin_ok, bool card_ready) {
|
||||
s_sd_diag.checked = true;
|
||||
if (s_sd_diag.attempts < 0xFF) ++s_sd_diag.attempts;
|
||||
s_sd_diag.last_attempt_hz = hz;
|
||||
s_sd_diag.last_begin_ok = begin_ok;
|
||||
s_sd_diag.mounted = card_ready;
|
||||
if (card_ready) s_sd_diag.mounted_hz = hz;
|
||||
}
|
||||
|
||||
void sdMountDiagSetMounted(bool mounted, uint32_t hz) {
|
||||
s_sd_diag.checked = true;
|
||||
s_sd_diag.mounted = mounted;
|
||||
if (!mounted) s_sd_diag.mounted_hz = 0;
|
||||
else if (hz) s_sd_diag.mounted_hz = hz;
|
||||
}
|
||||
|
||||
static void sdDiagClockText(uint32_t hz, char* out, size_t cap) {
|
||||
if (hz >= 1000000) snprintf(out, cap, "%lu MHz", (unsigned long)(hz / 1000000));
|
||||
else if (hz > 0) snprintf(out, cap, "%lu kHz", (unsigned long)(hz / 1000));
|
||||
else snprintf(out, cap, "unknown");
|
||||
}
|
||||
static uint32_t g_draw_buf_px = 240 * LV_DRAW_BUF_LINES; // actual buffer size in px; shrinks if the full alloc fails at boot
|
||||
#if CAP_LARGE_SCREEN
|
||||
// UI resolution scaling (Tanmatsu, no touchscreen). LVGL renders at s_lv_pw x s_lv_ph (PHYSICAL
|
||||
@@ -12431,11 +12474,11 @@ static void sysInfoTextRest(char* buf, size_t cap) {
|
||||
(unsigned)(sketch_size / 1024u),
|
||||
(unsigned)(sketch_free / 1024u));
|
||||
|
||||
#if CAP_SD || defined(TLORA_PAGER)
|
||||
// microSD size + free. The FAT scan (usedBytes()) is done by the core-0 worker — never
|
||||
// on this UI thread — so the About sheet can't freeze on it. We just read the worker's
|
||||
// cached result here and request a (re)scan at most every 30 s.
|
||||
#if CAP_MICROSD
|
||||
{
|
||||
#if CAP_SD
|
||||
// SPI-SD size + free. This existing FAT scan stays on the core-0 worker so
|
||||
// opening About cannot freeze the UI; SD_MMC builds remain fully passive.
|
||||
static uint32_t sd_req_ms = 0;
|
||||
const uint32_t nowm = millis();
|
||||
// Once armed, only the worker may clear this request (after publishing
|
||||
@@ -12446,16 +12489,56 @@ static void sysInfoTextRest(char* buf, size_t cap) {
|
||||
if (ensureTileFetchTaskRunning())
|
||||
s_sdinfo_request = true; // worker rescans off-thread
|
||||
}
|
||||
if (!s_sdinfo_done)
|
||||
p += snprintf(buf + p, cap - p, "microSD\n \xE2\x80\xA6\n\n"); // … (computing)
|
||||
else if (s_sdinfo_ok)
|
||||
#endif
|
||||
char sd_clock[16];
|
||||
sdDiagClockText(s_sd_diag.mounted ? s_sd_diag.mounted_hz
|
||||
: s_sd_diag.last_attempt_hz,
|
||||
sd_clock, sizeof sd_clock);
|
||||
if (!s_sd_diag.checked) {
|
||||
p += snprintf(buf + p, cap - p, "microSD\n status: not checked\n\n");
|
||||
} else if (!s_sd_diag.mounted && s_sd_diag.attempts == 0) {
|
||||
p += snprintf(buf + p, cap - p,
|
||||
"microSD\n size: %llu MB\n free: %llu MB\n\n",
|
||||
"microSD\n status: not mounted\n mount was not attempted\n\n");
|
||||
} else if (!s_sd_diag.mounted) {
|
||||
p += snprintf(buf + p, cap - p,
|
||||
"microSD\n status: not mounted (missing or unreadable)\n"
|
||||
" last mount: %u attempt%s, %s\n last init: %s\n\n",
|
||||
(unsigned)s_sd_diag.attempts,
|
||||
s_sd_diag.attempts == 1 ? "" : "s",
|
||||
sd_clock, s_sd_diag.last_begin_ok ? "ok" : "failed");
|
||||
#if CAP_SD
|
||||
} else if (!s_sdinfo_done) {
|
||||
p += snprintf(buf + p, cap - p,
|
||||
"microSD\n status: connected / mounted\n"
|
||||
" mount: %u attempt%s @ %s\n size: checking...\n\n",
|
||||
(unsigned)s_sd_diag.attempts,
|
||||
s_sd_diag.attempts == 1 ? "" : "s", sd_clock);
|
||||
} else if (s_sdinfo_ok) {
|
||||
p += snprintf(buf + p, cap - p,
|
||||
"microSD\n status: connected / mounted\n"
|
||||
" mount: %u attempt%s @ %s\n size: %llu MB\n free: %llu MB\n\n",
|
||||
(unsigned)s_sd_diag.attempts,
|
||||
s_sd_diag.attempts == 1 ? "" : "s", sd_clock,
|
||||
(unsigned long long)(s_sdinfo_tot / (1024ull * 1024ull)),
|
||||
(unsigned long long)(s_sdinfo_free / (1024ull * 1024ull)));
|
||||
else
|
||||
p += snprintf(buf + p, cap - p, "microSD\n not mounted\n\n");
|
||||
} else {
|
||||
p += snprintf(buf + p, cap - p,
|
||||
"microSD\n status: mounted, capacity read failed\n"
|
||||
" mount: %u attempt%s @ %s\n\n",
|
||||
(unsigned)s_sd_diag.attempts,
|
||||
s_sd_diag.attempts == 1 ? "" : "s", sd_clock);
|
||||
#else
|
||||
} else {
|
||||
p += snprintf(buf + p, cap - p,
|
||||
"microSD\n status: connected / mounted\n"
|
||||
" mount: %u attempt%s @ %s\n\n",
|
||||
(unsigned)s_sd_diag.attempts,
|
||||
s_sd_diag.attempts == 1 ? "" : "s", sd_clock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
p += snprintf(buf + p, cap - p, "microSD\n not available on this hardware\n\n");
|
||||
#endif
|
||||
|
||||
// NVS usage across the whole 'nvs' partition (shared by Wi-Fi creds, the
|
||||
@@ -12541,7 +12624,7 @@ static void refreshSysInfo(unsigned long now) {
|
||||
if (lv_indev_get_scroll_dir(in) != LV_DIR_NONE) { next = now + 120; return; }
|
||||
}
|
||||
next = now + 1000;
|
||||
char buf[832];
|
||||
char buf[1024];
|
||||
sysInfoTextLive(buf, sizeof buf);
|
||||
lv_label_set_text(s_sysinfo_lbl, buf);
|
||||
// Slow tier: pushing identical text would still invalidate + repaint the whole
|
||||
@@ -12614,7 +12697,7 @@ static void refreshSleepDiag(unsigned long now) {
|
||||
|
||||
static void buildSystemInfoSettings() {
|
||||
lv_obj_t* body = createSettingsModal(TR("System Information"), SettingsModalKind::SystemInfo);
|
||||
char buf[832];
|
||||
char buf[1024];
|
||||
|
||||
// FLEX COLUMN, deliberately not the manual y cursor the rest of this file uses.
|
||||
// Both labels below are re-texted AFTER build with text whose LINE COUNT
|
||||
@@ -21868,8 +21951,16 @@ static bool sdAdoptLiveMount() {
|
||||
s_sd_mounted = true;
|
||||
s_sd_size = SD.cardSize();
|
||||
s_sd_retry_after_ms = 0;
|
||||
sdMountDiagSetMounted(true, g_sd_operating_hz);
|
||||
return true;
|
||||
}
|
||||
static bool sdBeginTracked(SPIClass* spi, uint32_t hz, bool* begin_ok_out = nullptr) {
|
||||
const bool begin_ok = spi && SD.begin(PIN_SD_CS, *spi, hz, "/sd", 6);
|
||||
const bool card_ready = begin_ok && SD.cardType() != CARD_NONE;
|
||||
if (begin_ok_out) *begin_ok_out = begin_ok;
|
||||
sdMountDiagAttempt(hz, begin_ok, card_ready);
|
||||
return card_ready;
|
||||
}
|
||||
static bool sdRuntimeLifecycleBusy();
|
||||
static bool fmSdTryMount() {
|
||||
// main.cpp may already have mounted this global SD object for DataStore.
|
||||
@@ -21902,12 +21993,13 @@ static bool fmSdTryMount() {
|
||||
#endif
|
||||
SPIClass* spi = sdSharedSPI();
|
||||
if (!spi) return false;
|
||||
sdMountDiagBegin();
|
||||
#if defined(TLORA_PAGER)
|
||||
// Vendor-compatible Pager sequence: the shared display/radio bus is already
|
||||
// running, all other CS lines are parked HIGH, and the card gets one 4 MHz
|
||||
// mount attempt. Never tear down that live shared bus or add a retry ladder.
|
||||
const bool begin_ok = SD.begin(PIN_SD_CS, *spi, 4000000, "/sd", 6);
|
||||
const bool mounted = begin_ok && SD.cardType() != CARD_NONE;
|
||||
bool begin_ok = false;
|
||||
const bool mounted = sdBeginTracked(spi, 4000000, &begin_ok);
|
||||
#else
|
||||
// Cold microSD cards — especially the first mount after boot — often fail
|
||||
// the initial SD.begin and historically only recovered after a physical
|
||||
@@ -21950,7 +22042,7 @@ static bool fmSdTryMount() {
|
||||
for (int attempt = 0; attempt < kAttempts; ++attempt) {
|
||||
SD.end();
|
||||
delay(kMountLadder[attempt].settle_ms);
|
||||
if (SD.begin(PIN_SD_CS, *spi, kMountLadder[attempt].hz, "/sd", 6) && SD.cardType() != CARD_NONE) {
|
||||
if (sdBeginTracked(spi, kMountLadder[attempt].hz)) {
|
||||
mounted = true;
|
||||
mounted_hz = kMountLadder[attempt].hz;
|
||||
break;
|
||||
@@ -21963,10 +22055,10 @@ static bool fmSdTryMount() {
|
||||
if (mounted && mounted_hz < 4000000) {
|
||||
SD.end();
|
||||
delay(60);
|
||||
if (!(SD.begin(PIN_SD_CS, *spi, 4000000, "/sd", 6) && SD.cardType() != CARD_NONE)) {
|
||||
if (!sdBeginTracked(spi, 4000000)) {
|
||||
SD.end();
|
||||
delay(120);
|
||||
mounted = SD.begin(PIN_SD_CS, *spi, mounted_hz, "/sd", 6) && SD.cardType() != CARD_NONE;
|
||||
mounted = sdBeginTracked(spi, mounted_hz);
|
||||
} else {
|
||||
mounted_hz = 4000000;
|
||||
}
|
||||
@@ -21986,6 +22078,7 @@ static bool fmSdTryMount() {
|
||||
// later mount only restores the independently SD-backed data consumers.
|
||||
s_sd_data_warn_next_ms = 0;
|
||||
#endif
|
||||
sdMountDiagSetMounted(true, mounted_hz);
|
||||
return true;
|
||||
}
|
||||
#if defined(TLORA_PAGER)
|
||||
@@ -21998,6 +22091,7 @@ static bool fmSdTryMount() {
|
||||
#else
|
||||
SD.end(); // clean up on failure
|
||||
#endif
|
||||
sdMountDiagSetMounted(false, 0);
|
||||
s_sd_retry_after_ms = millis() + 10000; // back off so we don't hammer the card
|
||||
return false;
|
||||
}
|
||||
@@ -22009,6 +22103,7 @@ static void fmSdUnmount() {
|
||||
#endif
|
||||
s_sd_mounted = false;
|
||||
s_sd_size = 0;
|
||||
sdMountDiagSetMounted(false, 0);
|
||||
}
|
||||
s_sd_retry_after_ms = 0; // a reinsert should be able to mount right away
|
||||
}
|
||||
@@ -23365,23 +23460,39 @@ static bool tanSdTryMount() {
|
||||
if (luaAudioStorageBusy()) return false;
|
||||
#endif
|
||||
if (millis() < s_tan_sd_retry_after) return false;
|
||||
const uint32_t mount_hz = (uint32_t)SDMMC_FREQ_DEFAULT * 1000u;
|
||||
if (SD_MMC.cardType() != CARD_NONE) {
|
||||
s_tan_sd_mounted = true;
|
||||
s_tan_sd_size = SD_MMC.cardSize();
|
||||
sdMountDiagSetMounted(true, 0); // preserve the boot-recorded clock when adopting its mount
|
||||
return true;
|
||||
}
|
||||
sdMountDiagBegin();
|
||||
bool attempted = false;
|
||||
bool begin_ok = false;
|
||||
#if defined(HAS_WIO_TRACKER_L2)
|
||||
// 20 MHz to match main.cpp's boot mount — re-begin()ning at Arduino's 40 MHz
|
||||
// default would quietly re-clock a card the boot already brought up at 20.
|
||||
if (SD_MMC.cardType() != CARD_NONE ||
|
||||
(WioTrackerL2Io::ready() && WioTrackerL2Io::setSdPower(true) &&
|
||||
SD_MMC.setPins(2, 3, 1) &&
|
||||
SD_MMC.begin("/sdcard", true, false, SDMMC_FREQ_DEFAULT) &&
|
||||
SD_MMC.cardType() != CARD_NONE)) {
|
||||
if (WioTrackerL2Io::ready() && WioTrackerL2Io::setSdPower(true) &&
|
||||
SD_MMC.setPins(2, 3, 1)) {
|
||||
attempted = true;
|
||||
begin_ok = SD_MMC.begin("/sdcard", true, false, SDMMC_FREQ_DEFAULT);
|
||||
}
|
||||
#elif defined(HAS_TDISPLAY_P4)
|
||||
// Hot-insert path (no-op when main.cpp already mounted at boot): 20 MHz like the boot ladder,
|
||||
// not Arduino's 40 MHz HIGHSPEED default.
|
||||
if (SD_MMC.begin("/sdcard", false /*4-bit*/, false, SDMMC_FREQ_DEFAULT) && SD_MMC.cardType() != CARD_NONE) {
|
||||
attempted = true;
|
||||
begin_ok = SD_MMC.begin("/sdcard", false /*4-bit*/, false, SDMMC_FREQ_DEFAULT);
|
||||
#else
|
||||
if (SD_MMC.begin("/sdcard", false /*4-bit*/) && SD_MMC.cardType() != CARD_NONE) {
|
||||
attempted = true;
|
||||
begin_ok = SD_MMC.begin("/sdcard", false /*4-bit*/);
|
||||
#endif
|
||||
const bool card_ready = begin_ok && SD_MMC.cardType() != CARD_NONE;
|
||||
if (attempted) sdMountDiagAttempt(mount_hz, begin_ok, card_ready);
|
||||
if (card_ready) {
|
||||
s_tan_sd_mounted = true;
|
||||
s_tan_sd_size = SD_MMC.cardSize();
|
||||
sdMountDiagSetMounted(true, mount_hz);
|
||||
return true;
|
||||
}
|
||||
#if defined(HAS_WIO_TRACKER_L2)
|
||||
@@ -23400,6 +23511,7 @@ static bool tanSdTryMount() {
|
||||
#else
|
||||
SD_MMC.end();
|
||||
#endif
|
||||
sdMountDiagSetMounted(false, 0);
|
||||
s_tan_sd_retry_after = millis() + 8000; // don't grind a missing card on every roots render
|
||||
return false;
|
||||
}
|
||||
@@ -25393,6 +25505,7 @@ static void fileTransferStorageIoFailed() {
|
||||
#else
|
||||
s_tan_sd_mounted = false;
|
||||
s_tan_sd_retry_after = millis() + 8000;
|
||||
sdMountDiagSetMounted(false, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -29638,7 +29751,7 @@ static void tileFetchTaskFn(void* arg) {
|
||||
if (luaNetWorkerPending()) { luaNetWorkerService(&client, &http); continue; }
|
||||
}
|
||||
#endif
|
||||
#if CAP_SD || defined(TLORA_PAGER)
|
||||
#if CAP_SD
|
||||
// microSD usage for the About page — the FAT scan runs here, off the UI thread.
|
||||
if (s_sdinfo_request) {
|
||||
// Publish busy before clearing request so the loop task never observes a
|
||||
@@ -57492,21 +57605,22 @@ static void sdHealthTick() {
|
||||
#endif
|
||||
SPIClass* spi = sdSharedSPI();
|
||||
if (!spi) return;
|
||||
sdMountDiagBegin();
|
||||
#if defined(TLORA_PAGER)
|
||||
// The Pager shares this SPIClass with display + radio: one 4 MHz attempt,
|
||||
// with every other CS parked HIGH and no SD.end() of a potentially live bus.
|
||||
const bool begin_ok = SD.begin(PIN_SD_CS, *spi, 4000000, "/sd", 6);
|
||||
const bool remounted = begin_ok && SD.cardType() != CARD_NONE;
|
||||
bool begin_ok = false;
|
||||
const bool remounted = sdBeginTracked(spi, 4000000, &begin_ok);
|
||||
#else
|
||||
SD.end();
|
||||
bool remounted = SD.begin(PIN_SD_CS, *spi, 4000000, "/sd", 6) &&
|
||||
SD.cardType() != CARD_NONE;
|
||||
bool remounted = sdBeginTracked(spi, 4000000);
|
||||
if (remounted) {
|
||||
const uint32_t hz = sdTryFastClock(PIN_SD_CS, *spi, 4000000, "SD"); // no-op unless SD_SPI_FAST_HZ
|
||||
remounted = hz != 0;
|
||||
if (remounted) g_sd_operating_hz = hz;
|
||||
}
|
||||
#endif
|
||||
sdMountDiagSetMounted(remounted, remounted ? g_sd_operating_hz : 0);
|
||||
if (remounted) {
|
||||
s_sd_mounted = true;
|
||||
s_sd_size = SD.cardSize();
|
||||
|
||||
@@ -27,6 +27,10 @@ struct ContactInfo;
|
||||
/** Maps bottom tabs (Home, Chats, Contacts, Set — no separate Net tab). */
|
||||
enum class TouchUiScreen : uint8_t { Home = 0, ChatInbox = 1, Contacts = 2, Settings = 3 };
|
||||
|
||||
void sdMountDiagBegin();
|
||||
void sdMountDiagAttempt(uint32_t hz, bool begin_ok, bool card_ready);
|
||||
void sdMountDiagSetMounted(bool mounted, uint32_t hz);
|
||||
|
||||
class UITask : public AbstractUITask {
|
||||
public:
|
||||
static const int MAX_UI_MESSAGES = 500;
|
||||
|
||||
@@ -161,6 +161,15 @@
|
||||
#define CAP_LOCK_SCREEN 0
|
||||
#endif
|
||||
|
||||
// Physical removable microSD slot, independent of the filesystem API used to
|
||||
// drive it. CAP_SD specifically means Arduino SD over SPI; these three boards
|
||||
// use SD_MMC instead but still need the same user-facing card diagnostics.
|
||||
#if CAP_SD || defined(HAS_WIO_TRACKER_L2) || defined(HAS_TANMATSU) || defined(HAS_TDISPLAY_P4)
|
||||
#define CAP_MICROSD 1
|
||||
#else
|
||||
#define CAP_MICROSD 0
|
||||
#endif
|
||||
|
||||
// Persisted, restart-to-apply UI-size selector. Large-screen boards already
|
||||
// expose it; the Pager adds font-only presets because its 480x222 viewport is
|
||||
// wide enough for larger type but too short for global geometry scaling.
|
||||
|
||||
@@ -379,7 +379,11 @@ static void wadameshSetup() {
|
||||
// the build (-Og "worked by luck"; -Os made the exists()-gated identity + prefs loads come up
|
||||
// empty: fresh node identity, default name, profile changes lost every reboot). The card's FAT
|
||||
// metadata is truthful, so the WHOLE store lives there now; FFat remains only the no-card fallback.
|
||||
g_sd_ok = SD_MMC.begin("/sdcard", false /*1-bit*/) && SD_MMC.cardType() != CARD_NONE;
|
||||
sdMountDiagBegin();
|
||||
const bool sd_begin_ok = SD_MMC.begin("/sdcard", false /*1-bit*/);
|
||||
g_sd_ok = sd_begin_ok && SD_MMC.cardType() != CARD_NONE;
|
||||
sdMountDiagAttempt((uint32_t)SDMMC_FREQ_DEFAULT * 1000u, sd_begin_ok, g_sd_ok);
|
||||
sdMountDiagSetMounted(g_sd_ok, g_sd_ok ? (uint32_t)SDMMC_FREQ_DEFAULT * 1000u : 0);
|
||||
printf("[storage] SD_MMC.begin = %s\n", g_sd_ok ? "OK" : "no card");
|
||||
if (g_sd_ok) {
|
||||
SD_MMC.mkdir("/meshcomod");
|
||||
|
||||
@@ -212,13 +212,18 @@ static void wadameshSetup() {
|
||||
{ true, SDMMC_FREQ_DEFAULT, "1-bit 20MHz" },
|
||||
{ true, 5000, "1-bit 5MHz" },
|
||||
};
|
||||
sdMountDiagBegin();
|
||||
uint32_t mounted_hz = 0;
|
||||
for (auto &t : tries) {
|
||||
g_sd_ok = SD_MMC.begin("/sdcard", t.onebit, false, t.khz) && SD_MMC.cardType() != CARD_NONE;
|
||||
const bool begin_ok = SD_MMC.begin("/sdcard", t.onebit, false, t.khz);
|
||||
g_sd_ok = begin_ok && SD_MMC.cardType() != CARD_NONE;
|
||||
sdMountDiagAttempt((uint32_t)t.khz * 1000u, begin_ok, g_sd_ok);
|
||||
printf("[storage] SD_MMC try %s -> %s\n", t.tag, g_sd_ok ? "OK" : "fail");
|
||||
if (g_sd_ok) break;
|
||||
if (g_sd_ok) { mounted_hz = (uint32_t)t.khz * 1000u; break; }
|
||||
SD_MMC.end();
|
||||
delay(120);
|
||||
}
|
||||
sdMountDiagSetMounted(g_sd_ok, mounted_hz);
|
||||
}
|
||||
printf("[storage] SD_MMC = %s\n", g_sd_ok ? "OK" : "no card");
|
||||
if (g_sd_ok) {
|
||||
|
||||
Reference in new issue
Block a user