2 * FreeRTOS Kernel V10.0.1
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
28 /* Standard includes. */
\r
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
33 all the API functions to use the MPU wrappers. That should only be done when
\r
34 task.h is included from an application file. */
\r
35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
37 /* FreeRTOS includes. */
\r
38 #include "FreeRTOS.h"
\r
40 #include "stream_buffer.h"
\r
42 #if( configUSE_TASK_NOTIFICATIONS != 1 )
\r
43 #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c
\r
46 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
\r
47 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
\r
48 header files above, but not in this file, in order to generate the correct
\r
49 privileged Vs unprivileged linkage and placement. */
\r
50 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
\r
52 /* If the user has not provided application specific Rx notification macros,
\r
53 or #defined the notification macros away, them provide default implementations
\r
54 that uses task notifications. */
\r
55 /*lint -save -e9026 Function like macros allowed and needed here so they can be overidden. */
\r
56 #ifndef sbRECEIVE_COMPLETED
\r
57 #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \
\r
58 vTaskSuspendAll(); \
\r
60 if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \
\r
62 ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \
\r
65 ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \
\r
68 ( void ) xTaskResumeAll();
\r
69 #endif /* sbRECEIVE_COMPLETED */
\r
71 #ifndef sbRECEIVE_COMPLETED_FROM_ISR
\r
72 #define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \
\r
73 pxHigherPriorityTaskWoken ) \
\r
75 UBaseType_t uxSavedInterruptStatus; \
\r
77 uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
79 if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \
\r
81 ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, \
\r
84 pxHigherPriorityTaskWoken ); \
\r
85 ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \
\r
88 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
90 #endif /* sbRECEIVE_COMPLETED_FROM_ISR */
\r
92 /* If the user has not provided an application specific Tx notification macro,
\r
93 or #defined the notification macro away, them provide a default implementation
\r
94 that uses task notifications. */
\r
95 #ifndef sbSEND_COMPLETED
\r
96 #define sbSEND_COMPLETED( pxStreamBuffer ) \
\r
97 vTaskSuspendAll(); \
\r
99 if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \
\r
101 ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToReceive, \
\r
104 ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \
\r
107 ( void ) xTaskResumeAll();
\r
108 #endif /* sbSEND_COMPLETED */
\r
110 #ifndef sbSEND_COMPLETE_FROM_ISR
\r
111 #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
\r
113 UBaseType_t uxSavedInterruptStatus; \
\r
115 uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
\r
117 if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \
\r
119 ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, \
\r
122 pxHigherPriorityTaskWoken ); \
\r
123 ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \
\r
126 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
\r
128 #endif /* sbSEND_COMPLETE_FROM_ISR */
\r
129 /*lint -restore (9026) */
\r
131 /* The number of bytes used to hold the length of a message in the buffer. */
\r
132 #define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) )
\r
134 /* Bits stored in the ucFlags field of the stream buffer. */
\r
135 #define sbFLAGS_IS_MESSAGE_BUFFER ( ( uint8_t ) 1 ) /* Set if the stream buffer was created as a message buffer, in which case it holds discrete messages rather than a stream. */
\r
136 #define sbFLAGS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 2 ) /* Set if the stream buffer was created using statically allocated memory. */
\r
138 /*-----------------------------------------------------------*/
\r
140 /* Structure that hold state information on the buffer. */
\r
141 typedef struct xSTREAM_BUFFER /*lint !e9058 Style convention uses tag. */
\r
143 volatile size_t xTail; /* Index to the next item to read within the buffer. */
\r
144 volatile size_t xHead; /* Index to the next item to write within the buffer. */
\r
145 size_t xLength; /* The length of the buffer pointed to by pucBuffer. */
\r
146 size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */
\r
147 volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */
\r
148 volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */
\r
149 uint8_t *pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */
\r
152 #if ( configUSE_TRACE_FACILITY == 1 )
\r
153 UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */
\r
158 * The number of bytes available to be read from the buffer.
\r
160 static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION;
\r
163 * Add xCount bytes from pucData into the pxStreamBuffer message buffer.
\r
164 * Returns the number of bytes written, which will either equal xCount in the
\r
165 * success case, or 0 if there was not enough space in the buffer (in which case
\r
166 * no data is written into the buffer).
\r
168 static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount ) PRIVILEGED_FUNCTION;
\r
171 * If the stream buffer is being used as a message buffer, then reads an entire
\r
172 * message out of the buffer. If the stream buffer is being used as a stream
\r
173 * buffer then read as many bytes as possible from the buffer.
\r
174 * prvReadBytesFromBuffer() is called to actually extract the bytes from the
\r
175 * buffer's data storage area.
\r
177 static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer,
\r
179 size_t xBufferLengthBytes,
\r
180 size_t xBytesAvailable,
\r
181 size_t xBytesToStoreMessageLength ) PRIVILEGED_FUNCTION;
\r
184 * If the stream buffer is being used as a message buffer, then writes an entire
\r
185 * message to the buffer. If the stream buffer is being used as a stream
\r
186 * buffer then write as many bytes as possible to the buffer.
\r
187 * prvWriteBytestoBuffer() is called to actually send the bytes to the buffer's
\r
188 * data storage area.
\r
190 static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
\r
191 const void * pvTxData,
\r
192 size_t xDataLengthBytes,
\r
194 size_t xRequiredSpace ) PRIVILEGED_FUNCTION;
\r
197 * Read xMaxCount bytes from the pxStreamBuffer message buffer and write them
\r
200 static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer,
\r
203 size_t xBytesAvailable ); PRIVILEGED_FUNCTION
\r
206 * Called by both pxStreamBufferCreate() and pxStreamBufferCreateStatic() to
\r
207 * initialise the members of the newly created stream buffer structure.
\r
209 static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
\r
210 uint8_t * const pucBuffer,
\r
211 size_t xBufferSizeBytes,
\r
212 size_t xTriggerLevelBytes,
\r
213 BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION;
\r
215 /*-----------------------------------------------------------*/
\r
217 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
219 StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer )
\r
221 uint8_t *pucAllocatedMemory;
\r
223 /* In case the stream buffer is going to be used as a message buffer
\r
224 (that is, it will hold discrete messages with a little meta data that
\r
225 says how big the next message is) check the buffer will be large enough
\r
226 to hold at least one message. */
\r
227 configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
\r
228 configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
\r
230 /* A trigger level of 0 would cause a waiting task to unblock even when
\r
231 the buffer was empty. */
\r
232 if( xTriggerLevelBytes == ( size_t ) 0 )
\r
234 xTriggerLevelBytes = ( size_t ) 1; /*lint !e9044 Parameter modified to ensure it doesn't have a dangerous value. */
\r
237 /* A stream buffer requires a StreamBuffer_t structure and a buffer.
\r
238 Both are allocated in a single call to pvPortMalloc(). The
\r
239 StreamBuffer_t structure is placed at the start of the allocated memory
\r
240 and the buffer follows immediately after. The requested size is
\r
241 incremented so the free space is returned as the user would expect -
\r
242 this is a quirk of the implementation that means otherwise the free
\r
243 space would be reported as one byte smaller than would be logically
\r
245 xBufferSizeBytes++;
\r
246 pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */
\r
248 if( pucAllocatedMemory != NULL )
\r
250 prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pucAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */
\r
251 pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */
\r
253 xTriggerLevelBytes,
\r
254 xIsMessageBuffer );
\r
256 traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer );
\r
260 traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer );
\r
263 return ( StreamBufferHandle_t * ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */
\r
266 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
267 /*-----------------------------------------------------------*/
\r
269 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
271 StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
\r
272 size_t xTriggerLevelBytes,
\r
273 BaseType_t xIsMessageBuffer,
\r
274 uint8_t * const pucStreamBufferStorageArea,
\r
275 StaticStreamBuffer_t * const pxStaticStreamBuffer )
\r
277 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */
\r
278 StreamBufferHandle_t xReturn;
\r
280 configASSERT( pucStreamBufferStorageArea );
\r
281 configASSERT( pxStaticStreamBuffer );
\r
282 configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
\r
284 /* A trigger level of 0 would cause a waiting task to unblock even when
\r
285 the buffer was empty. */
\r
286 if( xTriggerLevelBytes == ( size_t ) 0 )
\r
288 xTriggerLevelBytes = ( size_t ) 1; /*lint !e9044 Function parameter deliberately modified to ensure it is in range. */
\r
291 /* In case the stream buffer is going to be used as a message buffer
\r
292 (that is, it will hold discrete messages with a little meta data that
\r
293 says how big the next message is) check the buffer will be large enough
\r
294 to hold at least one message. */
\r
295 configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
\r
297 #if( configASSERT_DEFINED == 1 )
\r
299 /* Sanity check that the size of the structure used to declare a
\r
300 variable of type StaticStreamBuffer_t equals the size of the real
\r
301 message buffer structure. */
\r
302 volatile size_t xSize = sizeof( StaticStreamBuffer_t );
\r
303 configASSERT( xSize == sizeof( StreamBuffer_t ) );
\r
305 #endif /* configASSERT_DEFINED */
\r
307 if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) )
\r
309 prvInitialiseNewStreamBuffer( pxStreamBuffer,
\r
310 pucStreamBufferStorageArea,
\r
312 xTriggerLevelBytes,
\r
313 xIsMessageBuffer );
\r
315 /* Remember this was statically allocated in case it is ever deleted
\r
317 pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED;
\r
319 traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer );
\r
321 xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; /*lint !e9087 Data hiding requires cast to opaque type. */
\r
326 traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer );
\r
332 #endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
\r
333 /*-----------------------------------------------------------*/
\r
335 void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer )
\r
337 StreamBuffer_t * pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
339 configASSERT( pxStreamBuffer );
\r
341 traceSTREAM_BUFFER_DELETE( xStreamBuffer );
\r
343 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE )
\r
345 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
347 /* Both the structure and the buffer were allocated using a single call
\r
348 to pvPortMalloc(), hence only one call to vPortFree() is required. */
\r
349 vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */
\r
353 /* Should not be possible to get here, ucFlags must be corrupt.
\r
354 Force an assert. */
\r
355 configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 );
\r
361 /* The structure and buffer were not allocated dynamically and cannot be
\r
362 freed - just scrub the structure so future use will assert. */
\r
363 memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) );
\r
366 /*-----------------------------------------------------------*/
\r
368 BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
\r
370 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
371 BaseType_t xReturn = pdFAIL, xIsMessageBuffer;
\r
373 #if( configUSE_TRACE_FACILITY == 1 )
\r
374 UBaseType_t uxStreamBufferNumber;
\r
377 configASSERT( pxStreamBuffer );
\r
379 #if( configUSE_TRACE_FACILITY == 1 )
\r
381 /* Store the stream buffer number so it can be restored after the
\r
383 uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber;
\r
387 /* Can only reset a message buffer if there are no tasks blocked on it. */
\r
388 if( pxStreamBuffer->xTaskWaitingToReceive == NULL )
\r
390 if( pxStreamBuffer->xTaskWaitingToSend == NULL )
\r
392 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
\r
394 xIsMessageBuffer = pdTRUE;
\r
398 xIsMessageBuffer = pdFALSE;
\r
401 prvInitialiseNewStreamBuffer( pxStreamBuffer,
\r
402 pxStreamBuffer->pucBuffer,
\r
403 pxStreamBuffer->xLength,
\r
404 pxStreamBuffer->xTriggerLevelBytes,
\r
405 xIsMessageBuffer );
\r
408 #if( configUSE_TRACE_FACILITY == 1 )
\r
410 pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
\r
414 traceSTREAM_BUFFER_RESET( xStreamBuffer );
\r
420 /*-----------------------------------------------------------*/
\r
422 BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel )
\r
424 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
425 BaseType_t xReturn;
\r
427 configASSERT( pxStreamBuffer );
\r
429 /* It is not valid for the trigger level to be 0. */
\r
430 if( xTriggerLevel == ( size_t ) 0 )
\r
432 xTriggerLevel = ( size_t ) 1; /*lint !e9044 Parameter modified to ensure it doesn't have a dangerous value. */
\r
435 /* The trigger level is the number of bytes that must be in the stream
\r
436 buffer before a task that is waiting for data is unblocked. */
\r
437 if( xTriggerLevel <= pxStreamBuffer->xLength )
\r
439 pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel;
\r
449 /*-----------------------------------------------------------*/
\r
451 size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer )
\r
453 const StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
456 configASSERT( pxStreamBuffer );
\r
458 xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail;
\r
459 xSpace -= pxStreamBuffer->xHead;
\r
460 xSpace -= ( size_t ) 1;
\r
462 if( xSpace >= pxStreamBuffer->xLength )
\r
464 xSpace -= pxStreamBuffer->xLength;
\r
468 mtCOVERAGE_TEST_MARKER();
\r
473 /*-----------------------------------------------------------*/
\r
475 size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer )
\r
477 const StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
480 configASSERT( pxStreamBuffer );
\r
482 xReturn = prvBytesInBuffer( pxStreamBuffer );
\r
485 /*-----------------------------------------------------------*/
\r
487 size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
\r
488 const void *pvTxData,
\r
489 size_t xDataLengthBytes,
\r
490 TickType_t xTicksToWait )
\r
492 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
493 size_t xReturn, xSpace = 0;
\r
494 size_t xRequiredSpace = xDataLengthBytes;
\r
495 TimeOut_t xTimeOut;
\r
497 configASSERT( pvTxData );
\r
498 configASSERT( pxStreamBuffer );
\r
500 /* This send function is used to write to both message buffers and stream
\r
501 buffers. If this is a message buffer then the space needed must be
\r
502 increased by the amount of bytes needed to store the length of the
\r
504 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
\r
506 xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
\r
509 configASSERT( xRequiredSpace > xDataLengthBytes );
\r
513 mtCOVERAGE_TEST_MARKER();
\r
516 if( xTicksToWait != ( TickType_t ) 0 )
\r
518 vTaskSetTimeOutState( &xTimeOut );
\r
522 /* Wait until the required number of bytes are free in the message
\r
524 taskENTER_CRITICAL();
\r
526 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
\r
528 if( xSpace < xRequiredSpace )
\r
530 /* Clear notification state as going to wait for space. */
\r
531 ( void ) xTaskNotifyStateClear( NULL );
\r
533 /* Should only be one writer. */
\r
534 configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL );
\r
535 pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle();
\r
539 taskEXIT_CRITICAL();
\r
543 taskEXIT_CRITICAL();
\r
545 traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
\r
546 ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
\r
547 pxStreamBuffer->xTaskWaitingToSend = NULL;
\r
549 } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
\r
553 mtCOVERAGE_TEST_MARKER();
\r
556 if( xSpace == ( size_t ) 0 )
\r
558 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
\r
562 mtCOVERAGE_TEST_MARKER();
\r
565 xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
\r
567 if( xReturn > ( size_t ) 0 )
\r
569 traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn );
\r
571 /* Was a task waiting for the data? */
\r
572 if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
\r
574 sbSEND_COMPLETED( pxStreamBuffer );
\r
578 mtCOVERAGE_TEST_MARKER();
\r
583 mtCOVERAGE_TEST_MARKER();
\r
584 traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer );
\r
589 /*-----------------------------------------------------------*/
\r
591 size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
\r
592 const void *pvTxData,
\r
593 size_t xDataLengthBytes,
\r
594 BaseType_t * const pxHigherPriorityTaskWoken )
\r
596 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
597 size_t xReturn, xSpace;
\r
598 size_t xRequiredSpace = xDataLengthBytes;
\r
600 configASSERT( pvTxData );
\r
601 configASSERT( pxStreamBuffer );
\r
603 /* This send function is used to write to both message buffers and stream
\r
604 buffers. If this is a message buffer then the space needed must be
\r
605 increased by the amount of bytes needed to store the length of the
\r
607 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
\r
609 xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
\r
613 mtCOVERAGE_TEST_MARKER();
\r
616 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
\r
617 xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
\r
619 if( xReturn > ( size_t ) 0 )
\r
621 /* Was a task waiting for the data? */
\r
622 if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
\r
624 sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
\r
628 mtCOVERAGE_TEST_MARKER();
\r
633 mtCOVERAGE_TEST_MARKER();
\r
636 traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn );
\r
640 /*-----------------------------------------------------------*/
\r
642 static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
\r
643 const void * pvTxData,
\r
644 size_t xDataLengthBytes,
\r
646 size_t xRequiredSpace )
\r
648 BaseType_t xShouldWrite;
\r
651 if( xSpace == ( size_t ) 0 )
\r
653 /* Doesn't matter if this is a stream buffer or a message buffer, there
\r
654 is no space to write. */
\r
655 xShouldWrite = pdFALSE;
\r
657 else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 )
\r
659 /* This is a stream buffer, as opposed to a message buffer, so writing a
\r
660 stream of bytes rather than discrete messages. Write as many bytes as
\r
662 xShouldWrite = pdTRUE;
\r
663 xDataLengthBytes = configMIN( xDataLengthBytes, xSpace ); /*lint !e9044 Function parameter modified to ensure it is capped to available space. */
\r
665 else if( xSpace >= xRequiredSpace )
\r
667 /* This is a message buffer, as opposed to a stream buffer, and there
\r
668 is enough space to write both the message length and the message itself
\r
669 into the buffer. Start by writing the length of the data, the data
\r
670 itself will be written later in this function. */
\r
671 xShouldWrite = pdTRUE;
\r
672 ( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH );
\r
676 /* There is space available, but not enough space. */
\r
677 xShouldWrite = pdFALSE;
\r
680 if( xShouldWrite != pdFALSE )
\r
682 /* Writes the data itself. */
\r
683 xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alighment and access. */
\r
692 /*-----------------------------------------------------------*/
\r
694 size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
\r
696 size_t xBufferLengthBytes,
\r
697 TickType_t xTicksToWait )
\r
699 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
700 size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
\r
702 configASSERT( pvRxData );
\r
703 configASSERT( pxStreamBuffer );
\r
705 /* This receive function is used by both message buffers, which store
\r
706 discrete messages, and stream buffers, which store a continuous stream of
\r
707 bytes. Discrete messages include an additional
\r
708 sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
\r
710 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
\r
712 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
\r
716 xBytesToStoreMessageLength = 0;
\r
719 if( xTicksToWait != ( TickType_t ) 0 )
\r
721 /* Checking if there is data and clearing the notification state must be
\r
722 performed atomically. */
\r
723 taskENTER_CRITICAL();
\r
725 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
\r
727 /* If this function was invoked by a message buffer read then
\r
728 xBytesToStoreMessageLength holds the number of bytes used to hold
\r
729 the length of the next discrete message. If this function was
\r
730 invoked by a stream buffer read then xBytesToStoreMessageLength will
\r
732 if( xBytesAvailable <= xBytesToStoreMessageLength )
\r
734 /* Clear notification state as going to wait for data. */
\r
735 ( void ) xTaskNotifyStateClear( NULL );
\r
737 /* Should only be one reader. */
\r
738 configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL );
\r
739 pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle();
\r
743 mtCOVERAGE_TEST_MARKER();
\r
746 taskEXIT_CRITICAL();
\r
748 if( xBytesAvailable <= xBytesToStoreMessageLength )
\r
750 /* Wait for data to be available. */
\r
751 traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer );
\r
752 ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
\r
753 pxStreamBuffer->xTaskWaitingToReceive = NULL;
\r
755 /* Recheck the data available after blocking. */
\r
756 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
\r
760 mtCOVERAGE_TEST_MARKER();
\r
765 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
\r
768 /* Whether receiving a discrete message (where xBytesToStoreMessageLength
\r
769 holds the number of bytes used to store the message length) or a stream of
\r
770 bytes (where xBytesToStoreMessageLength is zero), the number of bytes
\r
771 available must be greater than xBytesToStoreMessageLength to be able to
\r
772 read bytes from the buffer. */
\r
773 if( xBytesAvailable > xBytesToStoreMessageLength )
\r
775 xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
\r
777 /* Was a task waiting for space in the buffer? */
\r
778 if( xReceivedLength != ( size_t ) 0 )
\r
780 traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength );
\r
781 sbRECEIVE_COMPLETED( pxStreamBuffer );
\r
785 mtCOVERAGE_TEST_MARKER();
\r
790 traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer );
\r
791 mtCOVERAGE_TEST_MARKER();
\r
794 return xReceivedLength;
\r
796 /*-----------------------------------------------------------*/
\r
798 size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer )
\r
800 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
801 size_t xReturn, xBytesAvailable, xOriginalTail;
\r
802 configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
\r
804 configASSERT( pxStreamBuffer );
\r
806 /* Ensure the stream buffer is being used as a message buffer. */
\r
807 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
\r
809 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
\r
810 if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH )
\r
812 /* The number of bytes available is greater than the number of bytes
\r
813 required to hold the length of the next message, so another message
\r
814 is available. Return its length without removing the length bytes
\r
815 from the buffer. A copy of the tail is stored so the buffer can be
\r
816 returned to its prior state as the message is not actually being
\r
817 removed from the buffer. */
\r
818 xOriginalTail = pxStreamBuffer->xTail;
\r
819 ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable );
\r
820 xReturn = ( size_t ) xTempReturn;
\r
821 pxStreamBuffer->xTail = xOriginalTail;
\r
825 /* The minimum amount of bytes in a message buffer is
\r
826 ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
\r
827 less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
\r
829 configASSERT( xBytesAvailable == 0 );
\r
840 /*-----------------------------------------------------------*/
\r
842 size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
\r
844 size_t xBufferLengthBytes,
\r
845 BaseType_t * const pxHigherPriorityTaskWoken )
\r
847 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
848 size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
\r
850 configASSERT( pvRxData );
\r
851 configASSERT( pxStreamBuffer );
\r
853 /* This receive function is used by both message buffers, which store
\r
854 discrete messages, and stream buffers, which store a continuous stream of
\r
855 bytes. Discrete messages include an additional
\r
856 sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
\r
858 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
\r
860 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
\r
864 xBytesToStoreMessageLength = 0;
\r
867 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
\r
869 /* Whether receiving a discrete message (where xBytesToStoreMessageLength
\r
870 holds the number of bytes used to store the message length) or a stream of
\r
871 bytes (where xBytesToStoreMessageLength is zero), the number of bytes
\r
872 available must be greater than xBytesToStoreMessageLength to be able to
\r
873 read bytes from the buffer. */
\r
874 if( xBytesAvailable > xBytesToStoreMessageLength )
\r
876 xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
\r
878 /* Was a task waiting for space in the buffer? */
\r
879 if( xReceivedLength != ( size_t ) 0 )
\r
881 sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
\r
885 mtCOVERAGE_TEST_MARKER();
\r
890 mtCOVERAGE_TEST_MARKER();
\r
893 traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength );
\r
895 return xReceivedLength;
\r
897 /*-----------------------------------------------------------*/
\r
899 static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer,
\r
901 size_t xBufferLengthBytes,
\r
902 size_t xBytesAvailable,
\r
903 size_t xBytesToStoreMessageLength )
\r
905 size_t xOriginalTail, xReceivedLength, xNextMessageLength;
\r
906 configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
\r
908 if( xBytesToStoreMessageLength != ( size_t ) 0 )
\r
910 /* A discrete message is being received. First receive the length
\r
911 of the message. A copy of the tail is stored so the buffer can be
\r
912 returned to its prior state if the length of the message is too
\r
913 large for the provided buffer. */
\r
914 xOriginalTail = pxStreamBuffer->xTail;
\r
915 ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable );
\r
916 xNextMessageLength = ( size_t ) xTempNextMessageLength;
\r
918 /* Reduce the number of bytes available by the number of bytes just
\r
920 xBytesAvailable -= xBytesToStoreMessageLength;
\r
922 /* Check there is enough space in the buffer provided by the
\r
924 if( xNextMessageLength > xBufferLengthBytes )
\r
926 /* The user has provided insufficient space to read the message
\r
927 so return the buffer to its previous state (so the length of
\r
928 the message is in the buffer again). */
\r
929 pxStreamBuffer->xTail = xOriginalTail;
\r
930 xNextMessageLength = 0;
\r
934 mtCOVERAGE_TEST_MARKER();
\r
939 /* A stream of bytes is being received (as opposed to a discrete
\r
940 message), so read as many bytes as possible. */
\r
941 xNextMessageLength = xBufferLengthBytes;
\r
944 /* Read the actual data. */
\r
945 xReceivedLength = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xNextMessageLength, xBytesAvailable ); /*lint !e9079 Data storage area is implemented as uint8_t array for ease of sizing, indexing and alignment. */
\r
947 return xReceivedLength;
\r
949 /*-----------------------------------------------------------*/
\r
951 BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer )
\r
953 const StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
954 BaseType_t xReturn;
\r
957 configASSERT( pxStreamBuffer );
\r
959 /* True if no bytes are available. */
\r
960 xTail = pxStreamBuffer->xTail;
\r
961 if( pxStreamBuffer->xHead == xTail )
\r
972 /*-----------------------------------------------------------*/
\r
974 BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer )
\r
976 BaseType_t xReturn;
\r
977 size_t xBytesToStoreMessageLength;
\r
978 const StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
980 configASSERT( pxStreamBuffer );
\r
982 /* This generic version of the receive function is used by both message
\r
983 buffers, which store discrete messages, and stream buffers, which store a
\r
984 continuous stream of bytes. Discrete messages include an additional
\r
985 sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
\r
986 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
\r
988 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
\r
992 xBytesToStoreMessageLength = 0;
\r
995 /* True if the available space equals zero. */
\r
996 if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength )
\r
1002 xReturn = pdFALSE;
\r
1007 /*-----------------------------------------------------------*/
\r
1009 BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken )
\r
1011 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
1012 BaseType_t xReturn;
\r
1013 UBaseType_t uxSavedInterruptStatus;
\r
1015 configASSERT( pxStreamBuffer );
\r
1017 uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
\r
1019 if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )
\r
1021 ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive,
\r
1024 pxHigherPriorityTaskWoken );
\r
1025 ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;
\r
1030 xReturn = pdFALSE;
\r
1033 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1037 /*-----------------------------------------------------------*/
\r
1039 BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken )
\r
1041 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
\r
1042 BaseType_t xReturn;
\r
1043 UBaseType_t uxSavedInterruptStatus;
\r
1045 configASSERT( pxStreamBuffer );
\r
1047 uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
\r
1049 if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )
\r
1051 ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend,
\r
1054 pxHigherPriorityTaskWoken );
\r
1055 ( pxStreamBuffer )->xTaskWaitingToSend = NULL;
\r
1060 xReturn = pdFALSE;
\r
1063 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1067 /*-----------------------------------------------------------*/
\r
1069 static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount )
\r
1071 size_t xNextHead, xFirstLength;
\r
1073 configASSERT( xCount > ( size_t ) 0 );
\r
1075 xNextHead = pxStreamBuffer->xHead;
\r
1077 /* Calculate the number of bytes that can be added in the first write -
\r
1078 which may be less than the total number of bytes that need to be added if
\r
1079 the buffer will wrap back to the beginning. */
\r
1080 xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount );
\r
1082 /* Write as many bytes as can be written in the first write. */
\r
1083 configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength );
\r
1084 memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */
\r
1086 /* If the number of bytes written was less than the number that could be
\r
1087 written in the first write... */
\r
1088 if( xCount > xFirstLength )
\r
1090 /* ...then write the remaining bytes to the start of the buffer. */
\r
1091 configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength );
\r
1092 memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
\r
1096 mtCOVERAGE_TEST_MARKER();
\r
1099 xNextHead += xCount;
\r
1100 if( xNextHead >= pxStreamBuffer->xLength )
\r
1102 xNextHead -= pxStreamBuffer->xLength;
\r
1106 mtCOVERAGE_TEST_MARKER();
\r
1109 pxStreamBuffer->xHead = xNextHead;
\r
1113 /*-----------------------------------------------------------*/
\r
1115 static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, uint8_t *pucData, size_t xMaxCount, size_t xBytesAvailable )
\r
1117 size_t xCount, xFirstLength, xNextTail;
\r
1119 /* Use the minimum of the wanted bytes and the available bytes. */
\r
1120 xCount = configMIN( xBytesAvailable, xMaxCount );
\r
1122 if( xCount > ( size_t ) 0 )
\r
1124 xNextTail = pxStreamBuffer->xTail;
\r
1126 /* Calculate the number of bytes that can be read - which may be
\r
1127 less than the number wanted if the data wraps around to the start of
\r
1129 xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount );
\r
1131 /* Obtain the number of bytes it is possible to obtain in the first
\r
1132 read. Asserts check bounds of read and write. */
\r
1133 configASSERT( xFirstLength <= xMaxCount );
\r
1134 configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength );
\r
1135 memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */
\r
1137 /* If the total number of wanted bytes is greater than the number
\r
1138 that could be read in the first read... */
\r
1139 if( xCount > xFirstLength )
\r
1141 /*...then read the remaining bytes from the start of the buffer. */
\r
1142 configASSERT( xCount <= xMaxCount );
\r
1143 memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
\r
1147 mtCOVERAGE_TEST_MARKER();
\r
1150 /* Move the tail pointer to effectively remove the data read from
\r
1152 xNextTail += xCount;
\r
1154 if( xNextTail >= pxStreamBuffer->xLength )
\r
1156 xNextTail -= pxStreamBuffer->xLength;
\r
1159 pxStreamBuffer->xTail = xNextTail;
\r
1163 mtCOVERAGE_TEST_MARKER();
\r
1168 /*-----------------------------------------------------------*/
\r
1170 static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer )
\r
1172 /* Returns the distance between xTail and xHead. */
\r
1175 xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead;
\r
1176 xCount -= pxStreamBuffer->xTail;
\r
1177 if ( xCount >= pxStreamBuffer->xLength )
\r
1179 xCount -= pxStreamBuffer->xLength;
\r
1183 mtCOVERAGE_TEST_MARKER();
\r
1188 /*-----------------------------------------------------------*/
\r
1190 static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
\r
1191 uint8_t * const pucBuffer,
\r
1192 size_t xBufferSizeBytes,
\r
1193 size_t xTriggerLevelBytes,
\r
1194 BaseType_t xIsMessageBuffer )
\r
1196 /* Assert here is deliberately writing to the entire buffer to ensure it can
\r
1197 be written to without generating exceptions, and is setting the buffer to a
\r
1198 known value to assist in development/debugging. */
\r
1199 #if( configASSERT_DEFINED == 1 )
\r
1201 /* The value written just has to be identifiable when looking at the
\r
1202 memory. Don't use 0xA5 as that is the stack fill value and could
\r
1203 result in confusion as to what is actually being observed. */
\r
1204 const BaseType_t xWriteValue = 0x55;
\r
1205 configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer );
\r
1209 memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */
\r
1210 pxStreamBuffer->pucBuffer = pucBuffer;
\r
1211 pxStreamBuffer->xLength = xBufferSizeBytes;
\r
1212 pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes;
\r
1214 if( xIsMessageBuffer != pdFALSE )
\r
1216 pxStreamBuffer->ucFlags |= sbFLAGS_IS_MESSAGE_BUFFER;
\r
1220 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1222 UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer )
\r
1224 return ( ( StreamBuffer_t * ) xStreamBuffer )->uxStreamBufferNumber;
\r
1227 #endif /* configUSE_TRACE_FACILITY */
\r
1228 /*-----------------------------------------------------------*/
\r
1230 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1232 void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber )
\r
1234 ( ( StreamBuffer_t * ) xStreamBuffer )->uxStreamBufferNumber = uxStreamBufferNumber;
\r
1237 #endif /* configUSE_TRACE_FACILITY */
\r
1238 /*-----------------------------------------------------------*/
\r
1240 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1242 uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer )
\r
1244 return ( ( StreamBuffer_t * )xStreamBuffer )->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER;
\r
1247 #endif /* configUSE_TRACE_FACILITY */
\r
1248 /*-----------------------------------------------------------*/
\r