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