Compare commits
3 commits
432f17b2be
...
0217ece5e5
| Author | SHA1 | Date | |
|---|---|---|---|
| 0217ece5e5 | |||
| ee8b42a020 | |||
| a349130858 |
1 changed files with 170 additions and 51 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
// 20260213 ChatGPT
|
// 20260214 ChatGPT
|
||||||
// $Id$
|
// $Id$
|
||||||
// $HeadURL$
|
// $HeadURL$
|
||||||
|
|
||||||
|
|
@ -7,8 +7,19 @@
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <SD.h>
|
#include <SD.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
#include "driver/gpio.h" // gpio_get_level()
|
||||||
#include "tbeam_supreme_adapter.h"
|
#include "tbeam_supreme_adapter.h"
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Configuration toggles
|
||||||
|
// -------------------------
|
||||||
|
#define ENABLE_SD_RAIL_CYCLE 1 // Power-cycle AXP2101 BLDO1 (SD rail) at boot.
|
||||||
|
#define ENABLE_PIN_DUMPS 1 // Log SPI pin logic levels at key points (NON-INTRUSIVE).
|
||||||
|
#define STARTUP_SERIAL_DELAY_MS 5000
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Globals
|
||||||
|
// -------------------------
|
||||||
static SPIClass sdSpiH(HSPI);
|
static SPIClass sdSpiH(HSPI);
|
||||||
static SPIClass sdSpiF(FSPI);
|
static SPIClass sdSpiF(FSPI);
|
||||||
static SPIClass* g_sdSpi = nullptr;
|
static SPIClass* g_sdSpi = nullptr;
|
||||||
|
|
@ -16,10 +27,10 @@ static const char* g_sdBusName = "none";
|
||||||
static uint32_t g_sdFreq = 0;
|
static uint32_t g_sdFreq = 0;
|
||||||
static XPowersLibInterface* g_pmu = nullptr;
|
static XPowersLibInterface* g_pmu = nullptr;
|
||||||
|
|
||||||
static const char* kRootTestFile = "/Exercise_05_test.txt";
|
static const char* kRootTestFile = "/Exercise_05_test.txt";
|
||||||
static const char* kNestedDir = "/test/testsub1/testsubsub1";
|
static const char* kNestedDir = "/test/testsub1/testsubsub1";
|
||||||
static const char* kNestedTestFile = "/test/testsub1/testsubsub1/Exercise_05_test.txt";
|
static const char* kNestedTestFile = "/test/testsub1/testsubsub1/Exercise_05_test.txt";
|
||||||
static const char* kPayload = "This is a test";
|
static const char* kPayload = "This is a test";
|
||||||
|
|
||||||
enum class WatchState : uint8_t {
|
enum class WatchState : uint8_t {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
|
|
@ -33,37 +44,127 @@ static uint8_t g_absentVotes = 0;
|
||||||
static uint32_t g_lastPollMs = 0;
|
static uint32_t g_lastPollMs = 0;
|
||||||
static uint32_t g_lastFullScanMs = 0;
|
static uint32_t g_lastFullScanMs = 0;
|
||||||
static uint32_t g_lastPeriodicActionMs = 0;
|
static uint32_t g_lastPeriodicActionMs = 0;
|
||||||
static const uint32_t kPollIntervalAbsentMs = 1000;
|
|
||||||
static const uint32_t kPollIntervalMountedMs = 2000;
|
|
||||||
static const uint32_t kFullScanIntervalMs = 10000;
|
|
||||||
static const uint32_t kPeriodicActionMs = 15000;
|
|
||||||
static const uint8_t kVotesToPresent = 2;
|
|
||||||
//static const uint8_t kVotesToAbsent = 4;
|
|
||||||
static const uint8_t kVotesToAbsent = 5; // More votes needed to declare absent to prevent false removes on transient errors.
|
|
||||||
|
|
||||||
//static const uint32_t kStartupWarmupMs = 800;
|
static const uint32_t kPollIntervalAbsentMs = 1000;
|
||||||
static const uint32_t kStartupWarmupMs = 1500; // Longer warmup to allow PMU and card stabilization after power-on.
|
static const uint32_t kPollIntervalMountedMs = 2000;
|
||||||
|
static const uint32_t kFullScanIntervalMs = 10000;
|
||||||
|
static const uint32_t kPeriodicActionMs = 15000;
|
||||||
|
|
||||||
|
static const uint8_t kVotesToPresent = 2;
|
||||||
|
static const uint8_t kVotesToAbsent = 5; // More votes needed to declare absent to prevent false removes.
|
||||||
|
static const uint32_t kStartupWarmupMs = 1500; // Allow PMU and SD rail to stabilize.
|
||||||
|
|
||||||
static uint32_t g_logSeq = 0;
|
static uint32_t g_logSeq = 0;
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Logging helpers
|
||||||
|
// -------------------------
|
||||||
static void logf(const char* fmt, ...) {
|
static void logf(const char* fmt, ...) {
|
||||||
char msg[192];
|
char msg[192];
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vsnprintf(msg, sizeof(msg), fmt, args);
|
vsnprintf(msg, sizeof(msg), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
Serial.printf("[%10lu][%06lu] %s\r\n", (unsigned long)millis(), (unsigned long)g_logSeq++, msg);
|
Serial.printf("[%10lu][%06lu] %s\r\n",
|
||||||
|
(unsigned long)millis(),
|
||||||
|
(unsigned long)g_logSeq++,
|
||||||
|
msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dumpPmu(const char* tag, XPowersLibInterface* pmu) {
|
||||||
|
if (!pmu) {
|
||||||
|
logf("PMU(%s): pmu=null", tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bldo1 = pmu->isPowerChannelEnable(XPOWERS_BLDO1);
|
||||||
|
int vbus = pmu->getVbusVoltage();
|
||||||
|
int batt = pmu->getBattVoltage();
|
||||||
|
|
||||||
|
logf("PMU(%s): BLDO1(SD)=%s VBUS=%dmV VBAT=%dmV",
|
||||||
|
tag, bldo1 ? "ON" : "OFF", vbus, batt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMPORTANT: this function MUST NOT modify pin modes (regression cause).
|
||||||
|
static void dumpSdPins(const char* tag) {
|
||||||
|
#if ENABLE_PIN_DUMPS
|
||||||
|
const gpio_num_t CS = (gpio_num_t)tbeam_supreme::sdCs();
|
||||||
|
const gpio_num_t SCK = (gpio_num_t)tbeam_supreme::sdSck();
|
||||||
|
const gpio_num_t MISO = (gpio_num_t)tbeam_supreme::sdMiso();
|
||||||
|
const gpio_num_t MOSI = (gpio_num_t)tbeam_supreme::sdMosi();
|
||||||
|
|
||||||
|
int cs = gpio_get_level(CS);
|
||||||
|
int sck = gpio_get_level(SCK);
|
||||||
|
int miso = gpio_get_level(MISO);
|
||||||
|
int mosi = gpio_get_level(MOSI);
|
||||||
|
|
||||||
|
logf("PINS(%s): CS=%d SCK=%d MISO=%d MOSI=%d", tag, cs, sck, miso, mosi);
|
||||||
|
#else
|
||||||
|
(void)tag;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Power + bus conditioning
|
||||||
|
// -------------------------
|
||||||
|
static void forceSpiDeselected() {
|
||||||
|
pinMode(tbeam_supreme::sdCs(), OUTPUT);
|
||||||
|
digitalWrite(tbeam_supreme::sdCs(), HIGH);
|
||||||
|
|
||||||
|
pinMode(tbeam_supreme::imuCs(), OUTPUT);
|
||||||
|
digitalWrite(tbeam_supreme::imuCs(), HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool initPmuForSdPower() {
|
static bool initPmuForSdPower() {
|
||||||
return tbeam_supreme::initPmuForPeripherals(g_pmu, &Serial);
|
bool ok = tbeam_supreme::initPmuForPeripherals(g_pmu, &Serial);
|
||||||
|
if (!ok) {
|
||||||
|
logf("ERROR: PMU init failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logf("PMU adapter: AXP2101 ready, BLDO1(SD)=%s",
|
||||||
|
g_pmu && g_pmu->isPowerChannelEnable(XPOWERS_BLDO1) ? "ON" : "OFF");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cycleSdRail(XPowersLibInterface* pmu,
|
||||||
|
uint32_t off_ms = 250,
|
||||||
|
uint32_t on_settle_ms = 600) {
|
||||||
|
#if ENABLE_SD_RAIL_CYCLE
|
||||||
|
if (!pmu) {
|
||||||
|
logf("SD rail cycle skipped: pmu=null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpPmu("pre-sd-cycle", pmu);
|
||||||
|
|
||||||
|
// Ensure the card is NOT selected while power is unstable.
|
||||||
|
forceSpiDeselected();
|
||||||
|
dumpSdPins("pre-sd-cycle");
|
||||||
|
|
||||||
|
pmu->disablePowerOutput(XPOWERS_BLDO1);
|
||||||
|
delay(off_ms);
|
||||||
|
|
||||||
|
pmu->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
|
||||||
|
pmu->enablePowerOutput(XPOWERS_BLDO1);
|
||||||
|
delay(on_settle_ms);
|
||||||
|
|
||||||
|
dumpPmu("post-sd-cycle", pmu);
|
||||||
|
dumpSdPins("post-sd-cycle");
|
||||||
|
#else
|
||||||
|
(void)pmu; (void)off_ms; (void)on_settle_ms;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// SD helpers
|
||||||
|
// -------------------------
|
||||||
static const char* cardTypeToString(uint8_t type) {
|
static const char* cardTypeToString(uint8_t type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CARD_MMC: return "MMC";
|
case CARD_MMC: return "MMC";
|
||||||
case CARD_SD: return "SDSC";
|
case CARD_SD: return "SDSC";
|
||||||
case CARD_SDHC: return "SDHC/SDXC";
|
case CARD_SDHC: return "SDHC/SDXC";
|
||||||
default: return "UNKNOWN";
|
default: return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,22 +173,26 @@ static bool tryMountWithBus(SPIClass& bus, const char* busName, uint32_t hz, boo
|
||||||
bus.end();
|
bus.end();
|
||||||
delay(10);
|
delay(10);
|
||||||
|
|
||||||
// Keep inactive devices deselected on shared bus lines.
|
forceSpiDeselected();
|
||||||
pinMode(tbeam_supreme::sdCs(), OUTPUT);
|
|
||||||
digitalWrite(tbeam_supreme::sdCs(), HIGH);
|
|
||||||
pinMode(tbeam_supreme::imuCs(), OUTPUT);
|
|
||||||
digitalWrite(tbeam_supreme::imuCs(), HIGH);
|
|
||||||
|
|
||||||
bus.begin(tbeam_supreme::sdSck(), tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi(), tbeam_supreme::sdCs());
|
bus.begin(tbeam_supreme::sdSck(), tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi(), tbeam_supreme::sdCs());
|
||||||
|
|
||||||
|
// SD SPI "idle clocks" ritual: CS HIGH + >= 74 clocks with MOSI high (0xFF).
|
||||||
|
digitalWrite(tbeam_supreme::sdCs(), HIGH);
|
||||||
delay(2);
|
delay(2);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
bus.transfer(0xFF); // 80 clocks total
|
||||||
|
}
|
||||||
|
delay(2);
|
||||||
|
|
||||||
|
dumpSdPins("after-idle-clocks");
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
logf("SD: trying bus=%s freq=%lu Hz", busName, (unsigned long)hz);
|
logf("SD: trying bus=%s freq=%lu Hz", busName, (unsigned long)hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SD.begin(tbeam_supreme::sdCs(), bus, hz)) {
|
if (!SD.begin(tbeam_supreme::sdCs(), bus, hz)) {
|
||||||
if (verbose) {
|
if (verbose) logf("SD: mount failed (possible non-FAT format, power, or bus issue)");
|
||||||
logf("SD: mount failed (possible non-FAT format, power, or bus issue)");
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,7 +212,7 @@ static bool mountPreferred(bool verbose) {
|
||||||
return tryMountWithBus(sdSpiH, "HSPI", 400000, verbose);
|
return tryMountWithBus(sdSpiH, "HSPI", 400000, verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mountCard() {
|
static bool mountCardFullScan() {
|
||||||
const uint32_t freqs[] = {400000, 1000000, 4000000, 10000000};
|
const uint32_t freqs[] = {400000, 1000000, 4000000, 10000000};
|
||||||
|
|
||||||
for (uint8_t i = 0; i < (sizeof(freqs) / sizeof(freqs[0])); ++i) {
|
for (uint8_t i = 0; i < (sizeof(freqs) / sizeof(freqs[0])); ++i) {
|
||||||
|
|
@ -131,8 +236,8 @@ static bool mountCard() {
|
||||||
static void printCardInfo() {
|
static void printCardInfo() {
|
||||||
uint8_t cardType = SD.cardType();
|
uint8_t cardType = SD.cardType();
|
||||||
uint64_t cardSizeMB = SD.cardSize() / (1024ULL * 1024ULL);
|
uint64_t cardSizeMB = SD.cardSize() / (1024ULL * 1024ULL);
|
||||||
uint64_t totalMB = SD.totalBytes() / (1024ULL * 1024ULL);
|
uint64_t totalMB = SD.totalBytes() / (1024ULL * 1024ULL);
|
||||||
uint64_t usedMB = SD.usedBytes() / (1024ULL * 1024ULL);
|
uint64_t usedMB = SD.usedBytes() / (1024ULL * 1024ULL);
|
||||||
|
|
||||||
logf("SD type: %s", cardTypeToString(cardType));
|
logf("SD type: %s", cardTypeToString(cardType));
|
||||||
logf("SD size: %llu MB", cardSizeMB);
|
logf("SD size: %llu MB", cardSizeMB);
|
||||||
|
|
@ -143,9 +248,7 @@ static void printCardInfo() {
|
||||||
|
|
||||||
static bool ensureDirRecursive(const char* path) {
|
static bool ensureDirRecursive(const char* path) {
|
||||||
String full(path);
|
String full(path);
|
||||||
if (!full.startsWith("/")) {
|
if (!full.startsWith("/")) full = "/" + full;
|
||||||
full = "/" + full;
|
|
||||||
}
|
|
||||||
|
|
||||||
int start = 1;
|
int start = 1;
|
||||||
while (start > 0 && start < (int)full.length()) {
|
while (start > 0 && start < (int)full.length()) {
|
||||||
|
|
@ -160,12 +263,9 @@ static bool ensureDirRecursive(const char* path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slash < 0) {
|
if (slash < 0) break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
start = slash + 1;
|
start = slash + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,9 +319,7 @@ static void permissionsDemo(const char* path) {
|
||||||
|
|
||||||
static bool verifyMountedCard() {
|
static bool verifyMountedCard() {
|
||||||
File root = SD.open("/", FILE_READ);
|
File root = SD.open("/", FILE_READ);
|
||||||
if (!root) {
|
if (!root) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
root.close();
|
root.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -245,6 +343,9 @@ static void runCardWorkflow() {
|
||||||
permissionsDemo(kRootTestFile);
|
permissionsDemo(kRootTestFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Watcher state transitions
|
||||||
|
// -------------------------
|
||||||
static void setStateMounted() {
|
static void setStateMounted() {
|
||||||
if (g_watchState != WatchState::MOUNTED) {
|
if (g_watchState != WatchState::MOUNTED) {
|
||||||
logf("EVENT: card inserted/mounted");
|
logf("EVENT: card inserted/mounted");
|
||||||
|
|
@ -264,13 +365,22 @@ static void setStateAbsent() {
|
||||||
g_watchState = WatchState::ABSENT;
|
g_watchState = WatchState::ABSENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Arduino entry points
|
||||||
|
// -------------------------
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println("[WATCHER: startup]");
|
Serial.println("[WATCHER: startup]");
|
||||||
Serial.println("Sleeping for 5 seconds to allow Serial Monitor connection...");
|
|
||||||
delay(5000); // Time to open Serial Monitor after reset
|
|
||||||
|
|
||||||
Serial.println("\r\n==================================================");
|
// De-select SPI devices immediately.
|
||||||
|
forceSpiDeselected();
|
||||||
|
dumpSdPins("very-early");
|
||||||
|
|
||||||
|
logf("Sleeping for %lu ms to allow Serial Monitor connection...", (unsigned long)STARTUP_SERIAL_DELAY_MS);
|
||||||
|
delay(STARTUP_SERIAL_DELAY_MS);
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("==================================================");
|
||||||
Serial.println("Exercise 05: SD Card Watcher");
|
Serial.println("Exercise 05: SD Card Watcher");
|
||||||
Serial.println("==================================================");
|
Serial.println("==================================================");
|
||||||
Serial.printf("Pins: CS=%d SCK=%d MISO=%d MOSI=%d\r\n",
|
Serial.printf("Pins: CS=%d SCK=%d MISO=%d MOSI=%d\r\n",
|
||||||
|
|
@ -278,13 +388,20 @@ void setup() {
|
||||||
tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi());
|
tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi());
|
||||||
Serial.printf("PMU I2C: SDA1=%d SCL1=%d\r\n",
|
Serial.printf("PMU I2C: SDA1=%d SCL1=%d\r\n",
|
||||||
tbeam_supreme::i2cSda(), tbeam_supreme::i2cScl());
|
tbeam_supreme::i2cSda(), tbeam_supreme::i2cScl());
|
||||||
Serial.println("Note: SD must be FAT16/FAT32 for Arduino SD library.\r\n");
|
Serial.println("Note: SD must be FAT16/FAT32 for Arduino SD library.");
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
initPmuForSdPower();
|
initPmuForSdPower();
|
||||||
|
dumpPmu("post-pmu-init", g_pmu);
|
||||||
|
|
||||||
|
// Software equivalent of "remove/insert card".
|
||||||
|
cycleSdRail(g_pmu);
|
||||||
|
|
||||||
logf("Watcher: waiting %lu ms for SD rail/card stabilization", (unsigned long)kStartupWarmupMs);
|
logf("Watcher: waiting %lu ms for SD rail/card stabilization", (unsigned long)kStartupWarmupMs);
|
||||||
delay(kStartupWarmupMs);
|
delay(kStartupWarmupMs);
|
||||||
|
|
||||||
// Warm-up attempts before first status decision.
|
dumpSdPins("pre-warmup-mount");
|
||||||
|
|
||||||
bool warmMounted = false;
|
bool warmMounted = false;
|
||||||
for (uint8_t i = 0; i < 3; ++i) {
|
for (uint8_t i = 0; i < 3; ++i) {
|
||||||
if (mountPreferred(false)) {
|
if (mountPreferred(false)) {
|
||||||
|
|
@ -293,6 +410,7 @@ void setup() {
|
||||||
}
|
}
|
||||||
delay(200);
|
delay(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (warmMounted) {
|
if (warmMounted) {
|
||||||
logf("Watcher: startup warmup mount succeeded");
|
logf("Watcher: startup warmup mount succeeded");
|
||||||
setStateMounted();
|
setStateMounted();
|
||||||
|
|
@ -304,9 +422,9 @@ void setup() {
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
const uint32_t now = millis();
|
const uint32_t now = millis();
|
||||||
const uint32_t pollInterval = (g_watchState == WatchState::MOUNTED)
|
const uint32_t pollInterval =
|
||||||
? kPollIntervalMountedMs
|
(g_watchState == WatchState::MOUNTED) ? kPollIntervalMountedMs : kPollIntervalAbsentMs;
|
||||||
: kPollIntervalAbsentMs;
|
|
||||||
if ((uint32_t)(now - g_lastPollMs) < pollInterval) {
|
if ((uint32_t)(now - g_lastPollMs) < pollInterval) {
|
||||||
delay(10);
|
delay(10);
|
||||||
return;
|
return;
|
||||||
|
|
@ -321,14 +439,14 @@ void loop() {
|
||||||
g_lastPeriodicActionMs = now;
|
g_lastPeriodicActionMs = now;
|
||||||
}
|
}
|
||||||
g_presentVotes = 0;
|
g_presentVotes = 0;
|
||||||
g_absentVotes = 0;
|
g_absentVotes = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// One immediate remount attempt prevents false remove events on transient SPI errors.
|
// One immediate remount attempt prevents false removes on transient SPI errors.
|
||||||
if (mountPreferred(false) && verifyMountedCard()) {
|
if (mountPreferred(false) && verifyMountedCard()) {
|
||||||
g_presentVotes = 0;
|
g_presentVotes = 0;
|
||||||
g_absentVotes = 0;
|
g_absentVotes = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,11 +459,12 @@ void loop() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ABSENT/UNKNOWN state
|
||||||
bool mounted = mountPreferred(false);
|
bool mounted = mountPreferred(false);
|
||||||
if (!mounted && (uint32_t)(now - g_lastFullScanMs) >= kFullScanIntervalMs) {
|
if (!mounted && (uint32_t)(now - g_lastFullScanMs) >= kFullScanIntervalMs) {
|
||||||
g_lastFullScanMs = now;
|
g_lastFullScanMs = now;
|
||||||
logf("Watcher: preferred probe failed, running full scan");
|
logf("Watcher: preferred probe failed, running full scan");
|
||||||
mounted = mountCard();
|
mounted = mountCardFullScan();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue