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