Skip to content

Commit efd7625

Browse files
committed
ESP8266 support and compiler warnings
1 parent 1292637 commit efd7625

4 files changed

Lines changed: 46 additions & 21 deletions

File tree

README.md

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,7 @@ I needed a way to buffer sensor events for a group engineering IOT project that
77

88
I decided to give object oriented programming a shot using only C (no C++) with this library, of course, it still compiles with C++ compilers such as in the Arduino IDE. Using C structs and function pointers, the library creates RingBuf objects that are complete with their own methods and attributes. Note that every method (except constructor), takes a `RingBuf *self` pointer. This is the equivalent of the `this` pointer in C++, but the C++ compiler automatically passes it behind the scenes. For this library, you must manually pass a the `RingBuf *self` pointer as the first argument.
99

10-
## FAQ's
11-
<dl>
12-
<dt>Can I buffer C++ objects?</dt>
13-
<dd>The library only shallow copies objects into the buffer, it will not call the copy constructor. For many C++ objects this works fine, but if you require a deep copy you will have to look into libraries that supports something like C++ templates. And to be honest, you shouldn't be doing deep copies on a microcontroller or you could get random freezes from memory fragmentation.</dd>
14-
15-
<dt>Does this library support non AVR platforms?</dt>
16-
<dd>Currently no, see <a href="https://github.com/wizard97/ArduinoRingBuffer/issues/2">#2</a>. If someone knows of a portable replacement for the `ATOMIC_BLOCK(ATOMIC_RESTORESTATE){}` macro please let me know.</dd>
17-
</dl>
10+
1811
## But I like C++'s object syntax...
1912

2013
Fine. I reluctantly wrapped the C stuff in a C++ class called `RingBufC`. All the methods are the same, except you no longer have to pass the this/self pointer. You can use either.
@@ -29,7 +22,7 @@ buf->add(buf, &mystr);
2922

3023
```
3124
// If you want to use the C++ wrapper
32-
char *mystr = "I like C++";
25+
char *mystr = "C++ has pretty object.method() syntax";
3326
3427
RingBufC = buf(sizeof(char*), 100);
3528
buf.add(&mystr);
@@ -93,7 +86,7 @@ Append an element to the buffer, where object is a pointer to object you wish to
9386
void *peek(RingBuf *self, unsigned int num);
9487
```
9588

96-
Peek at the num'th element in the buffer. Returns a void pointer to the location of the num'th element. If num is out of bounds or the num'th element is empty, a NULL pointer is returned. Cast the result of this call into a pointer of whatever type you are storing in the buffer. Note that this gives you direct memory access to the location of the num'th element in the buffer, allowing you to directly edit elements in the buffer. Note that while all of RingBuf's public methods are thread safe (including this one), directly using the pointer returned from this method is not thread safe. If there is a possibility an interrupt could fire and remove/modify the item pointed to by the returned pointer, disable interrupts first with `noInterrupts()`, do whatever you need to do with the pointer, then you can reenable interrupts by calling `interrupts()`.
89+
Peek at the num'th element in the buffer. Returns a void pointer to the location of the num'th element. If num is out of bounds or the num'th element is empty, a NULL pointer is returned. Cast the result of this call into a pointer of whatever type you are storing in the buffer. Note that this gives you direct memory access to the location of the num'th element in the buffer, allowing you to directly edit elements in the buffer. Note that while all of RingBuf's public methods are thread safe (including this one), directly using the pointer returned from this method is not thread safe. To use this returned pointer safely, disable interrupts first with `noInterrupts()`, do whatever you need to do with the pointer, then you can reenable interrupts by calling `interrupts()`.
9790

9891
### pull()
9992

RingBuf.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77
#include "RingBuf.h"
88
#include <string.h>
9-
#include <util/atomic.h>
109

1110
/////// Constructor //////////
1211
RingBuf *RingBuf_new(int size, int len)
@@ -86,7 +85,7 @@ int RingBufAdd(RingBuf *self, const void *object)
8685
{
8786
int index;
8887
// Perform all atomic opertaions
89-
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
88+
RB_ATOMIC_START
9089
{
9190
index = self->next_end_index(self);
9291
//if not full
@@ -97,30 +96,33 @@ int RingBufAdd(RingBuf *self, const void *object)
9796
self->elements++;
9897
}
9998
}
99+
RB_ATOMIC_END
100100

101101
return index;
102102
}
103103

104104
// Return pointer to num element, return null on empty or num out of bounds
105105
void *RingBufPeek(RingBuf *self, unsigned int num)
106106
{
107-
void *ret;
107+
void *ret = NULL;
108108
// Perform all atomic opertaions
109-
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
109+
RB_ATOMIC_START
110110
{
111111
//empty or out of bounds
112112
if (self->isEmpty(self) || num > self->elements - 1) ret = NULL;
113113
else ret = &self->buf[((self->start + num)%self->len)*self->size];
114114
}
115+
RB_ATOMIC_END
116+
115117
return ret;
116118
}
117119

118120
// Returns and removes first buffer element
119121
void *RingBufPull(RingBuf *self, void *object)
120122
{
121-
void *ret;
123+
void *ret = NULL;
122124
// Perform all atomic opertaions
123-
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
125+
RB_ATOMIC_START
124126
{
125127
if (self->isEmpty(self)) ret = NULL;
126128
// Else copy Object
@@ -133,6 +135,7 @@ void *RingBufPull(RingBuf *self, void *object)
133135
ret = object;
134136
}
135137
}
138+
RB_ATOMIC_END
136139

137140
return ret;
138141
}
@@ -143,10 +146,11 @@ unsigned int RingBufNumElements(RingBuf *self)
143146
unsigned int elements;
144147

145148
// Perform all atomic opertaions
146-
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
149+
RB_ATOMIC_START
147150
{
148151
elements = self->elements;
149152
}
153+
RB_ATOMIC_END
150154

151155
return elements;
152156
}
@@ -157,10 +161,11 @@ bool RingBufIsFull(RingBuf *self)
157161
bool ret;
158162

159163
// Perform all atomic opertaions
160-
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
164+
RB_ATOMIC_START
161165
{
162166
ret = self->elements == self->len;
163167
}
168+
RB_ATOMIC_END
164169

165170
return ret;
166171
}
@@ -171,10 +176,11 @@ bool RingBufIsEmpty(RingBuf *self)
171176
bool ret;
172177

173178
// Perform all atomic opertaions
174-
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
179+
RB_ATOMIC_START
175180
{
176181
ret = !self->elements;
177182
}
183+
RB_ATOMIC_END
178184

179185
return ret;
180186
}

RingBuf.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,32 @@
1515
#endif
1616
#endif
1717

18+
#if defined(ARDUINO_ARCH_AVR)
19+
#include <util/atomic.h>
20+
#define RB_ATOMIC_START ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
21+
#define RB_ATOMIC_END }
22+
23+
24+
#elif defined(ARDUINO_ARCH_ESP8266)
25+
#ifndef __STRINGIFY
26+
#define __STRINGIFY(a) #a
27+
#endif
28+
29+
#ifndef xt_rsil
30+
#define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)); state;}))
31+
#endif
32+
33+
#ifndef xt_wsr_ps
34+
#define xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
35+
#endif
36+
37+
#define RB_ATOMIC_START do { uint32_t _savedIS = xt_rsil(1) ;
38+
#define RB_ATOMIC_END xt_wsr_ps(_savedIS) ;} while(0);
39+
#else
40+
#error “This library only supports AVR and ESP8266 Boards.”
41+
#endif
42+
43+
1844
typedef struct RingBuf RingBuf;
1945

2046
typedef struct RingBuf

library.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name=RingBuf
2-
version=1.3
2+
version=2.0
33
author=D. Aaron Wisner (daw268@cornell.edu)
44
maintainer=D. Aaron Wisner (daw268@cornell.edu)
55
sentence=A library for buffering items into a ring (circular/FIFO) buffer
66
paragraph=This library is perfect for capturing pin states, timestamps, etc.. during an ISR. Then in void loop(), the buffer can be asynchronously processed whenever your program has free time.
77
category=Data Storage
88
url=https://github.com/wizard97/ArduinoRingBuffer
9-
architectures=avr
9+
architectures=avr,esp8266

0 commit comments

Comments
 (0)