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