Fix stepper/planner block handling, race conditions (#11136)
- 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. Co-Authored-By: ejtagle <ejtagle@hotmail.com>
This commit is contained in:
@@ -96,8 +96,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
|
||||
@@ -108,6 +106,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;
|
||||
|
||||
@@ -1128,6 +1128,8 @@ HAL_STEP_TIMER_ISR {
|
||||
#define STEP_MULTIPLY(A,B) MultiU24X32toH16(A, B)
|
||||
|
||||
void Stepper::isr() {
|
||||
DISABLE_ISRS();
|
||||
|
||||
// Program timer compare for the maximum period, so it does NOT
|
||||
// flag an interrupt while this ISR is running - So changes from small
|
||||
// periods to big periods are respected and the timer does not reset to 0
|
||||
@@ -1615,6 +1617,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)
|
||||
@@ -1824,6 +1827,29 @@ 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) {
|
||||
#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);
|
||||
|
||||
// Return if the block is busy or not
|
||||
return block == vnew;
|
||||
}
|
||||
|
||||
void Stepper::init() {
|
||||
|
||||
// Init Digipot Motor Current
|
||||
@@ -2021,7 +2047,9 @@ void Stepper::_set_position(const int32_t &a, const int32_t &b, const int32_t &c
|
||||
int32_t Stepper::position(const AxisEnum axis) {
|
||||
const bool was_enabled = STEPPER_ISR_ENABLED();
|
||||
if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
const int32_t v = count_position[axis];
|
||||
|
||||
if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
return v;
|
||||
}
|
||||
@@ -2059,8 +2087,11 @@ void Stepper::endstop_triggered(const AxisEnum axis) {
|
||||
int32_t Stepper::triggered_position(const AxisEnum axis) {
|
||||
const bool was_enabled = STEPPER_ISR_ENABLED();
|
||||
if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
const int32_t v = endstops_trigsteps[axis];
|
||||
|
||||
if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user