source: S-port/trunk/Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 42.7 KB
Line 
1/*
2 * FreeRTOS Kernel V10.3.1
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * 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, e9021 and e750 are suppressed as a MISRA exception justified
47because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
48for the header files above, but not in this file, in order to generate the
49correct privileged Vs unprivileged linkage and placement. */
50#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
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( configMESSAGE_BUFFER_LENGTH_TYPE ) )
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 StreamBufferDef_t /*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 uint8_t ucFlags ) 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 uint8_t ucFlags;
223
224 /* In case the stream buffer is going to be used as a message buffer
225 (that is, it will hold discrete messages with a little meta data that
226 says how big the next message is) check the buffer will be large enough
227 to hold at least one message. */
228 if( xIsMessageBuffer == pdTRUE )
229 {
230 /* Is a message buffer but not statically allocated. */
231 ucFlags = sbFLAGS_IS_MESSAGE_BUFFER;
232 configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
233 }
234 else
235 {
236 /* Not a message buffer and not statically allocated. */
237 ucFlags = 0;
238 configASSERT( xBufferSizeBytes > 0 );
239 }
240 configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
241
242 /* A trigger level of 0 would cause a waiting task to unblock even when
243 the buffer was empty. */
244 if( xTriggerLevelBytes == ( size_t ) 0 )
245 {
246 xTriggerLevelBytes = ( size_t ) 1;
247 }
248
249 /* A stream buffer requires a StreamBuffer_t structure and a buffer.
250 Both are allocated in a single call to pvPortMalloc(). The
251 StreamBuffer_t structure is placed at the start of the allocated memory
252 and the buffer follows immediately after. The requested size is
253 incremented so the free space is returned as the user would expect -
254 this is a quirk of the implementation that means otherwise the free
255 space would be reported as one byte smaller than would be logically
256 expected. */
257 xBufferSizeBytes++;
258 pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */
259
260 if( pucAllocatedMemory != NULL )
261 {
262 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. */
263 pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */
264 xBufferSizeBytes,
265 xTriggerLevelBytes,
266 ucFlags );
267
268 traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer );
269 }
270 else
271 {
272 traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer );
273 }
274
275 return ( StreamBufferHandle_t ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */
276 }
277
278#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
279/*-----------------------------------------------------------*/
280
281#if( configSUPPORT_STATIC_ALLOCATION == 1 )
282
283 StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
284 size_t xTriggerLevelBytes,
285 BaseType_t xIsMessageBuffer,
286 uint8_t * const pucStreamBufferStorageArea,
287 StaticStreamBuffer_t * const pxStaticStreamBuffer )
288 {
289 StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */
290 StreamBufferHandle_t xReturn;
291 uint8_t ucFlags;
292
293 configASSERT( pucStreamBufferStorageArea );
294 configASSERT( pxStaticStreamBuffer );
295 configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
296
297 /* A trigger level of 0 would cause a waiting task to unblock even when
298 the buffer was empty. */
299 if( xTriggerLevelBytes == ( size_t ) 0 )
300 {
301 xTriggerLevelBytes = ( size_t ) 1;
302 }
303
304 if( xIsMessageBuffer != pdFALSE )
305 {
306 /* Statically allocated message buffer. */
307 ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED;
308 }
309 else
310 {
311 /* Statically allocated stream buffer. */
312 ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED;
313 }
314
315 /* In case the stream buffer is going to be used as a message buffer
316 (that is, it will hold discrete messages with a little meta data that
317 says how big the next message is) check the buffer will be large enough
318 to hold at least one message. */
319 configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
320
321 #if( configASSERT_DEFINED == 1 )
322 {
323 /* Sanity check that the size of the structure used to declare a
324 variable of type StaticStreamBuffer_t equals the size of the real
325 message buffer structure. */
326 volatile size_t xSize = sizeof( StaticStreamBuffer_t );
327 configASSERT( xSize == sizeof( StreamBuffer_t ) );
328 } /*lint !e529 xSize is referenced is configASSERT() is defined. */
329 #endif /* configASSERT_DEFINED */
330
331 if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) )
332 {
333 prvInitialiseNewStreamBuffer( pxStreamBuffer,
334 pucStreamBufferStorageArea,
335 xBufferSizeBytes,
336 xTriggerLevelBytes,
337 ucFlags );
338
339 /* Remember this was statically allocated in case it is ever deleted
340 again. */
341 pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED;
342
343 traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer );
344
345 xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; /*lint !e9087 Data hiding requires cast to opaque type. */
346 }
347 else
348 {
349 xReturn = NULL;
350 traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer );
351 }
352
353 return xReturn;
354 }
355
356#endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
357/*-----------------------------------------------------------*/
358
359void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer )
360{
361StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
362
363 configASSERT( pxStreamBuffer );
364
365 traceSTREAM_BUFFER_DELETE( xStreamBuffer );
366
367 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE )
368 {
369 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
370 {
371 /* Both the structure and the buffer were allocated using a single call
372 to pvPortMalloc(), hence only one call to vPortFree() is required. */
373 vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */
374 }
375 #else
376 {
377 /* Should not be possible to get here, ucFlags must be corrupt.
378 Force an assert. */
379 configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 );
380 }
381 #endif
382 }
383 else
384 {
385 /* The structure and buffer were not allocated dynamically and cannot be
386 freed - just scrub the structure so future use will assert. */
387 ( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) );
388 }
389}
390/*-----------------------------------------------------------*/
391
392BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
393{
394StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
395BaseType_t xReturn = pdFAIL;
396
397#if( configUSE_TRACE_FACILITY == 1 )
398 UBaseType_t uxStreamBufferNumber;
399#endif
400
401 configASSERT( pxStreamBuffer );
402
403 #if( configUSE_TRACE_FACILITY == 1 )
404 {
405 /* Store the stream buffer number so it can be restored after the
406 reset. */
407 uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber;
408 }
409 #endif
410
411 /* Can only reset a message buffer if there are no tasks blocked on it. */
412 taskENTER_CRITICAL();
413 {
414 if( pxStreamBuffer->xTaskWaitingToReceive == NULL )
415 {
416 if( pxStreamBuffer->xTaskWaitingToSend == NULL )
417 {
418 prvInitialiseNewStreamBuffer( pxStreamBuffer,
419 pxStreamBuffer->pucBuffer,
420 pxStreamBuffer->xLength,
421 pxStreamBuffer->xTriggerLevelBytes,
422 pxStreamBuffer->ucFlags );
423 xReturn = pdPASS;
424
425 #if( configUSE_TRACE_FACILITY == 1 )
426 {
427 pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
428 }
429 #endif
430
431 traceSTREAM_BUFFER_RESET( xStreamBuffer );
432 }
433 }
434 }
435 taskEXIT_CRITICAL();
436
437 return xReturn;
438}
439/*-----------------------------------------------------------*/
440
441BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel )
442{
443StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
444BaseType_t xReturn;
445
446 configASSERT( pxStreamBuffer );
447
448 /* It is not valid for the trigger level to be 0. */
449 if( xTriggerLevel == ( size_t ) 0 )
450 {
451 xTriggerLevel = ( size_t ) 1;
452 }
453
454 /* The trigger level is the number of bytes that must be in the stream
455 buffer before a task that is waiting for data is unblocked. */
456 if( xTriggerLevel <= pxStreamBuffer->xLength )
457 {
458 pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel;
459 xReturn = pdPASS;
460 }
461 else
462 {
463 xReturn = pdFALSE;
464 }
465
466 return xReturn;
467}
468/*-----------------------------------------------------------*/
469
470size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer )
471{
472const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
473size_t xSpace;
474
475 configASSERT( pxStreamBuffer );
476
477 xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail;
478 xSpace -= pxStreamBuffer->xHead;
479 xSpace -= ( size_t ) 1;
480
481 if( xSpace >= pxStreamBuffer->xLength )
482 {
483 xSpace -= pxStreamBuffer->xLength;
484 }
485 else
486 {
487 mtCOVERAGE_TEST_MARKER();
488 }
489
490 return xSpace;
491}
492/*-----------------------------------------------------------*/
493
494size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer )
495{
496const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
497size_t xReturn;
498
499 configASSERT( pxStreamBuffer );
500
501 xReturn = prvBytesInBuffer( pxStreamBuffer );
502 return xReturn;
503}
504/*-----------------------------------------------------------*/
505
506size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
507 const void *pvTxData,
508 size_t xDataLengthBytes,
509 TickType_t xTicksToWait )
510{
511StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
512size_t xReturn, xSpace = 0;
513size_t xRequiredSpace = xDataLengthBytes;
514TimeOut_t xTimeOut;
515
516 configASSERT( pvTxData );
517 configASSERT( pxStreamBuffer );
518
519 /* This send function is used to write to both message buffers and stream
520 buffers. If this is a message buffer then the space needed must be
521 increased by the amount of bytes needed to store the length of the
522 message. */
523 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
524 {
525 xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
526
527 /* Overflow? */
528 configASSERT( xRequiredSpace > xDataLengthBytes );
529 }
530 else
531 {
532 mtCOVERAGE_TEST_MARKER();
533 }
534
535 if( xTicksToWait != ( TickType_t ) 0 )
536 {
537 vTaskSetTimeOutState( &xTimeOut );
538
539 do
540 {
541 /* Wait until the required number of bytes are free in the message
542 buffer. */
543 taskENTER_CRITICAL();
544 {
545 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
546
547 if( xSpace < xRequiredSpace )
548 {
549 /* Clear notification state as going to wait for space. */
550 ( void ) xTaskNotifyStateClear( NULL );
551
552 /* Should only be one writer. */
553 configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL );
554 pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle();
555 }
556 else
557 {
558 taskEXIT_CRITICAL();
559 break;
560 }
561 }
562 taskEXIT_CRITICAL();
563
564 traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
565 ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
566 pxStreamBuffer->xTaskWaitingToSend = NULL;
567
568 } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
569 }
570 else
571 {
572 mtCOVERAGE_TEST_MARKER();
573 }
574
575 if( xSpace == ( size_t ) 0 )
576 {
577 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
578 }
579 else
580 {
581 mtCOVERAGE_TEST_MARKER();
582 }
583
584 xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
585
586 if( xReturn > ( size_t ) 0 )
587 {
588 traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn );
589
590 /* Was a task waiting for the data? */
591 if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
592 {
593 sbSEND_COMPLETED( pxStreamBuffer );
594 }
595 else
596 {
597 mtCOVERAGE_TEST_MARKER();
598 }
599 }
600 else
601 {
602 mtCOVERAGE_TEST_MARKER();
603 traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer );
604 }
605
606 return xReturn;
607}
608/*-----------------------------------------------------------*/
609
610size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
611 const void *pvTxData,
612 size_t xDataLengthBytes,
613 BaseType_t * const pxHigherPriorityTaskWoken )
614{
615StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
616size_t xReturn, xSpace;
617size_t xRequiredSpace = xDataLengthBytes;
618
619 configASSERT( pvTxData );
620 configASSERT( pxStreamBuffer );
621
622 /* This send function is used to write to both message buffers and stream
623 buffers. If this is a message buffer then the space needed must be
624 increased by the amount of bytes needed to store the length of the
625 message. */
626 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
627 {
628 xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
629 }
630 else
631 {
632 mtCOVERAGE_TEST_MARKER();
633 }
634
635 xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
636 xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
637
638 if( xReturn > ( size_t ) 0 )
639 {
640 /* Was a task waiting for the data? */
641 if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
642 {
643 sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
644 }
645 else
646 {
647 mtCOVERAGE_TEST_MARKER();
648 }
649 }
650 else
651 {
652 mtCOVERAGE_TEST_MARKER();
653 }
654
655 traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn );
656
657 return xReturn;
658}
659/*-----------------------------------------------------------*/
660
661static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
662 const void * pvTxData,
663 size_t xDataLengthBytes,
664 size_t xSpace,
665 size_t xRequiredSpace )
666{
667 BaseType_t xShouldWrite;
668 size_t xReturn;
669
670 if( xSpace == ( size_t ) 0 )
671 {
672 /* Doesn't matter if this is a stream buffer or a message buffer, there
673 is no space to write. */
674 xShouldWrite = pdFALSE;
675 }
676 else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 )
677 {
678 /* This is a stream buffer, as opposed to a message buffer, so writing a
679 stream of bytes rather than discrete messages. Write as many bytes as
680 possible. */
681 xShouldWrite = pdTRUE;
682 xDataLengthBytes = configMIN( xDataLengthBytes, xSpace );
683 }
684 else if( xSpace >= xRequiredSpace )
685 {
686 /* This is a message buffer, as opposed to a stream buffer, and there
687 is enough space to write both the message length and the message itself
688 into the buffer. Start by writing the length of the data, the data
689 itself will be written later in this function. */
690 xShouldWrite = pdTRUE;
691 ( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH );
692 }
693 else
694 {
695 /* There is space available, but not enough space. */
696 xShouldWrite = pdFALSE;
697 }
698
699 if( xShouldWrite != pdFALSE )
700 {
701 /* Writes the data itself. */
702 xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alighment and access. */
703 }
704 else
705 {
706 xReturn = 0;
707 }
708
709 return xReturn;
710}
711/*-----------------------------------------------------------*/
712
713size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
714 void *pvRxData,
715 size_t xBufferLengthBytes,
716 TickType_t xTicksToWait )
717{
718StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
719size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
720
721 configASSERT( pvRxData );
722 configASSERT( pxStreamBuffer );
723
724 /* This receive function is used by both message buffers, which store
725 discrete messages, and stream buffers, which store a continuous stream of
726 bytes. Discrete messages include an additional
727 sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
728 message. */
729 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
730 {
731 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
732 }
733 else
734 {
735 xBytesToStoreMessageLength = 0;
736 }
737
738 if( xTicksToWait != ( TickType_t ) 0 )
739 {
740 /* Checking if there is data and clearing the notification state must be
741 performed atomically. */
742 taskENTER_CRITICAL();
743 {
744 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
745
746 /* If this function was invoked by a message buffer read then
747 xBytesToStoreMessageLength holds the number of bytes used to hold
748 the length of the next discrete message. If this function was
749 invoked by a stream buffer read then xBytesToStoreMessageLength will
750 be 0. */
751 if( xBytesAvailable <= xBytesToStoreMessageLength )
752 {
753 /* Clear notification state as going to wait for data. */
754 ( void ) xTaskNotifyStateClear( NULL );
755
756 /* Should only be one reader. */
757 configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL );
758 pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle();
759 }
760 else
761 {
762 mtCOVERAGE_TEST_MARKER();
763 }
764 }
765 taskEXIT_CRITICAL();
766
767 if( xBytesAvailable <= xBytesToStoreMessageLength )
768 {
769 /* Wait for data to be available. */
770 traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer );
771 ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
772 pxStreamBuffer->xTaskWaitingToReceive = NULL;
773
774 /* Recheck the data available after blocking. */
775 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
776 }
777 else
778 {
779 mtCOVERAGE_TEST_MARKER();
780 }
781 }
782 else
783 {
784 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
785 }
786
787 /* Whether receiving a discrete message (where xBytesToStoreMessageLength
788 holds the number of bytes used to store the message length) or a stream of
789 bytes (where xBytesToStoreMessageLength is zero), the number of bytes
790 available must be greater than xBytesToStoreMessageLength to be able to
791 read bytes from the buffer. */
792 if( xBytesAvailable > xBytesToStoreMessageLength )
793 {
794 xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
795
796 /* Was a task waiting for space in the buffer? */
797 if( xReceivedLength != ( size_t ) 0 )
798 {
799 traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength );
800 sbRECEIVE_COMPLETED( pxStreamBuffer );
801 }
802 else
803 {
804 mtCOVERAGE_TEST_MARKER();
805 }
806 }
807 else
808 {
809 traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer );
810 mtCOVERAGE_TEST_MARKER();
811 }
812
813 return xReceivedLength;
814}
815/*-----------------------------------------------------------*/
816
817size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer )
818{
819StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
820size_t xReturn, xBytesAvailable, xOriginalTail;
821configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
822
823 configASSERT( pxStreamBuffer );
824
825 /* Ensure the stream buffer is being used as a message buffer. */
826 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
827 {
828 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
829 if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH )
830 {
831 /* The number of bytes available is greater than the number of bytes
832 required to hold the length of the next message, so another message
833 is available. Return its length without removing the length bytes
834 from the buffer. A copy of the tail is stored so the buffer can be
835 returned to its prior state as the message is not actually being
836 removed from the buffer. */
837 xOriginalTail = pxStreamBuffer->xTail;
838 ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable );
839 xReturn = ( size_t ) xTempReturn;
840 pxStreamBuffer->xTail = xOriginalTail;
841 }
842 else
843 {
844 /* The minimum amount of bytes in a message buffer is
845 ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
846 less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
847 value is 0. */
848 configASSERT( xBytesAvailable == 0 );
849 xReturn = 0;
850 }
851 }
852 else
853 {
854 xReturn = 0;
855 }
856
857 return xReturn;
858}
859/*-----------------------------------------------------------*/
860
861size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
862 void *pvRxData,
863 size_t xBufferLengthBytes,
864 BaseType_t * const pxHigherPriorityTaskWoken )
865{
866StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
867size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
868
869 configASSERT( pvRxData );
870 configASSERT( pxStreamBuffer );
871
872 /* This receive function is used by both message buffers, which store
873 discrete messages, and stream buffers, which store a continuous stream of
874 bytes. Discrete messages include an additional
875 sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
876 message. */
877 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
878 {
879 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
880 }
881 else
882 {
883 xBytesToStoreMessageLength = 0;
884 }
885
886 xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
887
888 /* Whether receiving a discrete message (where xBytesToStoreMessageLength
889 holds the number of bytes used to store the message length) or a stream of
890 bytes (where xBytesToStoreMessageLength is zero), the number of bytes
891 available must be greater than xBytesToStoreMessageLength to be able to
892 read bytes from the buffer. */
893 if( xBytesAvailable > xBytesToStoreMessageLength )
894 {
895 xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength );
896
897 /* Was a task waiting for space in the buffer? */
898 if( xReceivedLength != ( size_t ) 0 )
899 {
900 sbRECEIVE_COMPLETED_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_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength );
913
914 return xReceivedLength;
915}
916/*-----------------------------------------------------------*/
917
918static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer,
919 void *pvRxData,
920 size_t xBufferLengthBytes,
921 size_t xBytesAvailable,
922 size_t xBytesToStoreMessageLength )
923{
924size_t xOriginalTail, xReceivedLength, xNextMessageLength;
925configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
926
927 if( xBytesToStoreMessageLength != ( size_t ) 0 )
928 {
929 /* A discrete message is being received. First receive the length
930 of the message. A copy of the tail is stored so the buffer can be
931 returned to its prior state if the length of the message is too
932 large for the provided buffer. */
933 xOriginalTail = pxStreamBuffer->xTail;
934 ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable );
935 xNextMessageLength = ( size_t ) xTempNextMessageLength;
936
937 /* Reduce the number of bytes available by the number of bytes just
938 read out. */
939 xBytesAvailable -= xBytesToStoreMessageLength;
940
941 /* Check there is enough space in the buffer provided by the
942 user. */
943 if( xNextMessageLength > xBufferLengthBytes )
944 {
945 /* The user has provided insufficient space to read the message
946 so return the buffer to its previous state (so the length of
947 the message is in the buffer again). */
948 pxStreamBuffer->xTail = xOriginalTail;
949 xNextMessageLength = 0;
950 }
951 else
952 {
953 mtCOVERAGE_TEST_MARKER();
954 }
955 }
956 else
957 {
958 /* A stream of bytes is being received (as opposed to a discrete
959 message), so read as many bytes as possible. */
960 xNextMessageLength = xBufferLengthBytes;
961 }
962
963 /* Read the actual data. */
964 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. */
965
966 return xReceivedLength;
967}
968/*-----------------------------------------------------------*/
969
970BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer )
971{
972const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
973BaseType_t xReturn;
974size_t xTail;
975
976 configASSERT( pxStreamBuffer );
977
978 /* True if no bytes are available. */
979 xTail = pxStreamBuffer->xTail;
980 if( pxStreamBuffer->xHead == xTail )
981 {
982 xReturn = pdTRUE;
983 }
984 else
985 {
986 xReturn = pdFALSE;
987 }
988
989 return xReturn;
990}
991/*-----------------------------------------------------------*/
992
993BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer )
994{
995BaseType_t xReturn;
996size_t xBytesToStoreMessageLength;
997const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
998
999 configASSERT( pxStreamBuffer );
1000
1001 /* This generic version of the receive function is used by both message
1002 buffers, which store discrete messages, and stream buffers, which store a
1003 continuous stream of bytes. Discrete messages include an additional
1004 sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
1005 if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
1006 {
1007 xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
1008 }
1009 else
1010 {
1011 xBytesToStoreMessageLength = 0;
1012 }
1013
1014 /* True if the available space equals zero. */
1015 if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength )
1016 {
1017 xReturn = pdTRUE;
1018 }
1019 else
1020 {
1021 xReturn = pdFALSE;
1022 }
1023
1024 return xReturn;
1025}
1026/*-----------------------------------------------------------*/
1027
1028BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken )
1029{
1030StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1031BaseType_t xReturn;
1032UBaseType_t uxSavedInterruptStatus;
1033
1034 configASSERT( pxStreamBuffer );
1035
1036 uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
1037 {
1038 if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )
1039 {
1040 ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive,
1041 ( uint32_t ) 0,
1042 eNoAction,
1043 pxHigherPriorityTaskWoken );
1044 ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;
1045 xReturn = pdTRUE;
1046 }
1047 else
1048 {
1049 xReturn = pdFALSE;
1050 }
1051 }
1052 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1053
1054 return xReturn;
1055}
1056/*-----------------------------------------------------------*/
1057
1058BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken )
1059{
1060StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
1061BaseType_t xReturn;
1062UBaseType_t uxSavedInterruptStatus;
1063
1064 configASSERT( pxStreamBuffer );
1065
1066 uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
1067 {
1068 if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )
1069 {
1070 ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend,
1071 ( uint32_t ) 0,
1072 eNoAction,
1073 pxHigherPriorityTaskWoken );
1074 ( pxStreamBuffer )->xTaskWaitingToSend = NULL;
1075 xReturn = pdTRUE;
1076 }
1077 else
1078 {
1079 xReturn = pdFALSE;
1080 }
1081 }
1082 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1083
1084 return xReturn;
1085}
1086/*-----------------------------------------------------------*/
1087
1088static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount )
1089{
1090size_t xNextHead, xFirstLength;
1091
1092 configASSERT( xCount > ( size_t ) 0 );
1093
1094 xNextHead = pxStreamBuffer->xHead;
1095
1096 /* Calculate the number of bytes that can be added in the first write -
1097 which may be less than the total number of bytes that need to be added if
1098 the buffer will wrap back to the beginning. */
1099 xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount );
1100
1101 /* Write as many bytes as can be written in the first write. */
1102 configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength );
1103 ( void ) memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1104
1105 /* If the number of bytes written was less than the number that could be
1106 written in the first write... */
1107 if( xCount > xFirstLength )
1108 {
1109 /* ...then write the remaining bytes to the start of the buffer. */
1110 configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength );
1111 ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1112 }
1113 else
1114 {
1115 mtCOVERAGE_TEST_MARKER();
1116 }
1117
1118 xNextHead += xCount;
1119 if( xNextHead >= pxStreamBuffer->xLength )
1120 {
1121 xNextHead -= pxStreamBuffer->xLength;
1122 }
1123 else
1124 {
1125 mtCOVERAGE_TEST_MARKER();
1126 }
1127
1128 pxStreamBuffer->xHead = xNextHead;
1129
1130 return xCount;
1131}
1132/*-----------------------------------------------------------*/
1133
1134static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, uint8_t *pucData, size_t xMaxCount, size_t xBytesAvailable )
1135{
1136size_t xCount, xFirstLength, xNextTail;
1137
1138 /* Use the minimum of the wanted bytes and the available bytes. */
1139 xCount = configMIN( xBytesAvailable, xMaxCount );
1140
1141 if( xCount > ( size_t ) 0 )
1142 {
1143 xNextTail = pxStreamBuffer->xTail;
1144
1145 /* Calculate the number of bytes that can be read - which may be
1146 less than the number wanted if the data wraps around to the start of
1147 the buffer. */
1148 xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount );
1149
1150 /* Obtain the number of bytes it is possible to obtain in the first
1151 read. Asserts check bounds of read and write. */
1152 configASSERT( xFirstLength <= xMaxCount );
1153 configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength );
1154 ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1155
1156 /* If the total number of wanted bytes is greater than the number
1157 that could be read in the first read... */
1158 if( xCount > xFirstLength )
1159 {
1160 /*...then read the remaining bytes from the start of the buffer. */
1161 configASSERT( xCount <= xMaxCount );
1162 ( void ) memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
1163 }
1164 else
1165 {
1166 mtCOVERAGE_TEST_MARKER();
1167 }
1168
1169 /* Move the tail pointer to effectively remove the data read from
1170 the buffer. */
1171 xNextTail += xCount;
1172
1173 if( xNextTail >= pxStreamBuffer->xLength )
1174 {
1175 xNextTail -= pxStreamBuffer->xLength;
1176 }
1177
1178 pxStreamBuffer->xTail = xNextTail;
1179 }
1180 else
1181 {
1182 mtCOVERAGE_TEST_MARKER();
1183 }
1184
1185 return xCount;
1186}
1187/*-----------------------------------------------------------*/
1188
1189static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer )
1190{
1191/* Returns the distance between xTail and xHead. */
1192size_t xCount;
1193
1194 xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead;
1195 xCount -= pxStreamBuffer->xTail;
1196 if ( xCount >= pxStreamBuffer->xLength )
1197 {
1198 xCount -= pxStreamBuffer->xLength;
1199 }
1200 else
1201 {
1202 mtCOVERAGE_TEST_MARKER();
1203 }
1204
1205 return xCount;
1206}
1207/*-----------------------------------------------------------*/
1208
1209static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
1210 uint8_t * const pucBuffer,
1211 size_t xBufferSizeBytes,
1212 size_t xTriggerLevelBytes,
1213 uint8_t ucFlags )
1214{
1215 /* Assert here is deliberately writing to the entire buffer to ensure it can
1216 be written to without generating exceptions, and is setting the buffer to a
1217 known value to assist in development/debugging. */
1218 #if( configASSERT_DEFINED == 1 )
1219 {
1220 /* The value written just has to be identifiable when looking at the
1221 memory. Don't use 0xA5 as that is the stack fill value and could
1222 result in confusion as to what is actually being observed. */
1223 const BaseType_t xWriteValue = 0x55;
1224 configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer );
1225 } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */
1226 #endif
1227
1228 ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */
1229 pxStreamBuffer->pucBuffer = pucBuffer;
1230 pxStreamBuffer->xLength = xBufferSizeBytes;
1231 pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes;
1232 pxStreamBuffer->ucFlags = ucFlags;
1233}
1234
1235#if ( configUSE_TRACE_FACILITY == 1 )
1236
1237 UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer )
1238 {
1239 return xStreamBuffer->uxStreamBufferNumber;
1240 }
1241
1242#endif /* configUSE_TRACE_FACILITY */
1243/*-----------------------------------------------------------*/
1244
1245#if ( configUSE_TRACE_FACILITY == 1 )
1246
1247 void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber )
1248 {
1249 xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
1250 }
1251
1252#endif /* configUSE_TRACE_FACILITY */
1253/*-----------------------------------------------------------*/
1254
1255#if ( configUSE_TRACE_FACILITY == 1 )
1256
1257 uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer )
1258 {
1259 return ( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER );
1260 }
1261
1262#endif /* configUSE_TRACE_FACILITY */
1263/*-----------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.