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