Browse Source

Fix interrupt-based endstop detection

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

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

24
  * Endstop Interrupts
24
  * Endstop Interrupts
25
  *
25
  *
26
  * Without endstop interrupts the endstop pins must be polled continually in
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
  * With this feature endstops.update() is called only when we know that at
28
  * With this feature endstops.update() is called only when we know that at
29
  * least one endstop has changed state, saving valuable CPU cycles.
29
  * least one endstop has changed state, saving valuable CPU cycles.
30
  *
30
  *
40
 
40
 
41
 #include "../../core/macros.h"
41
 #include "../../core/macros.h"
42
 #include <stdint.h>
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
 // One ISR for all EXT-Interrupts
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
  * Patch for pins_arduino.h (...\Arduino\hardware\arduino\avr\variants\mega\pins_arduino.h)
49
  * Patch for pins_arduino.h (...\Arduino\hardware\arduino\avr\variants\mega\pins_arduino.h)
95
 
88
 
96
 // Handlers for pin change interrupts
89
 // Handlers for pin change interrupts
97
 #ifdef PCINT0_vect
90
 #ifdef PCINT0_vect
98
-  ISR(PCINT0_vect) { endstop_ISR_worker(); }
91
+  ISR(PCINT0_vect) { endstop_ISR(); }
99
 #endif
92
 #endif
100
 
93
 
101
 #ifdef PCINT1_vect
94
 #ifdef PCINT1_vect
102
-  ISR(PCINT1_vect) { endstop_ISR_worker(); }
95
+  ISR(PCINT1_vect) { endstop_ISR(); }
103
 #endif
96
 #endif
104
 
97
 
105
 #ifdef PCINT2_vect
98
 #ifdef PCINT2_vect
106
-  ISR(PCINT2_vect) { endstop_ISR_worker(); }
99
+  ISR(PCINT2_vect) { endstop_ISR(); }
107
 #endif
100
 #endif
108
 
101
 
109
 #ifdef PCINT3_vect
102
 #ifdef PCINT3_vect
110
-  ISR(PCINT3_vect) { endstop_ISR_worker(); }
103
+  ISR(PCINT3_vect) { endstop_ISR(); }
111
 #endif
104
 #endif
112
 
105
 
113
 void setup_endstop_interrupts( void ) {
106
 void setup_endstop_interrupts( void ) {

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

24
  * Endstop Interrupts
24
  * Endstop Interrupts
25
  *
25
  *
26
  * Without endstop interrupts the endstop pins must be polled continually in
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
  * With this feature endstops.update() is called only when we know that at
28
  * With this feature endstops.update() is called only when we know that at
29
  * least one endstop has changed state, saving valuable CPU cycles.
29
  * least one endstop has changed state, saving valuable CPU cycles.
30
  *
30
  *
37
 #ifndef _ENDSTOP_INTERRUPTS_H_
37
 #ifndef _ENDSTOP_INTERRUPTS_H_
38
 #define _ENDSTOP_INTERRUPTS_H_
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
 // One ISR for all EXT-Interrupts
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
  *  Endstop interrupts for Due based targets.
46
  *  Endstop interrupts for Due based targets.

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

24
  * Endstop Interrupts
24
  * Endstop Interrupts
25
  *
25
  *
26
  * Without endstop interrupts the endstop pins must be polled continually in
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
  * With this feature endstops.update() is called only when we know that at
28
  * With this feature endstops.update() is called only when we know that at
29
  * least one endstop has changed state, saving valuable CPU cycles.
29
  * least one endstop has changed state, saving valuable CPU cycles.
30
  *
30
  *
40
 //Currently this is untested and broken
40
 //Currently this is untested and broken
41
 #error "Please disable Endstop Interrupts LPC176x is currently an unsupported platform"
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
 // One ISR for all EXT-Interrupts
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
 void setup_endstop_interrupts(void) {
48
 void setup_endstop_interrupts(void) {
55
   #if HAS_X_MAX
49
   #if HAS_X_MAX

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

36
  * Endstop Interrupts
36
  * Endstop Interrupts
37
  *
37
  *
38
  * Without endstop interrupts the endstop pins must be polled continually in
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
  * With this feature endstops.update() is called only when we know that at
40
  * With this feature endstops.update() is called only when we know that at
41
  * least one endstop has changed state, saving valuable CPU cycles.
41
  * least one endstop has changed state, saving valuable CPU cycles.
42
  *
42
  *
49
 #ifndef _ENDSTOP_INTERRUPTS_H_
49
 #ifndef _ENDSTOP_INTERRUPTS_H_
50
 #define _ENDSTOP_INTERRUPTS_H_
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
 // One ISR for all EXT-Interrupts
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
 void setup_endstop_interrupts(void) {
57
 void setup_endstop_interrupts(void) {
64
   #if HAS_X_MAX
58
   #if HAS_X_MAX

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

24
 #ifndef _ENDSTOP_INTERRUPTS_H_
24
 #ifndef _ENDSTOP_INTERRUPTS_H_
25
 #define _ENDSTOP_INTERRUPTS_H_
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
 // One ISR for all EXT-Interrupts
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
 void setup_endstop_interrupts(void) {
32
 void setup_endstop_interrupts(void) {
39
   #if HAS_X_MAX
33
   #if HAS_X_MAX

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

26
 #ifndef _ENDSTOP_INTERRUPTS_H_
26
 #ifndef _ENDSTOP_INTERRUPTS_H_
27
 #define _ENDSTOP_INTERRUPTS_H_
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
 // One ISR for all EXT-Interrupts
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
 void setup_endstop_interrupts(void) {
34
 void setup_endstop_interrupts(void) {
41
   #if HAS_X_MAX
35
   #if HAS_X_MAX

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

24
  * Endstop Interrupts
24
  * Endstop Interrupts
25
  *
25
  *
26
  * Without endstop interrupts the endstop pins must be polled continually in
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
  * With this feature endstops.update() is called only when we know that at
28
  * With this feature endstops.update() is called only when we know that at
29
  * least one endstop has changed state, saving valuable CPU cycles.
29
  * least one endstop has changed state, saving valuable CPU cycles.
30
  *
30
  *
37
 #ifndef _ENDSTOP_INTERRUPTS_H_
37
 #ifndef _ENDSTOP_INTERRUPTS_H_
38
 #define _ENDSTOP_INTERRUPTS_H_
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
 // One ISR for all EXT-Interrupts
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
  *  Endstop interrupts for Due based targets.
46
  *  Endstop interrupts for Due based targets.

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

95
   #include "feature/I2CPositionEncoder.h"
95
   #include "feature/I2CPositionEncoder.h"
96
 #endif
96
 #endif
97
 
97
 
98
-#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
99
-  #include HAL_PATH(HAL, endstop_interrupts.h)
100
-#endif
101
-
102
 #if HAS_TRINAMIC
98
 #if HAS_TRINAMIC
103
   #include "feature/tmc_util.h"
99
   #include "feature/tmc_util.h"
104
 #endif
100
 #endif
748
 
744
 
749
   print_job_timer.init();   // Initial setup of print job timer
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
   #if HAS_SERVOS
751
   #if HAS_SERVOS
754
     servo_init();
752
     servo_init();
860
     i2c.onRequest(i2c_on_request);
858
     i2c.onRequest(i2c_on_request);
861
   #endif
859
   #endif
862
 
860
 
863
-  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
864
-    setup_endstop_interrupts();
865
-  #endif
866
-
867
   #if DO_SWITCH_EXTRUDER
861
   #if DO_SWITCH_EXTRUDER
868
     move_extruder_servo(0);  // Initialize extruder servo
862
     move_extruder_servo(0);  // Initialize extruder servo
869
   #endif
863
   #endif

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

32
 #include "../module/temperature.h"
32
 #include "../module/temperature.h"
33
 #include "../lcd/ultralcd.h"
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
 Endstops endstops;
48
 Endstops endstops;
39
 
49
 
40
 // public:
50
 // public:
41
 
51
 
42
 bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.load()
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
 #if HAS_BED_PROBE
57
 #if HAS_BED_PROBE
49
   volatile bool Endstops::z_probe_enabled = false;
58
   volatile bool Endstops::z_probe_enabled = false;
196
     #endif
205
     #endif
197
   #endif
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
 } // Endstops::init
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
 void Endstops::report_state() {
295
 void Endstops::report_state() {
202
   if (endstop_hit_bits) {
296
   if (endstop_hit_bits) {
203
     #if ENABLED(ULTRA_LCD)
297
     #if ENABLED(ULTRA_LCD)
300
   #endif
394
   #endif
301
 } // Endstops::M119
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
 #if ENABLED(X_DUAL_ENDSTOPS)
400
 #if ENABLED(X_DUAL_ENDSTOPS)
304
   void Endstops::test_dual_x_endstops(const EndstopEnum es1, const EndstopEnum es2) {
401
   void Endstops::test_dual_x_endstops(const EndstopEnum es1, const EndstopEnum es2) {
305
     const byte x_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for X, bit 1 for X2
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
       SBI(endstop_hit_bits, X_MIN);
404
       SBI(endstop_hit_bits, X_MIN);
308
       if (!stepper.performing_homing || (x_test == 0x3))  //if not performing home or if both endstops were trigged during homing...
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
 #endif
409
 #endif
313
 #if ENABLED(Y_DUAL_ENDSTOPS)
410
 #if ENABLED(Y_DUAL_ENDSTOPS)
314
   void Endstops::test_dual_y_endstops(const EndstopEnum es1, const EndstopEnum es2) {
411
   void Endstops::test_dual_y_endstops(const EndstopEnum es1, const EndstopEnum es2) {
315
     const byte y_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Y, bit 1 for Y2
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
       SBI(endstop_hit_bits, Y_MIN);
414
       SBI(endstop_hit_bits, Y_MIN);
318
       if (!stepper.performing_homing || (y_test == 0x3))  //if not performing home or if both endstops were trigged during homing...
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
 #endif
419
 #endif
323
 #if ENABLED(Z_DUAL_ENDSTOPS)
420
 #if ENABLED(Z_DUAL_ENDSTOPS)
324
   void Endstops::test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2) {
421
   void Endstops::test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2) {
325
     const byte z_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Z, bit 1 for Z2
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
       SBI(endstop_hit_bits, Z_MIN);
424
       SBI(endstop_hit_bits, Z_MIN);
328
       if (!stepper.performing_homing || (z_test == 0x3))  //if not performing home or if both endstops were trigged during homing...
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
 #endif
429
 #endif
333
 
430
 
334
-// Check endstops - Called from ISR!
431
+// Check endstops - Could be called from ISR!
335
 void Endstops::update() {
432
 void Endstops::update() {
336
 
433
 
337
   #define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
434
   #define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
358
     if (G38_move) {
455
     if (G38_move) {
359
       UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
456
       UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
360
       if (TEST_ENDSTOP(_ENDSTOP(Z, MIN_PROBE))) {
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
         G38_endstop_hit = true;
461
         G38_endstop_hit = true;
365
       }
462
       }
366
     }
463
     }
371
    */
468
    */
372
 
469
 
373
   #if IS_CORE
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
     #define D_(N) stepper.motor_direction(CORE_AXIS_##N)
472
     #define D_(N) stepper.motor_direction(CORE_AXIS_##N)
376
   #endif
473
   #endif
377
 
474
 
391
     #define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) X_CMP D_(2)) )
488
     #define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) X_CMP D_(2)) )
392
     #define X_AXIS_HEAD X_HEAD
489
     #define X_AXIS_HEAD X_HEAD
393
   #else
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
     #define X_AXIS_HEAD X_AXIS
492
     #define X_AXIS_HEAD X_AXIS
396
   #endif
493
   #endif
397
 
494
 
411
     #define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Y_CMP D_(2)) )
508
     #define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Y_CMP D_(2)) )
412
     #define Y_AXIS_HEAD Y_HEAD
509
     #define Y_AXIS_HEAD Y_HEAD
413
   #else
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
     #define Y_AXIS_HEAD Y_AXIS
512
     #define Y_AXIS_HEAD Y_AXIS
416
   #endif
513
   #endif
417
 
514
 
431
     #define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Z_CMP D_(2)) )
528
     #define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Z_CMP D_(2)) )
432
     #define Z_AXIS_HEAD Z_HEAD
529
     #define Z_AXIS_HEAD Z_HEAD
433
   #else
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
     #define Z_AXIS_HEAD Z_AXIS
532
     #define Z_AXIS_HEAD Z_AXIS
436
   #endif
533
   #endif
437
 
534
 
438
   // With Dual X, endstops are only checked in the homing direction for the active extruder
535
   // With Dual X, endstops are only checked in the homing direction for the active extruder
439
   #if ENABLED(DUAL_X_CARRIAGE)
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
     #define X_MIN_TEST ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
538
     #define X_MIN_TEST ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
442
     #define X_MAX_TEST ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
539
     #define X_MAX_TEST ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
443
   #else
540
   #else
448
   /**
545
   /**
449
    * Check and update endstops according to conditions
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
           #else
555
           #else
465
-            if (X_MIN_TEST) UPDATE_ENDSTOP(X, MIN);
556
+            COPY_BIT(current_endstop_bits, X_MIN, X2_MIN);
466
           #endif
557
           #endif
558
+          test_dual_x_endstops(X_MIN, X2_MIN);
559
+        #else
560
+          if (X_MIN_TEST) UPDATE_ENDSTOP(X, MIN);
467
         #endif
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
           #else
570
           #else
480
-            if (X_MAX_TEST) UPDATE_ENDSTOP(X, MAX);
571
+            COPY_BIT(current_endstop_bits, X_MAX, X2_MAX);
481
           #endif
572
           #endif
573
+          test_dual_x_endstops(X_MAX, X2_MAX);
574
+        #else
575
+          if (X_MAX_TEST) UPDATE_ENDSTOP(X, MAX);
482
         #endif
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
           #else
588
           #else
498
-            UPDATE_ENDSTOP(Y, MIN);
589
+            COPY_BIT(current_endstop_bits, Y_MIN, Y2_MIN);
499
           #endif
590
           #endif
591
+          test_dual_y_endstops(Y_MIN, Y2_MIN);
592
+        #else
593
+          UPDATE_ENDSTOP(Y, MIN);
500
         #endif
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
           #else
603
           #else
513
-            UPDATE_ENDSTOP(Y, MAX);
604
+            COPY_BIT(current_endstop_bits, Y_MAX, Y2_MAX);
514
           #endif
605
           #endif
606
+          test_dual_y_endstops(Y_MAX, Y2_MAX);
607
+        #else
608
+          UPDATE_ENDSTOP(Y, MAX);
515
         #endif
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
           #else
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
           #endif
630
           #endif
537
         #endif
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
           #endif
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
         #endif
657
         #endif
564
-      }
658
+      #endif
565
     }
659
     }
566
-
567
-  } // stepper.current_block
568
-
569
-  old_endstop_bits = current_endstop_bits;
570
-
660
+  }
571
 } // Endstops::update()
661
 } // Endstops::update()
572
 
662
 
573
 #if ENABLED(PINS_DEBUGGING)
663
 #if ENABLED(PINS_DEBUGGING)

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

51
   public:
51
   public:
52
 
52
 
53
     static bool enabled, enabled_globally;
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
     #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
56
     #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
57
       typedef uint16_t esbits_t;
57
       typedef uint16_t esbits_t;
68
       typedef byte esbits_t;
68
       typedef byte esbits_t;
69
     #endif
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
      * Initialize the endstop pins
76
      * Initialize the endstop pins
86
     static void init();
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
      * Update the endstops bits from the pins
92
      * Update the endstops bits from the pins
90
      */
93
      */
91
     static void update();
94
     static void update();
101
     static void M119();
104
     static void M119();
102
 
105
 
103
     // Enable / disable endstop checking globally
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
     // Enable / disable endstop checking
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
     // Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
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
     // Clear endstops (i.e., they were hit intentionally) to suppress the report
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
     // Enable / disable endstop z-probe checking
118
     // Enable / disable endstop z-probe checking
116
     #if HAS_BED_PROBE
119
     #if HAS_BED_PROBE
117
       static volatile bool z_probe_enabled;
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
     #endif
122
     #endif
120
 
123
 
121
     // Debugging of endstops
124
     // Debugging of endstops
122
     #if ENABLED(PINS_DEBUGGING)
125
     #if ENABLED(PINS_DEBUGGING)
123
       static bool monitor_flag;
126
       static bool monitor_flag;
124
       static void monitor();
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
     #endif
129
     #endif
133
 
130
 
134
   private:
131
   private:
146
 
143
 
147
 extern Endstops endstops;
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
 #endif // __ENDSTOPS_H__
146
 #endif // __ENDSTOPS_H__

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

758
            final_rate = CEIL(block->nominal_rate * exit_factor); // (steps per second)
758
            final_rate = CEIL(block->nominal_rate * exit_factor); // (steps per second)
759
 
759
 
760
   // Limit minimal step rate (Otherwise the timer will overflow.)
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
   #if ENABLED(BEZIER_JERK_CONTROL)
764
   #if ENABLED(BEZIER_JERK_CONTROL)
765
     uint32_t cruise_rate = initial_rate;
765
     uint32_t cruise_rate = initial_rate;
1467
 }
1467
 }
1468
 
1468
 
1469
 void Planner::endstop_triggered(const AxisEnum axis) {
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
   stepper.endstop_triggered(axis);
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
 float Planner::triggered_position_mm(const AxisEnum axis) {
1474
 float Planner::triggered_position_mm(const AxisEnum axis) {
1682
   if (de < 0) SBI(dm, E_AXIS);
1667
   if (de < 0) SBI(dm, E_AXIS);
1683
 
1668
 
1684
   const float esteps_float = de * e_factor[extruder];
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
   // Clear all flags, including the "busy" bit
1672
   // Clear all flags, including the "busy" bit
1688
   block->flag = 0x00;
1673
   block->flag = 0x00;

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

96
 
96
 
97
 // private:
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
 #if ENABLED(X_DUAL_ENDSTOPS)
104
 #if ENABLED(X_DUAL_ENDSTOPS)
102
   bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
105
   bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
181
   #define DUAL_ENDSTOP_APPLY_STEP(A,V)                                                                                                           \
184
   #define DUAL_ENDSTOP_APPLY_STEP(A,V)                                                                                                           \
182
     if (performing_homing) {                                                                                                                        \
185
     if (performing_homing) {                                                                                                                        \
183
       if (A##_HOME_DIR < 0) {                                                                                                                    \
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
       else {                                                                                                                                        \
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
     else {                                                                                                                                          \
195
     else {                                                                                                                                          \
315
   #endif // !LIN_ADVANCE
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
 #if ENABLED(BEZIER_JERK_CONTROL)
321
 #if ENABLED(BEZIER_JERK_CONTROL)
323
   /**
322
   /**
324
    *   We are using a quintic (fifth-degree) Bézier polynomial for the velocity curve.
323
    *   We are using a quintic (fifth-degree) Bézier polynomial for the velocity curve.
1229
 // as constant as possible!!!!
1228
 // as constant as possible!!!!
1230
 void Stepper::stepper_pulse_phase_isr() {
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
   // If there is no current block, do nothing
1240
   // If there is no current block, do nothing
1233
   if (!current_block) return;
1241
   if (!current_block) return;
1234
 
1242
 
1558
           return interval; // No more queued movements!
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
       #if ENABLED(LIN_ADVANCE)
1573
       #if ENABLED(LIN_ADVANCE)
1565
         #if E_STEPPERS > 1
1574
         #if E_STEPPERS > 1
1566
-          if (current_block->active_extruder != last_extruder) {
1575
+          if (current_block->active_extruder != last_movement_extruder) {
1567
             current_adv_steps = 0; // If the now active extruder wasn't in use during the last move, its pressure is most likely gone.
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
             LA_active_extruder = current_block->active_extruder;
1577
             LA_active_extruder = current_block->active_extruder;
1569
           }
1578
           }
1576
         }
1585
         }
1577
       #endif
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
         last_direction_bits = current_block->direction_bits;
1589
         last_direction_bits = current_block->direction_bits;
1581
-        last_extruder = current_block->active_extruder;
1590
+        last_movement_extruder = current_block->active_extruder;
1582
         set_directions();
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
       // No acceleration / deceleration time elapsed so far
1603
       // No acceleration / deceleration time elapsed so far
1586
       acceleration_time = deceleration_time = 0;
1604
       acceleration_time = deceleration_time = 0;
1587
 
1605
 
1614
           counter_m[i] = -(current_block->mix_event_count[i] >> 1);
1632
           counter_m[i] = -(current_block->mix_event_count[i] >> 1);
1615
       #endif
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
       #if ENABLED(Z_LATE_ENABLE)
1635
       #if ENABLED(Z_LATE_ENABLE)
1623
         // If delayed Z enable, enable it now. This option will severely interfere with
1636
         // If delayed Z enable, enable it now. This option will severely interfere with
1624
         //  timing between pulses when chaining motion between blocks, and it could lead
1637
         //  timing between pulses when chaining motion between blocks, and it could lead
1894
     if (!E_ENABLE_ON) E4_ENABLE_WRITE(HIGH);
1907
     if (!E_ENABLE_ON) E4_ENABLE_WRITE(HIGH);
1895
   #endif
1908
   #endif
1896
 
1909
 
1897
-  // Init endstops and pullups
1898
-  endstops.init();
1899
-
1900
   #define _STEP_INIT(AXIS) AXIS ##_STEP_INIT
1910
   #define _STEP_INIT(AXIS) AXIS ##_STEP_INIT
1901
   #define _WRITE_STEP(AXIS, HIGHLOW) AXIS ##_STEP_WRITE(HIGHLOW)
1911
   #define _WRITE_STEP(AXIS, HIGHLOW) AXIS ##_STEP_WRITE(HIGHLOW)
1902
   #define _DISABLE(AXIS) disable_## AXIS()
1912
   #define _DISABLE(AXIS) disable_## AXIS()
2034
   return v;
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
 void Stepper::endstop_triggered(const AxisEnum axis) {
2053
 void Stepper::endstop_triggered(const AxisEnum axis) {
2054
+
2060
   const bool was_enabled = STEPPER_ISR_ENABLED();
2055
   const bool was_enabled = STEPPER_ISR_ENABLED();
2061
   if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2056
   if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2062
 
2057
 
2074
   #endif // !COREXY && !COREXZ && !COREYZ
2069
   #endif // !COREXY && !COREXZ && !COREYZ
2075
 
2070
 
2076
   // Discard the rest of the move if there is a current block
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
   if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2074
   if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2087
 }
2075
 }

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

75
 
75
 
76
   private:
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
     #if ENABLED(X_DUAL_ENDSTOPS)
83
     #if ENABLED(X_DUAL_ENDSTOPS)
81
       static bool locked_x_motor, locked_x2_motor;
84
       static bool locked_x_motor, locked_x2_motor;
189
     static void wake_up();
192
     static void wake_up();
190
 
193
 
191
     // Quickly stop all steppers
194
     // Quickly stop all steppers
192
-    static void quick_stop();
195
+    FORCE_INLINE static void quick_stop() { abort_current_block = true; }
193
 
196
 
194
     // The direction of a single motor
197
     // The direction of a single motor
195
     FORCE_INLINE static bool motor_direction(const AxisEnum axis) { return TEST(last_direction_bits, axis); }
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
     // Handle a triggered endstop
206
     // Handle a triggered endstop
201
     static void endstop_triggered(const AxisEnum axis);
207
     static void endstop_triggered(const AxisEnum axis);
249
     FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate) {
255
     FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate) {
250
       uint32_t timer;
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
       // TODO: HAL: tidy this up, use Conditionals_post.h
260
       // TODO: HAL: tidy this up, use Conditionals_post.h
255
       #ifdef CPU_32_BIT
261
       #ifdef CPU_32_BIT
288
         timer = uint32_t(HAL_STEPPER_TIMER_RATE) / step_rate;
294
         timer = uint32_t(HAL_STEPPER_TIMER_RATE) / step_rate;
289
         NOLESS(timer, min_time_per_step); // (STEP_DOUBLER_FREQUENCY * 2 kHz - this should never happen)
295
         NOLESS(timer, min_time_per_step); // (STEP_DOUBLER_FREQUENCY * 2 kHz - this should never happen)
290
       #else
296
       #else
291
-        NOLESS(step_rate, F_CPU / 500000);
297
+        NOLESS(step_rate, uint32_t(F_CPU / 500000U));
292
         step_rate -= F_CPU / 500000; // Correct for minimal speed
298
         step_rate -= F_CPU / 500000; // Correct for minimal speed
293
         if (step_rate >= (8 * 256)) { // higher step rate
299
         if (step_rate >= (8 * 256)) { // higher step rate
294
           uint8_t tmp_step_rate = (step_rate & 0x00FF);
300
           uint8_t tmp_step_rate = (step_rate & 0x00FF);

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

41
   #include "stepper.h"
41
   #include "stepper.h"
42
 #endif
42
 #endif
43
 
43
 
44
-#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(PINS_DEBUGGING)
45
-  #include "endstops.h"
46
-#endif
47
-
48
 #include "printcounter.h"
44
 #include "printcounter.h"
49
 
45
 
50
 #if ENABLED(FILAMENT_WIDTH_SENSOR)
46
 #if ENABLED(FILAMENT_WIDTH_SENSOR)
2247
     }
2243
     }
2248
   #endif // BABYSTEPPING
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
   // Periodically call the planner timer
2249
   // Periodically call the planner timer
2266
   planner.tick();
2250
   planner.tick();

Loading…
Cancel
Save