Skip to content

Commit 38ec3bc

Browse files
committed
further ringbuf cleanup
1 parent 1a71c8c commit 38ec3bc

File tree

12 files changed

+170
-111
lines changed

12 files changed

+170
-111
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
206206
}
207207

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

211213
claim_pin(self->rx_pin->pin);

ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ EXTERNAL_FLASH_DEVICES = "GD25Q16C"
1111

1212
# Allocate two, not just one I2C peripheral for CPB, so that we have both
1313
# on-board and off-board I2C available.
14-
# When SPIM3 becomes available we'll be able to have two I2C and two SPI peripherals.
1514
# We use a CFLAGS define here because there are include order issues
1615
# if we try to include "mpconfigport.h" into nrfx_config.h .
1716
CFLAGS += -DCIRCUITPY_NRF_NUM_I2C=2

ports/nrf/common-hal/_bleio/CharacteristicBuffer.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,11 @@
4242
#include "supervisor/shared/tick.h"
4343
#include "common-hal/_bleio/CharacteristicBuffer.h"
4444

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

@@ -100,11 +98,11 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe
10098

10199
}
102100

103-
int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
101+
uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
104102
uint64_t start_ticks = supervisor_ticks_ms64();
105103

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

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

124119
// Writes now OK.
125120
sd_nvic_critical_region_exit(is_nested_critical_region);
126121

127-
return rx_bytes;
122+
return num_bytes_read;
128123
}
129124

130125
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
131126
uint8_t is_nested_critical_region;
132127
sd_nvic_critical_region_enter(&is_nested_critical_region);
133-
uint16_t count = ringbuf_count(&self->ringbuf);
128+
uint16_t count = ringbuf_avail(&self->ringbuf);
134129
sd_nvic_critical_region_exit(is_nested_critical_region);
135130
return count;
136131
}

ports/nrf/common-hal/_bleio/PacketBuffer.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@
4343
#include "supervisor/shared/tick.h"
4444

4545
STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) {
46-
if (len + sizeof(uint16_t) > self->ringbuf.size) {
46+
if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) {
4747
// This shouldn't happen.
4848
return;
4949
}
5050
// Push all the data onto the ring buffer.
5151
uint8_t is_nested_critical_region;
5252
sd_nvic_critical_region_enter(&is_nested_critical_region);
5353
// Make room for the new value by dropping the oldest packets first.
54-
while (self->ringbuf.size - ringbuf_count(&self->ringbuf) < (int) (len + sizeof(uint16_t))) {
54+
while (ringbuf_capacity(&self->ringbuf) - ringbuf_avail(&self->ringbuf) < len + sizeof(uint16_t)) {
5555
uint16_t packet_length;
5656
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
5757
for (uint16_t i = 0; i < packet_length; i++) {
@@ -250,27 +250,33 @@ void common_hal_bleio_packet_buffer_construct(
250250
}
251251

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

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

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

264+
// Get packet length first.
265+
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
266+
264267
if (packet_length > len) {
265-
return len - packet_length;
268+
// Packet is longer than requested. Return negative of overrun value.
269+
ret = len - packet_length;
270+
} else {
271+
// Read as much as possible, but might be shorter than len.
272+
ringbuf_get_n(&self->ringbuf, data, packet_length);
273+
ret = packet_length;
266274
}
267275

268-
ringbuf_get_n(&self->ringbuf, data, packet_length);
269-
270276
// Writes now OK.
271277
sd_nvic_critical_region_exit(is_nested_critical_region);
272278

273-
return packet_length;
279+
return ret;
274280
}
275281

276282
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) {

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

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
240240
mp_raise_ValueError(translate("No RX pin"));
241241
}
242242

243-
size_t rx_bytes = 0;
244243
uint64_t start_ticks = supervisor_ticks_ms64();
245244

246245
// Wait for all bytes received or timeout
247-
while ( (ringbuf_count(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
246+
while ( (ringbuf_avail(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
248247
RUN_BACKGROUND_TASKS;
249248
// Allow user to break out of a timeout with a KeyboardInterrupt.
250249
if ( mp_hal_is_interrupted() ) {
@@ -255,12 +254,8 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
255254
// prevent conflict with uart irq
256255
NVIC_DisableIRQ(nrfx_get_irq_number(self->uarte->p_reg));
257256

258-
// copy received data
259-
rx_bytes = ringbuf_count(&self->rbuf);
260-
rx_bytes = MIN(rx_bytes, len);
261-
for ( uint16_t i = 0; i < rx_bytes; i++ ) {
262-
data[i] = ringbuf_get(&self->rbuf);
263-
}
257+
// Copy as much received data as available, up to len bytes.
258+
size_t rx_bytes = ringbuf_get_n(&self->rbuf, data, len);
264259

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

@@ -317,7 +312,7 @@ void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeou
317312
}
318313

319314
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
320-
return ringbuf_count(&self->rbuf);
315+
return ringbuf_avail(&self->rbuf);
321316
}
322317

323318
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {

ports/nrf/mpconfigport.mk

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ CIRCUITPY_AUDIOIO = 0
2424

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

27-
ifndef
27+
ifndef CIRCUITPY_BLEIO
2828
CIRCUITPY_BLEIO = 1
2929
endif
3030

@@ -51,8 +51,17 @@ endif
5151
# frequencyio not yet implemented
5252
CIRCUITPY_FREQUENCYIO = 0
5353

54+
ifndef CIRCUITPY_PROTOMATTER
5455
CIRCUITPY_PROTOMATTER = 1
56+
endif
57+
58+
ifndef CIRCUITPY_FRAMEBUFFERIO
5559
CIRCUITPY_FRAMEBUFFERIO = 1
60+
endif
61+
62+
ifndef CIRCUITPY_ULAB
63+
CIRCUITPY_ULAB = 1
64+
endif
5665

5766
# nRF52840-specific
5867

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

75-
CIRCUITPY_ULAB = 1
7684
endif

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
262262
uint64_t start_ticks = supervisor_ticks_ms64();
263263

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

277277
// Halt reception
278278
HAL_NVIC_DisableIRQ(self->irq);
279-
// copy received data
280-
rx_bytes = ringbuf_count(&self->rbuf);
281-
rx_bytes = MIN(rx_bytes, len);
282-
for (uint16_t i = 0; i < rx_bytes; i++) {
283-
data[i] = ringbuf_get(&self->rbuf);
284-
}
279+
// Copy as much received data as available, up to len bytes.
280+
size_t rx_bytes = ringbuf_get_n(&self->rbuf, data, len);
285281
HAL_NVIC_EnableIRQ(self->irq);
286282

287283
if (rx_bytes == 0) {
@@ -380,7 +376,7 @@ void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeou
380376
}
381377

382378
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
383-
return ringbuf_count(&self->rbuf);
379+
return ringbuf_avail(&self->rbuf);
384380
}
385381

386382
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {

py/py.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\
257257
repl.o \
258258
smallint.o \
259259
frozenmod.o \
260+
ringbuf.o \
260261
)
261262

262263
PY_EXTMOD_O_BASENAME = \

py/ringbuf.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Paul Sokolovsky
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "ringbuf.h"
28+
29+
// Dynamic initialization. This should be accessible from a root pointer.
30+
// capacity is the number of bytes the ring buffer can hold. The actual
31+
// size of the buffer is one greater than that, due to how the buffer
32+
// handles empty and full statuses.
33+
bool ringbuf_alloc(ringbuf_t *r, size_t capacity, bool long_lived) {
34+
r->buf = gc_alloc(capacity + 1, false, long_lived);
35+
r->size = capacity + 1;
36+
r->iget = r->iput = 0;
37+
return r->buf != NULL;
38+
}
39+
40+
size_t ringbuf_capacity(ringbuf_t *r) {
41+
return r->size - 1;
42+
}
43+
44+
// Returns -1 if buffer is empty, else returns byte fetched.
45+
int ringbuf_get(ringbuf_t *r) {
46+
if (r->iget == r->iput) {
47+
return -1;
48+
}
49+
uint8_t v = r->buf[r->iget++];
50+
if (r->iget >= r->size) {
51+
r->iget = 0;
52+
}
53+
return v;
54+
}
55+
56+
// Returns -1 if no room in buffer, else returns 0.
57+
int ringbuf_put(ringbuf_t *r, uint8_t v) {
58+
uint32_t iput_new = r->iput + 1;
59+
if (iput_new >= r->size) {
60+
iput_new = 0;
61+
}
62+
if (iput_new == r->iget) {
63+
return -1;
64+
}
65+
r->buf[r->iput] = v;
66+
r->iput = iput_new;
67+
return 0;
68+
}
69+
70+
void ringbuf_clear(ringbuf_t *r) {
71+
r->iput = r->iget = 0;
72+
}
73+
74+
// Number of free slots that can be written.
75+
size_t ringbuf_free(ringbuf_t *r) {
76+
return (r->size + r->iget - r->iput - 1) % r->size;
77+
}
78+
79+
// Number of bytes available to read.
80+
size_t ringbuf_avail(ringbuf_t *r) {
81+
return (r->size + r->iput - r->iget) % r->size;
82+
}
83+
84+
// If the ring buffer fills up, not all bytes will be written.
85+
// Returns how many bytes were successfully written.
86+
size_t ringbuf_put_n(ringbuf_t* r, uint8_t* buf, size_t bufsize)
87+
{
88+
for(size_t i=0; i < bufsize; i++) {
89+
if ( ringbuf_put(r, buf[i]) < 0 ) {
90+
// If ringbuf is full, give up and return how many bytes
91+
// we wrote so far.
92+
return i;
93+
}
94+
}
95+
return bufsize;
96+
}
97+
98+
// Returns how many bytes were fetched.
99+
size_t ringbuf_get_n(ringbuf_t* r, uint8_t* buf, size_t bufsize)
100+
{
101+
for(size_t i=0; i < bufsize; i++) {
102+
int b = ringbuf_get(r);
103+
if (b < 0) {
104+
return i;
105+
}
106+
buf[i] = b;
107+
}
108+
return bufsize;
109+
}

0 commit comments

Comments
 (0)