]> begriffs open source - freertos/blob - stream_buffer.c
Update the memory alignment within the Cortex-R5 port asm code (#1023)
[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 <string.h>
31
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
33  * all the API functions to use the MPU wrappers.  That should only be done when
34  * task.h is included from an application file. */
35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
36
37 /* FreeRTOS includes. */
38 #include "FreeRTOS.h"
39 #include "task.h"
40 #include "stream_buffer.h"
41
42 #if ( configUSE_TASK_NOTIFICATIONS != 1 )
43     #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c
44 #endif
45
46 #if ( INCLUDE_xTaskGetCurrentTaskHandle != 1 )
47     #error INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 to build stream_buffer.c
48 #endif
49
50 /* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
51  * for the header files above, but not in this file, in order to generate the
52  * correct privileged Vs unprivileged linkage and placement. */
53 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
54
55 /* This entire source file will be skipped if the application is not configured
56  * to include stream buffer functionality. This #if is closed at the very bottom
57  * of this file. If you want to include stream buffers then ensure
58  * configUSE_STREAM_BUFFERS is set to 1 in FreeRTOSConfig.h. */
59 #if ( configUSE_STREAM_BUFFERS == 1 )
60
61 /* If the user has not provided application specific Rx notification macros,
62  * or #defined the notification macros away, then provide default implementations
63  * that uses task notifications. */
64     #ifndef sbRECEIVE_COMPLETED
65         #define sbRECEIVE_COMPLETED( pxStreamBuffer )                                 \
66     do                                                                                \
67     {                                                                                 \
68         vTaskSuspendAll();                                                            \
69         {                                                                             \
70             if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )                      \
71             {                                                                         \
72                 ( void ) xTaskNotifyIndexed( ( pxStreamBuffer )->xTaskWaitingToSend,  \
73                                              ( pxStreamBuffer )->uxNotificationIndex, \
74                                              ( uint32_t ) 0,                          \
75                                              eNoAction );                             \
76                 ( pxStreamBuffer )->xTaskWaitingToSend = NULL;                        \
77             }                                                                         \
78         }                                                                             \
79         ( void ) xTaskResumeAll();                                                    \
80     } while( 0 )
81     #endif /* sbRECEIVE_COMPLETED */
82
83 /* If user has provided a per-instance receive complete callback, then
84  * invoke the callback else use the receive complete macro which is provided by default for all instances.
85  */
86     #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
87         #define prvRECEIVE_COMPLETED( pxStreamBuffer )                                           \
88     do {                                                                                         \
89         if( ( pxStreamBuffer )->pxReceiveCompletedCallback != NULL )                             \
90         {                                                                                        \
91             ( pxStreamBuffer )->pxReceiveCompletedCallback( ( pxStreamBuffer ), pdFALSE, NULL ); \
92         }                                                                                        \
93         else                                                                                     \
94         {                                                                                        \
95             sbRECEIVE_COMPLETED( ( pxStreamBuffer ) );                                           \
96         }                                                                                        \
97     } while( 0 )
98     #else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
99         #define prvRECEIVE_COMPLETED( pxStreamBuffer )    sbRECEIVE_COMPLETED( ( pxStreamBuffer ) )
100     #endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
101
102     #ifndef sbRECEIVE_COMPLETED_FROM_ISR
103         #define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer,                                \
104                                               pxHigherPriorityTaskWoken )                    \
105     do {                                                                                     \
106         UBaseType_t uxSavedInterruptStatus;                                                  \
107                                                                                              \
108         uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();                              \
109         {                                                                                    \
110             if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )                             \
111             {                                                                                \
112                 ( void ) xTaskNotifyIndexedFromISR( ( pxStreamBuffer )->xTaskWaitingToSend,  \
113                                                     ( pxStreamBuffer )->uxNotificationIndex, \
114                                                     ( uint32_t ) 0,                          \
115                                                     eNoAction,                               \
116                                                     ( pxHigherPriorityTaskWoken ) );         \
117                 ( pxStreamBuffer )->xTaskWaitingToSend = NULL;                               \
118             }                                                                                \
119         }                                                                                    \
120         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );                                \
121     } while( 0 )
122     #endif /* sbRECEIVE_COMPLETED_FROM_ISR */
123
124     #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
125         #define prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer,                                                           \
126                                                pxHigherPriorityTaskWoken )                                               \
127     do {                                                                                                                 \
128         if( ( pxStreamBuffer )->pxReceiveCompletedCallback != NULL )                                                     \
129         {                                                                                                                \
130             ( pxStreamBuffer )->pxReceiveCompletedCallback( ( pxStreamBuffer ), pdTRUE, ( pxHigherPriorityTaskWoken ) ); \
131         }                                                                                                                \
132         else                                                                                                             \
133         {                                                                                                                \
134             sbRECEIVE_COMPLETED_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) );                           \
135         }                                                                                                                \
136     } while( 0 )
137     #else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
138         #define prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
139     sbRECEIVE_COMPLETED_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) )
140     #endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
141
142 /* If the user has not provided an application specific Tx notification macro,
143  * or #defined the notification macro away, then provide a default
144  * implementation that uses task notifications.
145  */
146     #ifndef sbSEND_COMPLETED
147         #define sbSEND_COMPLETED( pxStreamBuffer )                                  \
148     vTaskSuspendAll();                                                              \
149     {                                                                               \
150         if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )                     \
151         {                                                                           \
152             ( void ) xTaskNotifyIndexed( ( pxStreamBuffer )->xTaskWaitingToReceive, \
153                                          ( pxStreamBuffer )->uxNotificationIndex,   \
154                                          ( uint32_t ) 0,                            \
155                                          eNoAction );                               \
156             ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;                       \
157         }                                                                           \
158     }                                                                               \
159     ( void ) xTaskResumeAll()
160     #endif /* sbSEND_COMPLETED */
161
162 /* If user has provided a per-instance send completed callback, then
163  * invoke the callback else use the send complete macro which is provided by default for all instances.
164  */
165     #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
166         #define prvSEND_COMPLETED( pxStreamBuffer )                                           \
167     do {                                                                                      \
168         if( ( pxStreamBuffer )->pxSendCompletedCallback != NULL )                             \
169         {                                                                                     \
170             ( pxStreamBuffer )->pxSendCompletedCallback( ( pxStreamBuffer ), pdFALSE, NULL ); \
171         }                                                                                     \
172         else                                                                                  \
173         {                                                                                     \
174             sbSEND_COMPLETED( ( pxStreamBuffer ) );                                           \
175         }                                                                                     \
176     } while( 0 )
177     #else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
178         #define prvSEND_COMPLETED( pxStreamBuffer )    sbSEND_COMPLETED( ( pxStreamBuffer ) )
179     #endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
180
181
182     #ifndef sbSEND_COMPLETE_FROM_ISR
183         #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken )          \
184     do {                                                                                       \
185         UBaseType_t uxSavedInterruptStatus;                                                    \
186                                                                                                \
187         uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();                                \
188         {                                                                                      \
189             if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )                            \
190             {                                                                                  \
191                 ( void ) xTaskNotifyIndexedFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, \
192                                                     ( pxStreamBuffer )->uxNotificationIndex,   \
193                                                     ( uint32_t ) 0,                            \
194                                                     eNoAction,                                 \
195                                                     ( pxHigherPriorityTaskWoken ) );           \
196                 ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;                              \
197             }                                                                                  \
198         }                                                                                      \
199         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );                                  \
200     } while( 0 )
201     #endif /* sbSEND_COMPLETE_FROM_ISR */
202
203
204     #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
205         #define prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken )                                \
206     do {                                                                                                              \
207         if( ( pxStreamBuffer )->pxSendCompletedCallback != NULL )                                                     \
208         {                                                                                                             \
209             ( pxStreamBuffer )->pxSendCompletedCallback( ( pxStreamBuffer ), pdTRUE, ( pxHigherPriorityTaskWoken ) ); \
210         }                                                                                                             \
211         else                                                                                                          \
212         {                                                                                                             \
213             sbSEND_COMPLETE_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) );                            \
214         }                                                                                                             \
215     } while( 0 )
216     #else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
217         #define prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
218     sbSEND_COMPLETE_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) )
219     #endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
220
221 /* The number of bytes used to hold the length of a message in the buffer. */
222     #define sbBYTES_TO_STORE_MESSAGE_LENGTH    ( sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) )
223
224 /* Bits stored in the ucFlags field of the stream buffer. */
225     #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. */
226     #define sbFLAGS_IS_STATICALLY_ALLOCATED    ( ( uint8_t ) 2 ) /* Set if the stream buffer was created using statically allocated memory. */
227
228 /*-----------------------------------------------------------*/
229
230 /* Structure that hold state information on the buffer. */
231 typedef struct StreamBufferDef_t
232 {
233     volatile size_t xTail;                       /* Index to the next item to read within the buffer. */
234     volatile size_t xHead;                       /* Index to the next item to write within the buffer. */
235     size_t xLength;                              /* The length of the buffer pointed to by pucBuffer. */
236     size_t xTriggerLevelBytes;                   /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */
237     volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */
238     volatile TaskHandle_t xTaskWaitingToSend;    /* Holds the handle of a task waiting to send data to a message buffer that is full. */
239     uint8_t * pucBuffer;                         /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */
240     uint8_t ucFlags;
241
242     #if ( configUSE_TRACE_FACILITY == 1 )
243         UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */
244     #endif
245
246     #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
247         StreamBufferCallbackFunction_t pxSendCompletedCallback;    /* Optional callback called on send complete. sbSEND_COMPLETED is called if this is NULL. */
248         StreamBufferCallbackFunction_t pxReceiveCompletedCallback; /* Optional callback called on receive complete.  sbRECEIVE_COMPLETED is called if this is NULL. */
249     #endif
250     UBaseType_t uxNotificationIndex;                               /* The index we are using for notification, by default tskDEFAULT_INDEX_TO_NOTIFY. */
251 } StreamBuffer_t;
252
253 /*
254  * The number of bytes available to be read from the buffer.
255  */
256 static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION;
257
258 /*
259  * Add xCount bytes from pucData into the pxStreamBuffer's data storage area.
260  * This function does not update the buffer's xHead pointer, so multiple writes
261  * may be chained together "atomically". This is useful for Message Buffers where
262  * the length and data bytes are written in two separate chunks, and we don't want
263  * the reader to see the buffer as having grown until after all data is copied over.
264  * This function takes a custom xHead value to indicate where to write to (necessary
265  * for chaining) and returns the the resulting xHead position.
266  * To mark the write as complete, manually set the buffer's xHead field with the
267  * returned xHead from this function.
268  */
269 static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer,
270                                      const uint8_t * pucData,
271                                      size_t xCount,
272                                      size_t xHead ) PRIVILEGED_FUNCTION;
273
274 /*
275  * If the stream buffer is being used as a message buffer, then reads an entire
276  * message out of the buffer.  If the stream buffer is being used as a stream
277  * buffer then read as many bytes as possible from the buffer.
278  * prvReadBytesFromBuffer() is called to actually extract the bytes from the
279  * buffer's data storage area.
280  */
281 static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer,
282                                         void * pvRxData,
283                                         size_t xBufferLengthBytes,
284                                         size_t xBytesAvailable ) PRIVILEGED_FUNCTION;
285
286 /*
287  * If the stream buffer is being used as a message buffer, then writes an entire
288  * message to the buffer.  If the stream buffer is being used as a stream
289  * buffer then write as many bytes as possible to the buffer.
290  * prvWriteBytestoBuffer() is called to actually send the bytes to the buffer's
291  * data storage area.
292  */
293 static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
294                                        const void * pvTxData,
295                                        size_t xDataLengthBytes,
296                                        size_t xSpace,
297                                        size_t xRequiredSpace ) PRIVILEGED_FUNCTION;
298
299 /*
300  * Copies xCount bytes from the pxStreamBuffer's data storage area to pucData.
301  * This function does not update the buffer's xTail pointer, so multiple reads
302  * may be chained together "atomically". This is useful for Message Buffers where
303  * the length and data bytes are read in two separate chunks, and we don't want
304  * the writer to see the buffer as having more free space until after all data is
305  * copied over, especially if we have to abort the read due to insufficient receiving space.
306  * This function takes a custom xTail value to indicate where to read from (necessary
307  * for chaining) and returns the the resulting xTail position.
308  * To mark the read as complete, manually set the buffer's xTail field with the
309  * returned xTail from this function.
310  */
311 static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer,
312                                       uint8_t * pucData,
313                                       size_t xCount,
314                                       size_t xTail ) PRIVILEGED_FUNCTION;
315
316 /*
317  * Called by both pxStreamBufferCreate() and pxStreamBufferCreateStatic() to
318  * initialise the members of the newly created stream buffer structure.
319  */
320 static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
321                                           uint8_t * const pucBuffer,
322                                           size_t xBufferSizeBytes,
323                                           size_t xTriggerLevelBytes,
324                                           uint8_t ucFlags,
325                                           StreamBufferCallbackFunction_t pxSendCompletedCallback,
326                                           StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
327
328 /*-----------------------------------------------------------*/
329     #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
330     StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
331                                                      size_t xTriggerLevelBytes,
332                                                      BaseType_t xIsMessageBuffer,
333                                                      StreamBufferCallbackFunction_t pxSendCompletedCallback,
334                                                      StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
335     {
336         void * pvAllocatedMemory;
337         uint8_t ucFlags;
338
339         traceENTER_xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback );
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         if( xIsMessageBuffer == pdTRUE )
346         {
347             /* Is a message buffer but not statically allocated. */
348             ucFlags = sbFLAGS_IS_MESSAGE_BUFFER;
349             configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
350         }
351         else
352         {
353             /* Not a message buffer and not statically allocated. */
354             ucFlags = 0;
355             configASSERT( xBufferSizeBytes > 0 );
356         }
357
358         configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
359
360         /* A trigger level of 0 would cause a waiting task to unblock even when
361          * the buffer was empty. */
362         if( xTriggerLevelBytes == ( size_t ) 0 )
363         {
364             xTriggerLevelBytes = ( size_t ) 1;
365         }
366
367         /* A stream buffer requires a StreamBuffer_t structure and a buffer.
368          * Both are allocated in a single call to pvPortMalloc().  The
369          * StreamBuffer_t structure is placed at the start of the allocated memory
370          * and the buffer follows immediately after.  The requested size is
371          * incremented so the free space is returned as the user would expect -
372          * this is a quirk of the implementation that means otherwise the free
373          * space would be reported as one byte smaller than would be logically
374          * expected. */
375         if( xBufferSizeBytes < ( xBufferSizeBytes + 1U + sizeof( StreamBuffer_t ) ) )
376         {
377             xBufferSizeBytes++;
378             pvAllocatedMemory = pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) );
379         }
380         else
381         {
382             pvAllocatedMemory = NULL;
383         }
384
385         if( pvAllocatedMemory != NULL )
386         {
387             /* MISRA Ref 11.5.1 [Malloc memory assignment] */
388             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
389             /* coverity[misra_c_2012_rule_11_5_violation] */
390             prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pvAllocatedMemory,                         /* Structure at the start of the allocated memory. */
391                                                                                                           /* MISRA Ref 11.5.1 [Malloc memory assignment] */
392                                                                                                           /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
393                                                                                                           /* coverity[misra_c_2012_rule_11_5_violation] */
394                                           ( ( uint8_t * ) pvAllocatedMemory ) + sizeof( StreamBuffer_t ), /* Storage area follows. */
395                                           xBufferSizeBytes,
396                                           xTriggerLevelBytes,
397                                           ucFlags,
398                                           pxSendCompletedCallback,
399                                           pxReceiveCompletedCallback );
400
401             traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pvAllocatedMemory ), xIsMessageBuffer );
402         }
403         else
404         {
405             traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer );
406         }
407
408         traceRETURN_xStreamBufferGenericCreate( pvAllocatedMemory );
409
410         /* MISRA Ref 11.5.1 [Malloc memory assignment] */
411         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
412         /* coverity[misra_c_2012_rule_11_5_violation] */
413         return ( StreamBufferHandle_t ) pvAllocatedMemory;
414     }
415     #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
416 /*-----------------------------------------------------------*/
417
418     #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
419
420     StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
421                                                            size_t xTriggerLevelBytes,
422                                                            BaseType_t xIsMessageBuffer,
423                                                            uint8_t * const pucStreamBufferStorageArea,
424                                                            StaticStreamBuffer_t * const pxStaticStreamBuffer,
425                                                            StreamBufferCallbackFunction_t pxSendCompletedCallback,
426                                                            StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
427     {
428         /* MISRA Ref 11.3.1 [Misaligned access] */
429         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
430         /* coverity[misra_c_2012_rule_11_3_violation] */
431         StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer;
432         StreamBufferHandle_t xReturn;
433         uint8_t ucFlags;
434
435         traceENTER_xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback );
436
437         configASSERT( pucStreamBufferStorageArea );
438         configASSERT( pxStaticStreamBuffer );
439         configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
440
441         /* A trigger level of 0 would cause a waiting task to unblock even when
442          * the buffer was empty. */
443         if( xTriggerLevelBytes == ( size_t ) 0 )
444         {
445             xTriggerLevelBytes = ( size_t ) 1;
446         }
447
448         /* In case the stream buffer is going to be used as a message buffer
449          * (that is, it will hold discrete messages with a little meta data that
450          * says how big the next message is) check the buffer will be large enough
451          * to hold at least one message. */
452
453         if( xIsMessageBuffer != pdFALSE )
454         {
455             /* Statically allocated message buffer. */
456             ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED;
457             configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
458         }
459         else
460         {
461             /* Statically allocated stream buffer. */
462             ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED;
463         }
464
465         #if ( configASSERT_DEFINED == 1 )
466         {
467             /* Sanity check that the size of the structure used to declare a
468              * variable of type StaticStreamBuffer_t equals the size of the real
469              * message buffer structure. */
470             volatile size_t xSize = sizeof( StaticStreamBuffer_t );
471             configASSERT( xSize == sizeof( StreamBuffer_t ) );
472         }
473         #endif /* configASSERT_DEFINED */
474
475         if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) )
476         {
477             prvInitialiseNewStreamBuffer( pxStreamBuffer,
478                                           pucStreamBufferStorageArea,
479                                           xBufferSizeBytes,
480                                           xTriggerLevelBytes,
481                                           ucFlags,
482                                           pxSendCompletedCallback,
483                                           pxReceiveCompletedCallback );
484
485             /* Remember this was statically allocated in case it is ever deleted
486              * again. */
487             pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED;
488
489             traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer );
490
491             /* MISRA Ref 11.3.1 [Misaligned access] */
492             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
493             /* coverity[misra_c_2012_rule_11_3_violation] */
494             xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer;
495         }
496         else
497         {
498             xReturn = NULL;
499             traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer );
500         }
501
502         traceRETURN_xStreamBufferGenericCreateStatic( xReturn );
503
504         return xReturn;
505     }
506     #endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
507 /*-----------------------------------------------------------*/
508
509     #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
510     BaseType_t xStreamBufferGetStaticBuffers( StreamBufferHandle_t xStreamBuffer,
511                                               uint8_t ** ppucStreamBufferStorageArea,
512                                               StaticStreamBuffer_t ** ppxStaticStreamBuffer )
513     {
514         BaseType_t xReturn;
515         StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
516
517         traceENTER_xStreamBufferGetStaticBuffers( xStreamBuffer, ppucStreamBufferStorageArea, ppxStaticStreamBuffer );
518
519         configASSERT( pxStreamBuffer );
520         configASSERT( ppucStreamBufferStorageArea );
521         configASSERT( ppxStaticStreamBuffer );
522
523         if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) != ( uint8_t ) 0 )
524         {
525             *ppucStreamBufferStorageArea = pxStreamBuffer->pucBuffer;
526             /* MISRA Ref 11.3.1 [Misaligned access] */
527             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */
528             /* coverity[misra_c_2012_rule_11_3_violation] */
529             *ppxStaticStreamBuffer = ( StaticStreamBuffer_t * ) pxStreamBuffer;
530             xReturn = pdTRUE;
531         }
532         else
533         {
534             xReturn = pdFALSE;
535         }
536
537         traceRETURN_xStreamBufferGetStaticBuffers( xReturn );
538
539         return xReturn;
540     }
541     #endif /* configSUPPORT_STATIC_ALLOCATION */
542 /*-----------------------------------------------------------*/
543
544 void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer )
545 {
546     StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
547
548     traceENTER_vStreamBufferDelete( xStreamBuffer );
549
550     configASSERT( pxStreamBuffer );
551
552     traceSTREAM_BUFFER_DELETE( xStreamBuffer );
553
554     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE )
555     {
556         #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
557         {
558             /* Both the structure and the buffer were allocated using a single call
559             * to pvPortMalloc(), hence only one call to vPortFree() is required. */
560             vPortFree( ( void * ) pxStreamBuffer );
561         }
562         #else
563         {
564             /* Should not be possible to get here, ucFlags must be corrupt.
565              * Force an assert. */
566             configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 );
567         }
568         #endif
569     }
570     else
571     {
572         /* The structure and buffer were not allocated dynamically and cannot be
573          * freed - just scrub the structure so future use will assert. */
574         ( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) );
575     }
576
577     traceRETURN_vStreamBufferDelete();
578 }
579 /*-----------------------------------------------------------*/
580
581 BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
582 {
583     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
584     BaseType_t xReturn = pdFAIL;
585     StreamBufferCallbackFunction_t pxSendCallback = NULL, pxReceiveCallback = NULL;
586
587     #if ( configUSE_TRACE_FACILITY == 1 )
588         UBaseType_t uxStreamBufferNumber;
589     #endif
590
591     traceENTER_xStreamBufferReset( xStreamBuffer );
592
593     configASSERT( pxStreamBuffer );
594
595     #if ( configUSE_TRACE_FACILITY == 1 )
596     {
597         /* Store the stream buffer number so it can be restored after the
598          * reset. */
599         uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber;
600     }
601     #endif
602
603     /* Can only reset a message buffer if there are no tasks blocked on it. */
604     taskENTER_CRITICAL();
605     {
606         if( ( pxStreamBuffer->xTaskWaitingToReceive == NULL ) && ( pxStreamBuffer->xTaskWaitingToSend == NULL ) )
607         {
608             #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
609             {
610                 pxSendCallback = pxStreamBuffer->pxSendCompletedCallback;
611                 pxReceiveCallback = pxStreamBuffer->pxReceiveCompletedCallback;
612             }
613             #endif
614
615             prvInitialiseNewStreamBuffer( pxStreamBuffer,
616                                           pxStreamBuffer->pucBuffer,
617                                           pxStreamBuffer->xLength,
618                                           pxStreamBuffer->xTriggerLevelBytes,
619                                           pxStreamBuffer->ucFlags,
620                                           pxSendCallback,
621                                           pxReceiveCallback );
622
623             #if ( configUSE_TRACE_FACILITY == 1 )
624             {
625                 pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
626             }
627             #endif
628
629             traceSTREAM_BUFFER_RESET( xStreamBuffer );
630
631             xReturn = pdPASS;
632         }
633     }
634     taskEXIT_CRITICAL();
635
636     traceRETURN_xStreamBufferReset( xReturn );
637
638     return xReturn;
639 }
640 /*-----------------------------------------------------------*/
641
642 BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
643                                          size_t xTriggerLevel )
644 {
645     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
646     BaseType_t xReturn;
647
648     traceENTER_xStreamBufferSetTriggerLevel( xStreamBuffer, xTriggerLevel );
649
650     configASSERT( pxStreamBuffer );
651
652     /* It is not valid for the trigger level to be 0. */
653     if( xTriggerLevel == ( size_t ) 0 )
654     {
655         xTriggerLevel = ( size_t ) 1;
656     }
657
658     /* The trigger level is the number of bytes that must be in the stream
659      * buffer before a task that is waiting for data is unblocked. */
660     if( xTriggerLevel < pxStreamBuffer->xLength )
661     {
662         pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel;
663         xReturn = pdPASS;
664     }
665     else
666     {
667         xReturn = pdFALSE;
668     }
669
670     traceRETURN_xStreamBufferSetTriggerLevel( xReturn );
671
672     return xReturn;
673 }
674 /*-----------------------------------------------------------*/
675
676 size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer )
677 {
678     const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
679     size_t xSpace;
680     size_t xOriginalTail;
681
682     traceENTER_xStreamBufferSpacesAvailable( xStreamBuffer );
683
684     configASSERT( pxStreamBuffer );
685
686     /* The code below reads xTail and then xHead.  This is safe if the stream
687      * buffer is updated once between the two reads - but not if the stream buffer
688      * is updated more than once between the two reads - hence the loop. */
689     do
690     {
691         xOriginalTail = pxStreamBuffer->xTail;
692         xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail;
693         xSpace -= pxStreamBuffer->xHead;
694     } while( xOriginalTail != pxStreamBuffer->xTail );
695
696     xSpace -= ( size_t ) 1;
697
698     if( xSpace >= pxStreamBuffer->xLength )
699     {
700         xSpace -= pxStreamBuffer->xLength;
701     }
702     else
703     {
704         mtCOVERAGE_TEST_MARKER();
705     }
706
707     traceRETURN_xStreamBufferSpacesAvailable( xSpace );
708
709     return xSpace;
710 }
711 /*-----------------------------------------------------------*/
712
713 size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer )
714 {
715     const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
716     size_t xReturn;
717
718     traceENTER_xStreamBufferBytesAvailable( xStreamBuffer );
719
720     configASSERT( pxStreamBuffer );
721
722     xReturn = prvBytesInBuffer( pxStreamBuffer );
723
724     traceRETURN_xStreamBufferBytesAvailable( xReturn );
725
726     return xReturn;
727 }
728 /*-----------------------------------------------------------*/
729
730 size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
731                           const void * pvTxData,
732                           size_t xDataLengthBytes,
733                           TickType_t xTicksToWait )
734 {
735     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
736     size_t xReturn, xSpace = 0;
737     size_t xRequiredSpace = xDataLengthBytes;
738     TimeOut_t xTimeOut;
739     size_t xMaxReportedSpace = 0;
740
741     traceENTER_xStreamBufferSend( xStreamBuffer, pvTxData, xDataLengthBytes, xTicksToWait );
742
743     configASSERT( pvTxData );
744     configASSERT( pxStreamBuffer );
745
746     /* The maximum amount of space a stream buffer will ever report is its length
747      * minus 1. */
748     xMaxReportedSpace = pxStreamBuffer->xLength - ( size_t ) 1;
749
750     /* This send function is used to write to both message buffers and stream
751      * buffers.  If this is a message buffer then the space needed must be
752      * increased by the amount of bytes needed to store the length of the
753      * message. */
754     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
755     {
756         xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
757
758         /* Overflow? */
759         configASSERT( xRequiredSpace > xDataLengthBytes );
760
761         /* If this is a message buffer then it must be possible to write the
762          * whole message. */
763         if( xRequiredSpace > xMaxReportedSpace )
764         {
765             /* The message would not fit even if the entire buffer was empty,
766              * so don't wait for space. */
767             xTicksToWait = ( TickType_t ) 0;
768         }
769         else
770         {
771             mtCOVERAGE_TEST_MARKER();
772         }
773     }
774     else
775     {
776         /* If this is a stream buffer then it is acceptable to write only part
777          * of the message to the buffer.  Cap the length to the total length of
778          * the buffer. */
779         if( xRequiredSpace > xMaxReportedSpace )
780         {
781             xRequiredSpace = xMaxReportedSpace;
782         }
783         else
784         {
785             mtCOVERAGE_TEST_MARKER();
786         }
787     }
788
789     if( xTicksToWait != ( TickType_t ) 0 )
790     {
791         vTaskSetTimeOutState( &xTimeOut );
792
793         do
794         {
795             /* Wait until the required number of bytes are free in the message
796              * buffer. */
797             taskENTER_CRITICAL();
798             {
799                 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
800
801                 if( xSpace < xRequiredSpace )
802                 {
803                     /* Clear notification state as going to wait for space. */
804                     ( void ) xTaskNotifyStateClearIndexed( NULL, pxStreamBuffer->uxNotificationIndex );
805
806                     /* Should only be one writer. */
807                     configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL );
808                     pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle();
809                 }
810                 else
811                 {
812                     taskEXIT_CRITICAL();
813                     break;
814                 }
815             }
816             taskEXIT_CRITICAL();
817
818             traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
819             ( void ) xTaskNotifyWaitIndexed( pxStreamBuffer->uxNotificationIndex, ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
820             pxStreamBuffer->xTaskWaitingToSend = NULL;
821         } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
822     }
823     else
824     {
825         mtCOVERAGE_TEST_MARKER();
826     }
827
828     if( xSpace == ( size_t ) 0 )
829     {
830         xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
831     }
832     else
833     {
834         mtCOVERAGE_TEST_MARKER();
835     }
836
837     xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
838
839     if( xReturn > ( size_t ) 0 )
840     {
841         traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn );
842
843         /* Was a task waiting for the data? */
844         if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
845         {
846             prvSEND_COMPLETED( pxStreamBuffer );
847         }
848         else
849         {
850             mtCOVERAGE_TEST_MARKER();
851         }
852     }
853     else
854     {
855         mtCOVERAGE_TEST_MARKER();
856         traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer );
857     }
858
859     traceRETURN_xStreamBufferSend( xReturn );
860
861     return xReturn;
862 }
863 /*-----------------------------------------------------------*/
864
865 size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
866                                  const void * pvTxData,
867                                  size_t xDataLengthBytes,
868                                  BaseType_t * const pxHigherPriorityTaskWoken )
869 {
870     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
871     size_t xReturn, xSpace;
872     size_t xRequiredSpace = xDataLengthBytes;
873
874     traceENTER_xStreamBufferSendFromISR( xStreamBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken );
875
876     configASSERT( pvTxData );
877     configASSERT( pxStreamBuffer );
878
879     /* This send function is used to write to both message buffers and stream
880      * buffers.  If this is a message buffer then the space needed must be
881      * increased by the amount of bytes needed to store the length of the
882      * message. */
883     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
884     {
885         xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
886     }
887     else
888     {
889         mtCOVERAGE_TEST_MARKER();
890     }
891
892     xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
893     xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
894
895     if( xReturn > ( size_t ) 0 )
896     {
897         /* Was a task waiting for the data? */
898         if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
899         {
900             prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
901         }
902         else
903         {
904             mtCOVERAGE_TEST_MARKER();
905         }
906     }
907     else
908     {
909         mtCOVERAGE_TEST_MARKER();
910     }
911
912     traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn );
913     traceRETURN_xStreamBufferSendFromISR( xReturn );
914
915     return xReturn;
916 }
917 /*-----------------------------------------------------------*/
918
919 static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
920                                        const void * pvTxData,
921                                        size_t xDataLengthBytes,
922                                        size_t xSpace,
923                                        size_t xRequiredSpace )
924 {
925     size_t xNextHead = pxStreamBuffer->xHead;
926     configMESSAGE_BUFFER_LENGTH_TYPE xMessageLength;
927
928     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
929     {
930         /* This is a message buffer, as opposed to a stream buffer. */
931
932         /* Convert xDataLengthBytes to the message length type. */
933         xMessageLength = ( configMESSAGE_BUFFER_LENGTH_TYPE ) xDataLengthBytes;
934
935         /* Ensure the data length given fits within configMESSAGE_BUFFER_LENGTH_TYPE. */
936         configASSERT( ( size_t ) xMessageLength == xDataLengthBytes );
937
938         if( xSpace >= xRequiredSpace )
939         {
940             /* There is enough space to write both the message length and the message
941              * itself into the buffer.  Start by writing the length of the data, the data
942              * itself will be written later in this function. */
943             xNextHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xMessageLength ), sbBYTES_TO_STORE_MESSAGE_LENGTH, xNextHead );
944         }
945         else
946         {
947             /* Not enough space, so do not write data to the buffer. */
948             xDataLengthBytes = 0;
949         }
950     }
951     else
952     {
953         /* This is a stream buffer, as opposed to a message buffer, so writing a
954          * stream of bytes rather than discrete messages.  Plan to write as many
955          * bytes as possible. */
956         xDataLengthBytes = configMIN( xDataLengthBytes, xSpace );
957     }
958
959     if( xDataLengthBytes != ( size_t ) 0 )
960     {
961         /* Write the data to the buffer. */
962         /* MISRA Ref 11.5.5 [Void pointer assignment] */
963         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
964         /* coverity[misra_c_2012_rule_11_5_violation] */
965         pxStreamBuffer->xHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes, xNextHead );
966     }
967
968     return xDataLengthBytes;
969 }
970 /*-----------------------------------------------------------*/
971
972 size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
973                              void * pvRxData,
974                              size_t xBufferLengthBytes,
975                              TickType_t xTicksToWait )
976 {
977     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
978     size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
979
980     traceENTER_xStreamBufferReceive( xStreamBuffer, pvRxData, xBufferLengthBytes, xTicksToWait );
981
982     configASSERT( pvRxData );
983     configASSERT( pxStreamBuffer );
984
985     /* This receive function is used by both message buffers, which store
986      * discrete messages, and stream buffers, which store a continuous stream of
987      * bytes.  Discrete messages include an additional
988      * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
989      * message. */
990     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
991     {
992         xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
993     }
994     else
995     {
996         xBytesToStoreMessageLength = 0;
997     }
998
999     if( xTicksToWait != ( TickType_t ) 0 )
1000     {
1001         /* Checking if there is data and clearing the notification state must be
1002          * performed atomically. */
1003         taskENTER_CRITICAL();
1004         {
1005             xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
1006
1007             /* If this function was invoked by a message buffer read then
1008              * xBytesToStoreMessageLength holds the number of bytes used to hold
1009              * the length of the next discrete message.  If this function was
1010              * invoked by a stream buffer read then xBytesToStoreMessageLength will
1011              * be 0. */
1012             if( xBytesAvailable <= xBytesToStoreMessageLength )
1013             {
1014                 /* Clear notification state as going to wait for data. */
1015                 ( void ) xTaskNotifyStateClearIndexed( NULL, pxStreamBuffer->uxNotificationIndex );
1016
1017                 /* Should only be one reader. */
1018                 configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL );
1019                 pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle();
1020             }
1021             else
1022             {
1023                 mtCOVERAGE_TEST_MARKER();
1024             }
1025         }
1026         taskEXIT_CRITICAL();
1027
1028         if( xBytesAvailable <= xBytesToStoreMessageLength )
1029         {
1030             /* Wait for data to be available. */
1031             traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer );
1032             ( void ) xTaskNotifyWaitIndexed( pxStreamBuffer->uxNotificationIndex, ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
1033             pxStreamBuffer->xTaskWaitingToReceive = NULL;
1034
1035             /* Recheck the data available after blocking. */
1036             xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
1037         }
1038         else
1039         {
1040             mtCOVERAGE_TEST_MARKER();
1041         }
1042     }
1043     else
1044     {
1045         xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
1046     }
1047
1048     /* Whether receiving a discrete message (where xBytesToStoreMessageLength
1049      * holds the number of bytes used to store the message length) or a stream of
1050      * bytes (where xBytesToStoreMessageLength is zero), the number of bytes
1051      * available must be greater than xBytesToStoreMessageLength to be able to
1052      * read bytes from the buffer. */
1053     if( xBytesAvailable > xBytesToStoreMessageLength )
1054     {
1055         xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable );
1056
1057         /* Was a task waiting for space in the buffer? */
1058         if( xReceivedLength != ( size_t ) 0 )
1059         {
1060             traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength );
1061             prvRECEIVE_COMPLETED( xStreamBuffer );
1062         }
1063         else
1064         {
1065             mtCOVERAGE_TEST_MARKER();
1066         }
1067     }
1068     else
1069     {
1070         traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer );
1071         mtCOVERAGE_TEST_MARKER();
1072     }
1073
1074     traceRETURN_xStreamBufferReceive( xReceivedLength );
1075
1076     return xReceivedLength;
1077 }
1078 /*-----------------------------------------------------------*/
1079
1080 size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer )
1081 {
1082     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1083     size_t xReturn, xBytesAvailable;
1084     configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
1085
1086     traceENTER_xStreamBufferNextMessageLengthBytes( xStreamBuffer );
1087
1088     configASSERT( pxStreamBuffer );
1089
1090     /* Ensure the stream buffer is being used as a message buffer. */
1091     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
1092     {
1093         xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
1094
1095         if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH )
1096         {
1097             /* The number of bytes available is greater than the number of bytes
1098              * required to hold the length of the next message, so another message
1099              * is available. */
1100             ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, pxStreamBuffer->xTail );
1101             xReturn = ( size_t ) xTempReturn;
1102         }
1103         else
1104         {
1105             /* The minimum amount of bytes in a message buffer is
1106              * ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
1107              * less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
1108              * value is 0. */
1109             configASSERT( xBytesAvailable == 0 );
1110             xReturn = 0;
1111         }
1112     }
1113     else
1114     {
1115         xReturn = 0;
1116     }
1117
1118     traceRETURN_xStreamBufferNextMessageLengthBytes( xReturn );
1119
1120     return xReturn;
1121 }
1122 /*-----------------------------------------------------------*/
1123
1124 size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
1125                                     void * pvRxData,
1126                                     size_t xBufferLengthBytes,
1127                                     BaseType_t * const pxHigherPriorityTaskWoken )
1128 {
1129     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1130     size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
1131
1132     traceENTER_xStreamBufferReceiveFromISR( xStreamBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken );
1133
1134     configASSERT( pvRxData );
1135     configASSERT( pxStreamBuffer );
1136
1137     /* This receive function is used by both message buffers, which store
1138      * discrete messages, and stream buffers, which store a continuous stream of
1139      * bytes.  Discrete messages include an additional
1140      * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
1141      * message. */
1142     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
1143     {
1144         xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
1145     }
1146     else
1147     {
1148         xBytesToStoreMessageLength = 0;
1149     }
1150
1151     xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
1152
1153     /* Whether receiving a discrete message (where xBytesToStoreMessageLength
1154      * holds the number of bytes used to store the message length) or a stream of
1155      * bytes (where xBytesToStoreMessageLength is zero), the number of bytes
1156      * available must be greater than xBytesToStoreMessageLength to be able to
1157      * read bytes from the buffer. */
1158     if( xBytesAvailable > xBytesToStoreMessageLength )
1159     {
1160         xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable );
1161
1162         /* Was a task waiting for space in the buffer? */
1163         if( xReceivedLength != ( size_t ) 0 )
1164         {
1165             prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
1166         }
1167         else
1168         {
1169             mtCOVERAGE_TEST_MARKER();
1170         }
1171     }
1172     else
1173     {
1174         mtCOVERAGE_TEST_MARKER();
1175     }
1176
1177     traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength );
1178     traceRETURN_xStreamBufferReceiveFromISR( xReceivedLength );
1179
1180     return xReceivedLength;
1181 }
1182 /*-----------------------------------------------------------*/
1183
1184 static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer,
1185                                         void * pvRxData,
1186                                         size_t xBufferLengthBytes,
1187                                         size_t xBytesAvailable )
1188 {
1189     size_t xCount, xNextMessageLength;
1190     configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
1191     size_t xNextTail = pxStreamBuffer->xTail;
1192
1193     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
1194     {
1195         /* A discrete message is being received.  First receive the length
1196          * of the message. */
1197         xNextTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, sbBYTES_TO_STORE_MESSAGE_LENGTH, xNextTail );
1198         xNextMessageLength = ( size_t ) xTempNextMessageLength;
1199
1200         /* Reduce the number of bytes available by the number of bytes just
1201          * read out. */
1202         xBytesAvailable -= sbBYTES_TO_STORE_MESSAGE_LENGTH;
1203
1204         /* Check there is enough space in the buffer provided by the
1205          * user. */
1206         if( xNextMessageLength > xBufferLengthBytes )
1207         {
1208             /* The user has provided insufficient space to read the message. */
1209             xNextMessageLength = 0;
1210         }
1211         else
1212         {
1213             mtCOVERAGE_TEST_MARKER();
1214         }
1215     }
1216     else
1217     {
1218         /* A stream of bytes is being received (as opposed to a discrete
1219          * message), so read as many bytes as possible. */
1220         xNextMessageLength = xBufferLengthBytes;
1221     }
1222
1223     /* Use the minimum of the wanted bytes and the available bytes. */
1224     xCount = configMIN( xNextMessageLength, xBytesAvailable );
1225
1226     if( xCount != ( size_t ) 0 )
1227     {
1228         /* Read the actual data and update the tail to mark the data as officially consumed. */
1229         /* MISRA Ref 11.5.5 [Void pointer assignment] */
1230         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
1231         /* coverity[misra_c_2012_rule_11_5_violation] */
1232         pxStreamBuffer->xTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xCount, xNextTail );
1233     }
1234
1235     return xCount;
1236 }
1237 /*-----------------------------------------------------------*/
1238
1239 BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer )
1240 {
1241     const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1242     BaseType_t xReturn;
1243     size_t xTail;
1244
1245     traceENTER_xStreamBufferIsEmpty( xStreamBuffer );
1246
1247     configASSERT( pxStreamBuffer );
1248
1249     /* True if no bytes are available. */
1250     xTail = pxStreamBuffer->xTail;
1251
1252     if( pxStreamBuffer->xHead == xTail )
1253     {
1254         xReturn = pdTRUE;
1255     }
1256     else
1257     {
1258         xReturn = pdFALSE;
1259     }
1260
1261     traceRETURN_xStreamBufferIsEmpty( xReturn );
1262
1263     return xReturn;
1264 }
1265 /*-----------------------------------------------------------*/
1266
1267 BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer )
1268 {
1269     BaseType_t xReturn;
1270     size_t xBytesToStoreMessageLength;
1271     const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1272
1273     traceENTER_xStreamBufferIsFull( xStreamBuffer );
1274
1275     configASSERT( pxStreamBuffer );
1276
1277     /* This generic version of the receive function is used by both message
1278      * buffers, which store discrete messages, and stream buffers, which store a
1279      * continuous stream of bytes.  Discrete messages include an additional
1280      * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
1281     if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
1282     {
1283         xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
1284     }
1285     else
1286     {
1287         xBytesToStoreMessageLength = 0;
1288     }
1289
1290     /* True if the available space equals zero. */
1291     if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength )
1292     {
1293         xReturn = pdTRUE;
1294     }
1295     else
1296     {
1297         xReturn = pdFALSE;
1298     }
1299
1300     traceRETURN_xStreamBufferIsFull( xReturn );
1301
1302     return xReturn;
1303 }
1304 /*-----------------------------------------------------------*/
1305
1306 BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
1307                                               BaseType_t * pxHigherPriorityTaskWoken )
1308 {
1309     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1310     BaseType_t xReturn;
1311     UBaseType_t uxSavedInterruptStatus;
1312
1313     traceENTER_xStreamBufferSendCompletedFromISR( xStreamBuffer, pxHigherPriorityTaskWoken );
1314
1315     configASSERT( pxStreamBuffer );
1316
1317     uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
1318     {
1319         if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )
1320         {
1321             ( void ) xTaskNotifyIndexedFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive,
1322                                                 ( pxStreamBuffer )->uxNotificationIndex,
1323                                                 ( uint32_t ) 0,
1324                                                 eNoAction,
1325                                                 pxHigherPriorityTaskWoken );
1326             ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;
1327             xReturn = pdTRUE;
1328         }
1329         else
1330         {
1331             xReturn = pdFALSE;
1332         }
1333     }
1334     taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
1335
1336     traceRETURN_xStreamBufferSendCompletedFromISR( xReturn );
1337
1338     return xReturn;
1339 }
1340 /*-----------------------------------------------------------*/
1341
1342 BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
1343                                                  BaseType_t * pxHigherPriorityTaskWoken )
1344 {
1345     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1346     BaseType_t xReturn;
1347     UBaseType_t uxSavedInterruptStatus;
1348
1349     traceENTER_xStreamBufferReceiveCompletedFromISR( xStreamBuffer, pxHigherPriorityTaskWoken );
1350
1351     configASSERT( pxStreamBuffer );
1352
1353     uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
1354     {
1355         if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )
1356         {
1357             ( void ) xTaskNotifyIndexedFromISR( ( pxStreamBuffer )->xTaskWaitingToSend,
1358                                                 ( pxStreamBuffer )->uxNotificationIndex,
1359                                                 ( uint32_t ) 0,
1360                                                 eNoAction,
1361                                                 pxHigherPriorityTaskWoken );
1362             ( pxStreamBuffer )->xTaskWaitingToSend = NULL;
1363             xReturn = pdTRUE;
1364         }
1365         else
1366         {
1367             xReturn = pdFALSE;
1368         }
1369     }
1370     taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
1371
1372     traceRETURN_xStreamBufferReceiveCompletedFromISR( xReturn );
1373
1374     return xReturn;
1375 }
1376 /*-----------------------------------------------------------*/
1377
1378 static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer,
1379                                      const uint8_t * pucData,
1380                                      size_t xCount,
1381                                      size_t xHead )
1382 {
1383     size_t xFirstLength;
1384
1385     configASSERT( xCount > ( size_t ) 0 );
1386
1387     /* Calculate the number of bytes that can be added in the first write -
1388      * which may be less than the total number of bytes that need to be added if
1389      * the buffer will wrap back to the beginning. */
1390     xFirstLength = configMIN( pxStreamBuffer->xLength - xHead, xCount );
1391
1392     /* Write as many bytes as can be written in the first write. */
1393     configASSERT( ( xHead + xFirstLength ) <= pxStreamBuffer->xLength );
1394     ( void ) memcpy( ( void * ) ( &( pxStreamBuffer->pucBuffer[ xHead ] ) ), ( const void * ) pucData, xFirstLength );
1395
1396     /* If the number of bytes written was less than the number that could be
1397      * written in the first write... */
1398     if( xCount > xFirstLength )
1399     {
1400         /* ...then write the remaining bytes to the start of the buffer. */
1401         configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength );
1402         ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength );
1403     }
1404     else
1405     {
1406         mtCOVERAGE_TEST_MARKER();
1407     }
1408
1409     xHead += xCount;
1410
1411     if( xHead >= pxStreamBuffer->xLength )
1412     {
1413         xHead -= pxStreamBuffer->xLength;
1414     }
1415     else
1416     {
1417         mtCOVERAGE_TEST_MARKER();
1418     }
1419
1420     return xHead;
1421 }
1422 /*-----------------------------------------------------------*/
1423
1424 static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer,
1425                                       uint8_t * pucData,
1426                                       size_t xCount,
1427                                       size_t xTail )
1428 {
1429     size_t xFirstLength;
1430
1431     configASSERT( xCount != ( size_t ) 0 );
1432
1433     /* Calculate the number of bytes that can be read - which may be
1434      * less than the number wanted if the data wraps around to the start of
1435      * the buffer. */
1436     xFirstLength = configMIN( pxStreamBuffer->xLength - xTail, xCount );
1437
1438     /* Obtain the number of bytes it is possible to obtain in the first
1439      * read.  Asserts check bounds of read and write. */
1440     configASSERT( xFirstLength <= xCount );
1441     configASSERT( ( xTail + xFirstLength ) <= pxStreamBuffer->xLength );
1442     ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xTail ] ), xFirstLength );
1443
1444     /* If the total number of wanted bytes is greater than the number
1445      * that could be read in the first read... */
1446     if( xCount > xFirstLength )
1447     {
1448         /* ...then read the remaining bytes from the start of the buffer. */
1449         ( void ) memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength );
1450     }
1451     else
1452     {
1453         mtCOVERAGE_TEST_MARKER();
1454     }
1455
1456     /* Move the tail pointer to effectively remove the data read from the buffer. */
1457     xTail += xCount;
1458
1459     if( xTail >= pxStreamBuffer->xLength )
1460     {
1461         xTail -= pxStreamBuffer->xLength;
1462     }
1463
1464     return xTail;
1465 }
1466 /*-----------------------------------------------------------*/
1467
1468 static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer )
1469 {
1470     /* Returns the distance between xTail and xHead. */
1471     size_t xCount;
1472
1473     xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead;
1474     xCount -= pxStreamBuffer->xTail;
1475
1476     if( xCount >= pxStreamBuffer->xLength )
1477     {
1478         xCount -= pxStreamBuffer->xLength;
1479     }
1480     else
1481     {
1482         mtCOVERAGE_TEST_MARKER();
1483     }
1484
1485     return xCount;
1486 }
1487 /*-----------------------------------------------------------*/
1488
1489 static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
1490                                           uint8_t * const pucBuffer,
1491                                           size_t xBufferSizeBytes,
1492                                           size_t xTriggerLevelBytes,
1493                                           uint8_t ucFlags,
1494                                           StreamBufferCallbackFunction_t pxSendCompletedCallback,
1495                                           StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
1496 {
1497     /* Assert here is deliberately writing to the entire buffer to ensure it can
1498      * be written to without generating exceptions, and is setting the buffer to a
1499      * known value to assist in development/debugging. */
1500     #if ( configASSERT_DEFINED == 1 )
1501     {
1502         /* The value written just has to be identifiable when looking at the
1503          * memory.  Don't use 0xA5 as that is the stack fill value and could
1504          * result in confusion as to what is actually being observed. */
1505         #define STREAM_BUFFER_BUFFER_WRITE_VALUE    ( 0x55 )
1506         configASSERT( memset( pucBuffer, ( int ) STREAM_BUFFER_BUFFER_WRITE_VALUE, xBufferSizeBytes ) == pucBuffer );
1507     }
1508     #endif
1509
1510     ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) );
1511     pxStreamBuffer->pucBuffer = pucBuffer;
1512     pxStreamBuffer->xLength = xBufferSizeBytes;
1513     pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes;
1514     pxStreamBuffer->ucFlags = ucFlags;
1515     pxStreamBuffer->uxNotificationIndex = tskDEFAULT_INDEX_TO_NOTIFY;
1516     #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
1517     {
1518         pxStreamBuffer->pxSendCompletedCallback = pxSendCompletedCallback;
1519         pxStreamBuffer->pxReceiveCompletedCallback = pxReceiveCompletedCallback;
1520     }
1521     #else
1522     {
1523         /* MISRA Ref 11.1.1 [Object type casting] */
1524         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-111 */
1525         /* coverity[misra_c_2012_rule_11_1_violation] */
1526         ( void ) pxSendCompletedCallback;
1527
1528         /* MISRA Ref 11.1.1 [Object type casting] */
1529         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-111 */
1530         /* coverity[misra_c_2012_rule_11_1_violation] */
1531         ( void ) pxReceiveCompletedCallback;
1532     }
1533     #endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
1534 }
1535 /*-----------------------------------------------------------*/
1536
1537 UBaseType_t uxStreamBufferGetStreamBufferNotificationIndex( StreamBufferHandle_t xStreamBuffer )
1538 {
1539     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1540
1541     traceENTER_uxStreamBufferGetStreamBufferNotificationIndex( xStreamBuffer );
1542
1543     configASSERT( pxStreamBuffer );
1544
1545     traceRETURN_uxStreamBufferGetStreamBufferNotificationIndex( pxStreamBuffer->uxNotificationIndex );
1546
1547     return pxStreamBuffer->uxNotificationIndex;
1548 }
1549 /*-----------------------------------------------------------*/
1550
1551 void vStreamBufferSetStreamBufferNotificationIndex( StreamBufferHandle_t xStreamBuffer,
1552                                                     UBaseType_t uxNotificationIndex )
1553 {
1554     StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1555
1556     traceENTER_vStreamBufferSetStreamBufferNotificationIndex( xStreamBuffer, uxNotificationIndex );
1557
1558     configASSERT( pxStreamBuffer );
1559
1560     /* There should be no task waiting otherwise we'd never resume them. */
1561     configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL );
1562     configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL );
1563
1564     /* Check that the task notification index is valid. */
1565     configASSERT( uxNotificationIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES );
1566
1567     pxStreamBuffer->uxNotificationIndex = uxNotificationIndex;
1568
1569     traceRETURN_vStreamBufferSetStreamBufferNotificationIndex();
1570 }
1571 /*-----------------------------------------------------------*/
1572
1573     #if ( configUSE_TRACE_FACILITY == 1 )
1574
1575     UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer )
1576     {
1577         traceENTER_uxStreamBufferGetStreamBufferNumber( xStreamBuffer );
1578
1579         traceRETURN_uxStreamBufferGetStreamBufferNumber( xStreamBuffer->uxStreamBufferNumber );
1580
1581         return xStreamBuffer->uxStreamBufferNumber;
1582     }
1583
1584     #endif /* configUSE_TRACE_FACILITY */
1585 /*-----------------------------------------------------------*/
1586
1587     #if ( configUSE_TRACE_FACILITY == 1 )
1588
1589     void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer,
1590                                              UBaseType_t uxStreamBufferNumber )
1591     {
1592         traceENTER_vStreamBufferSetStreamBufferNumber( xStreamBuffer, uxStreamBufferNumber );
1593
1594         xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
1595
1596         traceRETURN_vStreamBufferSetStreamBufferNumber();
1597     }
1598
1599     #endif /* configUSE_TRACE_FACILITY */
1600 /*-----------------------------------------------------------*/
1601
1602     #if ( configUSE_TRACE_FACILITY == 1 )
1603
1604     uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer )
1605     {
1606         traceENTER_ucStreamBufferGetStreamBufferType( xStreamBuffer );
1607
1608         traceRETURN_ucStreamBufferGetStreamBufferType( ( uint8_t ) ( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) );
1609
1610         return( ( uint8_t ) ( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) );
1611     }
1612
1613     #endif /* configUSE_TRACE_FACILITY */
1614 /*-----------------------------------------------------------*/
1615
1616 /* This entire source file will be skipped if the application is not configured
1617  * to include stream buffer functionality. This #if is closed at the very bottom
1618  * of this file. If you want to include stream buffers then ensure
1619  * configUSE_STREAM_BUFFERS is set to 1 in FreeRTOSConfig.h. */
1620 #endif /* configUSE_STREAM_BUFFERS == 1 */