From 5d6807a44e4087af01e5078772b6890cd3552c0b Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Tue, 4 Nov 2025 15:27:12 +0000 Subject: [PATCH 01/17] Update Dockerfile --- Firmware/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Firmware/Dockerfile b/Firmware/Dockerfile index 91eab12df..e687f0841 100644 --- a/Firmware/Dockerfile +++ b/Firmware/Dockerfile @@ -17,6 +17,9 @@ ARG DEBUG_LEVEL=error # Set to false for releases ARG ENABLE_DEVELOPER=true +# arduino-cli warnings: none default more all +ARG WARNINGS=default + # If you have your own u-blox PointPerfect token(s), define them here # or pass in as args when building the Dockerfile # POINTPERFECT_LBAND_TOKEN is the token for the deprecated u-blox L-band SPARTN service @@ -116,6 +119,7 @@ RUN cp RTKEverywhere.csv "/root/.arduino15/packages/esp32/hardware/esp32/${CORE_ # Compile Sketch RUN cd ./RTK_Everywhere \ && arduino-cli compile --fqbn "esp32:esp32:esp32":DebugLevel=${DEBUG_LEVEL},PSRAM=enabled \ + --warnings ${WARNINGS} \ ./RTK_Everywhere.ino \ --build-property build.partitions=RTKEverywhere \ --build-property upload.maximum_size=4055040 \ From 84432407872948e513ec30be8d53aca9ff4fd8f3 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Tue, 4 Nov 2025 15:28:21 +0000 Subject: [PATCH 02/17] Clean up some warnings --- Firmware/RTK_Everywhere/Display.ino | 4 ++-- Firmware/RTK_Everywhere/NTP.ino | 8 ++++---- Firmware/RTK_Everywhere/NVM.ino | 2 +- Firmware/RTK_Everywhere/States.ino | 1 + Firmware/RTK_Everywhere/Tasks.ino | 2 +- Firmware/RTK_Everywhere/menuCommands.ino | 4 ++-- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 5790490ea..171abd745 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1992,7 +1992,7 @@ void paintIPAddress() char ipAddress[16]; snprintf(ipAddress, sizeof(ipAddress), "%s", #ifdef COMPILE_ETHERNET - ETH.localIP().toString()); + ETH.localIP().toString().c_str()); #else // COMPILE_ETHERNET "0.0.0.0"); #endif // COMPILE_ETHERNET @@ -2052,7 +2052,7 @@ void displayFullIPAddress(std::vector *iconList) // Bottom // Display the IP address when it is available if (ipAddress != IPAddress((uint32_t)0)) { - snprintf(myAddress, sizeof(myAddress), "%s", ipAddress.toString()); + snprintf(myAddress, sizeof(myAddress), "%s", ipAddress.toString().c_str()); oled->setFont(QW_FONT_5X7); // Set font to smallest oled->setCursor(0, 55); diff --git a/Firmware/RTK_Everywhere/NTP.ino b/Firmware/RTK_Everywhere/NTP.ino index ee392b811..8a8c1878d 100644 --- a/Firmware/RTK_Everywhere/NTP.ino +++ b/Firmware/RTK_Everywhere/NTP.ino @@ -609,7 +609,7 @@ bool ntpProcessOneRequest(bool process, const timeval *recTv, const timeval *syn if (ntpDiag != nullptr) { char tmpbuf[128]; - snprintf(tmpbuf, sizeof(tmpbuf), "Originate Timestamp (Client Transmit): %u.%06u\r\n", + snprintf(tmpbuf, sizeof(tmpbuf), "Originate Timestamp (Client Transmit): %lu.%06lu\r\n", packet.transmitTimestampSeconds, packet.convertFractionToMicros(packet.transmitTimestampFraction)); strlcat(ntpDiag, tmpbuf, ntpDiagSize); @@ -631,7 +631,7 @@ bool ntpProcessOneRequest(bool process, const timeval *recTv, const timeval *syn if (ntpDiag != nullptr) { char tmpbuf[128]; - snprintf(tmpbuf, sizeof(tmpbuf), "Received Timestamp: %u.%06u\r\n", + snprintf(tmpbuf, sizeof(tmpbuf), "Received Timestamp: %lu.%06lu\r\n", packet.receiveTimestampSeconds, packet.convertFractionToMicros(packet.receiveTimestampFraction)); strlcat(ntpDiag, tmpbuf, ntpDiagSize); @@ -649,7 +649,7 @@ bool ntpProcessOneRequest(bool process, const timeval *recTv, const timeval *syn if (ntpDiag != nullptr) { char tmpbuf[128]; - snprintf(tmpbuf, sizeof(tmpbuf), "Reference Timestamp (Last Sync): %u.%06u\r\n", + snprintf(tmpbuf, sizeof(tmpbuf), "Reference Timestamp (Last Sync): %lu.%06lu\r\n", packet.referenceTimestampSeconds, packet.convertFractionToMicros(packet.referenceTimestampFraction)); strlcat(ntpDiag, tmpbuf, ntpDiagSize); @@ -677,7 +677,7 @@ bool ntpProcessOneRequest(bool process, const timeval *recTv, const timeval *syn if (ntpDiag != nullptr) { char tmpbuf[128]; - snprintf(tmpbuf, sizeof(tmpbuf), "Transmit Timestamp: %u.%06u\r\n", + snprintf(tmpbuf, sizeof(tmpbuf), "Transmit Timestamp: %lu.%06lu\r\n", packet.transmitTimestampSeconds, packet.convertFractionToMicros(packet.transmitTimestampFraction)); strlcat(ntpDiag, tmpbuf, ntpDiagSize); diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index cb819c9e3..ad9064f59 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -279,7 +279,7 @@ void recordSystemSettingsToFile(File *settingsFile) break; case _uint32_t: { uint32_t *ptr = (uint32_t *)rtkSettingsEntries[i].var; - settingsFile->printf("%s=%d\r\n", rtkSettingsEntries[i].name, *ptr); + settingsFile->printf("%s=%lu\r\n", rtkSettingsEntries[i].name, *ptr); } break; case _uint64_t: { diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 9712eaafa..0c00e1084 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -683,6 +683,7 @@ const char *getState(SystemState state, char *buffer) return "STATE_DISPLAY_SETUP"; case (STATE_WEB_CONFIG_NOT_STARTED): return "STATE_WEB_CONFIG_NOT_STARTED"; + case (STATE_WEB_CONFIG_WAIT_FOR_NETWORK): case (STATE_WEB_CONFIG): return "STATE_WEB_CONFIG"; case (STATE_TEST): diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index fcb07f309..60ee9a1c8 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -1645,7 +1645,7 @@ void handleGnssDataTask(void *e) // Record trigger count with Time Of Week of rising edge (ms), Millisecond fraction of Time Of Week of // rising edge (ns), and accuracy estimate (ns) char eventData[82]; // Max NMEA sentence length is 82 - snprintf(eventData, sizeof(eventData), "%d,%d,%d,%d", triggerCount, triggerTowMsR, triggerTowSubMsR, + snprintf(eventData, sizeof(eventData), "%lu,%lu,%lu,%lu", triggerCount, triggerTowMsR, triggerTowSubMsR, triggerAccEst); char nmeaMessage[82]; // Max NMEA sentence length is 82 diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 79ecc6c6d..8adbce3e7 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -2438,7 +2438,7 @@ void stringRecord(char *settingsCSV, const char *id, int settingValue) void stringRecord(char *settingsCSV, const char *id, uint32_t settingValue) { char record[100]; - snprintf(record, sizeof(record), "%s,%d,", id, settingValue); + snprintf(record, sizeof(record), "%s,%lu,", id, settingValue); strcat(settingsCSV, record); } @@ -4129,7 +4129,7 @@ void printAvailableSettings() // Convert int to string char batteryChargingPercentStr[3] = {0}; // 45 - snprintf(batteryChargingPercentStr, sizeof(batteryChargingPercentStr), "%0.0f", batteryChargingPercentStr); + snprintf(batteryChargingPercentStr, sizeof(batteryChargingPercentStr), "%0.0f", batteryChargingPercentPerHour); // Create the settingType based on the length of the firmware version char settingType[100]; From 644847b30ee13343ba89029d050c35b447fda33f Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Tue, 4 Nov 2025 15:36:26 +0000 Subject: [PATCH 03/17] Restructure NTRIP_SERVER_DATA - make the struct contents volatile --- Firmware/RTK_Everywhere/NtripServer.ino | 26 ++++++++++++------------- Firmware/RTK_Everywhere/settings.h | 22 ++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index 39ffc4ff9..c44788117 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -173,7 +173,7 @@ const RtkMode_t ntripServerMode = RTK_MODE_BASE_FIXED; //---------------------------------------- // NTRIP Servers -volatile static NTRIP_SERVER_DATA ntripServerArray[NTRIP_SERVER_MAX]; +static NTRIP_SERVER_DATA ntripServerArray[NTRIP_SERVER_MAX]; //---------------------------------------- // NTRIP Server Routines @@ -184,7 +184,7 @@ volatile static NTRIP_SERVER_DATA ntripServerArray[NTRIP_SERVER_MAX]; //---------------------------------------- bool ntripServerConnectCaster(int serverIndex) { - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; const int SERVER_BUFFER_SIZE = 512; char serverBuffer[SERVER_BUFFER_SIZE]; @@ -239,7 +239,7 @@ bool ntripServerConnectLimitReached(int serverIndex) { bool limitReached; int minutes; - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; int seconds; // Retry the connection a few times @@ -311,9 +311,9 @@ bool ntripServerEnabled(int serverIndex, const char ** line) { if (line) { - if (settings.ntripServer_CasterHost[0] == 0) + if (settings.ntripServer_CasterHost[serverIndex][0] == 0) *line = ", Caster host not specified!"; - else if (settings.ntripServer_CasterPort == 0) + else if (settings.ntripServer_CasterPort[serverIndex] == 0) *line = ", Caster port not specified!"; else *line = ", Mount point not specified!"; @@ -334,7 +334,7 @@ bool ntripServerEnabled(int serverIndex, const char ** line) //---------------------------------------- void ntripServerPrintStateSummary(int serverIndex) { - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; switch (ntripServer->state) { @@ -362,7 +362,7 @@ void ntripServerPrintStateSummary(int serverIndex) //---------------------------------------- void ntripServerPrintStatus(int serverIndex) { - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; uint64_t milliseconds; uint32_t days; byte hours; @@ -410,7 +410,7 @@ void ntripServerPrintStatus(int serverIndex) //---------------------------------------- void ntripServerProcessRTCM(int serverIndex, uint8_t incoming) { - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; if (ntripServer->state == NTRIP_SERVER_CASTING) { @@ -464,7 +464,7 @@ void ntripServerProcessRTCM(int serverIndex, uint8_t incoming) //---------------------------------------- void ntripServerResponse(int serverIndex, char *response, size_t maxLength) { - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; char *responseEnd; // Make sure that we can zero terminate the response @@ -483,7 +483,7 @@ void ntripServerResponse(int serverIndex, char *response, size_t maxLength) //---------------------------------------- void ntripServerRestart(int serverIndex) { - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; // Save the previous uptime value if (ntripServer->state == NTRIP_SERVER_CASTING) @@ -496,7 +496,7 @@ void ntripServerRestart(int serverIndex) //---------------------------------------- void ntripServerSetState(int serverIndex, uint8_t newState) { - volatile NTRIP_SERVER_DATA * ntripServer; + NTRIP_SERVER_DATA * ntripServer; ntripServer = &ntripServerArray[serverIndex]; if (settings.debugNtripServerState) @@ -548,7 +548,7 @@ void ntripServerStop(int serverIndex, bool shutdown) { bool enabled; int index; - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; if (ntripServer->networkClient) { @@ -612,7 +612,7 @@ void ntripServerUpdate(int serverIndex) const char * line = ""; // Get the NTRIP data structure - volatile NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; + NTRIP_SERVER_DATA *ntripServer = &ntripServerArray[serverIndex]; // Shutdown the NTRIP server when the mode or setting changes DMW_if diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 2a11d5864..88a108a2e 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -385,34 +385,34 @@ enum PeriodDisplayValues #ifdef COMPILE_NETWORK -// NTRIP Server data - the array is declared volatile in NtripServer.ino +// NTRIP Server data typedef struct { // Network connection used to push RTCM to NTRIP caster NetworkClient *networkClient; - uint8_t state; + volatile uint8_t state; // Count of bytes sent by the NTRIP server to the NTRIP caster - uint32_t bytesSent; + volatile uint32_t bytesSent; // Throttle the time between connection attempts // ms - Max of 4,294,967,295 or 4.3M seconds or 71,000 minutes or 1193 hours or 49 days between attempts - uint32_t connectionAttemptTimeout; - uint32_t lastConnectionAttempt; - int connectionAttempts; // Count the number of connection attempts between restarts + volatile uint32_t connectionAttemptTimeout; + volatile uint32_t lastConnectionAttempt; + volatile int connectionAttempts; // Count the number of connection attempts between restarts // NTRIP server timer usage: // * Reconnection delay // * Measure the connection response time // * Receive RTCM correction data timeout // * Monitor last RTCM byte received for frame counting - uint32_t timer; - uint32_t startTime; - int connectionAttemptsTotal; // Count the number of connection attempts absolutely + volatile uint32_t timer; + volatile uint32_t startTime; + volatile int connectionAttemptsTotal; // Count the number of connection attempts absolutely // Better debug printing by ntripServerProcessRTCM - uint32_t rtcmBytesSent; - uint32_t previousMilliseconds; + volatile uint32_t rtcmBytesSent; + volatile uint32_t previousMilliseconds; } NTRIP_SERVER_DATA; #endif // COMPILE_NETWORK From ac6e0d3195b6fa92f97f6da1247741d808de36bc Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Wed, 5 Nov 2025 14:10:55 +0000 Subject: [PATCH 04/17] Add ethernetUpdate and ethernetRestartRequested Restart Ethernet when disconnected, to free any TCP resources --- Firmware/RTK_Everywhere/Developer.ino | 5 +++-- Firmware/RTK_Everywhere/Ethernet.ino | 17 +++++++++++++++++ Firmware/RTK_Everywhere/Network.ino | 3 +++ Firmware/RTK_Everywhere/RTK_Everywhere.ino | 1 + 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 42677f2f4..75ce977f5 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -9,8 +9,9 @@ // Ethernet //---------------------------------------- -bool ethernetLinkUp() {return false;} -void menuEthernet() {systemPrintln("**Ethernet not compiled**");} +bool ethernetLinkUp() {return false;} +void menuEthernet() {systemPrintln("**Ethernet not compiled**");} +void ethernetUpdate() {} bool ntpLogIncreasing = false; diff --git a/Firmware/RTK_Everywhere/Ethernet.ino b/Firmware/RTK_Everywhere/Ethernet.ino index 387037fed..3469dafe7 100644 --- a/Firmware/RTK_Everywhere/Ethernet.ino +++ b/Firmware/RTK_Everywhere/Ethernet.ino @@ -188,6 +188,9 @@ void ethernetEvent(arduino_event_id_t event, arduino_event_info_t info) case ARDUINO_EVENT_ETH_DISCONNECTED: if (settings.enablePrintEthernetDiag && (!inMainMenu)) systemPrintln("ETH Disconnected"); + + ethernetRestartRequested = true; // Perform ETH.end() to disconnect TCP resources + break; case ARDUINO_EVENT_ETH_STOP: @@ -236,6 +239,20 @@ const char *ethernetGetEventName(arduino_event_id_t event) } } +//---------------------------------------- +// Update Ethernet. Restart if requested +//---------------------------------------- +void ethernetUpdate() +{ + if (ethernetRestartRequested) + { + if (settings.enablePrintEthernetDiag && (!inMainMenu)) + systemPrintln("Restarting Ethernet"); + ethernetRestart(); + ethernetRestartRequested = false; + } +} + //---------------------------------------- // Restart the Ethernet controller //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 32a98faa1..651fd049b 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -2453,6 +2453,9 @@ void networkUpdate() // Update the WiFi state wifiStationUpdate(); + // Update Ethernet + ethernetUpdate(); + // Update the network services // Start or stop mDNS if (networkMdnsRequests != networkMdnsRunning) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 2bb55c1d2..ae2144fe1 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -737,6 +737,7 @@ IPAddress ethernetSubnetMask; // }; volatile struct timeval ethernetNtpTv; // This will hold the time the Ethernet NTP packet arrived bool ntpLogIncreasing; +bool ethernetRestartRequested = false; // Perform ETH.end() to disconnect TCP resources #endif // COMPILE_ETHERNET unsigned long lastEthernetCheck; // Prevents cable checking from continually happening From 0555fb603190f3f2b6fa5198305359656892ae6b Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Wed, 5 Nov 2025 14:13:19 +0000 Subject: [PATCH 05/17] NtripServer - gently absorb incoming traffic (to free TCP resources); break connection if write fails --- Firmware/RTK_Everywhere/NtripServer.ino | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index d2030560d..c84e21231 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -445,11 +445,25 @@ void ntripServerProcessRTCM(int serverIndex, uint8_t incoming) if (ntripServer->networkClient && ntripServer->networkClient->connected()) { - ntripServer->networkClient->write(incoming); // Send this byte to socket - ntripServer->bytesSent = ntripServer->bytesSent + 1; - ntripServer->rtcmBytesSent = ntripServer->rtcmBytesSent + 1; - ntripServer->timer = millis(); - netOutgoingRTCM = true; + if (ntripServer->networkClient->write(incoming) == 1) // Send this byte to socket + { + ntripServer->bytesSent = ntripServer->bytesSent + 1; + ntripServer->rtcmBytesSent = ntripServer->rtcmBytesSent + 1; + ntripServer->timer = millis(); + netOutgoingRTCM = true; + if (ntripServer->networkClient->available()) + ntripServer->networkClient->read(); // Gently absorb any unwanted incoming traffic + } + // Failed to write the data + else + { + // Done with this client connection + if (!inMainMenu) + systemPrintf("NTRIP Server %d breaking connection to %s\r\n", serverIndex, + settings.ntripServer_CasterHost[serverIndex]); + + ntripServerShutdown(serverIndex); + } } } From 248be192a480d39aaa218a712c75a96ef16d7ab5 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Wed, 5 Nov 2025 14:13:53 +0000 Subject: [PATCH 06/17] TcpClient - gently absorb incoming data (to free TCP resources) --- Firmware/RTK_Everywhere/TcpClient.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Firmware/RTK_Everywhere/TcpClient.ino b/Firmware/RTK_Everywhere/TcpClient.ino index 690e872ac..e8b4c69e1 100644 --- a/Firmware/RTK_Everywhere/TcpClient.ino +++ b/Firmware/RTK_Everywhere/TcpClient.ino @@ -249,6 +249,9 @@ int32_t tcpClientSendData(uint16_t dataHead) bytesToSend = dataHead - tcpClientTail; if (bytesToSend < 0) bytesToSend += settings.gnssHandlerBufferSize; + + if(tcpClient->available()) + tcpClient->read(); // Gently absorb any unwanted incoming traffic } // Failed to write the data From 0b0d0521cdfede41ac7b79637584f44b964c519e Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Wed, 5 Nov 2025 16:41:54 +0000 Subject: [PATCH 07/17] Absorb all available data in ntripServer and tcpClient --- Firmware/RTK_Everywhere/NtripServer.ino | 10 ++++------ Firmware/RTK_Everywhere/TcpClient.ino | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index c84e21231..4566a1239 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -451,18 +451,16 @@ void ntripServerProcessRTCM(int serverIndex, uint8_t incoming) ntripServer->rtcmBytesSent = ntripServer->rtcmBytesSent + 1; ntripServer->timer = millis(); netOutgoingRTCM = true; - if (ntripServer->networkClient->available()) - ntripServer->networkClient->read(); // Gently absorb any unwanted incoming traffic + while (ntripServer->networkClient->available()) + ntripServer->networkClient->read(); // Absorb any unwanted incoming traffic } // Failed to write the data else { // Done with this client connection - if (!inMainMenu) - systemPrintf("NTRIP Server %d breaking connection to %s\r\n", serverIndex, + if (settings.debugNtripServerRtcm && (!inMainMenu)) + systemPrintf("NTRIP Server %d broken connection to %s\r\n", serverIndex, settings.ntripServer_CasterHost[serverIndex]); - - ntripServerShutdown(serverIndex); } } } diff --git a/Firmware/RTK_Everywhere/TcpClient.ino b/Firmware/RTK_Everywhere/TcpClient.ino index e8b4c69e1..e45def741 100644 --- a/Firmware/RTK_Everywhere/TcpClient.ino +++ b/Firmware/RTK_Everywhere/TcpClient.ino @@ -250,8 +250,8 @@ int32_t tcpClientSendData(uint16_t dataHead) if (bytesToSend < 0) bytesToSend += settings.gnssHandlerBufferSize; - if(tcpClient->available()) - tcpClient->read(); // Gently absorb any unwanted incoming traffic + while(tcpClient->available()) + tcpClient->read(); // Absorb any unwanted incoming traffic } // Failed to write the data From 7772ba5782b18c7234b596c51b73d0419731d05d Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Wed, 5 Nov 2025 16:42:39 +0000 Subject: [PATCH 08/17] Remove redundant checks around networkMulticastDNSUpdate --- Firmware/RTK_Everywhere/Network.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 651fd049b..7a8a531c6 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -2458,8 +2458,7 @@ void networkUpdate() // Update the network services // Start or stop mDNS - if (networkMdnsRequests != networkMdnsRunning) - networkMulticastDNSUpdate(); + networkMulticastDNSUpdate(); // Update the network services DMW_c("mqttClientUpdate"); From 184515262634cac62c039d4cfe1973b42059f70c Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Sat, 8 Nov 2025 13:48:51 +0000 Subject: [PATCH 09/17] Add NTRIP_SERVER_DATA semaphore and mutex methods --- Firmware/RTK_Everywhere/NtripServer.ino | 8 ++--- Firmware/RTK_Everywhere/settings.h | 41 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index 4566a1239..83b0ecb2e 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -447,9 +447,7 @@ void ntripServerProcessRTCM(int serverIndex, uint8_t incoming) { if (ntripServer->networkClient->write(incoming) == 1) // Send this byte to socket { - ntripServer->bytesSent = ntripServer->bytesSent + 1; - ntripServer->rtcmBytesSent = ntripServer->rtcmBytesSent + 1; - ntripServer->timer = millis(); + ntripServer->updateAfterWrite(); netOutgoingRTCM = true; while (ntripServer->networkClient->available()) ntripServer->networkClient->read(); // Absorb any unwanted incoming traffic @@ -828,7 +826,7 @@ void ntripServerUpdate(int serverIndex) settings.ntripServer_CasterHost[serverIndex]); ntripServerRestart(serverIndex); } - else if ((millis() - ntripServer->timer) > (10 * 1000)) + else if (ntripServer->millisSinceLastWrite() > (10 * 1000)) { // GNSS stopped sending RTCM correction data systemPrintf("NTRIP Server %d breaking connection to %s due to lack of RTCM data!\r\n", serverIndex, @@ -843,7 +841,7 @@ void ntripServerUpdate(int serverIndex) // connection. However increasing backoff delays should be // added when the NTRIP caster fails after a short connection // interval. - if (((millis() - ntripServer->startTime) > NTRIP_SERVER_CONNECTION_TIME) && + if ((ntripServer->millisSinceStart() > NTRIP_SERVER_CONNECTION_TIME) && (ntripServer->connectionAttempts || ntripServer->connectionAttemptTimeout)) { // After a long connection period, reset the attempt counter diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 6f221d484..437276f71 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -413,6 +413,47 @@ typedef struct // Better debug printing by ntripServerProcessRTCM volatile uint32_t rtcmBytesSent; volatile uint32_t previousMilliseconds; + + SemaphoreHandle_t serverSemaphore = NULL; + + unsigned long millisSinceLastWrite() + { + unsigned long retVal = 0; + if (serverSemaphore == NULL) + serverSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(serverSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + retVal = millis() - timer; + xSemaphoreGive(serverSemaphore); + } + return retVal; + } + + unsigned long millisSinceStart() + { + unsigned long retVal = 0; + if (serverSemaphore == NULL) + serverSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(serverSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + retVal = millis() - startTime; + xSemaphoreGive(serverSemaphore); + } + return retVal; + } + + void updateAfterWrite() + { + if (serverSemaphore == NULL) + serverSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(serverSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + bytesSent = bytesSent + 1; + rtcmBytesSent = rtcmBytesSent + 1; + timer = millis(); + xSemaphoreGive(serverSemaphore); + } + } } NTRIP_SERVER_DATA; #endif // COMPILE_NETWORK From 30c5fbe0b202f401401baeae5ba93778549cfba4 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Sun, 9 Nov 2025 07:37:41 +0000 Subject: [PATCH 10/17] More NTRIP_SERVER_DATA mutex methods --- Firmware/RTK_Everywhere/NtripServer.ino | 31 +++++------- Firmware/RTK_Everywhere/settings.h | 65 +++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index 83b0ecb2e..61e0b96b6 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -380,7 +380,7 @@ void ntripServerPrintStatus(int serverIndex) if (ntripServer->state == NTRIP_SERVER_CASTING) // Use ntripServer->timer since it gets reset after each successful data // reception from the NTRIP caster - milliseconds = ntripServer->timer - ntripServer->startTime; + milliseconds = ntripServer->getUptime(); else { milliseconds = ntripServer->startTime; @@ -434,20 +434,15 @@ void ntripServerProcessRTCM(int serverIndex, uint8_t incoming) } // If we have not gotten new RTCM bytes for a period of time, assume end of frame - if (((millis() - ntripServer->timer) > 100) && (ntripServer->bytesSent > 0)) - { - if ((!inMainMenu) && settings.debugNtripServerRtcm) - systemPrintf("NTRIP Server %d transmitted %d RTCM bytes to Caster\r\n", serverIndex, - ntripServer->bytesSent); - - ntripServer->bytesSent = 0; - } + if (ntripServer->checkBytesSentAndReset(100) && (!inMainMenu) && settings.debugNtripServerRtcm) + systemPrintf("NTRIP Server %d transmitted %d RTCM bytes to Caster\r\n", serverIndex, + ntripServer->bytesSent); if (ntripServer->networkClient && ntripServer->networkClient->connected()) { if (ntripServer->networkClient->write(incoming) == 1) // Send this byte to socket { - ntripServer->updateAfterWrite(); + ntripServer->updateTimerAndBytesSent(); netOutgoingRTCM = true; while (ntripServer->networkClient->available()) ntripServer->networkClient->read(); // Absorb any unwanted incoming traffic @@ -498,7 +493,7 @@ void ntripServerRestart(int serverIndex) // Save the previous uptime value if (ntripServer->state == NTRIP_SERVER_CASTING) - ntripServer->startTime = ntripServer->timer - ntripServer->startTime; + ntripServer->startTime = ntripServer->getUptime(); ntripServerConnectLimitReached(serverIndex); } @@ -576,7 +571,7 @@ void ntripServerStop(int serverIndex, bool shutdown) // Increase timeouts if we started the network if (ntripServer->state > NTRIP_SERVER_OFF) // Mark the Server stop so that we don't immediately attempt re-connect to Caster - ntripServer->timer = millis(); + ntripServer->setTimerToMillis(); // Determine the next NTRIP server state online.ntripServer[serverIndex] = false; @@ -707,7 +702,7 @@ void ntripServerUpdate(int serverIndex) // Initiate the connection to the NTRIP caster case NTRIP_SERVER_CONNECTING: // Delay before opening the NTRIP server connection - if ((millis() - ntripServer->timer) >= ntripServer->connectionAttemptTimeout) + if (ntripServer->checkConnectionAttemptTimeout()) { // Attempt a connection to the NTRIP caster if (!ntripServerConnectCaster(serverIndex)) @@ -721,7 +716,7 @@ void ntripServerUpdate(int serverIndex) else { // Connection open to NTRIP caster, wait for the authorization response - ntripServer->timer = millis(); + ntripServer->setTimerToMillis(); ntripServerSetState(serverIndex, NTRIP_SERVER_AUTHORIZATION); } } @@ -734,7 +729,7 @@ void ntripServerUpdate(int serverIndex) strlen("ICY 200 OK")) // Wait until at least a few bytes have arrived { // Check for response timeout - if ((millis() - ntripServer->timer) > 10000) + if (ntripServer->millisSinceTimer() > 10000) { if (ntripServerConnectLimitReached(serverIndex)) systemPrintf( @@ -781,7 +776,7 @@ void ntripServerUpdate(int serverIndex) settings.ntripServer_MountPoint[serverIndex]); // Connection is now open, start the RTCM correction data timer - ntripServer->timer = millis(); + ntripServer->setTimerToMillis(); // We don't use a task because we use I2C hardware (and don't have a semaphore). online.ntripServer[serverIndex] = true; @@ -826,7 +821,7 @@ void ntripServerUpdate(int serverIndex) settings.ntripServer_CasterHost[serverIndex]); ntripServerRestart(serverIndex); } - else if (ntripServer->millisSinceLastWrite() > (10 * 1000)) + else if (ntripServer->millisSinceTimer() > (10 * 1000)) { // GNSS stopped sending RTCM correction data systemPrintf("NTRIP Server %d breaking connection to %s due to lack of RTCM data!\r\n", serverIndex, @@ -841,7 +836,7 @@ void ntripServerUpdate(int serverIndex) // connection. However increasing backoff delays should be // added when the NTRIP caster fails after a short connection // interval. - if ((ntripServer->millisSinceStart() > NTRIP_SERVER_CONNECTION_TIME) && + if ((ntripServer->millisSinceStartTime() > NTRIP_SERVER_CONNECTION_TIME) && (ntripServer->connectionAttempts || ntripServer->connectionAttemptTimeout)) { // After a long connection period, reset the attempt counter diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 437276f71..baafb1135 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -414,9 +414,11 @@ typedef struct volatile uint32_t rtcmBytesSent; volatile uint32_t previousMilliseconds; + + // Protect all methods that manipulate timer with a mutex - to avoid race conditions SemaphoreHandle_t serverSemaphore = NULL; - unsigned long millisSinceLastWrite() + unsigned long millisSinceTimer() { unsigned long retVal = 0; if (serverSemaphore == NULL) @@ -429,7 +431,7 @@ typedef struct return retVal; } - unsigned long millisSinceStart() + unsigned long millisSinceStartTime() { unsigned long retVal = 0; if (serverSemaphore == NULL) @@ -442,7 +444,7 @@ typedef struct return retVal; } - void updateAfterWrite() + void updateTimerAndBytesSent() { if (serverSemaphore == NULL) serverSemaphore = xSemaphoreCreateMutex(); @@ -454,6 +456,63 @@ typedef struct xSemaphoreGive(serverSemaphore); } } + + bool checkBytesSentAndReset(uint32_t timerLimit) + { + bool retVal = false; + if (serverSemaphore == NULL) + serverSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(serverSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + if (((millis() - timer) > timerLimit) && (bytesSent > 0)) + { + retVal = true; + bytesSent = 0; + } + xSemaphoreGive(serverSemaphore); + } + return retVal; + } + + unsigned long getUptime() + { + unsigned long retVal = 0; + if (serverSemaphore == NULL) + serverSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(serverSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + retVal = timer - startTime; + xSemaphoreGive(serverSemaphore); + } + return retVal; + } + + void setTimerToMillis() + { + if (serverSemaphore == NULL) + serverSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(serverSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + timer = millis(); + xSemaphoreGive(serverSemaphore); + } + } + + bool checkConnectionAttemptTimeout() + { + bool retVal = false; + if (serverSemaphore == NULL) + serverSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(serverSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + if ((millis() - timer) >= connectionAttemptTimeout) + { + retVal = true; + } + xSemaphoreGive(serverSemaphore); + } + return retVal; + } } NTRIP_SERVER_DATA; #endif // COMPILE_NETWORK From 61f5ead69eebab4f2d2fb9b706b2657acb312623 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Sun, 9 Nov 2025 07:58:17 +0000 Subject: [PATCH 11/17] Remove ntripServer lastConnectionAttempt - it is never set! lastConnectionAttempt looks like very old code from RTK Firmware The reconnect delay is handled by NTRIP_SERVER_CONNECTING --- Firmware/RTK_Everywhere/NtripServer.ino | 3 +-- Firmware/RTK_Everywhere/settings.h | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index 61e0b96b6..1353783ac 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -683,8 +683,7 @@ void ntripServerUpdate(int serverIndex) // Failed to connect to to the network, attempt to restart the network ntripServerRestart(serverIndex); - else if (settings.enableNtripServer && - ((millis() - ntripServer->lastConnectionAttempt) > ntripServer->connectionAttemptTimeout)) + else if (settings.enableNtripServer) { // No RTCM correction data sent yet rtcmPacketsSent = 0; diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index baafb1135..f23f8a1cf 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -398,7 +398,6 @@ typedef struct // Throttle the time between connection attempts // ms - Max of 4,294,967,295 or 4.3M seconds or 71,000 minutes or 1193 hours or 49 days between attempts volatile uint32_t connectionAttemptTimeout; - volatile uint32_t lastConnectionAttempt; volatile int connectionAttempts; // Count the number of connection attempts between restarts // NTRIP server timer usage: @@ -416,6 +415,8 @@ typedef struct // Protect all methods that manipulate timer with a mutex - to avoid race conditions + // Remember that data is pushed to the servers by + // gnssReadTask -> processUart1Message -> processRTCM -> ntripServerProcessRTCM SemaphoreHandle_t serverSemaphore = NULL; unsigned long millisSinceTimer() From f7c33e02e51f1fb07243bc91c3622fb84ac82205 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Sun, 9 Nov 2025 10:52:18 +0000 Subject: [PATCH 12/17] Add semaphore protection for lastSetupMenuChange This should prevent the occasional glitching during button setup --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 35 +++++++++++++++++++++- Firmware/RTK_Everywhere/States.ino | 2 +- Firmware/RTK_Everywhere/Tasks.ino | 10 +++---- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index ae2144fe1..57b56c17f 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -872,7 +872,40 @@ uint32_t rtcmLastPacketSent; // Time stamp of RTCM going out (to NTRIP Server, E uint32_t maxSurveyInWait_s = 60L * 15L; // Re-start survey-in after X seconds -uint32_t lastSetupMenuChange; // Limits how much time is spent in the setup menu +typedef struct { + uint32_t timer; + + SemaphoreHandle_t updateSemaphore = NULL; + + void setTimerToMillis() + { + if (updateSemaphore == NULL) + updateSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(updateSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + timer = millis(); + xSemaphoreGive(updateSemaphore); + } + } + + unsigned long millisSinceUpdate() + { + unsigned long retVal = 0; + if (updateSemaphore == NULL) + updateSemaphore = xSemaphoreCreateMutex(); + if (xSemaphoreTake(updateSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) + { + retVal = millis() - timer; + xSemaphoreGive(updateSemaphore); + } + return retVal; + } +} semaphoreProtectedTimer; +// Needs a mutex because the timer is updated by the button task +// but read by stateUpdate the loop. Prevents a race condition +// and the occasional glitching seen in the button menu +semaphoreProtectedTimer lastSetupMenuChange; // Limits how much time is spent in the setup menu + uint32_t lastTestMenuChange; // Avoids exiting the test menu for at least 1 second uint8_t setupSelectedButton = 0; // In Display Setup, start displaying at this button. This is the selected (highlighted) button. diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 708f4fab9..b66a06661 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -399,7 +399,7 @@ void stateUpdate() break; case (STATE_DISPLAY_SETUP): { - if ((millis() - lastSetupMenuChange) > 10000) // Exit Setup after 10s + if (lastSetupMenuChange.millisSinceUpdate() > 10000) // Exit Setup after 10s { firstButtonThrownOut = false; changeState(lastSystemState); // Return to the last system state diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 60ee9a1c8..97b04f392 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -2183,7 +2183,7 @@ void buttonCheckTask(void *e) else if ((systemState == STATE_BASE_NOT_STARTED) && (firstRoverStart == true) && (buttonPressedFor(500) == true)) { - lastSetupMenuChange = millis(); // Prevent a timeout during state change + lastSetupMenuChange.setTimerToMillis(); // Prevent a timeout during state change forceSystemStateUpdate = true; requestChangeState(STATE_TEST); } @@ -2216,7 +2216,7 @@ void buttonCheckTask(void *e) case STATE_NTPSERVER_SYNC: lastSystemState = systemState; // Remember this state to return if needed requestChangeState(STATE_DISPLAY_SETUP); - lastSetupMenuChange = millis(); + lastSetupMenuChange.setTimerToMillis(); setupSelectedButton = 0; // Highlight the first button showMenu = false; break; @@ -2225,7 +2225,7 @@ void buttonCheckTask(void *e) // If we are displaying the setup menu, a single tap will cycle through possible system states // Exit into new system state on double tap - see below // Exit display setup into previous state after ~10s - see updateSystemState() - lastSetupMenuChange = millis(); + lastSetupMenuChange.setTimerToMillis(); forceDisplayUpdate = true; // User is interacting so repaint display quickly @@ -2262,7 +2262,7 @@ void buttonCheckTask(void *e) case STATE_TESTING: // If we are in testing, return to Base Not Started - lastSetupMenuChange = millis(); // Prevent a timeout during state change + lastSetupMenuChange.setTimerToMillis(); // Prevent a timeout during state change baseCasterDisableOverride(); // Leave Caster mode requestChangeState(STATE_BASE_NOT_STARTED); break; @@ -2287,7 +2287,7 @@ void buttonCheckTask(void *e) // If we are displaying the setup menu, a single tap will cycle through possible system states - see // above Exit into new system state on double tap Exit display setup into previous state after ~10s // - see updateSystemState() - lastSetupMenuChange = millis(); // Prevent a timeout during state change + lastSetupMenuChange.setTimerToMillis(); // Prevent a timeout during state change uint8_t thisIsButton = 0; for (auto it = setupButtons.begin(); it != setupButtons.end(); it = std::next(it)) { From aa031fa9dd3d711a0348130c190171b0b182e517 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Sun, 9 Nov 2025 11:17:01 +0000 Subject: [PATCH 13/17] Sync more often if log file size is not increasing --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 7 ++++--- Firmware/RTK_Everywhere/Tasks.ino | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 57b56c17f..7b3932561 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -944,7 +944,7 @@ uint32_t max_idle_count = MAX_IDLE_TIME_COUNT; bool bluetoothIncomingRTCM; bool bluetoothOutgoingRTCM; bool netIncomingRTCM; -bool netOutgoingRTCM; +volatile bool netOutgoingRTCM; volatile bool mqttClientDataReceived; // Flag for display uint16_t failedParserMessages_UBX; @@ -1669,7 +1669,7 @@ void logUpdate() { // Calculate generation and write speeds every 5 seconds uint64_t fileSizeDelta = logFileSize - lastLogSize; - systemPrintf(" - Generation rate: %0.1fkB/s", ((float)fileSizeDelta) / 5.0 / 1000.0); + systemPrintf(" - Generation rate: %0.1fkB/s", ((double)fileSizeDelta) / 5.0 / 1000.0); } else { @@ -1686,7 +1686,8 @@ void logUpdate() } else { - log_d("No increase in file size"); + if ((settings.enablePrintLogFileStatus) && (!inMainMenu)) + systemPrintf("No increase in file size: %llu -> %llu\r\n", lastLogSize, logFileSize); logIncreasing = false; endSD(false, true); // alreadyHaveSemaphore, releaseSemaphore diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 97b04f392..c651537bd 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -1693,8 +1693,9 @@ void handleGnssDataTask(void *e) logFileSize = logFile->fileSize(); // Update file size - // Force file sync every 60s - if ((millis() - lastUBXLogSyncTime) > 60000) + // Force file sync every 60s - or every two seconds if the size is not increasing + if (((logFileSize == lastLogSize) && ((millis() - lastUBXLogSyncTime) > 2000)) + || ((millis() - lastUBXLogSyncTime) > 60000)) { baseStatusLedBlink(); // Blink LED to indicate logging activity From 19c6f162b87031c3efcfbf47da1dbd5f6745ce4d Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Sun, 9 Nov 2025 11:43:24 +0000 Subject: [PATCH 14/17] Increase uartReceiveBufferSize to 4K. EVK needs 4K. SEMP errors are seen with 2K and 3K. --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 2 +- Firmware/RTK_Everywhere/settings.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 7b3932561..5d53d478a 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -607,7 +607,7 @@ uint8_t *ringBuffer; // Buffer for reading from GNSS receiver. At 230400bps, 230 const int gnssReadTaskStackSize = 8000; const size_t sempGnssReadBufferSize = 8000; // Make the SEMP buffer size the ~same -const int handleGnssDataTaskStackSize = 3000; +const int handleGnssDataTaskStackSize = 4000; TaskHandle_t pinBluetoothTaskHandle; // Dummy task to start hardware on an assigned core volatile bool bluetoothPinned; // This variable is touched by core 0 but checked by core 1. Must be volatile. diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index f23f8a1cf..b99209dac 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -861,11 +861,11 @@ struct Settings // GNSS UART uint16_t serialGNSSRxFullThreshold = 50; // RX FIFO full interrupt. Max of ~128. See pinUART2Task(). - int uartReceiveBufferSize = 1024 * 2; // This buffer is filled automatically as the UART receives characters. + int uartReceiveBufferSize = 1024 * 4; // This buffer is filled automatically as the UART receives characters. EVK needs 4K // Hardware - bool enableExternalHardwareEventLogging = false; // Log when INT/TM2 pin goes low - uint16_t spiFrequency = 16; // By default, use 16MHz SPI + bool enableExternalHardwareEventLogging = false; // Log when INT/TM2 pin goes low + uint16_t spiFrequency = 16; // By default, use 16MHz SPI // HTTP bool debugHttpClientData = false; // Debug the HTTP Client (ZTP) data flow From 91d719e5d5b36519923afacea63db855073caaa7 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Sun, 9 Nov 2025 13:33:16 +0000 Subject: [PATCH 15/17] Initialize previousPriority - to display IP address on first connect --- Firmware/RTK_Everywhere/Display.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index e676d173e..bcb1ef59a 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2032,7 +2032,7 @@ void displayFullIPAddress(std::vector *iconList) // Bottom { static IPAddress ipAddress; NetPriority_t priority; - static NetPriority_t previousPriority; + static NetPriority_t previousPriority = NETWORK_NONE; // Max width: 15*6 = 90 pixels (6 pixels per character, nnn.nnn.nnn.nnn) if (present.display_type == DISPLAY_128x64) From ba34680b9c41ea62804397e66f680b470280a112 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Mon, 10 Nov 2025 09:29:42 +0000 Subject: [PATCH 16/17] Make semaphoreProtectedTimer timer volatile! --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 5d53d478a..90d4f8bf7 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -873,7 +873,7 @@ uint32_t rtcmLastPacketSent; // Time stamp of RTCM going out (to NTRIP Server, E uint32_t maxSurveyInWait_s = 60L * 15L; // Re-start survey-in after X seconds typedef struct { - uint32_t timer; + volatile unsigned long timer; SemaphoreHandle_t updateSemaphore = NULL; From 1aa3465014f9f3503c03481e5d723ee772cabaed Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Mon, 10 Nov 2025 11:48:19 +0000 Subject: [PATCH 17/17] Add comment --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 90d4f8bf7..20cdf21b7 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -895,6 +895,8 @@ typedef struct { updateSemaphore = xSemaphoreCreateMutex(); if (xSemaphoreTake(updateSemaphore, 10 / portTICK_PERIOD_MS) == pdPASS) { + // The semaphore prevents the race condition where timer is updated after + // millis() is read but before the subtraction. It prevents retVal from underflowing retVal = millis() - timer; xSemaphoreGive(updateSemaphore); }