1 // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef FREERTOS_RINGBUF_H
16 #define FREERTOS_RINGBUF_H
17 
18 #ifndef INC_FREERTOS_H
19     #error "include FreeRTOS.h" must appear in source files before "include ringbuf.h"
20 #endif
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #include <freertos/queue.h>
27 
28 /**
29  * Type by which ring buffers are referenced. For example, a call to xRingbufferCreate()
30  * returns a RingbufHandle_t variable that can then be used as a parameter to
31  * xRingbufferSend(), xRingbufferReceive(), etc.
32  */
33 typedef void * RingbufHandle_t;
34 
35 typedef enum {
36     /**
37      * No-split buffers will only store an item in contiguous memory and will
38      * never split an item. Each item requires an 8 byte overhead for a header
39      * and will always internally occupy a 32-bit aligned size of space.
40      */
41     RINGBUF_TYPE_NOSPLIT = 0,
42     /**
43      * Allow-split buffers will split an item into two parts if necessary in
44      * order to store it. Each item requires an 8 byte overhead for a header,
45      * splitting incurs an extra header. Each item will always internally occupy
46      * a 32-bit aligned size of space.
47      */
48     RINGBUF_TYPE_ALLOWSPLIT,
49     /**
50      * Byte buffers store data as a sequence of bytes and do not maintain separate
51      * items, therefore byte buffers have no overhead. All data is stored as a
52      * sequence of byte and any number of bytes can be sent or retrieved each
53      * time.
54      */
55     RINGBUF_TYPE_BYTEBUF,
56     RINGBUF_TYPE_MAX,
57 } RingbufferType_t;
58 
59 /**
60  * @brief Struct that is equivalent in size to the ring buffer's data structure
61  *
62  * The contents of this struct are not meant to be used directly. This
63  * structure is meant to be used when creating a statically allocated ring
64  * buffer where this struct is of the exact size required to store a ring
65  * buffer's control data structure.
66  *
67  */
68 #if ( configSUPPORT_STATIC_ALLOCATION == 1)
69 typedef struct xSTATIC_RINGBUFFER {
70     /** @cond */    //Doxygen command to hide this structure from API Reference
71     size_t xDummy1[2];
72     UBaseType_t uxDummy2;
73     BaseType_t xDummy3;
74     void *pvDummy4[11];
75     StaticSemaphore_t xDummy5[2];
76     portMUX_TYPE muxDummy;
77     /** @endcond */
78 } StaticRingbuffer_t;
79 #endif
80 
81 /**
82  * @brief       Create a ring buffer
83  *
84  * @param[in]   xBufferSize Size of the buffer in bytes. Note that items require
85  *              space for overhead in no-split/allow-split buffers
86  * @param[in]   xBufferType Type of ring buffer, see documentation.
87  *
88  * @note    xBufferSize of no-split/allow-split buffers will be rounded up to the nearest 32-bit aligned size.
89  *
90  * @return  A handle to the created ring buffer, or NULL in case of error.
91  */
92 RingbufHandle_t xRingbufferCreate(size_t xBufferSize, RingbufferType_t xBufferType);
93 
94 /**
95  * @brief Create a ring buffer of type RINGBUF_TYPE_NOSPLIT for a fixed item_size
96  *
97  * This API is similar to xRingbufferCreate(), but it will internally allocate
98  * additional space for the headers.
99  *
100  * @param[in]   xItemSize   Size of each item to be put into the ring buffer
101  * @param[in]   xItemNum    Maximum number of items the buffer needs to hold simultaneously
102  *
103  * @return  A RingbufHandle_t handle to the created ring buffer, or NULL in case of error.
104  */
105 RingbufHandle_t xRingbufferCreateNoSplit(size_t xItemSize, size_t xItemNum);
106 
107 
108 /**
109  * @brief       Create a ring buffer but manually provide the required memory
110  *
111  * @param[in]   xBufferSize Size of the buffer in bytes.
112  * @param[in]   xBufferType Type of ring buffer, see documentation
113  * @param[in]   pucRingbufferStorage Pointer to the ring buffer's storage area.
114  *              Storage area must of the same size as specified by xBufferSize
115  * @param[in]   pxStaticRingbuffer Pointed to a struct of type StaticRingbuffer_t
116  *              which will be used to hold the ring buffer's data structure
117  *
118  * @note    xBufferSize of no-split/allow-split buffers MUST be 32-bit aligned.
119  *
120  * @return  A handle to the created ring buffer
121  */
122 #if ( configSUPPORT_STATIC_ALLOCATION == 1)
123 RingbufHandle_t xRingbufferCreateStatic(size_t xBufferSize,
124                                         RingbufferType_t xBufferType,
125                                         uint8_t *pucRingbufferStorage,
126                                         StaticRingbuffer_t *pxStaticRingbuffer);
127 #endif
128 
129 /**
130  * @brief       Insert an item into the ring buffer
131  *
132  * Attempt to insert an item into the ring buffer. This function will block until
133  * enough free space is available or until it times out.
134  *
135  * @param[in]   xRingbuffer     Ring buffer to insert the item into
136  * @param[in]   pvItem          Pointer to data to insert. NULL is allowed if xItemSize is 0.
137  * @param[in]   xItemSize       Size of data to insert.
138  * @param[in]   xTicksToWait    Ticks to wait for room in the ring buffer.
139  *
140  * @note    For no-split/allow-split ring buffers, the actual size of memory that
141  *          the item will occupy will be rounded up to the nearest 32-bit aligned
142  *          size. This is done to ensure all items are always stored in 32-bit
143  *          aligned fashion.
144  *
145  * @return
146  *      - pdTRUE if succeeded
147  *      - pdFALSE on time-out or when the data is larger than the maximum permissible size of the buffer
148  */
149 BaseType_t xRingbufferSend(RingbufHandle_t xRingbuffer,
150                            const void *pvItem,
151                            size_t xItemSize,
152                            TickType_t xTicksToWait);
153 
154 /**
155  * @brief       Insert an item into the ring buffer in an ISR
156  *
157  * Attempt to insert an item into the ring buffer from an ISR. This function
158  * will return immediately if there is insufficient free space in the buffer.
159  *
160  * @param[in]   xRingbuffer Ring buffer to insert the item into
161  * @param[in]   pvItem      Pointer to data to insert. NULL is allowed if xItemSize is 0.
162  * @param[in]   xItemSize   Size of data to insert.
163  * @param[out]  pxHigherPriorityTaskWoken   Value pointed to will be set to pdTRUE if the function woke up a higher priority task.
164  *
165  * @note    For no-split/allow-split ring buffers, the actual size of memory that
166  *          the item will occupy will be rounded up to the nearest 32-bit aligned
167  *          size. This is done to ensure all items are always stored in 32-bit
168  *          aligned fashion.
169  *
170  * @return
171  *      - pdTRUE if succeeded
172  *      - pdFALSE when the ring buffer does not have space.
173  */
174 BaseType_t xRingbufferSendFromISR(RingbufHandle_t xRingbuffer,
175                                   const void *pvItem,
176                                   size_t xItemSize,
177                                   BaseType_t *pxHigherPriorityTaskWoken);
178 
179 /**
180  * @brief Acquire memory from the ring buffer to be written to by an external
181  *        source and to be sent later.
182  *
183  * Attempt to allocate buffer for an item to be sent into the ring buffer. This
184  * function will block until enough free space is available or until it
185  * timesout.
186  *
187  * The item, as well as the following items ``SendAcquire`` or ``Send`` after it,
188  * will not be able to be read from the ring buffer until this item is actually
189  * sent into the ring buffer.
190  *
191  * @param[in]   xRingbuffer     Ring buffer to allocate the memory
192  * @param[out]  ppvItem         Double pointer to memory acquired (set to NULL if no memory were retrieved)
193  * @param[in]   xItemSize       Size of item to acquire.
194  * @param[in]   xTicksToWait    Ticks to wait for room in the ring buffer.
195  *
196  * @note Only applicable for no-split ring buffers now, the actual size of
197  *       memory that the item will occupy will be rounded up to the nearest 32-bit
198  *       aligned size. This is done to ensure all items are always stored in 32-bit
199  *       aligned fashion.
200  *
201  * @return
202  *      - pdTRUE if succeeded
203  *      - pdFALSE on time-out or when the data is larger than the maximum permissible size of the buffer
204  */
205 BaseType_t xRingbufferSendAcquire(RingbufHandle_t xRingbuffer, void **ppvItem, size_t xItemSize, TickType_t xTicksToWait);
206 
207 /**
208  * @brief       Actually send an item into the ring buffer allocated before by
209  *              ``xRingbufferSendAcquire``.
210  *
211  * @param[in]   xRingbuffer     Ring buffer to insert the item into
212  * @param[in]   pvItem          Pointer to item in allocated memory to insert.
213  *
214  * @note Only applicable for no-split ring buffers. Only call for items
215  *       allocated by ``xRingbufferSendAcquire``.
216  *
217  * @return
218  *      - pdTRUE if succeeded
219  *      - pdFALSE if fail for some reason.
220  */
221 BaseType_t xRingbufferSendComplete(RingbufHandle_t xRingbuffer, void *pvItem);
222 
223 /**
224  * @brief   Retrieve an item from the ring buffer
225  *
226  * Attempt to retrieve an item from the ring buffer. This function will block
227  * until an item is available or until it times out.
228  *
229  * @param[in]   xRingbuffer     Ring buffer to retrieve the item from
230  * @param[out]  pxItemSize      Pointer to a variable to which the size of the retrieved item will be written.
231  * @param[in]   xTicksToWait    Ticks to wait for items in the ring buffer.
232  *
233  * @note    A call to vRingbufferReturnItem() is required after this to free the item retrieved.
234  *
235  * @return
236  *      - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item.
237  *      - NULL on timeout, *pxItemSize is untouched in that case.
238  */
239 void *xRingbufferReceive(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait);
240 
241 /**
242  * @brief   Retrieve an item from the ring buffer in an ISR
243  *
244  * Attempt to retrieve an item from the ring buffer. This function returns immediately
245  * if there are no items available for retrieval
246  *
247  * @param[in]   xRingbuffer     Ring buffer to retrieve the item from
248  * @param[out]  pxItemSize      Pointer to a variable to which the size of the
249  *                              retrieved item will be written.
250  *
251  * @note    A call to vRingbufferReturnItemFromISR() is required after this to free the item retrieved.
252  * @note    Byte buffers do not allow multiple retrievals before returning an item
253  * @note    Two calls to RingbufferReceiveFromISR() are required if the bytes wrap around the end of the ring buffer.
254  *
255  * @return
256  *      - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item.
257  *      - NULL when the ring buffer is empty, *pxItemSize is untouched in that case.
258  */
259 void *xRingbufferReceiveFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize);
260 
261 /**
262  * @brief   Retrieve a split item from an allow-split ring buffer
263  *
264  * Attempt to retrieve a split item from an allow-split ring buffer. If the item
265  * is not split, only a single item is retried. If the item is split, both parts
266  * will be retrieved. This function will block until an item is available or
267  * until it times out.
268  *
269  * @param[in]   xRingbuffer     Ring buffer to retrieve the item from
270  * @param[out]  ppvHeadItem     Double pointer to first part (set to NULL if no items were retrieved)
271  * @param[out]  ppvTailItem     Double pointer to second part (set to NULL if item is not split)
272  * @param[out]  pxHeadItemSize  Pointer to size of first part (unmodified if no items were retrieved)
273  * @param[out]  pxTailItemSize  Pointer to size of second part (unmodified if item is not split)
274  * @param[in]   xTicksToWait    Ticks to wait for items in the ring buffer.
275  *
276  * @note    Call(s) to vRingbufferReturnItem() is required after this to free up the item(s) retrieved.
277  * @note    This function should only be called on allow-split buffers
278  *
279  * @return
280  *      - pdTRUE if an item (split or unsplit) was retrieved
281  *      - pdFALSE when no item was retrieved
282  */
283 BaseType_t xRingbufferReceiveSplit(RingbufHandle_t xRingbuffer,
284                                    void **ppvHeadItem,
285                                    void **ppvTailItem,
286                                    size_t *pxHeadItemSize,
287                                    size_t *pxTailItemSize,
288                                    TickType_t xTicksToWait);
289 
290 /**
291  * @brief   Retrieve a split item from an allow-split ring buffer in an ISR
292  *
293  * Attempt to retrieve a split item from an allow-split ring buffer. If the item
294  * is not split, only a single item is retried. If the item is split, both parts
295  * will be retrieved. This function returns immediately if there are no items
296  * available for retrieval
297  *
298  * @param[in]   xRingbuffer     Ring buffer to retrieve the item from
299  * @param[out]  ppvHeadItem     Double pointer to first part (set to NULL if no items were retrieved)
300  * @param[out]  ppvTailItem     Double pointer to second part (set to NULL if item is not split)
301  * @param[out]  pxHeadItemSize  Pointer to size of first part (unmodified if no items were retrieved)
302  * @param[out]  pxTailItemSize  Pointer to size of second part (unmodified if item is not split)
303  *
304  * @note    Calls to vRingbufferReturnItemFromISR() is required after this to free up the item(s) retrieved.
305  * @note    This function should only be called on allow-split buffers
306  *
307  * @return
308  *      - pdTRUE if an item (split or unsplit) was retrieved
309  *      - pdFALSE when no item was retrieved
310  */
311 BaseType_t xRingbufferReceiveSplitFromISR(RingbufHandle_t xRingbuffer,
312                                           void **ppvHeadItem,
313                                           void **ppvTailItem,
314                                           size_t *pxHeadItemSize,
315                                           size_t *pxTailItemSize);
316 
317 /**
318  * @brief   Retrieve bytes from a byte buffer, specifying the maximum amount of bytes to retrieve
319  *
320  * Attempt to retrieve data from a byte buffer whilst specifying a maximum number
321  * of bytes to retrieve. This function will block until there is data available
322  * for retrieval or until it times out.
323  *
324  * @param[in]   xRingbuffer     Ring buffer to retrieve the item from
325  * @param[out]  pxItemSize      Pointer to a variable to which the size of the retrieved item will be written.
326  * @param[in]   xTicksToWait    Ticks to wait for items in the ring buffer.
327  * @param[in]   xMaxSize        Maximum number of bytes to return.
328  *
329  * @note    A call to vRingbufferReturnItem() is required after this to free up the data retrieved.
330  * @note    This function should only be called on byte buffers
331  * @note    Byte buffers do not allow multiple retrievals before returning an item
332  * @note    Two calls to RingbufferReceiveUpTo() are required if the bytes wrap around the end of the ring buffer.
333  *
334  * @return
335  *      - Pointer to the retrieved item on success; *pxItemSize filled with
336  *        the length of the item.
337  *      - NULL on timeout, *pxItemSize is untouched in that case.
338  */
339 void *xRingbufferReceiveUpTo(RingbufHandle_t xRingbuffer,
340                              size_t *pxItemSize,
341                              TickType_t xTicksToWait,
342                              size_t xMaxSize);
343 
344 /**
345  * @brief   Retrieve bytes from a byte buffer, specifying the maximum amount of
346  *          bytes to retrieve. Call this from an ISR.
347  *
348  * Attempt to retrieve bytes from a byte buffer whilst specifying a maximum number
349  * of bytes to retrieve. This function will return immediately if there is no data
350  * available for retrieval.
351  *
352  * @param[in]   xRingbuffer Ring buffer to retrieve the item from
353  * @param[out]  pxItemSize  Pointer to a variable to which the size of the retrieved item will be written.
354  * @param[in]   xMaxSize    Maximum number of bytes to return.
355  *
356  * @note    A call to vRingbufferReturnItemFromISR() is required after this to free up the data received.
357  * @note    This function should only be called on byte buffers
358  * @note    Byte buffers do not allow multiple retrievals before returning an item
359  *
360  * @return
361  *      - Pointer to the retrieved item on success; *pxItemSize filled with
362  *        the length of the item.
363  *      - NULL when the ring buffer is empty, *pxItemSize is untouched in that case.
364  */
365 void *xRingbufferReceiveUpToFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize, size_t xMaxSize);
366 
367 /**
368  * @brief   Return a previously-retrieved item to the ring buffer
369  *
370  * @param[in]   xRingbuffer Ring buffer the item was retrieved from
371  * @param[in]   pvItem      Item that was received earlier
372  *
373  * @note    If a split item is retrieved, both parts should be returned by calling this function twice
374  */
375 void vRingbufferReturnItem(RingbufHandle_t xRingbuffer, void *pvItem);
376 
377 /**
378  * @brief   Return a previously-retrieved item to the ring buffer from an ISR
379  *
380  * @param[in]   xRingbuffer Ring buffer the item was retrieved from
381  * @param[in]   pvItem      Item that was received earlier
382  * @param[out]  pxHigherPriorityTaskWoken   Value pointed to will be set to pdTRUE
383  *                                          if the function woke up a higher priority task.
384  *
385  * @note    If a split item is retrieved, both parts should be returned by calling this function twice
386  */
387 void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, BaseType_t *pxHigherPriorityTaskWoken);
388 
389 /**
390  * @brief   Delete a ring buffer
391  *
392  * @param[in]   xRingbuffer     Ring buffer to delete
393  *
394  * @note    This function will not deallocate any memory if the ring buffer was
395  *          created using xRingbufferCreateStatic(). Deallocation must be done
396  *          manually be the user.
397  */
398 void vRingbufferDelete(RingbufHandle_t xRingbuffer);
399 
400 /**
401  * @brief   Get maximum size of an item that can be placed in the ring buffer
402  *
403  * This function returns the maximum size an item can have if it was placed in
404  * an empty ring buffer.
405  *
406  * @param[in]   xRingbuffer     Ring buffer to query
407  *
408  * @note    The max item size for a no-split buffer is limited to
409  *          ((buffer_size/2)-header_size). This limit is imposed so that an item
410  *          of max item size can always be sent to the an empty no-split buffer
411  *          regardless of the internal positions of the buffer's read/write/free
412  *          pointers.
413  *
414  * @return  Maximum size, in bytes, of an item that can be placed in a ring buffer.
415  */
416 size_t xRingbufferGetMaxItemSize(RingbufHandle_t xRingbuffer);
417 
418 /**
419  * @brief   Get current free size available for an item/data in the buffer
420  *
421  * This gives the real time free space available for an item/data in the ring
422  * buffer. This represents the maximum size an item/data can have if it was
423  * currently sent to the ring buffer.
424  *
425  * @warning This API is not thread safe. So, if multiple threads are accessing
426  *          the same ring buffer, it is the application's responsibility to
427  *          ensure atomic access to this API and the subsequent Send
428  *
429  * @note    An empty no-split buffer has a max current free size for an item
430  *          that is limited to ((buffer_size/2)-header_size). See API reference
431  *          for xRingbufferGetMaxItemSize().
432  *
433  * @param[in]   xRingbuffer     Ring buffer to query
434  *
435  * @return  Current free size, in bytes, available for an entry
436  */
437 size_t xRingbufferGetCurFreeSize(RingbufHandle_t xRingbuffer);
438 
439 /**
440  * @brief   Add the ring buffer's read semaphore to a queue set.
441  *
442  * The ring buffer's read semaphore indicates that data has been written
443  * to the ring buffer. This function adds the ring buffer's read semaphore to
444  * a queue set.
445  *
446  * @param[in]   xRingbuffer     Ring buffer to add to the queue set
447  * @param[in]   xQueueSet       Queue set to add the ring buffer's read semaphore to
448  *
449  * @return
450  *      - pdTRUE on success, pdFALSE otherwise
451  */
452 BaseType_t xRingbufferAddToQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet);
453 
454 
455 /**
456  * @brief   Check if the selected queue set member is the ring buffer's read semaphore
457  *
458  * This API checks if queue set member returned from xQueueSelectFromSet()
459  * is the read semaphore of this ring buffer. If so, this indicates the ring buffer
460  * has items waiting to be retrieved.
461  *
462  * @param[in]   xRingbuffer     Ring buffer which should be checked
463  * @param[in]   xMember         Member returned from xQueueSelectFromSet
464  *
465  * @return
466  *      - pdTRUE when semaphore belongs to ring buffer
467  *      - pdFALSE otherwise.
468  */
469 BaseType_t xRingbufferCanRead(RingbufHandle_t xRingbuffer, QueueSetMemberHandle_t xMember);
470 
471 /**
472  * @brief   Remove the ring buffer's read semaphore from a queue set.
473  *
474  * This specifically removes a ring buffer's read semaphore from a queue set. The
475  * read semaphore is used to indicate when data has been written to the ring buffer
476  *
477  * @param[in]   xRingbuffer     Ring buffer to remove from the queue set
478  * @param[in]   xQueueSet       Queue set to remove the ring buffer's read semaphore from
479  *
480  * @return
481  *      - pdTRUE on success
482  *      - pdFALSE otherwise
483  */
484 BaseType_t xRingbufferRemoveFromQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet);
485 
486 /**
487  * @brief   Get information about ring buffer status
488  *
489  * Get information of the a ring buffer's current status such as
490  * free/read/write pointer positions, and number of items waiting to be retrieved.
491  * Arguments can be set to NULL if they are not required.
492  *
493  * @param[in]   xRingbuffer     Ring buffer to remove from the queue set
494  * @param[out]  uxFree          Pointer use to store free pointer position
495  * @param[out]  uxRead          Pointer use to store read pointer position
496  * @param[out]  uxWrite         Pointer use to store write pointer position
497  * @param[out]  uxAcquire       Pointer use to store acquire pointer position
498  * @param[out]  uxItemsWaiting  Pointer use to store number of items (bytes for byte buffer) waiting to be retrieved
499  */
500 void vRingbufferGetInfo(RingbufHandle_t xRingbuffer,
501                         UBaseType_t *uxFree,
502                         UBaseType_t *uxRead,
503                         UBaseType_t *uxWrite,
504                         UBaseType_t *uxAcquire,
505                         UBaseType_t *uxItemsWaiting);
506 
507 /**
508  * @brief   Debugging function to print the internal pointers in the ring buffer
509  *
510  * @param   xRingbuffer Ring buffer to show
511  */
512 void xRingbufferPrintInfo(RingbufHandle_t xRingbuffer);
513 
514 #ifdef __cplusplus
515 }
516 #endif
517 
518 #endif /* FREERTOS_RINGBUF_H */
519