diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index cef98fb07f..95921c055d 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -35,8 +35,10 @@ #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" +#include "py/ringbuf.h" #include "pin.h" #include "genhdr/pins.h" +#include "lib/utils/interrupt_char.h" #include "uart.h" #include "mpconfigboard.h" @@ -47,15 +49,25 @@ #if MICROPY_PY_MACHINE_UART +typedef struct _machine_hard_uart_buf_t { + uint8_t tx_buf[1]; + uint8_t rx_buf[1]; + uint8_t rx_ringbuf_array[64]; + volatile ringbuf_t rx_ringbuf; +} machine_hard_uart_buf_t; + typedef struct _machine_hard_uart_obj_t { mp_obj_base_t base; const nrfx_uart_t * p_uart; // Driver instance + machine_hard_uart_buf_t *buf; } machine_hard_uart_obj_t; static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE(0); +STATIC machine_hard_uart_buf_t machine_hard_uart_buf[1]; + STATIC const machine_hard_uart_obj_t machine_hard_uart_obj[] = { - {{&machine_hard_uart_type}, .p_uart = &instance0}, + {{&machine_hard_uart_type}, .p_uart = &instance0, .buf = &machine_hard_uart_buf[0]}, }; void uart_init0(void) { @@ -70,27 +82,36 @@ STATIC int uart_find(mp_obj_t id) { mp_raise_ValueError("UART doesn't exist"); } -void uart_irq_handler(mp_uint_t uart_id) { - +STATIC void uart_event_handler(nrfx_uart_event_t const *p_event, void *p_context) { + machine_hard_uart_obj_t *self = p_context; + if (p_event->type == NRFX_UART_EVT_RX_DONE) { + int chr = self->buf->rx_buf[0]; + nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1); + #if !MICROPY_PY_BLE_NUS && MICROPY_KBD_EXCEPTION + if (chr == mp_interrupt_char) { + mp_keyboard_interrupt(); + } else + #endif + { + ringbuf_put((ringbuf_t*)&self->buf->rx_ringbuf, chr); + } + } } -bool uart_rx_any(const machine_hard_uart_obj_t *uart_obj) { - // TODO: uart will block for now. - return true; +bool uart_rx_any(const machine_hard_uart_obj_t *self) { + return self->buf->rx_ringbuf.iput != self->buf->rx_ringbuf.iget; } int uart_rx_char(const machine_hard_uart_obj_t * self) { - uint8_t ch; - nrfx_uart_rx(self->p_uart, &ch, 1); - return (int)ch; + return ringbuf_get((ringbuf_t*)&self->buf->rx_ringbuf); } STATIC nrfx_err_t uart_tx_char(const machine_hard_uart_obj_t * self, int c) { while (nrfx_uart_tx_in_progress(self->p_uart)) { ; } - - return nrfx_uart_tx(self->p_uart, (uint8_t *)&c, 1); + self->buf->tx_buf[0] = c; + return nrfx_uart_tx(self->p_uart, &self->buf->tx_buf[0], 1); } @@ -181,9 +202,15 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a // Set context to this instance of UART config.p_context = (void *)self; - // Set NULL as callback function to keep it blocking - nrfx_uart_init(self->p_uart, &config, NULL); + // Initialise ring buffer + self->buf->rx_ringbuf.buf = self->buf->rx_ringbuf_array; + self->buf->rx_ringbuf.size = sizeof(self->buf->rx_ringbuf_array); + self->buf->rx_ringbuf.iget = 0; + self->buf->rx_ringbuf.iput = 0; + // Enable event callback and start asynchronous receive + nrfx_uart_init(self->p_uart, &config, uart_event_handler); + nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1); nrfx_uart_rx_enable(self->p_uart); return MP_OBJ_FROM_PTR(self); @@ -250,6 +277,8 @@ STATIC mp_uint_t machine_hard_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_ // read the data for (size_t i = 0; i < size; i++) { + while (!uart_rx_any(self)) { + } buf[i] = uart_rx_char(self); }