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.
pull/4404/head^2
Damien George 2019-05-03 12:35:33 +10:00
rodzic d80abd035e
commit 302ffdba7f
1 zmienionych plików z 42 dodań i 13 usunięć

Wyświetl plik

@ -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);
}