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