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.
This commit is contained in:
Markus Hitter 2015-08-03 22:32:20 +02:00
parent a1feb32fe3
commit 77630167e7
2 changed files with 24 additions and 4 deletions

View File

@ -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)

View File

@ -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