Merge pull request #1402 from hathach/nrf_uartio_fix

use rbuf for busio uart
This commit is contained in:
Dan Halbert 2018-12-13 15:47:02 -05:00 committed by GitHub
commit 5e4b3a8fb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 54 deletions

View File

@ -52,21 +52,44 @@
static uint32_t get_nrf_baud (uint32_t baudrate);
static uint16_t ringbuf_count(ringbuf_t *r)
{
volatile int count = r->iput - r->iget;
if ( count < 0 ) {
count += r->size;
}
return (uint16_t) count;
}
static void ringbuf_clear(ringbuf_t *r)
{
r->iput = r->iget = 0;
}
static void uart_callback_irq (const nrfx_uarte_event_t * event, void * context) {
busio_uart_obj_t* self = (busio_uart_obj_t*) context;
switch ( event->type ) {
case NRFX_UARTE_EVT_RX_DONE:
self->rx_count = event->data.rxtx.bytes;
for(uint8_t i=0; i < event->data.rxtx.bytes; i++) {
if ( ringbuf_put(&self->rbuf, event->data.rxtx.p_data[i]) < 0 ) {
// if full overwrite old data
(void) ringbuf_get(&self->rbuf);
ringbuf_put(&self->rbuf, event->data.rxtx.p_data[i]);
}
}
// keep receiving
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, &self->rx_char, 1));
break;
case NRFX_UARTE_EVT_TX_DONE:
// nothing to do
break;
case NRFX_UARTE_EVT_ERROR:
if ( self->rx_count == -1 ) {
self->rx_count = 0;
}
// Handle error
break;
default:
@ -110,12 +133,15 @@ void common_hal_busio_uart_construct (busio_uart_obj_t *self,
// Init buffer for rx
if ( rx != mp_const_none ) {
self->buffer = (uint8_t *) gc_alloc(receiver_buffer_size, false, false);
if ( !self->buffer ) {
self->rbuf.buf = (uint8_t *) gc_alloc(receiver_buffer_size, false, false);
if ( !self->rbuf.buf ) {
nrfx_uarte_uninit(&self->uarte);
mp_raise_msg(&mp_type_MemoryError, translate("Failed to allocate RX buffer"));
}
self->bufsize = receiver_buffer_size;
self->rbuf.size = receiver_buffer_size;
self->rbuf.iget = self->rbuf.iput = 0;
self->rx_pin_number = rx->number;
claim_pin(rx);
@ -131,9 +157,8 @@ void common_hal_busio_uart_construct (busio_uart_obj_t *self,
self->baudrate = baudrate;
self->timeout_ms = timeout * 1000;
// queue 1-byte transfer for rx_characters_available()
self->rx_count = -1;
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1));
// Initial wait for incoming byte
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, &self->rx_char, 1));
}
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) {
reset_pin_number(self->rx_pin_number);
self->tx_pin_number = NO_PIN;
self->rx_pin_number = NO_PIN;
gc_free(self->buffer);
gc_free(self->rbuf.buf);
self->rbuf.size = 0;
self->rbuf.iput = self->rbuf.iget = 0;
}
}
@ -157,48 +185,33 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
mp_raise_ValueError(translate("No RX pin"));
}
size_t remain = len;
size_t rx_bytes = 0;
uint64_t start_ticks = ticks_ms;
while ( 1 ) {
// Wait for on-going transfer to complete
while ( (self->rx_count == -1) && (ticks_ms - start_ticks < self->timeout_ms) ) {
// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
return 0;
}
MICROPY_VM_HOOK_LOOP ;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
return 0;
}
#endif
}
// copy received data
if ( self->rx_count > 0 ) {
memcpy(data, self->buffer, self->rx_count);
data += self->rx_count;
remain -= self->rx_count;
self->rx_count = 0;
}
// exit if complete or time up
if ( !remain || !(ticks_ms - start_ticks < self->timeout_ms) ) {
break;
}
// prepare next receiving
const size_t cnt = MIN(self->bufsize, remain);
self->rx_count = -1;
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, cnt));
}
// queue 1-byte transfer for rx_characters_available()
if ( self->rx_count == 0 ) {
self->rx_count = -1;
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1));
// prevent conflict with uart irq
NVIC_DisableIRQ(nrfx_get_irq_number(self->uarte.p_reg));
// copy received data
rx_bytes = ringbuf_count(&self->rbuf);
rx_bytes = MIN(rx_bytes, len);
for ( uint16_t i = 0; i < rx_bytes; i++ ) {
data[i] = ringbuf_get(&self->rbuf);
}
return len - remain;
NVIC_EnableIRQ(nrfx_get_irq_number(self->uarte.p_reg));
return rx_bytes;
}
// Write characters.
@ -258,15 +271,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat
}
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
return (self->rx_count > 0) ? self->rx_count : 0;
return ringbuf_count(&self->rbuf);
}
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
// Discard received byte, and queue 1-byte transfer for rx_characters_available()
if ( self->rx_count > 0 ) {
self->rx_count = -1;
_VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1));
}
// prevent conflict with uart irq
NVIC_DisableIRQ(nrfx_get_irq_number(self->uarte.p_reg));
ringbuf_clear(&self->rbuf);
NVIC_EnableIRQ(nrfx_get_irq_number(self->uarte.p_reg));
}
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {

View File

@ -41,9 +41,8 @@ typedef struct {
uint32_t baudrate;
uint32_t timeout_ms;
uint8_t* buffer;
uint32_t bufsize;
volatile int32_t rx_count;
ringbuf_t rbuf;
uint8_t rx_char; // EasyDMA buf
uint8_t tx_pin_number;
uint8_t rx_pin_number;