8000 Merge pull request #1402 from hathach/nrf_uartio_fix · eighthree/circuitpython@5e4b3a8 · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Nov 27, 2024. It is now read-only.

Commit 5e4b3a8

Browse files
authored
Merge pull request adafruit#1402 from hathach/nrf_uartio_fix
use rbuf for busio uart
2 parents 6773fe6 + b37b2fa commit 5e4b3a8

File tree

2 files changed

+64
-53
lines changed

2 files changed

+64
-53
lines changed

ports/nrf/common-hal/busio/UART.c

Lines changed: 62 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,44 @@
5252

5353
static uint32_t get_nrf_baud (uint32_t baudrate);
5454

55+
static uint16_t ringbuf_count(ringbuf_t *r)
56+
{
57+
volatile int count = r->iput - r->iget;
58+
if ( count < 0 ) {
59+
count += r->size;
60+
}
61+
62+
return (uint16_t) count;
63+
}
64+
65+
static void ringbuf_clear(ringbuf_t *r)
66+
{
67+
r->iput = r->iget = 0;
68+
}
69+
5570
static void uart_callback_irq (const nrfx_uarte_event_t * event, void * context) {
5671
busio_uart_obj_t* self = (busio_uart_obj_t*) context;
5772

5873
switch ( event->type ) {
5974
case NRFX_UARTE_EVT_RX_DONE:
60-
self->rx_count = event->data.rxtx.bytes;
75+
for(uint8_t i=0; i < event->data.rxtx.bytes; i++) {
76+
if ( ringbuf_put(&self->rbuf, event->data.rxtx.p_data[i]) < 0 ) {
77+
// if full overwrite old data
78+
(void) ringbuf_get(&self->rbuf);
79+
ringbuf_put(&self->rbuf, event->data.rxtx.p_data[i]);
80+
}
81+
}
82+
83+
// keep receiving
84+
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, &self->rx_char, 1));
6185
break;
6286

6387
case NRFX_UARTE_EVT_TX_DONE:
88+
// nothing to do
6489
break;
6590

6691
case NRFX_UARTE_EVT_ERROR:
67-
if ( self->rx_count == -1 ) {
68-
self->rx_count = 0;
69-
}
92+
// Handle error
7093
break;
7194

7295
default:
@@ -110,12 +133,15 @@ void common_hal_busio_uart_construct (busio_uart_obj_t *self,
110133

111134
// Init buffer for rx
112135
if ( rx != mp_const_none ) {
113-
self->buffer = (uint8_t *) gc_alloc(receiver_buffer_size, false, false);
114-
if ( !self->buffer ) {
136+
self->rbuf.buf = (uint8_t *) gc_alloc(receiver_buffer_size, false, false);
137+
138+
if ( !self->rbuf.buf ) {
115139
nrfx_uarte_uninit(&self->uarte);
116140
mp_raise_msg(&mp_type_MemoryError, translate("Failed to allocate RX buffer"));
117141
}
118-
self->bufsize = receiver_buffer_size;
142+
143+
self->rbuf.size = receiver_buffer_size;
144+
self->rbuf.iget = self->rbuf.iput = 0;
119145

120146
self->rx_pin_number = rx->number;
121147
claim_pin(rx);
@@ -131,9 +157,8 @@ void common_hal_busio_uart_construct (busio_uart_obj_t *self,
131157
self->baudrate = baudrate;
132158
self->timeout_ms = timeout * 1000;
133159

134-
// queue 1-byte transfer for rx_characters_available()
135-
self->rx_count = -1;
136-
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1));
160+
// Initial wait for incoming byte
161+
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, &self->rx_char, 1));
137162
}
138163

139164
bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
@@ -147,7 +172,10 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
147172
reset_pin_number(self->rx_pin_number);
148173
self->tx_pin_number = NO_PIN;
149174
self->rx_pin_number = NO_PIN;
150-
gc_free(self->buffer);
175+
176+
gc_free(self->rbuf.buf);
177+
self->rbuf.size = 0;
178+
self->rbuf.iput = self->rbuf.iget = 0;
151179
}
152180
}
153181

@@ -157,48 +185,33 @@ size_t common_hal_busio_uart_read 8000 (busio_uart_obj_t *self, uint8_t *data, size_t
157185
mp_raise_ValueError(translate("No RX pin"));
158186
}
159187

160-
size_t remain = len;
188+
size_t rx_bytes = 0;
161189
uint64_t start_ticks = ticks_ms;
162190

163-
while ( 1 ) {
164-
// Wait for on-going transfer to complete
165-
while ( (self->rx_count == -1) && (ticks_ms - start_ticks < self->timeout_ms) ) {
191+
// Wait for all bytes received or timeout
192+
while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
166193
#ifdef MICROPY_VM_HOOK_LOOP
167-
MICROPY_VM_HOOK_LOOP;
168-
// Allow user to break out of a timeout with a KeyboardInterrupt.
169-
if (mp_hal_is_interrupted()) {
170-
return 0;
171-
}
172-
#endif
173-
}
174-
175-
// copy received data
176-
if ( self->rx_count > 0 ) {
177-
memcpy(data, self->buffer, self->rx_count);
178-
data += self->rx_count;
179-
remain -= self->rx_count;
180-
181-
self->rx_count = 0;
194+
MICROPY_VM_HOOK_LOOP ;
195+
// Allow user to break out of a timeout with a KeyboardInterrupt.
196+
if ( mp_hal_is_interrupted() ) {
197+
return 0;
182198
}
199+
#endif
200+
}
183201

184-
// exit if complete or time up
185-
if ( !remain || !(ticks_ms - start_ticks < self->timeout_ms) ) {
186-
break;
187-
}
202+
// prevent conflict with uart irq
203+
NVIC_DisableIRQ(nrfx_get_irq_number(self->uarte.p_reg));
188204

189-
// prepare next receiving
190-
const size_t cnt = MIN(self->bufsize, remain);
191-
self->rx_count = -1;
192-
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, cnt));
205+
// copy received data
206+
rx_bytes = ringbuf_count(&self->rbuf);
207+
rx_bytes = MIN(rx_bytes, len);
208+
for ( uint16_t i = 0; i < rx_bytes; i++ ) {
209+
data[i] = ringbuf_get(&self->rbuf);
193210
}
194211

195-
// queue 1-byte transfer for rx_characters_available()
196-
if ( self->rx_count == 0 ) {
197-
self->rx_count = -1;
198-
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1));
199-
}
212+
NVIC_EnableIRQ(nrfx_get_irq_number(self->uarte.p_reg));
200213

201-
return len - remain;
214+
return rx_bytes;
202215
}
203216

204217
// Write characters.
@@ -258,15 +271,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat
258271
}
259272

260273
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
261-
return (self->rx_count > 0) ? self->rx_count : 0;
274+
return ringbuf_count(&self->rbuf);
262275
}
263276

264277
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
265-
// Discard received byte, and queue 1-byte transfer for rx_characters_available()
266-
if ( self->rx_count > 0 ) {
267-
self->rx_count = -1;
268-
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1));
269-
}
278+
// prevent conflict with uart irq
279+
NVIC_DisableIRQ(nrfx_get_irq_number(self->uarte.p_reg));
280+
ringbuf_clear(&self->rbuf);
281+
NVIC_EnableIRQ(nrfx_get_irq_number(self->uarte.p_reg));
270282
}
271283

272284
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {

ports/nrf/common-hal/busio/UART.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ typedef struct {
4141
uint32_t baudrate;
4242
uint32_t timeout_ms;
4343

44-
uint8_t* buffer;
45-
uint32_t bufsize;
46-
volatile int32_t rx_count;
44+
ringbuf_t rbuf;
45+
uint8_t rx_char; // EasyDMA buf
4746

4847
uint8_t tx_pin_number;
4948
uint8_t rx_pin_number;

0 commit comments

Comments
 (0)
0