Skip to content
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

Add PyPortal Titano plus fallback Fs reinit and repeated serial if Halted #540

Merged
merged 8 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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!");
tyeth marked this conversation as resolved.
Show resolved Hide resolved
}
}

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) {
tyeth marked this conversation as resolved.
Show resolved Hide resolved
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);
brentru marked this conversation as resolved.
Show resolved Hide resolved
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) {
tyeth marked this conversation as resolved.
Show resolved Hide resolved
// 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
Loading