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