]> begriffs open source - cmsis-freertos/blob - Source/stream_buffer.c
Compiler warning statement fixed
[cmsis-freertos] / Source / stream_buffer.c
1 /*
2  * FreeRTOS Kernel V10.0.1
3  * Copyright (C) 2017 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  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /* Standard includes. */
29 #include <stdint.h>
30 #include <string.h>
31
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
33 all the API functions to use the MPU wrappers.  That should only be done when
34 task.h is included from an application file. */
35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
36
37 /* FreeRTOS includes. */
38 #include "FreeRTOS.h"
39 #include "task.h"
40 #include "stream_buffer.h"
41
42 #if( configUSE_TASK_NOTIFICATIONS != 1 )
43         #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c
44 #endif
45
46 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
47 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
48 header files above, but not in this file, in order to generate the correct
49 privileged Vs unprivileged linkage and placement. */
50 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
51
52 /* If the user has not provided application specific Rx notification macros,
53 or #defined the notification macros away, them provide default implementations
54 that uses task notifications. */
55 /*lint -save -e9026 Function like macros allowed and needed here so they can be overidden. */
56 #ifndef sbRECEIVE_COMPLETED
57         #define sbRECEIVE_COMPLETED( pxStreamBuffer )                                                                           \
58                 vTaskSuspendAll();                                                                                                                              \
59                 {                                                                                                                                                               \
60                         if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )                                            \
61                         {                                                                                                                                                       \
62                                 ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend,                   \
63                                                                           ( uint32_t ) 0,                                                                       \
64                                                                           eNoAction );                                                                          \
65                                 ( pxStreamBuffer )->xTaskWaitingToSend = NULL;                                                  \
66                         }                                                                                                                                                       \
67                 }                                                                                                                                                               \
68                 ( void ) xTaskResumeAll();
69 #endif /* sbRECEIVE_COMPLETED */
70
71 #ifndef sbRECEIVE_COMPLETED_FROM_ISR
72         #define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer,                                                           \
73                                                                                   pxHigherPriorityTaskWoken )                                   \
74         {                                                                                                                                                                       \
75         UBaseType_t uxSavedInterruptStatus;                                                                                                     \
76                                                                                                                                                                                 \
77                 uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();             \
78                 {                                                                                                                                                               \
79                         if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )                                            \
80                         {                                                                                                                                                       \
81                                 ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend,    \
82                                                                                          ( uint32_t ) 0,                                                        \
83                                                                                          eNoAction,                                                                     \
84                                                                                          pxHigherPriorityTaskWoken );                           \
85                                 ( pxStreamBuffer )->xTaskWaitingToSend = NULL;                                                  \
86                         }                                                                                                                                                       \
87                 }                                                                                                                                                               \
88                 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );                                    \
89         }
90 #endif /* sbRECEIVE_COMPLETED_FROM_ISR */
91
92 /* If the user has not provided an application specific Tx notification macro,
93 or #defined the notification macro away, them provide a default implementation
94 that uses task notifications. */
95 #ifndef sbSEND_COMPLETED
96         #define sbSEND_COMPLETED( pxStreamBuffer )                                                                                      \
97                 vTaskSuspendAll();                                                                                                                              \
98                 {                                                                                                                                                               \
99                         if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )                                         \
100                         {                                                                                                                                                       \
101                                 ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToReceive,                \
102                                                                           ( uint32_t ) 0,                                                                       \
103                                                                           eNoAction );                                                                          \
104                                 ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;                                               \
105                         }                                                                                                                                                       \
106                 }                                                                                                                                                               \
107                 ( void ) xTaskResumeAll();
108 #endif /* sbSEND_COMPLETED */
109
110 #ifndef sbSEND_COMPLETE_FROM_ISR
111         #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken )           \
112         {                                                                                                                                                                       \
113         UBaseType_t uxSavedInterruptStatus;                                                                                                     \
114                                                                                                                                                                                 \
115                 uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();             \
116                 {                                                                                                                                                               \
117                         if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )                                         \
118                         {                                                                                                                                                       \
119                                 ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, \
120                                                                                          ( uint32_t ) 0,                                                        \
121                                                                                          eNoAction,                                                                     \
122                                                                                          pxHigherPriorityTaskWoken );                           \
123                                 ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;                                               \
124                         }                                                                                                                                                       \
125                 }                                                                                                                                                               \
126                 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );                                    \
127         }
128 #endif /* sbSEND_COMPLETE_FROM_ISR */
129 /*lint -restore (9026) */
130
131 /* The number of bytes used to hold the length of a message in the buffer. */
132 #define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( size_t ) )
133
134 /* Bits stored in the ucFlags field of the stream buffer. */
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. */
136 #define sbFLAGS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 2 ) /* Set if the stream buffer was created using statically allocated memory. */
137
138 /*-----------------------------------------------------------*/
139
140 /* Structure that hold state information on the buffer. */
141 typedef struct xSTREAM_BUFFER /*lint !e9058 Style convention uses tag. */
142 {
143         volatile size_t xTail;                          /* Index to the next item to read within the buffer. */
144         volatile size_t xHead;                          /* Index to the next item to write within the buffer. */
145         size_t xLength;                                         /* The length of the buffer pointed to by pucBuffer. */
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. */
147         volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */
148         volatile TaskHandle_t xTaskWaitingToSend;       /* Holds the handle of a task waiting to send data to a message buffer that is full. */
149         uint8_t *pucBuffer;                                     /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */
150         uint8_t ucFlags;
151
152         #if ( configUSE_TRACE_FACILITY == 1 )
153                 UBaseType_t uxStreamBufferNumber;               /* Used for tracing purposes. */
154         #endif
155 } StreamBuffer_t;
156
157 /*
158  * The number of bytes available to be read from the buffer.
159  */
160 static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION;
161
162 /*
163  * Add xCount bytes from pucData into the pxStreamBuffer message buffer.
164  * Returns the number of bytes written, which will either equal xCount in the
165  * success case, or 0 if there was not enough space in the buffer (in which case
166  * no data is written into the buffer).
167  */
168 static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount ) PRIVILEGED_FUNCTION;
169
170 /*
171  * If the stream buffer is being used as a message buffer, then reads an entire
172  * message out of the buffer.  If the stream buffer is being used as a stream
173  * buffer then read as many bytes as possible from the buffer.
174  * prvReadBytesFromBuffer() is called to actually extract the bytes from the
175  * buffer's data storage area.
176  */
177 static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer,
178                                                                                 void *pvRxData,
179                                                                                 size_t xBufferLengthBytes,
180                                                                                 size_t xBytesAvailable,
181                                                                                 size_t xBytesToStoreMessageLength ) PRIVILEGED_FUNCTION;
182
183 /*
184  * If the stream buffer is being used as a message buffer, then writes an entire
185  * message to the buffer.  If the stream buffer is being used as a stream
186  * buffer then write as many bytes as possible to the buffer.
187  * prvWriteBytestoBuffer() is called to actually send the bytes to the buffer's
188  * data storage area.
189  */
190 static size_t prvWriteMessageToBuffer(  StreamBuffer_t * const pxStreamBuffer,
191                                                                                 const void * pvTxData,
192                                                                                 size_t xDataLengthBytes,
193                                                                                 size_t xSpace,
194                                                                                 size_t xRequiredSpace ) PRIVILEGED_FUNCTION;
195
196 /*
197  * Read xMaxCount bytes from the pxStreamBuffer message buffer and write them
198  * to pucData.
199  */
200 static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer,
201                                                                           uint8_t *pucData,
202                                                                           size_t xMaxCount,
203                                                                           size_t xBytesAvailable ); PRIVILEGED_FUNCTION
204
205 /*
206  * Called by both pxStreamBufferCreate() and pxStreamBufferCreateStatic() to
207  * initialise the members of the newly created stream buffer structure.
208  */
209 static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
210                                                                                   uint8_t * const pucBuffer,
211                                                                                   size_t xBufferSizeBytes,
212                                                                                   size_t xTriggerLevelBytes,
213                                                                                   BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION;
214
215 /*-----------------------------------------------------------*/
216
217 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
218
219         StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer )
220         {
221         uint8_t *pucAllocatedMemory;
222
223                 /* In case the stream buffer is going to be used as a message buffer
224                 (that is, it will hold discrete messages with a little meta data that
225                 says how big the next message is) check the buffer will be large enough
226                 to hold at least one message. */
227                 configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
228                 configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
229
230                 /* A trigger level of 0 would cause a waiting task to unblock even when
231                 the buffer was empty. */
232                 if( xTriggerLevelBytes == ( size_t ) 0 )
233                 {
234                         xTriggerLevelBytes = ( size_t ) 1; /*lint !e9044 Parameter modified to ensure it doesn't have a dangerous value. */
235                 }
236
237                 /* A stream buffer requires a StreamBuffer_t structure and a buffer.
238                 Both are allocated in a single call to pvPortMalloc().  The
239                 StreamBuffer_t structure is placed at the start of the allocated memory
240                 and the buffer follows immediately after.  The requested size is
241                 incremented so the free space is returned as the user would expect -
242                 this is a quirk of the implementation that means otherwise the free
243                 space would be reported as one byte smaller than would be logically
244                 expected. */
245                 xBufferSizeBytes++;
246                 pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */
247
248                 if( pucAllocatedMemory != NULL )
249                 {
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. */
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. */
252                                                                                    xBufferSizeBytes,
253                                                                                    xTriggerLevelBytes,
254                                                                                    xIsMessageBuffer );
255
256                         traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer );
257                 }
258                 else
259                 {
260                         traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer );
261                 }
262
263                 return ( StreamBufferHandle_t * ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */
264         }
265
266 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
267 /*-----------------------------------------------------------*/
268
269 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
270
271         StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
272                                                                                                                    size_t xTriggerLevelBytes,
273                                                                                                                    BaseType_t xIsMessageBuffer,
274                                                                                                                    uint8_t * const pucStreamBufferStorageArea,
275                                                                                                                    StaticStreamBuffer_t * const pxStaticStreamBuffer )
276         {
277         StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */
278         StreamBufferHandle_t xReturn;
279
280                 configASSERT( pucStreamBufferStorageArea );
281                 configASSERT( pxStaticStreamBuffer );
282                 configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
283
284                 /* A trigger level of 0 would cause a waiting task to unblock even when
285                 the buffer was empty. */
286                 if( xTriggerLevelBytes == ( size_t ) 0 )
287                 {
288                         xTriggerLevelBytes = ( size_t ) 1; /*lint !e9044 Function parameter deliberately modified to ensure it is in range. */
289                 }
290
291                 /* In case the stream buffer is going to be used as a message buffer
292                 (that is, it will hold discrete messages with a little meta data that
293                 says how big the next message is) check the buffer will be large enough
294                 to hold at least one message. */
295                 configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
296
297                 #if( configASSERT_DEFINED == 1 )
298                 {
299                         /* Sanity check that the size of the structure used to declare a
300                         variable of type StaticStreamBuffer_t equals the size of the real
301                         message buffer structure. */
302                         volatile size_t xSize = sizeof( StaticStreamBuffer_t );
303                         configASSERT( xSize == sizeof( StreamBuffer_t ) );
304                 }
305                 #endif /* configASSERT_DEFINED */
306
307                 if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) )
308                 {
309                         prvInitialiseNewStreamBuffer( pxStreamBuffer,
310                                                                                   pucStreamBufferStorageArea,
311                                                                                   xBufferSizeBytes,
312                                                                                   xTriggerLevelBytes,
313                                                                                   xIsMessageBuffer );
314
315                         /* Remember this was statically allocated in case it is ever deleted
316                         again. */
317                         pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED;
318
319                         traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer );
320
321                         xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; /*lint !e9087 Data hiding requires cast to opaque type. */
322                 }
323                 else
324                 {
325                         xReturn = NULL;
326                         traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer );
327                 }
328
329                 return xReturn;
330         }
331
332 #endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
333 /*-----------------------------------------------------------*/
334
335 void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer )
336 {
337 StreamBuffer_t * pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
338
339         configASSERT( pxStreamBuffer );
340
341         traceSTREAM_BUFFER_DELETE( xStreamBuffer );
342
343         if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE )
344         {
345                 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
346                 {
347                         /* Both the structure and the buffer were allocated using a single call
348                         to pvPortMalloc(), hence only one call to vPortFree() is required. */
349                         vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */
350                 }
351                 #else
352                 {
353                         /* Should not be possible to get here, ucFlags must be corrupt.
354                         Force an assert. */
355                         configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 );
356                 }
357                 #endif
358         }
359         else
360         {
361                 /* The structure and buffer were not allocated dynamically and cannot be
362                 freed - just scrub the structure so future use will assert. */
363                 memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) );
364         }
365 }
366 /*-----------------------------------------------------------*/
367
368 BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
369 {
370 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
371 BaseType_t xReturn = pdFAIL, xIsMessageBuffer;
372
373 #if( configUSE_TRACE_FACILITY == 1 )
374         UBaseType_t uxStreamBufferNumber;
375 #endif
376
377         configASSERT( pxStreamBuffer );
378
379         #if( configUSE_TRACE_FACILITY == 1 )
380         {
381                 /* Store the stream buffer number so it can be restored after the
382                 reset. */
383                 uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber;
384         }
385         #endif
386
387         /* Can only reset a message buffer if there are no tasks blocked on it. */
388         if( pxStreamBuffer->xTaskWaitingToReceive == NULL )
389         {
390                 if( pxStreamBuffer->xTaskWaitingToSend == NULL )
391                 {
392                         if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
393                         {
394                                 xIsMessageBuffer = pdTRUE;
395                         }
396                         else
397                         {
398                                 xIsMessageBuffer = pdFALSE;
399                         }
400
401                         prvInitialiseNewStreamBuffer( pxStreamBuffer,
402                                                                                   pxStreamBuffer->pucBuffer,
403                                                                                   pxStreamBuffer->xLength,
404                                                                                   pxStreamBuffer->xTriggerLevelBytes,
405                                                                                   xIsMessageBuffer );
406                         xReturn = pdPASS;
407
408                         #if( configUSE_TRACE_FACILITY == 1 )
409                         {
410                                 pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
411                         }
412                         #endif
413
414                         traceSTREAM_BUFFER_RESET( xStreamBuffer );
415                 }
416         }
417
418         return xReturn;
419 }
420 /*-----------------------------------------------------------*/
421
422 BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel )
423 {
424 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
425 BaseType_t xReturn;
426
427         configASSERT( pxStreamBuffer );
428
429         /* It is not valid for the trigger level to be 0. */
430         if( xTriggerLevel == ( size_t ) 0 )
431         {
432                 xTriggerLevel = ( size_t ) 1; /*lint !e9044 Parameter modified to ensure it doesn't have a dangerous value. */
433         }
434
435         /* The trigger level is the number of bytes that must be in the stream
436         buffer before a task that is waiting for data is unblocked. */
437         if( xTriggerLevel <= pxStreamBuffer->xLength )
438         {
439                 pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel;
440                 xReturn = pdPASS;
441         }
442         else
443         {
444                 xReturn = pdFALSE;
445         }
446
447         return xReturn;
448 }
449 /*-----------------------------------------------------------*/
450
451 size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer )
452 {
453 const StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
454 size_t xSpace;
455
456         configASSERT( pxStreamBuffer );
457
458         xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail;
459         xSpace -= pxStreamBuffer->xHead;
460         xSpace -= ( size_t ) 1;
461
462         if( xSpace >= pxStreamBuffer->xLength )
463         {
464                 xSpace -= pxStreamBuffer->xLength;
465         }
466         else
467         {
468                 mtCOVERAGE_TEST_MARKER();
469         }
470
471         return xSpace;
472 }
473 /*-----------------------------------------------------------*/
474
475 size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer )
476 {
477 const StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
478 size_t xReturn;
479
480         configASSERT( pxStreamBuffer );
481
482         xReturn = prvBytesInBuffer( pxStreamBuffer );
483         return xReturn;
484 }
485 /*-----------------------------------------------------------*/
486
487 size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
488                                                   const void *pvTxData,
489                                                   size_t xDataLengthBytes,
490                                                   TickType_t xTicksToWait )
491 {
492 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
493 size_t xReturn, xSpace = 0;
494 size_t xRequiredSpace = xDataLengthBytes;
495 TimeOut_t xTimeOut;
496
497         configASSERT( pvTxData );
498         configASSERT( pxStreamBuffer );
499
500         /* This send function is used to write to both message buffers and stream
501         buffers.  If this is a message buffer then the space needed must be
502         increased by the amount of bytes needed to store the length of the
503         message. */
504         if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
505         {
506                 xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
507         }
508         else
509         {
510                 mtCOVERAGE_TEST_MARKER();
511         }
512
513         if( xTicksToWait != ( TickType_t ) 0 )
514         {
515                 vTaskSetTimeOutState( &xTimeOut );
516
517                 do
518                 {
519                         /* Wait until the required number of bytes are free in the message
520                         buffer. */
521                         taskENTER_CRITICAL();
522                         {
523                                 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
524
525                                 if( xSpace < xRequiredSpace )
526                                 {
527                                         /* Clear notification state as going to wait for space. */
528                                         ( void ) xTaskNotifyStateClear( NULL );
529
530                                         /* Should only be one writer. */
531                                         configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL );
532                                         pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle();
533                                 }
534                                 else
535                                 {
536                                         taskEXIT_CRITICAL();
537                                         break;
538                                 }
539                         }
540                         taskEXIT_CRITICAL();
541
542                         traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
543                         ( void ) xTaskNotifyWait( ( uint32_t ) 0, UINT32_MAX, NULL, xTicksToWait );
544                         pxStreamBuffer->xTaskWaitingToSend = NULL;
545
546                 } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
547         }
548         else
549         {
550                 mtCOVERAGE_TEST_MARKER();
551         }
552
553         if( xSpace == ( size_t ) 0 )
554         {
555                 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
556         }
557         else
558         {
559                 mtCOVERAGE_TEST_MARKER();
560         }
561
562         xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
563
564         if( xReturn > ( size_t ) 0 )
565         {
566                 traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn );
567
568                 /* Was a task waiting for the data? */
569                 if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
570                 {
571                         sbSEND_COMPLETED( pxStreamBuffer );
572                 }
573                 else
574                 {
575                         mtCOVERAGE_TEST_MARKER();
576                 }
577         }
578         else
579         {
580                 mtCOVERAGE_TEST_MARKER();
581                 traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer );
582         }
583
584         return xReturn;
585 }
586 /*-----------------------------------------------------------*/
587
588 size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
589                                                                  const void *pvTxData,
590                                                                  size_t xDataLengthBytes,
591                                                                  BaseType_t * const pxHigherPriorityTaskWoken )
592 {
593 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
594 size_t xReturn, xSpace;
595 size_t xRequiredSpace = xDataLengthBytes;
596
597         configASSERT( pvTxData );
598         configASSERT( pxStreamBuffer );
599
600         /* This send function is used to write to both message buffers and stream
601         buffers.  If this is a message buffer then the space needed must be
602         increased by the amount of bytes needed to store the length of the
603         message. */
604         if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
605         {
606                 xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
607         }
608         else
609         {
610                 mtCOVERAGE_TEST_MARKER();
611         }
612
613         xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
614         xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
615
616         if( xReturn > ( size_t ) 0 )
617         {
618                 /* Was a task waiting for the data? */
619                 if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
620                 {
621                         sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
622                 }
623                 else
624                 {
625                         mtCOVERAGE_TEST_MARKER();
626                 }
627         }
628         else
629         {
630                 mtCOVERAGE_TEST_MARKER();
631         }
632
633         traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn );
634
635         return xReturn;
636 }
637 /*-----------------------------------------------------------*/
638
639 static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
640                                                                            const void * pvTxData,
641                                                                            size_t xDataLengthBytes,
642                                                                            size_t xSpace,
643                                                                            size_t xRequiredSpace )
644 {
645         BaseType_t xShouldWrite;
646         size_t xReturn;
647
648         if( xSpace == ( size_t ) 0 )
649         {
650                 /* Doesn't matter if this is a stream buffer or a message buffer, there
651                 is no space to write. */
652                 xShouldWrite = pdFALSE;
653         }
654         else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 )
655         {
656                 /* This is a stream buffer, as opposed to a message buffer, so writing a
657                 stream of bytes rather than discrete messages.  Write as many bytes as
658                 possible. */
659                 xShouldWrite = pdTRUE;
660                 xDataLengthBytes = configMIN( xDataLengthBytes, xSpace ); /*lint !e9044 Function parameter modified to ensure it is capped to available space. */
661         }
662         else if( xSpace >= xRequiredSpace )
663         {
664                 /* This is a message buffer, as opposed to a stream buffer, and there
665                 is enough space to write both the message length and the message itself
666                 into the buffer.  Start by writing the length of the data, the data
667                 itself will be written later in this function. */
668                 xShouldWrite = pdTRUE;
669                 ( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH );
670         }
671         else
672         {
673                 /* There is space available, but not enough space. */
674                 xShouldWrite = pdFALSE;
675         }
676
677         if( xShouldWrite != pdFALSE )
678         {
679                 /* Writes the data itself. */
680                 xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alighment and access. */
681         }
682         else
683         {
684                 xReturn = 0;
685         }
686
687         return xReturn;
688 }
689 /*-----------------------------------------------------------*/
690
691 size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
692                                                          void *pvRxData,
693                                                          size_t xBufferLengthBytes,
694                                                          TickType_t xTicksToWait )
695 {
696 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
697 size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
698
699         configASSERT( pvRxData );
700         configASSERT( pxStreamBuffer );
701
702         /* This receive function is used by both message buffers, which store
703         discrete messages, and stream buffers, which store a continuous stream of
704         bytes.  Discrete messages include an additional
705         sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
706         message. */
707         if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
708         {
709                 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
710         }
711         else
712         {
713                 xBytesToStoreMessageLength = 0;
714         }
715
716         if( xTicksToWait != ( TickType_t ) 0 )
717         {
718                 /* Checking if there is data and clearing the notification state must be
719                 performed atomically. */
720                 taskENTER_CRITICAL();
721                 {
722                         xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
723
724                         /* If this function was invoked by a message buffer read then
725                         xBytesToStoreMessageLength holds the number of bytes used to hold
726                         the length of the next discrete message.  If this function was
727                         invoked by a stream buffer read then xBytesToStoreMessageLength will
728                         be 0. */
729                         if( xBytesAvailable <= xBytesToStoreMessageLength )
730                         {
731                                 /* Clear notification state as going to wait for data. */
732                                 ( void ) xTaskNotifyStateClear( NULL );
733
734                                 /* Should only be one reader. */
735                                 configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL );
736                                 pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle();
737                         }
738                         else
739                         {
740                                 mtCOVERAGE_TEST_MARKER();
741                         }
742                 }
743                 taskEXIT_CRITICAL();
744
745                 if( xBytesAvailable <= xBytesToStoreMessageLength )
746                 {
747                         /* Wait for data to be available. */
748                         traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer );
749                         ( void ) xTaskNotifyWait( ( uint32_t ) 0, UINT32_MAX, NULL, xTicksToWait );
750                         pxStreamBuffer->xTaskWaitingToReceive = NULL;
751
752                         /* Recheck the data available after blocking. */
753                         xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
754                 }
755                 else
756                 {
757                         mtCOVERAGE_TEST_MARKER();
758                 }
759         }
760         else
761         {
762                 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
763         }
764
765         /* Whether receiving a discrete message (where xBytesToStoreMessageLength
766         holds the number of bytes used to store the message length) or a stream of
767         bytes (where xBytesToStoreMessageLength is zero), the number of bytes
768         available must be greater than xBytesToStoreMessageLength to be able to
769         read bytes from the buffer. */
770         if( xBytesAvailable > xBytesToStoreMessageLength )
771         {
772                 xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
773
774                 /* Was a task waiting for space in the buffer? */
775                 if( xReceivedLength != ( size_t ) 0 )
776                 {
777                         traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength );
778                         sbRECEIVE_COMPLETED( pxStreamBuffer );
779                 }
780                 else
781                 {
782                         mtCOVERAGE_TEST_MARKER();
783                 }
784         }
785         else
786         {
787                 traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer );
788                 mtCOVERAGE_TEST_MARKER();
789         }
790
791         return xReceivedLength;
792 }
793 /*-----------------------------------------------------------*/
794
795 size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
796                                                                         void *pvRxData,
797                                                                         size_t xBufferLengthBytes,
798                                                                         BaseType_t * const pxHigherPriorityTaskWoken )
799 {
800 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
801 size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
802
803         configASSERT( pvRxData );
804         configASSERT( pxStreamBuffer );
805
806         /* This receive function is used by both message buffers, which store
807         discrete messages, and stream buffers, which store a continuous stream of
808         bytes.  Discrete messages include an additional
809         sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
810         message. */
811         if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
812         {
813                 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
814         }
815         else
816         {
817                 xBytesToStoreMessageLength = 0;
818         }
819
820         xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
821
822         /* Whether receiving a discrete message (where xBytesToStoreMessageLength
823         holds the number of bytes used to store the message length) or a stream of
824         bytes (where xBytesToStoreMessageLength is zero), the number of bytes
825         available must be greater than xBytesToStoreMessageLength to be able to
826         read bytes from the buffer. */
827         if( xBytesAvailable > xBytesToStoreMessageLength )
828         {
829                 xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
830
831                 /* Was a task waiting for space in the buffer? */
832                 if( xReceivedLength != ( size_t ) 0 )
833                 {
834                         sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
835                 }
836                 else
837                 {
838                         mtCOVERAGE_TEST_MARKER();
839                 }
840         }
841         else
842         {
843                 mtCOVERAGE_TEST_MARKER();
844         }
845
846         traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength );
847
848         return xReceivedLength;
849 }
850 /*-----------------------------------------------------------*/
851
852 static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer,
853                                                                                 void *pvRxData,
854                                                                                 size_t xBufferLengthBytes,
855                                                                                 size_t xBytesAvailable,
856                                                                                 size_t xBytesToStoreMessageLength )
857 {
858 size_t xOriginalTail, xReceivedLength, xNextMessageLength;
859
860         if( xBytesToStoreMessageLength != ( size_t ) 0 )
861         {
862                 /* A discrete message is being received.  First receive the length
863                 of the message.  A copy of the tail is stored so the buffer can be
864                 returned to its prior state if the length of the message is too
865                 large for the provided buffer. */
866                 xOriginalTail = pxStreamBuffer->xTail;
867                 ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable );
868
869                 /* Reduce the number of bytes available by the number of bytes just
870                 read out. */
871                 xBytesAvailable -= xBytesToStoreMessageLength;
872
873                 /* Check there is enough space in the buffer provided by the
874                 user. */
875                 if( xNextMessageLength > xBufferLengthBytes )
876                 {
877                         /* The user has provided insufficient space to read the message
878                         so return the buffer to its previous state (so the length of
879                         the message is in the buffer again). */
880                         pxStreamBuffer->xTail = xOriginalTail;
881                         xNextMessageLength = 0;
882                 }
883                 else
884                 {
885                         mtCOVERAGE_TEST_MARKER();
886                 }
887         }
888         else
889         {
890                 /* A stream of bytes is being received (as opposed to a discrete
891                 message), so read as many bytes as possible. */
892                 xNextMessageLength = xBufferLengthBytes;
893         }
894
895         /* Read the actual data. */
896         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. */
897
898         return xReceivedLength;
899 }
900 /*-----------------------------------------------------------*/
901
902 BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer )
903 {
904 const StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
905 BaseType_t xReturn;
906 size_t xTail;
907
908         configASSERT( pxStreamBuffer );
909
910         /* True if no bytes are available. */
911         xTail = pxStreamBuffer->xTail;
912         if( pxStreamBuffer->xHead == xTail )
913         {
914                 xReturn = pdTRUE;
915         }
916         else
917         {
918                 xReturn = pdFALSE;
919         }
920
921         return xReturn;
922 }
923 /*-----------------------------------------------------------*/
924
925 BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer )
926 {
927 BaseType_t xReturn;
928 size_t xBytesToStoreMessageLength;
929 const StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
930
931         configASSERT( pxStreamBuffer );
932
933         /* This generic version of the receive function is used by both message
934         buffers, which store discrete messages, and stream buffers, which store a
935         continuous stream of bytes.  Discrete messages include an additional
936         sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
937         if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
938         {
939                 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
940         }
941         else
942         {
943                 xBytesToStoreMessageLength = 0;
944         }
945
946         /* True if the available space equals zero. */
947         if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength )
948         {
949                 xReturn = pdTRUE;
950         }
951         else
952         {
953                 xReturn = pdFALSE;
954         }
955
956         return xReturn;
957 }
958 /*-----------------------------------------------------------*/
959
960 BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken )
961 {
962 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
963 BaseType_t xReturn;
964 UBaseType_t uxSavedInterruptStatus;
965
966         configASSERT( pxStreamBuffer );
967
968         uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
969         {
970                 if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )
971                 {
972                         ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive,
973                                                                                  ( uint32_t ) 0,
974                                                                                  eNoAction,
975                                                                                  pxHigherPriorityTaskWoken );
976                         ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;
977                         xReturn = pdTRUE;
978                 }
979                 else
980                 {
981                         xReturn = pdFALSE;
982                 }
983         }
984         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
985
986         return xReturn;
987 }
988 /*-----------------------------------------------------------*/
989
990 BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken )
991 {
992 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
993 BaseType_t xReturn;
994 UBaseType_t uxSavedInterruptStatus;
995
996         configASSERT( pxStreamBuffer );
997
998         uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
999         {
1000                 if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )
1001                 {
1002                         ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend,
1003                                                                                  ( uint32_t ) 0,
1004                                                                                  eNoAction,
1005                                                                                  pxHigherPriorityTaskWoken );
1006                         ( pxStreamBuffer )->xTaskWaitingToSend = NULL;
1007                         xReturn = pdTRUE;
1008                 }
1009                 else
1010                 {
1011                         xReturn = pdFALSE;
1012                 }
1013         }
1014         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1015
1016         return xReturn;
1017 }
1018 /*-----------------------------------------------------------*/
1019
1020 static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount )
1021 {
1022 size_t xNextHead, xFirstLength;
1023
1024         configASSERT( xCount > ( size_t ) 0 );
1025
1026         xNextHead = pxStreamBuffer->xHead;
1027
1028         /* Calculate the number of bytes that can be added in the first write -
1029         which may be less than the total number of bytes that need to be added if
1030         the buffer will wrap back to the beginning. */
1031         xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount );
1032
1033         /* Write as many bytes as can be written in the first write. */
1034         configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength );
1035         memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1036
1037         /* If the number of bytes written was less than the number that could be
1038         written in the first write... */
1039         if( xCount > xFirstLength )
1040         {
1041                 /* ...then write the remaining bytes to the start of the buffer. */
1042                 configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength );
1043                 memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1044         }
1045         else
1046         {
1047                 mtCOVERAGE_TEST_MARKER();
1048         }
1049
1050         xNextHead += xCount;
1051         if( xNextHead >= pxStreamBuffer->xLength )
1052         {
1053                 xNextHead -= pxStreamBuffer->xLength;
1054         }
1055         else
1056         {
1057                 mtCOVERAGE_TEST_MARKER();
1058         }
1059
1060         pxStreamBuffer->xHead = xNextHead;
1061
1062         return xCount;
1063 }
1064 /*-----------------------------------------------------------*/
1065
1066 static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, uint8_t *pucData, size_t xMaxCount, size_t xBytesAvailable )
1067 {
1068 size_t xCount, xFirstLength, xNextTail;
1069
1070         /* Use the minimum of the wanted bytes and the available bytes. */
1071         xCount = configMIN( xBytesAvailable, xMaxCount );
1072
1073         if( xCount > ( size_t ) 0 )
1074         {
1075                 xNextTail = pxStreamBuffer->xTail;
1076
1077                 /* Calculate the number of bytes that can be read - which may be
1078                 less than the number wanted if the data wraps around to the start of
1079                 the buffer. */
1080                 xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount );
1081
1082                 /* Obtain the number of bytes it is possible to obtain in the first
1083                 read.  Asserts check bounds of read and write. */
1084                 configASSERT( xFirstLength <= xMaxCount );
1085                 configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength );
1086                 memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1087
1088                 /* If the total number of wanted bytes is greater than the number
1089                 that could be read in the first read... */
1090                 if( xCount > xFirstLength )
1091                 {
1092                         /*...then read the remaining bytes from the start of the buffer. */
1093                         configASSERT( xCount <= xMaxCount );
1094                         memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1095                 }
1096                 else
1097                 {
1098                         mtCOVERAGE_TEST_MARKER();
1099                 }
1100
1101                 /* Move the tail pointer to effectively remove the data read from
1102                 the buffer. */
1103                 xNextTail += xCount;
1104
1105                 if( xNextTail >= pxStreamBuffer->xLength )
1106                 {
1107                         xNextTail -= pxStreamBuffer->xLength;
1108                 }
1109
1110                 pxStreamBuffer->xTail = xNextTail;
1111         }
1112         else
1113         {
1114                 mtCOVERAGE_TEST_MARKER();
1115         }
1116
1117         return xCount;
1118 }
1119 /*-----------------------------------------------------------*/
1120
1121 static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer )
1122 {
1123 /* Returns the distance between xTail and xHead. */
1124 size_t xCount;
1125
1126         xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead;
1127         xCount -= pxStreamBuffer->xTail;
1128         if ( xCount >= pxStreamBuffer->xLength )
1129         {
1130                 xCount -= pxStreamBuffer->xLength;
1131         }
1132         else
1133         {
1134                 mtCOVERAGE_TEST_MARKER();
1135         }
1136
1137         return xCount;
1138 }
1139 /*-----------------------------------------------------------*/
1140
1141 static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
1142                                                                                   uint8_t * const pucBuffer,
1143                                                                                   size_t xBufferSizeBytes,
1144                                                                                   size_t xTriggerLevelBytes,
1145                                                                                   BaseType_t xIsMessageBuffer )
1146 {
1147         /* Assert here is deliberately writing to the entire buffer to ensure it can
1148         be written to without generating exceptions, and is setting the buffer to a
1149         known value to assist in development/debugging. */
1150         #if( configASSERT_DEFINED == 1 )
1151         {
1152                 /* The value written just has to be identifiable when looking at the
1153                 memory.  Don't use 0xA5 as that is the stack fill value and could
1154                 result in confusion as to what is actually being observed. */
1155                 const BaseType_t xWriteValue = 0x55;
1156                 configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer );
1157         }
1158         #endif
1159
1160         memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */
1161         pxStreamBuffer->pucBuffer = pucBuffer;
1162         pxStreamBuffer->xLength = xBufferSizeBytes;
1163         pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes;
1164
1165         if( xIsMessageBuffer != pdFALSE )
1166         {
1167                 pxStreamBuffer->ucFlags |= sbFLAGS_IS_MESSAGE_BUFFER;
1168         }
1169 }
1170
1171 #if ( configUSE_TRACE_FACILITY == 1 )
1172
1173         UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer )
1174         {
1175                 return ( ( StreamBuffer_t * ) xStreamBuffer )->uxStreamBufferNumber;
1176         }
1177
1178 #endif /* configUSE_TRACE_FACILITY */
1179 /*-----------------------------------------------------------*/
1180
1181 #if ( configUSE_TRACE_FACILITY == 1 )
1182
1183         void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber )
1184         {
1185                 ( ( StreamBuffer_t * ) xStreamBuffer )->uxStreamBufferNumber = uxStreamBufferNumber;
1186         }
1187
1188 #endif /* configUSE_TRACE_FACILITY */
1189 /*-----------------------------------------------------------*/
1190
1191 #if ( configUSE_TRACE_FACILITY == 1 )
1192
1193         uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer )
1194         {
1195                 return ( ( StreamBuffer_t * )xStreamBuffer )->ucFlags | sbFLAGS_IS_MESSAGE_BUFFER;
1196         }
1197
1198 #endif /* configUSE_TRACE_FACILITY */
1199 /*-----------------------------------------------------------*/