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-18 14:09:22 +0300
committerDavid Crocker <dcrocker@eschertech.com>2021-10-18 14:09:22 +0300
commit4e15856c84b9378d3336c5c6b7ddea9de59305ae (patch)
tree648477df3fe26c584b7e01bff1a5bf5ebb9626f7 /src/Movement
parent6d6d3b8b62a20d842539afb2e319dd335a785af5 (diff)
Added sgresultMin to StandardDriverStatus
Also removed tracking of maximum stallguard result Reinstated TMC22xx function removed in prevous commit to fix Duet 3 Mini build error
Diffstat (limited to 'src/Movement')
-rw-r--r--src/Movement/StepperDrivers/TMC22xx.cpp120
-rw-r--r--src/Movement/StepperDrivers/TMC2660.cpp54
-rw-r--r--src/Movement/StepperDrivers/TMC51xx.cpp48
3 files changed, 151 insertions, 71 deletions
diff --git a/src/Movement/StepperDrivers/TMC22xx.cpp b/src/Movement/StepperDrivers/TMC22xx.cpp
index b3ed6cc0..5bab7a0b 100644
--- a/src/Movement/StepperDrivers/TMC22xx.cpp
+++ b/src/Movement/StepperDrivers/TMC22xx.cpp
@@ -419,6 +419,7 @@ public:
void AppendStallConfig(const StringRef& reply) const noexcept;
#endif
void AppendDriverStatus(const StringRef& reply) noexcept;
+ StandardDriverStatus GetStandardDriverStatus() const noexcept;
uint8_t GetDriverNumber() const noexcept { return driverNumber; }
bool UpdatePending() const noexcept;
#if TMC22xx_HAS_ENABLE_PINS
@@ -483,8 +484,7 @@ private:
#if HAS_STALL_DETECT
void ResetLoadRegisters() noexcept
{
- minSgLoadRegister = 1023;
- maxSgLoadRegister = 0;
+ minSgLoadRegister = 9999; // values read from the driver are in the range 0 to 1023, so 9999 indicates that it hasn't been read
}
#endif
@@ -552,8 +552,7 @@ private:
uint32_t maxOpenLoadStepInterval; // the maximum step pulse interval for which we consider open load detection to be reliable
#if HAS_STALL_DETECT
- uint32_t minSgLoadRegister; // the minimum value of the StallGuard bits we read
- uint32_t maxSgLoadRegister; // the maximum value of the StallGuard bits we read
+ uint16_t minSgLoadRegister; // the minimum value of the StallGuard bits we read
#endif
#if TMC22xx_HAS_MUX || TMC22xx_SINGLE_DRIVER
@@ -1300,13 +1299,13 @@ void TmcDriverState::AppendDriverStatus(const StringRef& reply) noexcept
}
#if HAS_STALL_DETECT
- if (minSgLoadRegister <= maxSgLoadRegister)
+ if (minSgLoadRegister <= 1023)
{
- reply.catf(", SG min/max %" PRIu32 "/%" PRIu32, minSgLoadRegister, maxSgLoadRegister);
+ reply.catf(", SG min %u", minSgLoadRegister);
}
else
{
- reply.cat(", SG min/max n/a");
+ reply.cat(", SG min n/a");
}
ResetLoadRegisters();
#endif
@@ -1321,6 +1320,20 @@ void TmcDriverState::AppendDriverStatus(const StringRef& reply) noexcept
readErrors = writeErrors = numReads = numWrites = numTimeouts = numDmaErrors = 0;
}
+StandardDriverStatus TmcDriverState::GetStandardDriverStatus() const noexcept
+{
+ StandardDriverStatus rslt;
+ const uint32_t status = ReadLiveStatus();
+ // The lowest 8 bits of StandardDriverStatus have the same meanings as for the TMC2209 status
+ rslt.all = status & 0x000000FF;
+ rslt.all |= ExtractBit(status, TMC_RR_STST_BIT_POS, StandardDriverStatus::StandstillBitPos); // put the standstill bit in the right place
+ rslt.all |= ExtractBit(status, TMC_RR_SG_BIT_POS, StandardDriverStatus::StallBitPos); // put the stall bit in the right place
+#if HAS_STALL_DETECT
+ rslt.sgresultMin = minSgLoadRegister;
+#endif
+ return rslt;
+}
+
// This is called by the ISR when the SPI transfer has completed
inline void TmcDriverState::TransferDone() noexcept
{
@@ -1377,15 +1390,11 @@ inline void TmcDriverState::TransferDone() noexcept
#if HAS_STALL_DETECT
else if (registerToRead == ReadSgResult)
{
- const uint32_t sgResult = regVal & SG_RESULT_MASK;
+ const uint16_t sgResult = regVal & SG_RESULT_MASK;
if (sgResult < minSgLoadRegister)
{
minSgLoadRegister = sgResult;
}
- if (sgResult > maxSgLoadRegister)
- {
- maxSgLoadRegister = sgResult;
- }
}
#endif
readRegisters[registerToRead] = regVal;
@@ -2140,24 +2149,91 @@ GCodeResult SmartDrivers::SetAnyRegister(size_t driver, const StringRef& reply,
StandardDriverStatus SmartDrivers::GetStandardDriverStatus(size_t driver) noexcept
{
- StandardDriverStatus rslt;
if (driver < GetNumTmcDrivers())
{
- const uint32_t status = driverStates[driver].ReadLiveStatus();
- // The lowest 8 bits of StandardDriverStatus have the same meanings as for the TMC2209 status
- rslt.all = status & 0x000000FF;
- rslt.all |= ExtractBit(status, TMC_RR_STST_BIT_POS, StandardDriverStatus::StandstillBitPos); // put the standstill bit in the right place
- rslt.all |= ExtractBit(status, TMC_RR_SG_BIT_POS, StandardDriverStatus::StallBitPos); // put the stall bit in the right place
- }
- else
- {
- rslt.all = 0;
+ return driverStates[driver].GetStandardDriverStatus();
}
+ StandardDriverStatus rslt;
+ rslt.all = 0;
return rslt;
}
#if HAS_STALL_DETECT
+# ifdef DUET3MINI
+
+// Stall detection for Duet 3 Mini v0.4 and later
+// Each TMC2209 DIAG output is routed to its own MCU pin, however we don't have enough EXINTs on the SAME54 to give each one its own interrupt.
+// So we route them all to CCL input pins instead, which lets us selectively OR them together in 3 groups and generate an interrupt from the resulting events
+
+// Set up to generate interrupts on the specified drivers stalling
+void EnableStallInterrupt(DriversBitmap drivers) noexcept
+{
+ // Disable all the Diag event interrupts
+ for (unsigned int i = 1; i < 3; ++i)
+ {
+ CCL->LUTCTRL[i].reg &= ~CCL_LUTCTRL_ENABLE;
+ EVSYS->Channel[CclLut0Event + i].CHINTENCLR.reg = EVSYS_CHINTENCLR_EVD | EVSYS_CHINTENCLR_OVR;
+ EVSYS->Channel[CclLut0Event + i].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTENCLR_OVR;
+ }
+
+ if (!drivers.IsEmpty())
+ {
+ // Calculate the new LUT control values
+ constexpr uint32_t lutDefault = CCL_LUTCTRL_TRUTH(0xFE) | CCL_LUTCTRL_LUTEO; // OR function, disabled, event output enabled
+ uint32_t lutInputControls[4] = { lutDefault, lutDefault, lutDefault, lutDefault };
+ drivers.IterateWhile([&lutInputControls](unsigned int driver, unsigned int count) -> bool
+ { if (driver < GetNumTmcDrivers())
+ {
+ const uint32_t cclInput = CclDiagInputs[driver];
+ lutInputControls[cclInput & 3] |= cclInput & 0x000000FFFFFF0000;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ } );
+
+ // Now set up the CCL with those inputs. We only use CCL 1-3 so leave 0 alone for possible other applications.
+ for (unsigned int i = 1; i < 4; ++i)
+ {
+ if (lutInputControls[i] & 0x000000FFFFFF0000) // if any inputs are enabled
+ {
+ CCL->LUTCTRL[i].reg = lutInputControls[i];
+ CCL->LUTCTRL[i].reg = lutInputControls[i] | CCL_LUTCTRL_ENABLE;
+ EVSYS->Channel[CclLut0Event + i].CHINTENSET.reg = EVSYS_CHINTENCLR_EVD;
+ }
+ }
+ }
+}
+
+// Initialise the stall detection logic that is external to the drivers. Only needs to be called once.
+static void InitStallDetectionLogic() noexcept
+{
+ // Set up the DIAG inputs as CCL inputs
+ for (Pin p : DriverDiagPins)
+ {
+ pinMode(p, INPUT_PULLDOWN); // enable pulldown in case of missing drivers
+ SetPinFunction(p, GpioPinFunction::N);
+ }
+
+ // Set up the event channels for CCL LUTs 1 to 3. We only use CCL 1-3 so leave 0 alone for possible other applications.
+ for (unsigned int i = 1; i < 4; ++i)
+ {
+ GCLK->PCHCTRL[EVSYS_GCLK_ID_0 + i].reg = GCLK_PCHCTRL_GEN(GclkNum60MHz) | GCLK_PCHCTRL_CHEN; // enable the GCLK, needed to use the resynchronised path
+ EVSYS->Channel[CclLut0Event + i].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(0x74 + i) | EVSYS_CHANNEL_PATH_RESYNCHRONIZED;
+ // LUT output events on the SAME5x are event generator numbers 0x74 to 0x77. Resynchronised path allows interrupts.
+ EVSYS->Channel[CclLut0Event + i].CHINTENCLR.reg = EVSYS_CHINTENCLR_EVD | EVSYS_CHINTENCLR_OVR; // disable interrupts for now
+ NVIC_SetPriority((IRQn)(EVSYS_0_IRQn + i), NvicPriorityDriverDiag);
+ NVIC_EnableIRQ((IRQn)(EVSYS_0_IRQn + i)); // enable the interrupt for this event channel in the NVIC
+ }
+
+ CCL->CTRL.reg = CCL_CTRL_ENABLE; // enable the CCL
+}
+
+# endif
+
DriversBitmap SmartDrivers::GetStalledDrivers(DriversBitmap driversOfInterest) noexcept
{
DriversBitmap rslt;
diff --git a/src/Movement/StepperDrivers/TMC2660.cpp b/src/Movement/StepperDrivers/TMC2660.cpp
index de545401..44f18bd0 100644
--- a/src/Movement/StepperDrivers/TMC2660.cpp
+++ b/src/Movement/StepperDrivers/TMC2660.cpp
@@ -227,6 +227,7 @@ public:
void SetStallMinimumStepsPerSecond(unsigned int stepsPerSecond) noexcept;
void AppendStallConfig(const StringRef& reply) const noexcept;
void AppendDriverStatus(const StringRef& reply) noexcept;
+ StandardDriverStatus GetStandardDriverStatus() const noexcept;
bool SetRegister(SmartDriverRegister reg, uint32_t regVal) noexcept;
uint32_t GetRegister(SmartDriverRegister reg) const noexcept;
@@ -245,8 +246,7 @@ private:
void ResetLoadRegisters() noexcept
{
- minSgLoadRegister = 1023;
- maxSgLoadRegister = 0;
+ minSgLoadRegister = 9999; // values read from the driver are in the range 0 to 1023, so 9999 indicates that it hasn't been read
}
static void SetupDMA(uint32_t outVal) noexcept SPEED_CRITICAL; // set up the PDC to send a register and receive the status
@@ -270,12 +270,12 @@ private:
uint32_t axisNumber; // the axis number of this driver as used to index the DriveMovements in the DDA
uint32_t microstepShiftFactor; // how much we need to shift 1 left by to get the current microstepping
uint32_t maxStallStepInterval; // maximum interval between full steps to take any notice of stall detection
- uint32_t minSgLoadRegister; // the minimum value of the StallGuard bits we read
- uint32_t maxSgLoadRegister; // the maximum value of the StallGuard bits we read
uint32_t mstepPosition; // the current microstep position, or 0xFFFFFFFF if unknown
volatile uint32_t lastReadStatus; // the status word that we read most recently, updated by the ISR
volatile uint32_t accumulatedStatus;
+
+ uint16_t minSgLoadRegister; // the minimum value of the StallGuard bits we read
bool enabled;
volatile uint8_t rdselState; // 0-3 = actual RDSEL value, 0xFF = unknown
};
@@ -718,13 +718,13 @@ void TmcDriverState::AppendDriverStatus(const StringRef& reply) noexcept
reply.cat("ok, ");
}
- if (minSgLoadRegister <= maxSgLoadRegister)
+ if (minSgLoadRegister <= 1023)
{
- reply.catf("SG min/max %" PRIu32 "/%" PRIu32, minSgLoadRegister, maxSgLoadRegister);
+ reply.catf("SG min %u", minSgLoadRegister);
}
else
{
- reply.cat("SG min/max n/a");
+ reply.cat("SG min n/a");
}
ResetLoadRegisters();
}
@@ -736,6 +736,23 @@ unsigned int TmcDriverState::GetMicrostepping(bool& interpolation) const noexcep
return 1u << microstepShiftFactor;
}
+// Get the status of the driver
+StandardDriverStatus TmcDriverState::GetStandardDriverStatus() const noexcept
+{
+ const uint32_t status = ReadLiveStatus();
+ StandardDriverStatus rslt;
+ // The lowest 8 bits of StandardDriverStatus have the same meanings as for the TMC2209 status, but the TMC2660 uses different bit assignments
+ rslt.all = ExtractBit(status, TMC_RR_OT_BIT_POS, StandardDriverStatus::OtBitPos);
+ rslt.all |= ExtractBit(status, TMC_RR_OTPW_BIT_POS, StandardDriverStatus::OtpwBitPos);
+ rslt.all |= (status & TMC_RR_S2G) >> 1; // put the S2G bits in the right place
+ rslt.all |= (status & (TMC_RR_OLA | TMC_RR_OLB)) << 1; // put the open load bits in the right place
+ rslt.all |= ExtractBit(status, TMC_RR_STST_BIT_POS, StandardDriverStatus::StandstillBitPos); // put the standstill bit in the right place
+ rslt.all |= ExtractBit(status, TMC_RR_SG_BIT_POS, StandardDriverStatus::StallBitPos); // put the stall bit in the right place
+ rslt.sgresultMin = minSgLoadRegister;
+ return rslt;
+}
+
+
// This is called by the ISR when the SPI transfer has completed
inline void TmcDriverState::TransferDone() noexcept
{
@@ -752,15 +769,11 @@ inline void TmcDriverState::TransferDone() noexcept
}
else if (rdselState == 1)
{
- const uint32_t sgLoad = (status >> TMC_RR_SG_LOAD_SHIFT) & 1023; // get the StallGuard load register
+ const uint16_t sgLoad = (status >> TMC_RR_SG_LOAD_SHIFT) & 1023; // get the StallGuard load register
if (sgLoad < minSgLoadRegister)
{
minSgLoadRegister = sgLoad;
}
- if (sgLoad > maxSgLoadRegister)
- {
- maxSgLoadRegister = sgLoad;
- }
if ((status & TMC_RR_SG) != 0)
{
EndstopOrZProbe::SetDriversStalled(driverBit);
@@ -1243,24 +1256,15 @@ uint32_t SmartDrivers::GetRegister(size_t driver, SmartDriverRegister reg) noexc
StandardDriverStatus SmartDrivers::GetStandardDriverStatus(size_t driver) noexcept
{
- StandardDriverStatus rslt;
if (driver < numTmc2660Drivers)
{
- const uint32_t status = driverStates[driver].ReadLiveStatus();
- // The lowest 8 bits of StandardDriverStatus have the same meanings as for the TMC2209 status, but the TMC2660 uses different bit assignments
- rslt.all = ExtractBit(status, TMC_RR_OT_BIT_POS, StandardDriverStatus::OtBitPos);
- rslt.all |= ExtractBit(status, TMC_RR_OTPW_BIT_POS, StandardDriverStatus::OtpwBitPos);
- rslt.all |= (status & TMC_RR_S2G) >> 1; // put the S2G bits in the right place
- rslt.all |= (status & (TMC_RR_OLA | TMC_RR_OLB)) << 1; // put the open load bits in the right place
- rslt.all |= ExtractBit(status, TMC_RR_STST_BIT_POS, StandardDriverStatus::StandstillBitPos); // put the standstill bit in the right place
- rslt.all |= ExtractBit(status, TMC_RR_SG_BIT_POS, StandardDriverStatus::StallBitPos); // put the stall bit in the right place
- }
- else
- {
- rslt.all = 0;
+ return driverStates[driver].GetStandardDriverStatus();
}
+ StandardDriverStatus rslt;
+ rslt.all = 0;
return rslt;
}
+
#endif
// End
diff --git a/src/Movement/StepperDrivers/TMC51xx.cpp b/src/Movement/StepperDrivers/TMC51xx.cpp
index ca2201ec..e105fe0b 100644
--- a/src/Movement/StepperDrivers/TMC51xx.cpp
+++ b/src/Movement/StepperDrivers/TMC51xx.cpp
@@ -288,6 +288,7 @@ public:
void SetStallDetectFilter(bool sgFilter) noexcept;
void SetStallMinimumStepsPerSecond(unsigned int stepsPerSecond) noexcept;
void AppendStallConfig(const StringRef& reply) const noexcept;
+ StandardDriverStatus GetStandardDriverStatus() const noexcept;
bool SetRegister(SmartDriverRegister reg, uint32_t regVal) noexcept;
uint32_t GetRegister(SmartDriverRegister reg) const noexcept;
@@ -314,8 +315,7 @@ private:
void ResetLoadRegisters() noexcept
{
- minSgLoadRegister = 1023;
- maxSgLoadRegister = 0;
+ minSgLoadRegister = 9999; // values read from the driver are in the range 0 to 1023, so 9999 indicates that it hasn't been read
}
// Write register numbers are in priority order, most urgent first, in same order as WriteRegNumbers
@@ -359,8 +359,6 @@ private:
uint32_t configuredChopConfReg; // the configured chopper control register, in the Enabled state, without the microstepping bits
uint32_t maxStallStepInterval; // maximum interval between full steps to take any notice of stall detection
- uint32_t minSgLoadRegister; // the minimum value of the StallGuard bits we read
- uint32_t maxSgLoadRegister; // the maximum value of the StallGuard bits we read
volatile uint32_t newRegistersToUpdate; // bitmap of register indices whose values need to be sent to the driver chip
uint32_t registersToUpdate; // bitmap of register indices whose values need to be sent to the driver chip
@@ -369,6 +367,7 @@ private:
uint32_t microstepShiftFactor; // how much we need to shift 1 left by to get the current microstepping
uint32_t motorCurrent; // the configured motor current in mA
+ uint16_t minSgLoadRegister; // the minimum value of the StallGuard bits we read
uint16_t numReads, numWrites; // how many successful reads and writes we had
static uint16_t numTimeouts; // how many times a transfer timed out
@@ -794,13 +793,13 @@ void TmcDriverState::AppendDriverStatus(const StringRef& reply, bool clearGlobal
reply.cat(" ok");
}
- if (minSgLoadRegister <= maxSgLoadRegister)
+ if (minSgLoadRegister <= 1023)
{
- reply.catf(", SG min/max %" PRIu32 "/%" PRIu32, minSgLoadRegister, maxSgLoadRegister);
+ reply.catf(", SG min %u", minSgLoadRegister);
}
else
{
- reply.cat(", SG min/max n/a");
+ reply.cat(", SG min n/a");
}
ResetLoadRegisters();
@@ -813,6 +812,20 @@ void TmcDriverState::AppendDriverStatus(const StringRef& reply, bool clearGlobal
}
+StandardDriverStatus TmcDriverState::GetStandardDriverStatus() const noexcept
+{
+ StandardDriverStatus rslt;
+ const uint32_t status = ReadLiveStatus();
+ // The lowest 8 bits of StandardDriverStatus have the same meanings as for the TMC2209 status, but the TMC51xx uses different bit assignments
+ rslt.all = (status >> (25 - 0)) & (0x0F << 0); // this puts the ot, otpw, s2ga and s2gb bits in the right place
+ rslt.all |= (status >> (12 - 4)) & (3u << 4); // put s2vsa and s2vsb in the right place
+ rslt.all |= (status >> (29 - 6)) & (3u << 6); // put ola and olb in the right place
+ rslt.all |= ExtractBit(status, TMC_RR_STST_BIT_POS, StandardDriverStatus::StandstillBitPos); // put the standstill bit in the right place
+ rslt.all |= ExtractBit(status, TMC_RR_SG_BIT_POS, StandardDriverStatus::StallBitPos); // put the stall bit in the right place
+ rslt.sgresultMin = minSgLoadRegister;
+ return rslt;
+}
+
void TmcDriverState::SetStallDetectFilter(bool sgFilter) noexcept
{
if (sgFilter)
@@ -914,15 +927,11 @@ void TmcDriverState::TransferSucceeded(const uint8_t *rcvDataBlock) noexcept
// We treat the DRV_STATUS register separately
if ((regVal & TMC_RR_STST) == 0) // in standstill, SG_RESULT returns the chopper on-time instead
{
- const uint32_t sgResult = regVal & TMC_RR_SGRESULT;
+ const uint16_t sgResult = regVal & TMC_RR_SGRESULT;
if (sgResult < minSgLoadRegister)
{
minSgLoadRegister = sgResult;
}
- if (sgResult > maxSgLoadRegister)
- {
- maxSgLoadRegister = sgResult;
- }
}
if ((regVal & (TMC_RR_OLA | TMC_RR_OLB)) != 0)
@@ -1602,21 +1611,12 @@ GCodeResult SmartDrivers::SetAnyRegister(size_t driver, const StringRef& reply,
StandardDriverStatus SmartDrivers::GetStandardDriverStatus(size_t driver) noexcept
{
- StandardDriverStatus rslt;
if (driver < numTmc51xxDrivers)
{
- const uint32_t status = driverStates[driver].ReadLiveStatus();
- // The lowest 8 bits of StandardDriverStatus have the same meanings as for the TMC2209 status, but the TMC51xx uses different bit assignments
- rslt.all = (status >> (25 - 0)) & (0x0F << 0); // this puts the ot, otpw, s2ga and s2gb bits in the right place
- rslt.all |= (status >> (12 - 4)) & (3u << 4); // put s2vsa and s2vsb in the right place
- rslt.all |= (status >> (29 - 6)) & (3u << 6); // put ola and olb in the right place
- rslt.all |= ExtractBit(status, TMC_RR_STST_BIT_POS, StandardDriverStatus::StandstillBitPos); // put the standstill bit in the right place
- rslt.all |= ExtractBit(status, TMC_RR_SG_BIT_POS, StandardDriverStatus::StallBitPos); // put the stall bit in the right place
- }
- else
- {
- rslt.all = 0;
+ return driverStates[driver].GetStandardDriverStatus();
}
+ StandardDriverStatus rslt;
+ rslt.all = 0;
return rslt;
}