Skip to content

Commit

Permalink
Manually add missing changes from Add M576: Buffer monitoring MarlinF…
Browse files Browse the repository at this point in the history
…irmware#19674

weird import just added manually to test
  • Loading branch information
tomc committed Jul 9, 2021
1 parent 1f90733 commit 8444d59
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 4 deletions.
8 changes: 8 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -2211,6 +2211,14 @@
// Some clients will have this feature soon. This could make the NO_TIMEOUTS unnecessary.
#define ADVANCED_OK

/**
* Buffer monitoring
*
* To help diagnose print quality issues stemming from command buffers being empty,
* we add M576 which enables reporting of buffer empty
*/
//#define BUFFER_MONITORING

// Printrun may have trouble receiving long strings all at once.
// This option inserts short delays between lines of serial output.
#define SERIAL_OVERRUN_PROTECTION
Expand Down
4 changes: 4 additions & 0 deletions Marlin/src/gcode/gcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 575: M575(); break; // M575: Set serial baudrate
#endif

#if ENABLED(BUFFER_MONITORING) // M576: Buffer monitoring
case 576: M576(); break;
#endif

#if ENABLED(ADVANCED_PAUSE_FEATURE)
case 600: M600(); break; // M600: Pause for Filament Change
case 603: M603(); break; // M603: Configure Filament Change
Expand Down
2 changes: 2 additions & 0 deletions Marlin/src/gcode/gcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,8 @@ class GcodeSuite {
static void M575();
#endif

TERN_(BUFFER_MONITORING, static void M576());

#if ENABLED(ADVANCED_PAUSE_FEATURE)
static void M600();
static void M603();
Expand Down
87 changes: 85 additions & 2 deletions Marlin/src/gcode/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,22 @@ GCodeQueue::RingBuffer GCodeQueue::ring_buffer = { 0 };
#endif

/**
* Serial command injection
* Track buffer underruns
*/
#if ENABLED(BUFFER_MONITORING)
uint32_t GCodeQueue::command_buffer_underruns = 0;
bool GCodeQueue::command_buffer_empty = false;
millis_t GCodeQueue::max_command_buffer_empty_duration = 0;
millis_t GCodeQueue::command_buffer_empty_at = 0;

uint32_t GCodeQueue::planner_buffer_underruns = 0;
bool GCodeQueue::planner_buffer_empty = false;
millis_t GCodeQueue::max_planner_buffer_empty_duration = 0;
millis_t GCodeQueue::planner_buffer_empty_at = 0;

uint8_t GCodeQueue::auto_buffer_report_interval;
millis_t GCodeQueue::next_buffer_report_ms;
#endif

/**
* Next Injected PROGMEM Command pointer. (nullptr == empty)
Expand Down Expand Up @@ -621,7 +635,27 @@ void GCodeQueue::advance() {
if (process_injected_command_P() || process_injected_command()) return;

// Return if the G-code buffer is empty
if (ring_buffer.empty()) return;
if (ring_buffer.empty()) {
#if ENABLED(BUFFER_MONITORING)
if (!command_buffer_empty) {
command_buffer_empty = true;
command_buffer_underruns++;
command_buffer_empty_at = millis();
}
#endif
return;
}

#if ENABLED(BUFFER_MONITORING)
if (command_buffer_empty) {
static millis_t command_buffer_empty_duration;
command_buffer_empty_duration = millis() - command_buffer_empty_at;
if (command_buffer_empty_duration > max_command_buffer_empty_duration) {
max_command_buffer_empty_duration = command_buffer_empty_duration;
}
command_buffer_empty = false;
}
#endif

#if ENABLED(SDSUPPORT)

Expand Down Expand Up @@ -664,3 +698,52 @@ void GCodeQueue::advance() {
// The queue may be reset by a command handler or by code invoked by idle() within a handler
ring_buffer.advance_pos(ring_buffer.index_r, -1);
}

#if ENABLED(BUFFER_MONITORING)
void GCodeQueue::report_buffer_statistics() {
SERIAL_ECHO("M576");
SERIAL_ECHOLNPAIR(SP_P_STR, int(planner.moves_free()),
SP_B_STR, int(BUFSIZE - length),
" PU", queue.planner_buffer_underruns,
" PD", queue.max_planner_buffer_empty_duration,
" BU", queue.command_buffer_underruns,
" BD", queue.max_command_buffer_empty_duration,
);

command_buffer_underruns = 0;
max_command_buffer_empty_duration = 0;

planner_buffer_underruns = 0;
max_planner_buffer_empty_duration = 0;
}

void GCodeQueue::auto_report_buffer_statistics() {
// Bit of a hack to try to catch planner buffer underruns without having logic
// running inside Stepper::block_phase_isr
if (planner.movesplanned() == 0) {
if (!planner_buffer_empty) { // if the planner buffer wasn't empty, but now it is
planner_buffer_empty = true;
planner_buffer_underruns++;
planner_buffer_empty_at = millis();
}
} else if (planner_buffer_empty) { // if the planner buffer was empty, but now it ain't
static millis_t planner_buffer_empty_duration;
planner_buffer_empty_duration = millis() - planner_buffer_empty_at;

// if it's longer than the currently tracked max duration, replace it
if (planner_buffer_empty_duration > max_planner_buffer_empty_duration) {
max_planner_buffer_empty_duration = planner_buffer_empty_duration;
}

planner_buffer_empty = false;
}

if (queue.auto_buffer_report_interval && ELAPSED(millis(), queue.next_buffer_report_ms)) {
queue.next_buffer_report_ms = millis() + 1000UL * queue.auto_buffer_report_interval;
PORT_REDIRECT(SERIAL_BOTH);
report_buffer_statistics();
PORT_RESTORE();
}
}

#endif
2 changes: 0 additions & 2 deletions Marlin/src/gcode/queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,6 @@ class GCodeQueue {
*/
static inline void set_current_line_number(long n) { serial_state[ring_buffer.command_port().index].last_N = n; }

private:

static void get_serial_commands();

#if ENABLED(SDSUPPORT)
Expand Down
54 changes: 54 additions & 0 deletions Marlin/src/gcode/stats/M576.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

#include "../../inc/MarlinConfig.h"
#include "../../MarlinCore.h" // for SP_P/B_STR, etc.

#if ENABLED(BUFFER_MONITORING)

#include "../gcode.h"
#include "../queue.h"

/**
* M576: Return buffer stats, and optionally set auto-report interval.
* Usage: M576 [S<seconds>]
*
* When called, printer emits the following output:
* "M576 P<nn> B<nn> PU<nn> PD<nn> BU<nn> BD<nn>"
* Where:
* P: Planner buffers available
* B: Command buffers available
* PU: Planner buffer underruns since last report
* PD: Maximum time in ms planner buffer was empty since last report
* BU: Command buffer underruns since last report
* BD: Maximum time in ms command buffer was empty since last report
*/
void GcodeSuite::M576() {
if (parser.seenval('S')) {
queue.set_auto_report_interval((uint8_t)parser.value_byte());
}

queue.report_buffer_statistics();
}

#endif // BUFFER_MONITORING

0 comments on commit 8444d59

Please sign in to comment.