fix: run FTP server in dedicated FreeRTOS task to unblock LVGL
Move ftpSrv.handleFTP() from Arduino loop() into a dedicated FreeRTOS task pinned to core 0, leaving core 1 free for LVGL display updates. FTP callbacks now only set volatile flags (ftp_ui_dirty, ftp_sd_dirty) which the main loop polls to safely update UI and NeoPixel from core 1. This eliminates the 20-second PASV data connection timeouts caused by handleFTP() competing with display.update() for CPU time. Also fix pre-existing BLACK constant build error in display_manager.cpp.
This commit is contained in:
Vendored
+1
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"Jason2866.esp-decoder",
|
||||
"pioarduino.pioarduino-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
|
||||
@@ -51,7 +51,7 @@ bool DisplayManager::init() {
|
||||
if (pct > 100) pct = 100;
|
||||
gfx->setBrightness((uint8_t)(((uint16_t)pct * 255 + 50) / 100));
|
||||
}
|
||||
gfx->fillScreen(BLACK);
|
||||
gfx->fillScreen((uint16_t)0x0000);
|
||||
Serial.println("[DISP] Panel OK");
|
||||
|
||||
/* ── LVGL 9 init ───────────────────────────────────────────── */
|
||||
|
||||
+49
-13
@@ -72,6 +72,12 @@ static bool pmic_ok = false;
|
||||
static unsigned long last_time_update = 0;
|
||||
static unsigned long last_batt_update = 0;
|
||||
|
||||
// FTP task → main loop cross-core signalling (set by FTP callbacks, consumed in loop)
|
||||
enum FtpUiState : uint8_t { FTP_ST_IDLE, FTP_ST_CONNECTED, FTP_ST_TRANSFERRING };
|
||||
static volatile FtpUiState ftp_ui_state = FTP_ST_IDLE;
|
||||
static volatile bool ftp_ui_dirty = false; // UI label + LED need refresh
|
||||
static volatile bool ftp_sd_dirty = false; // SD usage info needs refresh
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NeoPixel helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -141,6 +147,7 @@ static void updateSdInfo() {
|
||||
|
||||
/**
|
||||
* Called on FTP connect / disconnect events.
|
||||
* NOTE: Runs on the FTP task (core 0) — only set flags here, never call LVGL/UI.
|
||||
*/
|
||||
void ftpCallback(FtpOperation ftpOperation, uint32_t freeSpace, uint32_t totalSpace) {
|
||||
switch (ftpOperation) {
|
||||
@@ -148,38 +155,42 @@ void ftpCallback(FtpOperation ftpOperation, uint32_t freeSpace, uint32_t totalSp
|
||||
Serial.println("[FTP] Client connected");
|
||||
ftp_client_on = true;
|
||||
ftp_transfer = false;
|
||||
ui_set_ftp("Connected");
|
||||
ftp_ui_state = FTP_ST_CONNECTED;
|
||||
ftp_ui_dirty = true;
|
||||
break;
|
||||
case FTP_DISCONNECT:
|
||||
Serial.println("[FTP] Client disconnected");
|
||||
ftp_client_on = false;
|
||||
ftp_transfer = false;
|
||||
ui_set_ftp("Idle");
|
||||
ftp_ui_state = FTP_ST_IDLE;
|
||||
ftp_ui_dirty = true;
|
||||
break;
|
||||
case FTP_FREE_SPACE_CHANGE:
|
||||
Serial.printf("[FTP] Free space: %u / %u\n", freeSpace, totalSpace);
|
||||
updateSdInfo();
|
||||
ftp_sd_dirty = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
updateLed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during file transfer operations.
|
||||
* NOTE: Runs on the FTP task (core 0) — only set flags here, never call LVGL/UI.
|
||||
*/
|
||||
void ftpTransferCallback(FtpTransferOperation ftpOperation, const char *name, uint32_t transferredSize) {
|
||||
switch (ftpOperation) {
|
||||
case FTP_UPLOAD_START:
|
||||
Serial.printf("[FTP] Upload start: %s\n", name);
|
||||
ftp_transfer = true;
|
||||
ui_set_ftp("Transferring");
|
||||
ftp_ui_state = FTP_ST_TRANSFERRING;
|
||||
ftp_ui_dirty = true;
|
||||
break;
|
||||
case FTP_DOWNLOAD_START:
|
||||
Serial.printf("[FTP] Download start: %s\n", name);
|
||||
ftp_transfer = true;
|
||||
ui_set_ftp("Transferring");
|
||||
ftp_ui_state = FTP_ST_TRANSFERRING;
|
||||
ftp_ui_dirty = true;
|
||||
break;
|
||||
case FTP_UPLOAD:
|
||||
case FTP_DOWNLOAD:
|
||||
@@ -187,18 +198,19 @@ void ftpTransferCallback(FtpTransferOperation ftpOperation, const char *name, ui
|
||||
case FTP_TRANSFER_STOP:
|
||||
Serial.printf("[FTP] Transfer done: %s (%u bytes)\n", name, transferredSize);
|
||||
ftp_transfer = false;
|
||||
ui_set_ftp(ftp_client_on ? "Connected" : "Idle");
|
||||
updateSdInfo();
|
||||
ftp_ui_state = ftp_client_on ? FTP_ST_CONNECTED : FTP_ST_IDLE;
|
||||
ftp_ui_dirty = true;
|
||||
ftp_sd_dirty = true;
|
||||
break;
|
||||
case FTP_TRANSFER_ERROR:
|
||||
Serial.printf("[FTP] Transfer error: %s\n", name);
|
||||
ftp_transfer = false;
|
||||
ui_set_ftp(ftp_client_on ? "Connected" : "Idle");
|
||||
ftp_ui_state = ftp_client_on ? FTP_ST_CONNECTED : FTP_ST_IDLE;
|
||||
ftp_ui_dirty = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
updateLed();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -438,7 +450,16 @@ static void initNtp() {
|
||||
Serial.println("[NTP] Warning: time not yet synced (will update in background)");
|
||||
}
|
||||
|
||||
/** Start FTP server with callbacks */
|
||||
/** FTP task — runs handleFTP() in a dedicated loop on core 0 */
|
||||
static void ftpTask(void *param) {
|
||||
(void)param;
|
||||
for (;;) {
|
||||
ftpSrv.handleFTP();
|
||||
vTaskDelay(pdMS_TO_TICKS(1)); // yield ~1 ms between iterations
|
||||
}
|
||||
}
|
||||
|
||||
/** Start FTP server with callbacks and launch dedicated task */
|
||||
static void initFtp() {
|
||||
Serial.println("[FTP] Starting FTP server (user: kode, port: 21)...");
|
||||
ftpSrv.setCallback(ftpCallback);
|
||||
@@ -446,7 +467,11 @@ static void initFtp() {
|
||||
/* Set local IP so PASV mode sends the correct address to clients */
|
||||
ftpSrv.setLocalIp(WiFi.localIP());
|
||||
ftpSrv.begin("kode", "kode");
|
||||
Serial.printf("[FTP] FTP server ready (PASV IP: %s, data port: 50009)\n",
|
||||
|
||||
/* Run FTP in its own task on core 0 so it never blocks LVGL on core 1 */
|
||||
xTaskCreatePinnedToCore(ftpTask, "ftp", 8192, NULL, 1, NULL, 0);
|
||||
|
||||
Serial.printf("[FTP] FTP server ready on core 0 (PASV IP: %s, data port: 50009)\n",
|
||||
WiFi.localIP().toString().c_str());
|
||||
ui_set_ftp("Idle");
|
||||
}
|
||||
@@ -543,7 +568,18 @@ void setup() {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void loop() {
|
||||
ftpSrv.handleFTP();
|
||||
/* Process FTP status flags (set by callbacks on core 0, consumed here on core 1) */
|
||||
if (ftp_ui_dirty) {
|
||||
ftp_ui_dirty = false;
|
||||
static const char *ftp_st_str[] = {"Idle", "Connected", "Transferring"};
|
||||
ui_set_ftp(ftp_st_str[ftp_ui_state]);
|
||||
updateLed();
|
||||
}
|
||||
if (ftp_sd_dirty) {
|
||||
ftp_sd_dirty = false;
|
||||
updateSdInfo();
|
||||
}
|
||||
|
||||
display.update();
|
||||
updateTimeDisplay();
|
||||
updateBattery();
|
||||
|
||||
Reference in New Issue
Block a user