1 /* 2 * FreeRTOS Kernel V10.6.2 3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 * this software and associated documentation files (the "Software"), to deal in 9 * the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 * the Software, and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * https://www.FreeRTOS.org 25 * https://github.com/FreeRTOS 26 * 27 */ 28 29 /* 30 * Stream buffers are used to send a continuous stream of data from one task or 31 * interrupt to another. Their implementation is light weight, making them 32 * particularly suited for interrupt to task and core to core communication 33 * scenarios. 34 * 35 * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer 36 * implementation (so also the message buffer implementation, as message buffers 37 * are built on top of stream buffers) assumes there is only one task or 38 * interrupt that will write to the buffer (the writer), and only one task or 39 * interrupt that will read from the buffer (the reader). It is safe for the 40 * writer and reader to be different tasks or interrupts, but, unlike other 41 * FreeRTOS objects, it is not safe to have multiple different writers or 42 * multiple different readers. If there are to be multiple different writers 43 * then the application writer must place each call to a writing API function 44 * (such as xStreamBufferSend()) inside a critical section and set the send 45 * block time to 0. Likewise, if there are to be multiple different readers 46 * then the application writer must place each call to a reading API function 47 * (such as xStreamBufferReceive()) inside a critical section section and set the 48 * receive block time to 0. 49 * 50 */ 51 52 #ifndef STREAM_BUFFER_H 53 #define STREAM_BUFFER_H 54 55 #ifndef INC_FREERTOS_H 56 #error "include FreeRTOS.h must appear in source files before include stream_buffer.h" 57 #endif 58 59 /* *INDENT-OFF* */ 60 #if defined( __cplusplus ) 61 extern "C" { 62 #endif 63 /* *INDENT-ON* */ 64 65 /** 66 * Type by which stream buffers are referenced. For example, a call to 67 * xStreamBufferCreate() returns an StreamBufferHandle_t variable that can 68 * then be used as a parameter to xStreamBufferSend(), xStreamBufferReceive(), 69 * etc. 70 */ 71 struct StreamBufferDef_t; 72 typedef struct StreamBufferDef_t * StreamBufferHandle_t; 73 74 /** 75 * Type used as a stream buffer's optional callback. 76 */ 77 typedef void (* StreamBufferCallbackFunction_t)( StreamBufferHandle_t xStreamBuffer, 78 BaseType_t xIsInsideISR, 79 BaseType_t * const pxHigherPriorityTaskWoken ); 80 81 /** 82 * stream_buffer.h 83 * 84 * @code{c} 85 * StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes ); 86 * @endcode 87 * 88 * Creates a new stream buffer using dynamically allocated memory. See 89 * xStreamBufferCreateStatic() for a version that uses statically allocated 90 * memory (memory that is allocated at compile time). 91 * 92 * configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in 93 * FreeRTOSConfig.h for xStreamBufferCreate() to be available. 94 * 95 * @param xBufferSizeBytes The total number of bytes the stream buffer will be 96 * able to hold at any one time. 97 * 98 * @param xTriggerLevelBytes The number of bytes that must be in the stream 99 * buffer before a task that is blocked on the stream buffer to wait for data is 100 * moved out of the blocked state. For example, if a task is blocked on a read 101 * of an empty stream buffer that has a trigger level of 1 then the task will be 102 * unblocked when a single byte is written to the buffer or the task's block 103 * time expires. As another example, if a task is blocked on a read of an empty 104 * stream buffer that has a trigger level of 10 then the task will not be 105 * unblocked until the stream buffer contains at least 10 bytes or the task's 106 * block time expires. If a reading task's block time expires before the 107 * trigger level is reached then the task will still receive however many bytes 108 * are actually available. Setting a trigger level of 0 will result in a 109 * trigger level of 1 being used. It is not valid to specify a trigger level 110 * that is greater than the buffer size. 111 * 112 * @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to 113 * trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default 114 * implementation provided by sbSEND_COMPLETED macro. To enable the callback, 115 * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. 116 * 117 * @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a 118 * stream buffer. If the parameter is NULL, it will use the default 119 * implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback, 120 * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. 121 * 122 * @return If NULL is returned, then the stream buffer cannot be created 123 * because there is insufficient heap memory available for FreeRTOS to allocate 124 * the stream buffer data structures and storage area. A non-NULL value being 125 * returned indicates that the stream buffer has been created successfully - 126 * the returned value should be stored as the handle to the created stream 127 * buffer. 128 * 129 * Example use: 130 * @code{c} 131 * 132 * void vAFunction( void ) 133 * { 134 * StreamBufferHandle_t xStreamBuffer; 135 * const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10; 136 * 137 * // Create a stream buffer that can hold 100 bytes. The memory used to hold 138 * // both the stream buffer structure and the data in the stream buffer is 139 * // allocated dynamically. 140 * xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel ); 141 * 142 * if( xStreamBuffer == NULL ) 143 * { 144 * // There was not enough heap memory space available to create the 145 * // stream buffer. 146 * } 147 * else 148 * { 149 * // The stream buffer was created successfully and can now be used. 150 * } 151 * } 152 * @endcode 153 * \defgroup xStreamBufferCreate xStreamBufferCreate 154 * \ingroup StreamBufferManagement 155 */ 156 157 #define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) \ 158 xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, NULL, NULL ) 159 160 #if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) 161 #define xStreamBufferCreateWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \ 162 xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) ) 163 #endif 164 165 /** 166 * stream_buffer.h 167 * 168 * @code{c} 169 * StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes, 170 * size_t xTriggerLevelBytes, 171 * uint8_t *pucStreamBufferStorageArea, 172 * StaticStreamBuffer_t *pxStaticStreamBuffer ); 173 * @endcode 174 * Creates a new stream buffer using statically allocated memory. See 175 * xStreamBufferCreate() for a version that uses dynamically allocated memory. 176 * 177 * configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h for 178 * xStreamBufferCreateStatic() to be available. 179 * 180 * @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the 181 * pucStreamBufferStorageArea parameter. 182 * 183 * @param xTriggerLevelBytes The number of bytes that must be in the stream 184 * buffer before a task that is blocked on the stream buffer to wait for data is 185 * moved out of the blocked state. For example, if a task is blocked on a read 186 * of an empty stream buffer that has a trigger level of 1 then the task will be 187 * unblocked when a single byte is written to the buffer or the task's block 188 * time expires. As another example, if a task is blocked on a read of an empty 189 * stream buffer that has a trigger level of 10 then the task will not be 190 * unblocked until the stream buffer contains at least 10 bytes or the task's 191 * block time expires. If a reading task's block time expires before the 192 * trigger level is reached then the task will still receive however many bytes 193 * are actually available. Setting a trigger level of 0 will result in a 194 * trigger level of 1 being used. It is not valid to specify a trigger level 195 * that is greater than the buffer size. 196 * 197 * @param pucStreamBufferStorageArea Must point to a uint8_t array that is at 198 * least xBufferSizeBytes big. This is the array to which streams are 199 * copied when they are written to the stream buffer. 200 * 201 * @param pxStaticStreamBuffer Must point to a variable of type 202 * StaticStreamBuffer_t, which will be used to hold the stream buffer's data 203 * structure. 204 * 205 * @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to 206 * trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default 207 * implementation provided by sbSEND_COMPLETED macro. To enable the callback, 208 * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. 209 * 210 * @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a 211 * stream buffer. If the parameter is NULL, it will use the default 212 * implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback, 213 * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h. 214 * 215 * @return If the stream buffer is created successfully then a handle to the 216 * created stream buffer is returned. If either pucStreamBufferStorageArea or 217 * pxStaticstreamBuffer are NULL then NULL is returned. 218 * 219 * Example use: 220 * @code{c} 221 * 222 * // Used to dimension the array used to hold the streams. The available space 223 * // will actually be one less than this, so 999. 224 #define STORAGE_SIZE_BYTES 1000 225 * 226 * // Defines the memory that will actually hold the streams within the stream 227 * // buffer. 228 * static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ]; 229 * 230 * // The variable used to hold the stream buffer structure. 231 * StaticStreamBuffer_t xStreamBufferStruct; 232 * 233 * void MyFunction( void ) 234 * { 235 * StreamBufferHandle_t xStreamBuffer; 236 * const size_t xTriggerLevel = 1; 237 * 238 * xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStorageBuffer ), 239 * xTriggerLevel, 240 * ucStorageBuffer, 241 * &xStreamBufferStruct ); 242 * 243 * // As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer 244 * // parameters were NULL, xStreamBuffer will not be NULL, and can be used to 245 * // reference the created stream buffer in other stream buffer API calls. 246 * 247 * // Other code that uses the stream buffer can go here. 248 * } 249 * 250 * @endcode 251 * \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic 252 * \ingroup StreamBufferManagement 253 */ 254 255 #define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \ 256 xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pucStreamBufferStorageArea ), ( pxStaticStreamBuffer ), NULL, NULL ) 257 258 #if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) 259 #define xStreamBufferCreateStaticWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \ 260 xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pucStreamBufferStorageArea ), ( pxStaticStreamBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) ) 261 #endif 262 263 /** 264 * stream_buffer.h 265 * 266 * @code{c} 267 * BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer, 268 * uint8_t ** ppucStreamBufferStorageArea, 269 * StaticStreamBuffer_t ** ppxStaticStreamBuffer ); 270 * @endcode 271 * 272 * Retrieve pointers to a statically created stream buffer's data structure 273 * buffer and storage area buffer. These are the same buffers that are supplied 274 * at the time of creation. 275 * 276 * @param xStreamBuffer The stream buffer for which to retrieve the buffers. 277 * 278 * @param ppucStreamBufferStorageArea Used to return a pointer to the stream 279 * buffer's storage area buffer. 280 * 281 * @param ppxStaticStreamBuffer Used to return a pointer to the stream 282 * buffer's data structure buffer. 283 * 284 * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. 285 * 286 * \defgroup xStreamBufferGetStaticBuffers xStreamBufferGetStaticBuffers 287 * \ingroup StreamBufferManagement 288 */ 289 #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 290 BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer, 291 uint8_t ** ppucStreamBufferStorageArea, 292 StaticStreamBuffer_t ** ppxStaticStreamBuffer ) PRIVILEGED_FUNCTION; 293 #endif /* configSUPPORT_STATIC_ALLOCATION */ 294 295 /** 296 * stream_buffer.h 297 * 298 * @code{c} 299 * size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, 300 * const void *pvTxData, 301 * size_t xDataLengthBytes, 302 * TickType_t xTicksToWait ); 303 * @endcode 304 * 305 * Sends bytes to a stream buffer. The bytes are copied into the stream buffer. 306 * 307 * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer 308 * implementation (so also the message buffer implementation, as message buffers 309 * are built on top of stream buffers) assumes there is only one task or 310 * interrupt that will write to the buffer (the writer), and only one task or 311 * interrupt that will read from the buffer (the reader). It is safe for the 312 * writer and reader to be different tasks or interrupts, but, unlike other 313 * FreeRTOS objects, it is not safe to have multiple different writers or 314 * multiple different readers. If there are to be multiple different writers 315 * then the application writer must place each call to a writing API function 316 * (such as xStreamBufferSend()) inside a critical section and set the send 317 * block time to 0. Likewise, if there are to be multiple different readers 318 * then the application writer must place each call to a reading API function 319 * (such as xStreamBufferReceive()) inside a critical section and set the receive 320 * block time to 0. 321 * 322 * Use xStreamBufferSend() to write to a stream buffer from a task. Use 323 * xStreamBufferSendFromISR() to write to a stream buffer from an interrupt 324 * service routine (ISR). 325 * 326 * @param xStreamBuffer The handle of the stream buffer to which a stream is 327 * being sent. 328 * 329 * @param pvTxData A pointer to the buffer that holds the bytes to be copied 330 * into the stream buffer. 331 * 332 * @param xDataLengthBytes The maximum number of bytes to copy from pvTxData 333 * into the stream buffer. 334 * 335 * @param xTicksToWait The maximum amount of time the task should remain in the 336 * Blocked state to wait for enough space to become available in the stream 337 * buffer, should the stream buffer contain too little space to hold the 338 * another xDataLengthBytes bytes. The block time is specified in tick periods, 339 * so the absolute time it represents is dependent on the tick frequency. The 340 * macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds 341 * into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will 342 * cause the task to wait indefinitely (without timing out), provided 343 * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. If a task times out 344 * before it can write all xDataLengthBytes into the buffer it will still write 345 * as many bytes as possible. A task does not use any CPU time when it is in 346 * the blocked state. 347 * 348 * @return The number of bytes written to the stream buffer. If a task times 349 * out before it can write all xDataLengthBytes into the buffer it will still 350 * write as many bytes as possible. 351 * 352 * Example use: 353 * @code{c} 354 * void vAFunction( StreamBufferHandle_t xStreamBuffer ) 355 * { 356 * size_t xBytesSent; 357 * uint8_t ucArrayToSend[] = { 0, 1, 2, 3 }; 358 * char *pcStringToSend = "String to send"; 359 * const TickType_t x100ms = pdMS_TO_TICKS( 100 ); 360 * 361 * // Send an array to the stream buffer, blocking for a maximum of 100ms to 362 * // wait for enough space to be available in the stream buffer. 363 * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms ); 364 * 365 * if( xBytesSent != sizeof( ucArrayToSend ) ) 366 * { 367 * // The call to xStreamBufferSend() times out before there was enough 368 * // space in the buffer for the data to be written, but it did 369 * // successfully write xBytesSent bytes. 370 * } 371 * 372 * // Send the string to the stream buffer. Return immediately if there is not 373 * // enough space in the buffer. 374 * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 ); 375 * 376 * if( xBytesSent != strlen( pcStringToSend ) ) 377 * { 378 * // The entire string could not be added to the stream buffer because 379 * // there was not enough free space in the buffer, but xBytesSent bytes 380 * // were sent. Could try again to send the remaining bytes. 381 * } 382 * } 383 * @endcode 384 * \defgroup xStreamBufferSend xStreamBufferSend 385 * \ingroup StreamBufferManagement 386 */ 387 size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, 388 const void * pvTxData, 389 size_t xDataLengthBytes, 390 TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; 391 392 /** 393 * stream_buffer.h 394 * 395 * @code{c} 396 * size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, 397 * const void *pvTxData, 398 * size_t xDataLengthBytes, 399 * BaseType_t *pxHigherPriorityTaskWoken ); 400 * @endcode 401 * 402 * Interrupt safe version of the API function that sends a stream of bytes to 403 * the stream buffer. 404 * 405 * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer 406 * implementation (so also the message buffer implementation, as message buffers 407 * are built on top of stream buffers) assumes there is only one task or 408 * interrupt that will write to the buffer (the writer), and only one task or 409 * interrupt that will read from the buffer (the reader). It is safe for the 410 * writer and reader to be different tasks or interrupts, but, unlike other 411 * FreeRTOS objects, it is not safe to have multiple different writers or 412 * multiple different readers. If there are to be multiple different writers 413 * then the application writer must place each call to a writing API function 414 * (such as xStreamBufferSend()) inside a critical section and set the send 415 * block time to 0. Likewise, if there are to be multiple different readers 416 * then the application writer must place each call to a reading API function 417 * (such as xStreamBufferReceive()) inside a critical section and set the receive 418 * block time to 0. 419 * 420 * Use xStreamBufferSend() to write to a stream buffer from a task. Use 421 * xStreamBufferSendFromISR() to write to a stream buffer from an interrupt 422 * service routine (ISR). 423 * 424 * @param xStreamBuffer The handle of the stream buffer to which a stream is 425 * being sent. 426 * 427 * @param pvTxData A pointer to the data that is to be copied into the stream 428 * buffer. 429 * 430 * @param xDataLengthBytes The maximum number of bytes to copy from pvTxData 431 * into the stream buffer. 432 * 433 * @param pxHigherPriorityTaskWoken It is possible that a stream buffer will 434 * have a task blocked on it waiting for data. Calling 435 * xStreamBufferSendFromISR() can make data available, and so cause a task that 436 * was waiting for data to leave the Blocked state. If calling 437 * xStreamBufferSendFromISR() causes a task to leave the Blocked state, and the 438 * unblocked task has a priority higher than the currently executing task (the 439 * task that was interrupted), then, internally, xStreamBufferSendFromISR() 440 * will set *pxHigherPriorityTaskWoken to pdTRUE. If 441 * xStreamBufferSendFromISR() sets this value to pdTRUE, then normally a 442 * context switch should be performed before the interrupt is exited. This will 443 * ensure that the interrupt returns directly to the highest priority Ready 444 * state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it 445 * is passed into the function. See the example code below for an example. 446 * 447 * @return The number of bytes actually written to the stream buffer, which will 448 * be less than xDataLengthBytes if the stream buffer didn't have enough free 449 * space for all the bytes to be written. 450 * 451 * Example use: 452 * @code{c} 453 * // A stream buffer that has already been created. 454 * StreamBufferHandle_t xStreamBuffer; 455 * 456 * void vAnInterruptServiceRoutine( void ) 457 * { 458 * size_t xBytesSent; 459 * char *pcStringToSend = "String to send"; 460 * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. 461 * 462 * // Attempt to send the string to the stream buffer. 463 * xBytesSent = xStreamBufferSendFromISR( xStreamBuffer, 464 * ( void * ) pcStringToSend, 465 * strlen( pcStringToSend ), 466 * &xHigherPriorityTaskWoken ); 467 * 468 * if( xBytesSent != strlen( pcStringToSend ) ) 469 * { 470 * // There was not enough free space in the stream buffer for the entire 471 * // string to be written, ut xBytesSent bytes were written. 472 * } 473 * 474 * // If xHigherPriorityTaskWoken was set to pdTRUE inside 475 * // xStreamBufferSendFromISR() then a task that has a priority above the 476 * // priority of the currently executing task was unblocked and a context 477 * // switch should be performed to ensure the ISR returns to the unblocked 478 * // task. In most FreeRTOS ports this is done by simply passing 479 * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the 480 * // variables value, and perform the context switch if necessary. Check the 481 * // documentation for the port in use for port specific instructions. 482 * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); 483 * } 484 * @endcode 485 * \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR 486 * \ingroup StreamBufferManagement 487 */ 488 size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, 489 const void * pvTxData, 490 size_t xDataLengthBytes, 491 BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; 492 493 /** 494 * stream_buffer.h 495 * 496 * @code{c} 497 * size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, 498 * void *pvRxData, 499 * size_t xBufferLengthBytes, 500 * TickType_t xTicksToWait ); 501 * @endcode 502 * 503 * Receives bytes from a stream buffer. 504 * 505 * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer 506 * implementation (so also the message buffer implementation, as message buffers 507 * are built on top of stream buffers) assumes there is only one task or 508 * interrupt that will write to the buffer (the writer), and only one task or 509 * interrupt that will read from the buffer (the reader). It is safe for the 510 * writer and reader to be different tasks or interrupts, but, unlike other 511 * FreeRTOS objects, it is not safe to have multiple different writers or 512 * multiple different readers. If there are to be multiple different writers 513 * then the application writer must place each call to a writing API function 514 * (such as xStreamBufferSend()) inside a critical section and set the send 515 * block time to 0. Likewise, if there are to be multiple different readers 516 * then the application writer must place each call to a reading API function 517 * (such as xStreamBufferReceive()) inside a critical section and set the receive 518 * block time to 0. 519 * 520 * Use xStreamBufferReceive() to read from a stream buffer from a task. Use 521 * xStreamBufferReceiveFromISR() to read from a stream buffer from an 522 * interrupt service routine (ISR). 523 * 524 * @param xStreamBuffer The handle of the stream buffer from which bytes are to 525 * be received. 526 * 527 * @param pvRxData A pointer to the buffer into which the received bytes will be 528 * copied. 529 * 530 * @param xBufferLengthBytes The length of the buffer pointed to by the 531 * pvRxData parameter. This sets the maximum number of bytes to receive in one 532 * call. xStreamBufferReceive will return as many bytes as possible up to a 533 * maximum set by xBufferLengthBytes. 534 * 535 * @param xTicksToWait The maximum amount of time the task should remain in the 536 * Blocked state to wait for data to become available if the stream buffer is 537 * empty. xStreamBufferReceive() will return immediately if xTicksToWait is 538 * zero. The block time is specified in tick periods, so the absolute time it 539 * represents is dependent on the tick frequency. The macro pdMS_TO_TICKS() can 540 * be used to convert a time specified in milliseconds into a time specified in 541 * ticks. Setting xTicksToWait to portMAX_DELAY will cause the task to wait 542 * indefinitely (without timing out), provided INCLUDE_vTaskSuspend is set to 1 543 * in FreeRTOSConfig.h. A task does not use any CPU time when it is in the 544 * Blocked state. 545 * 546 * @return The number of bytes actually read from the stream buffer, which will 547 * be less than xBufferLengthBytes if the call to xStreamBufferReceive() timed 548 * out before xBufferLengthBytes were available. 549 * 550 * Example use: 551 * @code{c} 552 * void vAFunction( StreamBuffer_t xStreamBuffer ) 553 * { 554 * uint8_t ucRxData[ 20 ]; 555 * size_t xReceivedBytes; 556 * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 ); 557 * 558 * // Receive up to another sizeof( ucRxData ) bytes from the stream buffer. 559 * // Wait in the Blocked state (so not using any CPU processing time) for a 560 * // maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be 561 * // available. 562 * xReceivedBytes = xStreamBufferReceive( xStreamBuffer, 563 * ( void * ) ucRxData, 564 * sizeof( ucRxData ), 565 * xBlockTime ); 566 * 567 * if( xReceivedBytes > 0 ) 568 * { 569 * // A ucRxData contains another xReceivedBytes bytes of data, which can 570 * // be processed here.... 571 * } 572 * } 573 * @endcode 574 * \defgroup xStreamBufferReceive xStreamBufferReceive 575 * \ingroup StreamBufferManagement 576 */ 577 size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, 578 void * pvRxData, 579 size_t xBufferLengthBytes, 580 TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; 581 582 /** 583 * stream_buffer.h 584 * 585 * @code{c} 586 * size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, 587 * void *pvRxData, 588 * size_t xBufferLengthBytes, 589 * BaseType_t *pxHigherPriorityTaskWoken ); 590 * @endcode 591 * 592 * An interrupt safe version of the API function that receives bytes from a 593 * stream buffer. 594 * 595 * Use xStreamBufferReceive() to read bytes from a stream buffer from a task. 596 * Use xStreamBufferReceiveFromISR() to read bytes from a stream buffer from an 597 * interrupt service routine (ISR). 598 * 599 * @param xStreamBuffer The handle of the stream buffer from which a stream 600 * is being received. 601 * 602 * @param pvRxData A pointer to the buffer into which the received bytes are 603 * copied. 604 * 605 * @param xBufferLengthBytes The length of the buffer pointed to by the 606 * pvRxData parameter. This sets the maximum number of bytes to receive in one 607 * call. xStreamBufferReceive will return as many bytes as possible up to a 608 * maximum set by xBufferLengthBytes. 609 * 610 * @param pxHigherPriorityTaskWoken It is possible that a stream buffer will 611 * have a task blocked on it waiting for space to become available. Calling 612 * xStreamBufferReceiveFromISR() can make space available, and so cause a task 613 * that is waiting for space to leave the Blocked state. If calling 614 * xStreamBufferReceiveFromISR() causes a task to leave the Blocked state, and 615 * the unblocked task has a priority higher than the currently executing task 616 * (the task that was interrupted), then, internally, 617 * xStreamBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE. 618 * If xStreamBufferReceiveFromISR() sets this value to pdTRUE, then normally a 619 * context switch should be performed before the interrupt is exited. That will 620 * ensure the interrupt returns directly to the highest priority Ready state 621 * task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is 622 * passed into the function. See the code example below for an example. 623 * 624 * @return The number of bytes read from the stream buffer, if any. 625 * 626 * Example use: 627 * @code{c} 628 * // A stream buffer that has already been created. 629 * StreamBuffer_t xStreamBuffer; 630 * 631 * void vAnInterruptServiceRoutine( void ) 632 * { 633 * uint8_t ucRxData[ 20 ]; 634 * size_t xReceivedBytes; 635 * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. 636 * 637 * // Receive the next stream from the stream buffer. 638 * xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer, 639 * ( void * ) ucRxData, 640 * sizeof( ucRxData ), 641 * &xHigherPriorityTaskWoken ); 642 * 643 * if( xReceivedBytes > 0 ) 644 * { 645 * // ucRxData contains xReceivedBytes read from the stream buffer. 646 * // Process the stream here.... 647 * } 648 * 649 * // If xHigherPriorityTaskWoken was set to pdTRUE inside 650 * // xStreamBufferReceiveFromISR() then a task that has a priority above the 651 * // priority of the currently executing task was unblocked and a context 652 * // switch should be performed to ensure the ISR returns to the unblocked 653 * // task. In most FreeRTOS ports this is done by simply passing 654 * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the 655 * // variables value, and perform the context switch if necessary. Check the 656 * // documentation for the port in use for port specific instructions. 657 * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); 658 * } 659 * @endcode 660 * \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR 661 * \ingroup StreamBufferManagement 662 */ 663 size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, 664 void * pvRxData, 665 size_t xBufferLengthBytes, 666 BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; 667 668 /** 669 * stream_buffer.h 670 * 671 * @code{c} 672 * void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ); 673 * @endcode 674 * 675 * Deletes a stream buffer that was previously created using a call to 676 * xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream 677 * buffer was created using dynamic memory (that is, by xStreamBufferCreate()), 678 * then the allocated memory is freed. 679 * 680 * A stream buffer handle must not be used after the stream buffer has been 681 * deleted. 682 * 683 * @param xStreamBuffer The handle of the stream buffer to be deleted. 684 * 685 * \defgroup vStreamBufferDelete vStreamBufferDelete 686 * \ingroup StreamBufferManagement 687 */ 688 void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 689 690 /** 691 * stream_buffer.h 692 * 693 * @code{c} 694 * BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ); 695 * @endcode 696 * 697 * Queries a stream buffer to see if it is full. A stream buffer is full if it 698 * does not have any free space, and therefore cannot accept any more data. 699 * 700 * @param xStreamBuffer The handle of the stream buffer being queried. 701 * 702 * @return If the stream buffer is full then pdTRUE is returned. Otherwise 703 * pdFALSE is returned. 704 * 705 * \defgroup xStreamBufferIsFull xStreamBufferIsFull 706 * \ingroup StreamBufferManagement 707 */ 708 BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 709 710 /** 711 * stream_buffer.h 712 * 713 * @code{c} 714 * BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ); 715 * @endcode 716 * 717 * Queries a stream buffer to see if it is empty. A stream buffer is empty if 718 * it does not contain any data. 719 * 720 * @param xStreamBuffer The handle of the stream buffer being queried. 721 * 722 * @return If the stream buffer is empty then pdTRUE is returned. Otherwise 723 * pdFALSE is returned. 724 * 725 * \defgroup xStreamBufferIsEmpty xStreamBufferIsEmpty 726 * \ingroup StreamBufferManagement 727 */ 728 BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 729 730 /** 731 * stream_buffer.h 732 * 733 * @code{c} 734 * BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ); 735 * @endcode 736 * 737 * Resets a stream buffer to its initial, empty, state. Any data that was in 738 * the stream buffer is discarded. A stream buffer can only be reset if there 739 * are no tasks blocked waiting to either send to or receive from the stream 740 * buffer. 741 * 742 * @param xStreamBuffer The handle of the stream buffer being reset. 743 * 744 * @return If the stream buffer is reset then pdPASS is returned. If there was 745 * a task blocked waiting to send to or read from the stream buffer then the 746 * stream buffer is not reset and pdFAIL is returned. 747 * 748 * \defgroup xStreamBufferReset xStreamBufferReset 749 * \ingroup StreamBufferManagement 750 */ 751 BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 752 753 /** 754 * stream_buffer.h 755 * 756 * @code{c} 757 * size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ); 758 * @endcode 759 * 760 * Queries a stream buffer to see how much free space it contains, which is 761 * equal to the amount of data that can be sent to the stream buffer before it 762 * is full. 763 * 764 * @param xStreamBuffer The handle of the stream buffer being queried. 765 * 766 * @return The number of bytes that can be written to the stream buffer before 767 * the stream buffer would be full. 768 * 769 * \defgroup xStreamBufferSpacesAvailable xStreamBufferSpacesAvailable 770 * \ingroup StreamBufferManagement 771 */ 772 size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 773 774 /** 775 * stream_buffer.h 776 * 777 * @code{c} 778 * size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ); 779 * @endcode 780 * 781 * Queries a stream buffer to see how much data it contains, which is equal to 782 * the number of bytes that can be read from the stream buffer before the stream 783 * buffer would be empty. 784 * 785 * @param xStreamBuffer The handle of the stream buffer being queried. 786 * 787 * @return The number of bytes that can be read from the stream buffer before 788 * the stream buffer would be empty. 789 * 790 * \defgroup xStreamBufferBytesAvailable xStreamBufferBytesAvailable 791 * \ingroup StreamBufferManagement 792 */ 793 size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 794 795 /** 796 * stream_buffer.h 797 * 798 * @code{c} 799 * BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ); 800 * @endcode 801 * 802 * A stream buffer's trigger level is the number of bytes that must be in the 803 * stream buffer before a task that is blocked on the stream buffer to 804 * wait for data is moved out of the blocked state. For example, if a task is 805 * blocked on a read of an empty stream buffer that has a trigger level of 1 806 * then the task will be unblocked when a single byte is written to the buffer 807 * or the task's block time expires. As another example, if a task is blocked 808 * on a read of an empty stream buffer that has a trigger level of 10 then the 809 * task will not be unblocked until the stream buffer contains at least 10 bytes 810 * or the task's block time expires. If a reading task's block time expires 811 * before the trigger level is reached then the task will still receive however 812 * many bytes are actually available. Setting a trigger level of 0 will result 813 * in a trigger level of 1 being used. It is not valid to specify a trigger 814 * level that is greater than the buffer size. 815 * 816 * A trigger level is set when the stream buffer is created, and can be modified 817 * using xStreamBufferSetTriggerLevel(). 818 * 819 * @param xStreamBuffer The handle of the stream buffer being updated. 820 * 821 * @param xTriggerLevel The new trigger level for the stream buffer. 822 * 823 * @return If xTriggerLevel was less than or equal to the stream buffer's length 824 * then the trigger level will be updated and pdTRUE is returned. Otherwise 825 * pdFALSE is returned. 826 * 827 * \defgroup xStreamBufferSetTriggerLevel xStreamBufferSetTriggerLevel 828 * \ingroup StreamBufferManagement 829 */ 830 BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, 831 size_t xTriggerLevel ) PRIVILEGED_FUNCTION; 832 833 /** 834 * stream_buffer.h 835 * 836 * @code{c} 837 * BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); 838 * @endcode 839 * 840 * For advanced users only. 841 * 842 * The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when 843 * data is sent to a message buffer or stream buffer. If there was a task that 844 * was blocked on the message or stream buffer waiting for data to arrive then 845 * the sbSEND_COMPLETED() macro sends a notification to the task to remove it 846 * from the Blocked state. xStreamBufferSendCompletedFromISR() does the same 847 * thing. It is provided to enable application writers to implement their own 848 * version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME. 849 * 850 * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for 851 * additional information. 852 * 853 * @param xStreamBuffer The handle of the stream buffer to which data was 854 * written. 855 * 856 * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be 857 * initialised to pdFALSE before it is passed into 858 * xStreamBufferSendCompletedFromISR(). If calling 859 * xStreamBufferSendCompletedFromISR() removes a task from the Blocked state, 860 * and the task has a priority above the priority of the currently running task, 861 * then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a 862 * context switch should be performed before exiting the ISR. 863 * 864 * @return If a task was removed from the Blocked state then pdTRUE is returned. 865 * Otherwise pdFALSE is returned. 866 * 867 * \defgroup xStreamBufferSendCompletedFromISR xStreamBufferSendCompletedFromISR 868 * \ingroup StreamBufferManagement 869 */ 870 BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, 871 BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; 872 873 /** 874 * stream_buffer.h 875 * 876 * @code{c} 877 * BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); 878 * @endcode 879 * 880 * For advanced users only. 881 * 882 * The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when 883 * data is read out of a message buffer or stream buffer. If there was a task 884 * that was blocked on the message or stream buffer waiting for data to arrive 885 * then the sbRECEIVE_COMPLETED() macro sends a notification to the task to 886 * remove it from the Blocked state. xStreamBufferReceiveCompletedFromISR() 887 * does the same thing. It is provided to enable application writers to 888 * implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT 889 * ANY OTHER TIME. 890 * 891 * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for 892 * additional information. 893 * 894 * @param xStreamBuffer The handle of the stream buffer from which data was 895 * read. 896 * 897 * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be 898 * initialised to pdFALSE before it is passed into 899 * xStreamBufferReceiveCompletedFromISR(). If calling 900 * xStreamBufferReceiveCompletedFromISR() removes a task from the Blocked state, 901 * and the task has a priority above the priority of the currently running task, 902 * then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a 903 * context switch should be performed before exiting the ISR. 904 * 905 * @return If a task was removed from the Blocked state then pdTRUE is returned. 906 * Otherwise pdFALSE is returned. 907 * 908 * \defgroup xStreamBufferReceiveCompletedFromISR xStreamBufferReceiveCompletedFromISR 909 * \ingroup StreamBufferManagement 910 */ 911 BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, 912 BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; 913 914 /* Functions below here are not part of the public API. */ 915 StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, 916 size_t xTriggerLevelBytes, 917 BaseType_t xIsMessageBuffer, 918 StreamBufferCallbackFunction_t pxSendCompletedCallback, 919 StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; 920 921 922 StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, 923 size_t xTriggerLevelBytes, 924 BaseType_t xIsMessageBuffer, 925 uint8_t * const pucStreamBufferStorageArea, 926 StaticStreamBuffer_t * const pxStaticStreamBuffer, 927 StreamBufferCallbackFunction_t pxSendCompletedCallback, 928 StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; 929 930 size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 931 932 #if ( configUSE_TRACE_FACILITY == 1 ) 933 void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, 934 UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION; 935 UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 936 uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; 937 #endif 938 939 /* *INDENT-OFF* */ 940 #if defined( __cplusplus ) 941 } 942 #endif 943 /* *INDENT-ON* */ 944 945 #endif /* !defined( STREAM_BUFFER_H ) */ 946