From 77630167e7983387d7e66142914a6e55fd2f5953 Mon Sep 17 00:00:00 2001 From: Markus Hitter Date: Mon, 3 Aug 2015 22:32:20 +0200 Subject: [PATCH] Serial: postpone sending "ok" until a slot is free. Previously acknoledgement was sent as soon as the command was parsed. Accordingly, the host would send the next command and this command would wait in the RX buffer without being parsed. This worked reasonably, unless an incoming line of G-code was longer than the RX buffer, in which case the line end was dropped and parsing of the line never completed. With a 64 bytes buffer on AVR this was rarely the case, with the 16 bytes hardware buffer on ARM LPC1114 it happens regularly. And there's no recovering from such a situation. This should solve issue #52. --- gcode_parse.c | 4 ++-- mendel.c | 24 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/gcode_parse.c b/gcode_parse.c index 3bff098..56c38e2 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -387,9 +387,9 @@ uint8_t gcode_parse_char(uint8_t c) { #endif ) { // process - serial_writestr_P(PSTR("ok ")); process_gcode_command(); - serial_writechar('\n'); + + // Acknowledgement ("ok") is sent in the main loop, in mendel.c. // expect next line number if (next_target.seen_N == 1) diff --git a/mendel.c b/mendel.c index 569566c..687edaf 100644 --- a/mendel.c +++ b/mendel.c @@ -261,6 +261,8 @@ int main (int argc, char** argv) int main (void) { #endif + uint8_t c, line_done, ack_waiting = 0; + init(); // main loop @@ -268,15 +270,33 @@ int main (void) { // if queue is full, no point in reading chars- host will just have to wait if (queue_full() == 0) { - uint8_t c, line_done; + /** + Postpone sending acknowledgement until there's a free slot in the + movement queue. This way the host waits with sending the next line + until it can be processed immediately. As a result, the serial receive + queue is always almost empty; it exists only for receiving via XON/XOFF + flow control. Another result is, the incoming line can be longer than + the receiving buffer, see Github issue #52. + + At the time of the introduction of this strategy gcode_parse_char() + parsed a single character in 100 to 400 CPU clocks, processing + the line end took some 30'000 clocks. 115200 baud mean one character + incoming every about 1250 CPU clocks on AVR 16 MHz. + */ + if (ack_waiting) { + serial_writestr_P(PSTR("ok\n")); + ack_waiting = 0; + } if (( ! gcode_active || gcode_active & GCODE_SOURCE_SERIAL) && serial_rxchars() != 0) { gcode_active = GCODE_SOURCE_SERIAL; c = serial_popchar(); line_done = gcode_parse_char(c); - if (line_done) + if (line_done) { gcode_active = 0; + ack_waiting = 1; + } } #ifdef SD