8000 mimxrt: Refactor timeout handling for uart.write(). · micropython/micropython@50f8566 · GitHub
[go: up one dir, main page]

Skip to content

Commit 50f8566

Browse files
committed
mimxrt: Refactor timeout handling for uart.write().
1. if a transmission is ongoing - if the blocking time is longer than the timeout, set MP_AGAIN and return MP_STREAM_ERROR. - If the blocking time is shorter than the timeout, wait. 2. if no transmission is ongoing - if the message is shorter than the buffer, just send it. - if the message is longer than the buffer and the expected blocking time is larger than the timeout, just send a buffer size amount of data and return that size. - if the message is longer than the buffer and the expected blocking time is smaller than the timeout, send all data and return that size.
1 parent e435583 commit 50f8566

File tree

1 file changed

+44
-28
lines changed

1 file changed

+44
-28
lines changed

ports/mimxrt/machine_uart.c

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "fsl_lpuart.h"
3434
#include "fsl_iomuxc.h"
3535
#include CLOCK_CONFIG_H
36-
3736
#define DEFAULT_UART_BAUDRATE (115200)
3837
#define DEFAULT_BUFFER_SIZE (256)
3938
#define MIN_BUFFER_SIZE (32)
@@ -372,12 +371,27 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin
372371
lpuart_transfer_t xfer;
373372
uint64_t t;
374373
size_t remaining = size;
375-
size_t offset = 0;
374+
size_t first_part_size = 0;
375+
uint32_t block_time;
376+
uint32_t timeout_budget = self->timeout;
376377
uint8_t fifo_size = FSL_FEATURE_LPUART_FIFO_SIZEn(0);
377378

378-
// First check if a previous transfer is still ongoing,
379-
// then wait at least the number of remaining character times.
380-
t = ticks_us64() + (uint64_t)(self->handle.txDataSize + fifo_size) * (13000000 / self->config.baudRate_Bps + 1000);
379+
// Check if a tansmission is still going on and will block longer than timeout
380+
// In that case, return immediately
381+
// For block time estimations, a 11 bit frame size is assumed instead of getting
382+
// actual frame size, for worst case timeouts a 13 bit frame.
383+
if (self->tx_status != kStatus_LPUART_TxIdle) {
384+
block_time = (self->handle.txDataSize + fifo_size) * 11000 / self->config.baudRate_Bps;
385+
if (timeout_budget < block_time) {
386+
*errcode = MP_EAGAIN;
387+
return MP_STREAM_ERROR;
388+
}
389+
timeout_budget -= block_time;
390+
}
391+
392+
// Now wait for the previous transfer to finish, but not longer than the expected
393+
// transfer time.
394+
t = ticks_us64() + (uint64_t)(self->handle.txDataSize + fifo_size) * 13000000 / self->config.baudRate_Bps + 1000;
381395
while (self->tx_status != kStatus_LPUART_TxIdle) {
382396
if (ticks_us64() > t) { // timed out, hard error
383397
*errcode = MP_ETIMEDOUT;
@@ -388,41 +402,43 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin
388402

389403
// Check if the first part has to be sent semi-blocking.
390404
if (size > self->txbuf_len) {
391-
// Send the first block.
392-
xfer.data = (uint8_t *)buf_in;
393-
offset = xfer.dataSize = size - self->txbuf_len;
394-
self->tx_status = kStatus_LPUART_TxBusy;
395-
LPUART_TransferSendNonBlocking(self->lpuart, &self->handle, &xfer);
396-
397-
// Wait at least the number of character times for this chunk.
398-
t = ticks_us64() + (uint64_t)xfer.dataSize * (13000000 / self->config.baudRate_Bps + 1000);
399-
while (self->tx_status != kStatus_LPUART_TxIdle) {
400-
// Wait for the first/next character to be sent.
401-
if (ticks_us64() > t) { // timed out
402-
if (self->handle.txDataSize >= size) {
403-
*errcode = MP_ETIMEDOUT;
404-
return MP_STREAM_ERROR;
405-
} else {
406-
return size - self->handle.txDataSize;
405+
// check if it blocks shorter than the remaining timeout budget
406+
block_time = (size - self->txbuf_len) * 11000 / self->config.baudRate_Bps;
407+
if (timeout_budget > block_time) {
408+
// Send the first block.
409+
xfer.data = (uint8_t *)buf_in;
410+
first_part_size = xfer.dataSize = size - self->txbuf_len;
411+
self->tx_status = kStatus_LPUART_TxBusy;
412+
LPUART_TransferSendNonBlocking(self->lpuart, &self->handle, &xfer);
413+
414+
// Wait at least the number of character times for this chunk.
415+
t = ticks_us64() + (uint64_t)(self->handle.txDataSize + fifo_size) *
416+
13000000 / self->config.baudRate_Bps + 1000;
417+
while (self->tx_status != kStatus_LPUART_TxIdle) {
418+
// Wait for the first/next character to be sent.
419+
if (ticks_us64() > t) { // timed out
420+
if (self->handle.txDataSize >= first_part_size) {
421+
*errcode = MP_ETIMEDOUT;
422+
return MP_STREAM_ERROR;
423+
} else {
424+
return first_part_size - self->handle.txDataSize;
425+
}
407426
}
427+
MICROPY_EVENT_POLL_HOOK
408428
}
409-
MICROPY_EVENT_POLL_HOOK
410429
}
430+
// In any case, just sent a buffer sized chunk in the next step
411431
remaining = self->txbuf_len;
412-
} else {
413-
// The data fits into the tx buffer.
414-
offset = 0;
415-
remaining = size;
416432
}
417433

418434
// Send the remaining data without waiting for completion.
419-
memcpy(self->txbuf, (uint8_t *)buf_in + offset, remaining);
435+
memcpy(self->txbuf, (uint8_t *)buf_in + first_part_size, remaining);
420436
xfer.data = self->txbuf;
421437
xfer.dataSize = remaining;
422438
self->tx_status = kStatus_LPUART_TxBusy;
423439
LPUART_TransferSendNonBlocking(self->lpuart, &self->handle, &xfer);
424440

425-
return size;
441+
return first_part_size + remaining;
426442
}
427443

428444
STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {

0 commit comments

Comments
 (0)
0