]> begriffs open source - freertos/blob - stream_buffer.c
Add SPDX-License-Identifier: MIT to MIT licensed files.
[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     xSpace -= ( size_t ) 1;
515
516     if( xSpace >= pxStreamBuffer->xLength )
517     {
518         xSpace -= pxStreamBuffer->xLength;
519     }
520     else
521     {
522         mtCOVERAGE_TEST_MARKER();
523     }
524
525     return xSpace;
526 }
527 /*-----------------------------------------------------------*/
528
529 size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer )
530 {
531     const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
532     size_t xReturn;
533
534     configASSERT( pxStreamBuffer );
535
536     xReturn = prvBytesInBuffer( pxStreamBuffer );
537     return xReturn;
538 }
539 /*-----------------------------------------------------------*/
540
541 size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
542                           const void * pvTxData,
543                           size_t xDataLengthBytes,
544                           TickType_t xTicksToWait )
545 {
546     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
547     size_t xReturn, xSpace = 0;
548     size_t xRequiredSpace = xDataLengthBytes;
549     TimeOut_t xTimeOut;
550     size_t xMaxReportedSpace = 0;
551
552     configASSERT( pvTxData );
553     configASSERT( pxStreamBuffer );
554
555     /* The maximum amount of space a stream buffer will ever report is its length
556      * minus 1. */
557     xMaxReportedSpace = pxStreamBuffer->xLength - ( size_t ) 1;
558
559     /* This send function is used to write to both message buffers and stream
560      * buffers.  If this is a message buffer then the space needed must be
561      * increased by the amount of bytes needed to store the length of the
562      * message. */
563     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
564     {
565         xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
566
567         /* Overflow? */
568         configASSERT( xRequiredSpace > xDataLengthBytes );
569
570         /* If this is a message buffer then it must be possible to write the
571          * whole message. */
572         if( xRequiredSpace > xMaxReportedSpace )
573         {
574             /* The message would not fit even if the entire buffer was empty,
575              * so don't wait for space. */
576             xTicksToWait = ( TickType_t ) 0;
577         }
578         else
579         {
580             mtCOVERAGE_TEST_MARKER();
581         }
582     }
583     else
584     {
585         /* If this is a stream buffer then it is acceptable to write only part
586          * of the message to the buffer.  Cap the length to the total length of
587          * the buffer. */
588         if( xRequiredSpace > xMaxReportedSpace )
589         {
590             xRequiredSpace = xMaxReportedSpace;
591         }
592         else
593         {
594             mtCOVERAGE_TEST_MARKER();
595         }
596     }
597
598     if( xTicksToWait != ( TickType_t ) 0 )
599     {
600         vTaskSetTimeOutState( &xTimeOut );
601
602         do
603         {
604             /* Wait until the required number of bytes are free in the message
605              * buffer. */
606             taskENTER_CRITICAL();
607             {
608                 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
609
610                 if( xSpace < xRequiredSpace )
611                 {
612                     /* Clear notification state as going to wait for space. */
613                     ( void ) xTaskNotifyStateClear( NULL );
614
615                     /* Should only be one writer. */
616                     configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL );
617                     pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle();
618                 }
619                 else
620                 {
621                     taskEXIT_CRITICAL();
622                     break;
623                 }
624             }
625             taskEXIT_CRITICAL();
626
627             traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
628             ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
629             pxStreamBuffer->xTaskWaitingToSend = NULL;
630         } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
631     }
632     else
633     {
634         mtCOVERAGE_TEST_MARKER();
635     }
636
637     if( xSpace == ( size_t ) 0 )
638     {
639         xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
640     }
641     else
642     {
643         mtCOVERAGE_TEST_MARKER();
644     }
645
646     xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
647
648     if( xReturn > ( size_t ) 0 )
649     {
650         traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn );
651
652         /* Was a task waiting for the data? */
653         if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
654         {
655             sbSEND_COMPLETED( pxStreamBuffer );
656         }
657         else
658         {
659             mtCOVERAGE_TEST_MARKER();
660         }
661     }
662     else
663     {
664         mtCOVERAGE_TEST_MARKER();
665         traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer );
666     }
667
668     return xReturn;
669 }
670 /*-----------------------------------------------------------*/
671
672 size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
673                                  const void * pvTxData,
674                                  size_t xDataLengthBytes,
675                                  BaseType_t * const pxHigherPriorityTaskWoken )
676 {
677     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
678     size_t xReturn, xSpace;
679     size_t xRequiredSpace = xDataLengthBytes;
680
681     configASSERT( pvTxData );
682     configASSERT( pxStreamBuffer );
683
684     /* This send function is used to write to both message buffers and stream
685      * buffers.  If this is a message buffer then the space needed must be
686      * increased by the amount of bytes needed to store the length of the
687      * message. */
688     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
689     {
690         xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
691     }
692     else
693     {
694         mtCOVERAGE_TEST_MARKER();
695     }
696
697     xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
698     xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
699
700     if( xReturn > ( size_t ) 0 )
701     {
702         /* Was a task waiting for the data? */
703         if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
704         {
705             sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
706         }
707         else
708         {
709             mtCOVERAGE_TEST_MARKER();
710         }
711     }
712     else
713     {
714         mtCOVERAGE_TEST_MARKER();
715     }
716
717     traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn );
718
719     return xReturn;
720 }
721 /*-----------------------------------------------------------*/
722
723 static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
724                                        const void * pvTxData,
725                                        size_t xDataLengthBytes,
726                                        size_t xSpace,
727                                        size_t xRequiredSpace )
728 {
729     size_t xNextHead = pxStreamBuffer->xHead;
730
731     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
732     {
733         /* This is a message buffer, as opposed to a stream buffer. */
734
735         if( xSpace >= xRequiredSpace )
736         {
737             /* There is enough space to write both the message length and the message
738              * itself into the buffer.  Start by writing the length of the data, the data
739              * itself will be written later in this function. */
740             xNextHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH, xNextHead );
741         }
742         else
743         {
744             /* Not enough space, so do not write data to the buffer. */
745             xDataLengthBytes = 0;
746         }
747     }
748     else
749     {
750         /* This is a stream buffer, as opposed to a message buffer, so writing a
751          * stream of bytes rather than discrete messages.  Plan to write as many
752          * bytes as possible. */
753         xDataLengthBytes = configMIN( xDataLengthBytes, xSpace );
754     }
755
756     if( xDataLengthBytes != ( size_t ) 0 )
757     {
758         /* Write the data to the buffer. */
759         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. */
760     }
761
762     return xDataLengthBytes;
763 }
764 /*-----------------------------------------------------------*/
765
766 size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
767                              void * pvRxData,
768                              size_t xBufferLengthBytes,
769                              TickType_t xTicksToWait )
770 {
771     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
772     size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
773
774     configASSERT( pvRxData );
775     configASSERT( pxStreamBuffer );
776
777     /* This receive function is used by both message buffers, which store
778      * discrete messages, and stream buffers, which store a continuous stream of
779      * bytes.  Discrete messages include an additional
780      * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
781      * message. */
782     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
783     {
784         xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
785     }
786     else
787     {
788         xBytesToStoreMessageLength = 0;
789     }
790
791     if( xTicksToWait != ( TickType_t ) 0 )
792     {
793         /* Checking if there is data and clearing the notification state must be
794          * performed atomically. */
795         taskENTER_CRITICAL();
796         {
797             xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
798
799             /* If this function was invoked by a message buffer read then
800              * xBytesToStoreMessageLength holds the number of bytes used to hold
801              * the length of the next discrete message.  If this function was
802              * invoked by a stream buffer read then xBytesToStoreMessageLength will
803              * be 0. */
804             if( xBytesAvailable <= xBytesToStoreMessageLength )
805             {
806                 /* Clear notification state as going to wait for data. */
807                 ( void ) xTaskNotifyStateClear( NULL );
808
809                 /* Should only be one reader. */
810                 configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL );
811                 pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle();
812             }
813             else
814             {
815                 mtCOVERAGE_TEST_MARKER();
816             }
817         }
818         taskEXIT_CRITICAL();
819
820         if( xBytesAvailable <= xBytesToStoreMessageLength )
821         {
822             /* Wait for data to be available. */
823             traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer );
824             ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
825             pxStreamBuffer->xTaskWaitingToReceive = NULL;
826
827             /* Recheck the data available after blocking. */
828             xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
829         }
830         else
831         {
832             mtCOVERAGE_TEST_MARKER();
833         }
834     }
835     else
836     {
837         xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
838     }
839
840     /* Whether receiving a discrete message (where xBytesToStoreMessageLength
841      * holds the number of bytes used to store the message length) or a stream of
842      * bytes (where xBytesToStoreMessageLength is zero), the number of bytes
843      * available must be greater than xBytesToStoreMessageLength to be able to
844      * read bytes from the buffer. */
845     if( xBytesAvailable > xBytesToStoreMessageLength )
846     {
847         xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable );
848
849         /* Was a task waiting for space in the buffer? */
850         if( xReceivedLength != ( size_t ) 0 )
851         {
852             traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength );
853             sbRECEIVE_COMPLETED( pxStreamBuffer );
854         }
855         else
856         {
857             mtCOVERAGE_TEST_MARKER();
858         }
859     }
860     else
861     {
862         traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer );
863         mtCOVERAGE_TEST_MARKER();
864     }
865
866     return xReceivedLength;
867 }
868 /*-----------------------------------------------------------*/
869
870 size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer )
871 {
872     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
873     size_t xReturn, xBytesAvailable;
874     configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
875
876     configASSERT( pxStreamBuffer );
877
878     /* Ensure the stream buffer is being used as a message buffer. */
879     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
880     {
881         xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
882
883         if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH )
884         {
885             /* The number of bytes available is greater than the number of bytes
886              * required to hold the length of the next message, so another message
887              * is available. */
888              ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, pxStreamBuffer->xTail );
889              xReturn = ( size_t ) xTempReturn;
890         }
891         else
892         {
893             /* The minimum amount of bytes in a message buffer is
894              * ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
895              * less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
896              * value is 0. */
897             configASSERT( xBytesAvailable == 0 );
898             xReturn = 0;
899         }
900     }
901     else
902     {
903         xReturn = 0;
904     }
905
906     return xReturn;
907 }
908 /*-----------------------------------------------------------*/
909
910 size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
911                                     void * pvRxData,
912                                     size_t xBufferLengthBytes,
913                                     BaseType_t * const pxHigherPriorityTaskWoken )
914 {
915     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
916     size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
917
918     configASSERT( pvRxData );
919     configASSERT( pxStreamBuffer );
920
921     /* This receive function is used by both message buffers, which store
922      * discrete messages, and stream buffers, which store a continuous stream of
923      * bytes.  Discrete messages include an additional
924      * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
925      * message. */
926     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
927     {
928         xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
929     }
930     else
931     {
932         xBytesToStoreMessageLength = 0;
933     }
934
935     xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
936
937     /* Whether receiving a discrete message (where xBytesToStoreMessageLength
938      * holds the number of bytes used to store the message length) or a stream of
939      * bytes (where xBytesToStoreMessageLength is zero), the number of bytes
940      * available must be greater than xBytesToStoreMessageLength to be able to
941      * read bytes from the buffer. */
942     if( xBytesAvailable > xBytesToStoreMessageLength )
943     {
944         xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable );
945
946         /* Was a task waiting for space in the buffer? */
947         if( xReceivedLength != ( size_t ) 0 )
948         {
949             sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
950         }
951         else
952         {
953             mtCOVERAGE_TEST_MARKER();
954         }
955     }
956     else
957     {
958         mtCOVERAGE_TEST_MARKER();
959     }
960
961     traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength );
962
963     return xReceivedLength;
964 }
965 /*-----------------------------------------------------------*/
966
967 static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer,
968                                         void * pvRxData,
969                                         size_t xBufferLengthBytes,
970                                         size_t xBytesAvailable )
971 {
972     size_t xCount, xNextMessageLength;
973     configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
974     size_t xNextTail = pxStreamBuffer->xTail;
975
976     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
977     {
978         /* A discrete message is being received.  First receive the length
979          * of the message. */
980         xNextTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, sbBYTES_TO_STORE_MESSAGE_LENGTH, xNextTail );
981         xNextMessageLength = ( size_t ) xTempNextMessageLength;
982
983         /* Reduce the number of bytes available by the number of bytes just
984          * read out. */
985         xBytesAvailable -= sbBYTES_TO_STORE_MESSAGE_LENGTH;
986
987         /* Check there is enough space in the buffer provided by the
988          * user. */
989         if( xNextMessageLength > xBufferLengthBytes )
990         {
991             /* The user has provided insufficient space to read the message. */
992             xNextMessageLength = 0;
993         }
994         else
995         {
996             mtCOVERAGE_TEST_MARKER();
997         }
998     }
999     else
1000     {
1001         /* A stream of bytes is being received (as opposed to a discrete
1002          * message), so read as many bytes as possible. */
1003         xNextMessageLength = xBufferLengthBytes;
1004     }
1005
1006     /* Use the minimum of the wanted bytes and the available bytes. */
1007     xCount = configMIN( xNextMessageLength, xBytesAvailable );
1008
1009     if( xCount != ( size_t ) 0 )
1010     {
1011         /* Read the actual data and update the tail to mark the data as officially consumed. */
1012         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. */
1013     }
1014
1015     return xCount;
1016 }
1017 /*-----------------------------------------------------------*/
1018
1019 BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer )
1020 {
1021     const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1022     BaseType_t xReturn;
1023     size_t xTail;
1024
1025     configASSERT( pxStreamBuffer );
1026
1027     /* True if no bytes are available. */
1028     xTail = pxStreamBuffer->xTail;
1029
1030     if( pxStreamBuffer->xHead == xTail )
1031     {
1032         xReturn = pdTRUE;
1033     }
1034     else
1035     {
1036         xReturn = pdFALSE;
1037     }
1038
1039     return xReturn;
1040 }
1041 /*-----------------------------------------------------------*/
1042
1043 BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer )
1044 {
1045     BaseType_t xReturn;
1046     size_t xBytesToStoreMessageLength;
1047     const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1048
1049     configASSERT( pxStreamBuffer );
1050
1051     /* This generic version of the receive function is used by both message
1052      * buffers, which store discrete messages, and stream buffers, which store a
1053      * continuous stream of bytes.  Discrete messages include an additional
1054      * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
1055     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
1056     {
1057         xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
1058     }
1059     else
1060     {
1061         xBytesToStoreMessageLength = 0;
1062     }
1063
1064     /* True if the available space equals zero. */
1065     if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength )
1066     {
1067         xReturn = pdTRUE;
1068     }
1069     else
1070     {
1071         xReturn = pdFALSE;
1072     }
1073
1074     return xReturn;
1075 }
1076 /*-----------------------------------------------------------*/
1077
1078 BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
1079                                               BaseType_t * pxHigherPriorityTaskWoken )
1080 {
1081     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1082     BaseType_t xReturn;
1083     UBaseType_t uxSavedInterruptStatus;
1084
1085     configASSERT( pxStreamBuffer );
1086
1087     uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
1088     {
1089         if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )
1090         {
1091             ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive,
1092                                          ( uint32_t ) 0,
1093                                          eNoAction,
1094                                          pxHigherPriorityTaskWoken );
1095             ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;
1096             xReturn = pdTRUE;
1097         }
1098         else
1099         {
1100             xReturn = pdFALSE;
1101         }
1102     }
1103     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1104
1105     return xReturn;
1106 }
1107 /*-----------------------------------------------------------*/
1108
1109 BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
1110                                                  BaseType_t * pxHigherPriorityTaskWoken )
1111 {
1112     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1113     BaseType_t xReturn;
1114     UBaseType_t uxSavedInterruptStatus;
1115
1116     configASSERT( pxStreamBuffer );
1117
1118     uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
1119     {
1120         if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )
1121         {
1122             ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend,
1123                                          ( uint32_t ) 0,
1124                                          eNoAction,
1125                                          pxHigherPriorityTaskWoken );
1126             ( pxStreamBuffer )->xTaskWaitingToSend = NULL;
1127             xReturn = pdTRUE;
1128         }
1129         else
1130         {
1131             xReturn = pdFALSE;
1132         }
1133     }
1134     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1135
1136     return xReturn;
1137 }
1138 /*-----------------------------------------------------------*/
1139
1140 static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer,
1141                                      const uint8_t * pucData,
1142                                      size_t xCount,
1143                                      size_t xHead )
1144 {
1145     size_t xFirstLength;
1146
1147     configASSERT( xCount > ( size_t ) 0 );
1148
1149     /* Calculate the number of bytes that can be added in the first write -
1150      * which may be less than the total number of bytes that need to be added if
1151      * the buffer will wrap back to the beginning. */
1152     xFirstLength = configMIN( pxStreamBuffer->xLength - xHead, xCount );
1153
1154     /* Write as many bytes as can be written in the first write. */
1155     configASSERT( ( xHead + xFirstLength ) <= pxStreamBuffer->xLength );
1156     ( void ) memcpy( ( void * ) ( &( pxStreamBuffer->pucBuffer[ xHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1157
1158     /* If the number of bytes written was less than the number that could be
1159      * written in the first write... */
1160     if( xCount > xFirstLength )
1161     {
1162         /* ...then write the remaining bytes to the start of the buffer. */
1163         configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength );
1164         ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1165     }
1166     else
1167     {
1168         mtCOVERAGE_TEST_MARKER();
1169     }
1170
1171     xHead += xCount;
1172
1173     if( xHead >= pxStreamBuffer->xLength )
1174     {
1175         xHead -= pxStreamBuffer->xLength;
1176     }
1177     else
1178     {
1179         mtCOVERAGE_TEST_MARKER();
1180     }
1181
1182     return xHead;
1183 }
1184 /*-----------------------------------------------------------*/
1185
1186 static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer,
1187                                       uint8_t * pucData,
1188                                       size_t xCount,
1189                                       size_t xTail )
1190 {
1191     size_t xFirstLength;
1192
1193     configASSERT( xCount != ( size_t ) 0 );
1194
1195     /* Calculate the number of bytes that can be read - which may be
1196      * less than the number wanted if the data wraps around to the start of
1197      * the buffer. */
1198     xFirstLength = configMIN( pxStreamBuffer->xLength - xTail, xCount );
1199
1200     /* Obtain the number of bytes it is possible to obtain in the first
1201      * read.  Asserts check bounds of read and write. */
1202     configASSERT( xFirstLength <= xCount );
1203     configASSERT( ( xTail + xFirstLength ) <= pxStreamBuffer->xLength );
1204     ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1205
1206     /* If the total number of wanted bytes is greater than the number
1207      * that could be read in the first read... */
1208     if( xCount > xFirstLength )
1209     {
1210         /* ...then read the remaining bytes from the start of the buffer. */
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 the buffer. */
1219     xTail += xCount;
1220
1221     if( xTail >= pxStreamBuffer->xLength )
1222     {
1223         xTail -= pxStreamBuffer->xLength;
1224     }
1225
1226     return xTail;
1227 }
1228 /*-----------------------------------------------------------*/
1229
1230 static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer )
1231 {
1232 /* Returns the distance between xTail and xHead. */
1233     size_t xCount;
1234
1235     xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead;
1236     xCount -= pxStreamBuffer->xTail;
1237
1238     if( xCount >= pxStreamBuffer->xLength )
1239     {
1240         xCount -= pxStreamBuffer->xLength;
1241     }
1242     else
1243     {
1244         mtCOVERAGE_TEST_MARKER();
1245     }
1246
1247     return xCount;
1248 }
1249 /*-----------------------------------------------------------*/
1250
1251 static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
1252                                           uint8_t * const pucBuffer,
1253                                           size_t xBufferSizeBytes,
1254                                           size_t xTriggerLevelBytes,
1255                                           uint8_t ucFlags )
1256 {
1257     /* Assert here is deliberately writing to the entire buffer to ensure it can
1258      * be written to without generating exceptions, and is setting the buffer to a
1259      * known value to assist in development/debugging. */
1260     #if ( configASSERT_DEFINED == 1 )
1261         {
1262             /* The value written just has to be identifiable when looking at the
1263              * memory.  Don't use 0xA5 as that is the stack fill value and could
1264              * result in confusion as to what is actually being observed. */
1265             const BaseType_t xWriteValue = 0x55;
1266             configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer );
1267         } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */
1268     #endif
1269
1270     ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */
1271     pxStreamBuffer->pucBuffer = pucBuffer;
1272     pxStreamBuffer->xLength = xBufferSizeBytes;
1273     pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes;
1274     pxStreamBuffer->ucFlags = ucFlags;
1275 }
1276
1277 #if ( configUSE_TRACE_FACILITY == 1 )
1278
1279     UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer )
1280     {
1281         return xStreamBuffer->uxStreamBufferNumber;
1282     }
1283
1284 #endif /* configUSE_TRACE_FACILITY */
1285 /*-----------------------------------------------------------*/
1286
1287 #if ( configUSE_TRACE_FACILITY == 1 )
1288
1289     void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer,
1290                                              UBaseType_t uxStreamBufferNumber )
1291     {
1292         xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
1293     }
1294
1295 #endif /* configUSE_TRACE_FACILITY */
1296 /*-----------------------------------------------------------*/
1297
1298 #if ( configUSE_TRACE_FACILITY == 1 )
1299
1300     uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer )
1301     {
1302         return( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER );
1303     }
1304
1305 #endif /* configUSE_TRACE_FACILITY */
1306 /*-----------------------------------------------------------*/