Skip to content
Snippets Groups Projects
Commit 302ffdba authored by Damien George's avatar Damien George
Browse files

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.
parent d80abd03
No related branches found
No related tags found
No related merge requests found
...@@ -35,8 +35,10 @@ ...@@ -35,8 +35,10 @@
#include "py/stream.h" #include "py/stream.h"
#include "py/mperrno.h" #include "py/mperrno.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "py/ringbuf.h"
#include "pin.h" #include "pin.h"
#include "genhdr/pins.h" #include "genhdr/pins.h"
#include "lib/utils/interrupt_char.h"
#include "uart.h" #include "uart.h"
#include "mpconfigboard.h" #include "mpconfigboard.h"
...@@ -47,15 +49,25 @@ ...@@ -47,15 +49,25 @@
#if MICROPY_PY_MACHINE_UART #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 { typedef struct _machine_hard_uart_obj_t {
mp_obj_base_t base; mp_obj_base_t base;
const nrfx_uart_t * p_uart; // Driver instance const nrfx_uart_t * p_uart; // Driver instance
machine_hard_uart_buf_t *buf;
} machine_hard_uart_obj_t; } machine_hard_uart_obj_t;
static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE(0); 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[] = { 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) { void uart_init0(void) {
...@@ -70,27 +82,36 @@ STATIC int uart_find(mp_obj_t id) { ...@@ -70,27 +82,36 @@ STATIC int uart_find(mp_obj_t id) {
mp_raise_ValueError("UART doesn't exist"); 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) { bool uart_rx_any(const machine_hard_uart_obj_t *self) {
// TODO: uart will block for now. return self->buf->rx_ringbuf.iput != self->buf->rx_ringbuf.iget;
return true;
} }
int uart_rx_char(const machine_hard_uart_obj_t * self) { int uart_rx_char(const machine_hard_uart_obj_t * self) {
uint8_t ch; return ringbuf_get((ringbuf_t*)&self->buf->rx_ringbuf);
nrfx_uart_rx(self->p_uart, &ch, 1);
return (int)ch;
} }
STATIC nrfx_err_t uart_tx_char(const machine_hard_uart_obj_t * self, int c) { 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)) { while (nrfx_uart_tx_in_progress(self->p_uart)) {
; ;
} }
self->buf->tx_buf[0] = c;
return nrfx_uart_tx(self->p_uart, (uint8_t *)&c, 1); 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 ...@@ -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 // Set context to this instance of UART
config.p_context = (void *)self; config.p_context = (void *)self;
// Set NULL as callback function to keep it blocking // Initialise ring buffer
nrfx_uart_init(self->p_uart, &config, NULL); 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); nrfx_uart_rx_enable(self->p_uart);
return MP_OBJ_FROM_PTR(self); 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_ ...@@ -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 // read the data
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
while (!uart_rx_any(self)) {
}
buf[i] = uart_rx_char(self); buf[i] = uart_rx_char(self);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment