|
@@ -628,6 +628,8 @@ void crashdet_stop_and_save_print2()
|
|
|
cmdqueue_reset(); //empty cmdqueue
|
|
|
card.sdprinting = false;
|
|
|
card.closefile();
|
|
|
+ // Reset and re-enable the stepper timer just before the global interrupts are enabled.
|
|
|
+ st_reset_timer();
|
|
|
sei();
|
|
|
}
|
|
|
|
|
@@ -1421,8 +1423,12 @@ void loop()
|
|
|
#endif //SDSUPPORT
|
|
|
|
|
|
if (! cmdbuffer_front_already_processed && buflen)
|
|
|
- {
|
|
|
- cli();
|
|
|
+ {
|
|
|
+ // ptr points to the start of the block currently being processed.
|
|
|
+ // The first character in the block is the block type.
|
|
|
+ char *ptr = cmdbuffer + bufindr;
|
|
|
+ if (*ptr == CMDBUFFER_CURRENT_TYPE_SDCARD) {
|
|
|
+ // To support power panic, move the lenght of the command on the SD card to a planner buffer.
|
|
|
union {
|
|
|
struct {
|
|
|
char lo;
|
|
@@ -1431,14 +1437,28 @@ void loop()
|
|
|
uint16_t value;
|
|
|
} sdlen;
|
|
|
sdlen.value = 0;
|
|
|
- if (CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_SDCARD) {
|
|
|
- sdlen.lohi.lo = cmdbuffer[bufindr + 1];
|
|
|
- sdlen.lohi.hi = cmdbuffer[bufindr + 2];
|
|
|
+ {
|
|
|
+ // This block locks the interrupts globally for 3.25 us,
|
|
|
+ // which corresponds to a maximum repeat frequency of 307.69 kHz.
|
|
|
+ // This blocking is safe in the context of a 10kHz stepper driver interrupt
|
|
|
+ // or a 115200 Bd serial line receive interrupt, which will not trigger faster than 12kHz.
|
|
|
+ cli();
|
|
|
+ // Reset the command to something, which will be ignored by the power panic routine,
|
|
|
+ // so this buffer length will not be counted twice.
|
|
|
+ *ptr ++ = CMDBUFFER_CURRENT_TYPE_TO_BE_REMOVED;
|
|
|
+ // Extract the current buffer length.
|
|
|
+ sdlen.lohi.lo = *ptr ++;
|
|
|
+ sdlen.lohi.hi = *ptr;
|
|
|
+ // and pass it to the planner queue.
|
|
|
+ planner_add_sd_length(sdlen.value);
|
|
|
+ sei();
|
|
|
}
|
|
|
- cmdqueue_pop_front();
|
|
|
- planner_add_sd_length(sdlen.value);
|
|
|
- sei();
|
|
|
- }
|
|
|
+ }
|
|
|
+ // Now it is safe to release the already processed command block. If interrupted by the power panic now,
|
|
|
+ // this block's SD card length will not be counted twice as its command type has been replaced
|
|
|
+ // by CMDBUFFER_CURRENT_TYPE_TO_BE_REMOVED.
|
|
|
+ cmdqueue_pop_front();
|
|
|
+ }
|
|
|
host_keepalive();
|
|
|
}
|
|
|
}
|
|
@@ -1987,11 +2007,14 @@ void force_high_power_mode(bool start_high_power_section) {
|
|
|
if (silent == 1) {
|
|
|
//we are in silent mode, set to normal mode to enable crash detection
|
|
|
|
|
|
-
|
|
|
+ // Wait for the planner queue to drain and for the stepper timer routine to reach an idle state.
|
|
|
st_synchronize();
|
|
|
cli();
|
|
|
tmc2130_mode = (start_high_power_section == true) ? TMC2130_MODE_NORMAL : TMC2130_MODE_SILENT;
|
|
|
tmc2130_init();
|
|
|
+ // We may have missed a stepper timer interrupt due to the time spent in the tmc2130_init() routine.
|
|
|
+ // Be safe than sorry, reset the stepper timer before re-enabling interrupts.
|
|
|
+ st_reset_timer();
|
|
|
sei();
|
|
|
digipot_init();
|
|
|
}
|
|
@@ -7555,6 +7578,8 @@ void setup_fan_interrupt() {
|
|
|
EIMSK |= (1 << 7);
|
|
|
}
|
|
|
|
|
|
+// The fan interrupt is triggered at maximum 325Hz (may be a bit more due to component tollerances),
|
|
|
+// and it takes 4.24 us to process (the interrupt invocation overhead not taken into account).
|
|
|
ISR(INT7_vect) {
|
|
|
//measuring speed now works for fanSpeed > 18 (approximately), which is sufficient because MIN_PRINT_FAN_SPEED is higher
|
|
|
|
|
@@ -7912,6 +7937,8 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
|
|
|
card.sdprinting = false;
|
|
|
// card.closefile();
|
|
|
saved_printing = true;
|
|
|
+ // We may have missed a stepper timer interrupt. Be safe than sorry, reset the stepper timer before re-enabling interrupts.
|
|
|
+ st_reset_timer();
|
|
|
sei();
|
|
|
if ((z_move != 0) || (e_move != 0)) { // extruder or z move
|
|
|
#if 1
|