8000 nrf/uart: Change UART driver to be non-blocking and use IRQs. · devmonkZA/micropython@302ffdb · GitHub
[go: up one dir, main page]

Skip to content

Commit 302ffdb

Browse files
committed
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.
1 parent d80abd0 commit 302ffdb

File tree

1 file changed

+42
-13
lines changed
  • ports/nrf/modules/machine

1 file changed

+42
-13
lines changed

ports/nrf/modules/machine/uart.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@
3535
#include "py/stream.h"
3636
#include "py/mperrno.h"
3737
#include "py/mphal.h"
38+
#include "py/ringbuf.h"
3839
#include "pin.h"
3940
#include "genhdr/pins.h"
41+
#include "lib/utils/interrupt_char.h"
4042

4143
#include "uart.h"
4244
#include "mpconfigboard.h"
@@ -47,15 +49,25 @@
4749

4850
#if MICROPY_PY_MACHINE_UART
4951

52+
typedef struct _machine_hard_uart_buf_t {
53+
uint8_t tx_buf[1];
54+
uint8_t rx_buf[1];
55+
uint8_t rx_ringbuf_array[64];
56+
volatile ringbuf_t rx_ringbuf;
57+
} machine_hard_uart_buf_t;
58+
5059
typedef struct _machine_hard_uart_obj_t {
5160
mp_obj_base_t base;
5261
const nrfx_uart_t * p_uart; // Driver instance
62+
machine_hard_uart_buf_t *buf;
5363
} machine_hard_uart_obj_t;
5464

5565
static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE(0);
5666

67+
STATIC machine_hard_uart_buf_t machine_hard_uart_buf[1];
68+
5769
STATIC const machine_hard_uart_obj_t machine_hard_uart_obj[] = {
58-
{{&machine_hard_uart_type}, .p_uart = &instance0},
70+
{{&machine_hard_uart_type}, .p_uart = &instance0, .buf = &machine_hard_uart_buf[0]},
5971
};
6072

6173
void uart_init0(void) {
@@ -70,27 +82,36 @@ STATIC int uart_find(mp_obj_t id) {
7082
mp_raise_ValueError("UART doesn't exist");
7183
}
7284

73-
void uart_irq_handler(mp_uint_t uart_id) {
74-
85+
STATIC void uart_event_handler(nrfx_uart_event_t const *p_event, void *p_context) {
86+
machine_hard_uart_obj_t *self = p_context;
87+
if (p_event->type == NRFX_UART_EVT_RX_DONE) {
88+
int chr = self->buf->rx_buf[0];
89+
nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1);
90+
#if !MICROPY_PY_BLE_NUS && MICROPY_KBD_EXCEPTION
91+
if (chr == mp_interrupt_char) {
92+
mp_keyboard_interrupt();
93+
} else
94+
#endif
95+
{
96+
ringbuf_put((ringbuf_t*)&self->buf->rx_ringbuf, chr);
97+
}
98+
}
7599
}
76100

77-
bool uart_rx_any(const machine_hard_uart_obj_t *uart_obj) {
78-
// TODO: uart will block for now.
79-
return true;
101+
bool uart_rx_any(const machine_hard_uart_obj_t *self) {
102+
return self->buf->rx_ringbuf.iput != self->buf->rx_ringbuf.iget;
80103
}
81104

82105
int uart_rx_char(const machine_hard_uart_obj_t * self) {
83-
uint8_t ch;
84-
nrfx_uart_rx(self->p_uart, &ch, 1);
85-
return (int)ch;
106+
return ringbuf_get((ringbuf_t*)&self->buf->rx_ringbuf);
86107
}
87108

88109
STATIC nrfx_err_t uart_tx_char(const machine_hard_uart_obj_t * self, int c) {
89110
while (nrfx_uart_tx_in_progress(self->p_uart)) {
90111
;
91112
}
92-
93-
return nrfx_uart_tx(self->p_uart, (uint8_t *)&c, 1);
113+
self->buf->tx_buf[0] = c;
114+
return nrfx_uart_tx(self->p_uart, &self->buf->tx_buf[0], 1);
94115
}
95116

96117

@@ -181,9 +202,15 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a
181202
// Set context to this instance of UART
182203
config.p_context = (void *)self;
183204

184-
// Set NULL as callback function to keep it blocking
185-
nrfx_uart_init(self->p_uart, &config, NULL);
205+
// Initialise ring buffer
206+
self->buf->rx_ringbuf.buf = self->buf->rx_ringbuf_array;
207+
self->buf->rx_ringbuf.size = sizeof(self->buf->rx_ringbuf_array);
208+
self->buf->rx_ringbuf.iget = 0;
209+
self->buf->rx_ringbuf.iput = 0;
186210

211+
// Enable event callback and start asynchronous receive
212+
nrfx_uart_init(self->p_uart, &config, uart_event_handler);
213+
nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1);
187214
nrfx_uart_rx_enable(self->p_uart);
188215

189216
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_
250277

251278
// read the data
252279
for (size_t i = 0; i < size; i++) {
280+
while (!uart_rx_any(self)) {
281+
}
253282
buf[i] = uart_rx_char(self);
254283
}
255284

0 commit comments

Comments
 (0)
0