|
@@ -642,7 +642,7 @@ void Stepper::set_directions() {
|
642
|
642
|
A("mul %10,%9") /* r1:r0 = 10*HI(v0-v1) */
|
643
|
643
|
A("add %7,r0") /* %7:%6:?? += 10*HI(v0-v1) << 16 */
|
644
|
644
|
A("sts bezier_C+1, %6")
|
645
|
|
- " sts bezier_C+2, %7" /* bezier_C = %7:%6:?? = 10*(v0-v1) [65 cycles worst] */
|
|
645
|
+ " sts bezier_C+2, %7" /* bezier_C = %7:%6:?? = 10*(v0-v1) [65 cycles worst] */
|
646
|
646
|
: "+r" (r2),
|
647
|
647
|
"+d" (r3),
|
648
|
648
|
"=r" (r4),
|
|
@@ -1025,7 +1025,7 @@ void Stepper::set_directions() {
|
1025
|
1025
|
A("add %3,r0")
|
1026
|
1026
|
A("adc %4,r1") /* %4:%3:%2:%9 += HI(bezier_A) * LO(f) << 16*/
|
1027
|
1027
|
L("2")
|
1028
|
|
- " clr __zero_reg__" /* C runtime expects r1 = __zero_reg__ = 0 */
|
|
1028
|
+ " clr __zero_reg__" /* C runtime expects r1 = __zero_reg__ = 0 */
|
1029
|
1029
|
: "+r"(r0),
|
1030
|
1030
|
"+r"(r1),
|
1031
|
1031
|
"+r"(r2),
|
|
@@ -1152,16 +1152,8 @@ HAL_STEP_TIMER_ISR {
|
1152
|
1152
|
// Call the ISR scheduler
|
1153
|
1153
|
hal_timer_t ticks = Stepper::isr_scheduler();
|
1154
|
1154
|
|
1155
|
|
- // Now 'ticks' contains the period to the next Stepper ISR.
|
1156
|
|
- // Potential problem: Since the timer continues to run, the requested
|
1157
|
|
- // compare value may already have passed.
|
1158
|
|
- //
|
1159
|
|
- // Assuming at least 6µs between calls to this ISR...
|
1160
|
|
- // On AVR the ISR epilogue is estimated at 40 instructions - close to 2.5µS.
|
1161
|
|
- // On ARM the ISR epilogue is estimated at 10 instructions - close to 200nS.
|
1162
|
|
- // In either case leave at least 4µS for other tasks to execute.
|
1163
|
|
- const hal_timer_t minticks = HAL_timer_get_count(STEP_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * 4); // ISR never takes more than 1ms, so this shouldn't cause trouble
|
1164
|
|
- NOLESS(ticks, MAX(minticks, hal_timer_t((STEP_TIMER_MIN_INTERVAL) * (HAL_TICKS_PER_US))));
|
|
1155
|
+ // Now 'ticks' contains the period to the next Stepper ISR - And we are
|
|
1156
|
+ // sure that the time has not arrived yet - Warrantied by the scheduler
|
1165
|
1157
|
|
1166
|
1158
|
// Set the next ISR to fire at the proper time
|
1167
|
1159
|
HAL_timer_set_compare(STEP_TIMER_NUM, ticks);
|
|
@@ -1178,54 +1170,105 @@ HAL_STEP_TIMER_ISR {
|
1178
|
1170
|
hal_timer_t Stepper::isr_scheduler() {
|
1179
|
1171
|
uint32_t interval;
|
1180
|
1172
|
|
1181
|
|
- // Run main stepping pulse phase ISR if we have to
|
1182
|
|
- if (!nextMainISR) Stepper::stepper_pulse_phase_isr();
|
|
1173
|
+ // Count of ticks for the next ISR
|
|
1174
|
+ hal_timer_t next_isr_ticks = 0;
|
1183
|
1175
|
|
1184
|
|
- #if ENABLED(LIN_ADVANCE)
|
1185
|
|
- // Run linear advance stepper ISR if we have to
|
1186
|
|
- if (!nextAdvanceISR) nextAdvanceISR = Stepper::advance_isr();
|
1187
|
|
- #endif
|
|
1176
|
+ // Limit the amount of iterations
|
|
1177
|
+ uint8_t max_loops = 10;
|
|
1178
|
+
|
|
1179
|
+ // We need this variable here to be able to use it in the following loop
|
|
1180
|
+ hal_timer_t min_ticks;
|
|
1181
|
+ do {
|
|
1182
|
+ // Run main stepping pulse phase ISR if we have to
|
|
1183
|
+ if (!nextMainISR) Stepper::stepper_pulse_phase_isr();
|
1188
|
1184
|
|
1189
|
|
- // ^== Time critical. NOTHING besides pulse generation should be above here!!!
|
|
1185
|
+ #if ENABLED(LIN_ADVANCE)
|
|
1186
|
+ // Run linear advance stepper ISR if we have to
|
|
1187
|
+ if (!nextAdvanceISR) nextAdvanceISR = Stepper::advance_isr();
|
|
1188
|
+ #endif
|
1190
|
1189
|
|
1191
|
|
- // Run main stepping block processing ISR if we have to
|
1192
|
|
- if (!nextMainISR) nextMainISR = Stepper::stepper_block_phase_isr();
|
|
1190
|
+ // ^== Time critical. NOTHING besides pulse generation should be above here!!!
|
1193
|
1191
|
|
1194
|
|
- #if ENABLED(LIN_ADVANCE)
|
1195
|
|
- // Select the closest interval in time
|
1196
|
|
- interval = (nextAdvanceISR <= nextMainISR)
|
1197
|
|
- ? nextAdvanceISR
|
1198
|
|
- : nextMainISR;
|
|
1192
|
+ // Run main stepping block processing ISR if we have to
|
|
1193
|
+ if (!nextMainISR) nextMainISR = Stepper::stepper_block_phase_isr();
|
1199
|
1194
|
|
1200
|
|
- #else // !ENABLED(LIN_ADVANCE)
|
|
1195
|
+ #if ENABLED(LIN_ADVANCE)
|
|
1196
|
+ // Select the closest interval in time
|
|
1197
|
+ interval = (nextAdvanceISR <= nextMainISR) ? nextAdvanceISR : nextMainISR;
|
|
1198
|
+ #else
|
|
1199
|
+ // The interval is just the remaining time to the stepper ISR
|
|
1200
|
+ interval = nextMainISR;
|
|
1201
|
+ #endif
|
1201
|
1202
|
|
1202
|
|
- // The interval is just the remaining time to the stepper ISR
|
1203
|
|
- interval = nextMainISR;
|
1204
|
|
- #endif
|
|
1203
|
+ // Limit the value to the maximum possible value of the timer
|
|
1204
|
+ NOMORE(interval, HAL_TIMER_TYPE_MAX);
|
1205
|
1205
|
|
1206
|
|
- // Limit the value to the maximum possible value of the timer
|
1207
|
|
- if (interval > HAL_TIMER_TYPE_MAX)
|
1208
|
|
- interval = HAL_TIMER_TYPE_MAX;
|
|
1206
|
+ // Compute the time remaining for the main isr
|
|
1207
|
+ nextMainISR -= interval;
|
1209
|
1208
|
|
1210
|
|
- // Compute the time remaining for the main isr
|
1211
|
|
- nextMainISR -= interval;
|
|
1209
|
+ #if ENABLED(LIN_ADVANCE)
|
|
1210
|
+ // Compute the time remaining for the advance isr
|
|
1211
|
+ if (nextAdvanceISR != ADV_NEVER) nextAdvanceISR -= interval;
|
|
1212
|
+ #endif
|
1212
|
1213
|
|
1213
|
|
- #if ENABLED(LIN_ADVANCE)
|
1214
|
|
- // Compute the time remaining for the advance isr
|
1215
|
|
- if (nextAdvanceISR != ADV_NEVER)
|
1216
|
|
- nextAdvanceISR -= interval;
|
1217
|
|
- #endif
|
|
1214
|
+ /**
|
|
1215
|
+ * This needs to avoid a race-condition caused by interleaving
|
|
1216
|
+ * of interrupts required by both the LA and Stepper algorithms.
|
|
1217
|
+ *
|
|
1218
|
+ * Assume the following tick times for stepper pulses:
|
|
1219
|
+ * Stepper ISR (S): 1 1000 2000 3000 4000
|
|
1220
|
+ * Linear Adv. (E): 10 1010 2010 3010 4010
|
|
1221
|
+ *
|
|
1222
|
+ * The current algorithm tries to interleave them, giving:
|
|
1223
|
+ * 1:S 10:E 1000:S 1010:E 2000:S 2010:E 3000:S 3010:E 4000:S 4010:E
|
|
1224
|
+ *
|
|
1225
|
+ * Ideal timing would yield these delta periods:
|
|
1226
|
+ * 1:S 9:E 990:S 10:E 990:S 10:E 990:S 10:E 990:S 10:E
|
|
1227
|
+ *
|
|
1228
|
+ * But, since each event must fire an ISR with a minimum duration, the
|
|
1229
|
+ * minimum delta might be 900, so deltas under 900 get rounded up:
|
|
1230
|
+ * 900:S d900:E d990:S d900:E d990:S d900:E d990:S d900:E d990:S d900:E
|
|
1231
|
+ *
|
|
1232
|
+ * It works, but divides the speed of all motors by half, leading to a sudden
|
|
1233
|
+ * reduction to 1/2 speed! Such jumps in speed lead to lost steps (not even
|
|
1234
|
+ * accounting for double/quad stepping, which makes it even worse).
|
|
1235
|
+ */
|
|
1236
|
+
|
|
1237
|
+ // Compute the tick count for the next ISR
|
|
1238
|
+ next_isr_ticks += interval;
|
|
1239
|
+
|
|
1240
|
+ /**
|
|
1241
|
+ * Get the current tick value + margin
|
|
1242
|
+ * Assuming at least 6µs between calls to this ISR...
|
|
1243
|
+ * On AVR the ISR epilogue is estimated at 40 instructions - close to 2.5µS.
|
|
1244
|
+ * On ARM the ISR epilogue is estimated at 10 instructions - close to 200nS.
|
|
1245
|
+ * In either case leave at least 8µS for other tasks to execute - That allows
|
|
1246
|
+ * up to 100khz stepping rates
|
|
1247
|
+ */
|
|
1248
|
+ min_ticks = HAL_timer_get_count(STEP_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * 8); // ISR never takes more than 1ms, so this shouldn't cause trouble
|
1218
|
1249
|
|
1219
|
|
- return (hal_timer_t)interval;
|
|
1250
|
+ /**
|
|
1251
|
+ * NB: If for some reason the stepper monopolizes the MPU, eventually the
|
|
1252
|
+ * timer will wrap around (and so will 'next_isr_ticks'). So, limit the
|
|
1253
|
+ * loop to 10 iterations. Beyond that, there's no way to ensure correct pulse
|
|
1254
|
+ * timing, since the MCU isn't fast enough.
|
|
1255
|
+ */
|
|
1256
|
+ if (!--max_loops) next_isr_ticks = min_ticks;
|
|
1257
|
+
|
|
1258
|
+ // Advance pulses if not enough time to wait for the next ISR
|
|
1259
|
+ } while (next_isr_ticks < min_ticks);
|
|
1260
|
+
|
|
1261
|
+ // Return the count of ticks for the next ISR
|
|
1262
|
+ return (hal_timer_t)next_isr_ticks;
|
1220
|
1263
|
}
|
1221
|
1264
|
|
1222
|
|
-// This part of the ISR should ONLY create the pulses for the steppers
|
1223
|
|
-// -- Nothing more, nothing less -- We want to avoid jitter from where
|
1224
|
|
-// the pulses should be generated (when the interrupt triggers) to the
|
1225
|
|
-// time pulses are actually created. So, PLEASE DO NOT PLACE ANY CODE
|
1226
|
|
-// above this line that can conditionally change that time (we are trying
|
1227
|
|
-// to keep the delay between the interrupt triggering and pulse generation
|
1228
|
|
-// as constant as possible!!!!
|
|
1265
|
+/**
|
|
1266
|
+ * This phase of the ISR should ONLY create the pulses for the steppers.
|
|
1267
|
+ * This prevents jitter caused by the interval between the start of the
|
|
1268
|
+ * interrupt and the start of the pulses. DON'T add any logic ahead of the
|
|
1269
|
+ * call to this method that might cause variation in the timing. The aim
|
|
1270
|
+ * is to keep pulse timing as regular as possible.
|
|
1271
|
+ */
|
1229
|
1272
|
void Stepper::stepper_pulse_phase_isr() {
|
1230
|
1273
|
|
1231
|
1274
|
// If we must abort the current block, do so!
|