Browse Source

Fix interrupt-based endstop detection

- Also implemented real endstop reading on interrupt.
etagle 6 years ago
parent
commit
569df3fc0c

+ 7
- 14
Marlin/src/HAL/HAL_AVR/endstop_interrupts.h View File

@@ -24,7 +24,7 @@
24 24
  * Endstop Interrupts
25 25
  *
26 26
  * Without endstop interrupts the endstop pins must be polled continually in
27
- * the stepper-ISR via endstops.update(), most of the time finding no change.
27
+ * the temperature-ISR via endstops.update(), most of the time finding no change.
28 28
  * With this feature endstops.update() is called only when we know that at
29 29
  * least one endstop has changed state, saving valuable CPU cycles.
30 30
  *
@@ -40,17 +40,10 @@
40 40
 
41 41
 #include "../../core/macros.h"
42 42
 #include <stdint.h>
43
-
44
-volatile uint8_t e_hit = 0; // Different from 0 when the endstops should be tested in detail.
45
-                            // Must be reset to 0 by the test function when finished.
46
-
47
-// This is what is really done inside the interrupts.
48
-FORCE_INLINE void endstop_ISR_worker( void ) {
49
-  e_hit = 2; // Because the detection of a e-stop hit has a 1 step debouncer it has to be called at least twice.
50
-}
43
+#include "../../module/endstops.h"
51 44
 
52 45
 // One ISR for all EXT-Interrupts
53
-void endstop_ISR(void) { endstop_ISR_worker(); }
46
+void endstop_ISR(void) { endstops.check_possible_change(); }
54 47
 
55 48
 /**
56 49
  * Patch for pins_arduino.h (...\Arduino\hardware\arduino\avr\variants\mega\pins_arduino.h)
@@ -95,19 +88,19 @@ void pciSetup(const int8_t pin) {
95 88
 
96 89
 // Handlers for pin change interrupts
97 90
 #ifdef PCINT0_vect
98
-  ISR(PCINT0_vect) { endstop_ISR_worker(); }
91
+  ISR(PCINT0_vect) { endstop_ISR(); }
99 92
 #endif
100 93
 
101 94
 #ifdef PCINT1_vect
102
-  ISR(PCINT1_vect) { endstop_ISR_worker(); }
95
+  ISR(PCINT1_vect) { endstop_ISR(); }
103 96
 #endif
104 97
 
105 98
 #ifdef PCINT2_vect
106
-  ISR(PCINT2_vect) { endstop_ISR_worker(); }
99
+  ISR(PCINT2_vect) { endstop_ISR(); }
107 100
 #endif
108 101
 
109 102
 #ifdef PCINT3_vect
110
-  ISR(PCINT3_vect) { endstop_ISR_worker(); }
103
+  ISR(PCINT3_vect) { endstop_ISR(); }
111 104
 #endif
112 105
 
113 106
 void setup_endstop_interrupts( void ) {

+ 3
- 9
Marlin/src/HAL/HAL_DUE/endstop_interrupts.h View File

@@ -24,7 +24,7 @@
24 24
  * Endstop Interrupts
25 25
  *
26 26
  * Without endstop interrupts the endstop pins must be polled continually in
27
- * the stepper-ISR via endstops.update(), most of the time finding no change.
27
+ * the temperature-ISR via endstops.update(), most of the time finding no change.
28 28
  * With this feature endstops.update() is called only when we know that at
29 29
  * least one endstop has changed state, saving valuable CPU cycles.
30 30
  *
@@ -37,16 +37,10 @@
37 37
 #ifndef _ENDSTOP_INTERRUPTS_H_
38 38
 #define _ENDSTOP_INTERRUPTS_H_
39 39
 
40
-volatile uint8_t e_hit = 0; // Different from 0 when the endstops should be tested in detail.
41
-                            // Must be reset to 0 by the test function when finished.
42
-
43
-// This is what is really done inside the interrupts.
44
-FORCE_INLINE void endstop_ISR_worker( void ) {
45
-  e_hit = 2; // Because the detection of a e-stop hit has a 1 step debouncer it has to be called at least twice.
46
-}
40
+#include "../../module/endstops.h"
47 41
 
48 42
 // One ISR for all EXT-Interrupts
49
-void endstop_ISR(void) { endstop_ISR_worker(); }
43
+void endstop_ISR(void) { endstops.check_possible_change(); }
50 44
 
51 45
 /**
52 46
  *  Endstop interrupts for Due based targets.

+ 3
- 9
Marlin/src/HAL/HAL_LPC1768/endstop_interrupts.h View File

@@ -24,7 +24,7 @@
24 24
  * Endstop Interrupts
25 25
  *
26 26
  * Without endstop interrupts the endstop pins must be polled continually in
27
- * the stepper-ISR via endstops.update(), most of the time finding no change.
27
+ * the temperature-ISR via endstops.update(), most of the time finding no change.
28 28
  * With this feature endstops.update() is called only when we know that at
29 29
  * least one endstop has changed state, saving valuable CPU cycles.
30 30
  *
@@ -40,16 +40,10 @@
40 40
 //Currently this is untested and broken
41 41
 #error "Please disable Endstop Interrupts LPC176x is currently an unsupported platform"
42 42
 
43
-volatile uint8_t e_hit = 0; // Different from 0 when the endstops should be tested in detail.
44
-                            // Must be reset to 0 by the test function when finished.
45
-
46
-// This is what is really done inside the interrupts.
47
-FORCE_INLINE void endstop_ISR_worker( void ) {
48
-  e_hit = 2; // Because the detection of a e-stop hit has a 1 step debouncer it has to be called at least twice.
49
-}
43
+#include "../../module/endstops.h"
50 44
 
51 45
 // One ISR for all EXT-Interrupts
52
-void endstop_ISR(void) { endstop_ISR_worker(); }
46
+void endstop_ISR(void) { endstops.check_possible_change(); }
53 47
 
54 48
 void setup_endstop_interrupts(void) {
55 49
   #if HAS_X_MAX

+ 3
- 9
Marlin/src/HAL/HAL_STM32F1/endstop_interrupts.h View File

@@ -36,7 +36,7 @@
36 36
  * Endstop Interrupts
37 37
  *
38 38
  * Without endstop interrupts the endstop pins must be polled continually in
39
- * the stepper-ISR via endstops.update(), most of the time finding no change.
39
+ * the temperature-ISR via endstops.update(), most of the time finding no change.
40 40
  * With this feature endstops.update() is called only when we know that at
41 41
  * least one endstop has changed state, saving valuable CPU cycles.
42 42
  *
@@ -49,16 +49,10 @@
49 49
 #ifndef _ENDSTOP_INTERRUPTS_H_
50 50
 #define _ENDSTOP_INTERRUPTS_H_
51 51
 
52
-volatile uint8_t e_hit = 0; // Different from 0 when the endstops should be tested in detail.
53
-                            // Must be reset to 0 by the test function when finished.
54
-
55
-// This is what is really done inside the interrupts.
56
-FORCE_INLINE void endstop_ISR_worker( void ) {
57
-  e_hit = 2; // Because the detection of a e-stop hit has a 1 step debouncer it has to be called at least twice.
58
-}
52
+#include "../../module/endstops.h"
59 53
 
60 54
 // One ISR for all EXT-Interrupts
61
-void endstop_ISR(void) { endstop_ISR_worker(); }
55
+void endstop_ISR(void) { endstops.check_possible_change(); }
62 56
 
63 57
 void setup_endstop_interrupts(void) {
64 58
   #if HAS_X_MAX

+ 2
- 8
Marlin/src/HAL/HAL_STM32F4/endstop_interrupts.h View File

@@ -24,16 +24,10 @@
24 24
 #ifndef _ENDSTOP_INTERRUPTS_H_
25 25
 #define _ENDSTOP_INTERRUPTS_H_
26 26
 
27
-volatile uint8_t e_hit = 0; // Different from 0 when the endstops should be tested in detail.
28
-                            // Must be reset to 0 by the test function when finished.
29
-
30
-// This is what is really done inside the interrupts.
31
-FORCE_INLINE void endstop_ISR_worker( void ) {
32
-  e_hit = 2; // Because the detection of a e-stop hit has a 1 step debouncer it has to be called at least twice.
33
-}
27
+#include "../../module/endstops.h"
34 28
 
35 29
 // One ISR for all EXT-Interrupts
36
-void endstop_ISR(void) { endstop_ISR_worker(); }
30
+void endstop_ISR(void) { endstops.check_possible_change(); }
37 31
 
38 32
 void setup_endstop_interrupts(void) {
39 33
   #if HAS_X_MAX

+ 2
- 8
Marlin/src/HAL/HAL_STM32F7/endstop_interrupts.h View File

@@ -26,16 +26,10 @@
26 26
 #ifndef _ENDSTOP_INTERRUPTS_H_
27 27
 #define _ENDSTOP_INTERRUPTS_H_
28 28
 
29
-volatile uint8_t e_hit = 0; // Different from 0 when the endstops should be tested in detail.
30
-                            // Must be reset to 0 by the test function when finished.
31
-
32
-// This is what is really done inside the interrupts.
33
-FORCE_INLINE void endstop_ISR_worker( void ) {
34
-  e_hit = 2; // Because the detection of a e-stop hit has a 1 step debouncer it has to be called at least twice.
35
-}
29
+#include "../../module/endstops.h"
36 30
 
37 31
 // One ISR for all EXT-Interrupts
38
-void endstop_ISR(void) { endstop_ISR_worker(); }
32
+void endstop_ISR(void) { endstops.check_possible_change(); }
39 33
 
40 34
 void setup_endstop_interrupts(void) {
41 35
   #if HAS_X_MAX

+ 3
- 9
Marlin/src/HAL/HAL_TEENSY35_36/endstop_interrupts.h View File

@@ -24,7 +24,7 @@
24 24
  * Endstop Interrupts
25 25
  *
26 26
  * Without endstop interrupts the endstop pins must be polled continually in
27
- * the stepper-ISR via endstops.update(), most of the time finding no change.
27
+ * the temperature-ISR via endstops.update(), most of the time finding no change.
28 28
  * With this feature endstops.update() is called only when we know that at
29 29
  * least one endstop has changed state, saving valuable CPU cycles.
30 30
  *
@@ -37,16 +37,10 @@
37 37
 #ifndef _ENDSTOP_INTERRUPTS_H_
38 38
 #define _ENDSTOP_INTERRUPTS_H_
39 39
 
40
-volatile uint8_t e_hit = 0; // Different from 0 when the endstops should be tested in detail.
41
-                            // Must be reset to 0 by the test function when finished.
42
-
43
-// This is what is really done inside the interrupts.
44
-FORCE_INLINE void endstop_ISR_worker( void ) {
45
-  e_hit = 2; // Because the detection of a e-stop hit has a 1 step debouncer it has to be called at least twice.
46
-}
40
+#include "../../module/endstops.h"
47 41
 
48 42
 // One ISR for all EXT-Interrupts
49
-void endstop_ISR(void) { endstop_ISR_worker(); }
43
+void endstop_ISR(void) { endstops.check_possible_change(); }
50 44
 
51 45
 /**
52 46
  *  Endstop interrupts for Due based targets.

+ 3
- 9
Marlin/src/Marlin.cpp View File

@@ -95,10 +95,6 @@
95 95
   #include "feature/I2CPositionEncoder.h"
96 96
 #endif
97 97
 
98
-#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
99
-  #include HAL_PATH(HAL, endstop_interrupts.h)
100
-#endif
101
-
102 98
 #if HAS_TRINAMIC
103 99
   #include "feature/tmc_util.h"
104 100
 #endif
@@ -748,7 +744,9 @@ void setup() {
748 744
 
749 745
   print_job_timer.init();   // Initial setup of print job timer
750 746
 
751
-  stepper.init();    // Initialize stepper, this enables interrupts!
747
+  endstops.init();          // Init endstops and pullups
748
+
749
+  stepper.init();           // Init stepper. This enables interrupts!
752 750
 
753 751
   #if HAS_SERVOS
754 752
     servo_init();
@@ -860,10 +858,6 @@ void setup() {
860 858
     i2c.onRequest(i2c_on_request);
861 859
   #endif
862 860
 
863
-  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
864
-    setup_endstop_interrupts();
865
-  #endif
866
-
867 861
   #if DO_SWITCH_EXTRUDER
868 862
     move_extruder_servo(0);  // Initialize extruder servo
869 863
   #endif

+ 207
- 117
Marlin/src/module/endstops.cpp View File

@@ -32,18 +32,27 @@
32 32
 #include "../module/temperature.h"
33 33
 #include "../lcd/ultralcd.h"
34 34
 
35
-// TEST_ENDSTOP: test the old and the current status of an endstop
36
-#define TEST_ENDSTOP(ENDSTOP) (TEST(current_endstop_bits & old_endstop_bits, ENDSTOP))
35
+#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
36
+  #include HAL_PATH(../HAL, endstop_interrupts.h)
37
+#endif
38
+
39
+// TEST_ENDSTOP: test the current status of an endstop
40
+#define TEST_ENDSTOP(ENDSTOP) (TEST(current_endstop_bits, ENDSTOP))
41
+
42
+#if HAS_BED_PROBE
43
+  #define ENDSTOPS_ENABLED  (endstops.enabled || endstops.z_probe_enabled)
44
+#else
45
+  #define ENDSTOPS_ENABLED  endstops.enabled
46
+#endif
37 47
 
38 48
 Endstops endstops;
39 49
 
40 50
 // public:
41 51
 
42 52
 bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.load()
43
-volatile char Endstops::endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
53
+volatile uint8_t Endstops::endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
44 54
 
45
-Endstops::esbits_t Endstops::current_endstop_bits = 0,
46
-                   Endstops::old_endstop_bits = 0;
55
+Endstops::esbits_t Endstops::current_endstop_bits = 0;
47 56
 
48 57
 #if HAS_BED_PROBE
49 58
   volatile bool Endstops::z_probe_enabled = false;
@@ -196,8 +205,93 @@ void Endstops::init() {
196 205
     #endif
197 206
   #endif
198 207
 
208
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
209
+    setup_endstop_interrupts();
210
+  #endif
211
+
212
+  // Enable endstops
213
+  enable_globally(
214
+    #if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
215
+      true
216
+    #else
217
+      false
218
+    #endif
219
+  );
220
+
199 221
 } // Endstops::init
200 222
 
223
+// Called from ISR. A change was detected. Find out what happened!
224
+void Endstops::check_possible_change() { if (ENDSTOPS_ENABLED) endstops.update(); }
225
+
226
+// Called from ISR: Poll endstop state if required
227
+void Endstops::poll() {
228
+
229
+  #if ENABLED(PINS_DEBUGGING)
230
+    endstops.run_monitor();  // report changes in endstop status
231
+  #endif
232
+
233
+  #if DISABLED(ENDSTOP_INTERRUPTS_FEATURE)
234
+    if (ENDSTOPS_ENABLED) endstops.update();
235
+  #endif
236
+}
237
+
238
+void Endstops::enable_globally(const bool onoff) {
239
+  enabled_globally = enabled = onoff;
240
+
241
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
242
+    if (onoff) endstops.update(); // If enabling, update state now
243
+  #endif
244
+}
245
+
246
+// Enable / disable endstop checking
247
+void Endstops::enable(const bool onoff) {
248
+  enabled = onoff;
249
+
250
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
251
+    if (onoff) endstops.update(); // If enabling, update state now
252
+  #endif
253
+}
254
+
255
+
256
+// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
257
+void Endstops::not_homing() {
258
+  enabled = enabled_globally;
259
+
260
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
261
+    if (enabled) endstops.update(); // If enabling, update state now
262
+  #endif
263
+}
264
+
265
+// Clear endstops (i.e., they were hit intentionally) to suppress the report
266
+void Endstops::hit_on_purpose() {
267
+  endstop_hit_bits = 0;
268
+
269
+  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
270
+    if (enabled) endstops.update(); // If enabling, update state now
271
+  #endif
272
+}
273
+
274
+// Enable / disable endstop z-probe checking
275
+#if HAS_BED_PROBE
276
+  void Endstops::enable_z_probe(bool onoff) {
277
+    z_probe_enabled = onoff;
278
+
279
+    #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
280
+      if (enabled) endstops.update(); // If enabling, update state now
281
+    #endif
282
+  }
283
+#endif
284
+
285
+#if ENABLED(PINS_DEBUGGING)
286
+  void Endstops::run_monitor() {
287
+    if (!monitor_flag) return;
288
+    static uint8_t monitor_count = 16;  // offset this check from the others
289
+    monitor_count += _BV(1);            //  15 Hz
290
+    monitor_count &= 0x7F;
291
+    if (!monitor_count) monitor();      // report changes in endstop status
292
+  }
293
+#endif
294
+
201 295
 void Endstops::report_state() {
202 296
   if (endstop_hit_bits) {
203 297
     #if ENABLED(ULTRA_LCD)
@@ -300,38 +394,41 @@ void Endstops::M119() {
300 394
   #endif
301 395
 } // Endstops::M119
302 396
 
397
+// The following routines are called from an ISR context. It could be the temperature ISR, the
398
+// endstop ISR or the Stepper ISR.
399
+
303 400
 #if ENABLED(X_DUAL_ENDSTOPS)
304 401
   void Endstops::test_dual_x_endstops(const EndstopEnum es1, const EndstopEnum es2) {
305 402
     const byte x_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for X, bit 1 for X2
306
-    if (x_test && stepper.current_block->steps[X_AXIS] > 0) {
403
+    if (x_test && stepper.movement_non_null(X_AXIS)) {
307 404
       SBI(endstop_hit_bits, X_MIN);
308 405
       if (!stepper.performing_homing || (x_test == 0x3))  //if not performing home or if both endstops were trigged during homing...
309
-        stepper.kill_current_block();
406
+        stepper.quick_stop();
310 407
     }
311 408
   }
312 409
 #endif
313 410
 #if ENABLED(Y_DUAL_ENDSTOPS)
314 411
   void Endstops::test_dual_y_endstops(const EndstopEnum es1, const EndstopEnum es2) {
315 412
     const byte y_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Y, bit 1 for Y2
316
-    if (y_test && stepper.current_block->steps[Y_AXIS] > 0) {
413
+    if (y_test && stepper.movement_non_null(Y_AXIS)) {
317 414
       SBI(endstop_hit_bits, Y_MIN);
318 415
       if (!stepper.performing_homing || (y_test == 0x3))  //if not performing home or if both endstops were trigged during homing...
319
-        stepper.kill_current_block();
416
+        stepper.quick_stop();
320 417
     }
321 418
   }
322 419
 #endif
323 420
 #if ENABLED(Z_DUAL_ENDSTOPS)
324 421
   void Endstops::test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2) {
325 422
     const byte z_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Z, bit 1 for Z2
326
-    if (z_test && stepper.current_block->steps[Z_AXIS] > 0) {
423
+    if (z_test && stepper.movement_non_null(Z_AXIS)) {
327 424
       SBI(endstop_hit_bits, Z_MIN);
328 425
       if (!stepper.performing_homing || (z_test == 0x3))  //if not performing home or if both endstops were trigged during homing...
329
-        stepper.kill_current_block();
426
+        stepper.quick_stop();
330 427
     }
331 428
   }
332 429
 #endif
333 430
 
334
-// Check endstops - Called from ISR!
431
+// Check endstops - Could be called from ISR!
335 432
 void Endstops::update() {
336 433
 
337 434
   #define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
@@ -358,9 +455,9 @@ void Endstops::update() {
358 455
     if (G38_move) {
359 456
       UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
360 457
       if (TEST_ENDSTOP(_ENDSTOP(Z, MIN_PROBE))) {
361
-        if      (stepper.current_block->steps[_AXIS(X)] > 0) { _ENDSTOP_HIT(X, MIN); planner.endstop_triggered(_AXIS(X)); }
362
-        else if (stepper.current_block->steps[_AXIS(Y)] > 0) { _ENDSTOP_HIT(Y, MIN); planner.endstop_triggered(_AXIS(Y)); }
363
-        else if (stepper.current_block->steps[_AXIS(Z)] > 0) { _ENDSTOP_HIT(Z, MIN); planner.endstop_triggered(_AXIS(Z)); }
458
+        if      (stepper.movement_non_null(_AXIS(X))) { _ENDSTOP_HIT(X, MIN); planner.endstop_triggered(_AXIS(X)); }
459
+        else if (stepper.movement_non_null(_AXIS(Y))) { _ENDSTOP_HIT(Y, MIN); planner.endstop_triggered(_AXIS(Y)); }
460
+        else if (stepper.movement_non_null(_AXIS(Z))) { _ENDSTOP_HIT(Z, MIN); planner.endstop_triggered(_AXIS(Z)); }
364 461
         G38_endstop_hit = true;
365 462
       }
366 463
     }
@@ -371,7 +468,7 @@ void Endstops::update() {
371 468
    */
372 469
 
373 470
   #if IS_CORE
374
-    #define S_(N) stepper.current_block->steps[CORE_AXIS_##N]
471
+    #define S_(N) stepper.movement_non_null(CORE_AXIS_##N)
375 472
     #define D_(N) stepper.motor_direction(CORE_AXIS_##N)
376 473
   #endif
377 474
 
@@ -391,7 +488,7 @@ void Endstops::update() {
391 488
     #define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) X_CMP D_(2)) )
392 489
     #define X_AXIS_HEAD X_HEAD
393 490
   #else
394
-    #define X_MOVE_TEST stepper.current_block->steps[X_AXIS] > 0
491
+    #define X_MOVE_TEST stepper.movement_non_null(X_AXIS)
395 492
     #define X_AXIS_HEAD X_AXIS
396 493
   #endif
397 494
 
@@ -411,7 +508,7 @@ void Endstops::update() {
411 508
     #define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Y_CMP D_(2)) )
412 509
     #define Y_AXIS_HEAD Y_HEAD
413 510
   #else
414
-    #define Y_MOVE_TEST stepper.current_block->steps[Y_AXIS] > 0
511
+    #define Y_MOVE_TEST stepper.movement_non_null(Y_AXIS)
415 512
     #define Y_AXIS_HEAD Y_AXIS
416 513
   #endif
417 514
 
@@ -431,13 +528,13 @@ void Endstops::update() {
431 528
     #define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Z_CMP D_(2)) )
432 529
     #define Z_AXIS_HEAD Z_HEAD
433 530
   #else
434
-    #define Z_MOVE_TEST stepper.current_block->steps[Z_AXIS] > 0
531
+    #define Z_MOVE_TEST stepper.movement_non_null(Z_AXIS)
435 532
     #define Z_AXIS_HEAD Z_AXIS
436 533
   #endif
437 534
 
438 535
   // With Dual X, endstops are only checked in the homing direction for the active extruder
439 536
   #if ENABLED(DUAL_X_CARRIAGE)
440
-    #define E0_ACTIVE stepper.current_block->active_extruder == 0
537
+    #define E0_ACTIVE stepper.movement_extruder() == 0
441 538
     #define X_MIN_TEST ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
442 539
     #define X_MAX_TEST ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
443 540
   #else
@@ -448,126 +545,119 @@ void Endstops::update() {
448 545
   /**
449 546
    * Check and update endstops according to conditions
450 547
    */
451
-  if (stepper.current_block) {
452
-
453
-    if (X_MOVE_TEST) {
454
-      if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
455
-        #if HAS_X_MIN
456
-          #if ENABLED(X_DUAL_ENDSTOPS)
457
-            UPDATE_ENDSTOP_BIT(X, MIN);
458
-            #if HAS_X2_MIN
459
-              UPDATE_ENDSTOP_BIT(X2, MIN);
460
-            #else
461
-              COPY_BIT(current_endstop_bits, X_MIN, X2_MIN);
462
-            #endif
463
-            test_dual_x_endstops(X_MIN, X2_MIN);
548
+  if (X_MOVE_TEST) {
549
+    if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
550
+      #if HAS_X_MIN
551
+        #if ENABLED(X_DUAL_ENDSTOPS)
552
+          UPDATE_ENDSTOP_BIT(X, MIN);
553
+          #if HAS_X2_MIN
554
+            UPDATE_ENDSTOP_BIT(X2, MIN);
464 555
           #else
465
-            if (X_MIN_TEST) UPDATE_ENDSTOP(X, MIN);
556
+            COPY_BIT(current_endstop_bits, X_MIN, X2_MIN);
466 557
           #endif
558
+          test_dual_x_endstops(X_MIN, X2_MIN);
559
+        #else
560
+          if (X_MIN_TEST) UPDATE_ENDSTOP(X, MIN);
467 561
         #endif
468
-      }
469
-      else { // +direction
470
-        #if HAS_X_MAX
471
-          #if ENABLED(X_DUAL_ENDSTOPS)
472
-            UPDATE_ENDSTOP_BIT(X, MAX);
473
-            #if HAS_X2_MAX
474
-              UPDATE_ENDSTOP_BIT(X2, MAX);
475
-            #else
476
-              COPY_BIT(current_endstop_bits, X_MAX, X2_MAX);
477
-            #endif
478
-            test_dual_x_endstops(X_MAX, X2_MAX);
562
+      #endif
563
+    }
564
+    else { // +direction
565
+      #if HAS_X_MAX
566
+        #if ENABLED(X_DUAL_ENDSTOPS)
567
+          UPDATE_ENDSTOP_BIT(X, MAX);
568
+          #if HAS_X2_MAX
569
+            UPDATE_ENDSTOP_BIT(X2, MAX);
479 570
           #else
480
-            if (X_MAX_TEST) UPDATE_ENDSTOP(X, MAX);
571
+            COPY_BIT(current_endstop_bits, X_MAX, X2_MAX);
481 572
           #endif
573
+          test_dual_x_endstops(X_MAX, X2_MAX);
574
+        #else
575
+          if (X_MAX_TEST) UPDATE_ENDSTOP(X, MAX);
482 576
         #endif
483
-      }
577
+      #endif
484 578
     }
579
+  }
485 580
 
486
-    if (Y_MOVE_TEST) {
487
-      if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
488
-        #if HAS_Y_MIN
489
-          #if ENABLED(Y_DUAL_ENDSTOPS)
490
-            UPDATE_ENDSTOP_BIT(Y, MIN);
491
-            #if HAS_Y2_MIN
492
-              UPDATE_ENDSTOP_BIT(Y2, MIN);
493
-            #else
494
-              COPY_BIT(current_endstop_bits, Y_MIN, Y2_MIN);
495
-            #endif
496
-            test_dual_y_endstops(Y_MIN, Y2_MIN);
581
+  if (Y_MOVE_TEST) {
582
+    if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
583
+      #if HAS_Y_MIN
584
+        #if ENABLED(Y_DUAL_ENDSTOPS)
585
+          UPDATE_ENDSTOP_BIT(Y, MIN);
586
+          #if HAS_Y2_MIN
587
+            UPDATE_ENDSTOP_BIT(Y2, MIN);
497 588
           #else
498
-            UPDATE_ENDSTOP(Y, MIN);
589
+            COPY_BIT(current_endstop_bits, Y_MIN, Y2_MIN);
499 590
           #endif
591
+          test_dual_y_endstops(Y_MIN, Y2_MIN);
592
+        #else
593
+          UPDATE_ENDSTOP(Y, MIN);
500 594
         #endif
501
-      }
502
-      else { // +direction
503
-        #if HAS_Y_MAX
504
-          #if ENABLED(Y_DUAL_ENDSTOPS)
505
-            UPDATE_ENDSTOP_BIT(Y, MAX);
506
-            #if HAS_Y2_MAX
507
-              UPDATE_ENDSTOP_BIT(Y2, MAX);
508
-            #else
509
-              COPY_BIT(current_endstop_bits, Y_MAX, Y2_MAX);
510
-            #endif
511
-            test_dual_y_endstops(Y_MAX, Y2_MAX);
595
+      #endif
596
+    }
597
+    else { // +direction
598
+      #if HAS_Y_MAX
599
+        #if ENABLED(Y_DUAL_ENDSTOPS)
600
+          UPDATE_ENDSTOP_BIT(Y, MAX);
601
+          #if HAS_Y2_MAX
602
+            UPDATE_ENDSTOP_BIT(Y2, MAX);
512 603
           #else
513
-            UPDATE_ENDSTOP(Y, MAX);
604
+            COPY_BIT(current_endstop_bits, Y_MAX, Y2_MAX);
514 605
           #endif
606
+          test_dual_y_endstops(Y_MAX, Y2_MAX);
607
+        #else
608
+          UPDATE_ENDSTOP(Y, MAX);
515 609
         #endif
516
-      }
610
+      #endif
517 611
     }
612
+  }
518 613
 
519
-    if (Z_MOVE_TEST) {
520
-      if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
521
-        #if HAS_Z_MIN
522
-          #if ENABLED(Z_DUAL_ENDSTOPS)
523
-            UPDATE_ENDSTOP_BIT(Z, MIN);
524
-            #if HAS_Z2_MIN
525
-              UPDATE_ENDSTOP_BIT(Z2, MIN);
526
-            #else
527
-              COPY_BIT(current_endstop_bits, Z_MIN, Z2_MIN);
528
-            #endif
529
-            test_dual_z_endstops(Z_MIN, Z2_MIN);
614
+  if (Z_MOVE_TEST) {
615
+    if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
616
+      #if HAS_Z_MIN
617
+        #if ENABLED(Z_DUAL_ENDSTOPS)
618
+          UPDATE_ENDSTOP_BIT(Z, MIN);
619
+          #if HAS_Z2_MIN
620
+            UPDATE_ENDSTOP_BIT(Z2, MIN);
621
+          #else
622
+            COPY_BIT(current_endstop_bits, Z_MIN, Z2_MIN);
623
+          #endif
624
+          test_dual_z_endstops(Z_MIN, Z2_MIN);
625
+        #else
626
+          #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
627
+            if (z_probe_enabled) UPDATE_ENDSTOP(Z, MIN);
530 628
           #else
531
-            #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
532
-              if (z_probe_enabled) UPDATE_ENDSTOP(Z, MIN);
533
-            #else
534
-              UPDATE_ENDSTOP(Z, MIN);
535
-            #endif
629
+            UPDATE_ENDSTOP(Z, MIN);
536 630
           #endif
537 631
         #endif
632
+      #endif
538 633
 
539
-        // When closing the gap check the enabled probe
540
-        #if ENABLED(Z_MIN_PROBE_ENDSTOP)
541
-          if (z_probe_enabled) {
542
-            UPDATE_ENDSTOP(Z, MIN_PROBE);
543
-            if (TEST_ENDSTOP(Z_MIN_PROBE)) SBI(endstop_hit_bits, Z_MIN_PROBE);
544
-          }
545
-        #endif
546
-      }
547
-      else { // Z +direction. Gantry up, bed down.
548
-        #if HAS_Z_MAX
549
-          // Check both Z dual endstops
550
-          #if ENABLED(Z_DUAL_ENDSTOPS)
551
-            UPDATE_ENDSTOP_BIT(Z, MAX);
552
-            #if HAS_Z2_MAX
553
-              UPDATE_ENDSTOP_BIT(Z2, MAX);
554
-            #else
555
-              COPY_BIT(current_endstop_bits, Z_MAX, Z2_MAX);
556
-            #endif
557
-            test_dual_z_endstops(Z_MAX, Z2_MAX);
558
-          // If this pin is not hijacked for the bed probe
559
-          // then it belongs to the Z endstop
560
-          #elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
561
-            UPDATE_ENDSTOP(Z, MAX);
634
+      // When closing the gap check the enabled probe
635
+      #if ENABLED(Z_MIN_PROBE_ENDSTOP)
636
+        if (z_probe_enabled) {
637
+          UPDATE_ENDSTOP(Z, MIN_PROBE);
638
+          if (TEST_ENDSTOP(Z_MIN_PROBE)) SBI(endstop_hit_bits, Z_MIN_PROBE);
639
+        }
640
+      #endif
641
+    }
642
+    else { // Z +direction. Gantry up, bed down.
643
+      #if HAS_Z_MAX
644
+        // Check both Z dual endstops
645
+        #if ENABLED(Z_DUAL_ENDSTOPS)
646
+          UPDATE_ENDSTOP_BIT(Z, MAX);
647
+          #if HAS_Z2_MAX
648
+            UPDATE_ENDSTOP_BIT(Z2, MAX);
649
+          #else
650
+            COPY_BIT(current_endstop_bits, Z_MAX, Z2_MAX);
562 651
           #endif
652
+          test_dual_z_endstops(Z_MAX, Z2_MAX);
653
+        // If this pin is not hijacked for the bed probe
654
+        // then it belongs to the Z endstop
655
+        #elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
656
+          UPDATE_ENDSTOP(Z, MAX);
563 657
         #endif
564
-      }
658
+      #endif
565 659
     }
566
-
567
-  } // stepper.current_block
568
-
569
-  old_endstop_bits = current_endstop_bits;
570
-
660
+  }
571 661
 } // Endstops::update()
572 662
 
573 663
 #if ENABLED(PINS_DEBUGGING)

+ 20
- 29
Marlin/src/module/endstops.h View File

@@ -51,7 +51,7 @@ class Endstops {
51 51
   public:
52 52
 
53 53
     static bool enabled, enabled_globally;
54
-    static volatile char endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
54
+    static volatile uint8_t endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
55 55
 
56 56
     #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
57 57
       typedef uint16_t esbits_t;
@@ -68,17 +68,9 @@ class Endstops {
68 68
       typedef byte esbits_t;
69 69
     #endif
70 70
 
71
-    static esbits_t current_endstop_bits, old_endstop_bits;
71
+    static esbits_t current_endstop_bits;
72 72
 
73
-    Endstops() {
74
-      enable_globally(
75
-        #if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
76
-          true
77
-        #else
78
-          false
79
-        #endif
80
-      );
81
-    };
73
+    Endstops() {};
82 74
 
83 75
     /**
84 76
      * Initialize the endstop pins
@@ -86,6 +78,17 @@ class Endstops {
86 78
     static void init();
87 79
 
88 80
     /**
81
+     * A change was detected or presumed to be in endstops pins. Find out what
82
+     * changed, if anything. Called from ISR contexts
83
+     */
84
+    static void check_possible_change();
85
+
86
+    /**
87
+     * Periodic call to poll endstops if required. Called from temperature ISR
88
+     */
89
+    static void poll();
90
+
91
+    /**
89 92
      * Update the endstops bits from the pins
90 93
      */
91 94
     static void update();
@@ -101,34 +104,28 @@ class Endstops {
101 104
     static void M119();
102 105
 
103 106
     // Enable / disable endstop checking globally
104
-    static void enable_globally(bool onoff=true) { enabled_globally = enabled = onoff; }
107
+    static void enable_globally(const bool onoff=true);
105 108
 
106 109
     // Enable / disable endstop checking
107
-    static void enable(bool onoff=true) { enabled = onoff; }
110
+    static void enable(const bool onoff=true);
108 111
 
109 112
     // Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
110
-    static void not_homing() { enabled = enabled_globally; }
113
+    static void not_homing();
111 114
 
112 115
     // Clear endstops (i.e., they were hit intentionally) to suppress the report
113
-    static void hit_on_purpose() { endstop_hit_bits = 0; }
116
+    static void hit_on_purpose();
114 117
 
115 118
     // Enable / disable endstop z-probe checking
116 119
     #if HAS_BED_PROBE
117 120
       static volatile bool z_probe_enabled;
118
-      static void enable_z_probe(bool onoff=true) { z_probe_enabled = onoff; }
121
+      static void enable_z_probe(bool onoff=true);
119 122
     #endif
120 123
 
121 124
     // Debugging of endstops
122 125
     #if ENABLED(PINS_DEBUGGING)
123 126
       static bool monitor_flag;
124 127
       static void monitor();
125
-      FORCE_INLINE static void run_monitor() {
126
-        if (!monitor_flag) return;
127
-        static uint8_t monitor_count = 16;  // offset this check from the others
128
-        monitor_count += _BV(1);            //  15 Hz
129
-        monitor_count &= 0x7F;
130
-        if (!monitor_count) monitor();      // report changes in endstop status
131
-      }
128
+      static void run_monitor();
132 129
     #endif
133 130
 
134 131
   private:
@@ -146,10 +143,4 @@ class Endstops {
146 143
 
147 144
 extern Endstops endstops;
148 145
 
149
-#if HAS_BED_PROBE
150
-  #define ENDSTOPS_ENABLED  (endstops.enabled || endstops.z_probe_enabled)
151
-#else
152
-  #define ENDSTOPS_ENABLED  endstops.enabled
153
-#endif
154
-
155 146
 #endif // __ENDSTOPS_H__

+ 4
- 19
Marlin/src/module/planner.cpp View File

@@ -758,8 +758,8 @@ void Planner::calculate_trapezoid_for_block(block_t* const block, const float &e
758 758
            final_rate = CEIL(block->nominal_rate * exit_factor); // (steps per second)
759 759
 
760 760
   // Limit minimal step rate (Otherwise the timer will overflow.)
761
-  NOLESS(initial_rate, MINIMAL_STEP_RATE);
762
-  NOLESS(final_rate, MINIMAL_STEP_RATE);
761
+  NOLESS(initial_rate, uint32_t(MINIMAL_STEP_RATE));
762
+  NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE));
763 763
 
764 764
   #if ENABLED(BEZIER_JERK_CONTROL)
765 765
     uint32_t cruise_rate = initial_rate;
@@ -1467,23 +1467,8 @@ void Planner::quick_stop() {
1467 1467
 }
1468 1468
 
1469 1469
 void Planner::endstop_triggered(const AxisEnum axis) {
1470
-
1471
-  /*NB: This will be called via endstops.update()
1472
-    and endstops.update() can be called from the temperature
1473
-    ISR. So Stepper interrupts are enabled */
1474
-
1475
-  // Disable stepper ISR
1476
-  bool stepper_isr_enabled = STEPPER_ISR_ENABLED();
1477
-  DISABLE_STEPPER_DRIVER_INTERRUPT();
1478
-
1479
-  // Record stepper position
1470
+  // Record stepper position and discard the current block
1480 1471
   stepper.endstop_triggered(axis);
1481
-
1482
-  // Discard the active block that led to the trigger
1483
-  discard_current_block();
1484
-
1485
-  // Reenable stepper ISR if it was enabled
1486
-  if (stepper_isr_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
1487 1472
 }
1488 1473
 
1489 1474
 float Planner::triggered_position_mm(const AxisEnum axis) {
@@ -1682,7 +1667,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
1682 1667
   if (de < 0) SBI(dm, E_AXIS);
1683 1668
 
1684 1669
   const float esteps_float = de * e_factor[extruder];
1685
-  const int32_t esteps = ABS(esteps_float) + 0.5;
1670
+  const uint32_t esteps = ABS(esteps_float) + 0.5;
1686 1671
 
1687 1672
   // Clear all flags, including the "busy" bit
1688 1673
   block->flag = 0x00;

+ 40
- 52
Marlin/src/module/stepper.cpp View File

@@ -96,7 +96,10 @@ block_t* Stepper::current_block = NULL;  // A pointer to the block currently bei
96 96
 
97 97
 // private:
98 98
 
99
-uint8_t Stepper::last_direction_bits = 0;        // The next stepping-bits to be output
99
+uint8_t Stepper::last_direction_bits = 0,       // The next stepping-bits to be output
100
+        Stepper::last_movement_extruder = 0xFF; // Last movement extruder, as computed when the last movement was fetched from planner
101
+bool Stepper::abort_current_block,              // Signals to the stepper that current block should be aborted
102
+     Stepper::last_movement_non_null[NUM_AXIS]; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
100 103
 
101 104
 #if ENABLED(X_DUAL_ENDSTOPS)
102 105
   bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
@@ -181,12 +184,12 @@ volatile int32_t Stepper::endstops_trigsteps[XYZ];
181 184
   #define DUAL_ENDSTOP_APPLY_STEP(A,V)                                                                                                           \
182 185
     if (performing_homing) {                                                                                                                        \
183 186
       if (A##_HOME_DIR < 0) {                                                                                                                    \
184
-        if (!(TEST(endstops.old_endstop_bits, A##_MIN) && count_direction[_AXIS(A)] < 0) && !LOCKED_##A##_MOTOR) A##_STEP_WRITE(V);     \
185
-        if (!(TEST(endstops.old_endstop_bits, A##2_MIN) && count_direction[_AXIS(A)] < 0) && !LOCKED_##A##2_MOTOR) A##2_STEP_WRITE(V);  \
187
+        if (!(TEST(endstops.current_endstop_bits, A##_MIN) && count_direction[_AXIS(A)] < 0) && !LOCKED_##A##_MOTOR) A##_STEP_WRITE(V);     \
188
+        if (!(TEST(endstops.current_endstop_bits, A##2_MIN) && count_direction[_AXIS(A)] < 0) && !LOCKED_##A##2_MOTOR) A##2_STEP_WRITE(V);  \
186 189
       }                                                                                                                                             \
187 190
       else {                                                                                                                                        \
188
-        if (!(TEST(endstops.old_endstop_bits, A##_MAX) && count_direction[_AXIS(A)] > 0) && !LOCKED_##A##_MOTOR) A##_STEP_WRITE(V);     \
189
-        if (!(TEST(endstops.old_endstop_bits, A##2_MAX) && count_direction[_AXIS(A)] > 0) && !LOCKED_##A##2_MOTOR) A##2_STEP_WRITE(V);  \
191
+        if (!(TEST(endstops.current_endstop_bits, A##_MAX) && count_direction[_AXIS(A)] > 0) && !LOCKED_##A##_MOTOR) A##_STEP_WRITE(V);     \
192
+        if (!(TEST(endstops.current_endstop_bits, A##2_MAX) && count_direction[_AXIS(A)] > 0) && !LOCKED_##A##2_MOTOR) A##2_STEP_WRITE(V);  \
190 193
       }                                                                                                                                             \
191 194
     }                                                                                                                                               \
192 195
     else {                                                                                                                                          \
@@ -315,10 +318,6 @@ void Stepper::set_directions() {
315 318
   #endif // !LIN_ADVANCE
316 319
 }
317 320
 
318
-#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
319
-  extern volatile uint8_t e_hit;
320
-#endif
321
-
322 321
 #if ENABLED(BEZIER_JERK_CONTROL)
323 322
   /**
324 323
    *   We are using a quintic (fifth-degree) Bézier polynomial for the velocity curve.
@@ -1229,6 +1228,15 @@ hal_timer_t Stepper::isr_scheduler() {
1229 1228
 // as constant as possible!!!!
1230 1229
 void Stepper::stepper_pulse_phase_isr() {
1231 1230
 
1231
+  // If we must abort the current block, do so!
1232
+  if (abort_current_block) {
1233
+    abort_current_block = false;
1234
+    if (current_block) {
1235
+      current_block = NULL;
1236
+      planner.discard_current_block();
1237
+    }
1238
+  }
1239
+
1232 1240
   // If there is no current block, do nothing
1233 1241
   if (!current_block) return;
1234 1242
 
@@ -1558,12 +1566,13 @@ uint32_t Stepper::stepper_block_phase_isr() {
1558 1566
           return interval; // No more queued movements!
1559 1567
       }
1560 1568
 
1561
-      // Initialize the trapezoid generator from the current block.
1562
-      static int8_t last_extruder = -1;
1569
+      // Compute movement direction for proper endstop handling
1570
+      LOOP_NA(i) last_movement_non_null[i] = !!current_block->steps[i];
1563 1571
 
1572
+      // Initialize the trapezoid generator from the current block.
1564 1573
       #if ENABLED(LIN_ADVANCE)
1565 1574
         #if E_STEPPERS > 1
1566
-          if (current_block->active_extruder != last_extruder) {
1575
+          if (current_block->active_extruder != last_movement_extruder) {
1567 1576
             current_adv_steps = 0; // If the now active extruder wasn't in use during the last move, its pressure is most likely gone.
1568 1577
             LA_active_extruder = current_block->active_extruder;
1569 1578
           }
@@ -1576,12 +1585,21 @@ uint32_t Stepper::stepper_block_phase_isr() {
1576 1585
         }
1577 1586
       #endif
1578 1587
 
1579
-      if (current_block->direction_bits != last_direction_bits || current_block->active_extruder != last_extruder) {
1588
+      if (current_block->direction_bits != last_direction_bits || current_block->active_extruder != last_movement_extruder) {
1580 1589
         last_direction_bits = current_block->direction_bits;
1581
-        last_extruder = current_block->active_extruder;
1590
+        last_movement_extruder = current_block->active_extruder;
1582 1591
         set_directions();
1583 1592
       }
1584 1593
 
1594
+      // At this point, we must ensure the movement about to execute isn't
1595
+      // trying to force the head against a limit switch. If using interrupt-
1596
+      // driven change detection, and already against a limit then no call to
1597
+      // the endstop_triggered method will be done and the movement will be
1598
+      // done against the endstop. So, check the limits here: If the movement
1599
+      // is against the limits, the block will be marked as to be killed, and
1600
+      // on the next call to this ISR, will be discarded.
1601
+      endstops.check_possible_change();
1602
+
1585 1603
       // No acceleration / deceleration time elapsed so far
1586 1604
       acceleration_time = deceleration_time = 0;
1587 1605
 
@@ -1614,11 +1632,6 @@ uint32_t Stepper::stepper_block_phase_isr() {
1614 1632
           counter_m[i] = -(current_block->mix_event_count[i] >> 1);
1615 1633
       #endif
1616 1634
 
1617
-      #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
1618
-        e_hit = 2; // Needed for the case an endstop is already triggered before the new move begins.
1619
-                   // No 'change' can be detected.
1620
-      #endif
1621
-
1622 1635
       #if ENABLED(Z_LATE_ENABLE)
1623 1636
         // If delayed Z enable, enable it now. This option will severely interfere with
1624 1637
         //  timing between pulses when chaining motion between blocks, and it could lead
@@ -1894,9 +1907,6 @@ void Stepper::init() {
1894 1907
     if (!E_ENABLE_ON) E4_ENABLE_WRITE(HIGH);
1895 1908
   #endif
1896 1909
 
1897
-  // Init endstops and pullups
1898
-  endstops.init();
1899
-
1900 1910
   #define _STEP_INIT(AXIS) AXIS ##_STEP_INIT
1901 1911
   #define _WRITE_STEP(AXIS, HIGHLOW) AXIS ##_STEP_WRITE(HIGHLOW)
1902 1912
   #define _DISABLE(AXIS) disable_## AXIS()
@@ -2034,29 +2044,14 @@ int32_t Stepper::position(const AxisEnum axis) {
2034 2044
   return v;
2035 2045
 }
2036 2046
 
2037
-void Stepper::quick_stop() {
2038
-  const bool was_enabled = STEPPER_ISR_ENABLED();
2039
-  DISABLE_STEPPER_DRIVER_INTERRUPT();
2040
-
2041
-  if (current_block) {
2042
-    step_events_completed = current_block->step_event_count;
2043
-    current_block = NULL;
2044
-  }
2045
-
2046
-  if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2047
-}
2048
-
2049
-void Stepper::kill_current_block() {
2050
-  const bool was_enabled = STEPPER_ISR_ENABLED();
2051
-  DISABLE_STEPPER_DRIVER_INTERRUPT();
2052
-
2053
-  if (current_block)
2054
-    step_events_completed = current_block->step_event_count;
2055
-
2056
-  if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2057
-}
2058
-
2047
+// Signal endstops were triggered - This function can be called from
2048
+// an ISR context  (Temperature, Stepper or limits ISR), so we must
2049
+// be very careful here. If the interrupt being preempted was the
2050
+// Stepper ISR (this CAN happen with the endstop limits ISR) then
2051
+// when the stepper ISR resumes, we must be very sure that the movement
2052
+// is properly cancelled
2059 2053
 void Stepper::endstop_triggered(const AxisEnum axis) {
2054
+
2060 2055
   const bool was_enabled = STEPPER_ISR_ENABLED();
2061 2056
   if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2062 2057
 
@@ -2074,14 +2069,7 @@ void Stepper::endstop_triggered(const AxisEnum axis) {
2074 2069
   #endif // !COREXY && !COREXZ && !COREYZ
2075 2070
 
2076 2071
   // Discard the rest of the move if there is a current block
2077
-  if (current_block) {
2078
-
2079
-    // Kill the current block being executed
2080
-    step_events_completed = current_block->step_event_count;
2081
-
2082
-    // Prep to get a new block after cleaning
2083
-    current_block = NULL;
2084
-  }
2072
+  quick_stop();
2085 2073
 
2086 2074
   if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2087 2075
 }

+ 12
- 6
Marlin/src/module/stepper.h View File

@@ -75,7 +75,10 @@ class Stepper {
75 75
 
76 76
   private:
77 77
 
78
-    static uint8_t last_direction_bits;        // The next stepping-bits to be output
78
+    static uint8_t last_direction_bits,           // The next stepping-bits to be output
79
+                   last_movement_extruder;        // Last movement extruder, as computed when the last movement was fetched from planner
80
+    static bool abort_current_block,              // Signals to the stepper that current block should be aborted
81
+                last_movement_non_null[NUM_AXIS]; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
79 82
 
80 83
     #if ENABLED(X_DUAL_ENDSTOPS)
81 84
       static bool locked_x_motor, locked_x2_motor;
@@ -189,13 +192,16 @@ class Stepper {
189 192
     static void wake_up();
190 193
 
191 194
     // Quickly stop all steppers
192
-    static void quick_stop();
195
+    FORCE_INLINE static void quick_stop() { abort_current_block = true; }
193 196
 
194 197
     // The direction of a single motor
195 198
     FORCE_INLINE static bool motor_direction(const AxisEnum axis) { return TEST(last_direction_bits, axis); }
196 199
 
197
-    // Kill current block
198
-    static void kill_current_block();
200
+    // The last movement direction was not null on the specified axis. Note that motor direction is not necessarily the same.
201
+    FORCE_INLINE static bool movement_non_null(const AxisEnum axis) { return last_movement_non_null[axis]; }
202
+
203
+    // The extruder associated to the last movement
204
+    FORCE_INLINE static uint8_t movement_extruder() { return last_movement_extruder; }
199 205
 
200 206
     // Handle a triggered endstop
201 207
     static void endstop_triggered(const AxisEnum axis);
@@ -249,7 +255,7 @@ class Stepper {
249 255
     FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate) {
250 256
       uint32_t timer;
251 257
 
252
-      NOMORE(step_rate, MAX_STEP_FREQUENCY);
258
+      NOMORE(step_rate, uint32_t(MAX_STEP_FREQUENCY));
253 259
 
254 260
       // TODO: HAL: tidy this up, use Conditionals_post.h
255 261
       #ifdef CPU_32_BIT
@@ -288,7 +294,7 @@ class Stepper {
288 294
         timer = uint32_t(HAL_STEPPER_TIMER_RATE) / step_rate;
289 295
         NOLESS(timer, min_time_per_step); // (STEP_DOUBLER_FREQUENCY * 2 kHz - this should never happen)
290 296
       #else
291
-        NOLESS(step_rate, F_CPU / 500000);
297
+        NOLESS(step_rate, uint32_t(F_CPU / 500000U));
292 298
         step_rate -= F_CPU / 500000; // Correct for minimal speed
293 299
         if (step_rate >= (8 * 256)) { // higher step rate
294 300
           uint8_t tmp_step_rate = (step_rate & 0x00FF);

+ 2
- 18
Marlin/src/module/temperature.cpp View File

@@ -41,10 +41,6 @@
41 41
   #include "stepper.h"
42 42
 #endif
43 43
 
44
-#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(PINS_DEBUGGING)
45
-  #include "endstops.h"
46
-#endif
47
-
48 44
 #include "printcounter.h"
49 45
 
50 46
 #if ENABLED(FILAMENT_WIDTH_SENSOR)
@@ -2247,20 +2243,8 @@ void Temperature::isr() {
2247 2243
     }
2248 2244
   #endif // BABYSTEPPING
2249 2245
 
2250
-  #if ENABLED(PINS_DEBUGGING)
2251
-    endstops.run_monitor();  // report changes in endstop status
2252
-  #endif
2253
-
2254
-  // Update endstops state, if enabled
2255
-  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
2256
-    extern volatile uint8_t e_hit;
2257
-    if (e_hit && ENDSTOPS_ENABLED) {
2258
-      endstops.update();
2259
-      e_hit--;
2260
-    }
2261
-  #else
2262
-    if (ENDSTOPS_ENABLED) endstops.update();
2263
-  #endif
2246
+  // Poll endstops state, if required
2247
+  endstops.poll();
2264 2248
 
2265 2249
   // Periodically call the planner timer
2266 2250
   planner.tick();

Loading…
Cancel
Save