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