-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No fs format nor file recreation and boot reason changes #656
base: main
Are you sure you want to change the base?
Changes from 14 commits
9b52d98
e6bafe8
09c5b8b
7f02707
eb966ff
1d6fb07
2ea44c6
d0b9a59
4b911bf
b18fcf8
f454535
293c8ba
3fc98a2
2c0b752
2f1cce7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,6 +97,7 @@ Wippersnapper_FS::Wippersnapper_FS() { | |
WS_DEBUG_PRINTLN(project_dependencies); | ||
WS_DEBUG_PRINTLN("*********************"); | ||
WS_PRINTER.flush(); | ||
delay(50); // give host a chance to finish reading serial buffer | ||
#endif | ||
// Detach USB device during init. | ||
TinyUSBDevice.detach(); | ||
|
@@ -105,17 +106,34 @@ Wippersnapper_FS::Wippersnapper_FS() { | |
|
||
// If a filesystem does not already exist - attempt to initialize a new | ||
// filesystem | ||
if (!initFilesystem() && !initFilesystem(true)) { | ||
setStatusLEDColor(RED); | ||
fsHalt("ERROR Initializing Filesystem"); | ||
if (!initFilesystem()) { | ||
if (WS.brownOutCausedReset) { | ||
// try once more for good measure | ||
delay(10); // let power stablise after failure | ||
if (!initFilesystem()) { | ||
// no lights, save power as we're probably on a low battery | ||
fsHalt("Brownout detected. Couldn't initialise filesystem."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please add some descriptive text/instructions on what to do if we couldn't recreate the FS after a brownout? |
||
} | ||
} else if (!WS.brownOutCausedReset && !initFilesystem(true)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a brownout was detected, all the handling for this was performed inside the Consider changing this to an |
||
setStatusLEDColor(RED); | ||
fsHalt("ERROR Initializing Filesystem"); | ||
} | ||
} | ||
|
||
// Initialize USB-MSD | ||
initUSBMSC(); | ||
|
||
// If we created a new filesystem, halt until user RESETs device. | ||
tyeth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (_freshFS) | ||
fsHalt("New filesystem created! Press the reset button on your board."); | ||
{ | ||
WS_DEBUG_PRINTLN("New filesystem created! Resetting the board shortly..."); | ||
WS_PRINTER.flush(); | ||
tyeth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
WS.enableWDT(500); | ||
while (1) | ||
{ | ||
delay(1000); | ||
} | ||
Comment on lines
+131
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is great, I like the idea of resetting instead of instructing the user to reset! Shorten this by doing:
|
||
} | ||
} | ||
|
||
/************************************************************/ | ||
|
@@ -159,32 +177,39 @@ bool Wippersnapper_FS::initFilesystem(bool force_format) { | |
if (!wipperFatFs.begin(&flash)) | ||
return false; | ||
|
||
//TODO: Don't do this unless we need the space and createSecrets fails | ||
// If CircuitPython was previously installed - erase CPY FS | ||
eraseCPFS(); | ||
|
||
// If WipperSnapper was previously installed - remove the | ||
// wippersnapper_boot_out.txt file | ||
eraseBootFile(); | ||
// Also, should probably relabel drive to WIPPER if CIRCUITPY was there | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be possible to do this within |
||
// using setVolumeLabel(), but note the FS must be unmounted first | ||
|
||
// No file indexing on macOS | ||
wipperFatFs.mkdir("/.fseventsd/"); | ||
File32 writeFile = wipperFatFs.open("/.fseventsd/no_log", FILE_WRITE); | ||
if (!writeFile) | ||
return false; | ||
writeFile.close(); | ||
|
||
writeFile = wipperFatFs.open("/.metadata_never_index", FILE_WRITE); | ||
if (!writeFile) | ||
return false; | ||
writeFile.close(); | ||
if (!wipperFatFs.exists("/.fseventsd/no_log")) | ||
{ | ||
wipperFatFs.mkdir("/.fseventsd/"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While we're in it, let's refactor out the macOS-specific handling to a new function, |
||
File32 writeFile = wipperFatFs.open("/.fseventsd/no_log", FILE_WRITE); | ||
if (!writeFile) | ||
return false; | ||
writeFile.close(); | ||
} | ||
|
||
writeFile = wipperFatFs.open("/.Trashes", FILE_WRITE); | ||
if (!writeFile) | ||
return false; | ||
writeFile.close(); | ||
if (!wipperFatFs.exists("/.metadata_never_index")) | ||
{ | ||
File32 writeFile = wipperFatFs.open("/.metadata_never_index", FILE_WRITE); | ||
if (!writeFile) | ||
return false; | ||
writeFile.close(); | ||
} | ||
if (!wipperFatFs.exists("/.Trashes")) | ||
{ | ||
File32 writeFile = wipperFatFs.open("/.Trashes", FILE_WRITE); | ||
if (!writeFile) | ||
return false; | ||
writeFile.close(); | ||
} | ||
|
||
// Create wippersnapper_boot_out.txt file | ||
if (!createBootFile()) | ||
if (!createBootFile() && !WS.brownOutCausedReset) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to check if a brownout happened here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We still check the bootlog contents in createBootfile, and print if there is a discrepency. In the event of a failure to write bootlog, assuming the secrets are still valid, we don't want to call it a failure by returning false |
||
return false; | ||
|
||
// Check if secrets.json file already exists | ||
|
@@ -241,6 +266,9 @@ bool Wippersnapper_FS::configFileExists() { | |
*/ | ||
/**************************************************************************/ | ||
void Wippersnapper_FS::eraseCPFS() { | ||
if (WS.brownOutCausedReset){ | ||
return; // Can't serial print here, in next PR check we're not out of space | ||
} | ||
if (wipperFatFs.exists("/boot_out.txt")) { | ||
wipperFatFs.remove("/boot_out.txt"); | ||
wipperFatFs.remove("/code.py"); | ||
|
@@ -269,44 +297,66 @@ void Wippersnapper_FS::eraseBootFile() { | |
bool Wippersnapper_FS::createBootFile() { | ||
bool is_success = false; | ||
char sMAC[18] = {0}; | ||
String newContent; | ||
|
||
File32 bootFile = wipperFatFs.open("/wipper_boot_out.txt", FILE_WRITE); | ||
if (bootFile) { | ||
bootFile.println("Adafruit.io WipperSnapper"); | ||
// Generate new content | ||
newContent += "Adafruit.io WipperSnapper\n"; | ||
newContent += "Firmware Version: " + String(WS_VERSION) + "\n"; | ||
newContent += "Board ID: " + String(BOARD_ID) + "\n"; | ||
sprintf(sMAC, "%02X:%02X:%02X:%02X:%02X:%02X", WS._macAddr[0], | ||
WS._macAddr[1], WS._macAddr[2], WS._macAddr[3], WS._macAddr[4], | ||
WS._macAddr[5]); | ||
newContent += "MAC Address: " + String(sMAC) + "\n"; | ||
|
||
bootFile.print("Firmware Version: "); | ||
bootFile.println(WS_VERSION); | ||
#if PRINT_DEPENDENCIES | ||
newContent += ("Build dependencies:\n"); | ||
newContent += (project_dependencies); | ||
newContent += ("\n"); | ||
#endif | ||
|
||
bootFile.print("Board ID: "); | ||
bootFile.println(BOARD_ID); | ||
#ifdef ARDUINO_ARCH_ESP32 | ||
newContent += "ESP-IDF Version: " + String(ESP.getSdkVersion()) + "\n"; | ||
newContent += "ESP32 Core Version: " + String(ESP.getCoreVersion()) + "\n"; | ||
#endif | ||
|
||
sprintf(sMAC, "%02X:%02X:%02X:%02X:%02X:%02X", WS._macAddr[0], | ||
WS._macAddr[1], WS._macAddr[2], WS._macAddr[3], WS._macAddr[4], | ||
WS._macAddr[5]); | ||
bootFile.print("MAC Address: "); | ||
bootFile.println(sMAC); | ||
// Check if the file exists and read its content | ||
File32 bootFile = wipperFatFs.open("/wipper_boot_out.txt", FILE_READ); | ||
if (bootFile) { | ||
String existingContent; | ||
while (bootFile.available()) { | ||
existingContent += char(bootFile.read()); | ||
} | ||
bootFile.close(); | ||
|
||
#if PRINT_DEPENDENCIES | ||
bootFile.println("Build dependencies:"); | ||
bootFile.println(project_dependencies); | ||
#endif | ||
// Compare existing content with new content | ||
if (existingContent == newContent) { | ||
WS_DEBUG_PRINTLN("INFO: wipper_boot_out.txt already exists with the " | ||
"same content."); | ||
return true; // No need to overwrite | ||
} else { | ||
WS_DEBUG_PRINTLN("INFO: wipper_boot_out.txt exists but with different " | ||
"content. Overwriting..."); | ||
} | ||
} else { | ||
WS_DEBUG_PRINTLN("INFO: could not open wipper_boot_out.txt for reading. " | ||
"Creating new file..."); | ||
} | ||
|
||
// Print ESP-specific info to boot file | ||
#ifdef ARDUINO_ARCH_ESP32 | ||
// Get version of ESP-IDF | ||
bootFile.print("ESP-IDF Version: "); | ||
bootFile.println(ESP.getSdkVersion()); | ||
// Get version of this core | ||
bootFile.print("ESP32 Core Version: "); | ||
bootFile.println(ESP.getCoreVersion()); | ||
#endif | ||
if (WS.brownOutCausedReset){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we checking for a brownout here, again? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We wanted to inform that the bootlog isn't correct but we can't update it. I guess I could return true instead, or comment this as to why |
||
return false; | ||
} | ||
|
||
// Overwrite the file with new content | ||
bootFile = wipperFatFs.open("/wipper_boot_out.txt", FILE_WRITE); | ||
if (bootFile) { | ||
bootFile.print(newContent); | ||
bootFile.flush(); | ||
bootFile.close(); | ||
is_success = true; | ||
} else { | ||
bootFile.close(); | ||
WS_DEBUG_PRINTLN("ERROR: Unable to open wipper_boot_out.txt for writing!"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't think we'll see this except in debug builds with Tx monitored. The next PR (#655) will resolve this. |
||
} | ||
|
||
return is_success; | ||
} | ||
|
||
|
@@ -338,6 +388,7 @@ void Wippersnapper_FS::createSecretsFile() { | |
secretsFile.flush(); | ||
secretsFile.close(); | ||
delay(2500); | ||
tyeth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
initUSBMSC(); // re-init USB MSC to show new file to user for editing | ||
tyeth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Signal to user that action must be taken (edit secrets.json) | ||
writeToBootOut( | ||
|
@@ -367,7 +418,23 @@ void Wippersnapper_FS::parseSecrets() { | |
// Attempt to deserialize the file's JSON document | ||
JsonDocument doc; | ||
DeserializationError error = deserializeJson(doc, secretsFile); | ||
if (error) { | ||
if (error == DeserializationError::EmptyInput) | ||
{ | ||
if (WS.brownOutCausedReset) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A special case to handle the brownout detection shouldn't be located here. We should only handle the brownout detection/errors within the class constructor/init. |
||
{ | ||
fsHalt("ERROR: Empty secrets.json file, can't recreate due to brownout - recharge or must be fixed manually."); | ||
} | ||
else | ||
{ | ||
// TODO: Can't serial print here, in next PR check we're not out of space | ||
WS_DEBUG_PRINTLN("ERROR: Empty secrets.json file, recreating..."); | ||
secretsFile.close(); | ||
wipperFatFs.remove("/secrets.json"); | ||
createSecretsFile(); // calls fsHalt | ||
} | ||
} | ||
else if (error) | ||
{ | ||
fsHalt(String("ERROR: Unable to parse secrets.json file - " | ||
"deserializeJson() failed with code") + | ||
error.c_str()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused about tracing the brownout detection throughout the
FS
class.Could you help clarify the following:
brownOutCausedReset
is set withinget_and_print_reset_reason_for_cpu()
.brownOutCausedReset
which isn't a function