| 1589 | #endif |
| 1590 | |
| 1591 | void Planner::quick_stop() { |
| 1592 | |
| 1593 | /** |
| 1594 | * Remove all the queued blocks. |
| 1595 | * NOTE: This function is NOT called from the Stepper ISR, |
| 1596 | * so we must consider tail as readonly! |
| 1597 | * That is why we set head to tail - But there is a race condition that |
| 1598 | * must be handled: The tail could change between the read and the assignment |
| 1599 | * so this must be enclosed in a critical section |
| 1600 | */ |
| 1601 | |
| 1602 | const bool was_enabled = stepper.suspend(); |
| 1603 | |
| 1604 | // Drop all queue entries |
| 1605 | const uint8_t tail_value = block_buffer_tail; // Read tail value once |
| 1606 | block_buffer_head = tail_value; |
| 1607 | block_buffer_nonbusy = tail_value; |
| 1608 | |
| 1609 | // Restart the block delay for the first movement - As the queue was |
| 1610 | // forced to empty, there's no risk the ISR will touch this. |
| 1611 | |
| 1612 | delay_before_delivering = TERN0(FT_MOTION, ftMotion.cfg.active) ? BLOCK_DELAY_NONE : BLOCK_DELAY_FOR_1ST_MOVE; |
| 1613 | |
| 1614 | TERN_(HAS_WIRED_LCD, clear_block_buffer_runtime()); // Clear the accumulated runtime |
| 1615 | |
| 1616 | // Make sure to drop any attempt of queuing moves for 1 second |
| 1617 | cleaning_buffer_counter = TEMP_TIMER_FREQUENCY; |
| 1618 | |
| 1619 | // Reenable Stepper ISR |
| 1620 | if (was_enabled) stepper.wake_up(); |
| 1621 | |
| 1622 | // And stop the stepper ISR |
| 1623 | stepper.quick_stop(); |
| 1624 | } |
| 1625 | |
| 1626 | #if ENABLED(REALTIME_REPORTING_COMMANDS) |
| 1627 |
no test coverage detected