From e1aaafb77a9f6e0bc159242de24b9b3cbb9e1782 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Fri, 3 Jan 2025 10:05:26 +0800 Subject: [PATCH] Cherrypick "add more locking for shared SPI devices (#5595) " (#5728) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add more locking for shared SPI devices (#5595) * add more locking for shared SPI devices * call initSPI before the lock is used * remove old one * don't double lock * Add missing unlock * More missing unlocks * Add locks to SafeFile, remove from `readcb`, introduce some LockGuards * fix lock in setupSDCard() * pull radiolib trunk with SPI-CS fixes * change ContentHandler to Constructor type locks, where applicable --------- Co-authored-by: mverch67 Co-authored-by: GUVWAF Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com> * mesh-tab: lower I2C touch frequency --------- Co-authored-by: Thomas Göttgens Co-authored-by: mverch67 Co-authored-by: GUVWAF Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com> --- platformio.ini | 3 ++- src/FSCommon.cpp | 21 ++++++++++++++-- src/SafeFile.cpp | 15 ++++++++---- src/SafeFile.h | 1 + src/main.cpp | 4 ++-- src/mesh/NodeDB.cpp | 22 +++++++++++++---- src/mesh/PhoneAPI.cpp | 3 +++ src/mesh/http/ContentHandler.cpp | 15 ++++++++++++ src/mesh/mesh-pb-constants.cpp | 8 +++++-- src/modules/AdminModule.cpp | 4 ++++ src/modules/CannedMessageModule.cpp | 7 ++++-- src/modules/RangeTestModule.cpp | 2 ++ src/modules/Telemetry/Sensor/BME680Sensor.cpp | 5 ++++ .../Telemetry/Sensor/NAU7802Sensor.cpp | 7 +++++- src/xmodem.cpp | 24 +++++++++++++++++++ variants/mesh-tab/platformio.ini | 6 ++--- 16 files changed, 125 insertions(+), 22 deletions(-) diff --git a/platformio.ini b/platformio.ini index 3129decaa..cd32ed179 100644 --- a/platformio.ini +++ b/platformio.ini @@ -124,7 +124,8 @@ lib_deps = [radiolib_base] lib_deps = - jgromes/RadioLib@7.1.0 + ; jgromes/RadioLib@7.1.0 + https://github.com/jgromes/RadioLib.git#92b687821ff4e6c358d866f84566f66672ab02b8 ; Common libs for environmental measurements in telemetry module ; (not included in native / portduino) diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp index df46c1941..6d8ff835c 100644 --- a/src/FSCommon.cpp +++ b/src/FSCommon.cpp @@ -9,6 +9,7 @@ * */ #include "FSCommon.h" +#include "SPILock.h" #include "configuration.h" #ifdef HAS_SDCARD @@ -102,6 +103,8 @@ bool copyFile(const char *from, const char *to) return true; #elif defined(FSCom) + // take SPI Lock + concurrency::LockGuard g(spiLock); unsigned char cbuffer[16]; File f1 = FSCom.open(from, FILE_O_READ); @@ -145,16 +148,23 @@ bool renameFile(const char *pathFrom, const char *pathTo) return false; } #elif defined(FSCom) + #ifdef ARCH_ESP32 + // take SPI Lock + spiLock->lock(); // rename was fixed for ESP32 IDF LittleFS in April - return FSCom.rename(pathFrom, pathTo); + bool result = FSCom.rename(pathFrom, pathTo); + spiLock->unlock(); + return result; #else + // copyFile does its own locking. if (copyFile(pathFrom, pathTo) && FSCom.remove(pathFrom)) { return true; } else { return false; } #endif + #endif } @@ -164,6 +174,7 @@ bool renameFile(const char *pathFrom, const char *pathTo) * @brief Get the list of files in a directory. * * This function returns a list of files in a directory. The list includes the full path of each file. + * We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK. * * @param dirname The name of the directory. * @param levels The number of levels of subdirectories to list. @@ -212,6 +223,7 @@ std::vector getFiles(const char *dirname, uint8_t levels) /** * Lists the contents of a directory. + * We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK. * * @param dirname The name of the directory to list. * @param levels The number of levels of subdirectories to list. @@ -325,18 +337,21 @@ void listDir(const char *dirname, uint8_t levels, bool del) void rmDir(const char *dirname) { #ifdef FSCom + #if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)) listDir(dirname, 10, true); #elif defined(ARCH_NRF52) // nRF52 implementation of LittleFS has a recursive delete function FSCom.rmdir_r(dirname); #endif + #endif } void fsInit() { #ifdef FSCom + spiLock->lock(); if (!FSBegin()) { LOG_ERROR("Filesystem mount failed"); // assert(0); This auto-formats the partition, so no need to fail here. @@ -347,6 +362,7 @@ void fsInit() LOG_DEBUG("Filesystem files:"); #endif listDir("/", 10); + spiLock->unlock(); #endif } @@ -356,6 +372,7 @@ void fsInit() void setupSDCard() { #ifdef HAS_SDCARD + concurrency::LockGuard g(spiLock); SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI); if (!SD.begin(SDCARD_CS, SDHandler)) { @@ -383,4 +400,4 @@ void setupSDCard() LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024))); LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024))); #endif -} \ No newline at end of file +} diff --git a/src/SafeFile.cpp b/src/SafeFile.cpp index c76ff8054..c5d7b335e 100644 --- a/src/SafeFile.cpp +++ b/src/SafeFile.cpp @@ -5,6 +5,7 @@ // Only way to work on both esp32 and nrf52 static File openFile(const char *filename, bool fullAtomic) { + concurrency::LockGuard g(spiLock); if (!fullAtomic) FSCom.remove(filename); // Nuke the old file to make space (ignore if it !exists) @@ -53,14 +54,19 @@ bool SafeFile::close() if (!f) return false; + spiLock->lock(); f.close(); + spiLock->unlock(); if (!testReadback()) return false; - // brief window of risk here ;-) - if (fullAtomic && FSCom.exists(filename.c_str()) && !FSCom.remove(filename.c_str())) { - LOG_ERROR("Can't remove old pref file"); - return false; + { // Scope for lock + concurrency::LockGuard g(spiLock); + // brief window of risk here ;-) + if (fullAtomic && FSCom.exists(filename.c_str()) && !FSCom.remove(filename.c_str())) { + LOG_ERROR("Can't remove old pref file"); + return false; + } } String filenameTmp = filename; @@ -76,6 +82,7 @@ bool SafeFile::close() /// Read our (closed) tempfile back in and compare the hash bool SafeFile::testReadback() { + concurrency::LockGuard g(spiLock); bool lfs_failed = lfs_assert_failed; lfs_assert_failed = false; diff --git a/src/SafeFile.h b/src/SafeFile.h index 61361d312..3d0f81cad 100644 --- a/src/SafeFile.h +++ b/src/SafeFile.h @@ -1,6 +1,7 @@ #pragma once #include "FSCommon.h" +#include "SPILock.h" #include "configuration.h" #ifdef FSCom diff --git a/src/main.cpp b/src/main.cpp index 5982e709d..c2b20b1c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -364,6 +364,8 @@ void setup() #endif #endif + initSPI(); + OSThread::setup(); ledPeriodic = new Periodic("Blink", ledBlinker); @@ -640,8 +642,6 @@ void setup() rp2040Setup(); #endif - initSPI(); // needed here before reading from littleFS - // We do this as early as possible because this loads preferences from flash // but we need to do this after main cpu init (esp32setup), because we need the random seed set nodeDB = new NodeDB; diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index bbc9eb1ea..8e084c99d 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -13,6 +13,7 @@ #include "PowerFSM.h" #include "RTC.h" #include "Router.h" +#include "SPILock.h" #include "SafeFile.h" #include "TypeConversions.h" #include "error.h" @@ -423,12 +424,15 @@ bool NodeDB::factoryReset(bool eraseBleBonds) { LOG_INFO("Perform factory reset!"); // first, remove the "/prefs" (this removes most prefs) - rmDir("/prefs"); + spiLock->lock(); + rmDir("/prefs"); // this uses spilock internally... + #ifdef FSCom if (FSCom.exists("/static/rangetest.csv") && !FSCom.remove("/static/rangetest.csv")) { LOG_ERROR("Could not remove rangetest.csv file"); } #endif + spiLock->unlock(); // second, install default state (this will deal with the duplicate mac address issue) installDefaultDeviceState(); installDefaultConfig(!eraseBleBonds); // Also preserve the private key if we're not erasing BLE bonds @@ -913,6 +917,7 @@ LoadFileResult NodeDB::loadProto(const char *filename, size_t protoSize, size_t { LoadFileResult state = LoadFileResult::OTHER_FAILURE; #ifdef FSCom + concurrency::LockGuard g(spiLock); auto f = FSCom.open(filename, FILE_O_READ); @@ -946,8 +951,10 @@ void NodeDB::loadFromDisk() // disk we will still factoryReset to restore things. #ifdef ARCH_ESP32 + spiLock->lock(); if (FSCom.exists("/static/static")) rmDir("/static/static"); // Remove bad static web files bundle from initial 2.5.13 release + spiLock->unlock(); #endif // static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM @@ -1097,9 +1104,6 @@ void NodeDB::loadFromDisk() bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct, bool fullAtomic) { -#ifdef ARCH_ESP32 - concurrency::LockGuard g(spiLock); -#endif bool okay = false; #ifdef FSCom auto f = SafeFile(filename, fullAtomic); @@ -1127,7 +1131,9 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_ bool NodeDB::saveChannelsToDisk() { #ifdef FSCom + spiLock->lock(); FSCom.mkdir("/prefs"); + spiLock->unlock(); #endif return saveProto(channelFileName, meshtastic_ChannelFile_size, &meshtastic_ChannelFile_msg, &channelFile); } @@ -1135,7 +1141,9 @@ bool NodeDB::saveChannelsToDisk() bool NodeDB::saveDeviceStateToDisk() { #ifdef FSCom + spiLock->lock(); FSCom.mkdir("/prefs"); + spiLock->unlock(); #endif // Note: if MAX_NUM_NODES=100 and meshtastic_NodeInfoLite_size=166, so will be approximately 17KB // Because so huge we _must_ not use fullAtomic, because the filesystem is probably too small to hold two copies of this @@ -1148,7 +1156,9 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat) bool success = true; #ifdef FSCom + spiLock->lock(); FSCom.mkdir("/prefs"); + spiLock->unlock(); #endif if (saveWhat & SEGMENT_CONFIG) { config.has_device = true; @@ -1199,7 +1209,9 @@ bool NodeDB::saveToDisk(int saveWhat) if (!success) { LOG_ERROR("Failed to save to disk, retrying"); #ifdef ARCH_NRF52 // @geeksville is not ready yet to say we should do this on other platforms. See bug #4184 discussion + spiLock->lock(); FSCom.format(); + spiLock->unlock(); #endif success = saveToDiskNoRetry(saveWhat); @@ -1518,4 +1530,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co LOG_ERROR("A critical failure occurred, portduino is exiting"); exit(2); #endif -} +} \ No newline at end of file diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 8c1ba74c7..6789acbb3 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -12,6 +12,7 @@ #include "PhoneAPI.h" #include "PowerFSM.h" #include "RadioInterface.h" +#include "SPILock.h" #include "TypeConversions.h" #include "main.h" #include "xmodem.h" @@ -54,7 +55,9 @@ void PhoneAPI::handleStartConfig() // even if we were already connected - restart our state machine state = STATE_SEND_MY_INFO; pauseBluetoothLogging = true; + spiLock->lock(); filesManifest = getFiles("/", 10); + spiLock->unlock(); LOG_DEBUG("Got %d files in manifest", filesManifest.size()); LOG_INFO("Start API client config"); diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp index aa8a68f91..5841fe478 100644 --- a/src/mesh/http/ContentHandler.cpp +++ b/src/mesh/http/ContentHandler.cpp @@ -10,6 +10,7 @@ #include "mesh/wifi/WiFiAPClient.h" #endif #include "Led.h" +#include "SPILock.h" #include "power.h" #include "serialization/JSON.h" #include @@ -236,6 +237,7 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res) void htmlDeleteDir(const char *dirname) { + File root = FSCom.open(dirname); if (!root) { return; @@ -318,6 +320,7 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res) res->setHeader("Access-Control-Allow-Origin", "*"); res->setHeader("Access-Control-Allow-Methods", "GET"); + concurrency::LockGuard g(spiLock); auto fileList = htmlListDir("/static", 10); // create json output structure @@ -349,9 +352,12 @@ void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res) res->setHeader("Content-Type", "application/json"); res->setHeader("Access-Control-Allow-Origin", "*"); res->setHeader("Access-Control-Allow-Methods", "DELETE"); + if (params->getQueryParameter("delete", paramValDelete)) { std::string pathDelete = "/" + paramValDelete; + concurrency::LockGuard g(spiLock); if (FSCom.remove(pathDelete.c_str())) { + LOG_INFO("%s", pathDelete.c_str()); JSONObject jsonObjOuter; jsonObjOuter["status"] = new JSONValue("ok"); @@ -360,6 +366,7 @@ void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res) delete value; return; } else { + LOG_INFO("%s", pathDelete.c_str()); JSONObject jsonObjOuter; jsonObjOuter["status"] = new JSONValue("Error"); @@ -393,6 +400,8 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res) filenameGzip = "/static/index.html.gz"; } + concurrency::LockGuard g(spiLock); + if (FSCom.exists(filename.c_str())) { file = FSCom.open(filename.c_str()); if (!file.available()) { @@ -410,6 +419,7 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res) file = FSCom.open(filenameGzip.c_str()); res->setHeader("Content-Type", "text/html"); if (!file.available()) { + LOG_WARN("File not available - %s", filenameGzip.c_str()); res->println("Web server is running.

The content you are looking for can't be found. Please see: FAQ.

printf("

Saved %d bytes to %s

", (int)fileLength, pathname.c_str()); } if (!didwrite) { @@ -642,9 +654,11 @@ void handleReport(HTTPRequest *req, HTTPResponse *res) jsonObjMemory["heap_free"] = new JSONValue((int)memGet.getFreeHeap()); jsonObjMemory["psram_total"] = new JSONValue((int)memGet.getPsramSize()); jsonObjMemory["psram_free"] = new JSONValue((int)memGet.getFreePsram()); + spiLock->lock(); jsonObjMemory["fs_total"] = new JSONValue((int)FSCom.totalBytes()); jsonObjMemory["fs_used"] = new JSONValue((int)FSCom.usedBytes()); jsonObjMemory["fs_free"] = new JSONValue(int(FSCom.totalBytes() - FSCom.usedBytes())); + spiLock->unlock(); // data->power JSONObject jsonObjPower; @@ -786,6 +800,7 @@ void handleDeleteFsContent(HTTPRequest *req, HTTPResponse *res) LOG_INFO("Delete files from /static/* : "); + concurrency::LockGuard g(spiLock); htmlDeleteDir("/static"); res->println("


Back to admin"); diff --git a/src/mesh/mesh-pb-constants.cpp b/src/mesh/mesh-pb-constants.cpp index deb93d0a6..a8f4fd6d8 100644 --- a/src/mesh/mesh-pb-constants.cpp +++ b/src/mesh/mesh-pb-constants.cpp @@ -1,6 +1,7 @@ #include "configuration.h" #include "FSCommon.h" +#include "SPILock.h" #include "mesh-pb-constants.h" #include #include @@ -55,9 +56,12 @@ bool readcb(pb_istream_t *stream, uint8_t *buf, size_t count) /// Write to an arduino file bool writecb(pb_ostream_t *stream, const uint8_t *buf, size_t count) { + spiLock->lock(); auto file = (Print *)stream->state; // LOG_DEBUG("writing %d bytes to protobuf file", count); - return file->write(buf, count) == count; + bool status = file->write(buf, count) == count; + spiLock->unlock(); + return status; } #endif @@ -68,4 +72,4 @@ bool is_in_helper(uint32_t n, const uint32_t *array, pb_size_t count) return true; return false; -} +} \ No newline at end of file diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index fc3b914e5..7906b410b 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -4,6 +4,7 @@ #include "NodeDB.h" #include "PowerFSM.h" #include "RTC.h" +#include "SPILock.h" #include "meshUtils.h" #include #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH @@ -358,12 +359,15 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta } case meshtastic_AdminMessage_delete_file_request_tag: { LOG_DEBUG("Client requesting to delete file: %s", r->delete_file_request); + #ifdef FSCom + spiLock->lock(); if (FSCom.remove(r->delete_file_request)) { LOG_DEBUG("Successfully deleted file"); } else { LOG_DEBUG("Failed to delete file"); } + spiLock->unlock(); #endif break; } diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index c20b7b56e..5fb32fff5 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -9,6 +9,7 @@ #include "MeshService.h" #include "NodeDB.h" #include "PowerFSM.h" // needed for button bypass +#include "SPILock.h" #include "detect/ScanI2C.h" #include "input/ScanAndSelect.h" #include "mesh/generated/meshtastic/cannedmessages.pb.h" @@ -1184,8 +1185,10 @@ bool CannedMessageModule::saveProtoForModule() { bool okay = true; -#ifdef FS - FS.mkdir("/prefs"); +#ifdef FSCom + spiLock->lock(); + FSCom.mkdir("/prefs"); + spiLock->unlock(); #endif okay &= nodeDB->saveProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size, diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index c42839d97..cad1d51f1 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -15,6 +15,7 @@ #include "PowerFSM.h" #include "RTC.h" #include "Router.h" +#include "SPILock.h" #include "airtime.h" #include "configuration.h" #include "gps/GeoCoord.h" @@ -205,6 +206,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) LOG_DEBUG("gpsStatus->getDOP() %d", gpsStatus->getDOP()); LOG_DEBUG("-----------------------------------------"); */ + concurrency::LockGuard g(spiLock); if (!FSBegin()) { LOG_DEBUG("An Error has occurred while mounting the filesystem"); return 0; diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.cpp b/src/modules/Telemetry/Sensor/BME680Sensor.cpp index 18515d0a8..9237cf0c9 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME680Sensor.cpp @@ -5,6 +5,7 @@ #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "BME680Sensor.h" #include "FSCommon.h" +#include "SPILock.h" #include "TelemetrySensor.h" BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {} @@ -75,6 +76,7 @@ bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement) void BME680Sensor::loadState() { #ifdef FSCom + spiLock->lock(); auto file = FSCom.open(bsecConfigFileName, FILE_O_READ); if (file) { file.read((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE); @@ -84,6 +86,7 @@ void BME680Sensor::loadState() } else { LOG_INFO("No %s state found (File: %s)", sensorName, bsecConfigFileName); } + spiLock->unlock(); #else LOG_ERROR("ERROR: Filesystem not implemented"); #endif @@ -92,6 +95,7 @@ void BME680Sensor::loadState() void BME680Sensor::updateState() { #ifdef FSCom + spiLock->lock(); bool update = false; if (stateUpdateCounter == 0) { /* First state update when IAQ accuracy is >= 3 */ @@ -127,6 +131,7 @@ void BME680Sensor::updateState() LOG_INFO("Can't write %s state (File: %s)", sensorName, bsecConfigFileName); } } + spiLock->unlock(); #else LOG_ERROR("ERROR: Filesystem not implemented"); #endif diff --git a/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp b/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp index 65f616686..1329c8d90 100644 --- a/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp +++ b/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp @@ -5,6 +5,7 @@ #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "FSCommon.h" #include "NAU7802Sensor.h" +#include "SPILock.h" #include "SafeFile.h" #include "TelemetrySensor.h" #include @@ -111,13 +112,16 @@ bool NAU7802Sensor::saveCalibrationData() } else { okay = true; } + spiLock->lock(); okay &= file.close(); + spiLock->unlock(); return okay; } bool NAU7802Sensor::loadCalibrationData() { + spiLock->lock(); auto file = FSCom.open(nau7802ConfigFileName, FILE_O_READ); bool okay = false; if (file) { @@ -134,7 +138,8 @@ bool NAU7802Sensor::loadCalibrationData() } else { LOG_INFO("No %s state found (File: %s)", sensorName, nau7802ConfigFileName); } + spiLock->unlock(); return okay; } -#endif +#endif \ No newline at end of file diff --git a/src/xmodem.cpp b/src/xmodem.cpp index bf25e2da7..1d8c77760 100644 --- a/src/xmodem.cpp +++ b/src/xmodem.cpp @@ -49,6 +49,7 @@ **********************************************************************************************************************/ #include "xmodem.h" +#include "SPILock.h" #ifdef FSCom @@ -119,8 +120,11 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) if ((xmodemPacket.seq == 0) && !isReceiving && !isTransmitting) { // NULL packet has the destination filename memcpy(filename, &xmodemPacket.buffer.bytes, xmodemPacket.buffer.size); + if (xmodemPacket.control == meshtastic_XModem_Control_SOH) { // Receive this file and put to Flash + spiLock->lock(); file = FSCom.open(filename, FILE_O_WRITE); + spiLock->unlock(); if (file) { sendControl(meshtastic_XModem_Control_ACK); isReceiving = true; @@ -132,14 +136,18 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) break; } else { // Transmit this file from Flash LOG_INFO("XModem: Transmit file %s", filename); + spiLock->lock(); file = FSCom.open(filename, FILE_O_READ); + spiLock->unlock(); if (file) { packetno = 1; isTransmitting = true; xmodemStore = meshtastic_XModem_init_zero; xmodemStore.control = meshtastic_XModem_Control_SOH; xmodemStore.seq = packetno; + spiLock->lock(); xmodemStore.buffer.size = file.read(xmodemStore.buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes)); + spiLock->unlock(); xmodemStore.crc16 = crc16_ccitt(xmodemStore.buffer.bytes, xmodemStore.buffer.size); LOG_DEBUG("XModem: STX Notify Send packet %d, %d Bytes", packetno, xmodemStore.buffer.size); if (xmodemStore.buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes)) { @@ -159,7 +167,9 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) if ((xmodemPacket.seq == packetno) && check(xmodemPacket.buffer.bytes, xmodemPacket.buffer.size, xmodemPacket.crc16)) { // valid packet + spiLock->lock(); file.write(xmodemPacket.buffer.bytes, xmodemPacket.buffer.size); + spiLock->unlock(); sendControl(meshtastic_XModem_Control_ACK); packetno++; break; @@ -178,16 +188,21 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) case meshtastic_XModem_Control_EOT: // End of transmission sendControl(meshtastic_XModem_Control_ACK); + spiLock->lock(); file.flush(); file.close(); + spiLock->unlock(); isReceiving = false; break; case meshtastic_XModem_Control_CAN: // Cancel transmission and remove file sendControl(meshtastic_XModem_Control_ACK); + spiLock->lock(); file.flush(); file.close(); + FSCom.remove(filename); + spiLock->unlock(); isReceiving = false; break; case meshtastic_XModem_Control_ACK: @@ -195,7 +210,9 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) if (isTransmitting) { if (isEOT) { sendControl(meshtastic_XModem_Control_EOT); + spiLock->lock(); file.close(); + spiLock->unlock(); LOG_INFO("XModem: Finished send file %s", filename); isTransmitting = false; isEOT = false; @@ -206,7 +223,9 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) xmodemStore = meshtastic_XModem_init_zero; xmodemStore.control = meshtastic_XModem_Control_SOH; xmodemStore.seq = packetno; + spiLock->lock(); xmodemStore.buffer.size = file.read(xmodemStore.buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes)); + spiLock->unlock(); xmodemStore.crc16 = crc16_ccitt(xmodemStore.buffer.bytes, xmodemStore.buffer.size); LOG_DEBUG("XModem: ACK Notify Send packet %d, %d Bytes", packetno, xmodemStore.buffer.size); if (xmodemStore.buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes)) { @@ -224,7 +243,9 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) if (isTransmitting) { if (--retrans <= 0) { sendControl(meshtastic_XModem_Control_CAN); + spiLock->lock(); file.close(); + spiLock->unlock(); LOG_INFO("XModem: Retransmit timeout, cancel file %s", filename); isTransmitting = false; break; @@ -232,8 +253,11 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) xmodemStore = meshtastic_XModem_init_zero; xmodemStore.control = meshtastic_XModem_Control_SOH; xmodemStore.seq = packetno; + spiLock->lock(); file.seek((packetno - 1) * sizeof(meshtastic_XModem_buffer_t::bytes)); + xmodemStore.buffer.size = file.read(xmodemStore.buffer.bytes, sizeof(meshtastic_XModem_buffer_t::bytes)); + spiLock->unlock(); xmodemStore.crc16 = crc16_ccitt(xmodemStore.buffer.bytes, xmodemStore.buffer.size); LOG_DEBUG("XModem: NAK Notify Send packet %d, %d Bytes", packetno, xmodemStore.buffer.size); if (xmodemStore.buffer.size < sizeof(meshtastic_XModem_buffer_t::bytes)) { diff --git a/variants/mesh-tab/platformio.ini b/variants/mesh-tab/platformio.ini index 26b072cde..a1007a7f4 100644 --- a/variants/mesh-tab/platformio.ini +++ b/variants/mesh-tab/platformio.ini @@ -178,7 +178,7 @@ build_flags = ${mesh_tab_base.build_flags} -D LGFX_TOUCH_Y_MIN=0 -D LGFX_TOUCH_Y_MAX=479 -D LGFX_TOUCH_ROTATION=0 - -D LGFX_TOUCH_I2C_FREQ=1000000 + -D LGFX_TOUCH_I2C_FREQ=400000 ; 3.5" IPS TFT ILI9488 / FT6236: https://vi.aliexpress.com/item/1005006893699919.html [env:mesh-tab-3-5-IPS-capacitive] @@ -204,7 +204,7 @@ build_flags = ${mesh_tab_base.build_flags} -D LGFX_TOUCH_Y_MIN=0 -D LGFX_TOUCH_Y_MAX=479 -D LGFX_TOUCH_ROTATION=1 - -D LGFX_TOUCH_I2C_FREQ=1000000 + -D LGFX_TOUCH_I2C_FREQ=400000 ; 4.0" IPS TFT ILI9488 / FT6236: https://vi.aliexpress.com/item/1005007082906950.html [env:mesh-tab-4-0-IPS-capacitive] @@ -230,4 +230,4 @@ build_flags = ${mesh_tab_base.build_flags} -D LGFX_TOUCH_Y_MIN=0 -D LGFX_TOUCH_Y_MAX=479 -D LGFX_TOUCH_ROTATION=1 - -D LGFX_TOUCH_I2C_FREQ=1000000 \ No newline at end of file + -D LGFX_TOUCH_I2C_FREQ=400000 \ No newline at end of file