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