Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2021-10-26 16:41:45 +0300
committerDavid Crocker <dcrocker@eschertech.com>2021-10-26 16:41:45 +0300
commit9744fbef6c10928a8fbf42d116ea56ced7b1af25 (patch)
tree5f6d882c67b8290245ac1eff9d623f185cad05c6 /src/Movement
parent54fb8c8c6142d55122b76c82837aa0715fbb7d6a (diff)
Changed how we update extrusion accumulators, fixed poss. race condition
Diffstat (limited to 'src/Movement')
-rw-r--r--src/Movement/DDA.cpp44
-rw-r--r--src/Movement/DDA.h1
-rw-r--r--src/Movement/DDARing.cpp17
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;
}