From 2b9eb4437b4a1192d25f7351ff1d67de2970db17 Mon Sep 17 00:00:00 2001
From: felixstorm <felix.storm@glueckkanja.com>
Date: Thu, 16 Jan 2020 12:57:14 +0100
Subject: [PATCH] ESP32 HAL: Fix random pauses during prints (#16548)
---
Marlin/src/HAL/HAL_ESP32/HAL.h | 41 ++++++++++++++++++++++++++++++
Marlin/src/HAL/HAL_ESP32/Servo.cpp | 2 +-
Marlin/src/HAL/shared/Delay.h | 16 +-----------
3 files changed, 43 insertions(+), 16 deletions(-)
diff --git a/Marlin/src/HAL/HAL_ESP32/HAL.h b/Marlin/src/HAL/HAL_ESP32/HAL.h
index 2e0cd32ec1..2c6858ba9c 100644
--- a/Marlin/src/HAL/HAL_ESP32/HAL.h
+++ b/Marlin/src/HAL/HAL_ESP32/HAL.h
@@ -137,3 +137,44 @@ void HAL_adc_start_conversion(uint8_t adc_pin);
void HAL_idletask();
void HAL_init();
void HAL_init_board();
+
+//
+// Delay in cycles (used by DELAY_NS / DELAY_US)
+//
+FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
+ unsigned long start, ccount, stop;
+
+ /**
+ * It's important to care for race conditions (and overflows) here.
+ * Race condition example: If `stop` calculates to being close to the upper boundary of
+ * `uint32_t` and if at the same time a longer loop interruption kicks in (e.g. due to other
+ * FreeRTOS tasks or interrupts), `ccount` might overflow (and therefore be below `stop` again)
+ * without the loop ever being able to notice that `ccount` had already been above `stop` once
+ * (and that therefore the number of cycles to delay has already passed).
+ * As DELAY_CYCLES (through DELAY_NS / DELAY_US) is used by software SPI bit banging to drive
+ * LCDs and therefore might be called very, very often, this seemingly improbable situation did
+ * actually happen in reality. It resulted in apparently random print pauses of ~17.9 seconds
+ * (0x100000000 / 240 MHz) or multiples thereof, essentially ruining the current print by causing
+ * large blobs of filament.
+ */
+
+ __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (start) );
+ stop = start + x;
+ ccount = start;
+
+ if (stop >= start) {
+ // no overflow, so only loop while in between start and stop:
+ // 0x00000000 -----------------start****stop-- 0xffffffff
+ while (ccount >= start && ccount < stop) {
+ __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) );
+ }
+ }
+ else {
+ // stop did overflow, so only loop while outside of stop and start:
+ // 0x00000000 **stop-------------------start** 0xffffffff
+ while (ccount >= start || ccount < stop) {
+ __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) );
+ }
+ }
+
+}
diff --git a/Marlin/src/HAL/HAL_ESP32/Servo.cpp b/Marlin/src/HAL/HAL_ESP32/Servo.cpp
index 3c3b8fa704..c80c29a4eb 100644
--- a/Marlin/src/HAL/HAL_ESP32/Servo.cpp
+++ b/Marlin/src/HAL/HAL_ESP32/Servo.cpp
@@ -37,7 +37,7 @@ Servo::Servo() {
int8_t Servo::attach(const int inPin) {
if (channel >= CHANNEL_MAX_NUM) return -1;
- if (pin > 0) pin = inPin;
+ if (inPin > 0) pin = inPin;
ledcSetup(channel, 50, 16); // channel X, 50 Hz, 16-bit depth
ledcAttachPin(pin, channel);
diff --git a/Marlin/src/HAL/shared/Delay.h b/Marlin/src/HAL/shared/Delay.h
index b1dafbb0f5..4ba14d9681 100644
--- a/Marlin/src/HAL/shared/Delay.h
+++ b/Marlin/src/HAL/shared/Delay.h
@@ -145,21 +145,7 @@
}
#undef nop
-#elif defined(ESP32)
-
- FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
- unsigned long ccount, stop;
-
- __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) );
-
- stop = ccount + x; // This can overflow
-
- while (ccount < stop) { // This doesn't deal with overflows
- __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) );
- }
- }
-
-#elif defined(__PLAT_LINUX__)
+#elif defined(__PLAT_LINUX__) || defined(ESP32)
// specified inside platform
--
GitLab