forked from espressif/arduino-esp32
-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathringbuf.h
415 lines (380 loc) · 17.8 KB
/
ringbuf.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef FREERTOS_RINGBUF_H
#define FREERTOS_RINGBUF_H
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h" must appear in source files before "include ringbuf.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <freertos/queue.h>
/**
* Type by which ring buffers are referenced. For example, a call to xRingbufferCreate()
* returns a RingbufHandle_t variable that can then be used as a parameter to
* xRingbufferSend(), xRingbufferReceive(), etc.
*/
typedef void * RingbufHandle_t;
typedef enum {
/**
* No-split buffers will only store an item in contiguous memory and will
* never split an item. Each item requires an 8 byte overhead for a header
* and will always internally occupy a 32-bit aligned size of space.
*/
RINGBUF_TYPE_NOSPLIT = 0,
/**
* Allow-split buffers will split an item into two parts if necessary in
* order to store it. Each item requires an 8 byte overhead for a header,
* splitting incurs an extra header. Each item will always internally occupy
* a 32-bit aligned size of space.
*/
RINGBUF_TYPE_ALLOWSPLIT,
/**
* Byte buffers store data as a sequence of bytes and do not maintain separate
* items, therefore byte buffers have no overhead. All data is stored as a
* sequence of byte and any number of bytes can be sent or retrieved each
* time.
*/
RINGBUF_TYPE_BYTEBUF
} ringbuf_type_t;
/**
* @brief Create a ring buffer
*
* @param[in] xBufferSize Size of the buffer in bytes. Note that items require
* space for overhead in no-split/allow-split buffers
* @param[in] xBufferType Type of ring buffer, see documentation.
*
* @note xBufferSize of no-split/allow-split buffers will be rounded up to the nearest 32-bit aligned size.
*
* @return A handle to the created ring buffer, or NULL in case of error.
*/
RingbufHandle_t xRingbufferCreate(size_t xBufferSize, ringbuf_type_t xBufferType);
/**
* @brief Create a ring buffer of type RINGBUF_TYPE_NOSPLIT for a fixed item_size
*
* This API is similar to xRingbufferCreate(), but it will internally allocate
* additional space for the headers.
*
* @param[in] xItemSize Size of each item to be put into the ring buffer
* @param[in] xItemNum Maximum number of items the buffer needs to hold simultaneously
*
* @return A RingbufHandle_t handle to the created ring buffer, or NULL in case of error.
*/
RingbufHandle_t xRingbufferCreateNoSplit(size_t xItemSize, size_t xItemNum);
/**
* @brief Insert an item into the ring buffer
*
* Attempt to insert an item into the ring buffer. This function will block until
* enough free space is available or until it timesout.
*
* @param[in] xRingbuffer Ring buffer to insert the item into
* @param[in] pvItem Pointer to data to insert. NULL is allowed if xItemSize is 0.
* @param[in] xItemSize Size of data to insert.
* @param[in] xTicksToWait Ticks to wait for room in the ring buffer.
*
* @note For no-split/allow-split ring buffers, the actual size of memory that
* the item will occupy will be rounded up to the nearest 32-bit aligned
* size. This is done to ensure all items are always stored in 32-bit
* aligned fashion.
*
* @return
* - pdTRUE if succeeded
* - pdFALSE on time-out or when the data is larger than the maximum permissible size of the buffer
*/
BaseType_t xRingbufferSend(RingbufHandle_t xRingbuffer, const void *pvItem, size_t xItemSize, TickType_t xTicksToWait);
/**
* @brief Insert an item into the ring buffer in an ISR
*
* Attempt to insert an item into the ring buffer from an ISR. This function
* will return immediately if there is insufficient free space in the buffer.
*
* @param[in] xRingbuffer Ring buffer to insert the item into
* @param[in] pvItem Pointer to data to insert. NULL is allowed if xItemSize is 0.
* @param[in] xItemSize Size of data to insert.
* @param[out] pxHigherPriorityTaskWoken Value pointed to will be set to pdTRUE if the function woke up a higher priority task.
*
* @note For no-split/allow-split ring buffers, the actual size of memory that
* the item will occupy will be rounded up to the nearest 32-bit aligned
* size. This is done to ensure all items are always stored in 32-bit
* aligned fashion.
*
* @return
* - pdTRUE if succeeded
* - pdFALSE when the ring buffer does not have space.
*/
BaseType_t xRingbufferSendFromISR(RingbufHandle_t xRingbuffer, const void *pvItem, size_t xItemSize, BaseType_t *pxHigherPriorityTaskWoken);
/**
* @brief Retrieve an item from the ring buffer
*
* Attempt to retrieve an item from the ring buffer. This function will block
* until an item is available or until it timesout.
*
* @param[in] xRingbuffer Ring buffer to retrieve the item from
* @param[out] pxItemSize Pointer to a variable to which the size of the retrieved item will be written.
* @param[in] xTicksToWait Ticks to wait for items in the ring buffer.
*
* @note A call to vRingbufferReturnItem() is required after this to free the item retrieved.
*
* @return
* - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item.
* - NULL on timeout, *pxItemSize is untouched in that case.
*/
void *xRingbufferReceive(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait);
/**
* @brief Retrieve an item from the ring buffer in an ISR
*
* Attempt to retrieve an item from the ring buffer. This function returns immediately
* if there are no items available for retrieval
*
* @param[in] xRingbuffer Ring buffer to retrieve the item from
* @param[out] pxItemSize Pointer to a variable to which the size of the
* retrieved item will be written.
*
* @note A call to vRingbufferReturnItemFromISR() is required after this to free the item retrieved.
* @note Byte buffers do not allow multiple retrievals before returning an item
*
* @return
* - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item.
* - NULL when the ring buffer is empty, *pxItemSize is untouched in that case.
*/
void *xRingbufferReceiveFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize);
/**
* @brief Retrieve a split item from an allow-split ring buffer
*
* Attempt to retrieve a split item from an allow-split ring buffer. If the item
* is not split, only a single item is retried. If the item is split, both parts
* will be retrieved. This function will block until an item is available or
* until it timesout.
*
* @param[in] xRingbuffer Ring buffer to retrieve the item from
* @param[out] ppvHeadItem Double pointer to first part (set to NULL if no items were retrieved)
* @param[out] ppvTailItem Double pointer to second part (set to NULL if item is not split)
* @param[out] pxHeadItemSize Pointer to size of first part (unmodified if no items were retrieved)
* @param[out] pxTailItemSize Pointer to size of second part (unmodified if item is not split)
* @param[in] xTicksToWait Ticks to wait for items in the ring buffer.
*
* @note Call(s) to vRingbufferReturnItem() is required after this to free up the item(s) retrieved.
* @note This function should only be called on allow-split buffers
*
* @return
* - pdTRUE if an item (split or unsplit) was retrieved
* - pdFALSE when no item was retrieved
*/
BaseType_t xRingbufferReceiveSplit(RingbufHandle_t xRingbuffer, void **ppvHeadItem, void **ppvTailItem, size_t *pxHeadItemSize, size_t *pxTailItemSize, TickType_t xTicksToWait);
/**
* @brief Retrieve a split item from an allow-split ring buffer in an ISR
*
* Attempt to retrieve a split item from an allow-split ring buffer. If the item
* is not split, only a single item is retried. If the item is split, both parts
* will be retrieved. This function returns immediately if there are no items
* available for retrieval
*
* @param[in] xRingbuffer Ring buffer to retrieve the item from
* @param[out] ppvHeadItem Double pointer to first part (set to NULL if no items were retrieved)
* @param[out] ppvTailItem Double pointer to second part (set to NULL if item is not split)
* @param[out] pxHeadItemSize Pointer to size of first part (unmodified if no items were retrieved)
* @param[out] pxTailItemSize Pointer to size of second part (unmodified if item is not split)
*
* @note Calls to vRingbufferReturnItemFromISR() is required after this to free up the item(s) retrieved.
* @note This function should only be called on allow-split buffers
*
* @return
* - pdTRUE if an item (split or unsplit) was retrieved
* - pdFALSE when no item was retrieved
*/
BaseType_t xRingbufferReceiveSplitFromISR(RingbufHandle_t xRingbuffer, void **ppvHeadItem, void **ppvTailItem, size_t *pxHeadItemSize, size_t *pxTailItemSize);
/**
* @brief Retrieve bytes from a byte buffer, specifying the maximum amount of bytes to retrieve
*
* Attempt to retrieve data from a byte buffer whilst specifying a maximum number
* of bytes to retrieve. This function will block until there is data available
* for retrieval or until it timesout.
*
* @param[in] xRingbuffer Ring buffer to retrieve the item from
* @param[out] pxItemSize Pointer to a variable to which the size of the retrieved item will be written.
* @param[in] xTicksToWait Ticks to wait for items in the ring buffer.
* @param[in] xMaxSize Maximum number of bytes to return.
*
* @note A call to vRingbufferReturnItem() is required after this to free up the data retrieved.
* @note This function should only be called on byte buffers
* @note Byte buffers do not allow multiple retrievals before returning an item
*
* @return
* - Pointer to the retrieved item on success; *pxItemSize filled with
* the length of the item.
* - NULL on timeout, *pxItemSize is untouched in that case.
*/
void *xRingbufferReceiveUpTo(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait, size_t xMaxSize);
/**
* @brief Retrieve bytes from a byte buffer, specifying the maximum amount of
* bytes to retrieve. Call this from an ISR.
*
* Attempt to retrieve bytes from a byte buffer whilst specifying a maximum number
* of bytes to retrieve. This function will return immediately if there is no data
* available for retrieval.
*
* @param[in] xRingbuffer Ring buffer to retrieve the item from
* @param[out] pxItemSize Pointer to a variable to which the size of the retrieved item will be written.
* @param[in] xMaxSize Maximum number of bytes to return.
*
* @note A call to vRingbufferReturnItemFromISR() is required after this to free up the data received.
* @note This function should only be called on byte buffers
* @note Byte buffers do not allow multiple retrievals before returning an item
*
* @return
* - Pointer to the retrieved item on success; *pxItemSize filled with
* the length of the item.
* - NULL when the ring buffer is empty, *pxItemSize is untouched in that case.
*/
void *xRingbufferReceiveUpToFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize, size_t xMaxSize);
/**
* @brief Return a previously-retrieved item to the ring buffer
*
* @param[in] xRingbuffer Ring buffer the item was retrieved from
* @param[in] pvItem Item that was received earlier
*
* @note If a split item is retrieved, both parts should be returned by calling this function twice
*/
void vRingbufferReturnItem(RingbufHandle_t xRingbuffer, void *pvItem);
/**
* @brief Return a previously-retrieved item to the ring buffer from an ISR
*
* @param[in] xRingbuffer Ring buffer the item was retrieved from
* @param[in] pvItem Item that was received earlier
* @param[out] pxHigherPriorityTaskWoken Value pointed to will be set to pdTRUE
* if the function woke up a higher priority task.
*
* @note If a split item is retrieved, both parts should be returned by calling this function twice
*/
void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, BaseType_t *pxHigherPriorityTaskWoken);
/**
* @brief Delete a ring buffer
*
* @param[in] xRingbuffer Ring buffer to delete
*/
void vRingbufferDelete(RingbufHandle_t xRingbuffer);
/**
* @brief Get maximum size of an item that can be placed in the ring buffer
*
* This function returns the maximum size an item can have if it was placed in
* an empty ring buffer.
*
* @param[in] xRingbuffer Ring buffer to query
*
* @return Maximum size, in bytes, of an item that can be placed in a ring buffer.
*/
size_t xRingbufferGetMaxItemSize(RingbufHandle_t xRingbuffer);
/**
* @brief Get current free size available for an item/data in the buffer
*
* This gives the real time free space available for an item/data in the ring
* buffer. This represents the maximum size an item/data can have if it was
* currently sent to the ring buffer.
*
* @warning This API is not thread safe. So, if multiple threads are accessing
* the same ring buffer, it is the application's responsibility to
* ensure atomic access to this API and the subsequent Send
*
* @param[in] xRingbuffer Ring buffer to query
*
* @return Current free size, in bytes, available for an entry
*/
size_t xRingbufferGetCurFreeSize(RingbufHandle_t xRingbuffer);
/**
* @brief Add the ring buffer's read semaphore to a queue set.
*
* The ring buffer's read semaphore indicates that data has been written
* to the ring buffer. This function adds the ring buffer's read semaphore to
* a queue set.
*
* @param[in] xRingbuffer Ring buffer to add to the queue set
* @param[in] xQueueSet Queue set to add the ring buffer's read semaphore to
*
* @return
* - pdTRUE on success, pdFALSE otherwise
*/
BaseType_t xRingbufferAddToQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet);
/**
* @brief Check if the selected queue set member is the ring buffer's read semaphore
*
* This API checks if queue set member returned from xQueueSelectFromSet()
* is the read semaphore of this ring buffer. If so, this indicates the ring buffer
* has items waiting to be retrieved.
*
* @param[in] xRingbuffer Ring buffer which should be checked
* @param[in] xMember Member returned from xQueueSelectFromSet
*
* @return
* - pdTRUE when semaphore belongs to ring buffer
* - pdFALSE otherwise.
*/
BaseType_t xRingbufferCanRead(RingbufHandle_t xRingbuffer, QueueSetMemberHandle_t xMember);
/**
* @brief Remove the ring buffer's read semaphore from a queue set.
*
* This specifically removes a ring buffer's read semaphore from a queue set. The
* read semaphore is used to indicate when data has been written to the ring buffer
*
* @param[in] xRingbuffer Ring buffer to remove from the queue set
* @param[in] xQueueSet Queue set to remove the ring buffer's read semaphore from
*
* @return
* - pdTRUE on success
* - pdFALSE otherwise
*/
BaseType_t xRingbufferRemoveFromQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet);
/**
* @brief Get information about ring buffer status
*
* Get information of the a ring buffer's current status such as
* free/read/write pointer positions, and number of items waiting to be retrieved.
* Arguments can be set to NULL if they are not required.
*
* @param[in] xRingbuffer Ring buffer to remove from the queue set
* @param[out] uxFree Pointer use to store free pointer position
* @param[out] uxRead Pointer use to store read pointer position
* @param[out] uxWrite Pointer use to store write pointer position
* @param[out] uxItemsWaiting Pointer use to store number of items (bytes for byte buffer) waiting to be retrieved
*/
void vRingbufferGetInfo(RingbufHandle_t xRingbuffer, UBaseType_t *uxFree, UBaseType_t *uxRead, UBaseType_t *uxWrite, UBaseType_t *uxItemsWaiting);
/**
* @brief Debugging function to print the internal pointers in the ring buffer
*
* @param xRingbuffer Ring buffer to show
*/
void xRingbufferPrintInfo(RingbufHandle_t xRingbuffer);
/* -------------------------------- Deprecated Functions --------------------------- */
/** @cond */ //Doxygen command to hide deprecated function from API Reference
/*
* Deprecated as function is not thread safe and does not check if an item is
* actually available for retrieval. Use xRingbufferReceiveSplit() instead for
* thread safe method of retrieve a split item.
*/
bool xRingbufferIsNextItemWrapped(RingbufHandle_t xRingbuffer) __attribute__((deprecated));
/*
* Deprecated as queue sets are not meant to be used for writing to buffers. Adding
* the ring buffer write semaphore to a queue set will break queue set usage rules,
* as every read of a semaphore must be preceded by a call to xQueueSelectFromSet().
* QueueSetWrite no longer supported.
*/
BaseType_t xRingbufferAddToQueueSetWrite(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet) __attribute__((deprecated));
/*
* Deprecated as queue sets are not meant to be used for writing to buffers.
* QueueSetWrite no longer supported.
*/
BaseType_t xRingbufferRemoveFromQueueSetWrite(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet) __attribute__((deprecated));
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif /* FREERTOS_RINGBUF_H */