Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
further ringbuf cleanup
  • Loading branch information
dhalbert committed Apr 21, 2020
commit 38ec3bc57476c6fde45cd7d722370a5408fd8e10
2 changes: 2 additions & 0 deletions ports/mimxrt10xx/common-hal/busio/UART.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
}

LPUART_TransferCreateHandle(self->uart, &self->handle, LPUART_UserCallback, self);
// Pass actual allocated size; the LPUART routines are cognizant that
// the capacity is one less than the size.
LPUART_TransferStartRingBuffer(self->uart, &self->handle, self->rbuf.buf, self->rbuf.size);

claim_pin(self->rx_pin->pin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ EXTERNAL_FLASH_DEVICES = "GD25Q16C"

# Allocate two, not just one I2C peripheral for CPB, so that we have both
# on-board and off-board I2C available.
# When SPIM3 becomes available we'll be able to have two I2C and two SPI peripherals.
# We use a CFLAGS define here because there are include order issues
# if we try to include "mpconfigport.h" into nrfx_config.h .
CFLAGS += -DCIRCUITPY_NRF_NUM_I2C=2
19 changes: 7 additions & 12 deletions ports/nrf/common-hal/_bleio/CharacteristicBuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,11 @@
#include "supervisor/shared/tick.h"
#include "common-hal/_bleio/CharacteristicBuffer.h"

// Push all the data onto the ring buffer. When the buffer is full, new bytes will be dropped.
STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
// Push all the data onto the ring buffer.
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);
for (size_t i = 0; i < len; i++) {
ringbuf_put(&self->ringbuf, data[i]);
}
ringbuf_put_n(&self->ringbuf, data, len);
sd_nvic_critical_region_exit(is_nested_critical_region);
}

Expand Down Expand Up @@ -100,11 +98,11 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe

}

int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
uint64_t start_ticks = supervisor_ticks_ms64();

// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->ringbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
while ( (ringbuf_avail(&self->ringbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
Expand All @@ -116,21 +114,18 @@ int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);

size_t rx_bytes = MIN(ringbuf_count(&self->ringbuf), len);
for ( size_t i = 0; i < rx_bytes; i++ ) {
data[i] = ringbuf_get(&self->ringbuf);
}
uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len);

// Writes now OK.
sd_nvic_critical_region_exit(is_nested_critical_region);

return rx_bytes;
return num_bytes_read;
}

uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);
uint16_t count = ringbuf_count(&self->ringbuf);
uint16_t count = ringbuf_avail(&self->ringbuf);
sd_nvic_critical_region_exit(is_nested_critical_region);
return count;
}
Expand Down
22 changes: 14 additions & 8 deletions ports/nrf/common-hal/_bleio/PacketBuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@
#include "supervisor/shared/tick.h"

STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) {
if (len + sizeof(uint16_t) > self->ringbuf.size) {
if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) {
// This shouldn't happen.
return;
}
// Push all the data onto the ring buffer.
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);
// Make room for the new value by dropping the oldest packets first.
while (self->ringbuf.size - ringbuf_count(&self->ringbuf) < (int) (len + sizeof(uint16_t))) {
while (ringbuf_capacity(&self->ringbuf) - ringbuf_avail(&self->ringbuf) < len + sizeof(uint16_t)) {
uint16_t packet_length;
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
for (uint16_t i = 0; i < packet_length; i++) {
Expand Down Expand Up @@ -250,27 +250,33 @@ void common_hal_bleio_packet_buffer_construct(
}

int common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) {
if (ringbuf_count(&self->ringbuf) < 2) {
if (ringbuf_avail(&self->ringbuf) < 2) {
return 0;
}

uint16_t packet_length;
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
int ret;

// Copy received data. Lock out write interrupt handler while copying.
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);

// Get packet length first.
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));

if (packet_length > len) {
return len - packet_length;
// Packet is longer than requested. Return negative of overrun value.
ret = len - packet_length;
} else {
// Read as much as possible, but might be shorter than len.
ringbuf_get_n(&self->ringbuf, data, packet_length);
ret = packet_length;
}

ringbuf_get_n(&self->ringbuf, data, packet_length);

// Writes now OK.
sd_nvic_critical_region_exit(is_nested_critical_region);

return packet_length;
return ret;
}

void common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len, uint8_t* header, size_t header_len) {
Expand Down
13 changes: 4 additions & 9 deletions ports/nrf/common-hal/busio/UART.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,10 @@ 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 rx_bytes = 0;
uint64_t start_ticks = supervisor_ticks_ms64();

// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
while ( (ringbuf_avail(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
Expand All @@ -255,12 +254,8 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
// 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);
}
// Copy as much received data as available, up to len bytes.
size_t rx_bytes = ringbuf_get_n(&self->rbuf, data, len);

NVIC_EnableIRQ(nrfx_get_irq_number(self->uarte->p_reg));

Expand Down Expand Up @@ -317,7 +312,7 @@ void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeou
}

uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
return ringbuf_count(&self->rbuf);
return ringbuf_avail(&self->rbuf);
}

void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
Expand Down
12 changes: 10 additions & 2 deletions ports/nrf/mpconfigport.mk
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ CIRCUITPY_AUDIOIO = 0

# The ifndef's allow overriding in mpconfigboard.mk.

ifndef
ifndef CIRCUITPY_BLEIO
CIRCUITPY_BLEIO = 1
endif

Expand All @@ -51,8 +51,17 @@ endif
# frequencyio not yet implemented
CIRCUITPY_FREQUENCYIO = 0

ifndef CIRCUITPY_PROTOMATTER
CIRCUITPY_PROTOMATTER = 1
endif

ifndef CIRCUITPY_FRAMEBUFFERIO
CIRCUITPY_FRAMEBUFFERIO = 1
endif

ifndef CIRCUITPY_ULAB
CIRCUITPY_ULAB = 1
endif

# nRF52840-specific

Expand All @@ -72,5 +81,4 @@ NRF_DEFINES += -DNRF52840_XXAA -DNRF52840
# Defined here because system_nrf52840.c doesn't #include any of our own include files.
CFLAGS += -DCONFIG_NFCT_PINS_AS_GPIOS

CIRCUITPY_ULAB = 1
endif
12 changes: 4 additions & 8 deletions ports/stm/common-hal/busio/UART.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
uint64_t start_ticks = supervisor_ticks_ms64();

// Wait for all bytes received or timeout, same as nrf
while ( (ringbuf_count(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
while ( (ringbuf_avail(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
//restart if it failed in the callback
if (errflag != HAL_OK) {
Expand All @@ -276,12 +276,8 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t

// Halt reception
HAL_NVIC_DisableIRQ(self->irq);
// 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);
}
// Copy as much received data as available, up to len bytes.
size_t rx_bytes = ringbuf_get_n(&self->rbuf, data, len);
HAL_NVIC_EnableIRQ(self->irq);

if (rx_bytes == 0) {
Expand Down Expand Up @@ -380,7 +376,7 @@ void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeou
}

uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
return ringbuf_count(&self->rbuf);
return ringbuf_avail(&self->rbuf);
}

void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
Expand Down
1 change: 1 addition & 0 deletions py/py.mk
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\
repl.o \
smallint.o \
frozenmod.o \
ringbuf.o \
)

PY_EXTMOD_O_BASENAME = \
Expand Down
109 changes: 109 additions & 0 deletions py/ringbuf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "ringbuf.h"

// Dynamic initialization. This should be accessible from a root pointer.
// capacity is the number of bytes the ring buffer can hold. The actual
// size of the buffer is one greater than that, due to how the buffer
// handles empty and full statuses.
bool ringbuf_alloc(ringbuf_t *r, size_t capacity, bool long_lived) {
r->buf = gc_alloc(capacity + 1, false, long_lived);
r->size = capacity + 1;
r->iget = r->iput = 0;
return r->buf != NULL;
}

size_t ringbuf_capacity(ringbuf_t *r) {
return r->size - 1;
}

// Returns -1 if buffer is empty, else returns byte fetched.
int ringbuf_get(ringbuf_t *r) {
if (r->iget == r->iput) {
return -1;
}
uint8_t v = r->buf[r->iget++];
if (r->iget >= r->size) {
r->iget = 0;
}
return v;
}

// Returns -1 if no room in buffer, else returns 0.
int ringbuf_put(ringbuf_t *r, uint8_t v) {
uint32_t iput_new = r->iput + 1;
if (iput_new >= r->size) {
iput_new = 0;
}
if (iput_new == r->iget) {
return -1;
}
r->buf[r->iput] = v;
r->iput = iput_new;
return 0;
}

void ringbuf_clear(ringbuf_t *r) {
r->iput = r->iget = 0;
}

// Number of free slots that can be written.
size_t ringbuf_free(ringbuf_t *r) {
return (r->size + r->iget - r->iput - 1) % r->size;
}

// Number of bytes available to read.
size_t ringbuf_avail(ringbuf_t *r) {
return (r->size + r->iput - r->iget) % r->size;
}

// If the ring buffer fills up, not all bytes will be written.
// Returns how many bytes were successfully written.
size_t ringbuf_put_n(ringbuf_t* r, uint8_t* buf, size_t bufsize)
{
for(size_t i=0; i < bufsize; i++) {
if ( ringbuf_put(r, buf[i]) < 0 ) {
// If ringbuf is full, give up and return how many bytes
// we wrote so far.
return i;
}
}
return bufsize;
}

// Returns how many bytes were fetched.
size_t ringbuf_get_n(ringbuf_t* r, uint8_t* buf, size_t bufsize)
{
for(size_t i=0; i < bufsize; i++) {
int b = ringbuf_get(r);
if (b < 0) {
return i;
}
buf[i] = b;
}
return bufsize;
}
Loading