summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2019-05-03 12:35:33 +1000
committerDamien George <damien.p.george@gmail.com>2019-05-22 12:47:19 +1000
commit302ffdba7f06e8827532834b5902406cd7bf4ea0 (patch)
tree43ee321ad7ef9a5d381c53256305a2a19d160660
parentd80abd035e209b8fcc399b142352a49702f701fc (diff)
nrf/uart: Change UART driver to be non-blocking and use IRQs.
As part of this, ctrl-C is now able to interrupt a running program.
-rw-r--r--ports/nrf/modules/machine/uart.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c
index cef98fb07..95921c055 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);
}