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