| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 |
- /*
- * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #pragma once
- #include "freertos/FreeRTOS.h"
- #include "freertos/queue.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- /**
- * 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_MAX,
- } RingbufferType_t;
- /**
- * @brief Struct that is equivalent in size to the ring buffer's data structure
- *
- * The contents of this struct are not meant to be used directly. This
- * structure is meant to be used when creating a statically allocated ring
- * buffer where this struct is of the exact size required to store a ring
- * buffer's control data structure.
- *
- */
- typedef struct xSTATIC_RINGBUFFER {
- /** @cond */ //Doxygen command to hide this structure from API Reference
- size_t xDummy1[2];
- UBaseType_t uxDummy2;
- void *pvDummy3[11];
- BaseType_t xDummy4;
- StaticList_t xDummy5[2];
- void * pvDummy6;
- portMUX_TYPE muxDummy;
- /** @endcond */
- } StaticRingbuffer_t;
- /**
- * @brief Create a ring buffer
- *
- * @param[in] xBufferSize Size of the buffer in bytes. Note that items require
- * space for a header 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, RingbufferType_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 Create a ring buffer but manually provide the required memory
- *
- * @param[in] xBufferSize Size of the buffer in bytes.
- * @param[in] xBufferType Type of ring buffer, see documentation
- * @param[in] pucRingbufferStorage Pointer to the ring buffer's storage area.
- * Storage area must have the same size as specified by xBufferSize
- * @param[in] pxStaticRingbuffer Pointed to a struct of type StaticRingbuffer_t
- * which will be used to hold the ring buffer's data structure
- *
- * @note xBufferSize of no-split/allow-split buffers MUST be 32-bit aligned.
- *
- * @return A handle to the created ring buffer
- */
- RingbufHandle_t xRingbufferCreateStatic(size_t xBufferSize,
- RingbufferType_t xBufferType,
- uint8_t *pucRingbufferStorage,
- StaticRingbuffer_t *pxStaticRingbuffer);
- /**
- * @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 times out.
- *
- * @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.
- * @note For no-split/allow-split buffers, an xItemSize of 0 will result in
- * an item with no data being set (i.e., item only contains the header).
- * For byte buffers, an xItemSize of 0 will simply return pdTRUE without
- * copying any data.
- *
- * @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.
- * @note For no-split/allow-split buffers, an xItemSize of 0 will result in
- * an item with no data being set (i.e., item only contains the header).
- * For byte buffers, an xItemSize of 0 will simply return pdTRUE without
- * copying any data.
- *
- * @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 Acquire memory from the ring buffer to be written to by an external
- * source and to be sent later.
- *
- * Attempt to allocate buffer for an item to be sent into the ring buffer. This
- * function will block until enough free space is available or until it
- * times out.
- *
- * The item, as well as the following items ``SendAcquire`` or ``Send`` after it,
- * will not be able to be read from the ring buffer until this item is actually
- * sent into the ring buffer.
- *
- * @param[in] xRingbuffer Ring buffer to allocate the memory
- * @param[out] ppvItem Double pointer to memory acquired (set to NULL if no memory were retrieved)
- * @param[in] xItemSize Size of item to acquire.
- * @param[in] xTicksToWait Ticks to wait for room in the ring buffer.
- *
- * @note Only applicable for no-split ring buffers now, 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.
- * @note An xItemSize of 0 will result in a buffer being acquired, but the buffer
- * will have a size of 0.
- *
- * @return
- * - pdTRUE if succeeded
- * - pdFALSE on time-out or when the data is larger than the maximum permissible size of the buffer
- */
- BaseType_t xRingbufferSendAcquire(RingbufHandle_t xRingbuffer, void **ppvItem, size_t xItemSize, TickType_t xTicksToWait);
- /**
- * @brief Actually send an item into the ring buffer allocated before by
- * ``xRingbufferSendAcquire``.
- *
- * @param[in] xRingbuffer Ring buffer to insert the item into
- * @param[in] pvItem Pointer to item in allocated memory to insert.
- *
- * @note Only applicable for no-split ring buffers. Only call for items
- * allocated by ``xRingbufferSendAcquire``.
- *
- * @return
- * - pdTRUE if succeeded
- * - pdFALSE if fail for some reason.
- */
- BaseType_t xRingbufferSendComplete(RingbufHandle_t xRingbuffer, void *pvItem);
- /**
- * @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 times out.
- *
- * @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.
- * @note It is possible to receive items with a pxItemSize of 0 on no-split/allow split buffers.
- *
- * @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
- * @note Two calls to RingbufferReceiveFromISR() are required if the bytes wrap around the end of the ring buffer.
- * @note It is possible to receive items with a pxItemSize of 0 on no-split/allow split buffers.
- *
- * @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 times out.
- *
- * @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
- * @note It is possible to receive items with a pxItemSize of 0 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
- * @note It is possible to receive items with a pxItemSize of 0 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 times out.
- *
- * @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
- * @note Two calls to RingbufferReceiveUpTo() are required if the bytes wrap around the end of the ring buffer.
- *
- * @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. Size of 0 simply returns NULL.
- *
- * @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
- *
- * @note This function will not deallocate any memory if the ring buffer was
- * created using xRingbufferCreateStatic(). Deallocation must be done
- * manually be the user.
- */
- 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
- *
- * @note The max item size for a no-split buffer is limited to
- * ((buffer_size/2)-header_size). This limit is imposed so that an item
- * of max item size can always be sent to an empty no-split buffer
- * regardless of the internal positions of the buffer's read/write/free
- * pointers.
- *
- * @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
- *
- * @note An empty no-split buffer has a max current free size for an item
- * that is limited to ((buffer_size/2)-header_size). See API reference
- * for xRingbufferGetMaxItemSize().
- *
- * @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 to a queue set. Notified when data has been written to the ring buffer
- *
- * This function adds the ring buffer to a queue set, thus allowing a task to
- * block on multiple queues/ring buffers. The queue set is notified when the new
- * data becomes available to read on the ring buffer.
- *
- * @param[in] xRingbuffer Ring buffer to add to the queue set
- * @param[in] xQueueSet Queue set to add the ring buffer 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 a particular ring buffer
- *
- * This API checks if queue set member returned from xQueueSelectFromSet() is
- * a particular ring buffer. If so, this indicates the ring buffer has items
- * waiting to be retrieved.
- *
- * @param[in] xRingbuffer Ring buffer to check
- * @param[in] xMember Member returned from xQueueSelectFromSet
- *
- * @return
- * - pdTRUE when selected queue set member is the ring buffer
- * - pdFALSE otherwise.
- */
- static inline BaseType_t xRingbufferCanRead(RingbufHandle_t xRingbuffer, QueueSetMemberHandle_t xMember)
- {
- return (xMember == (QueueSetMemberHandle_t)xRingbuffer) ? pdTRUE : pdFALSE;
- }
- /**
- * @brief Remove the ring buffer from a queue set
- *
- * This function removes a ring buffer from a queue set. The ring buffer must have been previously added to the queue
- * set using xRingbufferAddToQueueSetRead().
- *
- * @param[in] xRingbuffer Ring buffer to remove from the queue set
- * @param[in] xQueueSet Queue set to remove the ring buffer 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 a ring buffer's current status such as
- * free/read/write/acquire 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] uxAcquire Pointer use to store acquire 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 *uxAcquire,
- 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);
- /**
- * @brief Retrieve the pointers to a statically created ring buffer
- *
- * @param[in] xRingbuffer Ring buffer
- * @param[out] ppucRingbufferStorage Used to return a pointer to the queue's storage area buffer
- * @param[out] ppxStaticRingbuffer Used to return a pointer to the queue's data structure buffer
- * @return pdTRUE if buffers were retrieved, pdFALSE otherwise.
- */
- BaseType_t xRingbufferGetStaticBuffer(RingbufHandle_t xRingbuffer, uint8_t **ppucRingbufferStorage, StaticRingbuffer_t **ppxStaticRingbuffer);
- /**
- * @brief Creates a ring buffer with specific memory capabilities
- *
- * This function is similar to xRingbufferCreate(), except that it allows the
- * memory allocated for the ring buffer to have specific capabilities (e.g.,
- * MALLOC_CAP_INTERNAL).
- *
- * @note A queue created using this function must only be deleted using
- * vRingbufferDeleteWithCaps()
- * @param[in] xBufferSize Size of the buffer in bytes
- * @param[in] xBufferType Type of ring buffer, see documentation.
- * @param[in] uxMemoryCaps Memory capabilities of the queue's memory (see
- * esp_heap_caps.h)
- * @return Handle to the created ring buffer or NULL on failure.
- */
- RingbufHandle_t xRingbufferCreateWithCaps(size_t xBufferSize, RingbufferType_t xBufferType, UBaseType_t uxMemoryCaps);
- /**
- * @brief Deletes a ring buffer previously created using xRingbufferCreateWithCaps()
- *
- * @param xRingbuffer Ring buffer
- */
- void vRingbufferDeleteWithCaps(RingbufHandle_t xRingbuffer);
- #ifdef __cplusplus
- }
- #endif
|