ringbuf.h 22 KB

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