diff options
author | David Crocker <dcrocker@eschertech.com> | 2021-10-26 16:41:45 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2021-10-26 16:41:45 +0300 |
commit | 9744fbef6c10928a8fbf42d116ea56ced7b1af25 (patch) | |
tree | 5f6d882c67b8290245ac1eff9d623f185cad05c6 /src/Movement | |
parent | 54fb8c8c6142d55122b76c82837aa0715fbb7d6a (diff) |
Changed how we update extrusion accumulators, fixed poss. race condition
Diffstat (limited to 'src/Movement')
-rw-r--r-- | src/Movement/DDA.cpp | 44 | ||||
-rw-r--r-- | src/Movement/DDA.h | 1 | ||||
-rw-r--r-- | src/Movement/DDARing.cpp | 17 |
3 files changed, 50 insertions, 12 deletions
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp index 69626146..cf95272d 100644 --- a/src/Movement/DDA.cpp +++ b/src/Movement/DDA.cpp @@ -2326,6 +2326,50 @@ void DDA::LimitSpeedAndAcceleration(float maxSpeed, float maxAcceleration) noexc } } +// Update the movement accumulators to account for the move that has just finished. +// Only drives that correspond to extruders need to be updated, but it doesn't matter if we update them all. +// This is called with interrupts disabled. +void DDA::UpdateMovementAccumulators(volatile int32_t *accumulators) const noexcept +{ + // To identify all the extruder movement, we can either loop through extruder numbers and search both DM lists for a DM for that drive, + // or we can iterate through both DM lists, checking whether the drive it is for is an extruder. +#if 1 + // Loop through DMs, checking whether each associated drive is an extruder and updating the movement accumulator if so. + // We could omit the check that the drive is an accumulator so that we update all accumulators, but we would still need to check for leadscrew adjustment moves. + const unsigned int firstExtruderDrive = ExtruderToLogicalDrive(reprap.GetGCodes().GetNumExtruders() - 1); + for (const DriveMovement* dm = activeDMs; dm != nullptr; ) + { + const uint8_t drv = dm->drive; + if ( drv >= firstExtruderDrive // check that it's an extruder (to save the call to GetStepsTaken) + && drv < MaxAxesPlusExtruders // check that it's not a direct leadscrew move + ) + { + accumulators[drv] += dm->GetNetStepsTaken(); + } + dm = dm->nextDM; + } + for (const DriveMovement* dm = completedDMs; dm != nullptr; ) + { + const uint8_t drv = dm->drive; + if ( drv >= firstExtruderDrive // check that it's an extruder (to save the call to GetStepsTaken) + && drv < MaxAxesPlusExtruders // check that it's not a direct leadscrew move + ) + { + accumulators[drv] += dm->GetNetStepsTaken(); + } + dm = dm->nextDM; + } +#else + // Loop through extruders + const size_t numExtruders = reprap.GetGCodes().GetNumExtruders(); + for (size_t extruder = 0; extruder < numExtruders; ++extruder) + { + const size_t drv = ExtruderToLogicalDrive(extruder); + accumulators[drv] += GetStepsTaken(drv); + } +#endif +} + #if SUPPORT_LASER // Manage the laser power. Return the number of ticks until we should be called again, or 0 to be called at the start of the next move. diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h index 2c693d98..035b8f42 100644 --- a/src/Movement/DDA.h +++ b/src/Movement/DDA.h @@ -160,6 +160,7 @@ public: uint32_t GetClocksNeeded() const noexcept { return clocksNeeded; } bool IsGoodToPrepare() const noexcept; bool IsNonPrintingExtruderMove() const noexcept { return flags.isNonPrintingExtruderMove; } + void UpdateMovementAccumulators(volatile int32_t *accumulators) const noexcept; #if SUPPORT_LASER || SUPPORT_IOBITS LaserPwmOrIoBits GetLaserPwmOrIoBits() const noexcept { return laserPwmOrIoBits; } diff --git a/src/Movement/DDARing.cpp b/src/Movement/DDARing.cpp index 23270b35..4aeb39a7 100644 --- a/src/Movement/DDARing.cpp +++ b/src/Movement/DDARing.cpp @@ -572,18 +572,12 @@ void DDARing::CurrentMoveCompleted() noexcept liveCoordinatesValid = cdda->FetchEndPosition(const_cast<int32_t*>(liveEndPoints), const_cast<float *>(liveCoordinates)); liveCoordinatesChanged = true; - // In the following it doesn't currently matter whether we process all drives or just the extruders - // Instead of looping through extruders, we could loop through DMs. + // Disable interrupts before we touch any extrusion accumulators until after we set currentDda to null, in case the filament monitor interrupt has higher priority than ours { - const size_t numExtruders = reprap.GetGCodes().GetNumExtruders(); - for (size_t extruder = 0; extruder < numExtruders; ++extruder) - { - const size_t drv = ExtruderToLogicalDrive(extruder); - movementAccumulators[drv] += cdda->GetStepsTaken(drv); - } + AtomicCriticalSectionLocker lock; + cdda->UpdateMovementAccumulators(movementAccumulators); + currentDda = nullptr; } - - currentDda = nullptr; if (cdda->IsCheckingEndstops()) { Move::WakeMoveTaskFromISR(); // wake the Move task if we were checking endstops @@ -607,13 +601,12 @@ bool DDARing::SetWaitingToEmpty() noexcept int32_t DDARing::GetAccumulatedMovement(size_t drive, bool& isPrinting) noexcept { - const uint32_t basepri = ChangeBasePriority(NvicPriorityStep); + AtomicCriticalSectionLocker lock; const int32_t ret = movementAccumulators[drive]; const DDA * const cdda = currentDda; // capture volatile variable const int32_t adjustment = (cdda == nullptr) ? 0 : cdda->GetStepsTaken(drive); movementAccumulators[drive] = -adjustment; isPrinting = extrudersPrinting; - RestoreBasePriority(basepri); return ret + adjustment; } |