8000 Rework cbuf to use FreeRTOS Ringbuffer · chenset/arduino-esp32@13b92d3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 13b92d3

Browse files
committed
Rework cbuf to use FreeRTOS Ringbuffer
1 parent 23f653a commit 13b92d3

File tree

2 files changed

+163
-115
lines changed

2 files changed

+163
-115
lines changed

cores/esp32/cbuf.cpp

Lines changed: 151 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -20,177 +20,238 @@
2020

2121
#include "cbuf.h"
2222

23+
#if CONFIG_DISABLE_HAL_LOCKS
24+
#define CBUF_MUTEX_CREATE()
25+
#define CBUF_MUTEX_LOCK()
26+
#define CBUF_MUTEX_UNLOCK()
27+
#define CBUF_MUTEX_DELETE()
28+
#else
29+
#define CBUF_MUTEX_CREATE() if(_lock == NULL){_lock = xSemaphoreCreateMutex(); if(_lock == NULL){log_e("failed to create mutex");}}
30+
#define CBUF_MUTEX_LOCK() if(_lock != NULL){xSemaphoreTakeRecursive(_lock, portMAX_DELAY);}
31+
#define CBUF_MUTEX_UNLOCK() if(_lock != NULL){xSemaphoreGiveRecursive(_lock);}
32+
#define CBUF_MUTEX_DELETE() if(_lock != NULL){SemaphoreHandle_t l = _lock; _lock = NULL; vSemaphoreDelete(l);}
33+
#endif
34+
2335
cbuf::cbuf(size_t size) :
24-
next(NULL), _size(size+1), _buf(new char[size+1]), _bufend(_buf + size + 1), _begin(_buf), _end(_begin)
36+
next(NULL), _buf(xRingbufferCreate(size, RINGBUF_TYPE_BYTEBUF))
2537
{
38+
if(_buf == NULL) {
39+
log_e("failed to allocate ring buffer");
40+
}
41+
CBUF_MUTEX_CREATE();
2642
}
2743

2844
cbuf::~cbuf()
2945
{
30-
delete[] _buf;
46+
CBUF_MUTEX_LOCK();
47+
if(_buf != NULL){
48+
RingbufHandle_t b = _buf;
49+
_buf = NULL;
50+
vRingbufferDelete(b);
51+
}
52+
CBUF_MUTEX_UNLOCK();
53+
CBUF_MUTEX_DELETE();
3154
}
3255

3356
size_t cbuf::resizeAdd(size_t addSize)
3457
{
35-
return resize(_size + addSize);
58+
return resize(size() + addSize);
3659
}
3760

3861
size_t cbuf::resize(size_t newSize)
3962
{
63+
CBUF_MUTEX_LOCK();
64+
size_t _size = size();
65+
if(newSize == _size) {
66+
return _size;
67+
}
4068

41-
size_t bytes_available = available();
42-
newSize += 1;
4369
// not lose any data
4470
// if data can be lost use remove or flush before resize
45-
if((newSize < bytes_available) || (newSize == _size)) {
71+
size_t bytes_available = available();
72+
if(newSize < bytes_available) {
73+
CBUF_MUTEX_UNLOCK();
74+
log_e("new size is less than the currently available data size");
4675
return _size;
4776
}
4877

49-
char *newbuf = new char[newSize];
50-
char *oldbuf = _buf;
51-
52-
if(!newbuf) {
78+
RingbufHandle_t newbuf = xRingbufferCreate(newSize, RINGBUF_TYPE_BYTEBUF);
79+
if(newbuf == NULL) {
80+
CBUF_MUTEX_UNLOCK();
81+
log_e("failed to allocate new ring buffer");
5382
return _size;
5483
}
5584

56-
if(_buf) {
57-
read(newbuf, bytes_available);
58-
memset((newbuf + bytes_available), 0x00, (newSize - bytes_available));
85+
if(_buf != NULL) {
86+
if(bytes_available){
87+
char * old_data = (char *)malloc(bytes_available);
88+
if(old_data == NULL){
89+
vRingbufferDelete(newbuf);
90+
CBUF_MUTEX_UNLOCK();
91+
log_e("failed to allocate temporary buffer");
92+
return _size;
93+
}
94+
bytes_available = read(old_data, bytes_available);
95+
if(!bytes_available){
96+
free(old_data);
97+
vRingbufferDelete(newbuf);
98+
CBUF_MUTEX_UNLOCK();
99+
log_e("failed to read previous data");
100+
return _size;
101+
}
102+
if(xRingbufferSend(newbuf, (void*)old_data, bytes_available, 0) != pdTRUE){
103+
write(old_data, bytes_available);
104+
free(old_data);
105+
vRingbufferDelete(newbuf);
106+
CBUF_MUTEX_UNLOCK();
107+
log_e("failed to restore previous data");
108+
return _size;
109+
}
110+
free(old_data);
111+
}
112+
113+
RingbufHandle_t b = _buf;
114+
_buf = newbuf;
115+
vRingbufferDelete(b);
116+
} else {
117+
_buf = newbuf;
59118
}
60-
61-
_begin = newbuf;
62-
_end = newbuf + bytes_available;
63-
_bufend = newbuf + newSize;
64-
_size = newSize;
65-
66-
_buf = newbuf;
67-
delete[] oldbuf;
68-
69-
return _size;
119+
CBUF_MUTEX_UNLOCK();
120+
return newSize;
70121
}
71122

72123
size_t cbuf::available() const
73124
{
74-
if(_end >= _begin) {
75-
return _end - _begin;
125+
size_t available = 0;
126+
if(_buf != NULL){
127+
vRingbufferGetInfo(_buf, NULL, NULL, NULL, NULL, (UBaseType_t *)&available);
76128
}
77-
return _size - (_begin - _end);
129+
return available;
78130
}
79131

80132
size_t cbuf::size()
81133
{
134+
size_t _size = 0;
135+
if(_buf != NULL){
136+
_size = xRingbufferGetMaxItemSize(_buf);
137+
}
82138
return _size;
83139
}
84140

85141
size_t cbuf::room() const
86142
{
87-
if(_end >= _begin) {
88-
return _size - (_end - _begin) - 1;
143+
size_t _room = 0;
144+
if(_buf != NULL){
145+
_room = xRingbufferGetCurFreeSize(_buf);
89146
}
90-
return _begin - _end - 1;
147+
return _room;
91148
}
92149

93-
int cbuf::peek()
150+
bool cbuf::empty() const
94151
{
95-
if(empty()) {
96-
return -1;
97-
}
152+
return available() == 0;
153+
}
98154

99-
return static_cast<int>(*_begin);
155+
bool cbuf::full() const
156+
{
157+
return room() == 0;
158+
}
159+
160+
int cbuf::peek()
161+
{
162+
return -1;
100163
}
101164

102165
size_t cbuf::peek(char *dst, size_t size)
103166
{
104-
size_t bytes_available = available();
105-
size_t size_to_read = (size < bytes_available) ? size : bytes_available;
106-
size_t size_read = size_to_read;
107-
char * begin = _begin;
108-
if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) {
109-
size_t top_size = _bufend - _begin;
110-
memcpy(dst, _begin, top_size);
111-
begin = _buf;
112-
size_to_read -= top_size;
113-
dst += top_size;
114-
}
115-
memcpy(dst, begin, size_to_read);
116-
return size_read;
167+
return 0;
117168
}
118169

119170
int cbuf::read()
120171
{
121-
if(empty()) {
172+
char result = 0;
173+
if(!read(&result, 1)){
122174
return -1;
123175
}
124-
125-
char result = *_begin;
126-
_begin = wrap_if_bufend(_begin + 1);
127176
return static_cast<int>(result);
128177
}
129178

130179
size_t cbuf::read(char* dst, size_t size)
131180
{
181+
CBUF_MUTEX_LOCK();
132182
size_t bytes_available = available();
183+
if(!bytes_available || !size){
184+
CBUF_MUTEX_UNLOCK();
185+
return 0;
186+
}
133187
size_t size_to_read = (size < bytes_available) ? size : bytes_available;
134-
size_t size_read = size_to_read;
135-
if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) {
136-
size_t top_size = _bufend - _begin;
137-
memcpy(dst, _begin, top_size);
138-
_begin = _buf;
139-
size_to_read -= top_size;
140-
dst += top_size;
188+
size_t size_read = 0;
189+
size_t received_size = 0;
190+
uint8_t *received_buff = (uint8_t *)xRingbufferReceiveUpTo(_buf, &received_size, 0, size_to_read);
191+
if (received_buff != NULL) {
192+
if(dst != NULL){
193+
memcpy(dst, received_buff, received_size);
194+
}
195+
vRingbufferReturnItem(rx_ring_buf, received_buff);
196+
size_read = received_size;
197+
size_to_read -= received_size;
198+
// wrap around data
199+
if(size_to_read){
200+
received_size = 0;
201+
received_buff = (uint8_t *)xRingbufferReceiveUpTo(_buf, &received_size, 0, size_to_read);
202+
if (received_buff != NULL) {
203+
if(dst != NULL){
204+
memcpy(dst+size_read, received_buff, received_size);
205+
}
206+
vRingbufferReturnItem(rx_ring_buf, received_buff);
207+
size_read += received_size;
208+
} else {
209+
log_e("failed to read wrap around data from ring buffer");
210+
}
211+
}
212+
} else {
213+
log_e("failed to read from ring buffer");
141214
}
142-
memcpy(dst, _begin, size_to_read);
143-
_begin = wrap_if_bufend(_begin + size_to_read);
215+
CBUF_MUTEX_UNLOCK();
144216
return size_read;
145217
}
146218

147219
size_t cbuf::write(char c)
148220
{
149-
if(full()) {
150-
return 0;
151-
}
152-
153-
*_end = c;
154-
_end = wrap_if_bufend(_end + 1);
155-
return 1;
221+
return write(&c, 1);
156222
}
157223

158224
size_t cbuf::write(const char* src, size_t size)
159225
{
226+
CBUF_MUTEX_LOCK();
160227
size_t bytes_available = room();
228+
if(!bytes_available || !size){
229+
CBUF_MUTEX_UNLOCK();
230+
return 0;
231+
}
161232
size_t size_to_write = (size < bytes_available) ? size : bytes_available;
162-
size_t size_written = size_to_write;
163-
if(_end >= _begin && size_to_write > (size_t) (_bufend - _end)) {
164-
size_t top_size = _bufend - _end;
165-
memcpy(_end, src, top_size);
166-
_end = _buf;
167-
size_to_write -= top_size;
168-
src += top_size;
233+
if(xRingbufferSend(rx_ring_buf, (void*)src, size_to_write, 0) != pdTRUE){
234+
CBUF_MUTEX_UNLOCK();
235+
log_e("failed to write to ring buffer");
236+
return 0;
169237
}
170-
memcpy(_end, src, size_to_write);
171-
_end = wrap_if_bufend(_end + size_to_write);
172-
return size_written;
238+
CBUF_MUTEX_UNLOCK();
239+
return size_to_write;
173240
}
174241

175242
void cbuf::flush()
176243
{
177-
_begin = _buf;
178-
_end = _buf;
244+
read(NULL, available());
179245
}
180246

181247
size_t cbuf::remove(size_t size)
182248
{
249+
CBUF_MUTEX_LOCK();
183250
size_t bytes_available = available();
184-
if(size >= bytes_available) {
185-
flush();
186-
return 0;
187-
}
188-
size_t size_to_remove = (size < bytes_available) ? size : bytes_available;
189-
if(_end < _begin && size_to_remove > (size_t) (_bufend - _begin)) {
190-
size_t top_size = _bufend - _begin;
191-
_begin = _buf;
192-
size_to_remove -= top_size;
251+
if(bytes_available && size){
252+
size_t size_to_remove = (size < bytes_available) ? size : bytes_available;
253+
bytes_available -= read(NULL, size_to_remove);
193254
}
194-
_begin = wrap_if_bufend(_begin + size_to_remove);
195-
return available();
255+
CBUF_MUTEX_UNLOCK();
256+
return bytes_available;
196257
}

cores/esp32/cbuf.h

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1919
*/
2020

21-
#ifndef __cbuf_h
22-
#define __cbuf_h
21+
#pragma once
2322

2423
#include <stddef.h>
2524
#include <stdint.h>
2625
#include <string.h>
26+
#include "sdkconfig.h"
27+
#include "freertos/FreeRTOS.h"
28+
#include "freertos/ringbuf.h"
29+
#include "freertos/semphr.h"
2730

2831
class cbuf
2932
{
@@ -33,20 +36,12 @@ class cbuf
3336

3437
size_t resizeAdd(size_t addSize);
3538
size_t resize(size_t newSize);
39+
3640
size_t available() const;
3741
size_t size();
38-
3942
size_t room() const;
40-
41-
inline bool empty() const
42-
{
43-
return _begin == _end;
44-
}
45-
46-
inline bool full() const
47-
{
48-
return wrap_if_bufend(_end + 1) == _begin;
49-
}
43+
bool empty() const;
44+
bool full() const;
5045

5146
int peek();
5247
size_t peek(char *dst, size_t size);
@@ -63,17 +58,9 @@ class cbuf
6358
cbuf *next;
6459

6560
protected:
66-
inline char* wrap_if_bufend(char* ptr) const
67-
{
68-
return (ptr == _bufend) ? _buf : ptr;
69-
}
70-
71-
size_t _size;
72-
char* _buf;
73-
const char* _bufend;
74-
char* _begin;
75-
char* _end;
61+
RingbufHandle_t _buf;
62+
#if !CONFIG_DISABLE_HAL_LOCKS
63+
SemaphoreHandle_t _lock;
64+
#endif
7665

7766
};
78-
79-
#endif//__cbuf_h

0 commit comments

Comments
 (0)
0