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