Переглянути джерело

ESP32 HAL: Fix random pauses during prints (#16548)

felixstorm 4 роки тому
джерело
коміт
2b9eb4437b

+ 41
- 0
Marlin/src/HAL/HAL_ESP32/HAL.h Переглянути файл

@@ -137,3 +137,44 @@ void HAL_adc_start_conversion(uint8_t adc_pin);
137 137
 void HAL_idletask();
138 138
 void HAL_init();
139 139
 void HAL_init_board();
140
+
141
+//
142
+// Delay in cycles (used by DELAY_NS / DELAY_US)
143
+//
144
+FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
145
+  unsigned long start, ccount, stop;
146
+
147
+  /**
148
+   * It's important to care for race conditions (and overflows) here.
149
+   * Race condition example: If `stop` calculates to being close to the upper boundary of
150
+   * `uint32_t` and if at the same time a longer loop interruption kicks in (e.g. due to other
151
+   * FreeRTOS tasks or interrupts), `ccount` might overflow (and therefore be below `stop` again)
152
+   * without the loop ever being able to notice that `ccount` had already been above `stop` once
153
+   * (and that therefore the number of cycles to delay has already passed).
154
+   * As DELAY_CYCLES (through DELAY_NS / DELAY_US) is used by software SPI bit banging to drive
155
+   * LCDs and therefore might be called very, very often, this seemingly improbable situation did
156
+   * actually happen in reality. It resulted in apparently random print pauses of ~17.9 seconds
157
+   * (0x100000000 / 240 MHz) or multiples thereof, essentially ruining the current print by causing
158
+   * large blobs of filament.
159
+   */
160
+
161
+  __asm__ __volatile__ ( "rsr     %0, ccount" : "=a" (start) );
162
+  stop = start + x;
163
+  ccount = start;
164
+
165
+  if (stop >= start) {
166
+    // no overflow, so only loop while in between start and stop:
167
+    // 0x00000000 -----------------start****stop-- 0xffffffff
168
+    while (ccount >= start && ccount < stop) {
169
+      __asm__ __volatile__ ( "rsr     %0, ccount" : "=a" (ccount) );
170
+    }
171
+  }
172
+  else {
173
+    // stop did overflow, so only loop while outside of stop and start:
174
+    // 0x00000000 **stop-------------------start** 0xffffffff
175
+    while (ccount >= start || ccount < stop) {
176
+      __asm__ __volatile__ ( "rsr     %0, ccount" : "=a" (ccount) );
177
+    }
178
+  }
179
+
180
+}

+ 1
- 1
Marlin/src/HAL/HAL_ESP32/Servo.cpp Переглянути файл

@@ -37,7 +37,7 @@ Servo::Servo() {
37 37
 
38 38
 int8_t Servo::attach(const int inPin) {
39 39
   if (channel >= CHANNEL_MAX_NUM) return -1;
40
-  if (pin > 0) pin = inPin;
40
+  if (inPin > 0) pin = inPin;
41 41
 
42 42
   ledcSetup(channel, 50, 16); // channel X, 50 Hz, 16-bit depth
43 43
   ledcAttachPin(pin, channel);

+ 1
- 15
Marlin/src/HAL/shared/Delay.h Переглянути файл

@@ -145,21 +145,7 @@
145 145
   }
146 146
   #undef nop
147 147
 
148
-#elif defined(ESP32)
149
-
150
-  FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
151
-    unsigned long ccount, stop;
152
-
153
-    __asm__ __volatile__ ( "rsr     %0, ccount" : "=a" (ccount) );
154
-
155
-    stop = ccount + x; // This can overflow
156
-
157
-    while (ccount < stop) { // This doesn't deal with overflows
158
-      __asm__ __volatile__ ( "rsr     %0, ccount" : "=a" (ccount) );
159
-    }
160
-  }
161
-
162
-#elif defined(__PLAT_LINUX__)
148
+#elif defined(__PLAT_LINUX__) || defined(ESP32)
163 149
 
164 150
   // specified inside platform
165 151
 

Завантаження…
Відмінити
Зберегти