Skip to content

Commit

Permalink
Merge pull request #540 from adafruit/fs-reinit-plus-titano
Browse files Browse the repository at this point in the history
Add PyPortal Titano plus fallback Fs reinit and repeated serial if Halted
  • Loading branch information
tyeth authored Jan 30, 2024
2 parents e254ac0 + 6b3c3aa commit 68ef76a
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 53 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/build-clang-doxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
name: WipperSnapper Build CI

on:
workflow_dispatch:
pull_request:
workflow_call:
secrets:
Expand Down Expand Up @@ -192,7 +193,7 @@ jobs:
strategy:
fail-fast: false
matrix:
arduino-platform: ["pyportal_tinyusb", "metro_m4_airliftlite_tinyusb"]
arduino-platform: ["pyportal_tinyusb", "pyportal_titano_tinyusb", "metro_m4_airliftlite_tinyusb"]
steps:
- uses: actions/setup-python@v4
with:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@



3 changes: 3 additions & 0 deletions examples/Wippersnapper_demo/.pyportal_titano_tinyusb.generate
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@



Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@



2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=Adafruit WipperSnapper
version=1.0.0-beta.75
version=1.0.0-beta.76
author=Adafruit
maintainer=Adafruit <[email protected]>
sentence=Arduino application for Adafruit.io WipperSnapper
Expand Down
6 changes: 6 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ build_flags = -DUSE_TINYUSB=1
[env:adafruit_pyportal_m4_titano]
extends = common:atsamd
board = adafruit_pyportal_m4_titano
; build_type = debug
; upload_protocol = jlink
; debug_tool = jlink
; monitor_port = jlink
; debug_init_break =
lib_ignore = USBHost
build_flags = -DUSE_TINYUSB=1
-DADAFRUIT_PYPORTAL_M4_TITANO

Expand Down
4 changes: 4 additions & 0 deletions src/Wippersnapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2306,9 +2306,13 @@ void Wippersnapper::errorWriteHang(String error) {
WS_DEBUG_PRINTLN(error);
#ifdef USE_TINYUSB
_fileSystem->writeToBootOut(error.c_str());
TinyUSBDevice.attach();
delay(500);
#endif
// Signal and hang forever
while (1) {
WS_DEBUG_PRINTLN("ERROR: Halted execution");
WS_DEBUG_PRINTLN(error.c_str());
WS.feedWDT();
statusLEDBlink(WS_LED_STATUS_ERROR_RUNTIME);
delay(1000);
Expand Down
2 changes: 1 addition & 1 deletion src/Wippersnapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
#endif

#define WS_VERSION \
"1.0.0-beta.75" ///< WipperSnapper app. version (semver-formatted)
"1.0.0-beta.76" ///< WipperSnapper app. version (semver-formatted)

// Reserved Adafruit IO MQTT topics
#define TOPIC_IO_THROTTLE "/throttle" ///< Adafruit IO Throttle MQTT Topic
Expand Down
6 changes: 6 additions & 0 deletions src/Wippersnapper_Boards.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
#define USE_STATUS_NEOPIXEL
#define STATUS_NEOPIXEL_PIN 2
#define STATUS_NEOPIXEL_NUM 1
#elif defined(ADAFRUIT_PYPORTAL_M4_TITANO)
#define BOARD_ID "pyportal-titano-tinyusb"
#define USE_TINYUSB
#define USE_STATUS_NEOPIXEL
#define STATUS_NEOPIXEL_PIN 2
#define STATUS_NEOPIXEL_NUM 1
#elif defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE)
#define BOARD_ID "metro-m4-airliftlite-tinyusb"
#define USE_TINYUSB
Expand Down
5 changes: 3 additions & 2 deletions src/Wippersnapper_Networking.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
#ifndef WIPPERSNAPPER_NETWORKING_H
#define WIPPERSNAPPER_NETWORKING_H

#if defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || defined(ADAFRUIT_PYPORTAL) || \
defined(ADAFRUIT_METRO_M4_EXPRESS) || defined(USE_AIRLIFT)
#if defined(ADAFRUIT_METRO_M4_EXPRESS) || \
defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || defined(ADAFRUIT_PYPORTAL) || \
defined(ADAFRUIT_PYPORTAL_M4_TITANO) || defined(USE_AIRLIFT)
#include "network_interfaces/Wippersnapper_AIRLIFT.h"
/** Nina-FW (adafruit fork) networking class */
typedef Wippersnapper_AIRLIFT Wippersnapper_WiFi;
Expand Down
41 changes: 22 additions & 19 deletions src/provisioning/littlefs/WipperSnapper_LittleFS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@
WipperSnapper_LittleFS::WipperSnapper_LittleFS() {
// Attempt to initialize filesystem
if (!LittleFS.begin()) {
WS_DEBUG_PRINTLN("ERROR: Failure initializing LittleFS!");
setStatusLEDColor(RED);
while (1)
;
fsHalt("ERROR: Failure initializing LittleFS!");
}
}

Expand All @@ -51,25 +49,22 @@ WipperSnapper_LittleFS::~WipperSnapper_LittleFS() { LittleFS.end(); }
void WipperSnapper_LittleFS::parseSecrets() {
// Check if `secrets.json` file exists on FS
if (!LittleFS.exists("/secrets.json")) {
WS_DEBUG_PRINTLN("ERROR: No secrets.json found on filesystem - did you "
"upload credentials?");
fsHalt();
fsHalt("ERROR: No secrets.json found on filesystem - did you upload "
"credentials?");
}

// Attempt to open secrets.json file for reading
File secretsFile = LittleFS.open("/secrets.json", "r");
if (!secretsFile) {
WS_DEBUG_PRINTLN("ERROR: Could not open secrets.json file for reading!");
fsHalt();
fsHalt("ERROR: Could not open secrets.json file for reading!");
}

// Attempt to deserialize the file's JSON document
JsonDocument doc;
DeserializationError error = deserializeJson(doc, secretsFile);
if (error) {
WS_DEBUG_PRINT("ERROR: deserializeJson() failed with code ");
WS_DEBUG_PRINTLN(error.c_str());
fsHalt();
fsHalt(String("ERROR: deserializeJson() failed with code ") +
error.c_str());
}

// Extract a config struct from the JSON document
Expand All @@ -78,18 +73,16 @@ void WipperSnapper_LittleFS::parseSecrets() {
// Validate the config struct is not filled with default values
if (strcmp(WS._config.aio_user, "YOUR_IO_USERNAME_HERE") == 0 ||
strcmp(WS._config.aio_key, "YOUR_IO_KEY_HERE") == 0) {
WS_DEBUG_PRINTLN(
fsHalt(
"ERROR: Invalid IO credentials in secrets.json! TO FIX: Please change "
"io_username and io_key to match your Adafruit IO credentials!\n");
fsHalt();
}

if (strcmp(WS._config.network.ssid, "YOUR_WIFI_SSID_HERE") == 0 ||
strcmp(WS._config.network.pass, "YOUR_WIFI_PASS_HERE") == 0) {
WS_DEBUG_PRINTLN("ERROR: Invalid network credentials in secrets.json! TO "
"FIX: Please change network_ssid and network_password to "
"match your Adafruit IO credentials!\n");
fsHalt();
fsHalt("ERROR: Invalid network credentials in secrets.json! TO FIX: Please "
"change network_ssid and network_password to match your Adafruit IO "
"credentials!\n");
}

// Close the file
Expand All @@ -99,11 +92,21 @@ void WipperSnapper_LittleFS::parseSecrets() {
LittleFS.end();
}

void WipperSnapper_LittleFS::fsHalt() {
/**************************************************************************/
/*!
@brief Halts execution and blinks the status LEDs yellow.
@param msg
Error message to print to serial console.
*/
/**************************************************************************/
void WipperSnapper_LittleFS::fsHalt(String msg) {
statusLEDSolid(WS_LED_STATUS_FS_WRITE);
while (1) {
statusLEDSolid(WS_LED_STATUS_FS_WRITE);
WS_DEBUG_PRINTLN("Fatal Error: Halted execution!");
WS_DEBUG_PRINTLN(msg.c_str());
delay(1000);
yield();
}
}

#endif
2 changes: 1 addition & 1 deletion src/provisioning/littlefs/WipperSnapper_LittleFS.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class WipperSnapper_LittleFS {
WipperSnapper_LittleFS();
~WipperSnapper_LittleFS();
void parseSecrets();
void fsHalt();
void fsHalt(String msg);
};

extern Wippersnapper WS;
Expand Down
52 changes: 26 additions & 26 deletions src/provisioning/tinyusb/Wippersnapper_FS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
*/
#if defined(ARDUINO_MAGTAG29_ESP32S2) || defined(ARDUINO_METRO_ESP32S2) || \
defined(ARDUINO_FUNHOUSE_ESP32S2) || \
defined(ARDUINO_FUNHOUSE_ESP32S2) || defined(ADAFRUIT_PYPORTAL_M4_TITANO) || \
defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || defined(ADAFRUIT_PYPORTAL) || \
defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32S2) || \
Expand Down Expand Up @@ -95,19 +95,17 @@ Wippersnapper_FS::Wippersnapper_FS() {

// If a filesystem does not already exist - attempt to initialize a new
// filesystem
if (!initFilesystem()) {
WS_DEBUG_PRINTLN("ERROR Initializing Filesystem");
if (!initFilesystem() && !initFilesystem(true)) {
setStatusLEDColor(RED);
while (1)
;
fsHalt("ERROR Initializing Filesystem");
}

// Initialize USB-MSD
initUSBMSC();

// If we created a new filesystem, halt until user RESETs device.
if (_freshFS)
fsHalt();
fsHalt("New filesystem created! Press the reset button on your board.");
}

/************************************************************/
Expand All @@ -120,16 +118,18 @@ Wippersnapper_FS::~Wippersnapper_FS() {}
/**************************************************************************/
/*!
@brief Initializes the flash filesystem.
@param force_format
If true, forces a new filesystem to be created. [DESTRUCTIVE]
@return True if filesystem initialized correctly, false otherwise.
*/
/**************************************************************************/
bool Wippersnapper_FS::initFilesystem() {
bool Wippersnapper_FS::initFilesystem(bool force_format) {
// Init. flash library
if (!flash.begin())
return false;

// Check if FS exists
if (!wipperFatFs.begin(&flash)) {
if (force_format || !wipperFatFs.begin(&flash)) {
// No filesystem exists - create a new FS
// NOTE: THIS WILL ERASE ALL DATA ON THE FLASH
if (!makeFilesystem())
Expand Down Expand Up @@ -325,7 +325,7 @@ void Wippersnapper_FS::createSecretsFile() {
"Please edit it to reflect your Adafruit IO and network credentials. "
"When you're done, press RESET on the board.");
#endif
fsHalt();
fsHalt("ERROR: Please edit the secrets.json file. Then, reset your board.");
}

/**************************************************************************/
Expand All @@ -337,17 +337,14 @@ void Wippersnapper_FS::parseSecrets() {
// Attempt to open the secrets.json file for reading
File32 secretsFile = wipperFatFs.open("/secrets.json");
if (!secretsFile) {
WS_DEBUG_PRINTLN("ERROR: Could not open secrets.json file for reading!");
fsHalt();
fsHalt("ERROR: Could not open secrets.json file for reading!");
}

// Attempt to deserialize the file's JSON document
JsonDocument doc;
DeserializationError error = deserializeJson(doc, secretsFile);
if (error) {
WS_DEBUG_PRINT("ERROR: deserializeJson() failed with code ");
WS_DEBUG_PRINTLN(error.c_str());
fsHalt();
fsHalt(String("ERROR: Unable to parse secrets.json file - deserializeJson() failed with code") + error.c_str());
}

// Extract a config struct from the JSON document
Expand All @@ -362,7 +359,7 @@ void Wippersnapper_FS::parseSecrets() {
"The \"io_username/io_key\" fields within secrets.json are invalid, please "
"change it to match your Adafruit IO credentials. Then, press RESET.");
#endif
fsHalt();
fsHalt("ERROR: Invalid IO credentials in secrets.json! TO FIX: Please change io_username and io_key to match your Adafruit IO credentials!");
}

if (strcmp(WS._config.network.ssid, "YOUR_WIFI_SSID_HERE") == 0 || strcmp(WS._config.network.pass, "YOUR_WIFI_PASS_HERE") == 0) {
Expand All @@ -373,7 +370,7 @@ void Wippersnapper_FS::parseSecrets() {
"The \"network_ssid and network_password\" fields within secrets.json are invalid, please "
"change it to match your WiFi credentials. Then, press RESET.");
#endif
fsHalt();
fsHalt("ERROR: Invalid network credentials in secrets.json! TO FIX: Please change network_ssid and network_password to match your Adafruit IO credentials!");
}

// Close secrets.json file
Expand All @@ -396,17 +393,25 @@ void Wippersnapper_FS::writeToBootOut(PGM_P str) {
bootFile.close();
} else {
WS_DEBUG_PRINTLN("ERROR: Unable to open wipper_boot_out.txt for logging!");
// feels like we should check why, if good use-case ok, otherwise fsHalt
// as indicates fs corruption or disc access issue (maybe latter is okay)
}
}

/**************************************************************************/
/*!
@brief Halts execution and blinks the status LEDs yellow.
@param msg
Error message to print to serial console.
*/
/**************************************************************************/
void Wippersnapper_FS::fsHalt() {
void Wippersnapper_FS::fsHalt(String msg) {
TinyUSBDevice.attach();
delay(500);
statusLEDSolid(WS_LED_STATUS_FS_WRITE);
while (1) {
// statusLEDSolid(WS_LED_STATUS_FS_WRITE);
WS_DEBUG_PRINTLN("Fatal Error: Halted execution!");
WS_DEBUG_PRINTLN(msg.c_str());
delay(1000);
yield();
}
Expand All @@ -432,8 +437,7 @@ void Wippersnapper_FS::createDisplayConfig() {
// Create and fill JSON document from displayConfig
JsonDocument doc;
if (!doc.set(displayConfig)) {
WS_DEBUG_PRINTLN("ERROR: Unable to set displayConfig, no space in arduinoJSON document!");
fsHalt();
fsHalt("ERROR: Unable to set displayConfig, no space in arduinoJSON document!");
}
// Write the file out to the filesystem
serializeJsonPretty(doc, displayFile);
Expand All @@ -454,18 +458,14 @@ void Wippersnapper_FS::parseDisplayConfig(displayConfig &dispCfg) {
// Attempt to open file for JSON parsing
File32 file = wipperFatFs.open("/display_config.json", FILE_READ);
if (!file) {
WS_DEBUG_PRINTLN(
"FATAL ERROR: Unable to open display_config.json for parsing");
fsHalt();
fsHalt("FATAL ERROR: Unable to open display_config.json for parsing");
}

// Attempt to deserialize the file's json document
JsonDocument doc;
DeserializationError error = deserializeJson(doc, file);
if (error) {
WS_DEBUG_PRINTLN("deserializeJson() of display file failed, rc:")
Serial.println(error.c_str());
fsHalt();
fsHalt(String("FATAL ERROR: Unable to parse display_config.json - deserializeJson() failed with code") + error.c_str());
}
// Close the file, we're done with it
file.close();
Expand Down
4 changes: 2 additions & 2 deletions src/provisioning/tinyusb/Wippersnapper_FS.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Wippersnapper_FS {
Wippersnapper_FS();
~Wippersnapper_FS();

bool initFilesystem();
bool initFilesystem(bool force_format = false);
void initUSBMSC();

void eraseCPFS();
Expand All @@ -54,7 +54,7 @@ class Wippersnapper_FS {
void createSecretsFile();
bool createBootFile();
void writeToBootOut(PGM_P str);
void fsHalt();
void fsHalt(String msg);

void parseSecrets();

Expand Down

0 comments on commit 68ef76a

Please sign in to comment.