Fix stepper/planner block handling, race conditions (#11098)
- Allow planner to alter the deceleration phase of the currently executing block. - Remove BUSY flag, as it is NON ATOMIC to set bits in the Stepper ISR and Planner at the same time.
This commit is contained in:
committed by
Scott Lahteine
parent
4d3a9930c5
commit
edb21f349a
@ -107,8 +107,6 @@ Stepper stepper; // Singleton
|
||||
|
||||
// public:
|
||||
|
||||
block_t* Stepper::current_block = NULL; // A pointer to the block currently being traced
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
|
||||
bool Stepper::homing_dual_axis = false;
|
||||
#endif
|
||||
@ -119,6 +117,8 @@ block_t* Stepper::current_block = NULL; // A pointer to the block currently bei
|
||||
|
||||
// private:
|
||||
|
||||
block_t* Stepper::current_block = NULL; // A pointer to the block currently being traced
|
||||
|
||||
uint8_t Stepper::last_direction_bits = 0,
|
||||
Stepper::axis_did_move;
|
||||
|
||||
@ -1665,6 +1665,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
|
||||
acceleration_time = deceleration_time = 0;
|
||||
|
||||
uint8_t oversampling = 0; // Assume we won't use it
|
||||
|
||||
#if ENABLED(ADAPTIVE_STEP_SMOOTHING)
|
||||
// At this point, we must decide if we can use Stepper movement axis smoothing.
|
||||
uint32_t max_rate = current_block->nominal_rate; // Get the maximum rate (maximum event speed)
|
||||
@ -1874,6 +1875,34 @@ uint32_t Stepper::stepper_block_phase_isr() {
|
||||
}
|
||||
#endif // LIN_ADVANCE
|
||||
|
||||
// Check if the given block is busy or not - Must not be called from ISR contexts
|
||||
// The current_block could change in the middle of the read by an Stepper ISR, so
|
||||
// we must explicitly prevent that!
|
||||
bool Stepper::is_block_busy(const block_t* const block) {
|
||||
#ifdef __AVR__
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() asm volatile("": : :"memory");
|
||||
|
||||
// Keep reading until 2 consecutive reads return the same value,
|
||||
// meaning there was no update in-between caused by an interrupt.
|
||||
// This works because stepper ISRs happen at a slower rate than
|
||||
// successive reads of a variable, so 2 consecutive reads with
|
||||
// the same value means no interrupt updated it.
|
||||
block_t* vold, *vnew = current_block;
|
||||
sw_barrier();
|
||||
do {
|
||||
vold = vnew;
|
||||
vnew = current_block;
|
||||
sw_barrier();
|
||||
} while (vold != vnew);
|
||||
#else
|
||||
block_t *vnew = current_block;
|
||||
#endif
|
||||
|
||||
// Return if the block is busy or not
|
||||
return block == vnew;
|
||||
}
|
||||
|
||||
void Stepper::init() {
|
||||
|
||||
// Init Digipot Motor Current
|
||||
|
Reference in New Issue
Block a user