aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--klippy/chelper/serialqueue.c14
-rw-r--r--src/command.c12
-rw-r--r--src/command.h1
-rw-r--r--src/generic/serial_irq.c5
-rw-r--r--src/pru/pru0.c4
5 files changed, 27 insertions, 9 deletions
diff --git a/klippy/chelper/serialqueue.c b/klippy/chelper/serialqueue.c
index ab55d176..06ee0ee0 100644
--- a/klippy/chelper/serialqueue.c
+++ b/klippy/chelper/serialqueue.c
@@ -363,7 +363,7 @@ struct serialqueue {
double last_receive_sent_time;
// Retransmit support
uint64_t send_seq, receive_seq;
- uint64_t ignore_nak_seq, retransmit_seq, rtt_sample_seq;
+ uint64_t ignore_nak_seq, last_ack_seq, retransmit_seq, rtt_sample_seq;
struct list_head sent_queue;
double srtt, rttvar, rto;
// Pending transmission message queues
@@ -509,10 +509,14 @@ handle_message(struct serialqueue *sq, double eventtime, int len)
if (rseq != sq->receive_seq)
// New sequence number
update_receive_seq(sq, eventtime, rseq);
- else if (len == MESSAGE_MIN && rseq > sq->ignore_nak_seq
- && !list_empty(&sq->sent_queue))
- // Duplicate sequence number in an empty message is a nak
- pollreactor_update_timer(&sq->pr, SQPT_RETRANSMIT, PR_NOW);
+ if (len == MESSAGE_MIN) {
+ // Ack/nak message
+ if (sq->last_ack_seq < rseq)
+ sq->last_ack_seq = rseq;
+ else if (rseq > sq->ignore_nak_seq && !list_empty(&sq->sent_queue))
+ // Duplicate Ack is a Nak - do fast retransmit
+ pollreactor_update_timer(&sq->pr, SQPT_RETRANSMIT, PR_NOW);
+ }
if (len > MESSAGE_MIN) {
// Add message to receive queue
diff --git a/src/command.c b/src/command.c
index 2df70d85..b0c7f882 100644
--- a/src/command.c
+++ b/src/command.c
@@ -257,7 +257,6 @@ command_find_block(uint8_t *buf, uint_fast8_t buf_len, uint_fast8_t *pop_count)
goto nak;
}
next_sequence = ((msgseq + 1) & MESSAGE_SEQ_MASK) | MESSAGE_DEST;
- command_sendf(&encode_acknak);
return 1;
need_more_data:
@@ -308,13 +307,22 @@ command_dispatch(uint8_t *buf, uint_fast8_t msglen)
}
}
+// Send an ack message to the host (notifying that it can send more data)
+void
+command_send_ack(void)
+{
+ command_sendf(&encode_acknak);
+}
+
// Find a message block and then dispatch all the commands in it
int_fast8_t
command_find_and_dispatch(uint8_t *buf, uint_fast8_t buf_len
, uint_fast8_t *pop_count)
{
int_fast8_t ret = command_find_block(buf, buf_len, pop_count);
- if (ret > 0)
+ if (ret > 0) {
command_dispatch(buf, *pop_count);
+ command_send_ack();
+ }
return ret;
}
diff --git a/src/command.h b/src/command.h
index 035d3929..92315f38 100644
--- a/src/command.h
+++ b/src/command.h
@@ -72,6 +72,7 @@ void command_sendf(const struct command_encoder *ce, ...);
int_fast8_t command_find_block(uint8_t *buf, uint_fast8_t buf_len
, uint_fast8_t *pop_count);
void command_dispatch(uint8_t *buf, uint_fast8_t msglen);
+void command_send_ack(void);
int_fast8_t command_find_and_dispatch(uint8_t *buf, uint_fast8_t buf_len
, uint_fast8_t *pop_count);
diff --git a/src/generic/serial_irq.c b/src/generic/serial_irq.c
index 6b682a0f..a035364b 100644
--- a/src/generic/serial_irq.c
+++ b/src/generic/serial_irq.c
@@ -75,8 +75,11 @@ console_task(void)
int_fast8_t ret = command_find_block(receive_buf, rpos, &pop_count);
if (ret > 0)
command_dispatch(receive_buf, pop_count);
- if (ret)
+ if (ret) {
console_pop_input(pop_count);
+ if (ret > 0)
+ command_send_ack();
+ }
}
DECL_TASK(console_task);
diff --git a/src/pru/pru0.c b/src/pru/pru0.c
index 2a136e9e..4b60af27 100644
--- a/src/pru/pru0.c
+++ b/src/pru/pru0.c
@@ -148,8 +148,10 @@ check_can_read(void)
int_fast8_t ret = command_find_block(p, msglen, &pop_count);
if (!ret)
break;
- if (ret > 0)
+ if (ret > 0) {
do_dispatch(p, pop_count);
+ command_send_ack();
+ }
p += pop_count;
len -= pop_count;
}