浏览代码

Merge pull request #10688 from ejtagle/bugfix-2.0.x

[2.0.x] Refactor, optimization of core planner/stepper/endstops logic
Scott Lahteine 7 年前
父节点
当前提交
16f92dca44
没有帐户链接到提交者的电子邮件
共有 37 个文件被更改,包括 1666 次插入1141 次删除
  1. 142
    18
      Marlin/src/HAL/HAL_AVR/HAL.h
  2. 7
    14
      Marlin/src/HAL/HAL_AVR/endstop_interrupts.h
  3. 5
    0
      Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp
  4. 21
    6
      Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp
  5. 0
    2
      Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h
  6. 10
    0
      Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp
  7. 3
    9
      Marlin/src/HAL/HAL_DUE/endstop_interrupts.h
  8. 5
    0
      Marlin/src/HAL/HAL_DUE/watchdog_Due.cpp
  9. 13
    40
      Marlin/src/HAL/HAL_LPC1768/HAL_timers.cpp
  10. 78
    36
      Marlin/src/HAL/HAL_LPC1768/HAL_timers.h
  11. 24
    1
      Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.cpp
  12. 3
    9
      Marlin/src/HAL/HAL_LPC1768/endstop_interrupts.h
  13. 3
    9
      Marlin/src/HAL/HAL_STM32F1/endstop_interrupts.h
  14. 5
    0
      Marlin/src/HAL/HAL_STM32F4/HAL_timers_STM32F4.cpp
  15. 2
    8
      Marlin/src/HAL/HAL_STM32F4/endstop_interrupts.h
  16. 5
    0
      Marlin/src/HAL/HAL_STM32F7/HAL_timers_STM32F7.cpp
  17. 2
    8
      Marlin/src/HAL/HAL_STM32F7/endstop_interrupts.h
  18. 21
    0
      Marlin/src/HAL/HAL_TEENSY35_36/HAL_timers_Teensy.cpp
  19. 3
    9
      Marlin/src/HAL/HAL_TEENSY35_36/endstop_interrupts.h
  20. 4
    10
      Marlin/src/Marlin.cpp
  21. 0
    4
      Marlin/src/feature/Max7219_Debug_LEDs.cpp
  22. 6
    3
      Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp
  23. 1
    1
      Marlin/src/gcode/config/M540.cpp
  24. 1
    1
      Marlin/src/gcode/control/M17_M18_M84.cpp
  25. 1
    1
      Marlin/src/gcode/control/M80_M81.cpp
  26. 6
    3
      Marlin/src/gcode/motion/G2_G3.cpp
  27. 2
    4
      Marlin/src/lcd/ultralcd.cpp
  28. 210
    120
      Marlin/src/module/endstops.cpp
  29. 20
    29
      Marlin/src/module/endstops.h
  30. 12
    9
      Marlin/src/module/motion.cpp
  31. 475
    252
      Marlin/src/module/planner.cpp
  32. 185
    90
      Marlin/src/module/planner.h
  33. 4
    2
      Marlin/src/module/planner_bezier.cpp
  34. 328
    321
      Marlin/src/module/stepper.cpp
  35. 52
    102
      Marlin/src/module/stepper.h
  36. 6
    18
      Marlin/src/module/temperature.cpp
  37. 1
    2
      Marlin/src/sd/cardreader.cpp

+ 142
- 18
Marlin/src/HAL/HAL_AVR/HAL.h 查看文件

162
  * (otherwise, characters will be lost due to UART overflow).
162
  * (otherwise, characters will be lost due to UART overflow).
163
  * Then: Stepper, Endstops, Temperature, and -finally- all others.
163
  * Then: Stepper, Endstops, Temperature, and -finally- all others.
164
  */
164
  */
165
-#define HAL_timer_isr_prologue_0 do{ DISABLE_TEMPERATURE_INTERRUPT(); sei(); }while(0)
166
-#define HAL_timer_isr_epilogue_0 do{ cli(); ENABLE_TEMPERATURE_INTERRUPT(); }while(0)
167
-
168
-#define HAL_timer_isr_prologue_1 \
169
-  const bool temp_isr_was_enabled = TEMPERATURE_ISR_ENABLED(); \
170
-  do{ \
171
-    DISABLE_TEMPERATURE_INTERRUPT(); \
172
-    DISABLE_STEPPER_DRIVER_INTERRUPT(); \
173
-    sei(); \
174
-  }while(0)
175
-
176
-#define HAL_timer_isr_epilogue_1 do{ cli(); ENABLE_STEPPER_DRIVER_INTERRUPT(); if (temp_isr_was_enabled) ENABLE_TEMPERATURE_INTERRUPT(); }while(0)
177
-
178
-#define HAL_timer_isr_prologue(TIMER_NUM) _CAT(HAL_timer_isr_prologue_, TIMER_NUM)
179
-#define HAL_timer_isr_epilogue(TIMER_NUM) _CAT(HAL_timer_isr_epilogue_, TIMER_NUM)
180
-
181
-#define HAL_STEP_TIMER_ISR ISR(TIMER1_COMPA_vect)
182
-#define HAL_TEMP_TIMER_ISR ISR(TIMER0_COMPB_vect)
165
+#define HAL_timer_isr_prologue(TIMER_NUM)
166
+#define HAL_timer_isr_epilogue(TIMER_NUM)
167
+
168
+/* 18 cycles maximum latency */
169
+#define HAL_STEP_TIMER_ISR \
170
+extern "C" void TIMER1_COMPA_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
171
+extern "C" void TIMER1_COMPA_vect_bottom (void) asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
172
+void TIMER1_COMPA_vect (void) { \
173
+  __asm__ __volatile__ ( \
174
+    A("push r16")                      /* 2 Save R16 */ \
175
+    A("in r16, __SREG__")              /* 1 Get SREG */ \
176
+    A("push r16")                      /* 2 Save SREG into stack */ \
177
+    A("lds r16, %[timsk0]")            /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
178
+    A("push r16")                      /* 2 Save TIMSK0 into the stack */ \
179
+    A("andi r16,~%[msk0]")             /* 1 Disable the temperature ISR */ \
180
+    A("sts %[timsk0], r16")            /* 2 And set the new value */ \
181
+    A("lds r16, %[timsk1]")            /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
182
+    A("andi r16,~%[msk1]")             /* 1 Disable the stepper ISR */ \
183
+    A("sts %[timsk1], r16")            /* 2 And set the new value */ \
184
+    A("sei")                           /* 1 Enable global interrupts - stepper and temperature ISRs are disabled, so no risk of reentry or being preempted by the temperature ISR */    \
185
+    A("push r16")                      /* 2 Save TIMSK1 into stack */ \
186
+    A("in r16, 0x3B")                  /* 1 Get RAMPZ register */ \
187
+    A("push r16")                      /* 2 Save RAMPZ into stack */ \
188
+    A("in r16, 0x3C")                  /* 1 Get EIND register */ \
189
+    A("push r0")                       /* C runtime can modify all the following registers without restoring them */ \
190
+    A("push r1")                       \
191
+    A("push r18")                      \
192
+    A("push r19")                      \
193
+    A("push r20")                      \
194
+    A("push r21")                      \
195
+    A("push r22")                      \
196
+    A("push r23")                      \
197
+    A("push r24")                      \
198
+    A("push r25")                      \
199
+    A("push r26")                      \
200
+    A("push r27")                      \
201
+    A("push r30")                      \
202
+    A("push r31")                      \
203
+    A("clr r1")                        /* C runtime expects this register to be 0 */ \
204
+    A("call TIMER1_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */   \
205
+    A("pop r31")                       \
206
+    A("pop r30")                       \
207
+    A("pop r27")                       \
208
+    A("pop r26")                       \
209
+    A("pop r25")                       \
210
+    A("pop r24")                       \
211
+    A("pop r23")                       \
212
+    A("pop r22")                       \
213
+    A("pop r21")                       \
214
+    A("pop r20")                       \
215
+    A("pop r19")                       \
216
+    A("pop r18")                       \
217
+    A("pop r1")                        \
218
+    A("pop r0")                        \
219
+    A("out 0x3C, r16")                 /* 1 Restore EIND register */ \
220
+    A("pop r16")                       /* 2 Get the original RAMPZ register value */ \
221
+    A("out 0x3B, r16")                 /* 1 Restore RAMPZ register to its original value */ \
222
+    A("pop r16")                       /* 2 Get the original TIMSK1 value but with stepper ISR disabled */ \
223
+    A("ori r16,%[msk1]")               /* 1 Reenable the stepper ISR */ \
224
+    A("cli")                           /* 1 Disable global interrupts - Reenabling Stepper ISR can reenter amd temperature can reenter, and we want that, if it happens, after this ISR has ended */ \
225
+    A("sts %[timsk1], r16")            /* 2 And restore the old value - This reenables the stepper ISR */ \
226
+    A("pop r16")                       /* 2 Get the temperature timer Interrupt mask register [TIMSK0] */ \
227
+    A("sts %[timsk0], r16")            /* 2 And restore the old value - This reenables the temperature ISR */ \
228
+    A("pop r16")                       /* 2 Get the old SREG value */ \
229
+    A("out __SREG__, r16")             /* 1 And restore the SREG value */ \
230
+    A("pop r16")                       /* 2 Restore R16 value */ \
231
+    A("reti")                          /* 4 Return from interrupt */ \
232
+    :                                   \
233
+    : [timsk0] "i" ((uint16_t)&TIMSK0), \
234
+      [timsk1] "i" ((uint16_t)&TIMSK1), \
235
+      [msk0] "M" ((uint8_t)(1<<OCIE0B)),\
236
+      [msk1] "M" ((uint8_t)(1<<OCIE1A)) \
237
+    : \
238
+  ); \
239
+} \
240
+void TIMER1_COMPA_vect_bottom(void)
241
+
242
+/* 14 cycles maximum latency */
243
+#define HAL_TEMP_TIMER_ISR \
244
+extern "C" void TIMER0_COMPB_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
245
+extern "C" void TIMER0_COMPB_vect_bottom(void)  asm ("TIMER0_COMPB_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
246
+void TIMER0_COMPB_vect (void) { \
247
+  __asm__ __volatile__ ( \
248
+    A("push r16")                       /* 2 Save R16 */ \
249
+    A("in r16, __SREG__")               /* 1 Get SREG */ \
250
+    A("push r16")                       /* 2 Save SREG into stack */ \
251
+    A("lds r16, %[timsk0]")             /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
252
+    A("andi r16,~%[msk0]")              /* 1 Disable the temperature ISR */ \
253
+    A("sts %[timsk0], r16")             /* 2 And set the new value */ \
254
+    A("sei")                            /* 1 Enable global interrupts - It is safe, as the temperature ISR is disabled, so we cannot reenter it */    \
255
+    A("push r16")                       /* 2 Save TIMSK0 into stack */ \
256
+    A("in r16, 0x3B")                   /* 1 Get RAMPZ register */ \
257
+    A("push r16")                       /* 2 Save RAMPZ into stack */ \
258
+    A("in r16, 0x3C")                   /* 1 Get EIND register */ \
259
+    A("push r0")                        /* C runtime can modify all the following registers without restoring them */ \
260
+    A("push r1")                        \
261
+    A("push r18")                       \
262
+    A("push r19")                       \
263
+    A("push r20")                       \
264
+    A("push r21")                       \
265
+    A("push r22")                       \
266
+    A("push r23")                       \
267
+    A("push r24")                       \
268
+    A("push r25")                       \
269
+    A("push r26")                       \
270
+    A("push r27")                       \
271
+    A("push r30")                       \
272
+    A("push r31")                       \
273
+    A("clr r1")                         /* C runtime expects this register to be 0 */ \
274
+    A("call TIMER0_COMPB_vect_bottom")  /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */   \
275
+    A("pop r31")                        \
276
+    A("pop r30")                        \
277
+    A("pop r27")                        \
278
+    A("pop r26")                        \
279
+    A("pop r25")                        \
280
+    A("pop r24")                        \
281
+    A("pop r23")                        \
282
+    A("pop r22")                        \
283
+    A("pop r21")                        \
284
+    A("pop r20")                        \
285
+    A("pop r19")                        \
286
+    A("pop r18")                        \
287
+    A("pop r1")                         \
288
+    A("pop r0")                         \
289
+    A("out 0x3C, r16")                  /* 1 Restore EIND register */ \
290
+    A("pop r16")                        /* 2 Get the original RAMPZ register value */ \
291
+    A("out 0x3B, r16")                  /* 1 Restore RAMPZ register to its original value */ \
292
+    A("pop r16")                        /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
293
+    A("ori r16,%[msk0]")                /* 1 Enable temperature ISR */ \
294
+    A("cli")                            /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don´t want to reenter this handler until the current one is done */ \
295
+    A("sts %[timsk0], r16")             /* 2 And restore the old value */ \
296
+    A("pop r16")                        /* 2 Get the old SREG */ \
297
+    A("out __SREG__, r16")              /* 1 And restore the SREG value */ \
298
+    A("pop r16")                        /* 2 Restore R16 */ \
299
+    A("reti")                           /* 4 Return from interrupt */ \
300
+    :                                   \
301
+    : [timsk0] "i"((uint16_t)&TIMSK0),  \
302
+      [msk0] "M" ((uint8_t)(1<<OCIE0B)) \
303
+    : \
304
+  ); \
305
+} \
306
+void TIMER0_COMPB_vect_bottom(void)
183
 
307
 
184
 // ADC
308
 // ADC
185
 #ifdef DIDR2
309
 #ifdef DIDR2

+ 7
- 14
Marlin/src/HAL/HAL_AVR/endstop_interrupts.h 查看文件

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 ) {

+ 5
- 0
Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp 查看文件

46
   // Disable UART interrupt in NVIC
46
   // Disable UART interrupt in NVIC
47
   NVIC_DisableIRQ( UART_IRQn );
47
   NVIC_DisableIRQ( UART_IRQn );
48
 
48
 
49
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
50
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
51
+  __DSB();
52
+  __ISB();
53
+
49
   // Disable clock
54
   // Disable clock
50
   pmc_disable_periph_clk( ID_UART );
55
   pmc_disable_periph_clk( ID_UART );
51
 
56
 

+ 21
- 6
Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp 查看文件

99
   // Disable interrupt, just in case it was already enabled
99
   // Disable interrupt, just in case it was already enabled
100
   NVIC_DisableIRQ(irq);
100
   NVIC_DisableIRQ(irq);
101
 
101
 
102
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
103
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
104
+  __DSB();
105
+  __ISB();
106
+
102
   // Disable timer interrupt
107
   // Disable timer interrupt
103
   tc->TC_CHANNEL[channel].TC_IDR = TC_IDR_CPCS;
108
   tc->TC_CHANNEL[channel].TC_IDR = TC_IDR_CPCS;
104
 
109
 
126
 }
131
 }
127
 
132
 
128
 void HAL_timer_enable_interrupt(const uint8_t timer_num) {
133
 void HAL_timer_enable_interrupt(const uint8_t timer_num) {
129
-  const tTimerConfig * const pConfig = &TimerConfig[timer_num];
130
-  pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_IER = TC_IER_CPCS;
134
+  IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
135
+  NVIC_EnableIRQ(irq);
131
 }
136
 }
132
 
137
 
133
 void HAL_timer_disable_interrupt(const uint8_t timer_num) {
138
 void HAL_timer_disable_interrupt(const uint8_t timer_num) {
134
-  const tTimerConfig * const pConfig = &TimerConfig[timer_num];
135
-  pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_IDR = TC_IDR_CPCS;
139
+  IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
140
+  NVIC_DisableIRQ(irq);
141
+
142
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
143
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
144
+  __DSB();
145
+  __ISB();
146
+}
147
+
148
+// missing from CMSIS: Check if interrupt is enabled or not
149
+static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
150
+  return (NVIC->ISER[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) != 0;
136
 }
151
 }
137
 
152
 
138
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
153
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
139
-  const tTimerConfig * const pConfig = &TimerConfig[timer_num];
140
-  return (pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_IMR & TC_IMR_CPCS) != 0;
154
+  IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
155
+  return NVIC_GetEnabledIRQ(irq);
141
 }
156
 }
142
 
157
 
143
 #endif // ARDUINO_ARCH_SAM
158
 #endif // ARDUINO_ARCH_SAM

+ 0
- 2
Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h 查看文件

118
 void HAL_timer_disable_interrupt(const uint8_t timer_num);
118
 void HAL_timer_disable_interrupt(const uint8_t timer_num);
119
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
119
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
120
 
120
 
121
-//void HAL_timer_isr_prologue(const uint8_t timer_num);
122
-
123
 FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
121
 FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
124
   const tTimerConfig * const pConfig = &TimerConfig[timer_num];
122
   const tTimerConfig * const pConfig = &TimerConfig[timer_num];
125
   // Reading the status register clears the interrupt flag
123
   // Reading the status register clears the interrupt flag

+ 10
- 0
Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp 查看文件

245
     // Disable UART interrupt in NVIC
245
     // Disable UART interrupt in NVIC
246
     NVIC_DisableIRQ( HWUART_IRQ );
246
     NVIC_DisableIRQ( HWUART_IRQ );
247
 
247
 
248
+    // We NEED memory barriers to ensure Interrupts are actually disabled!
249
+    // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
250
+    __DSB();
251
+    __ISB();
252
+
248
     // Disable clock
253
     // Disable clock
249
     pmc_disable_periph_clk( HWUART_IRQ_ID );
254
     pmc_disable_periph_clk( HWUART_IRQ_ID );
250
 
255
 
290
     // Disable UART interrupt in NVIC
295
     // Disable UART interrupt in NVIC
291
     NVIC_DisableIRQ( HWUART_IRQ );
296
     NVIC_DisableIRQ( HWUART_IRQ );
292
 
297
 
298
+    // We NEED memory barriers to ensure Interrupts are actually disabled!
299
+    // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
300
+    __DSB();
301
+    __ISB();
302
+
293
     pmc_disable_periph_clk( HWUART_IRQ_ID );
303
     pmc_disable_periph_clk( HWUART_IRQ_ID );
294
   }
304
   }
295
 
305
 

+ 3
- 9
Marlin/src/HAL/HAL_DUE/endstop_interrupts.h 查看文件

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.

+ 5
- 0
Marlin/src/HAL/HAL_DUE/watchdog_Due.cpp 查看文件

68
       // Disable WDT interrupt (just in case, to avoid triggering it!)
68
       // Disable WDT interrupt (just in case, to avoid triggering it!)
69
       NVIC_DisableIRQ(WDT_IRQn);
69
       NVIC_DisableIRQ(WDT_IRQn);
70
 
70
 
71
+      // We NEED memory barriers to ensure Interrupts are actually disabled!
72
+      // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
73
+      __DSB();
74
+      __ISB();
75
+
71
       // Initialize WDT with the given parameters
76
       // Initialize WDT with the given parameters
72
       WDT_Enable(WDT, value);
77
       WDT_Enable(WDT, value);
73
 
78
 

+ 13
- 40
Marlin/src/HAL/HAL_LPC1768/HAL_timers.cpp 查看文件

23
 /**
23
 /**
24
  * Description:
24
  * Description:
25
  *
25
  *
26
- * For TARGET_LPC1768
26
+ * Timers for LPC1768
27
  */
27
  */
28
 
28
 
29
 #ifdef TARGET_LPC1768
29
 #ifdef TARGET_LPC1768
32
 #include "HAL_timers.h"
32
 #include "HAL_timers.h"
33
 
33
 
34
 void HAL_timer_init(void) {
34
 void HAL_timer_init(void) {
35
-  SBI(LPC_SC->PCONP, 1);  // power on timer0
35
+  SBI(LPC_SC->PCONP, SBIT_TIMER0);  // Power ON Timer 0
36
   LPC_TIM0->PR = (HAL_TIMER_RATE) / (HAL_STEPPER_TIMER_RATE) - 1; // Use prescaler to set frequency if needed
36
   LPC_TIM0->PR = (HAL_TIMER_RATE) / (HAL_STEPPER_TIMER_RATE) - 1; // Use prescaler to set frequency if needed
37
 
37
 
38
-  SBI(LPC_SC->PCONP, 2);  // power on timer1
38
+  SBI(LPC_SC->PCONP, SBIT_TIMER1);  // Power ON Timer 1
39
   LPC_TIM1->PR = (HAL_TIMER_RATE) / 1000000 - 1;
39
   LPC_TIM1->PR = (HAL_TIMER_RATE) / 1000000 - 1;
40
 }
40
 }
41
 
41
 
42
 void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
42
 void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
43
   switch (timer_num) {
43
   switch (timer_num) {
44
     case 0:
44
     case 0:
45
-      LPC_TIM0->MCR = 3;              // Match on MR0, reset on MR0
45
+      LPC_TIM0->MCR = _BV(SBIT_MR0I) | _BV(SBIT_MR0R); // Match on MR0, reset on MR0, interrupts when NVIC enables them
46
       LPC_TIM0->MR0 = uint32_t(HAL_STEPPER_TIMER_RATE) / frequency; // Match value (period) to set frequency
46
       LPC_TIM0->MR0 = uint32_t(HAL_STEPPER_TIMER_RATE) / frequency; // Match value (period) to set frequency
47
-      LPC_TIM0->TCR = _BV(0);       // enable
48
-      break;
49
-    case 1:
50
-      LPC_TIM1->MCR = 3;
51
-      LPC_TIM1->MR0 = uint32_t(HAL_TEMP_TIMER_RATE) / frequency;
52
-      LPC_TIM1->TCR = _BV(0);
53
-      break;
54
-    default: break;
55
-  }
56
-}
47
+      LPC_TIM0->TCR = _BV(SBIT_CNTEN); // Counter Enable
57
 
48
 
58
-void HAL_timer_enable_interrupt(const uint8_t timer_num) {
59
-  switch (timer_num) {
60
-    case 0:
61
-      NVIC_EnableIRQ(TIMER0_IRQn); // Enable interrupt handler
62
       NVIC_SetPriority(TIMER0_IRQn, NVIC_EncodePriority(0, 1, 0));
49
       NVIC_SetPriority(TIMER0_IRQn, NVIC_EncodePriority(0, 1, 0));
50
+      NVIC_EnableIRQ(TIMER0_IRQn);
63
       break;
51
       break;
52
+
64
     case 1:
53
     case 1:
65
-      NVIC_EnableIRQ(TIMER1_IRQn);
54
+      LPC_TIM1->MCR = _BV(SBIT_MR0I) | _BV(SBIT_MR0R); // Match on MR0, reset on MR0, interrupts when NVIC enables them
55
+      LPC_TIM1->MR0 = uint32_t(HAL_TEMP_TIMER_RATE) / frequency;
56
+      LPC_TIM1->TCR = _BV(SBIT_CNTEN); // Counter Enable
57
+
66
       NVIC_SetPriority(TIMER1_IRQn, NVIC_EncodePriority(0, 2, 0));
58
       NVIC_SetPriority(TIMER1_IRQn, NVIC_EncodePriority(0, 2, 0));
59
+      NVIC_EnableIRQ(TIMER1_IRQn);
67
       break;
60
       break;
68
-  }
69
-}
70
-
71
-void HAL_timer_disable_interrupt(const uint8_t timer_num) {
72
-  switch (timer_num) {
73
-    case 0: NVIC_DisableIRQ(TIMER0_IRQn); break; // disable interrupt handler
74
-    case 1: NVIC_DisableIRQ(TIMER1_IRQn); break;
75
-  }
76
-}
77
 
61
 
78
-bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
79
-  switch (timer_num) {
80
-    case 0: return NVIC_GetActive(TIMER0_IRQn);
81
-    case 1: return NVIC_GetActive(TIMER1_IRQn);
82
-  }
83
-  return false;
84
-}
85
-
86
-void HAL_timer_isr_prologue(const uint8_t timer_num) {
87
-  switch (timer_num) {
88
-    case 0: SBI(LPC_TIM0->IR, 0); break; // Clear the Interrupt
89
-    case 1: SBI(LPC_TIM1->IR, 0); break;
62
+    default: break;
90
   }
63
   }
91
 }
64
 }
92
 
65
 

+ 78
- 36
Marlin/src/HAL/HAL_LPC1768/HAL_timers.h 查看文件

34
 
34
 
35
 #include <stdint.h>
35
 #include <stdint.h>
36
 
36
 
37
+#include "../../core/macros.h"
38
+
39
+#define SBIT_TIMER0 1
40
+#define SBIT_TIMER1 2
41
+
42
+#define SBIT_CNTEN 0
43
+
44
+#define SBIT_MR0I  0 // Timer 0 Interrupt when TC matches MR0
45
+#define SBIT_MR0R  1 // Timer 0 Reset TC on Match
46
+#define SBIT_MR0S  2 // Timer 0 Stop TC and PC on Match
47
+#define SBIT_MR1I  3
48
+#define SBIT_MR1R  4
49
+#define SBIT_MR1S  5
50
+#define SBIT_MR2I  6
51
+#define SBIT_MR2R  7
52
+#define SBIT_MR2S  8
53
+#define SBIT_MR3I  9
54
+#define SBIT_MR3R 10
55
+#define SBIT_MR3S 11
56
+
37
 // --------------------------------------------------------------------------
57
 // --------------------------------------------------------------------------
38
 // Defines
58
 // Defines
39
 // --------------------------------------------------------------------------
59
 // --------------------------------------------------------------------------
40
 
60
 
41
-#define FORCE_INLINE __attribute__((always_inline)) inline
61
+#define _HAL_TIMER(T) _CAT(LPC_TIM, T)
62
+#define _HAL_TIMER_IRQ(T) TIMER##T##_IRQn
63
+#define __HAL_TIMER_ISR(T) extern "C" void TIMER##T##_IRQHandler(void)
64
+#define _HAL_TIMER_ISR(T)  __HAL_TIMER_ISR(T)
42
 
65
 
43
 typedef uint32_t hal_timer_t;
66
 typedef uint32_t hal_timer_t;
44
 #define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
67
 #define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
45
 
68
 
46
-#define STEP_TIMER_NUM 0  // index of timer to use for stepper
47
-#define TEMP_TIMER_NUM 1  // index of timer to use for temperature
69
+#define STEP_TIMER_NUM 0  // Timer Index for Stepper
70
+#define TEMP_TIMER_NUM 1  // Timer Index for Temperature
48
 #define PULSE_TIMER_NUM STEP_TIMER_NUM
71
 #define PULSE_TIMER_NUM STEP_TIMER_NUM
72
+#define PWM_TIMER_NUM 3   // Timer Index for PWM
49
 
73
 
50
 #define HAL_TIMER_RATE         ((SystemCoreClock) / 4)  // frequency of timers peripherals
74
 #define HAL_TIMER_RATE         ((SystemCoreClock) / 4)  // frequency of timers peripherals
51
 #define HAL_STEPPER_TIMER_RATE HAL_TIMER_RATE   // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
75
 #define HAL_STEPPER_TIMER_RATE HAL_TIMER_RATE   // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
66
 #define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
90
 #define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
67
 #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
91
 #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
68
 
92
 
69
-#define HAL_STEP_TIMER_ISR  extern "C" void TIMER0_IRQHandler(void)
70
-#define HAL_TEMP_TIMER_ISR  extern "C" void TIMER1_IRQHandler(void)
71
-
72
-// PWM timer
73
-#define HAL_PWM_TIMER      LPC_TIM3
74
-#define HAL_PWM_TIMER_ISR  extern "C" void TIMER3_IRQHandler(void)
75
-#define HAL_PWM_TIMER_IRQn TIMER3_IRQn
93
+#define HAL_STEP_TIMER_ISR _HAL_TIMER_ISR(STEP_TIMER_NUM)
94
+#define HAL_TEMP_TIMER_ISR _HAL_TIMER_ISR(TEMP_TIMER_NUM)
76
 
95
 
77
-// --------------------------------------------------------------------------
78
-// Types
79
-// --------------------------------------------------------------------------
80
-
81
-// --------------------------------------------------------------------------
82
-// Public Variables
83
-// --------------------------------------------------------------------------
96
+// Timer references by index
97
+#define STEP_TIMER _HAL_TIMER(STEP_TIMER_NUM)
98
+#define TEMP_TIMER _HAL_TIMER(TEMP_TIMER_NUM)
84
 
99
 
85
 // --------------------------------------------------------------------------
100
 // --------------------------------------------------------------------------
86
 // Public functions
101
 // Public functions
90
 
105
 
91
 FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
106
 FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
92
   switch (timer_num) {
107
   switch (timer_num) {
93
-    case 0:
94
-      LPC_TIM0->MR0 = compare;
95
-      if (LPC_TIM0->TC > compare)
96
-        LPC_TIM0->TC = compare - 5; // generate an immediate stepper ISR
97
-      break;
98
-    case 1:
99
-      LPC_TIM1->MR0 = compare;
100
-      if (LPC_TIM1->TC > compare)
101
-        LPC_TIM1->TC = compare - 5; // make sure we don't have one extra long period
102
-      break;
108
+    case 0: STEP_TIMER->MR0 = compare; break; // Stepper Timer Match Register 0
109
+    case 1: TEMP_TIMER->MR0 = compare; break; //    Temp Timer Match Register 0
103
   }
110
   }
104
 }
111
 }
105
 
112
 
106
 FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
113
 FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
107
   switch (timer_num) {
114
   switch (timer_num) {
108
-    case 0: return LPC_TIM0->MR0;
109
-    case 1: return LPC_TIM1->MR0;
115
+    case 0: return STEP_TIMER->MR0; // Stepper Timer Match Register 0
116
+    case 1: return TEMP_TIMER->MR0; //    Temp Timer Match Register 0
110
   }
117
   }
111
   return 0;
118
   return 0;
112
 }
119
 }
113
 
120
 
114
 FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
121
 FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
115
   switch (timer_num) {
122
   switch (timer_num) {
116
-    case 0: return LPC_TIM0->TC;
117
-    case 1: return LPC_TIM1->TC;
123
+    case 0: return STEP_TIMER->TC; // Stepper Timer Count
124
+    case 1: return TEMP_TIMER->TC; //    Temp Timer Count
118
   }
125
   }
119
   return 0;
126
   return 0;
120
 }
127
 }
124
   if (HAL_timer_get_compare(timer_num) < mincmp) HAL_timer_set_compare(timer_num, mincmp);
131
   if (HAL_timer_get_compare(timer_num) < mincmp) HAL_timer_set_compare(timer_num, mincmp);
125
 }
132
 }
126
 
133
 
127
-void HAL_timer_enable_interrupt(const uint8_t timer_num);
128
-void HAL_timer_disable_interrupt(const uint8_t timer_num);
129
-bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
130
-void HAL_timer_isr_prologue(const uint8_t timer_num);
134
+FORCE_INLINE static void HAL_timer_enable_interrupt(const uint8_t timer_num) {
135
+  switch (timer_num) {
136
+    case 0: NVIC_EnableIRQ(TIMER0_IRQn); // Enable interrupt handler
137
+    case 1: NVIC_EnableIRQ(TIMER1_IRQn); // Enable interrupt handler
138
+  }
139
+}
140
+
141
+FORCE_INLINE static void HAL_timer_disable_interrupt(const uint8_t timer_num) {
142
+  switch (timer_num) {
143
+    case 0: NVIC_DisableIRQ(TIMER0_IRQn); // Disable interrupt handler
144
+    case 1: NVIC_DisableIRQ(TIMER1_IRQn); // Disable interrupt handler
145
+  }
146
+
147
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
148
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
149
+  __DSB();
150
+  __ISB();
151
+}
152
+
153
+// This function is missing from CMSIS
154
+FORCE_INLINE static bool NVIC_GetEnableIRQ(IRQn_Type IRQn) {
155
+  return (NVIC->ISER[((uint32_t)IRQn) >> 5] & (1 << ((uint32_t)IRQn) & 0x1F)) != 0;
156
+}
157
+
158
+FORCE_INLINE static bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
159
+  switch (timer_num) {
160
+    case 0: return NVIC_GetEnableIRQ(TIMER0_IRQn); // Check if interrupt is enabled or not
161
+    case 1: return NVIC_GetEnableIRQ(TIMER1_IRQn); // Check if interrupt is enabled or not
162
+  }
163
+  return false;
164
+}
165
+
166
+FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
167
+  switch (timer_num) {
168
+    case 0: SBI(STEP_TIMER->IR, SBIT_CNTEN); break;
169
+    case 1: SBI(TEMP_TIMER->IR, SBIT_CNTEN); break;
170
+  }
171
+}
172
+
131
 #define HAL_timer_isr_epilogue(TIMER_NUM)
173
 #define HAL_timer_isr_epilogue(TIMER_NUM)
132
 
174
 
133
-#endif // _HAL_TIMERS_DUE_H
175
+#endif // _HAL_TIMERS_H

+ 24
- 1
Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.cpp 查看文件

78
 
78
 
79
 #define NUM_ISR_PWMS 20
79
 #define NUM_ISR_PWMS 20
80
 
80
 
81
+#define HAL_PWM_TIMER      LPC_TIM3
82
+#define HAL_PWM_TIMER_ISR  extern "C" void TIMER3_IRQHandler(void)
83
+#define HAL_PWM_TIMER_IRQn TIMER3_IRQn
81
 
84
 
82
 #define LPC_PORT_OFFSET         (0x0020)
85
 #define LPC_PORT_OFFSET         (0x0020)
83
 #define LPC_PIN(pin)            (1UL << pin)
86
 #define LPC_PIN(pin)            (1UL << pin)
84
 #define LPC_GPIO(port)          ((volatile LPC_GPIO_TypeDef *)(LPC_GPIO0_BASE + LPC_PORT_OFFSET * port))
87
 #define LPC_GPIO(port)          ((volatile LPC_GPIO_TypeDef *)(LPC_GPIO0_BASE + LPC_PORT_OFFSET * port))
85
 
88
 
86
-
87
 typedef struct {            // holds all data needed to control/init one of the PWM channels
89
 typedef struct {            // holds all data needed to control/init one of the PWM channels
88
   bool                active_flag;    // THIS TABLE ENTRY IS ACTIVELY TOGGLING A PIN
90
   bool                active_flag;    // THIS TABLE ENTRY IS ACTIVELY TOGGLING A PIN
89
   pin_t               pin;
91
   pin_t               pin;
256
                                  // OK to update the active table because the
258
                                  // OK to update the active table because the
257
                                  // ISR doesn't use any of the changed items
259
                                  // ISR doesn't use any of the changed items
258
 
260
 
261
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
262
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
263
+  __DSB();
264
+  __ISB();
265
+
259
   if (ISR_table_update) //use work table if that's the newest
266
   if (ISR_table_update) //use work table if that's the newest
260
     temp_table = work_table;
267
     temp_table = work_table;
261
   else
268
   else
340
 ////  interrupt controlled PWM code
347
 ////  interrupt controlled PWM code
341
   NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
348
   NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
342
 
349
 
350
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
351
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
352
+  __DSB();
353
+  __ISB();
354
+
343
   if (ISR_table_update) {
355
   if (ISR_table_update) {
344
     ISR_table_update = false;    // don't update yet - have another update to do
356
     ISR_table_update = false;    // don't update yet - have another update to do
345
     NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn);  // re-enable PWM interrupts
357
     NVIC_EnableIRQ(HAL_PWM_TIMER_IRQn);  // re-enable PWM interrupts
426
 
438
 
427
 ////  interrupt controlled PWM code
439
 ////  interrupt controlled PWM code
428
   NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
440
   NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
441
+
442
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
443
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
444
+  __DSB();
445
+  __ISB();
446
+
429
   if (!ISR_table_update)   // use the most up to date table
447
   if (!ISR_table_update)   // use the most up to date table
430
     COPY_ACTIVE_TABLE;  // copy active table into work table
448
     COPY_ACTIVE_TABLE;  // copy active table into work table
431
 
449
 
454
 
472
 
455
   NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
473
   NVIC_DisableIRQ(HAL_PWM_TIMER_IRQn);
456
 
474
 
475
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
476
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
477
+  __DSB();
478
+  __ISB();
479
+
457
   bool return_flag = false;
480
   bool return_flag = false;
458
   for (uint8_t i = 0; i < NUM_ISR_PWMS; i++)         // see if it's already setup
481
   for (uint8_t i = 0; i < NUM_ISR_PWMS; i++)         // see if it's already setup
459
     if (active_table[i].pin == pin) return_flag = true;
482
     if (active_table[i].pin == pin) return_flag = true;

+ 3
- 9
Marlin/src/HAL/HAL_LPC1768/endstop_interrupts.h 查看文件

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 查看文件

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

+ 5
- 0
Marlin/src/HAL/HAL_STM32F4/HAL_timers_STM32F4.cpp 查看文件

123
 
123
 
124
 void HAL_timer_disable_interrupt(const uint8_t timer_num) {
124
 void HAL_timer_disable_interrupt(const uint8_t timer_num) {
125
   HAL_NVIC_DisableIRQ(timerConfig[timer_num].IRQ_Id);
125
   HAL_NVIC_DisableIRQ(timerConfig[timer_num].IRQ_Id);
126
+
127
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
128
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
129
+  __DSB();
130
+  __ISB();
126
 }
131
 }
127
 
132
 
128
 hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
133
 hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {

+ 2
- 8
Marlin/src/HAL/HAL_STM32F4/endstop_interrupts.h 查看文件

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

+ 5
- 0
Marlin/src/HAL/HAL_STM32F7/HAL_timers_STM32F7.cpp 查看文件

127
 
127
 
128
 void HAL_timer_disable_interrupt(const uint8_t timer_num) {
128
 void HAL_timer_disable_interrupt(const uint8_t timer_num) {
129
   HAL_NVIC_DisableIRQ(timerConfig[timer_num].IRQ_Id);
129
   HAL_NVIC_DisableIRQ(timerConfig[timer_num].IRQ_Id);
130
+
131
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
132
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
133
+  __DSB();
134
+  __ISB();
130
 }
135
 }
131
 
136
 
132
 hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
137
 hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {

+ 2
- 8
Marlin/src/HAL/HAL_STM32F7/endstop_interrupts.h 查看文件

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

+ 21
- 0
Marlin/src/HAL/HAL_TEENSY35_36/HAL_timers_Teensy.cpp 查看文件

29
 #include "HAL.h"
29
 #include "HAL.h"
30
 #include "HAL_timers_Teensy.h"
30
 #include "HAL_timers_Teensy.h"
31
 
31
 
32
+/** \brief Instruction Synchronization Barrier
33
+  Instruction Synchronization Barrier flushes the pipeline in the processor,
34
+  so that all instructions following the ISB are fetched from cache or
35
+  memory, after the instruction has been completed.
36
+*/
37
+FORCE_INLINE static void __ISB(void) {
38
+  __asm__ __volatile__("isb 0xF":::"memory");
39
+}
40
+
41
+/** \brief Data Synchronization Barrier
42
+  This function acts as a special kind of Data Memory Barrier.
43
+  It completes when all explicit memory accesses before this instruction complete.
44
+*/
45
+FORCE_INLINE static void __DSB(void) {
46
+  __asm__ __volatile__("dsb 0xF":::"memory");
47
+}
32
 
48
 
33
 void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
49
 void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
34
   switch (timer_num) {
50
   switch (timer_num) {
65
     case 0: NVIC_DISABLE_IRQ(IRQ_FTM0); break;
81
     case 0: NVIC_DISABLE_IRQ(IRQ_FTM0); break;
66
     case 1: NVIC_DISABLE_IRQ(IRQ_FTM1); break;
82
     case 1: NVIC_DISABLE_IRQ(IRQ_FTM1); break;
67
   }
83
   }
84
+
85
+  // We NEED memory barriers to ensure Interrupts are actually disabled!
86
+  // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
87
+  __DSB();
88
+  __ISB();
68
 }
89
 }
69
 
90
 
70
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
91
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {

+ 3
- 9
Marlin/src/HAL/HAL_TEENSY35_36/endstop_interrupts.h 查看文件

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.

+ 4
- 10
Marlin/src/Marlin.cpp 查看文件

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
269
 }
265
 }
270
 
266
 
271
 void quickstop_stepper() {
267
 void quickstop_stepper() {
272
-  stepper.quick_stop();
268
+  planner.quick_stop();
273
   planner.synchronize();
269
   planner.synchronize();
274
   set_current_from_steppers_for_axis(ALL_AXES);
270
   set_current_from_steppers_for_axis(ALL_AXES);
275
   SYNC_PLAN_POSITION_KINEMATIC();
271
   SYNC_PLAN_POSITION_KINEMATIC();
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

+ 0
- 4
Marlin/src/feature/Max7219_Debug_LEDs.cpp 查看文件

73
 #endif
73
 #endif
74
 
74
 
75
 void Max7219_PutByte(uint8_t data) {
75
 void Max7219_PutByte(uint8_t data) {
76
-  CRITICAL_SECTION_START;
77
   for (uint8_t i = 8; i--;) {
76
   for (uint8_t i = 8; i--;) {
78
     SIG_DELAY();
77
     SIG_DELAY();
79
     WRITE(MAX7219_CLK_PIN, LOW);       // tick
78
     WRITE(MAX7219_CLK_PIN, LOW);       // tick
84
     SIG_DELAY();
83
     SIG_DELAY();
85
     data <<= 1;
84
     data <<= 1;
86
   }
85
   }
87
-  CRITICAL_SECTION_END;
88
 }
86
 }
89
 
87
 
90
 void Max7219(const uint8_t reg, const uint8_t data) {
88
 void Max7219(const uint8_t reg, const uint8_t data) {
91
   SIG_DELAY();
89
   SIG_DELAY();
92
-  CRITICAL_SECTION_START;
93
   WRITE(MAX7219_LOAD_PIN, LOW);  // begin
90
   WRITE(MAX7219_LOAD_PIN, LOW);  // begin
94
   SIG_DELAY();
91
   SIG_DELAY();
95
   Max7219_PutByte(reg);          // specify register
92
   Max7219_PutByte(reg);          // specify register
99
   WRITE(MAX7219_LOAD_PIN, LOW);  // and tell the chip to load the data
96
   WRITE(MAX7219_LOAD_PIN, LOW);  // and tell the chip to load the data
100
   SIG_DELAY();
97
   SIG_DELAY();
101
   WRITE(MAX7219_LOAD_PIN, HIGH);
98
   WRITE(MAX7219_LOAD_PIN, HIGH);
102
-  CRITICAL_SECTION_END;
103
   SIG_DELAY();
99
   SIG_DELAY();
104
 }
100
 }
105
 
101
 

+ 6
- 3
Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp 查看文件

262
             z_position = end[Z_AXIS];
262
             z_position = end[Z_AXIS];
263
           }
263
           }
264
 
264
 
265
-          planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder);
265
+          if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder))
266
+            break;
266
         } //else printf("FIRST MOVE PRUNED  ");
267
         } //else printf("FIRST MOVE PRUNED  ");
267
       }
268
       }
268
 
269
 
319
           e_position = end[E_AXIS];
320
           e_position = end[E_AXIS];
320
           z_position = end[Z_AXIS];
321
           z_position = end[Z_AXIS];
321
         }
322
         }
322
-        planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder);
323
+        if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder))
324
+          break;
323
         current_yi += dyi;
325
         current_yi += dyi;
324
         yi_cnt--;
326
         yi_cnt--;
325
       }
327
       }
342
           z_position = end[Z_AXIS];
344
           z_position = end[Z_AXIS];
343
         }
345
         }
344
 
346
 
345
-        planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder);
347
+        if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder))
348
+          break;
346
         current_xi += dxi;
349
         current_xi += dxi;
347
         xi_cnt--;
350
         xi_cnt--;
348
       }
351
       }

+ 1
- 1
Marlin/src/gcode/config/M540.cpp 查看文件

33
 void GcodeSuite::M540() {
33
 void GcodeSuite::M540() {
34
 
34
 
35
   if (parser.seen('S'))
35
   if (parser.seen('S'))
36
-    stepper.abort_on_endstop_hit = parser.value_bool();
36
+    planner.abort_on_endstop_hit = parser.value_bool();
37
 
37
 
38
 }
38
 }
39
 
39
 

+ 1
- 1
Marlin/src/gcode/control/M17_M18_M84.cpp 查看文件

47
   else {
47
   else {
48
     bool all_axis = !(parser.seen('X') || parser.seen('Y') || parser.seen('Z') || parser.seen('E'));
48
     bool all_axis = !(parser.seen('X') || parser.seen('Y') || parser.seen('Z') || parser.seen('E'));
49
     if (all_axis) {
49
     if (all_axis) {
50
-      stepper.finish_and_disable();
50
+      planner.finish_and_disable();
51
     }
51
     }
52
     else {
52
     else {
53
       planner.synchronize();
53
       planner.synchronize();

+ 1
- 1
Marlin/src/gcode/control/M80_M81.cpp 查看文件

95
  */
95
  */
96
 void GcodeSuite::M81() {
96
 void GcodeSuite::M81() {
97
   thermalManager.disable_all_heaters();
97
   thermalManager.disable_all_heaters();
98
-  stepper.finish_and_disable();
98
+  planner.finish_and_disable();
99
 
99
 
100
   #if FAN_COUNT > 0
100
   #if FAN_COUNT > 0
101
     for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0;
101
     for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0;

+ 6
- 3
Marlin/src/gcode/motion/G2_G3.cpp 查看文件

197
       // i.e., Complete the angular vector in the given time.
197
       // i.e., Complete the angular vector in the given time.
198
       inverse_kinematics(raw);
198
       inverse_kinematics(raw);
199
       ADJUST_DELTA(raw);
199
       ADJUST_DELTA(raw);
200
-      planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder);
200
+      if (!planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder))
201
+        break;
201
       oldA = delta[A_AXIS]; oldB = delta[B_AXIS];
202
       oldA = delta[A_AXIS]; oldB = delta[B_AXIS];
202
     #elif HAS_UBL_AND_CURVES
203
     #elif HAS_UBL_AND_CURVES
203
       float pos[XYZ] = { raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS] };
204
       float pos[XYZ] = { raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS] };
204
       planner.apply_leveling(pos);
205
       planner.apply_leveling(pos);
205
-      planner.buffer_segment(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], raw[E_AXIS], fr_mm_s, active_extruder);
206
+      if (!planner.buffer_segment(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], raw[E_AXIS], fr_mm_s, active_extruder))
207
+        break;
206
     #else
208
     #else
207
-      planner.buffer_line_kinematic(raw, fr_mm_s, active_extruder);
209
+      if (!planner.buffer_line_kinematic(raw, fr_mm_s, active_extruder))
210
+        break;
208
     #endif
211
     #endif
209
   }
212
   }
210
 
213
 

+ 2
- 4
Marlin/src/lcd/ultralcd.cpp 查看文件

2421
 
2421
 
2422
     void _lcd_do_nothing() {}
2422
     void _lcd_do_nothing() {}
2423
     void _lcd_hard_stop() {
2423
     void _lcd_hard_stop() {
2424
-      stepper.quick_stop();
2425
       const screenFunc_t old_screen = currentScreen;
2424
       const screenFunc_t old_screen = currentScreen;
2426
       currentScreen = _lcd_do_nothing;
2425
       currentScreen = _lcd_do_nothing;
2427
-      while (planner.movesplanned()) idle();
2426
+      planner.quick_stop();
2428
       currentScreen = old_screen;
2427
       currentScreen = old_screen;
2429
-      stepper.cleaning_buffer_counter = 0;
2430
       set_current_from_steppers_for_axis(ALL_AXES);
2428
       set_current_from_steppers_for_axis(ALL_AXES);
2431
       sync_plan_position();
2429
       sync_plan_position();
2432
     }
2430
     }
3856
 
3854
 
3857
     // M540 S - Abort on endstop hit when SD printing
3855
     // M540 S - Abort on endstop hit when SD printing
3858
     #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
3856
     #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
3859
-      MENU_ITEM_EDIT(bool, MSG_ENDSTOP_ABORT, &stepper.abort_on_endstop_hit);
3857
+      MENU_ITEM_EDIT(bool, MSG_ENDSTOP_ABORT, &planner.abort_on_endstop_hit);
3860
     #endif
3858
     #endif
3861
 
3859
 
3862
     END_MENU();
3860
     END_MENU();

+ 210
- 120
Marlin/src/module/endstops.cpp 查看文件

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)
208
     #endif
302
     #endif
209
 
303
 
210
     #define _ENDSTOP_HIT_ECHO(A,C) do{ \
304
     #define _ENDSTOP_HIT_ECHO(A,C) do{ \
211
-      SERIAL_ECHOPAIR(" " STRINGIFY(A) ":", stepper.triggered_position_mm(_AXIS(A))); \
305
+      SERIAL_ECHOPAIR(" " STRINGIFY(A) ":", planner.triggered_position_mm(_AXIS(A))); \
212
       _SET_STOP_CHAR(A,C); }while(0)
306
       _SET_STOP_CHAR(A,C); }while(0)
213
 
307
 
214
     #define _ENDSTOP_HIT_TEST(A,C) \
308
     #define _ENDSTOP_HIT_TEST(A,C) \
238
     hit_on_purpose();
332
     hit_on_purpose();
239
 
333
 
240
     #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) && ENABLED(SDSUPPORT)
334
     #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) && ENABLED(SDSUPPORT)
241
-      if (stepper.abort_on_endstop_hit) {
335
+      if (planner.abort_on_endstop_hit) {
242
         card.sdprinting = false;
336
         card.sdprinting = false;
243
         card.closefile();
337
         card.closefile();
244
         quickstop_stepper();
338
         quickstop_stepper();
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
349
       UPDATE_ENDSTOP_BIT(AXIS, MINMAX); \
446
       UPDATE_ENDSTOP_BIT(AXIS, MINMAX); \
350
       if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
447
       if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
351
         _ENDSTOP_HIT(AXIS, MINMAX); \
448
         _ENDSTOP_HIT(AXIS, MINMAX); \
352
-        stepper.endstop_triggered(_AXIS(AXIS)); \
449
+        planner.endstop_triggered(_AXIS(AXIS)); \
353
       } \
450
       } \
354
     }while(0)
451
     }while(0)
355
 
452
 
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); stepper.endstop_triggered(_AXIS(X)); }
362
-        else if (stepper.current_block->steps[_AXIS(Y)] > 0) { _ENDSTOP_HIT(Y, MIN); stepper.endstop_triggered(_AXIS(Y)); }
363
-        else if (stepper.current_block->steps[_AXIS(Z)] > 0) { _ENDSTOP_HIT(Z, MIN); stepper.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 查看文件

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__

+ 12
- 9
Marlin/src/module/motion.cpp 查看文件

644
       #if ENABLED(SCARA_FEEDRATE_SCALING)
644
       #if ENABLED(SCARA_FEEDRATE_SCALING)
645
         // For SCARA scale the feed rate from mm/s to degrees/s
645
         // For SCARA scale the feed rate from mm/s to degrees/s
646
         // i.e., Complete the angular vector in the given time.
646
         // i.e., Complete the angular vector in the given time.
647
-        planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder);
647
+        if (!planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder))
648
+          break;
648
         /*
649
         /*
649
         SERIAL_ECHO(segments);
650
         SERIAL_ECHO(segments);
650
         SERIAL_ECHOPAIR(": X=", raw[X_AXIS]); SERIAL_ECHOPAIR(" Y=", raw[Y_AXIS]);
651
         SERIAL_ECHOPAIR(": X=", raw[X_AXIS]); SERIAL_ECHOPAIR(" Y=", raw[Y_AXIS]);
654
         //*/
655
         //*/
655
         oldA = delta[A_AXIS]; oldB = delta[B_AXIS];
656
         oldA = delta[A_AXIS]; oldB = delta[B_AXIS];
656
       #else
657
       #else
657
-        planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], _feedrate_mm_s, active_extruder, cartesian_segment_mm);
658
+        if (!planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], _feedrate_mm_s, active_extruder, cartesian_segment_mm))
659
+          break;
658
       #endif
660
       #endif
659
     }
661
     }
660
 
662
 
746
           idle();
748
           idle();
747
         }
749
         }
748
         LOOP_XYZE(i) raw[i] += segment_distance[i];
750
         LOOP_XYZE(i) raw[i] += segment_distance[i];
749
-        planner.buffer_line_kinematic(raw, fr_mm_s, active_extruder, cartesian_segment_mm);
751
+        if (!planner.buffer_line_kinematic(raw, fr_mm_s, active_extruder, cartesian_segment_mm))
752
+          break;
750
       }
753
       }
751
 
754
 
752
       // Since segment_distance is only approximate,
755
       // Since segment_distance is only approximate,
848
           }
851
           }
849
           // unpark extruder: 1) raise, 2) move into starting XY position, 3) lower
852
           // unpark extruder: 1) raise, 2) move into starting XY position, 3) lower
850
           for (uint8_t i = 0; i < 3; i++)
853
           for (uint8_t i = 0; i < 3; i++)
851
-            planner.buffer_line(
854
+            if (!planner.buffer_line(
852
               i == 0 ? raised_parked_position[X_AXIS] : current_position[X_AXIS],
855
               i == 0 ? raised_parked_position[X_AXIS] : current_position[X_AXIS],
853
               i == 0 ? raised_parked_position[Y_AXIS] : current_position[Y_AXIS],
856
               i == 0 ? raised_parked_position[Y_AXIS] : current_position[Y_AXIS],
854
               i == 2 ? current_position[Z_AXIS] : raised_parked_position[Z_AXIS],
857
               i == 2 ? current_position[Z_AXIS] : raised_parked_position[Z_AXIS],
855
               current_position[E_AXIS],
858
               current_position[E_AXIS],
856
               i == 1 ? PLANNER_XY_FEEDRATE() : planner.max_feedrate_mm_s[Z_AXIS],
859
               i == 1 ? PLANNER_XY_FEEDRATE() : planner.max_feedrate_mm_s[Z_AXIS],
857
-              active_extruder
858
-            );
860
+              active_extruder)
861
+            ) break;
859
           delayed_move_time = 0;
862
           delayed_move_time = 0;
860
           active_extruder_parked = false;
863
           active_extruder_parked = false;
861
           #if ENABLED(DEBUG_LEVELING_FEATURE)
864
           #if ENABLED(DEBUG_LEVELING_FEATURE)
872
             #endif
875
             #endif
873
             // move duplicate extruder into correct duplication position.
876
             // move duplicate extruder into correct duplication position.
874
             planner.set_position_mm(inactive_extruder_x_pos, current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
877
             planner.set_position_mm(inactive_extruder_x_pos, current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
875
-            planner.buffer_line(
878
+            if (!planner.buffer_line(
876
               current_position[X_AXIS] + duplicate_extruder_x_offset,
879
               current_position[X_AXIS] + duplicate_extruder_x_offset,
877
               current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS],
880
               current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS],
878
-              planner.max_feedrate_mm_s[X_AXIS], 1
879
-            );
881
+              planner.max_feedrate_mm_s[X_AXIS], 1)
882
+            ) break;
880
             planner.synchronize();
883
             planner.synchronize();
881
             SYNC_PLAN_POSITION_KINEMATIC();
884
             SYNC_PLAN_POSITION_KINEMATIC();
882
             extruder_duplication_enabled = true;
885
             extruder_duplication_enabled = true;

+ 475
- 252
Marlin/src/module/planner.cpp
文件差异内容过多而无法显示
查看文件


+ 185
- 90
Marlin/src/module/planner.h 查看文件

35
 #include "../Marlin.h"
35
 #include "../Marlin.h"
36
 
36
 
37
 #include "motion.h"
37
 #include "motion.h"
38
+#include "../gcode/queue.h"
38
 
39
 
39
 #if ENABLED(DELTA)
40
 #if ENABLED(DELTA)
40
   #include "delta.h"
41
   #include "delta.h"
53
   // from a safe speed (in consideration of jerking from zero speed).
54
   // from a safe speed (in consideration of jerking from zero speed).
54
   BLOCK_BIT_NOMINAL_LENGTH,
55
   BLOCK_BIT_NOMINAL_LENGTH,
55
 
56
 
56
-  // The block is busy
57
+  // The block is busy, being interpreted by the stepper ISR
57
   BLOCK_BIT_BUSY,
58
   BLOCK_BIT_BUSY,
58
 
59
 
59
   // The block is segment 2+ of a longer move
60
   // The block is segment 2+ of a longer move
84
 
85
 
85
   uint8_t flag;                             // Block flags (See BlockFlag enum above)
86
   uint8_t flag;                             // Block flags (See BlockFlag enum above)
86
 
87
 
87
-  unsigned char active_extruder;            // The extruder to move (if E move)
88
+  // Fields used by the motion planner to manage acceleration
89
+  float nominal_speed_sqr,                  // The nominal speed for this block in (mm/sec)^2
90
+        entry_speed_sqr,                    // Entry speed at previous-current junction in (mm/sec)^2
91
+        max_entry_speed_sqr,                // Maximum allowable junction entry speed in (mm/sec)^2
92
+        millimeters,                        // The total travel of this block in mm
93
+        acceleration;                       // acceleration mm/sec^2
88
 
94
 
89
-  // Fields used by the Bresenham algorithm for tracing the line
90
-  int32_t steps[NUM_AXIS];                  // Step count along each axis
95
+  union {
96
+    // Data used by all move blocks
97
+    struct {
98
+      // Fields used by the Bresenham algorithm for tracing the line
99
+      uint32_t steps[NUM_AXIS];             // Step count along each axis
100
+    };
101
+    // Data used by all sync blocks
102
+    struct {
103
+      int32_t position[NUM_AXIS];           // New position to force when this sync block is executed
104
+    };
105
+  };
91
   uint32_t step_event_count;                // The number of step events required to complete this block
106
   uint32_t step_event_count;                // The number of step events required to complete this block
92
 
107
 
108
+  uint8_t active_extruder;                  // The extruder to move (if E move)
109
+
93
   #if ENABLED(MIXING_EXTRUDER)
110
   #if ENABLED(MIXING_EXTRUDER)
94
     uint32_t mix_event_count[MIXING_STEPPERS]; // Scaled step_event_count for the mixing steppers
111
     uint32_t mix_event_count[MIXING_STEPPERS]; // Scaled step_event_count for the mixing steppers
95
   #endif
112
   #endif
96
 
113
 
97
   // Settings for the trapezoid generator
114
   // Settings for the trapezoid generator
98
-  int32_t accelerate_until,                 // The index of the step event on which to stop acceleration
99
-          decelerate_after;                 // The index of the step event on which to start decelerating
115
+  uint32_t accelerate_until,                // The index of the step event on which to stop acceleration
116
+           decelerate_after;                // The index of the step event on which to start decelerating
100
 
117
 
101
   #if ENABLED(BEZIER_JERK_CONTROL)
118
   #if ENABLED(BEZIER_JERK_CONTROL)
102
     uint32_t cruise_rate;                   // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
119
     uint32_t cruise_rate;                   // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
105
     uint32_t acceleration_time_inverse,     // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used
122
     uint32_t acceleration_time_inverse,     // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used
106
              deceleration_time_inverse;
123
              deceleration_time_inverse;
107
   #else
124
   #else
108
-    int32_t acceleration_rate;              // The acceleration rate used for acceleration calculation
125
+    uint32_t acceleration_rate;             // The acceleration rate used for acceleration calculation
109
   #endif
126
   #endif
110
 
127
 
111
   uint8_t direction_bits;                   // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
128
   uint8_t direction_bits;                   // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
119
     float e_D_ratio;
136
     float e_D_ratio;
120
   #endif
137
   #endif
121
 
138
 
122
-  // Fields used by the motion planner to manage acceleration
123
-  float nominal_speed,                      // The nominal speed for this block in mm/sec
124
-        entry_speed,                        // Entry speed at previous-current junction in mm/sec
125
-        max_entry_speed,                    // Maximum allowable junction entry speed in mm/sec
126
-        millimeters,                        // The total travel of this block in mm
127
-        acceleration;                       // acceleration mm/sec^2
128
-
129
   uint32_t nominal_rate,                    // The nominal step rate for this block in step_events/sec
139
   uint32_t nominal_rate,                    // The nominal step rate for this block in step_events/sec
130
            initial_rate,                    // The jerk-adjusted step rate at start of block
140
            initial_rate,                    // The jerk-adjusted step rate at start of block
131
            final_rate,                      // The minimal rate at exit
141
            final_rate,                      // The minimal rate at exit
166
     static block_t block_buffer[BLOCK_BUFFER_SIZE];
176
     static block_t block_buffer[BLOCK_BUFFER_SIZE];
167
     static volatile uint8_t block_buffer_head,      // Index of the next block to be pushed
177
     static volatile uint8_t block_buffer_head,      // Index of the next block to be pushed
168
                             block_buffer_tail;      // Index of the busy block, if any
178
                             block_buffer_tail;      // Index of the busy block, if any
179
+    static uint16_t cleaning_buffer_counter;        // A counter to disable queuing of blocks
180
+    static uint8_t delay_before_delivering,         // This counter delays delivery of blocks when queue becomes empty to allow the opportunity of merging blocks
181
+                   block_buffer_planned;            // Index of the optimally planned block
182
+                   
169
 
183
 
170
     #if ENABLED(DISTINCT_E_FACTORS)
184
     #if ENABLED(DISTINCT_E_FACTORS)
171
       static uint8_t last_extruder;                 // Respond to extruder change
185
       static uint8_t last_extruder;                 // Respond to extruder change
233
       #endif
247
       #endif
234
     #endif
248
     #endif
235
 
249
 
250
+    #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
251
+      static bool abort_on_endstop_hit;
252
+    #endif
253
+
236
   private:
254
   private:
237
 
255
 
238
     /**
256
     /**
247
     static float previous_speed[NUM_AXIS];
265
     static float previous_speed[NUM_AXIS];
248
 
266
 
249
     /**
267
     /**
250
-     * Nominal speed of previous path line segment
268
+     * Nominal speed of previous path line segment (mm/s)^2
251
      */
269
      */
252
-    static float previous_nominal_speed;
270
+    static float previous_nominal_speed_sqr;
253
 
271
 
254
     /**
272
     /**
255
      * Limit where 64bit math is necessary for acceleration calculation
273
      * Limit where 64bit math is necessary for acceleration calculation
308
     // Manage fans, paste pressure, etc.
326
     // Manage fans, paste pressure, etc.
309
     static void check_axes_activity();
327
     static void check_axes_activity();
310
 
328
 
311
-    /**
312
-     * Number of moves currently in the planner
313
-     */
314
-    FORCE_INLINE static uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail + BLOCK_BUFFER_SIZE); }
315
-
316
-    FORCE_INLINE static void clear_block_buffer() { block_buffer_head = block_buffer_tail = 0; }
317
-
318
-    FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); }
319
-
320
     // Update multipliers based on new diameter measurements
329
     // Update multipliers based on new diameter measurements
321
     static void calculate_volumetric_multipliers();
330
     static void calculate_volumetric_multipliers();
322
 
331
 
424
       #define ARG_Z const float &rz
433
       #define ARG_Z const float &rz
425
     #endif
434
     #endif
426
 
435
 
436
+    // Number of moves currently in the planner
437
+    FORCE_INLINE static uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail); }
438
+
439
+    // Remove all blocks from the buffer
440
+    FORCE_INLINE static void clear_block_buffer() { block_buffer_head = block_buffer_tail = 0; }
441
+
442
+    // Check if movement queue is full
443
+    FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); }
444
+
445
+    // Get count of movement slots free
446
+    FORCE_INLINE static uint8_t moves_free() { return BLOCK_BUFFER_SIZE - 1 - movesplanned(); }
447
+
427
     /**
448
     /**
428
      * Planner::get_next_free_block
449
      * Planner::get_next_free_block
429
      *
450
      *
430
-     * - Get the next head index (passed by reference)
431
-     * - Wait for a space to open up in the planner
432
-     * - Return the head block
451
+     * - Get the next head indices (passed by reference)
452
+     * - Wait for the number of spaces to open up in the planner
453
+     * - Return the first head block
433
      */
454
      */
434
-    FORCE_INLINE static block_t* get_next_free_block(uint8_t &next_buffer_head) {
455
+    FORCE_INLINE static block_t* get_next_free_block(uint8_t &next_buffer_head, uint8_t count = 1) {
456
+
457
+      // Wait until there are enough slots free
458
+      while (moves_free() < count) { idle(); }
459
+
460
+      // Return the first available block
435
       next_buffer_head = next_block_index(block_buffer_head);
461
       next_buffer_head = next_block_index(block_buffer_head);
436
-      while (block_buffer_tail == next_buffer_head) idle(); // while (is_full)
437
       return &block_buffer[block_buffer_head];
462
       return &block_buffer[block_buffer_head];
438
     }
463
     }
439
 
464
 
446
      *  fr_mm_s     - (target) speed of the move
471
      *  fr_mm_s     - (target) speed of the move
447
      *  extruder    - target extruder
472
      *  extruder    - target extruder
448
      *  millimeters - the length of the movement, if known
473
      *  millimeters - the length of the movement, if known
474
+     *
475
+     * Returns true if movement was buffered, false otherwise
449
      */
476
      */
450
-    static void _buffer_steps(const int32_t (&target)[XYZE]
477
+    static bool _buffer_steps(const int32_t (&target)[XYZE]
478
+      #if HAS_POSITION_FLOAT
479
+        , const float (&target_float)[XYZE]
480
+      #endif
481
+      , float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
482
+    );
483
+
484
+    /**
485
+     * Planner::_populate_block
486
+     *
487
+     * Fills a new linear movement in the block (in terms of steps).
488
+     *
489
+     *  target      - target position in steps units
490
+     *  fr_mm_s     - (target) speed of the move
491
+     *  extruder    - target extruder
492
+     *  millimeters - the length of the movement, if known
493
+     *
494
+     * Returns true is movement is acceptable, false otherwise
495
+     */
496
+    static bool _populate_block(block_t * const block, bool split_move,
497
+        const int32_t (&target)[XYZE]
451
       #if HAS_POSITION_FLOAT
498
       #if HAS_POSITION_FLOAT
452
         , const float (&target_float)[XYZE]
499
         , const float (&target_float)[XYZE]
453
       #endif
500
       #endif
472
      *  extruder    - target extruder
519
      *  extruder    - target extruder
473
      *  millimeters - the length of the movement, if known
520
      *  millimeters - the length of the movement, if known
474
      */
521
      */
475
-    static void buffer_segment(const float &a, const float &b, const float &c, const float &e, const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0);
522
+    static bool buffer_segment(const float &a, const float &b, const float &c, const float &e, const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0);
476
 
523
 
477
     static void _set_position_mm(const float &a, const float &b, const float &c, const float &e);
524
     static void _set_position_mm(const float &a, const float &b, const float &c, const float &e);
478
 
525
 
489
      *  extruder     - target extruder
536
      *  extruder     - target extruder
490
      *  millimeters  - the length of the movement, if known
537
      *  millimeters  - the length of the movement, if known
491
      */
538
      */
492
-    FORCE_INLINE static void buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
539
+    FORCE_INLINE static bool buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
493
       #if PLANNER_LEVELING && IS_CARTESIAN
540
       #if PLANNER_LEVELING && IS_CARTESIAN
494
         apply_leveling(rx, ry, rz);
541
         apply_leveling(rx, ry, rz);
495
       #endif
542
       #endif
496
-      buffer_segment(rx, ry, rz, e, fr_mm_s, extruder, millimeters);
543
+      return buffer_segment(rx, ry, rz, e, fr_mm_s, extruder, millimeters);
497
     }
544
     }
498
 
545
 
499
     /**
546
     /**
506
      *  extruder     - target extruder
553
      *  extruder     - target extruder
507
      *  millimeters  - the length of the movement, if known
554
      *  millimeters  - the length of the movement, if known
508
      */
555
      */
509
-    FORCE_INLINE static void buffer_line_kinematic(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
556
+    FORCE_INLINE static bool buffer_line_kinematic(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
510
       #if PLANNER_LEVELING
557
       #if PLANNER_LEVELING
511
         float raw[XYZ] = { cart[X_AXIS], cart[Y_AXIS], cart[Z_AXIS] };
558
         float raw[XYZ] = { cart[X_AXIS], cart[Y_AXIS], cart[Z_AXIS] };
512
         apply_leveling(raw);
559
         apply_leveling(raw);
515
       #endif
562
       #endif
516
       #if IS_KINEMATIC
563
       #if IS_KINEMATIC
517
         inverse_kinematics(raw);
564
         inverse_kinematics(raw);
518
-        buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], cart[E_AXIS], fr_mm_s, extruder, millimeters);
565
+        return buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], cart[E_AXIS], fr_mm_s, extruder, millimeters);
519
       #else
566
       #else
520
-        buffer_segment(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], cart[E_AXIS], fr_mm_s, extruder, millimeters);
567
+        return buffer_segment(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], cart[E_AXIS], fr_mm_s, extruder, millimeters);
521
       #endif
568
       #endif
522
     }
569
     }
523
 
570
 
542
     FORCE_INLINE static void set_e_position_mm(const float &e) { set_position_mm(E_AXIS, e); }
589
     FORCE_INLINE static void set_e_position_mm(const float &e) { set_position_mm(E_AXIS, e); }
543
 
590
 
544
     /**
591
     /**
545
-     * Sync from the stepper positions. (e.g., after an interrupted move)
546
-     */
547
-    static void sync_from_steppers();
548
-
549
-    /**
550
      * Get an axis position according to stepper position(s)
592
      * Get an axis position according to stepper position(s)
551
      * For CORE machines apply translation from ABC to XYZ.
593
      * For CORE machines apply translation from ABC to XYZ.
552
      */
594
      */
557
       FORCE_INLINE static float get_axis_position_degrees(const AxisEnum axis) { return get_axis_position_mm(axis); }
599
       FORCE_INLINE static float get_axis_position_degrees(const AxisEnum axis) { return get_axis_position_mm(axis); }
558
     #endif
600
     #endif
559
 
601
 
560
-    /**
561
-     * Does the buffer have any blocks queued?
562
-     */
563
-    FORCE_INLINE static bool has_blocks_queued() { return (block_buffer_head != block_buffer_tail); }
602
+    // Called to force a quick stop of the machine (for example, when an emergency
603
+    // stop is required, or when endstops are hit)
604
+    static void quick_stop();
605
+
606
+    // Called when an endstop is triggered. Causes the machine to stop inmediately
607
+    static void endstop_triggered(const AxisEnum axis);
564
 
608
 
565
-    //
566
-    // Block until all buffered steps are executed
567
-    //
609
+    // Triggered position of an axis in mm (not core-savvy)
610
+    static float triggered_position_mm(const AxisEnum axis);
611
+
612
+    // Block until all buffered steps are executed / cleaned
568
     static void synchronize();
613
     static void synchronize();
569
 
614
 
570
-    /**
571
-     * "Discard" the block and "release" the memory.
572
-     * Called when the current block is no longer needed.
573
-     */
574
-    FORCE_INLINE static void discard_current_block() {
575
-      if (has_blocks_queued())
576
-        block_buffer_tail = BLOCK_MOD(block_buffer_tail + 1);
615
+    // Wait for moves to finish and disable all steppers
616
+    static void finish_and_disable();
617
+
618
+    // Periodic tick to handle cleaning timeouts
619
+    // Called from the Temperature ISR at ~1kHz
620
+    static void tick() {
621
+      if (cleaning_buffer_counter) {
622
+        --cleaning_buffer_counter;
623
+        #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
624
+          if (!cleaning_buffer_counter) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
625
+        #endif
626
+      }
577
     }
627
     }
578
 
628
 
579
     /**
629
     /**
580
-     * "Discard" the next block if it's continued.
581
-     * Called after an interrupted move to throw away the rest of the move.
630
+     * Does the buffer have any blocks queued?
582
      */
631
      */
583
-    FORCE_INLINE static bool discard_continued_block() {
584
-      const bool discard = has_blocks_queued() && TEST(block_buffer[block_buffer_tail].flag, BLOCK_BIT_CONTINUED);
585
-      if (discard) discard_current_block();
586
-      return discard;
587
-    }
632
+    FORCE_INLINE static bool has_blocks_queued() { return (block_buffer_head != block_buffer_tail); }
588
 
633
 
589
     /**
634
     /**
590
      * The current block. NULL if the buffer is empty.
635
      * The current block. NULL if the buffer is empty.
592
      * WARNING: Called from Stepper ISR context!
637
      * WARNING: Called from Stepper ISR context!
593
      */
638
      */
594
     static block_t* get_current_block() {
639
     static block_t* get_current_block() {
595
-      if (has_blocks_queued()) {
596
-        block_t * const block = &block_buffer[block_buffer_tail];
597
 
640
 
598
-        // If the block has no trapezoid calculated, it's unsafe to execute.
599
-        if (movesplanned() > 1) {
600
-          const block_t * const next = &block_buffer[next_block_index(block_buffer_tail)];
601
-          if (TEST(block->flag, BLOCK_BIT_RECALCULATE) || TEST(next->flag, BLOCK_BIT_RECALCULATE))
602
-            return NULL;
641
+      // Get the number of moves in the planner queue so far
642
+      uint8_t nr_moves = movesplanned();
643
+
644
+      // If there are any moves queued ...
645
+      if (nr_moves) {
646
+
647
+        // If there is still delay of delivery of blocks running, decrement it
648
+        if (delay_before_delivering) {
649
+          --delay_before_delivering;
650
+          // If the number of movements queued is less than 3, and there is still time
651
+          //  to wait, do not deliver anything
652
+          if (nr_moves < 3 && delay_before_delivering) return NULL;
653
+          delay_before_delivering = 0;
603
         }
654
         }
604
-        else if (TEST(block->flag, BLOCK_BIT_RECALCULATE))
605
-          return NULL;
655
+
656
+        // If we are here, there is no excuse to deliver the block
657
+        block_t * const block = &block_buffer[block_buffer_tail];
658
+
659
+        // No trapezoid calculated? Don't execute yet.
660
+        if (TEST(block->flag, BLOCK_BIT_RECALCULATE)) return NULL;
606
 
661
 
607
         #if ENABLED(ULTRA_LCD)
662
         #if ENABLED(ULTRA_LCD)
608
           block_buffer_runtime_us -= block->segment_time_us; // We can't be sure how long an active block will take, so don't count it.
663
           block_buffer_runtime_us -= block->segment_time_us; // We can't be sure how long an active block will take, so don't count it.
609
         #endif
664
         #endif
665
+
666
+        // Mark the block as busy, so the planner does not attempt to replan it
610
         SBI(block->flag, BLOCK_BIT_BUSY);
667
         SBI(block->flag, BLOCK_BIT_BUSY);
611
         return block;
668
         return block;
612
       }
669
       }
613
-      else {
614
-        #if ENABLED(ULTRA_LCD)
615
-          clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero.
616
-        #endif
617
-        return NULL;
670
+
671
+      // The queue became empty
672
+      #if ENABLED(ULTRA_LCD)
673
+        clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero.
674
+      #endif
675
+
676
+      return NULL;
677
+    }
678
+
679
+    /**
680
+     * "Discard" the block and "release" the memory.
681
+     * Called when the current block is no longer needed.
682
+     * NB: There MUST be a current block to call this function!!
683
+     */
684
+    FORCE_INLINE static void discard_current_block() {
685
+      if (has_blocks_queued()) { // Discard non-empty buffer.
686
+        uint8_t block_index = next_block_index( block_buffer_tail );
687
+
688
+        // Push block_buffer_planned pointer, if encountered.
689
+        if (!has_blocks_queued()) block_buffer_planned = block_index;
690
+
691
+        block_buffer_tail = block_index;
618
       }
692
       }
619
     }
693
     }
620
 
694
 
621
     #if ENABLED(ULTRA_LCD)
695
     #if ENABLED(ULTRA_LCD)
622
 
696
 
623
       static uint16_t block_buffer_runtime() {
697
       static uint16_t block_buffer_runtime() {
624
-        CRITICAL_SECTION_START
625
-          millis_t bbru = block_buffer_runtime_us;
626
-        CRITICAL_SECTION_END
698
+        #ifdef __AVR__
699
+          // Protect the access to the variable. Only required for AVR, as
700
+          //  any 32bit CPU offers atomic access to 32bit variables
701
+          bool was_enabled = STEPPER_ISR_ENABLED();
702
+          if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
703
+        #endif
704
+
705
+        millis_t bbru = block_buffer_runtime_us;
706
+
707
+        #ifdef __AVR__
708
+          // Reenable Stepper ISR
709
+          if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
710
+        #endif
711
+
627
         // To translate µs to ms a division by 1000 would be required.
712
         // To translate µs to ms a division by 1000 would be required.
628
         // We introduce 2.4% error here by dividing by 1024.
713
         // We introduce 2.4% error here by dividing by 1024.
629
         // Doesn't matter because block_buffer_runtime_us is already too small an estimation.
714
         // Doesn't matter because block_buffer_runtime_us is already too small an estimation.
634
       }
719
       }
635
 
720
 
636
       static void clear_block_buffer_runtime() {
721
       static void clear_block_buffer_runtime() {
637
-        CRITICAL_SECTION_START
638
-          block_buffer_runtime_us = 0;
639
-        CRITICAL_SECTION_END
722
+        #ifdef __AVR__
723
+          // Protect the access to the variable. Only required for AVR, as
724
+          //  any 32bit CPU offers atomic access to 32bit variables
725
+          bool was_enabled = STEPPER_ISR_ENABLED();
726
+          if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
727
+        #endif
728
+
729
+        block_buffer_runtime_us = 0;
730
+
731
+        #ifdef __AVR__
732
+          // Reenable Stepper ISR
733
+          if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
734
+        #endif
640
       }
735
       }
641
 
736
 
642
     #endif
737
     #endif
653
     /**
748
     /**
654
      * Get the index of the next / previous block in the ring buffer
749
      * Get the index of the next / previous block in the ring buffer
655
      */
750
      */
656
-    static constexpr int8_t next_block_index(const int8_t block_index) { return BLOCK_MOD(block_index + 1); }
657
-    static constexpr int8_t prev_block_index(const int8_t block_index) { return BLOCK_MOD(block_index - 1); }
751
+    static constexpr uint8_t next_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index + 1); }
752
+    static constexpr uint8_t prev_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index - 1); }
658
 
753
 
659
     /**
754
     /**
660
      * Calculate the distance (not time) it takes to accelerate
755
      * Calculate the distance (not time) it takes to accelerate
679
     }
774
     }
680
 
775
 
681
     /**
776
     /**
682
-     * Calculate the maximum allowable speed at this point, in order
683
-     * to reach 'target_velocity' using 'acceleration' within a given
777
+     * Calculate the maximum allowable speed squared at this point, in order
778
+     * to reach 'target_velocity_sqr' using 'acceleration' within a given
684
      * 'distance'.
779
      * 'distance'.
685
      */
780
      */
686
-    static float max_allowable_speed(const float &accel, const float &target_velocity, const float &distance) {
687
-      return SQRT(sq(target_velocity) - 2 * accel * distance);
781
+    static float max_allowable_speed_sqr(const float &accel, const float &target_velocity_sqr, const float &distance) {
782
+      return target_velocity_sqr - 2 * accel * distance;
688
     }
783
     }
689
 
784
 
690
     #if ENABLED(BEZIER_JERK_CONTROL)
785
     #if ENABLED(BEZIER_JERK_CONTROL)
699
     static void calculate_trapezoid_for_block(block_t* const block, const float &entry_factor, const float &exit_factor);
794
     static void calculate_trapezoid_for_block(block_t* const block, const float &entry_factor, const float &exit_factor);
700
 
795
 
701
     static void reverse_pass_kernel(block_t* const current, const block_t * const next);
796
     static void reverse_pass_kernel(block_t* const current, const block_t * const next);
702
-    static void forward_pass_kernel(const block_t * const previous, block_t* const current);
797
+    static void forward_pass_kernel(const block_t * const previous, block_t* const current, uint8_t block_index);
703
 
798
 
704
     static void reverse_pass();
799
     static void reverse_pass();
705
     static void forward_pass();
800
     static void forward_pass();

+ 4
- 2
Marlin/src/module/planner_bezier.cpp 查看文件

194
     #if HAS_UBL_AND_CURVES
194
     #if HAS_UBL_AND_CURVES
195
       float pos[XYZ] = { bez_target[X_AXIS], bez_target[Y_AXIS], bez_target[Z_AXIS] };
195
       float pos[XYZ] = { bez_target[X_AXIS], bez_target[Y_AXIS], bez_target[Z_AXIS] };
196
       planner.apply_leveling(pos);
196
       planner.apply_leveling(pos);
197
-      planner.buffer_segment(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], bez_target[E_AXIS], fr_mm_s, active_extruder);
197
+      if (!planner.buffer_segment(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], bez_target[E_AXIS], fr_mm_s, active_extruder))
198
+        break;
198
     #else
199
     #else
199
-      planner.buffer_line_kinematic(bez_target, fr_mm_s, extruder);
200
+      if (!planner.buffer_line_kinematic(bez_target, fr_mm_s, extruder))
201
+        break;
200
     #endif
202
     #endif
201
   }
203
   }
202
 }
204
 }

+ 328
- 321
Marlin/src/module/stepper.cpp 查看文件

86
 
86
 
87
 block_t* Stepper::current_block = NULL;  // A pointer to the block currently being traced
87
 block_t* Stepper::current_block = NULL;  // A pointer to the block currently being traced
88
 
88
 
89
-#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
90
-  bool Stepper::abort_on_endstop_hit = false;
91
-#endif
92
-
93
 #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
89
 #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
94
   bool Stepper::performing_homing = false;
90
   bool Stepper::performing_homing = false;
95
 #endif
91
 #endif
100
 
96
 
101
 // private:
97
 // private:
102
 
98
 
103
-uint8_t Stepper::last_direction_bits = 0;        // The next stepping-bits to be output
104
-int16_t Stepper::cleaning_buffer_counter = 0;
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
105
 
103
 
106
 #if ENABLED(X_DUAL_ENDSTOPS)
104
 #if ENABLED(X_DUAL_ENDSTOPS)
107
   bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
105
   bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
118
         Stepper::counter_Z = 0,
116
         Stepper::counter_Z = 0,
119
         Stepper::counter_E = 0;
117
         Stepper::counter_E = 0;
120
 
118
 
121
-volatile uint32_t Stepper::step_events_completed = 0; // The number of step events executed in the current block
119
+uint32_t Stepper::step_events_completed = 0; // The number of step events executed in the current block
122
 
120
 
123
 #if ENABLED(BEZIER_JERK_CONTROL)
121
 #if ENABLED(BEZIER_JERK_CONTROL)
124
   int32_t __attribute__((used)) Stepper::bezier_A __asm__("bezier_A");    // A coefficient in Bézier speed curve with alias for assembler
122
   int32_t __attribute__((used)) Stepper::bezier_A __asm__("bezier_A");    // A coefficient in Bézier speed curve with alias for assembler
132
   bool Stepper::bezier_2nd_half;    // =false If Bézier curve has been initialized or not
130
   bool Stepper::bezier_2nd_half;    // =false If Bézier curve has been initialized or not
133
 #endif
131
 #endif
134
 
132
 
133
+uint32_t Stepper::nextMainISR = 0;
134
+bool Stepper::all_steps_done = false;
135
+
135
 #if ENABLED(LIN_ADVANCE)
136
 #if ENABLED(LIN_ADVANCE)
136
 
137
 
137
   uint32_t Stepper::LA_decelerate_after;
138
   uint32_t Stepper::LA_decelerate_after;
138
 
139
 
139
-  constexpr hal_timer_t ADV_NEVER = HAL_TIMER_TYPE_MAX;
140
-
141
-  hal_timer_t Stepper::nextMainISR = 0,
142
-              Stepper::nextAdvanceISR = ADV_NEVER,
143
-              Stepper::eISR_Rate = ADV_NEVER;
140
+  constexpr uint32_t ADV_NEVER = 0xFFFFFFFF;
141
+  uint32_t Stepper::nextAdvanceISR = ADV_NEVER,
142
+           Stepper::eISR_Rate = ADV_NEVER;
144
   uint16_t Stepper::current_adv_steps = 0,
143
   uint16_t Stepper::current_adv_steps = 0,
145
            Stepper::final_adv_steps,
144
            Stepper::final_adv_steps,
146
            Stepper::max_adv_steps;
145
            Stepper::max_adv_steps;
157
 
156
 
158
 #endif // LIN_ADVANCE
157
 #endif // LIN_ADVANCE
159
 
158
 
160
-int32_t Stepper::acceleration_time, Stepper::deceleration_time;
159
+uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
161
 
160
 
162
 volatile int32_t Stepper::count_position[NUM_AXIS] = { 0 };
161
 volatile int32_t Stepper::count_position[NUM_AXIS] = { 0 };
163
 volatile signed char Stepper::count_direction[NUM_AXIS] = { 1, 1, 1, 1 };
162
 volatile signed char Stepper::count_direction[NUM_AXIS] = { 1, 1, 1, 1 };
166
   int32_t Stepper::counter_m[MIXING_STEPPERS];
165
   int32_t Stepper::counter_m[MIXING_STEPPERS];
167
 #endif
166
 #endif
168
 
167
 
168
+uint32_t Stepper::ticks_nominal;
169
 uint8_t Stepper::step_loops, Stepper::step_loops_nominal;
169
 uint8_t Stepper::step_loops, Stepper::step_loops_nominal;
170
 
170
 
171
-hal_timer_t Stepper::OCR1A_nominal;
172
 #if DISABLED(BEZIER_JERK_CONTROL)
171
 #if DISABLED(BEZIER_JERK_CONTROL)
173
-  hal_timer_t Stepper::acc_step_rate; // needed for deceleration start point
172
+  uint32_t Stepper::acc_step_rate; // needed for deceleration start point
174
 #endif
173
 #endif
175
 
174
 
176
 volatile int32_t Stepper::endstops_trigsteps[XYZ];
175
 volatile int32_t Stepper::endstops_trigsteps[XYZ];
185
   #define DUAL_ENDSTOP_APPLY_STEP(A,V)                                                                                                           \
184
   #define DUAL_ENDSTOP_APPLY_STEP(A,V)                                                                                                           \
186
     if (performing_homing) {                                                                                                                        \
185
     if (performing_homing) {                                                                                                                        \
187
       if (A##_HOME_DIR < 0) {                                                                                                                    \
186
       if (A##_HOME_DIR < 0) {                                                                                                                    \
188
-        if (!(TEST(endstops.old_endstop_bits, A##_MIN) && count_direction[_AXIS(A)] < 0) && !LOCKED_##A##_MOTOR) A##_STEP_WRITE(V);     \
189
-        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);  \
190
       }                                                                                                                                             \
189
       }                                                                                                                                             \
191
       else {                                                                                                                                        \
190
       else {                                                                                                                                        \
192
-        if (!(TEST(endstops.old_endstop_bits, A##_MAX) && count_direction[_AXIS(A)] > 0) && !LOCKED_##A##_MOTOR) A##_STEP_WRITE(V);     \
193
-        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);  \
194
       }                                                                                                                                             \
193
       }                                                                                                                                             \
195
     }                                                                                                                                               \
194
     }                                                                                                                                               \
196
     else {                                                                                                                                          \
195
     else {                                                                                                                                          \
319
   #endif // !LIN_ADVANCE
318
   #endif // !LIN_ADVANCE
320
 }
319
 }
321
 
320
 
322
-#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
323
-  extern volatile uint8_t e_hit;
324
-#endif
325
-
326
 #if ENABLED(BEZIER_JERK_CONTROL)
321
 #if ENABLED(BEZIER_JERK_CONTROL)
327
   /**
322
   /**
328
    *   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.
379
    *
374
    *
380
    *   Floating point arithmetic execution time cost is prohibitive, so we will transform the math to
375
    *   Floating point arithmetic execution time cost is prohibitive, so we will transform the math to
381
    * use fixed point values to be able to evaluate it in realtime. Assuming a maximum of 250000 steps
376
    * use fixed point values to be able to evaluate it in realtime. Assuming a maximum of 250000 steps
382
-   * per second (driver pulses should at least be 2uS hi/2uS lo), and allocating 2 bits to avoid
377
+   * per second (driver pulses should at least be 2µS hi/2µS lo), and allocating 2 bits to avoid
383
    * overflows on the evaluation of the Bézier curve, means we can use
378
    * overflows on the evaluation of the Bézier curve, means we can use
384
    *
379
    *
385
    *   t: unsigned Q0.32 (0 <= t < 1) |range 0 to 0xFFFFFFFF unsigned
380
    *   t: unsigned Q0.32 (0 <= t < 1) |range 0 to 0xFFFFFFFF unsigned
1149
 HAL_STEP_TIMER_ISR {
1144
 HAL_STEP_TIMER_ISR {
1150
   HAL_timer_isr_prologue(STEP_TIMER_NUM);
1145
   HAL_timer_isr_prologue(STEP_TIMER_NUM);
1151
 
1146
 
1152
-  #if ENABLED(LIN_ADVANCE)
1153
-    Stepper::advance_isr_scheduler();
1154
-  #else
1155
-    Stepper::isr();
1156
-  #endif
1147
+  // Program timer compare for the maximum period, so it does NOT
1148
+  // flag an interrupt while this ISR is running - So changes from small
1149
+  // periods to big periods are respected and the timer does not reset to 0
1150
+  HAL_timer_set_compare(STEP_TIMER_NUM, HAL_TIMER_TYPE_MAX);
1151
+
1152
+  // Call the ISR scheduler
1153
+  hal_timer_t ticks = Stepper::isr_scheduler();
1154
+
1155
+  // Now 'ticks' contains the period to the next Stepper ISR.
1156
+  // Potential problem: Since the timer continues to run, the requested
1157
+  // compare value may already have passed.
1158
+  //
1159
+  // Assuming at least 6µs between calls to this ISR...
1160
+  // On AVR the ISR epilogue is estimated at 40 instructions - close to 2.5µS.
1161
+  // On ARM the ISR epilogue is estimated at 10 instructions - close to 200nS.
1162
+  // In either case leave at least 4µS for other tasks to execute.
1163
+  const hal_timer_t minticks = HAL_timer_get_count(STEP_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * 4); // ISR never takes more than 1ms, so this shouldn't cause trouble
1164
+  NOLESS(ticks, MAX(minticks, hal_timer_t((STEP_TIMER_MIN_INTERVAL) * (HAL_TICKS_PER_US))));
1165
+
1166
+  // Set the next ISR to fire at the proper time
1167
+  HAL_timer_set_compare(STEP_TIMER_NUM, ticks);
1157
 
1168
 
1158
   HAL_timer_isr_epilogue(STEP_TIMER_NUM);
1169
   HAL_timer_isr_epilogue(STEP_TIMER_NUM);
1159
 }
1170
 }
1164
   #define STEP_MULTIPLY(A,B) MultiU24X32toH16(A, B)
1175
   #define STEP_MULTIPLY(A,B) MultiU24X32toH16(A, B)
1165
 #endif
1176
 #endif
1166
 
1177
 
1167
-void Stepper::isr() {
1168
-
1169
-  #define ENDSTOP_NOMINAL_OCR_VAL 1500 * HAL_TICKS_PER_US // Check endstops every 1.5ms to guarantee two stepper ISRs within 5ms for BLTouch
1170
-  #define OCR_VAL_TOLERANCE        500 * HAL_TICKS_PER_US // First max delay is 2.0ms, last min delay is 0.5ms, all others 1.5ms
1171
-
1172
-  hal_timer_t ocr_val;
1173
-  static uint32_t step_remaining = 0;  // SPLIT function always runs.  This allows 16 bit timers to be
1174
-                                       // used to generate the stepper ISR.
1175
-  #define SPLIT(L) do { \
1176
-    if (L > ENDSTOP_NOMINAL_OCR_VAL) { \
1177
-      const uint32_t remainder = (uint32_t)L % (ENDSTOP_NOMINAL_OCR_VAL); \
1178
-      ocr_val = (remainder < OCR_VAL_TOLERANCE) ? ENDSTOP_NOMINAL_OCR_VAL + remainder : ENDSTOP_NOMINAL_OCR_VAL; \
1179
-      step_remaining = (uint32_t)L - ocr_val; \
1180
-    } \
1181
-    else \
1182
-      ocr_val = L;\
1183
-  }while(0)
1184
-
1185
-  // Time remaining before the next step?
1186
-  if (step_remaining) {
1187
-
1188
-    // Make sure endstops are updated
1189
-    if (ENDSTOPS_ENABLED) endstops.update();
1190
-
1191
-    // Next ISR either for endstops or stepping
1192
-    ocr_val = step_remaining <= ENDSTOP_NOMINAL_OCR_VAL ? step_remaining : ENDSTOP_NOMINAL_OCR_VAL;
1193
-    step_remaining -= ocr_val;
1194
-    _NEXT_ISR(ocr_val);
1195
-
1196
-    #if DISABLED(LIN_ADVANCE)
1197
-      HAL_timer_restrain(STEP_TIMER_NUM, STEP_TIMER_MIN_INTERVAL * HAL_TICKS_PER_US);
1198
-    #endif
1199
-
1200
-    return;
1201
-  }
1202
-
1203
-  //
1204
-  // When cleaning, discard the current block and run fast
1205
-  //
1206
-  if (cleaning_buffer_counter) {
1207
-    if (cleaning_buffer_counter < 0) {          // Count up for endstop hit
1208
-      if (current_block) planner.discard_current_block(); // Discard the active block that led to the trigger
1209
-      if (!planner.discard_continued_block())   // Discard next CONTINUED block
1210
-        cleaning_buffer_counter = 0;            // Keep discarding until non-CONTINUED
1211
-    }
1212
-    else {
1213
-      planner.discard_current_block();
1214
-      --cleaning_buffer_counter;                // Count down for abort print
1215
-      #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
1216
-        if (!cleaning_buffer_counter) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
1217
-      #endif
1218
-    }
1219
-    current_block = NULL;                       // Prep to get a new block after cleaning
1220
-    _NEXT_ISR(HAL_STEPPER_TIMER_RATE / 10000);  // Run at max speed - 10 KHz
1221
-    return;
1222
-  }
1223
-
1224
-  // If there is no current block, attempt to pop one from the buffer
1225
-  if (!current_block) {
1226
-
1227
-    // Anything in the buffer?
1228
-    if ((current_block = planner.get_current_block())) {
1229
-
1230
-      // Sync block? Sync the stepper counts and return
1231
-      while (TEST(current_block->flag, BLOCK_BIT_SYNC_POSITION)) {
1232
-        _set_position(
1233
-          current_block->steps[A_AXIS], current_block->steps[B_AXIS],
1234
-          current_block->steps[C_AXIS], current_block->steps[E_AXIS]
1235
-        );
1236
-        planner.discard_current_block();
1237
-        if (!(current_block = planner.get_current_block())) return;
1238
-      }
1178
+hal_timer_t Stepper::isr_scheduler() {
1179
+  uint32_t interval;
1239
 
1180
 
1240
-      // Initialize the trapezoid generator from the current block.
1241
-      static int8_t last_extruder = -1;
1181
+  // Run main stepping pulse phase ISR if we have to
1182
+  if (!nextMainISR) Stepper::stepper_pulse_phase_isr();
1242
 
1183
 
1243
-      #if ENABLED(LIN_ADVANCE)
1244
-        #if E_STEPPERS > 1
1245
-          if (current_block->active_extruder != last_extruder) {
1246
-            current_adv_steps = 0; // If the now active extruder wasn't in use during the last move, its pressure is most likely gone.
1247
-            LA_active_extruder = current_block->active_extruder;
1248
-          }
1249
-        #endif
1250
-
1251
-        if ((use_advance_lead = current_block->use_advance_lead)) {
1252
-          LA_decelerate_after = current_block->decelerate_after;
1253
-          final_adv_steps = current_block->final_adv_steps;
1254
-          max_adv_steps = current_block->max_adv_steps;
1255
-        }
1256
-      #endif
1257
-
1258
-      if (current_block->direction_bits != last_direction_bits || current_block->active_extruder != last_extruder) {
1259
-        last_direction_bits = current_block->direction_bits;
1260
-        last_extruder = current_block->active_extruder;
1261
-        set_directions();
1262
-      }
1184
+  #if ENABLED(LIN_ADVANCE)
1185
+    // Run linear advance stepper ISR if we have to
1186
+    if (!nextAdvanceISR) nextAdvanceISR = Stepper::advance_isr();
1187
+  #endif
1263
 
1188
 
1264
-      // No acceleration / deceleration time elapsed so far
1265
-      acceleration_time = deceleration_time = 0;
1189
+  // ^== Time critical. NOTHING besides pulse generation should be above here!!!
1266
 
1190
 
1267
-      // No step events completed so far
1268
-      step_events_completed = 0;
1191
+  // Run main stepping block processing ISR if we have to
1192
+  if (!nextMainISR) nextMainISR = Stepper::stepper_block_phase_isr();
1269
 
1193
 
1270
-      // step_rate to timer interval
1271
-      OCR1A_nominal = calc_timer_interval(current_block->nominal_rate);
1194
+  #if ENABLED(LIN_ADVANCE)
1195
+    // Select the closest interval in time
1196
+    interval = (nextAdvanceISR <= nextMainISR)
1197
+      ? nextAdvanceISR
1198
+      : nextMainISR;
1272
 
1199
 
1273
-      // make a note of the number of step loops required at nominal speed
1274
-      step_loops_nominal = step_loops;
1200
+  #else // !ENABLED(LIN_ADVANCE)
1275
 
1201
 
1276
-      #if DISABLED(BEZIER_JERK_CONTROL)
1277
-        // Set as deceleration point the initial rate of the block
1278
-        acc_step_rate = current_block->initial_rate;
1279
-      #endif
1202
+    // The interval is just the remaining time to the stepper ISR
1203
+    interval = nextMainISR;
1204
+  #endif
1280
 
1205
 
1281
-      #if ENABLED(BEZIER_JERK_CONTROL)
1282
-        // Initialize the Bézier speed curve
1283
-        _calc_bezier_curve_coeffs(current_block->initial_rate, current_block->cruise_rate, current_block->acceleration_time_inverse);
1206
+  // Limit the value to the maximum possible value of the timer
1207
+  if (interval > HAL_TIMER_TYPE_MAX)
1208
+    interval = HAL_TIMER_TYPE_MAX;
1284
 
1209
 
1285
-        // We have not started the 2nd half of the trapezoid
1286
-        bezier_2nd_half = false;
1287
-      #endif
1210
+  // Compute the time remaining for the main isr
1211
+  nextMainISR -= interval;
1288
 
1212
 
1289
-      // Initialize Bresenham counters to 1/2 the ceiling
1290
-      counter_X = counter_Y = counter_Z = counter_E = -(current_block->step_event_count >> 1);
1291
-      #if ENABLED(MIXING_EXTRUDER)
1292
-        MIXING_STEPPERS_LOOP(i)
1293
-          counter_m[i] = -(current_block->mix_event_count[i] >> 1);
1294
-      #endif
1213
+  #if ENABLED(LIN_ADVANCE)
1214
+    // Compute the time remaining for the advance isr
1215
+    if (nextAdvanceISR != ADV_NEVER)
1216
+      nextAdvanceISR -= interval;
1217
+  #endif
1295
 
1218
 
1296
-      #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
1297
-        e_hit = 2; // Needed for the case an endstop is already triggered before the new move begins.
1298
-                   // No 'change' can be detected.
1299
-      #endif
1219
+  return (hal_timer_t)interval;
1220
+}
1300
 
1221
 
1301
-      #if ENABLED(Z_LATE_ENABLE)
1302
-        // If delayed Z enable, postpone move for 1mS
1303
-        if (current_block->steps[Z_AXIS] > 0) {
1304
-          enable_Z();
1305
-          _NEXT_ISR(HAL_STEPPER_TIMER_RATE / 1000); // Run at slow speed - 1 KHz
1306
-          return;
1307
-        }
1308
-      #endif
1309
-    }
1310
-    else {
1311
-      // If no more queued moves, postpone next check for 1mS
1312
-      _NEXT_ISR(HAL_STEPPER_TIMER_RATE / 1000); // Run at slow speed - 1 KHz
1313
-      return;
1222
+// This part of the ISR should ONLY create the pulses for the steppers
1223
+// -- Nothing more, nothing less -- We want to avoid jitter from where
1224
+// the pulses should be generated (when the interrupt triggers) to the
1225
+// time pulses are actually created. So, PLEASE DO NOT PLACE ANY CODE
1226
+// above this line that can conditionally change that time (we are trying
1227
+// to keep the delay between the interrupt triggering and pulse generation
1228
+// as constant as possible!!!!
1229
+void Stepper::stepper_pulse_phase_isr() {
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();
1314
     }
1237
     }
1315
   }
1238
   }
1316
 
1239
 
1317
-  // Update endstops state, if enabled
1318
-  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
1319
-    if (e_hit && ENDSTOPS_ENABLED) {
1320
-      endstops.update();
1321
-      e_hit--;
1322
-    }
1323
-  #else
1324
-    if (ENDSTOPS_ENABLED) endstops.update();
1325
-  #endif
1240
+  // If there is no current block, do nothing
1241
+  if (!current_block) return;
1326
 
1242
 
1327
   // Take multiple steps per interrupt (For high speed moves)
1243
   // Take multiple steps per interrupt (For high speed moves)
1328
-  bool all_steps_done = false;
1244
+  all_steps_done = false;
1329
   for (uint8_t i = step_loops; i--;) {
1245
   for (uint8_t i = step_loops; i--;) {
1330
 
1246
 
1331
     #define _COUNTER(AXIS) counter_## AXIS
1247
     #define _COUNTER(AXIS) counter_## AXIS
1520
     #endif
1436
     #endif
1521
 
1437
 
1522
   } // steps_loop
1438
   } // steps_loop
1439
+}
1523
 
1440
 
1524
-  // Calculate new timer value
1525
-  if (step_events_completed <= (uint32_t)current_block->accelerate_until) {
1441
+// This is the last half of the stepper interrupt: This one processes and
1442
+// properly schedules blocks from the planner. This is executed after creating
1443
+// the step pulses, so it is not time critical, as pulses are already done.
1526
 
1444
 
1527
-    #if ENABLED(BEZIER_JERK_CONTROL)
1528
-      // Get the next speed to use (Jerk limited!)
1529
-      hal_timer_t acc_step_rate =
1530
-        acceleration_time < current_block->acceleration_time
1531
-          ? _eval_bezier_curve(acceleration_time)
1532
-          : current_block->cruise_rate;
1533
-    #else
1534
-      acc_step_rate = STEP_MULTIPLY(acceleration_time, current_block->acceleration_rate) + current_block->initial_rate;
1535
-      NOMORE(acc_step_rate, current_block->nominal_rate);
1536
-    #endif
1445
+uint32_t Stepper::stepper_block_phase_isr() {
1537
 
1446
 
1538
-    // step_rate to timer interval
1539
-    const hal_timer_t interval = calc_timer_interval(acc_step_rate);
1447
+  // If no queued movements, just wait 1ms for the next move
1448
+  uint32_t interval = (HAL_STEPPER_TIMER_RATE / 1000);
1540
 
1449
 
1541
-    SPLIT(interval);  // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
1542
-    _NEXT_ISR(ocr_val);
1450
+  // If there is a current block
1451
+  if (current_block) {
1543
 
1452
 
1544
-    acceleration_time += interval;
1453
+    // Calculate new timer value
1454
+    if (step_events_completed <= current_block->accelerate_until) {
1545
 
1455
 
1546
-    #if ENABLED(LIN_ADVANCE)
1547
-      if (current_block->use_advance_lead) {
1548
-        if (step_events_completed == step_loops || (e_steps && eISR_Rate != current_block->advance_speed)) {
1549
-          nextAdvanceISR = 0; // Wake up eISR on first acceleration loop and fire ISR if final adv_rate is reached
1550
-          eISR_Rate = current_block->advance_speed;
1456
+      #if ENABLED(BEZIER_JERK_CONTROL)
1457
+        // Get the next speed to use (Jerk limited!)
1458
+        uint32_t acc_step_rate =
1459
+          acceleration_time < current_block->acceleration_time
1460
+            ? _eval_bezier_curve(acceleration_time)
1461
+            : current_block->cruise_rate;
1462
+      #else
1463
+        acc_step_rate = STEP_MULTIPLY(acceleration_time, current_block->acceleration_rate) + current_block->initial_rate;
1464
+        NOMORE(acc_step_rate, current_block->nominal_rate);
1465
+      #endif
1466
+
1467
+      // step_rate to timer interval
1468
+      interval = calc_timer_interval(acc_step_rate);
1469
+      acceleration_time += interval;
1470
+
1471
+      #if ENABLED(LIN_ADVANCE)
1472
+        if (current_block->use_advance_lead) {
1473
+          if (step_events_completed == step_loops || (e_steps && eISR_Rate != current_block->advance_speed)) {
1474
+            nextAdvanceISR = 0; // Wake up eISR on first acceleration loop and fire ISR if final adv_rate is reached
1475
+            eISR_Rate = current_block->advance_speed;
1476
+          }
1551
         }
1477
         }
1552
-      }
1553
-      else {
1554
-        eISR_Rate = ADV_NEVER;
1555
-        if (e_steps) nextAdvanceISR = 0;
1556
-      }
1557
-    #endif // LIN_ADVANCE
1478
+        else {
1479
+          eISR_Rate = ADV_NEVER;
1480
+          if (e_steps) nextAdvanceISR = 0;
1481
+        }
1482
+      #endif // LIN_ADVANCE
1483
+    }
1484
+    else if (step_events_completed > current_block->decelerate_after) {
1485
+      uint32_t step_rate;
1486
+
1487
+      #if ENABLED(BEZIER_JERK_CONTROL)
1488
+        // If this is the 1st time we process the 2nd half of the trapezoid...
1489
+        if (!bezier_2nd_half) {
1490
+          // Initialize the Bézier speed curve
1491
+          _calc_bezier_curve_coeffs(current_block->cruise_rate, current_block->final_rate, current_block->deceleration_time_inverse);
1492
+          bezier_2nd_half = true;
1493
+        }
1494
+
1495
+        // Calculate the next speed to use
1496
+        step_rate = deceleration_time < current_block->deceleration_time
1497
+          ? _eval_bezier_curve(deceleration_time)
1498
+          : current_block->final_rate;
1499
+      #else
1500
+
1501
+        // Using the old trapezoidal control
1502
+        step_rate = STEP_MULTIPLY(deceleration_time, current_block->acceleration_rate);
1503
+        if (step_rate < acc_step_rate) { // Still decelerating?
1504
+          step_rate = acc_step_rate - step_rate;
1505
+          NOLESS(step_rate, current_block->final_rate);
1506
+        }
1507
+        else
1508
+          step_rate = current_block->final_rate;
1509
+      #endif
1510
+
1511
+      // step_rate to timer interval
1512
+      interval = calc_timer_interval(step_rate);
1513
+      deceleration_time += interval;
1514
+
1515
+      #if ENABLED(LIN_ADVANCE)
1516
+        if (current_block->use_advance_lead) {
1517
+          if (step_events_completed <= current_block->decelerate_after + step_loops || (e_steps && eISR_Rate != current_block->advance_speed)) {
1518
+            nextAdvanceISR = 0; // Wake up eISR on first deceleration loop
1519
+            eISR_Rate = current_block->advance_speed;
1520
+          }
1521
+        }
1522
+        else {
1523
+          eISR_Rate = ADV_NEVER;
1524
+          if (e_steps) nextAdvanceISR = 0;
1525
+        }
1526
+      #endif // LIN_ADVANCE
1527
+    }
1528
+    else {
1529
+
1530
+      #if ENABLED(LIN_ADVANCE)
1531
+        // If there are any esteps, fire the next advance_isr "now"
1532
+        if (e_steps && eISR_Rate != current_block->advance_speed) nextAdvanceISR = 0;
1533
+      #endif
1534
+
1535
+      // The timer interval is just the nominal value for the nominal speed
1536
+      interval = ticks_nominal;
1537
+
1538
+      // Ensure this runs at the correct step rate, even if it just came off an acceleration
1539
+      step_loops = step_loops_nominal;
1540
+    }
1541
+
1542
+    // If current block is finished, reset pointer
1543
+    if (all_steps_done) {
1544
+      current_block = NULL;
1545
+      planner.discard_current_block();
1546
+    }
1558
   }
1547
   }
1559
-  else if (step_events_completed > (uint32_t)current_block->decelerate_after) {
1560
-    hal_timer_t step_rate;
1561
 
1548
 
1562
-    #if ENABLED(BEZIER_JERK_CONTROL)
1563
-      // If this is the 1st time we process the 2nd half of the trapezoid...
1564
-      if (!bezier_2nd_half) {
1549
+  // If there is no current block at this point, attempt to pop one from the buffer
1550
+  // and prepare its movement
1551
+  if (!current_block) {
1565
 
1552
 
1566
-        // Initialize the Bézier speed curve
1567
-        _calc_bezier_curve_coeffs(current_block->cruise_rate, current_block->final_rate, current_block->deceleration_time_inverse);
1568
-        bezier_2nd_half = true;
1553
+    // Anything in the buffer?
1554
+    if ((current_block = planner.get_current_block())) {
1555
+
1556
+      // Sync block? Sync the stepper counts and return
1557
+      while (TEST(current_block->flag, BLOCK_BIT_SYNC_POSITION)) {
1558
+        _set_position(
1559
+          current_block->position[A_AXIS], current_block->position[B_AXIS],
1560
+          current_block->position[C_AXIS], current_block->position[E_AXIS]
1561
+        );
1562
+        planner.discard_current_block();
1563
+
1564
+        // Try to get a new block
1565
+        if (!(current_block = planner.get_current_block()))
1566
+          return interval; // No more queued movements!
1569
       }
1567
       }
1570
 
1568
 
1571
-      // Calculate the next speed to use
1572
-      step_rate = deceleration_time < current_block->deceleration_time
1573
-        ? _eval_bezier_curve(deceleration_time)
1574
-        : current_block->final_rate;
1575
-    #else
1569
+      // Compute movement direction for proper endstop handling
1570
+      LOOP_NA(i) last_movement_non_null[i] = !!current_block->steps[i];
1571
+
1572
+      // Initialize the trapezoid generator from the current block.
1573
+      #if ENABLED(LIN_ADVANCE)
1574
+        #if E_STEPPERS > 1
1575
+          if (current_block->active_extruder != last_movement_extruder) {
1576
+            current_adv_steps = 0; // If the now active extruder wasn't in use during the last move, its pressure is most likely gone.
1577
+            LA_active_extruder = current_block->active_extruder;
1578
+          }
1579
+        #endif
1580
+
1581
+        if ((use_advance_lead = current_block->use_advance_lead)) {
1582
+          LA_decelerate_after = current_block->decelerate_after;
1583
+          final_adv_steps = current_block->final_adv_steps;
1584
+          max_adv_steps = current_block->max_adv_steps;
1585
+        }
1586
+      #endif
1576
 
1587
 
1577
-      // Using the old trapezoidal control
1578
-      step_rate = STEP_MULTIPLY(deceleration_time, current_block->acceleration_rate);
1579
-      if (step_rate < acc_step_rate) { // Still decelerating?
1580
-        step_rate = acc_step_rate - step_rate;
1581
-        NOLESS(step_rate, current_block->final_rate);
1588
+      if (current_block->direction_bits != last_direction_bits || current_block->active_extruder != last_movement_extruder) {
1589
+        last_direction_bits = current_block->direction_bits;
1590
+        last_movement_extruder = current_block->active_extruder;
1591
+        set_directions();
1582
       }
1592
       }
1583
-      else
1584
-        step_rate = current_block->final_rate;
1585
 
1593
 
1586
-    #endif
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();
1587
 
1602
 
1588
-    // step_rate to timer interval
1589
-    const hal_timer_t interval = calc_timer_interval(step_rate);
1603
+      // No acceleration / deceleration time elapsed so far
1604
+      acceleration_time = deceleration_time = 0;
1590
 
1605
 
1591
-    SPLIT(interval);  // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
1592
-    _NEXT_ISR(ocr_val);
1606
+      // No step events completed so far
1607
+      step_events_completed = 0;
1593
 
1608
 
1594
-    deceleration_time += interval;
1609
+      // step_rate to timer interval for the nominal speed
1610
+      ticks_nominal = calc_timer_interval(current_block->nominal_rate);
1595
 
1611
 
1596
-    #if ENABLED(LIN_ADVANCE)
1597
-      if (current_block->use_advance_lead) {
1598
-        if (step_events_completed <= (uint32_t)current_block->decelerate_after + step_loops || (e_steps && eISR_Rate != current_block->advance_speed)) {
1599
-          nextAdvanceISR = 0; // Wake up eISR on first deceleration loop
1600
-          eISR_Rate = current_block->advance_speed;
1601
-        }
1602
-      }
1603
-      else {
1604
-        eISR_Rate = ADV_NEVER;
1605
-        if (e_steps) nextAdvanceISR = 0;
1606
-      }
1607
-    #endif // LIN_ADVANCE
1608
-  }
1609
-  else {
1612
+      // make a note of the number of step loops required at nominal speed
1613
+      step_loops_nominal = step_loops;
1610
 
1614
 
1611
-    #if ENABLED(LIN_ADVANCE)
1612
-      // If we have esteps to execute, fire the next advance_isr "now"
1613
-      if (e_steps && eISR_Rate != current_block->advance_speed) nextAdvanceISR = 0;
1614
-    #endif
1615
+      #if DISABLED(BEZIER_JERK_CONTROL)
1616
+        // Set as deceleration point the initial rate of the block
1617
+        acc_step_rate = current_block->initial_rate;
1618
+      #endif
1615
 
1619
 
1616
-    SPLIT(OCR1A_nominal);  // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
1617
-    _NEXT_ISR(ocr_val);
1620
+      #if ENABLED(BEZIER_JERK_CONTROL)
1621
+        // Initialize the Bézier speed curve
1622
+        _calc_bezier_curve_coeffs(current_block->initial_rate, current_block->cruise_rate, current_block->acceleration_time_inverse);
1618
 
1623
 
1619
-    // ensure we're running at the correct step rate, even if we just came off an acceleration
1620
-    step_loops = step_loops_nominal;
1621
-  }
1624
+        // We have not started the 2nd half of the trapezoid
1625
+        bezier_2nd_half = false;
1626
+      #endif
1622
 
1627
 
1623
-  #if DISABLED(LIN_ADVANCE)
1624
-    // Make sure stepper ISR doesn't monopolize the CPU
1625
-    HAL_timer_restrain(STEP_TIMER_NUM, STEP_TIMER_MIN_INTERVAL * HAL_TICKS_PER_US);
1626
-  #endif
1628
+      // Initialize Bresenham counters to 1/2 the ceiling
1629
+      counter_X = counter_Y = counter_Z = counter_E = -((int32_t)(current_block->step_event_count >> 1));
1630
+      #if ENABLED(MIXING_EXTRUDER)
1631
+        MIXING_STEPPERS_LOOP(i)
1632
+          counter_m[i] = -(current_block->mix_event_count[i] >> 1);
1633
+      #endif
1627
 
1634
 
1628
-  // If current block is finished, reset pointer
1629
-  if (all_steps_done) {
1630
-    current_block = NULL;
1631
-    planner.discard_current_block();
1635
+      #if ENABLED(Z_LATE_ENABLE)
1636
+        // If delayed Z enable, enable it now. This option will severely interfere with
1637
+        //  timing between pulses when chaining motion between blocks, and it could lead
1638
+        //  to lost steps in both X and Y axis, so avoid using it unless strictly necessary!!
1639
+        if (current_block->steps[Z_AXIS]) enable_Z();
1640
+      #endif
1641
+    }
1632
   }
1642
   }
1643
+
1644
+  // Return the interval to wait
1645
+  return interval;
1633
 }
1646
 }
1634
 
1647
 
1635
 #if ENABLED(LIN_ADVANCE)
1648
 #if ENABLED(LIN_ADVANCE)
1638
   #define EXTRA_CYCLES_E (STEP_PULSE_CYCLES - (CYCLES_EATEN_E))
1651
   #define EXTRA_CYCLES_E (STEP_PULSE_CYCLES - (CYCLES_EATEN_E))
1639
 
1652
 
1640
   // Timer interrupt for E. e_steps is set in the main routine;
1653
   // Timer interrupt for E. e_steps is set in the main routine;
1641
-
1642
-  void Stepper::advance_isr() {
1654
+  uint32_t Stepper::advance_isr() {
1655
+    uint32_t interval;
1643
 
1656
 
1644
     #if ENABLED(MK2_MULTIPLEXER) // For SNMM even-numbered steppers are reversed
1657
     #if ENABLED(MK2_MULTIPLEXER) // For SNMM even-numbered steppers are reversed
1645
       #define SET_E_STEP_DIR(INDEX) do{ if (e_steps) E0_DIR_WRITE(e_steps < 0 ? !INVERT_E## INDEX ##_DIR ^ TEST(INDEX, 0) : INVERT_E## INDEX ##_DIR ^ TEST(INDEX, 0)); }while(0)
1658
       #define SET_E_STEP_DIR(INDEX) do{ if (e_steps) E0_DIR_WRITE(e_steps < 0 ? !INVERT_E## INDEX ##_DIR ^ TEST(INDEX, 0) : INVERT_E## INDEX ##_DIR ^ TEST(INDEX, 0)); }while(0)
1700
       if (step_events_completed > LA_decelerate_after && current_adv_steps > final_adv_steps) {
1713
       if (step_events_completed > LA_decelerate_after && current_adv_steps > final_adv_steps) {
1701
         e_steps--;
1714
         e_steps--;
1702
         current_adv_steps--;
1715
         current_adv_steps--;
1703
-        nextAdvanceISR = eISR_Rate;
1716
+        interval = eISR_Rate;
1704
       }
1717
       }
1705
       else if (step_events_completed < LA_decelerate_after && current_adv_steps < max_adv_steps) {
1718
       else if (step_events_completed < LA_decelerate_after && current_adv_steps < max_adv_steps) {
1706
              //step_events_completed <= (uint32_t)current_block->accelerate_until) {
1719
              //step_events_completed <= (uint32_t)current_block->accelerate_until) {
1707
         e_steps++;
1720
         e_steps++;
1708
         current_adv_steps++;
1721
         current_adv_steps++;
1709
-        nextAdvanceISR = eISR_Rate;
1722
+        interval = eISR_Rate;
1710
       }
1723
       }
1711
       else {
1724
       else {
1712
-        nextAdvanceISR = ADV_NEVER;
1725
+        interval = ADV_NEVER;
1713
         eISR_Rate = ADV_NEVER;
1726
         eISR_Rate = ADV_NEVER;
1714
       }
1727
       }
1715
     }
1728
     }
1716
     else
1729
     else
1717
-      nextAdvanceISR = ADV_NEVER;
1730
+      interval = ADV_NEVER;
1718
 
1731
 
1719
     switch (LA_active_extruder) {
1732
     switch (LA_active_extruder) {
1720
       case 0: SET_E_STEP_DIR(0); break;
1733
       case 0: SET_E_STEP_DIR(0); break;
1787
       #endif
1800
       #endif
1788
 
1801
 
1789
     } // e_steps
1802
     } // e_steps
1790
-  }
1791
-
1792
-  void Stepper::advance_isr_scheduler() {
1793
-
1794
-    // Run main stepping ISR if flagged
1795
-    if (!nextMainISR) isr();
1796
-
1797
-    // Run Advance stepping ISR if flagged
1798
-    if (!nextAdvanceISR) advance_isr();
1799
-
1800
-    // Is the next advance ISR scheduled before the next main ISR?
1801
-    if (nextAdvanceISR <= nextMainISR) {
1802
-      // Set up the next interrupt
1803
-      HAL_timer_set_compare(STEP_TIMER_NUM, nextAdvanceISR);
1804
-      // New interval for the next main ISR
1805
-      if (nextMainISR) nextMainISR -= nextAdvanceISR;
1806
-      // Will call Stepper::advance_isr on the next interrupt
1807
-      nextAdvanceISR = 0;
1808
-    }
1809
-    else {
1810
-      // The next main ISR comes first
1811
-      HAL_timer_set_compare(STEP_TIMER_NUM, nextMainISR);
1812
-      // New interval for the next advance ISR, if any
1813
-      if (nextAdvanceISR && nextAdvanceISR != ADV_NEVER)
1814
-        nextAdvanceISR -= nextMainISR;
1815
-      // Will call Stepper::isr on the next interrupt
1816
-      nextMainISR = 0;
1817
-    }
1818
 
1803
 
1819
-    // Make sure stepper ISR doesn't monopolize the CPU
1820
-    HAL_timer_restrain(STEP_TIMER_NUM, STEP_TIMER_MIN_INTERVAL * HAL_TICKS_PER_US);
1804
+    return interval;
1821
   }
1805
   }
1822
-
1823
 #endif // LIN_ADVANCE
1806
 #endif // LIN_ADVANCE
1824
 
1807
 
1825
 void Stepper::init() {
1808
 void Stepper::init() {
1924
     if (!E_ENABLE_ON) E4_ENABLE_WRITE(HIGH);
1907
     if (!E_ENABLE_ON) E4_ENABLE_WRITE(HIGH);
1925
   #endif
1908
   #endif
1926
 
1909
 
1927
-  // Init endstops and pullups
1928
-  endstops.init();
1929
-
1930
   #define _STEP_INIT(AXIS) AXIS ##_STEP_INIT
1910
   #define _STEP_INIT(AXIS) AXIS ##_STEP_INIT
1931
   #define _WRITE_STEP(AXIS, HIGHLOW) AXIS ##_STEP_WRITE(HIGHLOW)
1911
   #define _WRITE_STEP(AXIS, HIGHLOW) AXIS ##_STEP_WRITE(HIGHLOW)
1932
   #define _DISABLE(AXIS) disable_## AXIS()
1912
   #define _DISABLE(AXIS) disable_## AXIS()
2048
  * Get a stepper's position in steps.
2028
  * Get a stepper's position in steps.
2049
  */
2029
  */
2050
 int32_t Stepper::position(const AxisEnum axis) {
2030
 int32_t Stepper::position(const AxisEnum axis) {
2051
-  CRITICAL_SECTION_START;
2052
-  const int32_t count_pos = count_position[axis];
2053
-  CRITICAL_SECTION_END;
2054
-  return count_pos;
2055
-}
2031
+  #ifdef __AVR__
2032
+    // Protect the access to the position. Only required for AVR, as
2033
+    //  any 32bit CPU offers atomic access to 32bit variables
2034
+    const bool was_enabled = STEPPER_ISR_ENABLED();
2035
+    if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2036
+  #endif
2056
 
2037
 
2057
-void Stepper::finish_and_disable() {
2058
-  planner.synchronize();
2059
-  disable_all_steppers();
2060
-}
2038
+  int32_t v = count_position[axis];
2061
 
2039
 
2062
-void Stepper::quick_stop() {
2063
-  DISABLE_STEPPER_DRIVER_INTERRUPT();
2064
-  kill_current_block();
2065
-  current_block = NULL;
2066
-  cleaning_buffer_counter = 5000;
2067
-  planner.clear_block_buffer();
2068
-  ENABLE_STEPPER_DRIVER_INTERRUPT();
2069
-  #if ENABLED(ULTRA_LCD)
2070
-    planner.clear_block_buffer_runtime();
2040
+  #ifdef __AVR__
2041
+    // Reenable Stepper ISR
2042
+    if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2071
   #endif
2043
   #endif
2044
+  return v;
2072
 }
2045
 }
2073
 
2046
 
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
2074
 void Stepper::endstop_triggered(const AxisEnum axis) {
2053
 void Stepper::endstop_triggered(const AxisEnum axis) {
2075
 
2054
 
2055
+  const bool was_enabled = STEPPER_ISR_ENABLED();
2056
+  if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2057
+
2076
   #if IS_CORE
2058
   #if IS_CORE
2077
 
2059
 
2078
     endstops_trigsteps[axis] = 0.5f * (
2060
     endstops_trigsteps[axis] = 0.5f * (
2086
 
2068
 
2087
   #endif // !COREXY && !COREXZ && !COREYZ
2069
   #endif // !COREXY && !COREXZ && !COREYZ
2088
 
2070
 
2089
-  kill_current_block();
2090
-  cleaning_buffer_counter = -1; // Discard the rest of the move
2071
+  // Discard the rest of the move if there is a current block
2072
+  quick_stop();
2073
+
2074
+  if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2075
+}
2076
+
2077
+int32_t Stepper::triggered_position(const AxisEnum axis) {
2078
+  #ifdef __AVR__
2079
+    // Protect the access to the position. Only required for AVR, as
2080
+    //  any 32bit CPU offers atomic access to 32bit variables
2081
+    const bool was_enabled = STEPPER_ISR_ENABLED();
2082
+    if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2083
+  #endif
2084
+
2085
+  const int32_t v = endstops_trigsteps[axis];
2086
+
2087
+  #ifdef __AVR__
2088
+    // Reenable Stepper ISR
2089
+    if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2090
+  #endif
2091
+
2092
+  return v;
2091
 }
2093
 }
2092
 
2094
 
2093
 void Stepper::report_positions() {
2095
 void Stepper::report_positions() {
2094
-  CRITICAL_SECTION_START;
2096
+
2097
+  // Protect the access to the position.
2098
+  const bool was_enabled = STEPPER_ISR_ENABLED();
2099
+  if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2100
+
2095
   const int32_t xpos = count_position[X_AXIS],
2101
   const int32_t xpos = count_position[X_AXIS],
2096
                 ypos = count_position[Y_AXIS],
2102
                 ypos = count_position[Y_AXIS],
2097
                 zpos = count_position[Z_AXIS];
2103
                 zpos = count_position[Z_AXIS];
2098
-  CRITICAL_SECTION_END;
2104
+
2105
+  if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2099
 
2106
 
2100
   #if CORE_IS_XY || CORE_IS_XZ || IS_DELTA || IS_SCARA
2107
   #if CORE_IS_XY || CORE_IS_XZ || IS_DELTA || IS_SCARA
2101
     SERIAL_PROTOCOLPGM(MSG_COUNT_A);
2108
     SERIAL_PROTOCOLPGM(MSG_COUNT_A);

+ 52
- 102
Marlin/src/module/stepper.h 查看文件

62
 
62
 
63
     static block_t* current_block;  // A pointer to the block currently being traced
63
     static block_t* current_block;  // A pointer to the block currently being traced
64
 
64
 
65
-    #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
66
-      static bool abort_on_endstop_hit;
67
-    #endif
68
-
69
     #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
65
     #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
70
       static bool performing_homing;
66
       static bool performing_homing;
71
     #endif
67
     #endif
77
       static uint32_t motor_current_setting[3];
73
       static uint32_t motor_current_setting[3];
78
     #endif
74
     #endif
79
 
75
 
80
-    static int16_t cleaning_buffer_counter;
81
-
82
   private:
76
   private:
83
 
77
 
84
-    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
85
 
82
 
86
     #if ENABLED(X_DUAL_ENDSTOPS)
83
     #if ENABLED(X_DUAL_ENDSTOPS)
87
       static bool locked_x_motor, locked_x2_motor;
84
       static bool locked_x_motor, locked_x2_motor;
95
 
92
 
96
     // Counter variables for the Bresenham line tracer
93
     // Counter variables for the Bresenham line tracer
97
     static int32_t counter_X, counter_Y, counter_Z, counter_E;
94
     static int32_t counter_X, counter_Y, counter_Z, counter_E;
98
-    static volatile uint32_t step_events_completed; // The number of step events executed in the current block
95
+    static uint32_t step_events_completed; // The number of step events executed in the current block
99
 
96
 
100
     #if ENABLED(BEZIER_JERK_CONTROL)
97
     #if ENABLED(BEZIER_JERK_CONTROL)
101
       static int32_t bezier_A,     // A coefficient in Bézier speed curve
98
       static int32_t bezier_A,     // A coefficient in Bézier speed curve
109
       static bool bezier_2nd_half; // If Bézier curve has been initialized or not
106
       static bool bezier_2nd_half; // If Bézier curve has been initialized or not
110
     #endif
107
     #endif
111
 
108
 
109
+    static uint32_t nextMainISR;   // time remaining for the next Step ISR
110
+    static bool all_steps_done;    // all steps done
111
+
112
     #if ENABLED(LIN_ADVANCE)
112
     #if ENABLED(LIN_ADVANCE)
113
 
113
 
114
       static uint32_t LA_decelerate_after; // Copy from current executed block. Needed because current_block is set to NULL "too early".
114
       static uint32_t LA_decelerate_after; // Copy from current executed block. Needed because current_block is set to NULL "too early".
115
-      static hal_timer_t nextMainISR, nextAdvanceISR, eISR_Rate;
115
+      static uint32_t nextAdvanceISR, eISR_Rate;
116
       static uint16_t current_adv_steps, final_adv_steps, max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
116
       static uint16_t current_adv_steps, final_adv_steps, max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
117
-      #define _NEXT_ISR(T) nextMainISR = T
118
       static int8_t e_steps;
117
       static int8_t e_steps;
119
       static bool use_advance_lead;
118
       static bool use_advance_lead;
120
       #if E_STEPPERS > 1
119
       #if E_STEPPERS > 1
123
         static constexpr int8_t LA_active_extruder = 0;
122
         static constexpr int8_t LA_active_extruder = 0;
124
       #endif
123
       #endif
125
 
124
 
126
-    #else // !LIN_ADVANCE
127
-
128
-      #define _NEXT_ISR(T) HAL_timer_set_compare(STEP_TIMER_NUM, T);
125
+    #endif // LIN_ADVANCE
129
 
126
 
130
-    #endif // !LIN_ADVANCE
131
-
132
-    static int32_t acceleration_time, deceleration_time;
127
+    static uint32_t acceleration_time, deceleration_time;
133
     static uint8_t step_loops, step_loops_nominal;
128
     static uint8_t step_loops, step_loops_nominal;
134
 
129
 
135
-    static hal_timer_t OCR1A_nominal;
130
+    static uint32_t ticks_nominal;
136
     #if DISABLED(BEZIER_JERK_CONTROL)
131
     #if DISABLED(BEZIER_JERK_CONTROL)
137
-      static hal_timer_t acc_step_rate; // needed for deceleration start point
132
+      static uint32_t acc_step_rate; // needed for deceleration start point
138
     #endif
133
     #endif
139
 
134
 
140
     static volatile int32_t endstops_trigsteps[XYZ];
135
     static volatile int32_t endstops_trigsteps[XYZ];
167
     //
162
     //
168
     Stepper() { };
163
     Stepper() { };
169
 
164
 
170
-    //
171
     // Initialize stepper hardware
165
     // Initialize stepper hardware
172
-    //
173
     static void init();
166
     static void init();
174
 
167
 
175
-    //
176
     // Interrupt Service Routines
168
     // Interrupt Service Routines
177
-    //
178
-
179
-    static void isr();
180
 
169
 
181
-    #if ENABLED(LIN_ADVANCE)
182
-      static void advance_isr();
183
-      static void advance_isr_scheduler();
184
-    #endif
170
+    // The ISR scheduler
171
+    static hal_timer_t isr_scheduler();
185
 
172
 
186
-    //
187
-    // Set the current position in steps
188
-    //
189
-    static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
173
+    // The stepper pulse phase ISR
174
+    static void stepper_pulse_phase_isr();
190
 
175
 
191
-    FORCE_INLINE static void _set_position(const AxisEnum a, const int32_t &v) { count_position[a] = v; }
176
+    // The stepper block processing phase ISR
177
+    static uint32_t stepper_block_phase_isr();
192
 
178
 
193
-    FORCE_INLINE static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
194
-      planner.synchronize();
195
-      CRITICAL_SECTION_START;
196
-      _set_position(a, b, c, e);
197
-      CRITICAL_SECTION_END;
198
-    }
199
-
200
-    static void set_position(const AxisEnum a, const int32_t &v) {
201
-      planner.synchronize();
202
-      CRITICAL_SECTION_START;
203
-      count_position[a] = v;
204
-      CRITICAL_SECTION_END;
205
-    }
206
-
207
-    FORCE_INLINE static void _set_e_position(const int32_t &e) { count_position[E_AXIS] = e; }
208
-
209
-    static void set_e_position(const int32_t &e) {
210
-      planner.synchronize();
211
-      CRITICAL_SECTION_START;
212
-      count_position[E_AXIS] = e;
213
-      CRITICAL_SECTION_END;
214
-    }
215
-
216
-    //
217
-    // Set direction bits for all steppers
218
-    //
219
-    static void set_directions();
179
+    #if ENABLED(LIN_ADVANCE)
180
+      // The Linear advance stepper ISR
181
+      static uint32_t advance_isr();
182
+    #endif
220
 
183
 
221
-    //
222
     // Get the position of a stepper, in steps
184
     // Get the position of a stepper, in steps
223
-    //
224
     static int32_t position(const AxisEnum axis);
185
     static int32_t position(const AxisEnum axis);
225
 
186
 
226
-    //
227
     // Report the positions of the steppers, in steps
187
     // Report the positions of the steppers, in steps
228
-    //
229
     static void report_positions();
188
     static void report_positions();
230
 
189
 
231
-    //
232
     // The stepper subsystem goes to sleep when it runs out of things to execute. Call this
190
     // The stepper subsystem goes to sleep when it runs out of things to execute. Call this
233
     // to notify the subsystem that it is time to go to work.
191
     // to notify the subsystem that it is time to go to work.
234
-    //
235
     static void wake_up();
192
     static void wake_up();
236
 
193
 
237
-    //
238
-    // Wait for moves to finish and disable all steppers
239
-    //
240
-    static void finish_and_disable();
194
+    // Quickly stop all steppers
195
+    FORCE_INLINE static void quick_stop() { abort_current_block = true; }
241
 
196
 
242
-    //
243
-    // Quickly stop all steppers and clear the blocks queue
244
-    //
245
-    static void quick_stop();
246
-
247
-    //
248
     // The direction of a single motor
197
     // The direction of a single motor
249
-    //
250
     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); }
251
 
199
 
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; }
205
+
206
+    // Handle a triggered endstop
207
+    static void endstop_triggered(const AxisEnum axis);
208
+
209
+    // Triggered position of an axis in steps
210
+    static int32_t triggered_position(const AxisEnum axis);
211
+
252
     #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
212
     #if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
253
       static void digitalPotWrite(const int16_t address, const int16_t value);
213
       static void digitalPotWrite(const int16_t address, const int16_t value);
254
       static void digipot_current(const uint8_t driver, const int16_t current);
214
       static void digipot_current(const uint8_t driver, const int16_t current);
280
       static void babystep(const AxisEnum axis, const bool direction); // perform a short step with a single stepper motor, outside of any convention
240
       static void babystep(const AxisEnum axis, const bool direction); // perform a short step with a single stepper motor, outside of any convention
281
     #endif
241
     #endif
282
 
242
 
283
-    static inline void kill_current_block() {
284
-      step_events_completed = current_block->step_event_count;
285
-    }
286
-
287
-    //
288
-    // Handle a triggered endstop
289
-    //
290
-    static void endstop_triggered(const AxisEnum axis);
291
-
292
-    //
293
-    // Triggered position of an axis in mm (not core-savvy)
294
-    //
295
-    FORCE_INLINE static float triggered_position_mm(const AxisEnum axis) {
296
-      return endstops_trigsteps[axis] * planner.steps_to_mm[axis];
297
-    }
298
-
299
     #if HAS_MOTOR_CURRENT_PWM
243
     #if HAS_MOTOR_CURRENT_PWM
300
       static void refresh_motor_power();
244
       static void refresh_motor_power();
301
     #endif
245
     #endif
302
 
246
 
303
   private:
247
   private:
304
 
248
 
305
-    FORCE_INLINE static hal_timer_t calc_timer_interval(hal_timer_t step_rate) {
306
-      hal_timer_t timer;
249
+    // Set the current position in steps
250
+    static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
251
+
252
+    // Set direction bits for all steppers
253
+    static void set_directions();
254
+
255
+    FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate) {
256
+      uint32_t timer;
307
 
257
 
308
-      NOMORE(step_rate, MAX_STEP_FREQUENCY);
258
+      NOMORE(step_rate, uint32_t(MAX_STEP_FREQUENCY));
309
 
259
 
310
-      // TODO: HAL: tidy this up, use condtionals_post.h
260
+      // TODO: HAL: tidy this up, use Conditionals_post.h
311
       #ifdef CPU_32_BIT
261
       #ifdef CPU_32_BIT
312
         #if ENABLED(DISABLE_MULTI_STEPPING)
262
         #if ENABLED(DISABLE_MULTI_STEPPING)
313
           step_loops = 1;
263
           step_loops = 1;
344
         timer = uint32_t(HAL_STEPPER_TIMER_RATE) / step_rate;
294
         timer = uint32_t(HAL_STEPPER_TIMER_RATE) / step_rate;
345
         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)
346
       #else
296
       #else
347
-        NOLESS(step_rate, F_CPU / 500000);
297
+        NOLESS(step_rate, uint32_t(F_CPU / 500000U));
348
         step_rate -= F_CPU / 500000; // Correct for minimal speed
298
         step_rate -= F_CPU / 500000; // Correct for minimal speed
349
         if (step_rate >= (8 * 256)) { // higher step rate
299
         if (step_rate >= (8 * 256)) { // higher step rate
350
           uint8_t tmp_step_rate = (step_rate & 0x00FF);
300
           uint8_t tmp_step_rate = (step_rate & 0x00FF);
351
-          uint16_t table_address = (uint16_t)&speed_lookuptable_fast[(uint8_t)(step_rate >> 8)][0];
352
-          uint16_t gain = (uint16_t)pgm_read_word_near(table_address + 2);
301
+          uint16_t table_address = (uint16_t)&speed_lookuptable_fast[(uint8_t)(step_rate >> 8)][0],
302
+                   gain = (uint16_t)pgm_read_word_near(table_address + 2);
353
           timer = MultiU16X8toH16(tmp_step_rate, gain);
303
           timer = MultiU16X8toH16(tmp_step_rate, gain);
354
           timer = (uint16_t)pgm_read_word_near(table_address) - timer;
304
           timer = (uint16_t)pgm_read_word_near(table_address) - timer;
355
         }
305
         }
356
         else { // lower step rates
306
         else { // lower step rates
357
           uint16_t table_address = (uint16_t)&speed_lookuptable_slow[0][0];
307
           uint16_t table_address = (uint16_t)&speed_lookuptable_slow[0][0];
358
           table_address += ((step_rate) >> 1) & 0xFFFC;
308
           table_address += ((step_rate) >> 1) & 0xFFFC;
359
-          timer = (uint16_t)pgm_read_word_near(table_address);
360
-          timer -= (((uint16_t)pgm_read_word_near(table_address + 2) * (uint8_t)(step_rate & 0x0007)) >> 3);
309
+          timer = (uint16_t)pgm_read_word_near(table_address)
310
+                - (((uint16_t)pgm_read_word_near(table_address + 2) * (uint8_t)(step_rate & 0x0007)) >> 3);
361
         }
311
         }
362
         if (timer < 100) { // (20kHz - this should never happen)
312
         if (timer < 100) { // (20kHz - this should never happen)
363
           timer = 100;
313
           timer = 100;

+ 6
- 18
Marlin/src/module/temperature.cpp 查看文件

25
  */
25
  */
26
 
26
 
27
 #include "temperature.h"
27
 #include "temperature.h"
28
+#include "endstops.h"
28
 
29
 
29
 #include "../Marlin.h"
30
 #include "../Marlin.h"
30
 #include "../lcd/ultralcd.h"
31
 #include "../lcd/ultralcd.h"
40
   #include "stepper.h"
41
   #include "stepper.h"
41
 #endif
42
 #endif
42
 
43
 
43
-#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(PINS_DEBUGGING)
44
-  #include "endstops.h"
45
-#endif
46
-
47
 #include "printcounter.h"
44
 #include "printcounter.h"
48
 
45
 
49
 #if ENABLED(FILAMENT_WIDTH_SENSOR)
46
 #if ENABLED(FILAMENT_WIDTH_SENSOR)
1085
     watchdog_reset();
1082
     watchdog_reset();
1086
   #endif
1083
   #endif
1087
 
1084
 
1088
-  CRITICAL_SECTION_START;
1089
   temp_meas_ready = false;
1085
   temp_meas_ready = false;
1090
-  CRITICAL_SECTION_END;
1091
 }
1086
 }
1092
 
1087
 
1093
 
1088
 
1727
  *  - Step the babysteps value for each axis towards 0
1722
  *  - Step the babysteps value for each axis towards 0
1728
  *  - For PINS_DEBUGGING, monitor and report endstop pins
1723
  *  - For PINS_DEBUGGING, monitor and report endstop pins
1729
  *  - For ENDSTOP_INTERRUPTS_FEATURE check endstops if flagged
1724
  *  - For ENDSTOP_INTERRUPTS_FEATURE check endstops if flagged
1725
+ *  - Call planner.tick to count down its "ignore" time
1730
  */
1726
  */
1731
 HAL_TEMP_TIMER_ISR {
1727
 HAL_TEMP_TIMER_ISR {
1732
   HAL_timer_isr_prologue(TEMP_TIMER_NUM);
1728
   HAL_timer_isr_prologue(TEMP_TIMER_NUM);
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
-  #if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
2246
+  // Poll endstops state, if required
2247
+  endstops.poll();
2255
 
2248
 
2256
-    extern volatile uint8_t e_hit;
2257
-
2258
-    if (e_hit && ENDSTOPS_ENABLED) {
2259
-      endstops.update();  // call endstop update routine
2260
-      e_hit--;
2261
-    }
2262
-  #endif
2249
+  // Periodically call the planner timer
2250
+  planner.tick();
2263
 }
2251
 }
2264
 
2252
 
2265
 #if HAS_TEMP_SENSOR
2253
 #if HAS_TEMP_SENSOR

+ 1
- 2
Marlin/src/sd/cardreader.cpp 查看文件

29
 #include "../Marlin.h"
29
 #include "../Marlin.h"
30
 #include "../lcd/ultralcd.h"
30
 #include "../lcd/ultralcd.h"
31
 #include "../module/planner.h"
31
 #include "../module/planner.h"
32
-#include "../module/stepper.h"
33
 #include "../module/printcounter.h"
32
 #include "../module/printcounter.h"
34
 #include "../core/language.h"
33
 #include "../core/language.h"
35
 #include "../gcode/queue.h"
34
 #include "../gcode/queue.h"
983
     #endif
982
     #endif
984
 
983
 
985
     #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
984
     #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
986
-      stepper.cleaning_buffer_counter = 1; // The command will fire from the Stepper ISR
985
+      planner.finish_and_disable();
987
     #endif
986
     #endif
988
     print_job_timer.stop();
987
     print_job_timer.stop();
989
     if (print_job_timer.duration() > 60)
988
     if (print_job_timer.duration() > 60)

正在加载...
取消
保存