Skip to content

Commit b85ad4b

Browse files
robert-hhdpgeorge
authored andcommitted
mimxrt/machine_uart: Fix rx/tx buffer allocation bug.
The buffer would be reset on every call to `uart.init()`. If no sizes were given, the buffer would be set to the default size 256. That made problems e.g. with PPP. Also, the RX buffer was not stored at the UART object and not visible to GC as being in use. Then a `gc.collect()` would eventually free the buffer. This commit fixes those issues, keeping the buffer size if not deliberately changed and allocating new buffers only if the size was changed. Signed-off-by: robert-hh <[email protected]>
1 parent 1398e7f commit b85ad4b

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

ports/mimxrt/machine_uart.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ typedef struct _machine_uart_obj_t {
6666
uint16_t tx_status;
6767
uint8_t *txbuf;
6868
uint16_t txbuf_len;
69+
uint8_t *rxbuf;
70+
uint16_t rxbuf_len;
6971
bool new;
7072
uint16_t mp_irq_trigger; // user IRQ trigger mask
7173
uint16_t mp_irq_flags; // user IRQ active IRQ flags
@@ -197,7 +199,7 @@ static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_
197199
self->id, self->config.baudRate_Bps, 8 - self->config.dataBitsCount,
198200
_parity_name[self->config.parityMode], self->config.stopBitCount + 1,
199201
_flow_name[(self->config.enableTxCTS << 1) | self->config.enableRxRTS],
200-
self->handle.rxRingBufferSize, self->txbuf_len, self->timeout, self->timeout_char,
202+
self->rxbuf_len, self->txbuf_len, self->timeout, self->timeout_char,
201203
_invert_name[self->invert], self->mp_irq_trigger);
202204
}
203205

@@ -291,25 +293,33 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
291293
self->config.enableRx = true;
292294

293295
// Set the RX buffer size if configured.
294-
size_t rxbuf_len = DEFAULT_BUFFER_SIZE;
295296
if (args[ARG_rxbuf].u_int > 0) {
296-
rxbuf_len = args[ARG_rxbuf].u_int;
297+
size_t rxbuf_len = args[ARG_rxbuf].u_int;
297298
if (rxbuf_len < MIN_BUFFER_SIZE) {
298299
rxbuf_len = MIN_BUFFER_SIZE;
299300
} else if (rxbuf_len > MAX_BUFFER_SIZE) {
300301
mp_raise_ValueError(MP_ERROR_TEXT("rxbuf too large"));
301302
}
303+
// Force re-allocting of the buffer if the size changed
304+
if (rxbuf_len != self->rxbuf_len) {
305+
self->rxbuf = NULL;
306+
self->rxbuf_len = rxbuf_len;
307+
}
302308
}
303309

304310
// Set the TX buffer size if configured.
305-
size_t txbuf_len = DEFAULT_BUFFER_SIZE;
306311
if (args[ARG_txbuf].u_int > 0) {
307-
txbuf_len = args[ARG_txbuf].u_int;
312+
size_t txbuf_len = args[ARG_txbuf].u_int;
308313
if (txbuf_len < MIN_BUFFER_SIZE) {
309314
txbuf_len = MIN_BUFFER_SIZE;
310315
} else if (txbuf_len > MAX_BUFFER_SIZE) {
311316
mp_raise_ValueError(MP_ERROR_TEXT("txbuf too large"));
312317
}
318+
// Force re-allocting of the buffer if the size is changed
319+
if (txbuf_len != self->txbuf_len) {
320+
self->txbuf = NULL;
321+
self->txbuf_len = txbuf_len;
322+
}
313323
}
314324

315325
// Initialise the UART peripheral if any arguments given, or it was not initialised previously.
@@ -335,10 +345,13 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
335345
LPUART_Init(self->lpuart, &self->config, CLOCK_GetClockRootFreq(kCLOCK_UartClkRoot));
336346
#endif
337347
LPUART_TransferCreateHandle(self->lpuart, &self->handle, LPUART_UserCallback, self);
338-
uint8_t *buffer = m_new(uint8_t, rxbuf_len + 1);
339-
LPUART_TransferStartRingBuffer(self->lpuart, &self->handle, buffer, rxbuf_len);
340-
self->txbuf = m_new(uint8_t, txbuf_len); // Allocate the TX buffer.
341-
self->txbuf_len = txbuf_len;
348+
if (self->rxbuf == NULL) {
349+
self->rxbuf = m_new(uint8_t, self->rxbuf_len + 1);
350+
}
351+
LPUART_TransferStartRingBuffer(self->lpuart, &self->handle, self->rxbuf, self->rxbuf_len);
352+
if (self->txbuf == NULL) {
353+
self->txbuf = m_new(uint8_t, self->txbuf_len); // Allocate the TX buffer.
354+
}
342355

343356
#if MICROPY_PY_MACHINE_UART_IRQ
344357
LPUART_EnableInterrupts(self->lpuart, kLPUART_IdleLineInterruptEnable);
@@ -380,6 +393,10 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
380393
self->invert = false;
381394
self->timeout = 1;
382395
self->timeout_char = 1;
396+
self->rxbuf = NULL;
397+
self->rxbuf_len = DEFAULT_BUFFER_SIZE;
398+
self->txbuf = NULL;
399+
self->txbuf_len = DEFAULT_BUFFER_SIZE;
383400
self->new = true;
384401
self->mp_irq_obj = NULL;
385402
self->mp_irq_trigger = 0;

0 commit comments

Comments
 (0)