Browse Source

[2.0.x] Small assorted collection of fixes and improvements (#10911)

* Misc fixes and improvements

- Get rid of most critical sections on the Serial port drivers for AVR and DUE. Proper usage of FIFOs should allow interrupts to stay enabled without harm to queuing and dequeuing.
  Also, with 8-bit indices (for AVR) and up to 32-bit indices (for ARM), there is no need to protect reads and writes to those indices.
- Simplify the XON/XOFF logic quite a bit. Much cleaner now (both for AVR and ARM)
- Prevent a race condition (edge case) that could happen when estimating the proper value for the stepper timer (by reading it) and writing the calculated value for the time to the next ISR by disabling interrupts in those critical and small sections of the code - The problem could lead to lost steps.
- Fix dual endstops not properly homing bug (maybe).

* Set position immediately when possible
Eduardo José Tagle 7 years ago
parent
commit
d3c02410a8

+ 4
- 3
Marlin/src/HAL/HAL_AVR/HAL.h View File

64
   #define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli();
64
   #define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli();
65
   #define CRITICAL_SECTION_END    SREG = _sreg;
65
   #define CRITICAL_SECTION_END    SREG = _sreg;
66
 #endif
66
 #endif
67
-
67
+#define ISRS_ENABLED() TEST(SREG, SREG_I)
68
+#define ENABLE_ISRS()  sei()
69
+#define DISABLE_ISRS() cli()
68
 
70
 
69
 // On AVR this is in math.h?
71
 // On AVR this is in math.h?
70
 //#define square(x) ((x)*(x))
72
 //#define square(x) ((x)*(x))
181
     A("lds r16, %[timsk1]")            /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
183
     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 */ \
184
     A("andi r16,~%[msk1]")             /* 1 Disable the stepper ISR */ \
183
     A("sts %[timsk1], r16")            /* 2 And set the new value */ \
185
     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("push r16")                      /* 2 Save TIMSK1 into stack */ \
186
     A("in r16, 0x3B")                  /* 1 Get RAMPZ register */ \
187
     A("in r16, 0x3B")                  /* 1 Get RAMPZ register */ \
187
     A("push r16")                      /* 2 Save RAMPZ into stack */ \
188
     A("push r16")                      /* 2 Save RAMPZ into stack */ \
291
     A("out 0x3B, r16")                  /* 1 Restore RAMPZ register to its original value */ \
292
     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("pop r16")                        /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
293
     A("ori r16,%[msk0]")                /* 1 Enable temperature ISR */ \
294
     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("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("sts %[timsk0], r16")             /* 2 And restore the old value */ \
296
     A("pop r16")                        /* 2 Get the old SREG */ \
297
     A("pop r16")                        /* 2 Get the old SREG */ \
297
     A("out __SREG__, r16")              /* 1 And restore the SREG value */ \
298
     A("out __SREG__, r16")              /* 1 And restore the SREG value */ \

+ 128
- 101
Marlin/src/HAL/HAL_AVR/MarlinSerial.cpp View File

69
     uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
69
     uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
70
   #endif
70
   #endif
71
 
71
 
72
-  void clear_command_queue();
73
-
74
   #if ENABLED(SERIAL_STATS_DROPPED_RX)
72
   #if ENABLED(SERIAL_STATS_DROPPED_RX)
75
     uint8_t rx_dropped_bytes = 0;
73
     uint8_t rx_dropped_bytes = 0;
76
   #endif
74
   #endif
79
     ring_buffer_pos_t rx_max_enqueued = 0;
77
     ring_buffer_pos_t rx_max_enqueued = 0;
80
   #endif
78
   #endif
81
 
79
 
80
+  // A SW memory barrier, to ensure GCC does not overoptimize loops
81
+  #define sw_barrier() asm volatile("": : :"memory");
82
+
82
   #if ENABLED(EMERGENCY_PARSER)
83
   #if ENABLED(EMERGENCY_PARSER)
83
     #include "../../feature/emergency_parser.h"
84
     #include "../../feature/emergency_parser.h"
84
   #endif
85
   #endif
85
 
86
 
87
+  // (called with RX interrupts disabled)
86
   FORCE_INLINE void store_rxd_char() {
88
   FORCE_INLINE void store_rxd_char() {
87
 
89
 
88
     #if ENABLED(EMERGENCY_PARSER)
90
     #if ENABLED(EMERGENCY_PARSER)
129
         // let the host react and stop sending bytes. This translates to 13mS
131
         // let the host react and stop sending bytes. This translates to 13mS
130
         // propagation time.
132
         // propagation time.
131
         if (rx_count >= (RX_BUFFER_SIZE) / 8) {
133
         if (rx_count >= (RX_BUFFER_SIZE) / 8) {
134
+
132
           // If TX interrupts are disabled and data register is empty,
135
           // If TX interrupts are disabled and data register is empty,
133
           // just write the byte to the data register and be done. This
136
           // just write the byte to the data register and be done. This
134
           // shortcut helps significantly improve the effective datarate
137
           // shortcut helps significantly improve the effective datarate
135
           // at high (>500kbit/s) bitrates, where interrupt overhead
138
           // at high (>500kbit/s) bitrates, where interrupt overhead
136
           // becomes a slowdown.
139
           // becomes a slowdown.
137
           if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
140
           if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
141
+
138
             // Send an XOFF character
142
             // Send an XOFF character
139
             M_UDRx = XOFF_CHAR;
143
             M_UDRx = XOFF_CHAR;
144
+
140
             // clear the TXC bit -- "can be cleared by writing a one to its bit
145
             // clear the TXC bit -- "can be cleared by writing a one to its bit
141
             // location". This makes sure flush() won't return until the bytes
146
             // location". This makes sure flush() won't return until the bytes
142
             // actually got written
147
             // actually got written
143
             SBI(M_UCSRxA, M_TXCx);
148
             SBI(M_UCSRxA, M_TXCx);
149
+
144
             // And remember it was sent
150
             // And remember it was sent
145
             xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
151
             xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
146
           }
152
           }
153
               xon_xoff_state = XOFF_CHAR;
159
               xon_xoff_state = XOFF_CHAR;
154
             #else
160
             #else
155
               // We are not using TX interrupts, we will have to send this manually
161
               // We are not using TX interrupts, we will have to send this manually
156
-              while (!TEST(M_UCSRxA, M_UDREx)) { /* nada */ };
162
+              while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
157
               M_UDRx = XOFF_CHAR;
163
               M_UDRx = XOFF_CHAR;
164
+
165
+              // clear the TXC bit -- "can be cleared by writing a one to its bit
166
+              // location". This makes sure flush() won't return until the bytes
167
+              // actually got written
168
+              SBI(M_UCSRxA, M_TXCx);
169
+
158
               // And remember we already sent it
170
               // And remember we already sent it
159
               xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
171
               xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
160
             #endif
172
             #endif
170
 
182
 
171
   #if TX_BUFFER_SIZE > 0
183
   #if TX_BUFFER_SIZE > 0
172
 
184
 
185
+    // (called with TX irqs disabled)
173
     FORCE_INLINE void _tx_udr_empty_irq(void) {
186
     FORCE_INLINE void _tx_udr_empty_irq(void) {
174
       // If interrupts are enabled, there must be more data in the output
187
       // If interrupts are enabled, there must be more data in the output
175
       // buffer.
188
       // buffer.
251
     CBI(M_UCSRxB, M_UDRIEx);
264
     CBI(M_UCSRxB, M_UDRIEx);
252
   }
265
   }
253
 
266
 
254
-  void MarlinSerial::checkRx(void) {
255
-    if (TEST(M_UCSRxA, M_RXCx)) {
256
-      CRITICAL_SECTION_START;
257
-        store_rxd_char();
258
-      CRITICAL_SECTION_END;
259
-    }
260
-  }
261
-
262
   int MarlinSerial::peek(void) {
267
   int MarlinSerial::peek(void) {
263
-    CRITICAL_SECTION_START;
268
+    #if RX_BUFFER_SIZE > 256
269
+      // Disable RX interrupts, but only if non atomic reads
270
+      const bool isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
271
+      CBI(M_UCSRxB, M_RXCIEx);
272
+    #endif
264
       const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
273
       const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
265
-    CRITICAL_SECTION_END;
274
+    #if RX_BUFFER_SIZE > 256
275
+      // Reenable RX interrupts if they were enabled
276
+      if (isr_enabled) SBI(M_UCSRxB, M_RXCIEx);
277
+    #endif
266
     return v;
278
     return v;
267
   }
279
   }
268
 
280
 
269
   int MarlinSerial::read(void) {
281
   int MarlinSerial::read(void) {
270
     int v;
282
     int v;
271
-    CRITICAL_SECTION_START;
272
-      const ring_buffer_pos_t t = rx_buffer.tail;
273
-      if (rx_buffer.head == t)
274
-        v = -1;
275
-      else {
276
-        v = rx_buffer.buffer[t];
277
-        rx_buffer.tail = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
278
-
279
-        #if ENABLED(SERIAL_XON_XOFF)
280
-          if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
281
-            // Get count of bytes in the RX buffer
282
-            ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
283
-            // When below 10% of RX buffer capacity, send XON before
284
-            // running out of RX buffer bytes
285
-            if (rx_count < (RX_BUFFER_SIZE) / 10) {
286
-              xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
287
-              CRITICAL_SECTION_END;       // End critical section before returning!
288
-              writeNoHandshake(XON_CHAR);
289
-              return v;
290
-            }
283
+
284
+    #if RX_BUFFER_SIZE > 256
285
+      // Disable RX interrupts to ensure atomic reads
286
+      const bool isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
287
+      CBI(M_UCSRxB, M_RXCIEx);
288
+    #endif
289
+
290
+    const ring_buffer_pos_t h = rx_buffer.head;
291
+
292
+    #if RX_BUFFER_SIZE > 256
293
+      // End critical section
294
+      if (isr_enabled) SBI(M_UCSRxB, M_RXCIEx);
295
+    #endif
296
+
297
+    ring_buffer_pos_t t = rx_buffer.tail;
298
+
299
+    if (h == t)
300
+      v = -1;
301
+    else {
302
+      v = rx_buffer.buffer[t];
303
+      t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
304
+
305
+      #if RX_BUFFER_SIZE > 256
306
+        // Disable RX interrupts to ensure atomic write to tail, so
307
+        // the RX isr can't read partially updated values
308
+        const bool isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
309
+        CBI(M_UCSRxB, M_RXCIEx);
310
+      #endif
311
+
312
+      // Advance tail
313
+      rx_buffer.tail = t;
314
+
315
+      #if RX_BUFFER_SIZE > 256
316
+        // End critical section
317
+        if (isr_enabled) SBI(M_UCSRxB, M_RXCIEx);
318
+      #endif
319
+
320
+      #if ENABLED(SERIAL_XON_XOFF)
321
+        if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
322
+
323
+          // Get count of bytes in the RX buffer
324
+          ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
325
+
326
+          // When below 10% of RX buffer capacity, send XON before
327
+          // running out of RX buffer bytes
328
+          if (rx_count < (RX_BUFFER_SIZE) / 10) {
329
+            xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
330
+            write(XON_CHAR);
331
+            return v;
291
           }
332
           }
292
-        #endif
293
-      }
294
-    CRITICAL_SECTION_END;
333
+        }
334
+      #endif
335
+    }
336
+
295
     return v;
337
     return v;
296
   }
338
   }
297
 
339
 
298
   ring_buffer_pos_t MarlinSerial::available(void) {
340
   ring_buffer_pos_t MarlinSerial::available(void) {
299
-    CRITICAL_SECTION_START;
341
+    #if RX_BUFFER_SIZE > 256
342
+      const bool isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
343
+      CBI(M_UCSRxB, M_RXCIEx);
344
+    #endif
345
+
300
       const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
346
       const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
301
-    CRITICAL_SECTION_END;
347
+
348
+    #if RX_BUFFER_SIZE > 256
349
+      if (isr_enabled) SBI(M_UCSRxB, M_RXCIEx);
350
+    #endif
351
+
302
     return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
352
     return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
303
   }
353
   }
304
 
354
 
305
   void MarlinSerial::flush(void) {
355
   void MarlinSerial::flush(void) {
306
-    // Don't change this order of operations. If the RX interrupt occurs between
307
-    // reading rx_buffer_head and updating rx_buffer_tail, the previous rx_buffer_head
308
-    // may be written to rx_buffer_tail, making the buffer appear full rather than empty.
309
-    CRITICAL_SECTION_START;
310
-      rx_buffer.head = rx_buffer.tail = 0;
311
-      clear_command_queue();
312
-    CRITICAL_SECTION_END;
356
+    #if RX_BUFFER_SIZE > 256
357
+      const bool isr_enabled = TEST(M_UCSRxB, M_RXCIEx);
358
+      CBI(M_UCSRxB, M_RXCIEx);
359
+    #endif
360
+
361
+      rx_buffer.tail = rx_buffer.head;
362
+
363
+    #if RX_BUFFER_SIZE > 256
364
+      if (isr_enabled) SBI(M_UCSRxB, M_RXCIEx);
365
+    #endif
313
 
366
 
314
     #if ENABLED(SERIAL_XON_XOFF)
367
     #if ENABLED(SERIAL_XON_XOFF)
315
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
368
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
316
         xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
369
         xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
317
-        writeNoHandshake(XON_CHAR);
370
+        write(XON_CHAR);
318
       }
371
       }
319
     #endif
372
     #endif
320
   }
373
   }
321
 
374
 
322
   #if TX_BUFFER_SIZE > 0
375
   #if TX_BUFFER_SIZE > 0
323
-    uint8_t MarlinSerial::availableForWrite(void) {
324
-      CRITICAL_SECTION_START;
325
-        const uint8_t h = tx_buffer.head, t = tx_buffer.tail;
326
-      CRITICAL_SECTION_END;
327
-      return (uint8_t)(TX_BUFFER_SIZE + h - t) & (TX_BUFFER_SIZE - 1);
328
-    }
329
-
330
     void MarlinSerial::write(const uint8_t c) {
376
     void MarlinSerial::write(const uint8_t c) {
331
-      #if ENABLED(SERIAL_XON_XOFF)
332
-        const uint8_t state = xon_xoff_state;
333
-        if (!(state & XON_XOFF_CHAR_SENT)) {
334
-          // Send 2 chars: XON/XOFF, then a user-specified char
335
-          writeNoHandshake(state & XON_XOFF_CHAR_MASK);
336
-          xon_xoff_state = state | XON_XOFF_CHAR_SENT;
337
-        }
338
-      #endif
339
-      writeNoHandshake(c);
340
-    }
341
-
342
-    void MarlinSerial::writeNoHandshake(const uint8_t c) {
343
       _written = true;
377
       _written = true;
344
-      CRITICAL_SECTION_START;
345
-        bool emty = (tx_buffer.head == tx_buffer.tail);
346
-      CRITICAL_SECTION_END;
347
-      // If the buffer and the data register is empty, just write the byte
348
-      // to the data register and be done. This shortcut helps
349
-      // significantly improve the effective datarate at high (>
350
-      // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
351
-      if (emty && TEST(M_UCSRxA, M_UDREx)) {
352
-        CRITICAL_SECTION_START;
353
-          M_UDRx = c;
354
-          SBI(M_UCSRxA, M_TXCx);
355
-        CRITICAL_SECTION_END;
378
+
379
+      // If the TX interrupts are disabled and the data register
380
+      // is empty, just write the byte to the data register and
381
+      // be done. This shortcut helps significantly improve the
382
+      // effective datarate at high (>500kbit/s) bitrates, where
383
+      // interrupt overhead becomes a slowdown.
384
+      if (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
385
+        M_UDRx = c;
386
+
387
+        // clear the TXC bit -- "can be cleared by writing a one to its bit
388
+        // location". This makes sure flush() won't return until the bytes
389
+        // actually got written
390
+        SBI(M_UCSRxA, M_TXCx);
356
         return;
391
         return;
357
       }
392
       }
393
+
358
       const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
394
       const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
359
 
395
 
360
       // If the output buffer is full, there's nothing for it other than to
396
       // If the output buffer is full, there's nothing for it other than to
361
       // wait for the interrupt handler to empty it a bit
397
       // wait for the interrupt handler to empty it a bit
362
       while (i == tx_buffer.tail) {
398
       while (i == tx_buffer.tail) {
363
-        if (!TEST(SREG, SREG_I)) {
399
+        if (!ISRS_ENABLED()) {
364
           // Interrupts are disabled, so we'll have to poll the data
400
           // Interrupts are disabled, so we'll have to poll the data
365
           // register empty flag ourselves. If it is set, pretend an
401
           // register empty flag ourselves. If it is set, pretend an
366
           // interrupt has happened and call the handler to free up
402
           // interrupt has happened and call the handler to free up
368
           if (TEST(M_UCSRxA, M_UDREx))
404
           if (TEST(M_UCSRxA, M_UDREx))
369
             _tx_udr_empty_irq();
405
             _tx_udr_empty_irq();
370
         }
406
         }
371
-        else {
372
-          // nop, the interrupt handler will free up space for us
373
-        }
407
+        // (else , the interrupt handler will free up space for us)
408
+
409
+        // Make sure compiler rereads tx_buffer.tail
410
+        sw_barrier();
374
       }
411
       }
375
 
412
 
413
+      // Store new char. head is always safe to move
376
       tx_buffer.buffer[tx_buffer.head] = c;
414
       tx_buffer.buffer[tx_buffer.head] = c;
377
-      { CRITICAL_SECTION_START;
378
-          tx_buffer.head = i;
379
-          SBI(M_UCSRxB, M_UDRIEx);
380
-        CRITICAL_SECTION_END;
381
-      }
415
+      tx_buffer.head = i;
416
+
417
+      // Enable TX isr
418
+      SBI(M_UCSRxB, M_UDRIEx);
382
       return;
419
       return;
383
     }
420
     }
384
 
421
 
391
         return;
428
         return;
392
 
429
 
393
       while (TEST(M_UCSRxB, M_UDRIEx) || !TEST(M_UCSRxA, M_TXCx)) {
430
       while (TEST(M_UCSRxB, M_UDRIEx) || !TEST(M_UCSRxA, M_TXCx)) {
394
-        if (!TEST(SREG, SREG_I) && TEST(M_UCSRxB, M_UDRIEx))
431
+        if (!ISRS_ENABLED()) {
395
           // Interrupts are globally disabled, but the DR empty
432
           // Interrupts are globally disabled, but the DR empty
396
           // interrupt should be enabled, so poll the DR empty flag to
433
           // interrupt should be enabled, so poll the DR empty flag to
397
           // prevent deadlock
434
           // prevent deadlock
398
           if (TEST(M_UCSRxA, M_UDREx))
435
           if (TEST(M_UCSRxA, M_UDREx))
399
             _tx_udr_empty_irq();
436
             _tx_udr_empty_irq();
437
+        }
438
+        sw_barrier();
400
       }
439
       }
401
       // If we get here, nothing is queued anymore (DRIE is disabled) and
440
       // If we get here, nothing is queued anymore (DRIE is disabled) and
402
-      // the hardware finished tranmission (TXC is set).
441
+      // the hardware finished transmission (TXC is set).
403
     }
442
     }
404
 
443
 
405
   #else // TX_BUFFER_SIZE == 0
444
   #else // TX_BUFFER_SIZE == 0
406
 
445
 
407
     void MarlinSerial::write(const uint8_t c) {
446
     void MarlinSerial::write(const uint8_t c) {
408
-      #if ENABLED(SERIAL_XON_XOFF)
409
-        // Do a priority insertion of an XON/XOFF char, if needed.
410
-        const uint8_t state = xon_xoff_state;
411
-        if (!(state & XON_XOFF_CHAR_SENT)) {
412
-          writeNoHandshake(state & XON_XOFF_CHAR_MASK);
413
-          xon_xoff_state = state | XON_XOFF_CHAR_SENT;
414
-        }
415
-      #endif
416
-      writeNoHandshake(c);
417
-    }
418
-
419
-    void MarlinSerial::writeNoHandshake(const uint8_t c) {
420
-      while (!TEST(M_UCSRxA, M_UDREx)) { /* nada */ }
447
+      while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
421
       M_UDRx = c;
448
       M_UDRx = c;
422
     }
449
     }
423
 
450
 

+ 1
- 4
Marlin/src/HAL/HAL_AVR/MarlinSerial.h View File

94
     extern ring_buffer_pos_t rx_max_enqueued;
94
     extern ring_buffer_pos_t rx_max_enqueued;
95
   #endif
95
   #endif
96
 
96
 
97
-  class MarlinSerial { //: public Stream
97
+  class MarlinSerial {
98
 
98
 
99
     public:
99
     public:
100
       MarlinSerial() {};
100
       MarlinSerial() {};
104
       static int read(void);
104
       static int read(void);
105
       static void flush(void);
105
       static void flush(void);
106
       static ring_buffer_pos_t available(void);
106
       static ring_buffer_pos_t available(void);
107
-      static void checkRx(void);
108
       static void write(const uint8_t c);
107
       static void write(const uint8_t c);
109
       #if TX_BUFFER_SIZE > 0
108
       #if TX_BUFFER_SIZE > 0
110
-        static uint8_t availableForWrite(void);
111
         static void flushTX(void);
109
         static void flushTX(void);
112
       #endif
110
       #endif
113
-      static void writeNoHandshake(const uint8_t c);
114
 
111
 
115
       #if ENABLED(SERIAL_STATS_DROPPED_RX)
112
       #if ENABLED(SERIAL_STATS_DROPPED_RX)
116
         FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
113
         FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }

+ 5
- 2
Marlin/src/HAL/HAL_DUE/HAL.h View File

55
   #define analogInputToDigitalPin(p) ((p < 12u) ? (p) + 54u : -1)
55
   #define analogInputToDigitalPin(p) ((p < 12u) ? (p) + 54u : -1)
56
 #endif
56
 #endif
57
 
57
 
58
-#define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq();
59
-#define CRITICAL_SECTION_END    if (!primask) __enable_irq();
58
+#define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq()
59
+#define CRITICAL_SECTION_END    if (!primask) __enable_irq()
60
+#define ISRS_ENABLED() (!__get_PRIMASK())
61
+#define ENABLE_ISRS()  __enable_irq()
62
+#define DISABLE_ISRS() __disable_irq()
60
 
63
 
61
 // On AVR this is in math.h?
64
 // On AVR this is in math.h?
62
 #define square(x) ((x)*(x))
65
 #define square(x) ((x)*(x))

+ 41
- 86
Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.cpp View File

154
         // let the host react and stop sending bytes. This translates to 13mS
154
         // let the host react and stop sending bytes. This translates to 13mS
155
         // propagation time.
155
         // propagation time.
156
         if (rx_count >= (RX_BUFFER_SIZE) / 8) {
156
         if (rx_count >= (RX_BUFFER_SIZE) / 8) {
157
+          
157
           // If TX interrupts are disabled and data register is empty,
158
           // If TX interrupts are disabled and data register is empty,
158
           // just write the byte to the data register and be done. This
159
           // just write the byte to the data register and be done. This
159
           // shortcut helps significantly improve the effective datarate
160
           // shortcut helps significantly improve the effective datarate
160
           // at high (>500kbit/s) bitrates, where interrupt overhead
161
           // at high (>500kbit/s) bitrates, where interrupt overhead
161
           // becomes a slowdown.
162
           // becomes a slowdown.
162
           if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
163
           if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
164
+            
163
             // Send an XOFF character
165
             // Send an XOFF character
164
             HWUART->UART_THR = XOFF_CHAR;
166
             HWUART->UART_THR = XOFF_CHAR;
165
 
167
 
175
               xon_xoff_state = XOFF_CHAR;
177
               xon_xoff_state = XOFF_CHAR;
176
             #else
178
             #else
177
               // We are not using TX interrupts, we will have to send this manually
179
               // We are not using TX interrupts, we will have to send this manually
178
-              while (!(HWUART->UART_SR & UART_SR_TXRDY)) { sw_barrier(); };
180
+              while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
179
               HWUART->UART_THR = XOFF_CHAR;
181
               HWUART->UART_THR = XOFF_CHAR;
182
+              
180
               // And remember we already sent it
183
               // And remember we already sent it
181
               xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
184
               xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
182
             #endif
185
             #endif
303
     pmc_disable_periph_clk( HWUART_IRQ_ID );
306
     pmc_disable_periph_clk( HWUART_IRQ_ID );
304
   }
307
   }
305
 
308
 
306
-  void MarlinSerial::checkRx(void) {
307
-    if (HWUART->UART_SR & UART_SR_RXRDY) {
308
-      CRITICAL_SECTION_START;
309
-      store_rxd_char();
310
-      CRITICAL_SECTION_END;
311
-    }
312
-  }
313
-
314
   int MarlinSerial::peek(void) {
309
   int MarlinSerial::peek(void) {
315
-    CRITICAL_SECTION_START;
316
     const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
310
     const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
317
-    CRITICAL_SECTION_END;
318
     return v;
311
     return v;
319
   }
312
   }
320
 
313
 
321
   int MarlinSerial::read(void) {
314
   int MarlinSerial::read(void) {
322
     int v;
315
     int v;
323
-    CRITICAL_SECTION_START;
324
-    const ring_buffer_pos_t t = rx_buffer.tail;
325
-    if (rx_buffer.head == t)
316
+    
317
+    const ring_buffer_pos_t h = rx_buffer.head;
318
+    ring_buffer_pos_t t = rx_buffer.tail;
319
+    
320
+    if (h == t)
326
       v = -1;
321
       v = -1;
327
     else {
322
     else {
328
       v = rx_buffer.buffer[t];
323
       v = rx_buffer.buffer[t];
329
-      rx_buffer.tail = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
324
+      t = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1);
325
+      
326
+      // Advance tail
327
+      rx_buffer.tail = t;
330
 
328
 
331
       #if ENABLED(SERIAL_XON_XOFF)
329
       #if ENABLED(SERIAL_XON_XOFF)
332
         if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
330
         if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
331
+          
333
           // Get count of bytes in the RX buffer
332
           // Get count of bytes in the RX buffer
334
-          ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(rx_buffer.head - rx_buffer.tail) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
333
+          ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
334
+          
335
           // When below 10% of RX buffer capacity, send XON before
335
           // When below 10% of RX buffer capacity, send XON before
336
           // running out of RX buffer bytes
336
           // running out of RX buffer bytes
337
           if (rx_count < (RX_BUFFER_SIZE) / 10) {
337
           if (rx_count < (RX_BUFFER_SIZE) / 10) {
338
             xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
338
             xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
339
-            CRITICAL_SECTION_END;       // End critical section before returning!
340
-            writeNoHandshake(XON_CHAR);
339
+            write(XON_CHAR);
341
             return v;
340
             return v;
342
           }
341
           }
343
         }
342
         }
344
       #endif
343
       #endif
345
     }
344
     }
346
-    CRITICAL_SECTION_END;
347
     return v;
345
     return v;
348
   }
346
   }
349
 
347
 
350
   ring_buffer_pos_t MarlinSerial::available(void) {
348
   ring_buffer_pos_t MarlinSerial::available(void) {
351
-    CRITICAL_SECTION_START;
352
     const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
349
     const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
353
-    CRITICAL_SECTION_END;
354
     return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
350
     return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
355
   }
351
   }
356
 
352
 
357
   void MarlinSerial::flush(void) {
353
   void MarlinSerial::flush(void) {
358
-    // Don't change this order of operations. If the RX interrupt occurs between
359
-    // reading rx_buffer_head and updating rx_buffer_tail, the previous rx_buffer_head
360
-    // may be written to rx_buffer_tail, making the buffer appear full rather than empty.
361
-    CRITICAL_SECTION_START;
362
-    rx_buffer.head = rx_buffer.tail;
363
-    CRITICAL_SECTION_END;
354
+    rx_buffer.tail = rx_buffer.head;
364
 
355
 
365
     #if ENABLED(SERIAL_XON_XOFF)
356
     #if ENABLED(SERIAL_XON_XOFF)
366
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
357
       if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
367
         xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
358
         xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
368
-        writeNoHandshake(XON_CHAR);
359
+        write(XON_CHAR);
369
       }
360
       }
370
     #endif
361
     #endif
371
   }
362
   }
372
 
363
 
373
   #if TX_BUFFER_SIZE > 0
364
   #if TX_BUFFER_SIZE > 0
374
-
375
-    uint8_t MarlinSerial::availableForWrite(void) {
376
-      CRITICAL_SECTION_START;
377
-      const uint8_t h = tx_buffer.head, t = tx_buffer.tail;
378
-      CRITICAL_SECTION_END;
379
-      return (uint8_t)(TX_BUFFER_SIZE + h - t) & (TX_BUFFER_SIZE - 1);
380
-    }
381
-
382
     void MarlinSerial::write(const uint8_t c) {
365
     void MarlinSerial::write(const uint8_t c) {
383
-      #if ENABLED(SERIAL_XON_XOFF)
384
-        const uint8_t state = xon_xoff_state;
385
-        if (!(state & XON_XOFF_CHAR_SENT)) {
386
-          // Send 2 chars: XON/XOFF, then a user-specified char
387
-          writeNoHandshake(state & XON_XOFF_CHAR_MASK);
388
-          xon_xoff_state = state | XON_XOFF_CHAR_SENT;
389
-        }
390
-      #endif
391
-      writeNoHandshake(c);
392
-    }
393
-
394
-    void MarlinSerial::writeNoHandshake(const uint8_t c) {
395
       _written = true;
366
       _written = true;
396
-      CRITICAL_SECTION_START;
397
-      bool emty = (tx_buffer.head == tx_buffer.tail);
398
-      CRITICAL_SECTION_END;
399
-      // If the buffer and the data register is empty, just write the byte
400
-      // to the data register and be done. This shortcut helps
401
-      // significantly improve the effective datarate at high (>
402
-      // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
403
-      if (emty && (HWUART->UART_SR & UART_SR_TXRDY)) {
404
-        CRITICAL_SECTION_START;
405
-          HWUART->UART_THR = c;
406
-          HWUART->UART_IER = UART_IER_TXRDY;
407
-        CRITICAL_SECTION_END;
367
+      
368
+      // If the TX interrupts are disabled and the data register 
369
+      // is empty, just write the byte to the data register and 
370
+      // be done. This shortcut helps significantly improve the 
371
+      // effective datarate at high (>500kbit/s) bitrates, where 
372
+      // interrupt overhead becomes a slowdown.
373
+      if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
374
+        HWUART->UART_THR = c;
408
         return;
375
         return;
409
       }
376
       }
377
+      
410
       const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
378
       const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
411
 
379
 
412
       // If the output buffer is full, there's nothing for it other than to
380
       // If the output buffer is full, there's nothing for it other than to
413
       // wait for the interrupt handler to empty it a bit
381
       // wait for the interrupt handler to empty it a bit
414
       while (i == tx_buffer.tail) {
382
       while (i == tx_buffer.tail) {
415
-        if (__get_PRIMASK()) {
383
+        if (!ISRS_ENABLED()) {
416
           // Interrupts are disabled, so we'll have to poll the data
384
           // Interrupts are disabled, so we'll have to poll the data
417
           // register empty flag ourselves. If it is set, pretend an
385
           // register empty flag ourselves. If it is set, pretend an
418
           // interrupt has happened and call the handler to free up
386
           // interrupt has happened and call the handler to free up
420
           if (HWUART->UART_SR & UART_SR_TXRDY)
388
           if (HWUART->UART_SR & UART_SR_TXRDY)
421
             _tx_thr_empty_irq();
389
             _tx_thr_empty_irq();
422
         }
390
         }
423
-        else {
424
-          // nop, the interrupt handler will free up space for us
425
-        }
391
+        // (else , the interrupt handler will free up space for us)
392
+        
393
+        // Make sure compiler rereads tx_buffer.tail
426
         sw_barrier();
394
         sw_barrier();
427
       }
395
       }
428
 
396
 
429
       tx_buffer.buffer[tx_buffer.head] = c;
397
       tx_buffer.buffer[tx_buffer.head] = c;
430
-      { CRITICAL_SECTION_START;
431
-          tx_buffer.head = i;
432
-          HWUART->UART_IER = UART_IER_TXRDY;
433
-        CRITICAL_SECTION_END;
434
-      }
398
+      tx_buffer.head = i;
399
+      
400
+      // Enable TX isr
401
+      HWUART->UART_IER = UART_IER_TXRDY;
435
       return;
402
       return;
436
     }
403
     }
437
 
404
 
438
     void MarlinSerial::flushTX(void) {
405
     void MarlinSerial::flushTX(void) {
439
       // TX
406
       // TX
440
       // If we have never written a byte, no need to flush.
407
       // If we have never written a byte, no need to flush.
441
-      if (!_written)
442
-        return;
408
+      if (!_written) return;
443
 
409
 
444
       while ((HWUART->UART_IMR & UART_IMR_TXRDY) || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
410
       while ((HWUART->UART_IMR & UART_IMR_TXRDY) || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
445
-        if (__get_PRIMASK())
446
-          if ((HWUART->UART_SR & UART_SR_TXRDY))
411
+        if (!ISRS_ENABLED()) {
412
+          if (HWUART->UART_SR & UART_SR_TXRDY)
447
             _tx_thr_empty_irq();
413
             _tx_thr_empty_irq();
414
+        }
448
         sw_barrier();
415
         sw_barrier();
449
       }
416
       }
450
       // If we get here, nothing is queued anymore (TX interrupts are disabled) and
417
       // If we get here, nothing is queued anymore (TX interrupts are disabled) and
454
   #else // TX_BUFFER_SIZE == 0
421
   #else // TX_BUFFER_SIZE == 0
455
 
422
 
456
     void MarlinSerial::write(const uint8_t c) {
423
     void MarlinSerial::write(const uint8_t c) {
457
-      #if ENABLED(SERIAL_XON_XOFF)
458
-        // Do a priority insertion of an XON/XOFF char, if needed.
459
-        const uint8_t state = xon_xoff_state;
460
-        if (!(state & XON_XOFF_CHAR_SENT)) {
461
-          writeNoHandshake(state & XON_XOFF_CHAR_MASK);
462
-          xon_xoff_state = state | XON_XOFF_CHAR_SENT;
463
-        }
464
-      #endif
465
-      writeNoHandshake(c);
466
-    }
467
-
468
-    void MarlinSerial::writeNoHandshake(const uint8_t c) {
469
-      while (!(HWUART->UART_SR & UART_SR_TXRDY)) { sw_barrier(); };
424
+      while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
470
       HWUART->UART_THR = c;
425
       HWUART->UART_THR = c;
471
     }
426
     }
472
 
427
 

+ 0
- 3
Marlin/src/HAL/HAL_DUE/MarlinSerial_Due.h View File

84
   static int read(void);
84
   static int read(void);
85
   static void flush(void);
85
   static void flush(void);
86
   static ring_buffer_pos_t available(void);
86
   static ring_buffer_pos_t available(void);
87
-  static void checkRx(void);
88
   static void write(const uint8_t c);
87
   static void write(const uint8_t c);
89
   #if TX_BUFFER_SIZE > 0
88
   #if TX_BUFFER_SIZE > 0
90
-    static uint8_t availableForWrite(void);
91
     static void flushTX(void);
89
     static void flushTX(void);
92
   #endif
90
   #endif
93
-  static void writeNoHandshake(const uint8_t c);
94
 
91
 
95
   #if ENABLED(SERIAL_STATS_DROPPED_RX)
92
   #if ENABLED(SERIAL_STATS_DROPPED_RX)
96
     FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
93
     FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }

+ 5
- 2
Marlin/src/HAL/HAL_LPC1768/HAL.h View File

120
   #define NUM_SERIAL 1
120
   #define NUM_SERIAL 1
121
 #endif
121
 #endif
122
 
122
 
123
-#define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq();
124
-#define CRITICAL_SECTION_END    if (!primask) __enable_irq();
123
+#define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq()
124
+#define CRITICAL_SECTION_END    if (!primask) __enable_irq()
125
+#define ISRS_ENABLED() (!__get_PRIMASK())
126
+#define ENABLE_ISRS()  __enable_irq()
127
+#define DISABLE_ISRS() __disable_irq()
125
 
128
 
126
 //Utility functions
129
 //Utility functions
127
 int freeMemory(void);
130
 int freeMemory(void);

+ 5
- 2
Marlin/src/HAL/HAL_STM32F1/HAL.h View File

119
   #define analogInputToDigitalPin(p) (p)
119
   #define analogInputToDigitalPin(p) (p)
120
 #endif
120
 #endif
121
 
121
 
122
-#define CRITICAL_SECTION_START  noInterrupts();
123
-#define CRITICAL_SECTION_END    interrupts();
122
+#define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq()
123
+#define CRITICAL_SECTION_END    if (!primask) __enable_irq()
124
+#define ISRS_ENABLED() (!__get_PRIMASK())
125
+#define ENABLE_ISRS()  __enable_irq()
126
+#define DISABLE_ISRS() __disable_irq()
124
 
127
 
125
 // On AVR this is in math.h?
128
 // On AVR this is in math.h?
126
 #define square(x) ((x)*(x))
129
 #define square(x) ((x)*(x))

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

118
   #define analogInputToDigitalPin(p) (p)
118
   #define analogInputToDigitalPin(p) (p)
119
 #endif
119
 #endif
120
 
120
 
121
-#define CRITICAL_SECTION_START  noInterrupts();
122
-#define CRITICAL_SECTION_END    interrupts();
121
+#define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq()
122
+#define CRITICAL_SECTION_END    if (!primask) __enable_irq()
123
+#define ISRS_ENABLED() (!__get_PRIMASK())
124
+#define ENABLE_ISRS()  __enable_irq()
125
+#define DISABLE_ISRS() __disable_irq()
123
 
126
 
124
 // On AVR this is in math.h?
127
 // On AVR this is in math.h?
125
 #define square(x) ((x)*(x))
128
 #define square(x) ((x)*(x))

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

111
   #define analogInputToDigitalPin(p) (p)
111
   #define analogInputToDigitalPin(p) (p)
112
 #endif
112
 #endif
113
 
113
 
114
-#define CRITICAL_SECTION_START  noInterrupts();
115
-#define CRITICAL_SECTION_END    interrupts();
114
+#define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq()
115
+#define CRITICAL_SECTION_END    if (!primask) __enable_irq()
116
+#define ISRS_ENABLED() (!__get_PRIMASK())
117
+#define ENABLE_ISRS()  __enable_irq()
118
+#define DISABLE_ISRS() __disable_irq()
116
 
119
 
117
 // On AVR this is in math.h?
120
 // On AVR this is in math.h?
118
 #define square(x) ((x)*(x))
121
 #define square(x) ((x)*(x))

+ 5
- 2
Marlin/src/HAL/HAL_TEENSY35_36/HAL.h View File

88
   #define analogInputToDigitalPin(p) ((p < 12u) ? (p) + 54u : -1)
88
   #define analogInputToDigitalPin(p) ((p < 12u) ? (p) + 54u : -1)
89
 #endif
89
 #endif
90
 
90
 
91
-#define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli();
92
-#define CRITICAL_SECTION_END    SREG = _sreg;
91
+#define CRITICAL_SECTION_START  uint32_t primask = __get_PRIMASK(); __disable_irq()
92
+#define CRITICAL_SECTION_END    if (!primask) __enable_irq()
93
+#define ISRS_ENABLED() (!__get_PRIMASK())
94
+#define ENABLE_ISRS()  __enable_irq()
95
+#define DISABLE_ISRS() __disable_irq()
93
 
96
 
94
 #undef sq
97
 #undef sq
95
 #define sq(x) ((x)*(x))
98
 #define sq(x) ((x)*(x))

+ 13
- 10
Marlin/src/module/endstops.cpp View File

578
 
578
 
579
   // Call the endstop triggered routine for single endstops
579
   // Call the endstop triggered routine for single endstops
580
   #define PROCESS_ENDSTOP(AXIS,MINMAX) do { \
580
   #define PROCESS_ENDSTOP(AXIS,MINMAX) do { \
581
-      if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
582
-        _ENDSTOP_HIT(AXIS, MINMAX); \
583
-        planner.endstop_triggered(_AXIS(AXIS)); \
584
-      } \
585
-    }while(0)
581
+    if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
582
+      _ENDSTOP_HIT(AXIS, MINMAX); \
583
+      planner.endstop_triggered(_AXIS(AXIS)); \
584
+    } \
585
+  }while(0)
586
 
586
 
587
-  // Call the endstop triggered routine for single endstops
587
+  // Call the endstop triggered routine for dual endstops
588
   #define PROCESS_DUAL_ENDSTOP(AXIS1, AXIS2, MINMAX) do { \
588
   #define PROCESS_DUAL_ENDSTOP(AXIS1, AXIS2, MINMAX) do { \
589
-      if (TEST_ENDSTOP(_ENDSTOP(AXIS1, MINMAX)) || TEST_ENDSTOP(_ENDSTOP(AXIS2, MINMAX))) { \
590
-        _ENDSTOP_HIT(AXIS1, MINMAX); \
589
+    const byte dual_hit = TEST_ENDSTOP(_ENDSTOP(AXIS1, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(AXIS2, MINMAX)) << 1); \
590
+    if (dual_hit) { \
591
+      _ENDSTOP_HIT(AXIS1, MINMAX); \
592
+      /* if not performing home or if both endstops were trigged during homing... */ \
593
+      if (!stepper.performing_homing || dual_hit == 0x3) \
591
         planner.endstop_triggered(_AXIS(AXIS1)); \
594
         planner.endstop_triggered(_AXIS(AXIS1)); \
592
-      } \
593
-    }while(0)
595
+    } \
596
+  }while(0)
594
 
597
 
595
   #if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
598
   #if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
596
     // If G38 command is active check Z_MIN_PROBE for ALL movement
599
     // If G38 command is active check Z_MIN_PROBE for ALL movement

+ 9
- 1
Marlin/src/module/endstops.h View File

108
     /**
108
     /**
109
      * Get current endstops state
109
      * Get current endstops state
110
      */
110
      */
111
-    FORCE_INLINE static esbits_t state() { return live_state; }
111
+    FORCE_INLINE static esbits_t state() {
112
+      return
113
+        #if ENABLED(ENDSTOP_NOISE_FILTER)
114
+          validated_live_state
115
+        #else
116
+          live_state
117
+        #endif
118
+      ;
119
+    }
112
 
120
 
113
     /**
121
     /**
114
      * Report endstop hits to serial. Called from loop().
122
      * Report endstop hits to serial. Called from loop().

+ 13
- 5
Marlin/src/module/planner.cpp View File

2467
     position_float[C_AXIS] = c;
2467
     position_float[C_AXIS] = c;
2468
     position_float[E_AXIS] = e;
2468
     position_float[E_AXIS] = e;
2469
   #endif
2469
   #endif
2470
-  previous_nominal_speed_sqr = 0.0; // Resets planner junction speeds. Assumes start from rest.
2471
-  ZERO(previous_speed);
2472
-  buffer_sync_block();
2470
+  if (has_blocks_queued()) {
2471
+    //previous_nominal_speed_sqr = 0.0; // Reset planner junction speeds. Assume start from rest.
2472
+    //ZERO(previous_speed);
2473
+    buffer_sync_block();
2474
+  }
2475
+  else
2476
+    stepper.set_position(position[A_AXIS], position[B_AXIS], position[C_AXIS], position[E_AXIS]);
2473
 }
2477
 }
2474
 
2478
 
2475
 void Planner::set_position_mm_kinematic(const float (&cart)[XYZE]) {
2479
 void Planner::set_position_mm_kinematic(const float (&cart)[XYZE]) {
2501
   #if HAS_POSITION_FLOAT
2505
   #if HAS_POSITION_FLOAT
2502
     position_float[axis] = v;
2506
     position_float[axis] = v;
2503
   #endif
2507
   #endif
2504
-  previous_speed[axis] = 0.0;
2505
-  buffer_sync_block();
2508
+  if (has_blocks_queued()) {
2509
+    //previous_speed[axis] = 0.0;
2510
+    buffer_sync_block();
2511
+  }
2512
+  else
2513
+    stepper.set_position(axis, position[axis]);
2506
 }
2514
 }
2507
 
2515
 
2508
 // Recalculate the steps/s^2 acceleration rates, based on the mm/s^2
2516
 // Recalculate the steps/s^2 acceleration rates, based on the mm/s^2

+ 58
- 47
Marlin/src/module/stepper.cpp View File

102
 bool Stepper::abort_current_block;
102
 bool Stepper::abort_current_block;
103
 
103
 
104
 #if ENABLED(X_DUAL_ENDSTOPS)
104
 #if ENABLED(X_DUAL_ENDSTOPS)
105
-  bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
105
+  bool Stepper::locked_X_motor = false, Stepper::locked_X2_motor = false;
106
 #endif
106
 #endif
107
 #if ENABLED(Y_DUAL_ENDSTOPS)
107
 #if ENABLED(Y_DUAL_ENDSTOPS)
108
-  bool Stepper::locked_y_motor = false, Stepper::locked_y2_motor = false;
108
+  bool Stepper::locked_Y_motor = false, Stepper::locked_Y2_motor = false;
109
 #endif
109
 #endif
110
 #if ENABLED(Z_DUAL_ENDSTOPS)
110
 #if ENABLED(Z_DUAL_ENDSTOPS)
111
-  bool Stepper::locked_z_motor = false, Stepper::locked_z2_motor = false;
111
+  bool Stepper::locked_Z_motor = false, Stepper::locked_Z2_motor = false;
112
 #endif
112
 #endif
113
 
113
 
114
 /**
114
 /**
182
 volatile int32_t Stepper::endstops_trigsteps[XYZ];
182
 volatile int32_t Stepper::endstops_trigsteps[XYZ];
183
 
183
 
184
 #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
184
 #if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
185
-  #define LOCKED_X_MOTOR  locked_x_motor
186
-  #define LOCKED_Y_MOTOR  locked_y_motor
187
-  #define LOCKED_Z_MOTOR  locked_z_motor
188
-  #define LOCKED_X2_MOTOR locked_x2_motor
189
-  #define LOCKED_Y2_MOTOR locked_y2_motor
190
-  #define LOCKED_Z2_MOTOR locked_z2_motor
191
-  #define DUAL_ENDSTOP_APPLY_STEP(A,V)                                                                                                      \
192
-    if (performing_homing) {                                                                                                                \
193
-      if (A##_HOME_DIR < 0) {                                                                                                               \
194
-        if (!(TEST(endstops.state(), A##_MIN) && count_direction[_AXIS(A)] < 0) && !LOCKED_##A##_MOTOR) A##_STEP_WRITE(V);     \
195
-        if (!(TEST(endstops.state(), A##2_MIN) && count_direction[_AXIS(A)] < 0) && !LOCKED_##A##2_MOTOR) A##2_STEP_WRITE(V);  \
196
-      }                                                                                                                                     \
197
-      else {                                                                                                                                \
198
-        if (!(TEST(endstops.state(), A##_MAX) && count_direction[_AXIS(A)] > 0) && !LOCKED_##A##_MOTOR) A##_STEP_WRITE(V);     \
199
-        if (!(TEST(endstops.state(), A##2_MAX) && count_direction[_AXIS(A)] > 0) && !LOCKED_##A##2_MOTOR) A##2_STEP_WRITE(V);  \
200
-      }                                                                                                                                     \
201
-    }                                                                                                                                       \
202
-    else {                                                                                                                                  \
203
-      A##_STEP_WRITE(V);                                                                                                                    \
204
-      A##2_STEP_WRITE(V);                                                                                                                   \
185
+  #define DUAL_ENDSTOP_APPLY_STEP(A,V)                                                                                        \
186
+    if (performing_homing) {                                                                                                  \
187
+      if (A##_HOME_DIR < 0) {                                                                                                 \
188
+        if (!(TEST(endstops.state(), A##_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##_motor) A##_STEP_WRITE(V);    \
189
+        if (!(TEST(endstops.state(), A##2_MIN) && count_direction[_AXIS(A)] < 0) && !locked_##A##2_motor) A##2_STEP_WRITE(V); \
190
+      }                                                                                                                       \
191
+      else {                                                                                                                  \
192
+        if (!(TEST(endstops.state(), A##_MAX) && count_direction[_AXIS(A)] > 0) && !locked_##A##_motor) A##_STEP_WRITE(V);    \
193
+        if (!(TEST(endstops.state(), A##2_MAX) && count_direction[_AXIS(A)] > 0) && !locked_##A##2_motor) A##2_STEP_WRITE(V); \
194
+      }                                                                                                                       \
195
+    }                                                                                                                         \
196
+    else {                                                                                                                    \
197
+      A##_STEP_WRITE(V);                                                                                                      \
198
+      A##2_STEP_WRITE(V);                                                                                                     \
205
     }
199
     }
206
 #endif
200
 #endif
207
 
201
 
1150
 HAL_STEP_TIMER_ISR {
1144
 HAL_STEP_TIMER_ISR {
1151
   HAL_timer_isr_prologue(STEP_TIMER_NUM);
1145
   HAL_timer_isr_prologue(STEP_TIMER_NUM);
1152
 
1146
 
1153
-  // Program timer compare for the maximum period, so it does NOT
1154
-  // flag an interrupt while this ISR is running - So changes from small
1155
-  // periods to big periods are respected and the timer does not reset to 0
1156
-  HAL_timer_set_compare(STEP_TIMER_NUM, HAL_TIMER_TYPE_MAX);
1157
-
1158
-  // Call the ISR scheduler
1159
-  hal_timer_t ticks = Stepper::isr_scheduler();
1160
-
1161
-  // Now 'ticks' contains the period to the next Stepper ISR - And we are
1162
-  // sure that the time has not arrived yet - Warrantied by the scheduler
1163
-
1164
-  // Set the next ISR to fire at the proper time
1165
-  HAL_timer_set_compare(STEP_TIMER_NUM, ticks);
1147
+  // Call the ISR
1148
+  Stepper::isr();
1166
 
1149
 
1167
   HAL_timer_isr_epilogue(STEP_TIMER_NUM);
1150
   HAL_timer_isr_epilogue(STEP_TIMER_NUM);
1168
 }
1151
 }
1173
   #define STEP_MULTIPLY(A,B) MultiU24X32toH16(A, B)
1156
   #define STEP_MULTIPLY(A,B) MultiU24X32toH16(A, B)
1174
 #endif
1157
 #endif
1175
 
1158
 
1176
-hal_timer_t Stepper::isr_scheduler() {
1177
-  uint32_t interval;
1159
+void Stepper::isr() {
1160
+
1161
+  // Disable interrupts, to avoid ISR preemption while we reprogram the period
1162
+  DISABLE_ISRS();
1163
+
1164
+  // Program timer compare for the maximum period, so it does NOT
1165
+  // flag an interrupt while this ISR is running - So changes from small
1166
+  // periods to big periods are respected and the timer does not reset to 0
1167
+  HAL_timer_set_compare(STEP_TIMER_NUM, HAL_TIMER_TYPE_MAX);
1178
 
1168
 
1179
   // Count of ticks for the next ISR
1169
   // Count of ticks for the next ISR
1180
   hal_timer_t next_isr_ticks = 0;
1170
   hal_timer_t next_isr_ticks = 0;
1185
   // We need this variable here to be able to use it in the following loop
1175
   // We need this variable here to be able to use it in the following loop
1186
   hal_timer_t min_ticks;
1176
   hal_timer_t min_ticks;
1187
   do {
1177
   do {
1178
+    // Enable ISRs so the USART processing latency is reduced
1179
+    ENABLE_ISRS();
1180
+
1188
     // Run main stepping pulse phase ISR if we have to
1181
     // Run main stepping pulse phase ISR if we have to
1189
     if (!nextMainISR) Stepper::stepper_pulse_phase_isr();
1182
     if (!nextMainISR) Stepper::stepper_pulse_phase_isr();
1190
 
1183
 
1198
     // Run main stepping block processing ISR if we have to
1191
     // Run main stepping block processing ISR if we have to
1199
     if (!nextMainISR) nextMainISR = Stepper::stepper_block_phase_isr();
1192
     if (!nextMainISR) nextMainISR = Stepper::stepper_block_phase_isr();
1200
 
1193
 
1201
-    #if ENABLED(LIN_ADVANCE)
1202
-      // Select the closest interval in time
1203
-      interval = (nextAdvanceISR <= nextMainISR) ? nextAdvanceISR : nextMainISR;
1204
-    #else
1205
-      // The interval is just the remaining time to the stepper ISR
1206
-      interval = nextMainISR;
1207
-    #endif
1194
+    uint32_t interval =
1195
+      #if ENABLED(LIN_ADVANCE)
1196
+        // Select the closest interval in time
1197
+        MIN(nextAdvanceISR, nextMainISR)
1198
+      #else
1199
+        // The interval is just the remaining time to the stepper ISR
1200
+        nextMainISR
1201
+      #endif
1202
+    ;
1208
 
1203
 
1209
     // Limit the value to the maximum possible value of the timer
1204
     // Limit the value to the maximum possible value of the timer
1210
     NOMORE(interval, HAL_TIMER_TYPE_MAX);
1205
     NOMORE(interval, HAL_TIMER_TYPE_MAX);
1244
     next_isr_ticks += interval;
1239
     next_isr_ticks += interval;
1245
 
1240
 
1246
     /**
1241
     /**
1242
+     *  The following section must be done with global interrupts disabled.
1243
+     * We want nothing to interrupt it, as that could mess the calculations
1244
+     * we do for the next value to program in the period register of the
1245
+     * stepper timer and lead to skipped ISRs (if the value we happen to program
1246
+     * is less than the current count due to something preempting between the
1247
+     * read and the write of the new period value).
1248
+     */
1249
+    DISABLE_ISRS();
1250
+
1251
+    /**
1247
      * Get the current tick value + margin
1252
      * Get the current tick value + margin
1248
      * Assuming at least 6µs between calls to this ISR...
1253
      * Assuming at least 6µs between calls to this ISR...
1249
      * On AVR the ISR epilogue is estimated at 40 instructions - close to 2.5µS.
1254
      * On AVR the ISR epilogue is estimated at 40 instructions - close to 2.5µS.
1264
     // Advance pulses if not enough time to wait for the next ISR
1269
     // Advance pulses if not enough time to wait for the next ISR
1265
   } while (next_isr_ticks < min_ticks);
1270
   } while (next_isr_ticks < min_ticks);
1266
 
1271
 
1267
-  // Return the count of ticks for the next ISR
1268
-  return (hal_timer_t)next_isr_ticks;
1272
+  // Now 'next_isr_ticks' contains the period to the next Stepper ISR - And we are
1273
+  // sure that the time has not arrived yet - Warrantied by the scheduler
1274
+
1275
+  // Set the next ISR to fire at the proper time
1276
+  HAL_timer_set_compare(STEP_TIMER_NUM, hal_timer_t(next_isr_ticks));
1277
+
1278
+  // Don't forget to finally reenable interrupts
1279
+  ENABLE_ISRS();
1269
 }
1280
 }
1270
 
1281
 
1271
 /**
1282
 /**

+ 32
- 14
Marlin/src/module/stepper.h View File

81
     static bool abort_current_block;        // Signals to the stepper that current block should be aborted
81
     static bool abort_current_block;        // Signals to the stepper that current block should be aborted
82
 
82
 
83
     #if ENABLED(X_DUAL_ENDSTOPS)
83
     #if ENABLED(X_DUAL_ENDSTOPS)
84
-      static bool locked_x_motor, locked_x2_motor;
84
+      static bool locked_X_motor, locked_X2_motor;
85
     #endif
85
     #endif
86
     #if ENABLED(Y_DUAL_ENDSTOPS)
86
     #if ENABLED(Y_DUAL_ENDSTOPS)
87
-      static bool locked_y_motor, locked_y2_motor;
87
+      static bool locked_Y_motor, locked_Y2_motor;
88
     #endif
88
     #endif
89
     #if ENABLED(Z_DUAL_ENDSTOPS)
89
     #if ENABLED(Z_DUAL_ENDSTOPS)
90
-      static bool locked_z_motor, locked_z2_motor;
90
+      static bool locked_Z_motor, locked_Z2_motor;
91
     #endif
91
     #endif
92
 
92
 
93
     // Counter variables for the Bresenham line tracer
93
     // Counter variables for the Bresenham line tracer
168
     // Interrupt Service Routines
168
     // Interrupt Service Routines
169
 
169
 
170
     // The ISR scheduler
170
     // The ISR scheduler
171
-    static hal_timer_t isr_scheduler();
171
+    static void isr();
172
 
172
 
173
     // The stepper pulse phase ISR
173
     // The stepper pulse phase ISR
174
     static void stepper_pulse_phase_isr();
174
     static void stepper_pulse_phase_isr();
222
 
222
 
223
     #if ENABLED(X_DUAL_ENDSTOPS)
223
     #if ENABLED(X_DUAL_ENDSTOPS)
224
       FORCE_INLINE static void set_homing_flag_x(const bool state) { performing_homing = state; }
224
       FORCE_INLINE static void set_homing_flag_x(const bool state) { performing_homing = state; }
225
-      FORCE_INLINE static void set_x_lock(const bool state) { locked_x_motor = state; }
226
-      FORCE_INLINE static void set_x2_lock(const bool state) { locked_x2_motor = state; }
225
+      FORCE_INLINE static void set_x_lock(const bool state) { locked_X_motor = state; }
226
+      FORCE_INLINE static void set_x2_lock(const bool state) { locked_X2_motor = state; }
227
     #endif
227
     #endif
228
     #if ENABLED(Y_DUAL_ENDSTOPS)
228
     #if ENABLED(Y_DUAL_ENDSTOPS)
229
       FORCE_INLINE static void set_homing_flag_y(const bool state) { performing_homing = state; }
229
       FORCE_INLINE static void set_homing_flag_y(const bool state) { performing_homing = state; }
230
-      FORCE_INLINE static void set_y_lock(const bool state) { locked_y_motor = state; }
231
-      FORCE_INLINE static void set_y2_lock(const bool state) { locked_y2_motor = state; }
230
+      FORCE_INLINE static void set_y_lock(const bool state) { locked_Y_motor = state; }
231
+      FORCE_INLINE static void set_y2_lock(const bool state) { locked_Y2_motor = state; }
232
     #endif
232
     #endif
233
     #if ENABLED(Z_DUAL_ENDSTOPS)
233
     #if ENABLED(Z_DUAL_ENDSTOPS)
234
       FORCE_INLINE static void set_homing_flag_z(const bool state) { performing_homing = state; }
234
       FORCE_INLINE static void set_homing_flag_z(const bool state) { performing_homing = state; }
235
-      FORCE_INLINE static void set_z_lock(const bool state) { locked_z_motor = state; }
236
-      FORCE_INLINE static void set_z2_lock(const bool state) { locked_z2_motor = state; }
235
+      FORCE_INLINE static void set_z_lock(const bool state) { locked_Z_motor = state; }
236
+      FORCE_INLINE static void set_z2_lock(const bool state) { locked_Z2_motor = state; }
237
     #endif
237
     #endif
238
 
238
 
239
     #if ENABLED(BABYSTEPPING)
239
     #if ENABLED(BABYSTEPPING)
247
     // Set the current position in steps
247
     // Set the current position in steps
248
     inline static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
248
     inline static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
249
       planner.synchronize();
249
       planner.synchronize();
250
-      CRITICAL_SECTION_START;
250
+
251
+      // Disable stepper interrupts, to ensure atomic setting of all the position variables
252
+      const bool was_enabled = STEPPER_ISR_ENABLED();
253
+      if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
254
+
255
+      // Set position
251
       _set_position(a, b, c, e);
256
       _set_position(a, b, c, e);
252
-      CRITICAL_SECTION_END;
257
+
258
+      // Reenable Stepper ISR
259
+      if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
253
     }
260
     }
254
 
261
 
255
     inline static void set_position(const AxisEnum a, const int32_t &v) {
262
     inline static void set_position(const AxisEnum a, const int32_t &v) {
256
       planner.synchronize();
263
       planner.synchronize();
257
-      CRITICAL_SECTION_START;
264
+
265
+    #ifdef __AVR__
266
+      // Protect the access to the position. Only required for AVR, as
267
+      //  any 32bit CPU offers atomic access to 32bit variables
268
+      const bool was_enabled = STEPPER_ISR_ENABLED();
269
+      if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
270
+    #endif
271
+
258
       count_position[a] = v;
272
       count_position[a] = v;
259
-      CRITICAL_SECTION_END;
273
+
274
+    #ifdef __AVR__
275
+      // Reenable Stepper ISR
276
+      if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
277
+    #endif
260
     }
278
     }
261
 
279
 
262
   private:
280
   private:

Loading…
Cancel
Save