aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/chelper/serialqueue.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2018-05-28 09:42:59 -0400
committerKevin O'Connor <kevin@koconnor.net>2018-05-28 11:12:30 -0400
commitd798fae20b1cd87396ea884de737aa7f3e359193 (patch)
tree607759d9360d7d2e69cf638913f72155586a0d47 /klippy/chelper/serialqueue.c
parent0728c1a8be5f76d62fae79a9adcc998081049f9e (diff)
downloadkutter-d798fae20b1cd87396ea884de737aa7f3e359193.tar.gz
kutter-d798fae20b1cd87396ea884de737aa7f3e359193.tar.xz
kutter-d798fae20b1cd87396ea884de737aa7f3e359193.zip
serialqueue: Limit message transmission to available receive buffer size
If the mcu is using a traditional serial port, then only send a new message block if there is space available in the mcu receive buffer. This should make it significantly less likely that high load on the mcu will result in retransmits. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy/chelper/serialqueue.c')
-rw-r--r--klippy/chelper/serialqueue.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/klippy/chelper/serialqueue.c b/klippy/chelper/serialqueue.c
index 06ee0ee0..4a18e845 100644
--- a/klippy/chelper/serialqueue.c
+++ b/klippy/chelper/serialqueue.c
@@ -357,6 +357,7 @@ struct serialqueue {
pthread_cond_t cond;
int receive_waiting;
// Baud / clock tracking
+ int receive_window;
double baud_adjust, idle_time;
double est_freq, last_clock_time;
uint64_t last_clock;
@@ -368,7 +369,7 @@ struct serialqueue {
double srtt, rttvar, rto;
// Pending transmission message queues
struct list_head pending_queues;
- int ready_bytes, stalled_bytes, need_ack_bytes;
+ int ready_bytes, stalled_bytes, need_ack_bytes, last_ack_bytes;
uint64_t need_kick_clock;
// Received messages
struct list_head receive_queue;
@@ -458,6 +459,7 @@ update_receive_seq(struct serialqueue *sq, double eventtime, uint64_t rseq)
if (rseq == sent_seq) {
// Found sent message corresponding with the received sequence
sq->last_receive_sent_time = sent->receive_time;
+ sq->last_ack_bytes = sent->len;
break;
}
}
@@ -694,11 +696,18 @@ build_and_send_command(struct serialqueue *sq, double eventtime)
static double
check_send_command(struct serialqueue *sq, double eventtime)
{
- if ((sq->send_seq - sq->receive_seq >= MESSAGE_SEQ_MASK
- || (sq->need_ack_bytes - 2*MESSAGE_MAX) * sq->baud_adjust > sq->srtt)
+ if (sq->send_seq - sq->receive_seq >= MESSAGE_SEQ_MASK
&& sq->receive_seq != (uint64_t)-1)
// Need an ack before more messages can be sent
return PR_NEVER;
+ if (sq->send_seq > sq->receive_seq && sq->receive_window) {
+ int need_ack_bytes = sq->need_ack_bytes + MESSAGE_MAX;
+ if (sq->last_ack_seq < sq->receive_seq)
+ need_ack_bytes += sq->last_ack_bytes;
+ if (need_ack_bytes > sq->receive_window)
+ // Wait for ack from past messages before sending next message
+ return PR_NEVER;
+ }
// Check for stalled messages now ready
double idletime = eventtime > sq->idle_time ? eventtime : sq->idle_time;
@@ -1021,6 +1030,14 @@ serialqueue_set_baud_adjust(struct serialqueue *sq, double baud_adjust)
pthread_mutex_unlock(&sq->lock);
}
+void
+serialqueue_set_receive_window(struct serialqueue *sq, int receive_window)
+{
+ pthread_mutex_lock(&sq->lock);
+ sq->receive_window = receive_window;
+ pthread_mutex_unlock(&sq->lock);
+}
+
// Set the estimated clock rate of the mcu on the other end of the
// serial port
void