Browse Source

Clean up stepper and babystep (#16857)

Scott Lahteine 4 years ago
parent
commit
0b984519c3
No account linked to committer's email address

+ 2
- 2
Marlin/src/HAL/HAL_ESP32/i2s.cpp View File

@@ -153,8 +153,8 @@ void stepperTask(void* parameter) {
153 153
         remaining--;
154 154
       }
155 155
       else {
156
-        Stepper::stepper_pulse_phase_isr();
157
-        remaining = Stepper::stepper_block_phase_isr();
156
+        Stepper::pulse_phase_isr();
157
+        remaining = Stepper::block_phase_isr();
158 158
       }
159 159
     }
160 160
   }

+ 0
- 8
Marlin/src/feature/babystep.cpp View File

@@ -49,14 +49,6 @@ void Babystep::step_axis(const AxisEnum axis) {
49 49
   }
50 50
 }
51 51
 
52
-void Babystep::task() {
53
-  #if EITHER(BABYSTEP_XY, I2C_POSITION_ENCODERS)
54
-    LOOP_XYZ(axis) step_axis((AxisEnum)axis);
55
-  #else
56
-    step_axis(Z_AXIS);
57
-  #endif
58
-}
59
-
60 52
 void Babystep::add_mm(const AxisEnum axis, const float &mm) {
61 53
   add_steps(axis, mm * planner.settings.axis_steps_per_mm[axis]);
62 54
 }

+ 9
- 1
Marlin/src/feature/babystep.h View File

@@ -55,7 +55,15 @@ public:
55 55
 
56 56
   static void add_steps(const AxisEnum axis, const int16_t distance);
57 57
   static void add_mm(const AxisEnum axis, const float &mm);
58
-  static void task();
58
+
59
+  //
60
+  // Called by the Temperature ISR to
61
+  // apply accumulated babysteps to the axes.
62
+  //
63
+  static inline void task() {
64
+    LOOP_L_N(axis, BS_TODO_AXIS(Z_AXIS)) step_axis((AxisEnum)axis);
65
+  }
66
+
59 67
 private:
60 68
   static void step_axis(const AxisEnum axis);
61 69
 };

+ 101
- 9
Marlin/src/module/planner.cpp View File

@@ -710,6 +710,59 @@ void Planner::init() {
710 710
 #define MINIMAL_STEP_RATE 120
711 711
 
712 712
 /**
713
+ * Get the current block for processing
714
+ * and mark the block as busy.
715
+ * Return nullptr if the buffer is empty
716
+ * or if there is a first-block delay.
717
+ *
718
+ * WARNING: Called from Stepper ISR context!
719
+ */
720
+block_t* Planner::get_current_block() {
721
+  // Get the number of moves in the planner queue so far
722
+  const uint8_t nr_moves = movesplanned();
723
+
724
+  // If there are any moves queued ...
725
+  if (nr_moves) {
726
+
727
+    // If there is still delay of delivery of blocks running, decrement it
728
+    if (delay_before_delivering) {
729
+      --delay_before_delivering;
730
+      // If the number of movements queued is less than 3, and there is still time
731
+      //  to wait, do not deliver anything
732
+      if (nr_moves < 3 && delay_before_delivering) return nullptr;
733
+      delay_before_delivering = 0;
734
+    }
735
+
736
+    // If we are here, there is no excuse to deliver the block
737
+    block_t * const block = &block_buffer[block_buffer_tail];
738
+
739
+    // No trapezoid calculated? Don't execute yet.
740
+    if (TEST(block->flag, BLOCK_BIT_RECALCULATE)) return nullptr;
741
+
742
+    #if HAS_SPI_LCD
743
+      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.
744
+    #endif
745
+
746
+    // As this block is busy, advance the nonbusy block pointer
747
+    block_buffer_nonbusy = next_block_index(block_buffer_tail);
748
+
749
+    // Push block_buffer_planned pointer, if encountered.
750
+    if (block_buffer_tail == block_buffer_planned)
751
+      block_buffer_planned = block_buffer_nonbusy;
752
+
753
+    // Return the block
754
+    return block;
755
+  }
756
+
757
+  // The queue became empty
758
+  #if HAS_SPI_LCD
759
+    clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero.
760
+  #endif
761
+
762
+  return nullptr;
763
+}
764
+
765
+/**
713 766
  * Calculate trapezoid parameters, multiplying the entry- and exit-speeds
714 767
  * by the provided factors.
715 768
  **
@@ -1498,8 +1551,7 @@ void Planner::quick_stop() {
1498 1551
   // must be handled: The tail could change between the read and the assignment
1499 1552
   // so this must be enclosed in a critical section
1500 1553
 
1501
-  const bool was_enabled = STEPPER_ISR_ENABLED();
1502
-  if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
1554
+  const bool was_enabled = stepper.suspend();
1503 1555
 
1504 1556
   // Drop all queue entries
1505 1557
   block_buffer_nonbusy = block_buffer_planned = block_buffer_head = block_buffer_tail;
@@ -1517,7 +1569,7 @@ void Planner::quick_stop() {
1517 1569
   cleaning_buffer_counter = 1000;
1518 1570
 
1519 1571
   // Reenable Stepper ISR
1520
-  if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
1572
+  if (was_enabled) stepper.wake_up();
1521 1573
 
1522 1574
   // And stop the stepper ISR
1523 1575
   stepper.quick_stop();
@@ -1548,13 +1600,12 @@ float Planner::get_axis_position_mm(const AxisEnum axis) {
1548 1600
     if (axis == CORE_AXIS_1 || axis == CORE_AXIS_2) {
1549 1601
 
1550 1602
       // Protect the access to the position.
1551
-      const bool was_enabled = STEPPER_ISR_ENABLED();
1552
-      if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
1603
+      const bool was_enabled = stepper.suspend();
1553 1604
 
1554 1605
       const int32_t p1 = stepper.position(CORE_AXIS_1),
1555 1606
                     p2 = stepper.position(CORE_AXIS_2);
1556 1607
 
1557
-      if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
1608
+      if (was_enabled) stepper.wake_up();
1558 1609
 
1559 1610
       // ((a1+a2)+(a1-a2))/2 -> (a1+a2+a1-a2)/2 -> (a1+a1)/2 -> a1
1560 1611
       // ((a1+a2)-(a1-a2))/2 -> (a1+a2-a1+a2)/2 -> (a2+a2)/2 -> a2
@@ -2004,13 +2055,12 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
2004 2055
 
2005 2056
   #if HAS_SPI_LCD
2006 2057
     // Protect the access to the position.
2007
-    const bool was_enabled = STEPPER_ISR_ENABLED();
2008
-    if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2058
+    const bool was_enabled = stepper.suspend();
2009 2059
 
2010 2060
     block_buffer_runtime_us += segment_time_us;
2011 2061
     block->segment_time_us = segment_time_us;
2012 2062
 
2013
-    if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2063
+    if (was_enabled) stepper.wake_up();
2014 2064
   #endif
2015 2065
 
2016 2066
   block->nominal_speed_sqr = sq(block->millimeters * inverse_secs);   // (mm/sec)^2 Always > 0
@@ -2822,6 +2872,48 @@ void Planner::set_max_jerk(const AxisEnum axis, float targetValue) {
2822 2872
   #endif
2823 2873
 }
2824 2874
 
2875
+#if HAS_SPI_LCD
2876
+
2877
+  uint16_t Planner::block_buffer_runtime() {
2878
+    #ifdef __AVR__
2879
+      // Protect the access to the variable. Only required for AVR, as
2880
+      //  any 32bit CPU offers atomic access to 32bit variables
2881
+      const bool was_enabled = stepper.suspend();
2882
+    #endif
2883
+
2884
+    millis_t bbru = block_buffer_runtime_us;
2885
+
2886
+    #ifdef __AVR__
2887
+      // Reenable Stepper ISR
2888
+      if (was_enabled) stepper.wake_up();
2889
+    #endif
2890
+
2891
+    // To translate µs to ms a division by 1000 would be required.
2892
+    // We introduce 2.4% error here by dividing by 1024.
2893
+    // Doesn't matter because block_buffer_runtime_us is already too small an estimation.
2894
+    bbru >>= 10;
2895
+    // limit to about a minute.
2896
+    NOMORE(bbru, 0xFFFFul);
2897
+    return bbru;
2898
+  }
2899
+
2900
+  void Planner::clear_block_buffer_runtime() {
2901
+    #ifdef __AVR__
2902
+      // Protect the access to the variable. Only required for AVR, as
2903
+      //  any 32bit CPU offers atomic access to 32bit variables
2904
+      const bool was_enabled = stepper.suspend();
2905
+    #endif
2906
+
2907
+    block_buffer_runtime_us = 0;
2908
+
2909
+    #ifdef __AVR__
2910
+      // Reenable Stepper ISR
2911
+      if (was_enabled) stepper.wake_up();
2912
+    #endif
2913
+  }
2914
+
2915
+#endif
2916
+
2825 2917
 #if ENABLED(AUTOTEMP)
2826 2918
 
2827 2919
   void Planner::autotemp_M104_M109() {

+ 8
- 89
Marlin/src/module/planner.h View File

@@ -763,60 +763,18 @@ class Planner {
763 763
     FORCE_INLINE static bool has_blocks_queued() { return (block_buffer_head != block_buffer_tail); }
764 764
 
765 765
     /**
766
-     * The current block. nullptr if the buffer is empty.
767
-     * This also marks the block as busy.
766
+     * Get the current block for processing
767
+     * and mark the block as busy.
768
+     * Return nullptr if the buffer is empty
769
+     * or if there is a first-block delay.
770
+     *
768 771
      * WARNING: Called from Stepper ISR context!
769 772
      */
770
-    static block_t* get_current_block() {
771
-
772
-      // Get the number of moves in the planner queue so far
773
-      const uint8_t nr_moves = movesplanned();
774
-
775
-      // If there are any moves queued ...
776
-      if (nr_moves) {
777
-
778
-        // If there is still delay of delivery of blocks running, decrement it
779
-        if (delay_before_delivering) {
780
-          --delay_before_delivering;
781
-          // If the number of movements queued is less than 3, and there is still time
782
-          //  to wait, do not deliver anything
783
-          if (nr_moves < 3 && delay_before_delivering) return nullptr;
784
-          delay_before_delivering = 0;
785
-        }
786
-
787
-        // If we are here, there is no excuse to deliver the block
788
-        block_t * const block = &block_buffer[block_buffer_tail];
789
-
790
-        // No trapezoid calculated? Don't execute yet.
791
-        if (TEST(block->flag, BLOCK_BIT_RECALCULATE)) return nullptr;
792
-
793
-        #if HAS_SPI_LCD
794
-          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.
795
-        #endif
796
-
797
-        // As this block is busy, advance the nonbusy block pointer
798
-        block_buffer_nonbusy = next_block_index(block_buffer_tail);
799
-
800
-        // Push block_buffer_planned pointer, if encountered.
801
-        if (block_buffer_tail == block_buffer_planned)
802
-          block_buffer_planned = block_buffer_nonbusy;
803
-
804
-        // Return the block
805
-        return block;
806
-      }
807
-
808
-      // The queue became empty
809
-      #if HAS_SPI_LCD
810
-        clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero.
811
-      #endif
812
-
813
-      return nullptr;
814
-    }
773
+    static block_t* get_current_block();
815 774
 
816 775
     /**
817 776
      * "Discard" the block and "release" the memory.
818 777
      * Called when the current block is no longer needed.
819
-     * NB: There MUST be a current block to call this function!!
820 778
      */
821 779
     FORCE_INLINE static void discard_current_block() {
822 780
       if (has_blocks_queued())
@@ -824,47 +782,8 @@ class Planner {
824 782
     }
825 783
 
826 784
     #if HAS_SPI_LCD
827
-
828
-      static uint16_t block_buffer_runtime() {
829
-        #ifdef __AVR__
830
-          // Protect the access to the variable. Only required for AVR, as
831
-          //  any 32bit CPU offers atomic access to 32bit variables
832
-          bool was_enabled = STEPPER_ISR_ENABLED();
833
-          if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
834
-        #endif
835
-
836
-        millis_t bbru = block_buffer_runtime_us;
837
-
838
-        #ifdef __AVR__
839
-          // Reenable Stepper ISR
840
-          if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
841
-        #endif
842
-
843
-        // To translate µs to ms a division by 1000 would be required.
844
-        // We introduce 2.4% error here by dividing by 1024.
845
-        // Doesn't matter because block_buffer_runtime_us is already too small an estimation.
846
-        bbru >>= 10;
847
-        // limit to about a minute.
848
-        NOMORE(bbru, 0xFFFFul);
849
-        return bbru;
850
-      }
851
-
852
-      static void clear_block_buffer_runtime() {
853
-        #ifdef __AVR__
854
-          // Protect the access to the variable. Only required for AVR, as
855
-          //  any 32bit CPU offers atomic access to 32bit variables
856
-          bool was_enabled = STEPPER_ISR_ENABLED();
857
-          if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
858
-        #endif
859
-
860
-        block_buffer_runtime_us = 0;
861
-
862
-        #ifdef __AVR__
863
-          // Reenable Stepper ISR
864
-          if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
865
-        #endif
866
-      }
867
-
785
+      static uint16_t block_buffer_runtime();
786
+      static void clear_block_buffer_runtime();
868 787
     #endif
869 788
 
870 789
     #if ENABLED(AUTOTEMP)

+ 93
- 80
Marlin/src/module/stepper.cpp View File

@@ -203,11 +203,8 @@ uint32_t Stepper::advance_divisor = 0,
203 203
   bool Stepper::bezier_2nd_half;    // =false If Bézier curve has been initialized or not
204 204
 #endif
205 205
 
206
-uint32_t Stepper::nextMainISR = 0;
207
-
208 206
 #if ENABLED(LIN_ADVANCE)
209 207
 
210
-  constexpr uint32_t LA_ADV_NEVER = 0xFFFFFFFF;
211 208
   uint32_t Stepper::nextAdvanceISR = LA_ADV_NEVER,
212 209
            Stepper::LA_isr_rate = LA_ADV_NEVER;
213 210
   uint16_t Stepper::LA_current_adv_steps = 0,
@@ -402,13 +399,13 @@ constexpr uint32_t NS_TO_PULSE_TIMER_TICKS(uint32_t NS) { return (NS + (NS_PER_P
402 399
 #define PULSE_HIGH_TICK_COUNT hal_timer_t(NS_TO_PULSE_TIMER_TICKS(_MIN_PULSE_HIGH_NS - _MIN(_MIN_PULSE_HIGH_NS, TIMER_SETUP_NS)))
403 400
 #define PULSE_LOW_TICK_COUNT hal_timer_t(NS_TO_PULSE_TIMER_TICKS(_MIN_PULSE_LOW_NS - _MIN(_MIN_PULSE_LOW_NS, TIMER_SETUP_NS)))
404 401
 
405
-#define USING_TIMED_PULSE() hal_timer_t end_tick_count = 0
406
-#define START_TIMED_PULSE(DIR) (end_tick_count = HAL_timer_get_count(PULSE_TIMER_NUM) + PULSE_##DIR##_TICK_COUNT)
407
-#define AWAIT_TIMED_PULSE() while (HAL_timer_get_count(PULSE_TIMER_NUM) < end_tick_count) { }
402
+#define USING_TIMED_PULSE() hal_timer_t start_pulse_count = 0
403
+#define START_TIMED_PULSE(DIR) (start_pulse_count = HAL_timer_get_count(PULSE_TIMER_NUM))
404
+#define AWAIT_TIMED_PULSE(DIR) while (PULSE_##DIR##_TICK_COUNT > HAL_timer_get_count(PULSE_TIMER_NUM) - start_pulse_count) { }
408 405
 #define START_HIGH_PULSE()  START_TIMED_PULSE(HIGH)
406
+#define AWAIT_HIGH_PULSE()  AWAIT_TIMED_PULSE(HIGH)
409 407
 #define START_LOW_PULSE()   START_TIMED_PULSE(LOW)
410
-#define AWAIT_HIGH_PULSE()  AWAIT_TIMED_PULSE()
411
-#define AWAIT_LOW_PULSE()   AWAIT_TIMED_PULSE()
408
+#define AWAIT_LOW_PULSE()   AWAIT_TIMED_PULSE(LOW)
412 409
 
413 410
 #if MINIMUM_STEPPER_PRE_DIR_DELAY > 0
414 411
   #define DIR_WAIT_BEFORE() DELAY_NS(MINIMUM_STEPPER_PRE_DIR_DELAY)
@@ -422,11 +419,6 @@ constexpr uint32_t NS_TO_PULSE_TIMER_TICKS(uint32_t NS) { return (NS + (NS_PER_P
422 419
   #define DIR_WAIT_AFTER()
423 420
 #endif
424 421
 
425
-void Stepper::wake_up() {
426
-  // TCNT1 = 0;
427
-  ENABLE_STEPPER_DRIVER_INTERRUPT();
428
-}
429
-
430 422
 /**
431 423
  * Set the stepper direction of each axis
432 424
  *
@@ -1334,6 +1326,9 @@ HAL_STEP_TIMER_ISR() {
1334 1326
 #endif
1335 1327
 
1336 1328
 void Stepper::isr() {
1329
+
1330
+  static uint32_t nextMainISR = 0;  // Interval until the next main Stepper Pulse phase (0 = Now)
1331
+
1337 1332
   #ifndef __AVR__
1338 1333
     // Disable interrupts, to avoid ISR preemption while we reprogram the period
1339 1334
     // (AVR enters the ISR with global interrupts disabled, so no need to do it here)
@@ -1357,35 +1352,35 @@ void Stepper::isr() {
1357 1352
     // Enable ISRs to reduce USART processing latency
1358 1353
     ENABLE_ISRS();
1359 1354
 
1360
-    // Run main stepping pulse phase ISR if we have to
1361
-    if (!nextMainISR) Stepper::stepper_pulse_phase_isr();
1355
+    if (!nextMainISR) pulse_phase_isr();                            // 0 = Do coordinated axes Stepper pulses
1362 1356
 
1363 1357
     #if ENABLED(LIN_ADVANCE)
1364
-      // Run linear advance stepper ISR if we have to
1365
-      if (!nextAdvanceISR) nextAdvanceISR = Stepper::advance_isr();
1358
+      if (!nextAdvanceISR) nextAdvanceISR = advance_isr();          // 0 = Do Linear Advance E Stepper pulses
1366 1359
     #endif
1367 1360
 
1368 1361
     // ^== Time critical. NOTHING besides pulse generation should be above here!!!
1369 1362
 
1370
-    // Run main stepping block processing ISR if we have to
1371
-    if (!nextMainISR) nextMainISR = Stepper::stepper_block_phase_isr();
1363
+    if (!nextMainISR) nextMainISR = block_phase_isr();  // Manage acc/deceleration, get next block
1372 1364
 
1373
-    uint32_t interval =
1365
+    // Get the interval to the next ISR call
1366
+    const uint32_t interval = _MIN(
1367
+      nextMainISR                                       // Time until the next Stepper ISR
1374 1368
       #if ENABLED(LIN_ADVANCE)
1375
-        _MIN(nextAdvanceISR, nextMainISR)  // Nearest time interval
1376
-      #else
1377
-        nextMainISR                       // Remaining stepper ISR time
1369
+        , nextAdvanceISR                                // Come back early for Linear Advance?
1378 1370
       #endif
1379
-    ;
1371
+      , uint32_t(HAL_TIMER_TYPE_MAX)                    // Come back in a very long time
1372
+    );
1380 1373
 
1381
-    // Limit the value to the maximum possible value of the timer
1382
-    NOMORE(interval, uint32_t(HAL_TIMER_TYPE_MAX));
1374
+    //
1375
+    // Compute remaining time for each ISR phase
1376
+    //     NEVER : The phase is idle
1377
+    //      Zero : The phase will occur on the next ISR call
1378
+    //  Non-zero : The phase will occur on a future ISR call
1379
+    //
1383 1380
 
1384
-    // Compute the time remaining for the main isr
1385 1381
     nextMainISR -= interval;
1386 1382
 
1387 1383
     #if ENABLED(LIN_ADVANCE)
1388
-      // Compute the time remaining for the advance isr
1389 1384
       if (nextAdvanceISR != LA_ADV_NEVER) nextAdvanceISR -= interval;
1390 1385
     #endif
1391 1386
 
@@ -1471,7 +1466,7 @@ void Stepper::isr() {
1471 1466
  * call to this method that might cause variation in the timing. The aim
1472 1467
  * is to keep pulse timing as regular as possible.
1473 1468
  */
1474
-void Stepper::stepper_pulse_phase_isr() {
1469
+void Stepper::pulse_phase_isr() {
1475 1470
 
1476 1471
   // If we must abort the current block, do so!
1477 1472
   if (abort_current_block) {
@@ -1548,7 +1543,7 @@ void Stepper::stepper_pulse_phase_isr() {
1548 1543
           // Don't step E here - But remember the number of steps to perform
1549 1544
           motor_direction(E_AXIS) ? --LA_steps : ++LA_steps;
1550 1545
         #else
1551
-          step_needed.e = delta_error.e >= 0;
1546
+          step_needed.e = true;
1552 1547
         #endif
1553 1548
       }
1554 1549
     #elif HAS_E0_STEP
@@ -1604,20 +1599,14 @@ void Stepper::stepper_pulse_phase_isr() {
1604 1599
 
1605 1600
     #if DISABLED(LIN_ADVANCE)
1606 1601
       #if ENABLED(MIXING_EXTRUDER)
1607
-
1608 1602
         if (delta_error.e >= 0) {
1609 1603
           delta_error.e -= advance_divisor;
1610 1604
           E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN);
1611 1605
         }
1612
-
1613
-      #else // !MIXING_EXTRUDER
1614
-
1615
-        #if HAS_E0_STEP
1616
-          PULSE_STOP(E);
1617
-        #endif
1618
-
1619
-      #endif  // !MIXING_EXTRUDER
1620
-    #endif // !LIN_ADVANCE
1606
+      #elif HAS_E0_STEP
1607
+        PULSE_STOP(E);
1608
+      #endif
1609
+    #endif
1621 1610
 
1622 1611
     #if ISR_MULTI_STEPS
1623 1612
       if (events_to_do) START_LOW_PULSE();
@@ -1630,10 +1619,10 @@ void Stepper::stepper_pulse_phase_isr() {
1630 1619
 // properly schedules blocks from the planner. This is executed after creating
1631 1620
 // the step pulses, so it is not time critical, as pulses are already done.
1632 1621
 
1633
-uint32_t Stepper::stepper_block_phase_isr() {
1622
+uint32_t Stepper::block_phase_isr() {
1634 1623
 
1635
-  // If no queued movements, just wait 1ms for the next move
1636
-  uint32_t interval = (STEPPER_TIMER_RATE) / 1000;
1624
+  // If no queued movements, just wait 1ms for the next block
1625
+  uint32_t interval = (STEPPER_TIMER_RATE) / 1000UL;
1637 1626
 
1638 1627
   // If there is a current block
1639 1628
   if (current_block) {
@@ -1667,16 +1656,14 @@ uint32_t Stepper::stepper_block_phase_isr() {
1667 1656
         // acc_step_rate is in steps/second
1668 1657
 
1669 1658
         // step_rate to timer interval and steps per stepper isr
1670
-        interval = calc_timer_interval(acc_step_rate, oversampling_factor, &steps_per_isr);
1659
+        interval = calc_timer_interval(acc_step_rate, &steps_per_isr);
1671 1660
         acceleration_time += interval;
1672 1661
 
1673 1662
         #if ENABLED(LIN_ADVANCE)
1674
-          if (LA_use_advance_lead) {
1675
-            // Fire ISR if final adv_rate is reached
1676
-            if (LA_steps && LA_isr_rate != current_block->advance_speed) nextAdvanceISR = 0;
1677
-          }
1678
-          else if (LA_steps) nextAdvanceISR = 0;
1679
-        #endif // LIN_ADVANCE
1663
+          // Fire ISR if final adv_rate is reached
1664
+          if (LA_steps && (!LA_use_advance_lead || LA_isr_rate != current_block->advance_speed))
1665
+            initiateLA();
1666
+        #endif
1680 1667
       }
1681 1668
       // Are we in Deceleration phase ?
1682 1669
       else if (step_events_completed > decelerate_after) {
@@ -1712,32 +1699,32 @@ uint32_t Stepper::stepper_block_phase_isr() {
1712 1699
         // step_rate is in steps/second
1713 1700
 
1714 1701
         // step_rate to timer interval and steps per stepper isr
1715
-        interval = calc_timer_interval(step_rate, oversampling_factor, &steps_per_isr);
1702
+        interval = calc_timer_interval(step_rate, &steps_per_isr);
1716 1703
         deceleration_time += interval;
1717 1704
 
1718 1705
         #if ENABLED(LIN_ADVANCE)
1719 1706
           if (LA_use_advance_lead) {
1720 1707
             // Wake up eISR on first deceleration loop and fire ISR if final adv_rate is reached
1721 1708
             if (step_events_completed <= decelerate_after + steps_per_isr || (LA_steps && LA_isr_rate != current_block->advance_speed)) {
1722
-              nextAdvanceISR = 0;
1709
+              initiateLA();
1723 1710
               LA_isr_rate = current_block->advance_speed;
1724 1711
             }
1725 1712
           }
1726
-          else if (LA_steps) nextAdvanceISR = 0;
1727
-        #endif // LIN_ADVANCE
1713
+          else if (LA_steps) initiateLA();
1714
+        #endif
1728 1715
       }
1729 1716
       // We must be in cruise phase otherwise
1730 1717
       else {
1731 1718
 
1732 1719
         #if ENABLED(LIN_ADVANCE)
1733 1720
           // If there are any esteps, fire the next advance_isr "now"
1734
-          if (LA_steps && LA_isr_rate != current_block->advance_speed) nextAdvanceISR = 0;
1721
+          if (LA_steps && LA_isr_rate != current_block->advance_speed) initiateLA();
1735 1722
         #endif
1736 1723
 
1737 1724
         // Calculate the ticks_nominal for this nominal speed, if not done yet
1738 1725
         if (ticks_nominal < 0) {
1739 1726
           // step_rate to timer interval and loops for the nominal speed
1740
-          ticks_nominal = calc_timer_interval(current_block->nominal_rate, oversampling_factor, &steps_per_isr);
1727
+          ticks_nominal = calc_timer_interval(current_block->nominal_rate, &steps_per_isr);
1741 1728
         }
1742 1729
 
1743 1730
         // The timer interval is just the nominal value for the nominal speed
@@ -1846,17 +1833,17 @@ uint32_t Stepper::stepper_block_phase_isr() {
1846 1833
       // No acceleration / deceleration time elapsed so far
1847 1834
       acceleration_time = deceleration_time = 0;
1848 1835
 
1849
-      uint8_t oversampling = 0;                         // Assume we won't use it
1836
+      uint8_t oversampling = 0;                           // Assume no axis smoothing (via oversampling)
1850 1837
 
1851 1838
       #if ENABLED(ADAPTIVE_STEP_SMOOTHING)
1852
-        // At this point, we must decide if we can use Stepper movement axis smoothing.
1839
+        // Decide if axis smoothing is possible
1853 1840
         uint32_t max_rate = current_block->nominal_rate;  // Get the maximum rate (maximum event speed)
1854
-        while (max_rate < MIN_STEP_ISR_FREQUENCY) {
1855
-          max_rate <<= 1;
1856
-          if (max_rate >= MAX_STEP_ISR_FREQUENCY_1X) break;
1857
-          ++oversampling;
1841
+        while (max_rate < MIN_STEP_ISR_FREQUENCY) {         // As long as more ISRs are possible...
1842
+          max_rate <<= 1;                                   // Try to double the rate
1843
+          if (max_rate >= MAX_STEP_ISR_FREQUENCY_1X) break; // Don't exceed the estimated ISR limit
1844
+          ++oversampling;                                   // Increase the oversampling (used for left-shift)
1858 1845
         }
1859
-        oversampling_factor = oversampling;
1846
+        oversampling_factor = oversampling;                 // For all timer interval calculations
1860 1847
       #endif
1861 1848
 
1862 1849
       // Based on the oversampling factor, do the calculations
@@ -1894,8 +1881,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
1894 1881
         if ((LA_use_advance_lead = current_block->use_advance_lead)) {
1895 1882
           LA_final_adv_steps = current_block->final_adv_steps;
1896 1883
           LA_max_adv_steps = current_block->max_adv_steps;
1897
-          //Start the ISR
1898
-          nextAdvanceISR = 0;
1884
+          initiateLA(); // Start the ISR
1899 1885
           LA_isr_rate = current_block->advance_speed;
1900 1886
         }
1901 1887
         else LA_isr_rate = LA_ADV_NEVER;
@@ -1954,7 +1940,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
1954 1940
       #endif
1955 1941
 
1956 1942
       // Calculate the initial timer interval
1957
-      interval = calc_timer_interval(current_block->initial_rate, oversampling_factor, &steps_per_isr);
1943
+      interval = calc_timer_interval(current_block->initial_rate, &steps_per_isr);
1958 1944
     }
1959 1945
   }
1960 1946
 
@@ -2054,6 +2040,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
2054 2040
 
2055 2041
     return interval;
2056 2042
   }
2043
+
2057 2044
 #endif // LIN_ADVANCE
2058 2045
 
2059 2046
 // Check if the given block is busy or not - Must not be called from ISR contexts
@@ -2093,7 +2080,7 @@ void Stepper::init() {
2093 2080
       digipot_motor = 255 * (motor_current[i] / 2.5);
2094 2081
       dac084s085::setValue(i, digipot_motor);
2095 2082
     }
2096
-  #endif//MB(ALLIGATOR)
2083
+  #endif
2097 2084
 
2098 2085
   // Init Microstepping Pins
2099 2086
   #if HAS_MICROSTEPS
@@ -2287,7 +2274,7 @@ void Stepper::init() {
2287 2274
 
2288 2275
   #if DISABLED(I2S_STEPPER_STREAM)
2289 2276
     HAL_timer_start(STEP_TIMER_NUM, 122); // Init Stepper ISR to 122 Hz for quick starting
2290
-    ENABLE_STEPPER_DRIVER_INTERRUPT();
2277
+    wake_up();
2291 2278
     sei();
2292 2279
   #endif
2293 2280
 
@@ -2341,19 +2328,43 @@ int32_t Stepper::position(const AxisEnum axis) {
2341 2328
   #ifdef __AVR__
2342 2329
     // Protect the access to the position. Only required for AVR, as
2343 2330
     //  any 32bit CPU offers atomic access to 32bit variables
2344
-    const bool was_enabled = STEPPER_ISR_ENABLED();
2345
-    if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2331
+    const bool was_enabled = suspend();
2346 2332
   #endif
2347 2333
 
2348 2334
   const int32_t v = count_position[axis];
2349 2335
 
2350 2336
   #ifdef __AVR__
2351 2337
     // Reenable Stepper ISR
2352
-    if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2338
+    if (was_enabled) wake_up();
2353 2339
   #endif
2354 2340
   return v;
2355 2341
 }
2356 2342
 
2343
+// Set the current position in steps
2344
+void Stepper::set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
2345
+  planner.synchronize();
2346
+  const bool was_enabled = suspend();
2347
+  _set_position(a, b, c, e);
2348
+  if (was_enabled) wake_up();
2349
+}
2350
+
2351
+void Stepper::set_axis_position(const AxisEnum a, const int32_t &v) {
2352
+  planner.synchronize();
2353
+
2354
+  #ifdef __AVR__
2355
+    // Protect the access to the position. Only required for AVR, as
2356
+    //  any 32bit CPU offers atomic access to 32bit variables
2357
+    const bool was_enabled = suspend();
2358
+  #endif
2359
+
2360
+  count_position[a] = v;
2361
+
2362
+  #ifdef __AVR__
2363
+    // Reenable Stepper ISR
2364
+    if (was_enabled) wake_up();
2365
+  #endif
2366
+}
2367
+
2357 2368
 // Signal endstops were triggered - This function can be called from
2358 2369
 // an ISR context  (Temperature, Stepper or limits ISR), so we must
2359 2370
 // be very careful here. If the interrupt being preempted was the
@@ -2362,8 +2373,7 @@ int32_t Stepper::position(const AxisEnum axis) {
2362 2373
 // is properly canceled
2363 2374
 void Stepper::endstop_triggered(const AxisEnum axis) {
2364 2375
 
2365
-  const bool was_enabled = STEPPER_ISR_ENABLED();
2366
-  if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2376
+  const bool was_enabled = suspend();
2367 2377
   endstops_trigsteps[axis] = (
2368 2378
     #if IS_CORE
2369 2379
       (axis == CORE_AXIS_2
@@ -2378,22 +2388,21 @@ void Stepper::endstop_triggered(const AxisEnum axis) {
2378 2388
   // Discard the rest of the move if there is a current block
2379 2389
   quick_stop();
2380 2390
 
2381
-  if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2391
+  if (was_enabled) wake_up();
2382 2392
 }
2383 2393
 
2384 2394
 int32_t Stepper::triggered_position(const AxisEnum axis) {
2385 2395
   #ifdef __AVR__
2386 2396
     // Protect the access to the position. Only required for AVR, as
2387 2397
     //  any 32bit CPU offers atomic access to 32bit variables
2388
-    const bool was_enabled = STEPPER_ISR_ENABLED();
2389
-    if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2398
+    const bool was_enabled = suspend();
2390 2399
   #endif
2391 2400
 
2392 2401
   const int32_t v = endstops_trigsteps[axis];
2393 2402
 
2394 2403
   #ifdef __AVR__
2395 2404
     // Reenable Stepper ISR
2396
-    if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2405
+    if (was_enabled) wake_up();
2397 2406
   #endif
2398 2407
 
2399 2408
   return v;
@@ -2403,14 +2412,13 @@ void Stepper::report_positions() {
2403 2412
 
2404 2413
   #ifdef __AVR__
2405 2414
     // Protect the access to the position.
2406
-    const bool was_enabled = STEPPER_ISR_ENABLED();
2407
-    if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
2415
+    const bool was_enabled = suspend();
2408 2416
   #endif
2409 2417
 
2410 2418
   const xyz_long_t pos = count_position;
2411 2419
 
2412 2420
   #ifdef __AVR__
2413
-    if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
2421
+    if (was_enabled) wake_up();
2414 2422
   #endif
2415 2423
 
2416 2424
   #if CORE_IS_XY || CORE_IS_XZ || ENABLED(DELTA) || IS_SCARA
@@ -2571,16 +2579,21 @@ void Stepper::report_positions() {
2571 2579
           Z_STEP_WRITE(INVERT_Z_STEP_PIN);
2572 2580
 
2573 2581
           // Restore direction bits
2582
+          DIR_WAIT_BEFORE();
2583
+
2574 2584
           X_DIR_WRITE(old_dir.x);
2575 2585
           Y_DIR_WRITE(old_dir.y);
2576 2586
           Z_DIR_WRITE(old_dir.z);
2577 2587
 
2588
+          DIR_WAIT_AFTER();
2589
+
2578 2590
         #endif
2579 2591
 
2580 2592
       } break;
2581 2593
 
2582 2594
       default: break;
2583 2595
     }
2596
+
2584 2597
     sei();
2585 2598
   }
2586 2599
 

+ 28
- 47
Marlin/src/module/stepper.h View File

@@ -321,13 +321,13 @@ class Stepper {
321 321
       static bool bezier_2nd_half; // If Bézier curve has been initialized or not
322 322
     #endif
323 323
 
324
-    static uint32_t nextMainISR;   // time remaining for the next Step ISR
325 324
     #if ENABLED(LIN_ADVANCE)
325
+      static constexpr uint32_t LA_ADV_NEVER = 0xFFFFFFFF;
326 326
       static uint32_t nextAdvanceISR, LA_isr_rate;
327 327
       static uint16_t LA_current_adv_steps, LA_final_adv_steps, LA_max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
328 328
       static int8_t LA_steps;
329 329
       static bool LA_use_advance_lead;
330
-    #endif // LIN_ADVANCE
330
+    #endif
331 331
 
332 332
     static int32_t ticks_nominal;
333 333
     #if DISABLED(S_CURVE_ACCELERATION)
@@ -351,28 +351,36 @@ class Stepper {
351 351
 
352 352
   public:
353 353
 
354
-    //
355
-    // Constructor / initializer
356
-    //
357
-    Stepper() {};
358
-
359 354
     // Initialize stepper hardware
360 355
     static void init();
361 356
 
362
-    // Interrupt Service Routines
357
+    // Interrupt Service Routine and phases
358
+
359
+    // The stepper subsystem goes to sleep when it runs out of things to execute.
360
+    // Call this to notify the subsystem that it is time to go to work.
361
+    static inline void wake_up() { ENABLE_STEPPER_DRIVER_INTERRUPT(); }
362
+
363
+    static inline bool is_awake() { return STEPPER_ISR_ENABLED(); }
364
+
365
+    static inline bool suspend() {
366
+      const bool awake = is_awake();
367
+      if (awake) DISABLE_STEPPER_DRIVER_INTERRUPT();
368
+      return awake;
369
+    }
363 370
 
364 371
     // The ISR scheduler
365 372
     static void isr();
366 373
 
367
-    // The stepper pulse phase ISR
368
-    static void stepper_pulse_phase_isr();
374
+    // The stepper pulse ISR phase
375
+    static void pulse_phase_isr();
369 376
 
370
-    // The stepper block processing phase ISR
371
-    static uint32_t stepper_block_phase_isr();
377
+    // The stepper block processing ISR phase
378
+    static uint32_t block_phase_isr();
372 379
 
373 380
     #if ENABLED(LIN_ADVANCE)
374
-      // The Linear advance stepper ISR
381
+      // The Linear advance ISR phase
375 382
       static uint32_t advance_isr();
383
+      FORCE_INLINE static void initiateLA() { nextAdvanceISR = 0; }
376 384
     #endif
377 385
 
378 386
     // Check if the given block is busy or not - Must not be called from ISR contexts
@@ -381,13 +389,14 @@ class Stepper {
381 389
     // Get the position of a stepper, in steps
382 390
     static int32_t position(const AxisEnum axis);
383 391
 
392
+    // Set the current position in steps
393
+    static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
394
+    static inline void set_position(const xyze_long_t &abce) { set_position(abce.a, abce.b, abce.c, abce.e); }
395
+    static void set_axis_position(const AxisEnum a, const int32_t &v);
396
+
384 397
     // Report the positions of the steppers, in steps
385 398
     static void report_positions();
386 399
 
387
-    // The stepper subsystem goes to sleep when it runs out of things to execute. Call this
388
-    // to notify the subsystem that it is time to go to work.
389
-    static void wake_up();
390
-
391 400
     // Quickly stop all steppers
392 401
     FORCE_INLINE static void quick_stop() { abort_current_block = true; }
393 402
 
@@ -453,34 +462,6 @@ class Stepper {
453 462
       static void refresh_motor_power();
454 463
     #endif
455 464
 
456
-    // Set the current position in steps
457
-    static inline void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
458
-      planner.synchronize();
459
-      const bool was_enabled = STEPPER_ISR_ENABLED();
460
-      if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
461
-      _set_position(a, b, c, e);
462
-      if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
463
-    }
464
-    static inline void set_position(const xyze_long_t &abce) { set_position(abce.a, abce.b, abce.c, abce.e); }
465
-
466
-    static inline void set_axis_position(const AxisEnum a, const int32_t &v) {
467
-      planner.synchronize();
468
-
469
-      #ifdef __AVR__
470
-        // Protect the access to the position. Only required for AVR, as
471
-        //  any 32bit CPU offers atomic access to 32bit variables
472
-        const bool was_enabled = STEPPER_ISR_ENABLED();
473
-        if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
474
-      #endif
475
-
476
-      count_position[a] = v;
477
-
478
-      #ifdef __AVR__
479
-        // Reenable Stepper ISR
480
-        if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
481
-      #endif
482
-    }
483
-
484 465
     // Set direction bits for all steppers
485 466
     static void set_directions();
486 467
 
@@ -490,11 +471,11 @@ class Stepper {
490 471
     static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
491 472
     FORCE_INLINE static void _set_position(const abce_long_t &spos) { _set_position(spos.a, spos.b, spos.c, spos.e); }
492 473
 
493
-    FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t scale, uint8_t* loops) {
474
+    FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t* loops) {
494 475
       uint32_t timer;
495 476
 
496 477
       // Scale the frequency, as requested by the caller
497
-      step_rate <<= scale;
478
+      step_rate <<= oversampling_factor;
498 479
 
499 480
       uint8_t multistep = 1;
500 481
       #if DISABLED(DISABLE_MULTI_STEPPING)

+ 1
- 4
Marlin/src/module/temperature.cpp View File

@@ -65,15 +65,12 @@
65 65
   #include "../libs/private_spi.h"
66 66
 #endif
67 67
 
68
-#if EITHER(BABYSTEPPING, PID_EXTRUSION_SCALING)
68
+#if ENABLED(PID_EXTRUSION_SCALING)
69 69
   #include "stepper.h"
70 70
 #endif
71 71
 
72 72
 #if ENABLED(BABYSTEPPING)
73 73
   #include "../feature/babystep.h"
74
-  #if ENABLED(BABYSTEP_ALWAYS_AVAILABLE)
75
-    #include "../gcode/gcode.h"
76
-  #endif
77 74
 #endif
78 75
 
79 76
 #include "printcounter.h"

Loading…
Cancel
Save