For about 3 weeks I've been fighting with my Giga trying to get it to write files to an attached flash drive on the USB1 port. It will either hard crash or return a -22 error code and then it refuses to write files anymore. The confusing thing is that it works fine for a while but then stops working after a short pause. It logs it's own attempted server touches (HEAD requests just to keep the connection alive and available). After the first log, subsequent logging fails.
Here's my H and CPP files: Logs.h & Logs.cpp
Logs.h:
#pragma once
//------------------------------------------------------------------------------------------
#include "Arduino.h"
#include "WString.h"
#define __FILENAME__ (__builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__)
using namespace arduino;
//------------------------------------------------------------------------------------------
void DataLogStart(void);
void DataLog(const String &Text);
void DataLogEnd(void);
void QuickFormatUSB(void);
String uriEncode(const String &Text);
//------------------------------------------------------------------------------------------
Logs.cpp:
#include "Logs.h"
#include "ValidateRoutines.h"
#include <DigitalOut.h>
#include <FATFileSystem.h>
#include <Arduino_USBHostMbed5.h>
#include "lvgl.h"
#include "Times.h"
#include <WiFi.h>
#include <WiFiSSLClient.h>
#include "BUSYBomb.h"
//------------------------------------------------------------------------------------------
using namespace mbed;
USBHostMSD msd;
FATFileSystem usb("usb");
volatile bool usb_mounted=false;
void driveAttached();
void driveDettached();
void ResetUSB(void);
unsigned long timeoutStart;
unsigned long timeoutEnd;
signed long timeout;
#define timeoutLoop(timeout_test,timeout_length,timeout_failure_action) \
timeoutStart=millis(); \
timeoutEnd=timeoutStart+timeout_length; \
timeout=timeoutEnd-timeoutStart; \
while(!(timeout_test) && timeout>0) \
{ \
timeoutStart=millis(); \
timeout=timeoutEnd-timeoutStart; \
} \
if(timeout<=0){timeout_failure_action};
#define db Serial.print(String(__FILENAME__)+" ");Serial.println(__LINE__);
#define dbt(STRING) Serial.println(STRING);
//------------------------------------------------------------------------------------------
void DataLogStart(void)
{
BUSYBomb
db
if(usb_mounted)
{
db
ResetUSB();
return;
}
db
usb_mounted=false;
db
digitalWrite(PA_15, LOW);
db
delay(200);
db
digitalWrite(PA_15, HIGH);
db
/*if(!msd.attach_detected_callback(driveAttached))
{
dbt("DataLogStart: USBHostMSD::attach_detected_callback(...) call failed");
}
if(!msd.attach_removed_callback(driveDettached))
{
dbt("DataLogStart: USBHostMSD::attach_removed_callback(...) call failed");
}
*/
db
timeoutLoop(msd.connect(),1000,dbt("Timeout during \"msd::connect\" loop.");return;)
db
timeoutLoop(msd.connected(),1000,dbt("\"msd::connected(...)\" timeout.");)
// Attempt to mount the USB file system
db
if(usb.mount(&msd) != 0)
{
dbt("\"usb::mount(...)\" failed.");
return;
}
db
usb_mounted = true;
}
//------------------------------------------------------------------------------------------
void DataLog(const String &Text)
{
BUSYBomb
dbt("DataLog function entered.");
dbt("String to log: "+Text);
if (!usb_mounted)
{
db
DataLogStart();
db
if (!usb_mounted)
{
dbt("DatalogStart(...) failed during DataLog call.");
return;
}
}
String CurTime = getLocaltime();
String Line;
Line.reserve(CurTime.length() + Text.length() + 3); // Preallocate memory
Line += CurTime;
Line += "\t";
Line += Text;
Line += "\n";
db
if (!msd.connected())
{
dbt("USB (usb_mounted) flagged as mounted but msd::connected(...) returned false.");
return;
}
db
FILE *f = fopen("/usb/agsmac.log", "a+");
if (f == NULL)
{
dbt("\"fopen\" failed.");
return;
}
db
char *line = const_cast<char*>(Line.c_str());
size_t bytesToWrite=Line.length();
size_t bytesWritten=0;
bool writeProgress=true;
size_t writeLoopCount=0;
do
{
writeLoopCount++;
bytesWritten=fprintf(f, "%s", line);
if(bytesWritten>0)
{
bytesToWrite-=bytesWritten;
line+=bytesWritten;
writeProgress=true;
}
else if(bytesWritten<0)
{
fclose(f);
dbt("File write operation (fprintf) failed.");
return;
}
else if(bytesWritten==0)
{
fflush(f);
dbt("File write operation 0 bytes written. (fflush) called.");
if(!writeProgress)
{
dbt("No write progress 2 iterations in a row, haulting write operations.");
break;
}
writeProgress=false;
}
}
while(bytesToWrite>0 && bytesWritten>0 && writeProgress);
dbt("Write operation loop iteration count: "+String(writeLoopCount));
//db
//timeoutLoop(fflush(f)==0,10000,dbt("File flush operation (fflush) timeout.");)
db
timeoutLoop(fclose(f)==0,10000,dbt("File close operation (fclose) timeout."););
dbt("DataLog function leaving.");
}
//------------------------------------------------------------------------------------------ line 167
void DataLogEnd(void)
{
BUSYBomb
dbt("DataLogEnd: Preparing drive for safe removal...");
if (usb_mounted)
{
dbt("DataLogEnd: Unmounting the filesystem...");
if (usb.unmount() != 0)
{
dbt("DataLogEnd: Failed to unmount the filesystem.");
}
else
{
dbt("DataLogEnd: Filesystem unmounted successfully.");
}
usb_mounted = false;
}
dbt("DataLogEnd: Resetting USB connection...");
delay(500);
db
pinMode(PA_15, OUTPUT); // Control USB power
db
digitalWrite(PA_15, LOW); // Turn off USB power
db
delay(10); // Initial short delay
db
if (!msd.connected())
{
Serial.println("USB disconnected successfully.");
}
else
{
Serial.println("USB is still active after power-off.");
}
delay(990); // Remaining delay
db
digitalWrite(PA_15, HIGH); // Turn USB power back on
db
delay(500); // Allow time for the device to reinitialize
dbt("DataLogEnd: Drive is ready for safe removal.");
}
//------------------------------------------------------------------------------------------
void QuickFormatUSB(void)
{
BUSYBomb
dbt("QuickFormatUSB: Starting quick format...");
// Ensure the USB drive is connected
if (!msd.connected())
{
dbt("QuickFormatUSB: USB drive not connected. Attempting reset.");
ResetUSB();
db
if (!msd.connected())
{
dbt("QuickFormatUSB: Reset failed. USB drive is still not connected.");
return;
}
}
// If the filesystem is mounted, unmount it
db
if (usb_mounted)
{
dbt("QuickFormatUSB: Unmounting the filesystem...");
if(usb.unmount()!=0)
{
dbt("QuickFormatUSB: Failed to unmount the filesystem. Attempting reset.");
ResetUSB();
db
if (!msd.connected())
{
dbt("QuickFormatUSB: Reset failed. USB drive is not connected.");
return;
}
}
db
usb_mounted = false;
}
// Perform quick format by initializing the filesystem
dbt("QuickFormatUSB: Initializing the filesystem...");
int usbReformat=usb.reformat(&msd);
if (usbReformat != 0)
{
dbt("QuickFormatUSB: Failed to format the USB drive: Error code "+String(usbReformat,HEX)+". Attempting reset.");
ResetUSB();
db
if (!msd.connected())
{
dbt("QuickFormatUSB: Reset failed. USB drive is still not connected.");
return;
}
// Retry format after reset
db
usbReformat=usb.reformat(&msd);
if (usbReformat != 0)
{
dbt("QuickFormatUSB: Retry failed: Error code "+String(usbReformat,HEX)+" USB drive format unsuccessful.");
return;
}
}
// Remount the filesystem
dbt("QuickFormatUSB: Mounting the filesystem...");
int usbMount=usb.mount(&msd);
if (usbMount != 0)
{
dbt("QuickFormatUSB: Failed to remount the filesystem: Error code "+String(usbMount,HEX)+".");
return;
}
db
usb_mounted = true;
dbt("QuickFormatUSB: Format completed successfully.");
}
//------------------------------------------------------------------------------------------
void ResetUSB()
{
BUSYBomb
dbt("ResetUSB: Entered");
// Step 1: Unmount the file system
if (usb_mounted)
{
int result = usb.unmount();
if (result == 0)
{
dbt("\"usb::unmount(...)\" failed.");
}
else
{
dbt("\"usb::unmount(...)\" succeeded.");
}
usb_mounted = false;
}
// Step 2: Reset the USB connection
db
pinMode(PA_15, OUTPUT); // Set the USB power control pin
digitalWrite(PA_15, LOW); // Turn off USB port power
delay(1000); // Wait for a second
digitalWrite(PA_15, HIGH); // Turn USB port power back on
// Step 3: Reinitialize the USB device
db
timeoutLoop(msd.connect(),1000,dbt("Timeout during \"msd::connect(...)\".");)
// Step 4: Mount the file system
db
timeoutLoop(msd.connected(),1000,dbt("Timeout during \"msd::connected(...)\".");)
}
//------------------------------------------------------------------------------------------
void driveAttached()
{
ResetUSB();
//DataLogStart();
}
//------------------------------------------------------------------------------------------
void driveDettached()
{
ResetUSB();
//DataLogStart();
usb_mounted=false;
}
//------------------------------------------------------------------------------------------
String uriEncode(const String &Text)
{
const char *safeChars = "$-_.+!*'(),?/~"; // Allowed characters
String Res;
char buffer[4]; // Buffer for percent-encoding
for (size_t i = 0; i < Text.length(); i++)
{
char c = Text.charAt(i);
// Check if the character is alphanumeric or a safe character
if (isalnum(c) || strchr(safeChars, c))
{
Res += c; // Append safe character as-is
}
else
{
// Percent-encode the character
snprintf(buffer, sizeof(buffer), "%%%02X", (unsigned char)c);
Res += buffer;
}
}
return Res;
}//------------------------------------------------------------------------------------------
void SendLogs(const String &Server)
{
//usb.rename("/usb/agsmac.log","/usb/agsmac_topush.log");
}
//------------------------------------------------------------------------------------------
I've been "conversing" with ChatGPT 4o trying to troubleshoot this but to no avail. I've ordered a couple of compatible Ethernet Shields as a backup workaround but I'd really rather not to have to rely on the SD Card functionality as from my previous experience with the Uno it's rather slow.
It should be noted that I'm using older versions of the board libraries as using newer version causes renders using the LVGL library to malfunction and is unusable.
I've also tried using version regressing the Arduino_USBHostMbed5, also to no avail.
Here's the current versions of the regressed libraries I'm on:
/*
use version 4.1.5 of the [Arduino Mbed OS Giga Boards] library.
use version 8.3.11 of the [lvgl] library.
use version 0.2.0 of the [Arduino_USBHostMbed5] library.
*/

