Skip to content

Commit d140327

Browse files
committed
samd/machine_uart.c: Fix unintended UART buffer allocation on init().
The buffer was be reset on every call to uart.init(). If no sizes were given, the buffer was be set to the default size 256. That made problems e.g. with PPP. This PR fixes it, keeping the buffer size if not deliberately changed and allocating new buffers only if the size was changed. Cater for changes of the bits value, which require a change to the buffer size. Fix a lock-up in loopback mode if the read buffer is full. Signed-off-by: robert-hh <robert@hammelrath.com>
1 parent 4f5c856 commit d140327

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

ports/samd/machine_uart.c

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ typedef struct _machine_uart_obj_t {
8888
uint16_t timeout; // timeout waiting for first char (in ms)
8989
uint16_t timeout_char; // timeout waiting between chars (in ms)
9090
bool new;
91+
uint16_t rxbuf_len;
9192
ringbuf_t read_buffer;
9293
#if MICROPY_HW_UART_TXBUF
94+
uint16_t txbuf_len;
9395
ringbuf_t write_buffer;
9496
#endif
9597
#if MICROPY_PY_MACHINE_UART_IRQ
@@ -154,7 +156,8 @@ void common_uart_irq_handler(int uart_id) {
154156
}
155157
}
156158
#endif
157-
} else if (uart->USART.INTFLAG.bit.DRE != 0) {
159+
}
160+
if (uart->USART.INTFLAG.bit.DRE != 0) {
158161
#if MICROPY_HW_UART_TXBUF
159162
// handle the outgoing data
160163
if (ringbuf_avail(&self->write_buffer) > 0) {
@@ -287,16 +290,6 @@ void machine_uart_set_baudrate(mp_obj_t self_in, uint32_t baudrate) {
287290

288291
static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
289292
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
290-
size_t rxbuf_len = self->read_buffer.size - 1;
291-
#if MICROPY_HW_UART_TXBUF
292-
size_t txbuf_len = self->write_buffer.size - 1;
293-
#endif
294-
if (self->bits > 8) {
295-
rxbuf_len /= 2;
296-
#if MICROPY_HW_UART_TXBUF
297-
txbuf_len /= 2;
298-
#endif
299-
}
300293

301294
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, "
302295
"tx=\"%q\", rx=\"%q\", timeout=%u, timeout_char=%u, rxbuf=%d"
@@ -312,9 +305,9 @@ static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_
312305
")",
313306
self->id, self->baudrate, self->bits, _parity_name[self->parity],
314307
self->stop + 1, pin_find_by_id(self->tx)->name, pin_find_by_id(self->rx)->name,
315-
self->timeout, self->timeout_char, rxbuf_len
308+
self->timeout, self->timeout_char, self->rxbuf_len
316309
#if MICROPY_HW_UART_TXBUF
317-
, txbuf_len
310+
, self->txbuf_len
318311
#endif
319312
#if MICROPY_HW_UART_RTSCTS
320313
, self->rts != 0xff ? pin_find_by_id(self->rts)->name : MP_QSTR_None
@@ -358,6 +351,11 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
358351
// Set bits if configured.
359352
if (args[ARG_bits].u_int > 0) {
360353
self->bits = args[ARG_bits].u_int;
354+
// Invalidate the buffers since the size may have to be changed
355+
self->read_buffer.buf = NULL;
356+
#if MICROPY_HW_UART_TXBUF
357+
self->write_buffer.buf = NULL;
358+
#endif
361359
}
362360

363361
// Set parity if configured.
@@ -414,26 +412,36 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
414412
}
415413

416414
// Set the RX buffer size if configured.
417-
size_t rxbuf_len = DEFAULT_BUFFER_SIZE;
415+
size_t rxbuf_len = self->rxbuf_len;
418416
if (args[ARG_rxbuf].u_int > 0) {
419417
rxbuf_len = args[ARG_rxbuf].u_int;
420418
if (rxbuf_len < MIN_BUFFER_SIZE) {
421419
rxbuf_len = MIN_BUFFER_SIZE;
422420
} else if (rxbuf_len > MAX_BUFFER_SIZE) {
423421
mp_raise_ValueError(MP_ERROR_TEXT("rxbuf too large"));
424422
}
423+
// Force re-allocting of the buffer if the size changed
424+
if (rxbuf_len != self->rxbuf_len) {
425+
self->read_buffer.buf = NULL;
426+
self->rxbuf_len = rxbuf_len;
427+
}
425428
}
426429

427430
#if MICROPY_HW_UART_TXBUF
428431
// Set the TX buffer size if configured.
429-
size_t txbuf_len = DEFAULT_BUFFER_SIZE;
432+
size_t txbuf_len = self->txbuf_len;
430433
if (args[ARG_txbuf].u_int > 0) {
431434
txbuf_len = args[ARG_txbuf].u_int;
432435
if (txbuf_len < MIN_BUFFER_SIZE) {
433436
txbuf_len = MIN_BUFFER_SIZE;
434437
} else if (txbuf_len > MAX_BUFFER_SIZE) {
435438
mp_raise_ValueError(MP_ERROR_TEXT("txbuf too large"));
436439
}
440+
// Force re-allocting of the buffer if the size changed
441+
if (txbuf_len != self->txbuf_len) {
442+
self->write_buffer.buf = NULL;
443+
self->txbuf_len = txbuf_len;
444+
}
437445
}
438446
#endif
439447

@@ -462,10 +470,14 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
462470
}
463471

464472
// Allocate the RX/TX buffers.
465-
ringbuf_alloc(&(self->read_buffer), rxbuf_len + 1);
473+
if (self->read_buffer.buf == NULL) {
474+
ringbuf_alloc(&(self->read_buffer), rxbuf_len + 1);
475+
}
466476

467477
#if MICROPY_HW_UART_TXBUF
468-
ringbuf_alloc(&(self->write_buffer), txbuf_len + 1);
478+
if (self->write_buffer.buf == NULL) {
479+
ringbuf_alloc(&(self->write_buffer), txbuf_len + 1);
480+
}
469481
#endif
470482

471483
// Step 1: Configure the Pin mux.
@@ -503,6 +515,12 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
503515
self->stop = 0;
504516
self->timeout = 1;
505517
self->timeout_char = 1;
518+
self->rxbuf_len = DEFAULT_BUFFER_SIZE;
519+
self->read_buffer.buf = NULL;
520+
#if MICROPY_HW_UART_TXBUF
521+
self->txbuf_len = DEFAULT_BUFFER_SIZE;
522+
self->write_buffer.buf = NULL;
523+
#endif
506524
#if defined(pin_TX) && defined(pin_RX)
507525
// Initialize with the default pins
508526
self->tx = mp_hal_get_pin_obj((mp_obj_t)pin_TX);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy