summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c')
-rw-r--r--FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c2128
1 files changed, 1067 insertions, 1061 deletions
diff --git a/FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c b/FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c
index 228904b04..044dcd9d9 100644
--- a/FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c
+++ b/FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c
@@ -37,47 +37,47 @@
#include "StreamBufferDemo.h"
/* The number of bytes of storage in the stream buffers used in this test. */
-#define sbSTREAM_BUFFER_LENGTH_BYTES ( ( size_t ) 30 )
+#define sbSTREAM_BUFFER_LENGTH_BYTES ( ( size_t ) 30 )
/* Stream buffer length one. */
-#define sbSTREAM_BUFFER_LENGTH_ONE ( ( size_t ) 1 )
+#define sbSTREAM_BUFFER_LENGTH_ONE ( ( size_t ) 1 )
/* Start and end ASCII characters used in data sent to the buffers. */
-#define sbASCII_SPACE 32
-#define sbASCII_TILDA 126
+#define sbASCII_SPACE 32
+#define sbASCII_TILDA 126
/* Defines the number of tasks to create in this test and demo. */
-#define sbNUMBER_OF_ECHO_CLIENTS ( 2 )
-#define sbNUMBER_OF_SENDER_TASKS ( 2 )
+#define sbNUMBER_OF_ECHO_CLIENTS ( 2 )
+#define sbNUMBER_OF_SENDER_TASKS ( 2 )
/* Priority of the test tasks. The send and receive go from low to high
-priority tasks, and from high to low priority tasks. */
-#define sbLOWER_PRIORITY ( tskIDLE_PRIORITY )
-#define sbHIGHER_PRIORITY ( tskIDLE_PRIORITY + 1 )
+ * priority tasks, and from high to low priority tasks. */
+#define sbLOWER_PRIORITY ( tskIDLE_PRIORITY )
+#define sbHIGHER_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* Block times used when sending and receiving from the stream buffers. */
-#define sbRX_TX_BLOCK_TIME pdMS_TO_TICKS( 125UL )
+#define sbRX_TX_BLOCK_TIME pdMS_TO_TICKS( 125UL )
/* A block time of 0 means "don't block". */
-#define sbDONT_BLOCK ( 0 )
+#define sbDONT_BLOCK ( 0 )
/* The trigger level sets the number of bytes that must be present in the
-stream buffer before a task that is blocked on the stream buffer is moved out of
-the Blocked state so it can read the bytes. */
-#define sbTRIGGER_LEVEL_1 ( 1 )
+ * stream buffer before a task that is blocked on the stream buffer is moved out of
+ * the Blocked state so it can read the bytes. */
+#define sbTRIGGER_LEVEL_1 ( 1 )
/* The size of the stack allocated to the tasks that run as part of this demo/
-test. The stack size is over generous in most cases. */
+ * test. The stack size is over generous in most cases. */
#ifndef configSTREAM_BUFFER_SENDER_TASK_STACK_SIZE
- #define sbSTACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
+ #define sbSTACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
#else
- #define sbSTACK_SIZE configSTREAM_BUFFER_SENDER_TASK_STACK_SIZE
+ #define sbSTACK_SIZE configSTREAM_BUFFER_SENDER_TASK_STACK_SIZE
#endif
#ifndef configSTREAM_BUFFER_SMALLER_TASK_STACK_SIZE
- #define sbSMALLER_STACK_SIZE sbSTACK_SIZE
+ #define sbSMALLER_STACK_SIZE sbSTACK_SIZE
#else
- #define sbSMALLER_STACK_SIZE configSTREAM_BUFFER_SMALLER_TASK_STACK_SIZE
+ #define sbSMALLER_STACK_SIZE configSTREAM_BUFFER_SMALLER_TASK_STACK_SIZE
#endif
/*-----------------------------------------------------------*/
@@ -93,19 +93,19 @@ static void prvSingleTaskTests( StreamBufferHandle_t xStreamBuffer );
* data back to the echo client, which checks it receives exactly what it
* sent.
*/
-static void prvEchoClient( void *pvParameters );
-static void prvEchoServer( void *pvParameters );
+static void prvEchoClient( void * pvParameters );
+static void prvEchoServer( void * pvParameters );
/*
* Tasks that send and receive to a stream buffer at a low priority and without
* blocking, so the send and receive functions interleave in time as the tasks
* are switched in and out.
*/
-static void prvNonBlockingReceiverTask( void *pvParameters );
-static void prvNonBlockingSenderTask( void *pvParameters );
+static void prvNonBlockingReceiverTask( void * pvParameters );
+static void prvNonBlockingSenderTask( void * pvParameters );
/* Performs an assert() like check in a way that won't get removed when
-performing a code coverage analysis. */
+ * performing a code coverage analysis. */
static void prvCheckExpectedState( BaseType_t xState );
/*
@@ -113,24 +113,25 @@ static void prvCheckExpectedState( BaseType_t xState );
* receives a string from an interrupt (the RTOS tick hook) byte by byte to
* check it is only unblocked when the specified trigger level is reached.
*/
-static void prvInterruptTriggerLevelTest( void *pvParameters );
+static void prvInterruptTriggerLevelTest( void * pvParameters );
-#if( configSUPPORT_STATIC_ALLOCATION == 1 )
- /* This file tests both statically and dynamically allocated stream buffers.
- Allocate the structures and buffers to be used by the statically allocated
- objects, which get used in the echo tests. */
- static void prvReceiverTask( void *pvParameters );
- static void prvSenderTask( void *pvParameters );
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
- static StaticStreamBuffer_t xStaticStreamBuffers[ sbNUMBER_OF_ECHO_CLIENTS ];
- static uint32_t ulSenderLoopCounters[ sbNUMBER_OF_SENDER_TASKS ] = { 0 };
+/* This file tests both statically and dynamically allocated stream buffers.
+ * Allocate the structures and buffers to be used by the statically allocated
+ * objects, which get used in the echo tests. */
+ static void prvReceiverTask( void * pvParameters );
+ static void prvSenderTask( void * pvParameters );
+
+ static StaticStreamBuffer_t xStaticStreamBuffers[ sbNUMBER_OF_ECHO_CLIENTS ];
+ static uint32_t ulSenderLoopCounters[ sbNUMBER_OF_SENDER_TASKS ] = { 0 };
#endif /* configSUPPORT_STATIC_ALLOCATION */
/* The +1 is to make the test logic easier as the function that calculates the
-free space will return one less than the actual free space - adding a 1 to the
-actual length makes it appear to the tests as if the free space is returned as
-it might logically be expected. Returning 1 less than the actual free space is
-fine as it can never result in an overrun. */
+ * free space will return one less than the actual free space - adding a 1 to the
+ * actual length makes it appear to the tests as if the free space is returned as
+ * it might logically be expected. Returning 1 less than the actual free space is
+ * fine as it can never result in an overrun. */
static uint8_t ucBufferStorage[ sbNUMBER_OF_SENDER_TASKS ][ sbSTREAM_BUFFER_LENGTH_BYTES + 1 ];
/*-----------------------------------------------------------*/
@@ -138,1104 +139,1109 @@ static uint8_t ucBufferStorage[ sbNUMBER_OF_SENDER_TASKS ][ sbSTREAM_BUFFER_LENG
/* The buffers used by the echo client and server tasks. */
typedef struct ECHO_STREAM_BUFFERS
{
- /* Handles to the data structures that describe the stream buffers. */
- StreamBufferHandle_t xEchoClientBuffer;
- StreamBufferHandle_t xEchoServerBuffer;
+ /* Handles to the data structures that describe the stream buffers. */
+ StreamBufferHandle_t xEchoClientBuffer;
+ StreamBufferHandle_t xEchoServerBuffer;
} EchoStreamBuffers_t;
static volatile uint32_t ulEchoLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
/* The non-blocking tasks monitor their operation, and if no errors have been
-found, increment ulNonBlockingRxCounter. xAreStreamBufferTasksStillRunning()
-then checks ulNonBlockingRxCounter and only returns pdPASS if
-ulNonBlockingRxCounter is still incrementing. */
+ * found, increment ulNonBlockingRxCounter. xAreStreamBufferTasksStillRunning()
+ * then checks ulNonBlockingRxCounter and only returns pdPASS if
+ * ulNonBlockingRxCounter is still incrementing. */
static volatile uint32_t ulNonBlockingRxCounter = 0;
/* The task that receives characters from the tick interrupt in order to test
-different trigger levels monitors its own behaviour. If it has not detected any
-error then it increments ulInterruptTriggerCounter to indicate to the check task
-that it is still operating correctly. */
+ * different trigger levels monitors its own behaviour. If it has not detected any
+ * error then it increments ulInterruptTriggerCounter to indicate to the check task
+ * that it is still operating correctly. */
static volatile uint32_t ulInterruptTriggerCounter = 0UL;
/* The stream buffer used from the tick interrupt. This sends one byte at a time
-to a test task to test the trigger level operation. The variable is set to NULL
-in between test runs. */
+ * to a test task to test the trigger level operation. The variable is set to NULL
+ * in between test runs. */
static volatile StreamBufferHandle_t xInterruptStreamBuffer = NULL;
/* The data sent from the tick interrupt to the task that tests the trigger
-level functionality. */
-static const char *pcDataSentFromInterrupt = "0123456789";
+ * level functionality. */
+static const char * pcDataSentFromInterrupt = "0123456789";
/* Data that is longer than the buffer that is sent to the buffers as a stream
-of bytes. Parts of which are written to the stream buffer to test writing
-different lengths at different offsets, to many bytes, part streams, streams
-that wrap, etc.. Two messages are defined to ensure left over data is not
-accidentally read out of the buffer. */
-static const char *pc55ByteString = "One two three four five six seven eight nine ten eleven";
-static const char *pc54ByteString = "01234567891abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ";
+ * of bytes. Parts of which are written to the stream buffer to test writing
+ * different lengths at different offsets, to many bytes, part streams, streams
+ * that wrap, etc.. Two messages are defined to ensure left over data is not
+ * accidentally read out of the buffer. */
+static const char * pc55ByteString = "One two three four five six seven eight nine ten eleven";
+static const char * pc54ByteString = "01234567891abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ";
/* Used to log the status of the tests contained within this file for reporting
-to a monitoring task ('check' task). */
+ * to a monitoring task ('check' task). */
static BaseType_t xErrorStatus = pdPASS;
/*-----------------------------------------------------------*/
void vStartStreamBufferTasks( void )
{
-StreamBufferHandle_t xStreamBuffer;
-
- /* The echo servers sets up the stream buffers before creating the echo
- client tasks. One set of tasks has the server as the higher priority, and
- the other has the client as the higher priority. */
- xTaskCreate( prvEchoServer, "1StrEchoServer", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
- xTaskCreate( prvEchoServer, "2StrEchoServer", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
-
- /* The non blocking tasks run continuously and will interleave with each
- other, so must be created at the lowest priority. The stream buffer they
- use is created and passed in using the task's parameter. */
- xStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
- xTaskCreate( prvNonBlockingReceiverTask, "StrNonBlkRx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
- xTaskCreate( prvNonBlockingSenderTask, "StrNonBlkTx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
-
- /* The task that receives bytes from an interrupt to test that it unblocks
- at a specific trigger level must run at a high priority to minimise the risk
- of it receiving more characters before it can execute again after being
- unblocked. */
- xTaskCreate( prvInterruptTriggerLevelTest, "StrTrig", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
-
- #if( configSUPPORT_STATIC_ALLOCATION == 1 )
- {
- /* The sender tasks set up the stream buffers before creating the
- receiver tasks. Priorities must be 0 and 1 as the priority is used to
- index into the xStaticStreamBuffers and ucBufferStorage arrays. */
- xTaskCreate( prvSenderTask, "Str1Sender", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
- xTaskCreate( prvSenderTask, "Str2Sender", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
- }
- #endif /* configSUPPORT_STATIC_ALLOCATION */
+ StreamBufferHandle_t xStreamBuffer;
+
+ /* The echo servers sets up the stream buffers before creating the echo
+ * client tasks. One set of tasks has the server as the higher priority, and
+ * the other has the client as the higher priority. */
+ xTaskCreate( prvEchoServer, "1StrEchoServer", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
+ xTaskCreate( prvEchoServer, "2StrEchoServer", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
+
+ /* The non blocking tasks run continuously and will interleave with each
+ * other, so must be created at the lowest priority. The stream buffer they
+ * use is created and passed in using the task's parameter. */
+ xStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
+ xTaskCreate( prvNonBlockingReceiverTask, "StrNonBlkRx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
+ xTaskCreate( prvNonBlockingSenderTask, "StrNonBlkTx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
+
+ /* The task that receives bytes from an interrupt to test that it unblocks
+ * at a specific trigger level must run at a high priority to minimise the risk
+ * of it receiving more characters before it can execute again after being
+ * unblocked. */
+ xTaskCreate( prvInterruptTriggerLevelTest, "StrTrig", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
+
+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* The sender tasks set up the stream buffers before creating the
+ * receiver tasks. Priorities must be 0 and 1 as the priority is used to
+ * index into the xStaticStreamBuffers and ucBufferStorage arrays. */
+ xTaskCreate( prvSenderTask, "Str1Sender", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
+ xTaskCreate( prvSenderTask, "Str2Sender", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
}
/*-----------------------------------------------------------*/
static void prvCheckExpectedState( BaseType_t xState )
{
- configASSERT( xState );
- if( xState == pdFAIL )
- {
- xErrorStatus = pdFAIL;
- }
+ configASSERT( xState );
+
+ if( xState == pdFAIL )
+ {
+ xErrorStatus = pdFAIL;
+ }
}
/*-----------------------------------------------------------*/
static void prvSingleTaskTests( StreamBufferHandle_t xStreamBuffer )
{
-size_t xReturned, xItem, xExpected, xExpectedSpaces, xExpectedBytes;
-const size_t xMax6ByteMessages = sbSTREAM_BUFFER_LENGTH_BYTES / 6;
-const size_t xTrueSize = ( sizeof( ucBufferStorage ) / sbNUMBER_OF_SENDER_TASKS );
-const size_t x6ByteLength = 6, x17ByteLength = 17, xFullBufferSize = sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2;
-uint8_t *pucFullBuffer, *pucData, *pucReadData;
-TickType_t xTimeBeforeCall, xTimeAfterCall;
-const TickType_t xBlockTime = pdMS_TO_TICKS( 15 ), xAllowableMargin = pdMS_TO_TICKS( 3 ), xMinimalBlockTime = 2;
-UBaseType_t uxOriginalPriority;
-
- /* Remove warning in case configASSERT() is not defined. */
- ( void ) xAllowableMargin;
-
- /* To minimise stack and heap usage a full size buffer is allocated from the
- heap, then buffers which hold smaller amounts of data are overlayed with the
- larger buffer - just make sure not to use both at once! */
- pucFullBuffer = pvPortMalloc( xFullBufferSize );
- configASSERT( pucFullBuffer );
-
- pucData = pucFullBuffer;
- pucReadData = pucData + x17ByteLength;
-
- /* Nothing has been added or removed yet, so expect the free space to be
- exactly as created. Head and tail are both at 0. */
- xExpectedSpaces = sbSTREAM_BUFFER_LENGTH_BYTES;
- xExpectedBytes = 0;
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedSpaces );
- xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedBytes );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
-
- /* Add a single item - number of bytes available should go up by one and spaces
- available down by one. Head is in front of tail. */
- xExpectedSpaces--;
- xExpectedBytes++;
- xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
- prvCheckExpectedState( xReturned == sizeof( *pucData ) );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedSpaces );
- xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedBytes );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
-
- /* Now fill the buffer by adding another 29 bytes. Head is 30 tail is at 0. */
- xExpectedSpaces -= 29;
- xExpectedBytes += 29;
- xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, ( sbSTREAM_BUFFER_LENGTH_BYTES - 1 ), ( TickType_t ) 0 );
- prvCheckExpectedState( xReturned == ( sbSTREAM_BUFFER_LENGTH_BYTES - 1 ) );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedSpaces );
- xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedBytes );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
-
- /* Should not be able to add another byte now. */
- xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
- prvCheckExpectedState( xReturned == ( size_t ) 0 );
-
- /* Remove a byte so the tail pointer moves off 0. Head pointer remains at the
- end of the buffer. */
- xExpectedSpaces += 1;
- xExpectedBytes -= 1;
- xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
- prvCheckExpectedState( xReturned == sizeof( *pucData ) );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedSpaces );
- xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedBytes );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
-
- /* Should be able to add another byte to fill the buffer again now. */
- xExpectedSpaces -= 1;
- xExpectedBytes += 1;
- xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
- prvCheckExpectedState( xReturned == sizeof( *pucData ) );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedSpaces );
- xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedBytes );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
-
- /* Now the head pointer is behind the tail pointer. Read another 29 bytes so
- the tail pointer moves to the end of the buffer. */
- xExpectedSpaces += 29;
- xExpectedBytes -= 29;
- xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, ( size_t ) 29, ( TickType_t ) 0 );
- prvCheckExpectedState( xReturned == ( size_t ) 29 );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedSpaces );
- xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedBytes );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
-
- /* Read out one more byte to wrap the tail back around to the start, to get back
- to where we started. */
- xExpectedSpaces += 1;
- xExpectedBytes -= 1;
- xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
- prvCheckExpectedState( xReturned == sizeof( *pucData ) );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedSpaces );
- xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedBytes );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
-
- /* Try filling the message buffer in one write, blocking indefinitely. Expect to
- have written one byte less. */
- xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, xTrueSize, portMAX_DELAY );
- xExpectedSpaces = ( size_t ) 0;
- prvCheckExpectedState( xReturned == ( xTrueSize - ( size_t ) 1 ) );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == xExpectedSpaces );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
-
- /* Empty the buffer again ready for the rest of the tests. Again block
- indefinitely to ensure reading more than there can possible be won't lock this
- task up, so expect to actually receive one byte less than requested. */
- xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, xTrueSize, portMAX_DELAY );
- prvCheckExpectedState( xReturned == ( xTrueSize - ( size_t ) 1 ) );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == sbSTREAM_BUFFER_LENGTH_BYTES );
- xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == ( size_t ) 0 );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
-
-
- /* The buffer is 30 bytes long. 6 5 byte messages should fit before the
- buffer is completely full. */
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
- {
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
-
- /* Generate recognisable data to write to the buffer. This is just
- ascii characters that shows which loop iteration the data was written
- in. The 'FromISR' version is used to give it some exercise as a block
- time is not used, so the call must be inside a critical section so it
- runs with ports that don't support interrupt nesting (and therefore
- don't have interrupt safe critical sections). */
- memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
- taskENTER_CRITICAL();
- {
- xReturned = xStreamBufferSendFromISR( xStreamBuffer, ( void * ) pucData, x6ByteLength, NULL );
- }
- taskEXIT_CRITICAL();
- prvCheckExpectedState( xReturned == x6ByteLength );
-
- /* The space in the buffer will have reduced by the amount of user data
- written into the buffer. */
- xExpected -= x6ByteLength;
- xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xReturned == xExpected );
- xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
- /* +1 as it is zero indexed. */
- prvCheckExpectedState( xReturned == ( ( xItem + 1 ) * x6ByteLength ) );
- }
-
- /* Now the buffer should be full, and attempting to add anything should fail. */
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
- xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), sbDONT_BLOCK );
- prvCheckExpectedState( xReturned == 0 );
-
- /* Adding with a timeout should also fail after the appropriate time. The
- priority is temporarily boosted in this part of the test to keep the
- allowable margin to a minimum. */
- uxOriginalPriority = uxTaskPriorityGet( NULL );
- vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
- xTimeBeforeCall = xTaskGetTickCount();
- xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), xBlockTime );
- xTimeAfterCall = xTaskGetTickCount();
- vTaskPrioritySet( NULL, uxOriginalPriority );
- prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) >= xBlockTime );
- prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) < ( xBlockTime + xAllowableMargin ) );
- prvCheckExpectedState( xReturned == 0 );
-
- /* The buffer is now full of data in the form "000000", "111111", etc. Make
- sure the data is read out as expected. */
- for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
- {
- /* Generate the data that is expected to be read out for this loop
- iteration. */
- memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
-
- /* Read the next 6 bytes out. The 'FromISR' version is used to give it
- some exercise as a block time is not used, so a it must be called from
- a critical section so this will work on ports that don't support
- interrupt nesting (so don't have interrupt safe critical sections). */
- taskENTER_CRITICAL();
- {
- xReturned = xStreamBufferReceiveFromISR( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, NULL );
- }
- taskEXIT_CRITICAL();
- prvCheckExpectedState( xReturned == x6ByteLength );
-
- /* Does the data read out match that expected? */
- prvCheckExpectedState( memcmp( ( void * ) pucData, ( void * ) pucReadData, x6ByteLength ) == 0 );
-
- /* The space in the buffer will have increased by the amount of user
- data removed from the buffer. */
- xExpected += x6ByteLength;
- xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xReturned == xExpected );
- xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xReturned == ( sbSTREAM_BUFFER_LENGTH_BYTES - xExpected ) );
- }
-
- /* The buffer should be empty again. */
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
- xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xExpected == sbSTREAM_BUFFER_LENGTH_BYTES );
-
- /* Reading with a timeout should also fail after the appropriate time. The
- priority is temporarily boosted in this part of the test to keep the
- allowable margin to a minimum. */
- vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
- xTimeBeforeCall = xTaskGetTickCount();
- xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, xBlockTime );
- xTimeAfterCall = xTaskGetTickCount();
- vTaskPrioritySet( NULL, uxOriginalPriority );
- prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) >= xBlockTime );
- prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) < ( xBlockTime + xAllowableMargin ) );
- prvCheckExpectedState( xReturned == 0 );
-
-
- /* In the next loop 17 bytes are written to then read out on each
- iteration. As 30 is not divisible by 17 the data will wrap around. */
- xExpected = sbSTREAM_BUFFER_LENGTH_BYTES - x17ByteLength;
-
- for( xItem = 0; xItem < 100; xItem++ )
- {
- /* Generate recognisable data to write to the queue. This is just
- ascii characters that shows which loop iteration the data was written
- in. */
- memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x17ByteLength );
- xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, x17ByteLength, sbDONT_BLOCK );
- prvCheckExpectedState( xReturned == x17ByteLength );
-
- /* The space in the buffer will have reduced by the amount of user data
- written into the buffer. */
- xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xReturned == xExpected );
- xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xReturned == x17ByteLength );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
-
- /* Read the 17 bytes out again. */
- xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x17ByteLength, sbDONT_BLOCK );
- prvCheckExpectedState( xReturned == x17ByteLength );
-
- /* Does the data read out match that expected? */
- prvCheckExpectedState( memcmp( ( void * ) pucData, ( void * ) pucReadData, x17ByteLength ) == 0 );
-
- /* Full buffer space available again. */
- xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
- prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
- xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
- prvCheckExpectedState( xReturned == 0 );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
- }
-
- /* Fill the buffer with one message, check it is full, then read it back
- again and check the correct data is received. */
- xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
- xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
- prvCheckExpectedState( memcmp( pc55ByteString, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
-
- /* Fill the buffer one bytes at a time. */
- for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
- {
- /* Block time is only for test coverage, the task should never actually
- block here. */
- xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc54ByteString[ xItem ] ), sizeof( char ), sbRX_TX_BLOCK_TIME );
- }
-
- /* The buffer should now be full. */
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
-
- /* Read the message out in one go, even though it was written in individual
- bytes. Try reading much more data than is actually available to ensure only
- the available bytes are returned (otherwise this read will write outside of
- the memory allocated anyway!). */
- xReturned = xStreamBufferReceive( xStreamBuffer, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, sbRX_TX_BLOCK_TIME );
- prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
- prvCheckExpectedState( memcmp( ( const void * ) pc54ByteString, ( const void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
-
- /* Now do the opposite, write in one go and read out in single bytes. */
- xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES, sbRX_TX_BLOCK_TIME );
- prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferBytesAvailable( xStreamBuffer ) == sbSTREAM_BUFFER_LENGTH_BYTES );
- prvCheckExpectedState( xStreamBufferSpacesAvailable( xStreamBuffer ) == 0 );
-
- /* Read from the buffer one byte at a time. */
- for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
- {
- /* Block time is only for test coverage, the task should never actually
- block here. */
- xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sizeof( char ), sbRX_TX_BLOCK_TIME );
- prvCheckExpectedState( pc55ByteString[ xItem ] == pucFullBuffer[ 0 ] );
- }
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
-
- /* Try writing more bytes than there is space. */
- vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
- xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, xMinimalBlockTime );
- vTaskPrioritySet( NULL, uxOriginalPriority );
- prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
-
- /* No space now though. */
- xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, xMinimalBlockTime );
- prvCheckExpectedState( xReturned == 0 );
-
- /* Ensure data was written as expected even when there was an attempt to
- write more than was available. This also tries to read more bytes than are
- available. */
- xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, xFullBufferSize, xMinimalBlockTime );
- prvCheckExpectedState( memcmp( ( const void * ) pucFullBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
- prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
- prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
-
- /* Clean up with data in the buffer to ensure the tests that follow don't
- see the data (the data should be discarded). */
- ( void ) xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES / ( size_t ) 2, sbDONT_BLOCK );
- vPortFree( pucFullBuffer );
- xStreamBufferReset( xStreamBuffer );
+ size_t xReturned, xItem, xExpected, xExpectedSpaces, xExpectedBytes;
+ const size_t xMax6ByteMessages = sbSTREAM_BUFFER_LENGTH_BYTES / 6;
+ const size_t xTrueSize = ( sizeof( ucBufferStorage ) / sbNUMBER_OF_SENDER_TASKS );
+ const size_t x6ByteLength = 6, x17ByteLength = 17, xFullBufferSize = sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2;
+ uint8_t * pucFullBuffer, * pucData, * pucReadData;
+ TickType_t xTimeBeforeCall, xTimeAfterCall;
+ const TickType_t xBlockTime = pdMS_TO_TICKS( 15 ), xAllowableMargin = pdMS_TO_TICKS( 3 ), xMinimalBlockTime = 2;
+ UBaseType_t uxOriginalPriority;
+
+ /* Remove warning in case configASSERT() is not defined. */
+ ( void ) xAllowableMargin;
+
+ /* To minimise stack and heap usage a full size buffer is allocated from the
+ * heap, then buffers which hold smaller amounts of data are overlayed with the
+ * larger buffer - just make sure not to use both at once! */
+ pucFullBuffer = pvPortMalloc( xFullBufferSize );
+ configASSERT( pucFullBuffer );
+
+ pucData = pucFullBuffer;
+ pucReadData = pucData + x17ByteLength;
+
+ /* Nothing has been added or removed yet, so expect the free space to be
+ * exactly as created. Head and tail are both at 0. */
+ xExpectedSpaces = sbSTREAM_BUFFER_LENGTH_BYTES;
+ xExpectedBytes = 0;
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedSpaces );
+ xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedBytes );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+
+ /* Add a single item - number of bytes available should go up by one and spaces
+ * available down by one. Head is in front of tail. */
+ xExpectedSpaces--;
+ xExpectedBytes++;
+ xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
+ prvCheckExpectedState( xReturned == sizeof( *pucData ) );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedSpaces );
+ xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedBytes );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+
+ /* Now fill the buffer by adding another 29 bytes. Head is 30 tail is at 0. */
+ xExpectedSpaces -= 29;
+ xExpectedBytes += 29;
+ xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, ( sbSTREAM_BUFFER_LENGTH_BYTES - 1 ), ( TickType_t ) 0 );
+ prvCheckExpectedState( xReturned == ( sbSTREAM_BUFFER_LENGTH_BYTES - 1 ) );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedSpaces );
+ xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedBytes );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
+
+ /* Should not be able to add another byte now. */
+ xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
+ prvCheckExpectedState( xReturned == ( size_t ) 0 );
+
+ /* Remove a byte so the tail pointer moves off 0. Head pointer remains at the
+ * end of the buffer. */
+ xExpectedSpaces += 1;
+ xExpectedBytes -= 1;
+ xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
+ prvCheckExpectedState( xReturned == sizeof( *pucData ) );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedSpaces );
+ xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedBytes );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+
+ /* Should be able to add another byte to fill the buffer again now. */
+ xExpectedSpaces -= 1;
+ xExpectedBytes += 1;
+ xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
+ prvCheckExpectedState( xReturned == sizeof( *pucData ) );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedSpaces );
+ xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedBytes );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
+
+ /* Now the head pointer is behind the tail pointer. Read another 29 bytes so
+ * the tail pointer moves to the end of the buffer. */
+ xExpectedSpaces += 29;
+ xExpectedBytes -= 29;
+ xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, ( size_t ) 29, ( TickType_t ) 0 );
+ prvCheckExpectedState( xReturned == ( size_t ) 29 );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedSpaces );
+ xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedBytes );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+
+ /* Read out one more byte to wrap the tail back around to the start, to get back
+ * to where we started. */
+ xExpectedSpaces += 1;
+ xExpectedBytes -= 1;
+ xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
+ prvCheckExpectedState( xReturned == sizeof( *pucData ) );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedSpaces );
+ xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedBytes );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+
+ /* Try filling the message buffer in one write, blocking indefinitely. Expect to
+ * have written one byte less. */
+ xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, xTrueSize, portMAX_DELAY );
+ xExpectedSpaces = ( size_t ) 0;
+ prvCheckExpectedState( xReturned == ( xTrueSize - ( size_t ) 1 ) );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == xExpectedSpaces );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
+
+ /* Empty the buffer again ready for the rest of the tests. Again block
+ * indefinitely to ensure reading more than there can possible be won't lock this
+ * task up, so expect to actually receive one byte less than requested. */
+ xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, xTrueSize, portMAX_DELAY );
+ prvCheckExpectedState( xReturned == ( xTrueSize - ( size_t ) 1 ) );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == sbSTREAM_BUFFER_LENGTH_BYTES );
+ xExpected = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == ( size_t ) 0 );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+
+
+ /* The buffer is 30 bytes long. 6 5 byte messages should fit before the
+ * buffer is completely full. */
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+
+ for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
+ {
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+
+ /* Generate recognisable data to write to the buffer. This is just
+ * ascii characters that shows which loop iteration the data was written
+ * in. The 'FromISR' version is used to give it some exercise as a block
+ * time is not used, so the call must be inside a critical section so it
+ * runs with ports that don't support interrupt nesting (and therefore
+ * don't have interrupt safe critical sections). */
+ memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
+ taskENTER_CRITICAL();
+ {
+ xReturned = xStreamBufferSendFromISR( xStreamBuffer, ( void * ) pucData, x6ByteLength, NULL );
+ }
+ taskEXIT_CRITICAL();
+ prvCheckExpectedState( xReturned == x6ByteLength );
+
+ /* The space in the buffer will have reduced by the amount of user data
+ * written into the buffer. */
+ xExpected -= x6ByteLength;
+ xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xReturned == xExpected );
+ xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
+ /* +1 as it is zero indexed. */
+ prvCheckExpectedState( xReturned == ( ( xItem + 1 ) * x6ByteLength ) );
+ }
+
+ /* Now the buffer should be full, and attempting to add anything should fail. */
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
+ xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), sbDONT_BLOCK );
+ prvCheckExpectedState( xReturned == 0 );
+
+ /* Adding with a timeout should also fail after the appropriate time. The
+ * priority is temporarily boosted in this part of the test to keep the
+ * allowable margin to a minimum. */
+ uxOriginalPriority = uxTaskPriorityGet( NULL );
+ vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
+ xTimeBeforeCall = xTaskGetTickCount();
+ xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), xBlockTime );
+ xTimeAfterCall = xTaskGetTickCount();
+ vTaskPrioritySet( NULL, uxOriginalPriority );
+ prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) >= xBlockTime );
+ prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) < ( xBlockTime + xAllowableMargin ) );
+ prvCheckExpectedState( xReturned == 0 );
+
+ /* The buffer is now full of data in the form "000000", "111111", etc. Make
+ * sure the data is read out as expected. */
+ for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
+ {
+ /* Generate the data that is expected to be read out for this loop
+ * iteration. */
+ memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
+
+ /* Read the next 6 bytes out. The 'FromISR' version is used to give it
+ * some exercise as a block time is not used, so a it must be called from
+ * a critical section so this will work on ports that don't support
+ * interrupt nesting (so don't have interrupt safe critical sections). */
+ taskENTER_CRITICAL();
+ {
+ xReturned = xStreamBufferReceiveFromISR( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, NULL );
+ }
+ taskEXIT_CRITICAL();
+ prvCheckExpectedState( xReturned == x6ByteLength );
+
+ /* Does the data read out match that expected? */
+ prvCheckExpectedState( memcmp( ( void * ) pucData, ( void * ) pucReadData, x6ByteLength ) == 0 );
+
+ /* The space in the buffer will have increased by the amount of user
+ * data removed from the buffer. */
+ xExpected += x6ByteLength;
+ xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xReturned == xExpected );
+ xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xReturned == ( sbSTREAM_BUFFER_LENGTH_BYTES - xExpected ) );
+ }
+
+ /* The buffer should be empty again. */
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
+ xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xExpected == sbSTREAM_BUFFER_LENGTH_BYTES );
+
+ /* Reading with a timeout should also fail after the appropriate time. The
+ * priority is temporarily boosted in this part of the test to keep the
+ * allowable margin to a minimum. */
+ vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
+ xTimeBeforeCall = xTaskGetTickCount();
+ xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, xBlockTime );
+ xTimeAfterCall = xTaskGetTickCount();
+ vTaskPrioritySet( NULL, uxOriginalPriority );
+ prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) >= xBlockTime );
+ prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) < ( xBlockTime + xAllowableMargin ) );
+ prvCheckExpectedState( xReturned == 0 );
+
+
+ /* In the next loop 17 bytes are written to then read out on each
+ * iteration. As 30 is not divisible by 17 the data will wrap around. */
+ xExpected = sbSTREAM_BUFFER_LENGTH_BYTES - x17ByteLength;
+
+ for( xItem = 0; xItem < 100; xItem++ )
+ {
+ /* Generate recognisable data to write to the queue. This is just
+ * ascii characters that shows which loop iteration the data was written
+ * in. */
+ memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x17ByteLength );
+ xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, x17ByteLength, sbDONT_BLOCK );
+ prvCheckExpectedState( xReturned == x17ByteLength );
+
+ /* The space in the buffer will have reduced by the amount of user data
+ * written into the buffer. */
+ xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xReturned == xExpected );
+ xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xReturned == x17ByteLength );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+
+ /* Read the 17 bytes out again. */
+ xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x17ByteLength, sbDONT_BLOCK );
+ prvCheckExpectedState( xReturned == x17ByteLength );
+
+ /* Does the data read out match that expected? */
+ prvCheckExpectedState( memcmp( ( void * ) pucData, ( void * ) pucReadData, x17ByteLength ) == 0 );
+
+ /* Full buffer space available again. */
+ xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
+ xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
+ prvCheckExpectedState( xReturned == 0 );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
+ }
+
+ /* Fill the buffer with one message, check it is full, then read it back
+ * again and check the correct data is received. */
+ xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
+ xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
+ prvCheckExpectedState( memcmp( pc55ByteString, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
+
+ /* Fill the buffer one bytes at a time. */
+ for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
+ {
+ /* Block time is only for test coverage, the task should never actually
+ * block here. */
+ xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc54ByteString[ xItem ] ), sizeof( char ), sbRX_TX_BLOCK_TIME );
+ }
+
+ /* The buffer should now be full. */
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
+
+ /* Read the message out in one go, even though it was written in individual
+ * bytes. Try reading much more data than is actually available to ensure only
+ * the available bytes are returned (otherwise this read will write outside of
+ * the memory allocated anyway!). */
+ xReturned = xStreamBufferReceive( xStreamBuffer, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, sbRX_TX_BLOCK_TIME );
+ prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
+ prvCheckExpectedState( memcmp( ( const void * ) pc54ByteString, ( const void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
+
+ /* Now do the opposite, write in one go and read out in single bytes. */
+ xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES, sbRX_TX_BLOCK_TIME );
+ prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferBytesAvailable( xStreamBuffer ) == sbSTREAM_BUFFER_LENGTH_BYTES );
+ prvCheckExpectedState( xStreamBufferSpacesAvailable( xStreamBuffer ) == 0 );
+
+ /* Read from the buffer one byte at a time. */
+ for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
+ {
+ /* Block time is only for test coverage, the task should never actually
+ * block here. */
+ xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sizeof( char ), sbRX_TX_BLOCK_TIME );
+ prvCheckExpectedState( pc55ByteString[ xItem ] == pucFullBuffer[ 0 ] );
+ }
+
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+
+ /* Try writing more bytes than there is space. */
+ vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
+ xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, xMinimalBlockTime );
+ vTaskPrioritySet( NULL, uxOriginalPriority );
+ prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
+
+ /* No space now though. */
+ xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, xMinimalBlockTime );
+ prvCheckExpectedState( xReturned == 0 );
+
+ /* Ensure data was written as expected even when there was an attempt to
+ * write more than was available. This also tries to read more bytes than are
+ * available. */
+ xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, xFullBufferSize, xMinimalBlockTime );
+ prvCheckExpectedState( memcmp( ( const void * ) pucFullBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
+ prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
+ prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
+
+ /* Clean up with data in the buffer to ensure the tests that follow don't
+ * see the data (the data should be discarded). */
+ ( void ) xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES / ( size_t ) 2, sbDONT_BLOCK );
+ vPortFree( pucFullBuffer );
+ xStreamBufferReset( xStreamBuffer );
}
/*-----------------------------------------------------------*/
-static void prvNonBlockingSenderTask( void *pvParameters )
+static void prvNonBlockingSenderTask( void * pvParameters )
{
-StreamBufferHandle_t xStreamBuffer;
-size_t xNextChar = 0, xBytesToSend, xBytesActuallySent;
-const size_t xStringLength = strlen( pc54ByteString );
-
- /* In this case the stream buffer has already been created and is passed
- into the task using the task's parameter. */
- xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
-
- /* Keep sending the string to the stream buffer as many bytes as possible in
- each go. Doesn't block so calls can interleave with the non-blocking
- receives performed by prvNonBlockingReceiverTask(). */
- for( ;; )
- {
- /* The whole string cannot be sent at once, so xNextChar is an index to
- the position within the string that has been sent so far. How many
- bytes are there left to send before the end of the string? */
- xBytesToSend = xStringLength - xNextChar;
-
- /* Attempt to send right up to the end of the string. */
- xBytesActuallySent = xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc54ByteString[ xNextChar ] ), xBytesToSend, sbDONT_BLOCK );
- prvCheckExpectedState( xBytesActuallySent <= xBytesToSend );
-
- /* Move the index up the string to the next character to be sent,
- wrapping if the end of the string has been reached. */
- xNextChar += xBytesActuallySent;
- prvCheckExpectedState( xNextChar <= xStringLength );
-
- if( xNextChar == xStringLength )
- {
- xNextChar = 0;
- }
- }
+ StreamBufferHandle_t xStreamBuffer;
+ size_t xNextChar = 0, xBytesToSend, xBytesActuallySent;
+ const size_t xStringLength = strlen( pc54ByteString );
+
+ /* In this case the stream buffer has already been created and is passed
+ * into the task using the task's parameter. */
+ xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
+
+ /* Keep sending the string to the stream buffer as many bytes as possible in
+ * each go. Doesn't block so calls can interleave with the non-blocking
+ * receives performed by prvNonBlockingReceiverTask(). */
+ for( ; ; )
+ {
+ /* The whole string cannot be sent at once, so xNextChar is an index to
+ * the position within the string that has been sent so far. How many
+ * bytes are there left to send before the end of the string? */
+ xBytesToSend = xStringLength - xNextChar;
+
+ /* Attempt to send right up to the end of the string. */
+ xBytesActuallySent = xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc54ByteString[ xNextChar ] ), xBytesToSend, sbDONT_BLOCK );
+ prvCheckExpectedState( xBytesActuallySent <= xBytesToSend );
+
+ /* Move the index up the string to the next character to be sent,
+ * wrapping if the end of the string has been reached. */
+ xNextChar += xBytesActuallySent;
+ prvCheckExpectedState( xNextChar <= xStringLength );
+
+ if( xNextChar == xStringLength )
+ {
+ xNextChar = 0;
+ }
+ }
}
/*-----------------------------------------------------------*/
-static void prvNonBlockingReceiverTask( void *pvParameters )
+static void prvNonBlockingReceiverTask( void * pvParameters )
{
-StreamBufferHandle_t xStreamBuffer;
-size_t xNextChar = 0, xReceiveLength, xBytesToTest, xStartIndex;
-const size_t xStringLength = strlen( pc54ByteString );
-char cRxString[ 12 ]; /* Holds received characters. */
-BaseType_t xNonBlockingReceiveError = pdFALSE;
-
- /* In this case the stream buffer has already been created and is passed
- into the task using the task's parameter. */
- xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
-
- /* Expects to receive the pc54ByteString over and over again. Sends and
- receives are not blocking so will interleave. */
- for( ;; )
- {
- /* Attempt to receive as many bytes as possible, up to the limit of the
- Rx buffer size. */
- xReceiveLength = xStreamBufferReceive( xStreamBuffer, ( void * ) cRxString, sizeof( cRxString ), sbDONT_BLOCK );
-
- if( xReceiveLength > 0 )
- {
- /* xNextChar is the index into pc54ByteString that has been received
- already. If xReceiveLength bytes are added to that, will it go off
- the end of the string? If so, then first test up to the end of the
- string, then go back to the start of pc54ByteString to test the
- remains of the received data. */
- xBytesToTest = xReceiveLength;
- if( ( xNextChar + xBytesToTest ) > xStringLength )
- {
- /* Cap to test the received data to the end of the string. */
- xBytesToTest = xStringLength - xNextChar;
-
- if( memcmp( ( const void * ) &( pc54ByteString[ xNextChar ] ), ( const void * ) cRxString, xBytesToTest ) != 0 )
- {
- xNonBlockingReceiveError = pdTRUE;
- }
-
- /* Then move back to the start of the string to test the
- remaining received bytes. */
- xNextChar = 0;
- xStartIndex = xBytesToTest;
- xBytesToTest = xReceiveLength - xBytesToTest;
- }
- else
- {
- /* The string didn't wrap in the buffer, so start comparing from
- the start of the received data. */
- xStartIndex = 0;
- }
-
- /* Test the received bytes are as expected, then move the index
- along the string to the next expected char to receive. */
- if( memcmp( ( const void * ) &( pc54ByteString[ xNextChar ] ), ( const void * ) &( cRxString[ xStartIndex ] ), xBytesToTest ) != 0 )
- {
- xNonBlockingReceiveError = pdTRUE;
- }
-
- if( xNonBlockingReceiveError == pdFALSE )
- {
- /* No errors detected so increment the counter that lets the
- check task know this test is still functioning correctly. */
- ulNonBlockingRxCounter++;
- }
-
- xNextChar += xBytesToTest;
- if( xNextChar >= xStringLength )
- {
- xNextChar = 0;
- }
- }
- }
+ StreamBufferHandle_t xStreamBuffer;
+ size_t xNextChar = 0, xReceiveLength, xBytesToTest, xStartIndex;
+ const size_t xStringLength = strlen( pc54ByteString );
+ char cRxString[ 12 ]; /* Holds received characters. */
+ BaseType_t xNonBlockingReceiveError = pdFALSE;
+
+ /* In this case the stream buffer has already been created and is passed
+ * into the task using the task's parameter. */
+ xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
+
+ /* Expects to receive the pc54ByteString over and over again. Sends and
+ * receives are not blocking so will interleave. */
+ for( ; ; )
+ {
+ /* Attempt to receive as many bytes as possible, up to the limit of the
+ * Rx buffer size. */
+ xReceiveLength = xStreamBufferReceive( xStreamBuffer, ( void * ) cRxString, sizeof( cRxString ), sbDONT_BLOCK );
+
+ if( xReceiveLength > 0 )
+ {
+ /* xNextChar is the index into pc54ByteString that has been received
+ * already. If xReceiveLength bytes are added to that, will it go off
+ * the end of the string? If so, then first test up to the end of the
+ * string, then go back to the start of pc54ByteString to test the
+ * remains of the received data. */
+ xBytesToTest = xReceiveLength;
+
+ if( ( xNextChar + xBytesToTest ) > xStringLength )
+ {
+ /* Cap to test the received data to the end of the string. */
+ xBytesToTest = xStringLength - xNextChar;
+
+ if( memcmp( ( const void * ) &( pc54ByteString[ xNextChar ] ), ( const void * ) cRxString, xBytesToTest ) != 0 )
+ {
+ xNonBlockingReceiveError = pdTRUE;
+ }
+
+ /* Then move back to the start of the string to test the
+ * remaining received bytes. */
+ xNextChar = 0;
+ xStartIndex = xBytesToTest;
+ xBytesToTest = xReceiveLength - xBytesToTest;
+ }
+ else
+ {
+ /* The string didn't wrap in the buffer, so start comparing from
+ * the start of the received data. */
+ xStartIndex = 0;
+ }
+
+ /* Test the received bytes are as expected, then move the index
+ * along the string to the next expected char to receive. */
+ if( memcmp( ( const void * ) &( pc54ByteString[ xNextChar ] ), ( const void * ) &( cRxString[ xStartIndex ] ), xBytesToTest ) != 0 )
+ {
+ xNonBlockingReceiveError = pdTRUE;
+ }
+
+ if( xNonBlockingReceiveError == pdFALSE )
+ {
+ /* No errors detected so increment the counter that lets the
+ * check task know this test is still functioning correctly. */
+ ulNonBlockingRxCounter++;
+ }
+
+ xNextChar += xBytesToTest;
+
+ if( xNextChar >= xStringLength )
+ {
+ xNextChar = 0;
+ }
+ }
+ }
}
/*-----------------------------------------------------------*/
-#if( configSUPPORT_STATIC_ALLOCATION == 1 )
-
- static void prvSenderTask( void *pvParameters )
- {
- StreamBufferHandle_t xStreamBuffer, xTempStreamBuffer;
- static uint8_t ucTempBuffer[ 10 ]; /* Just used to exercise stream buffer creating and deletion. */
- const TickType_t xTicksToWait = sbRX_TX_BLOCK_TIME, xShortDelay = pdMS_TO_TICKS( 50 );
- StaticStreamBuffer_t xStaticStreamBuffer;
- size_t xNextChar = 0, xBytesToSend, xBytesActuallySent;
- const size_t xStringLength = strlen( pc55ByteString );
-
- /* The task's priority is used as an index into the loop counters used to
- indicate this task is still running. */
- UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
-
- /* Make sure a change in priority does not inadvertently result in an
- invalid array index. */
- prvCheckExpectedState( uxIndex < sbNUMBER_OF_ECHO_CLIENTS );
-
- /* Avoid compiler warnings about unused parameters. */
- ( void ) pvParameters;
-
- xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ) / sbNUMBER_OF_SENDER_TASKS, /* The number of bytes in each buffer in the array. */
- sbTRIGGER_LEVEL_1, /* The number of bytes to be in the buffer before a task blocked to wait for data is unblocked. */
- &( ucBufferStorage[ uxIndex ][ 0 ] ), /* The address of the buffer to use within the array. */
- &( xStaticStreamBuffers[ uxIndex ] ) ); /* The static stream buffer structure to use within the array. */
-
- /* Now the stream buffer has been created the receiver task can be
- created. If this sender task has the higher priority then the receiver
- task is created at the lower priority - if this sender task has the
- lower priority then the receiver task is created at the higher
- priority. */
- if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
- {
- /* Here prvSingleTaskTests() performs various tests on a stream buffer
- that was created statically. */
- prvSingleTaskTests( xStreamBuffer );
- xTaskCreate( prvReceiverTask, "StrReceiver", sbSMALLER_STACK_SIZE, ( void * ) xStreamBuffer, sbHIGHER_PRIORITY, NULL );
- }
- else
- {
- xTaskCreate( prvReceiverTask, "StrReceiver", sbSMALLER_STACK_SIZE, ( void * ) xStreamBuffer, sbLOWER_PRIORITY, NULL );
- }
-
- for( ;; )
- {
- /* The whole string cannot be sent at once, so xNextChar is an index
- to the position within the string that has been sent so far. How
- many bytes are there left to send before the end of the string? */
- xBytesToSend = xStringLength - xNextChar;
-
- /* Attempt to send right up to the end of the string. */
- xBytesActuallySent = xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc55ByteString[ xNextChar ] ), xBytesToSend, xTicksToWait );
- prvCheckExpectedState( xBytesActuallySent <= xBytesToSend );
-
- /* Move the index up the string to the next character to be sent,
- wrapping if the end of the string has been reached. */
- xNextChar += xBytesActuallySent;
- prvCheckExpectedState( xNextChar <= xStringLength );
-
- if( xNextChar == xStringLength )
- {
- xNextChar = 0;
- }
-
- /* Increment a loop counter so a check task can tell this task is
- still running as expected. */
- ulSenderLoopCounters[ uxIndex ]++;
-
- if( uxTaskPriorityGet( NULL ) == sbHIGHER_PRIORITY )
- {
- /* Allow other tasks to run. */
- vTaskDelay( xShortDelay );
- }
-
- /* This stream buffer is just created and deleted to ensure no
- issues when attempting to delete a stream buffer that was
- created using statically allocated memory. To save stack space
- the buffer is set to point to the pc55ByteString, which is a const
- string, but no data is written into the buffer so any valid address
- will do. */
- xTempStreamBuffer = xStreamBufferCreateStatic( sizeof( ucTempBuffer ), sbTRIGGER_LEVEL_1, ucTempBuffer, &xStaticStreamBuffer );
- xStreamBufferReset( xTempStreamBuffer );
- vStreamBufferDelete( xTempStreamBuffer );
- }
- }
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ static void prvSenderTask( void * pvParameters )
+ {
+ StreamBufferHandle_t xStreamBuffer, xTempStreamBuffer;
+ static uint8_t ucTempBuffer[ 10 ]; /* Just used to exercise stream buffer creating and deletion. */
+ const TickType_t xTicksToWait = sbRX_TX_BLOCK_TIME, xShortDelay = pdMS_TO_TICKS( 50 );
+ StaticStreamBuffer_t xStaticStreamBuffer;
+ size_t xNextChar = 0, xBytesToSend, xBytesActuallySent;
+ const size_t xStringLength = strlen( pc55ByteString );
+
+ /* The task's priority is used as an index into the loop counters used to
+ * indicate this task is still running. */
+ UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
+
+ /* Make sure a change in priority does not inadvertently result in an
+ * invalid array index. */
+ prvCheckExpectedState( uxIndex < sbNUMBER_OF_ECHO_CLIENTS );
+
+ /* Avoid compiler warnings about unused parameters. */
+ ( void ) pvParameters;
+
+ xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ) / sbNUMBER_OF_SENDER_TASKS, /* The number of bytes in each buffer in the array. */
+ sbTRIGGER_LEVEL_1, /* The number of bytes to be in the buffer before a task blocked to wait for data is unblocked. */
+ &( ucBufferStorage[ uxIndex ][ 0 ] ), /* The address of the buffer to use within the array. */
+ &( xStaticStreamBuffers[ uxIndex ] ) ); /* The static stream buffer structure to use within the array. */
+
+ /* Now the stream buffer has been created the receiver task can be
+ * created. If this sender task has the higher priority then the receiver
+ * task is created at the lower priority - if this sender task has the
+ * lower priority then the receiver task is created at the higher
+ * priority. */
+ if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
+ {
+ /* Here prvSingleTaskTests() performs various tests on a stream buffer
+ * that was created statically. */
+ prvSingleTaskTests( xStreamBuffer );
+ xTaskCreate( prvReceiverTask, "StrReceiver", sbSMALLER_STACK_SIZE, ( void * ) xStreamBuffer, sbHIGHER_PRIORITY, NULL );
+ }
+ else
+ {
+ xTaskCreate( prvReceiverTask, "StrReceiver", sbSMALLER_STACK_SIZE, ( void * ) xStreamBuffer, sbLOWER_PRIORITY, NULL );
+ }
+
+ for( ; ; )
+ {
+ /* The whole string cannot be sent at once, so xNextChar is an index
+ * to the position within the string that has been sent so far. How
+ * many bytes are there left to send before the end of the string? */
+ xBytesToSend = xStringLength - xNextChar;
+
+ /* Attempt to send right up to the end of the string. */
+ xBytesActuallySent = xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc55ByteString[ xNextChar ] ), xBytesToSend, xTicksToWait );
+ prvCheckExpectedState( xBytesActuallySent <= xBytesToSend );
+
+ /* Move the index up the string to the next character to be sent,
+ * wrapping if the end of the string has been reached. */
+ xNextChar += xBytesActuallySent;
+ prvCheckExpectedState( xNextChar <= xStringLength );
+
+ if( xNextChar == xStringLength )
+ {
+ xNextChar = 0;
+ }
+
+ /* Increment a loop counter so a check task can tell this task is
+ * still running as expected. */
+ ulSenderLoopCounters[ uxIndex ]++;
+
+ if( uxTaskPriorityGet( NULL ) == sbHIGHER_PRIORITY )
+ {
+ /* Allow other tasks to run. */
+ vTaskDelay( xShortDelay );
+ }
+
+ /* This stream buffer is just created and deleted to ensure no
+ * issues when attempting to delete a stream buffer that was
+ * created using statically allocated memory. To save stack space
+ * the buffer is set to point to the pc55ByteString, which is a const
+ * string, but no data is written into the buffer so any valid address
+ * will do. */
+ xTempStreamBuffer = xStreamBufferCreateStatic( sizeof( ucTempBuffer ), sbTRIGGER_LEVEL_1, ucTempBuffer, &xStaticStreamBuffer );
+ xStreamBufferReset( xTempStreamBuffer );
+ vStreamBufferDelete( xTempStreamBuffer );
+ }
+ }
#endif /* configSUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
-#if( configSUPPORT_STATIC_ALLOCATION == 1 )
-
- static void prvReceiverTask( void *pvParameters )
- {
- StreamBufferHandle_t const pxStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
- char cRxString[ 12 ]; /* Large enough to hold a 32-bit number in ASCII. */
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 5UL );
- const size_t xStringLength = strlen( pc55ByteString );
- size_t xNextChar = 0, xReceivedLength, xBytesToReceive;
-
- for( ;; )
- {
- /* Attempt to receive the number of bytes to the end of the string,
- or the number of byte that can be placed into the rx buffer,
- whichever is smallest. */
- xBytesToReceive = configMIN( ( xStringLength - xNextChar ), sizeof( cRxString ) );
-
- do
- {
- xReceivedLength = xStreamBufferReceive( pxStreamBuffer, ( void * ) cRxString, xBytesToReceive, xTicksToWait );
-
- } while( xReceivedLength == 0 );
-
- /* Ensure the received string matches the expected string. */
- prvCheckExpectedState( memcmp( ( void * ) cRxString, ( const void * ) &( pc55ByteString[ xNextChar ] ), xReceivedLength ) == 0 );
-
- /* Move the index into the string up to the end of the bytes
- received so far - wrapping if the end of the string has been
- reached. */
- xNextChar += xReceivedLength;
- if( xNextChar >= xStringLength )
- {
- xNextChar = 0;
- }
- }
- }
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ static void prvReceiverTask( void * pvParameters )
+ {
+ StreamBufferHandle_t const pxStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
+ char cRxString[ 12 ]; /* Large enough to hold a 32-bit number in ASCII. */
+ const TickType_t xTicksToWait = pdMS_TO_TICKS( 5UL );
+ const size_t xStringLength = strlen( pc55ByteString );
+ size_t xNextChar = 0, xReceivedLength, xBytesToReceive;
+
+ for( ; ; )
+ {
+ /* Attempt to receive the number of bytes to the end of the string,
+ * or the number of byte that can be placed into the rx buffer,
+ * whichever is smallest. */
+ xBytesToReceive = configMIN( ( xStringLength - xNextChar ), sizeof( cRxString ) );
+
+ do
+ {
+ xReceivedLength = xStreamBufferReceive( pxStreamBuffer, ( void * ) cRxString, xBytesToReceive, xTicksToWait );
+ } while( xReceivedLength == 0 );
+
+ /* Ensure the received string matches the expected string. */
+ prvCheckExpectedState( memcmp( ( void * ) cRxString, ( const void * ) &( pc55ByteString[ xNextChar ] ), xReceivedLength ) == 0 );
+
+ /* Move the index into the string up to the end of the bytes
+ * received so far - wrapping if the end of the string has been
+ * reached. */
+ xNextChar += xReceivedLength;
+
+ if( xNextChar >= xStringLength )
+ {
+ xNextChar = 0;
+ }
+ }
+ }
#endif /* configSUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
-static void prvEchoClient( void *pvParameters )
+static void prvEchoClient( void * pvParameters )
{
-size_t xSendLength = 0, ux;
-char *pcStringToSend, *pcStringReceived, cNextChar = sbASCII_SPACE;
-const TickType_t xTicksToWait = pdMS_TO_TICKS( 50 );
-StreamBufferHandle_t xTempStreamBuffer;
+ size_t xSendLength = 0, ux;
+ char * pcStringToSend, * pcStringReceived, cNextChar = sbASCII_SPACE;
+ const TickType_t xTicksToWait = pdMS_TO_TICKS( 50 );
+ StreamBufferHandle_t xTempStreamBuffer;
/* The task's priority is used as an index into the loop counters used to
-indicate this task is still running. */
-UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
+ * indicate this task is still running. */
+ UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
/* Pointers to the client and server stream buffers are passed into this task
-using the task's parameter. */
-EchoStreamBuffers_t *pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
-
- /* Prevent compiler warnings. */
- ( void ) pvParameters;
-
- /* Create the buffer into which strings to send to the server will be
- created, and the buffer into which strings echoed back from the server will
- be copied. */
- pcStringToSend = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
- pcStringReceived = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
-
- configASSERT( pcStringToSend );
- configASSERT( pcStringReceived );
-
- for( ;; )
- {
- /* Generate the length of the next string to send. */
- xSendLength++;
-
- /* The stream buffer is being used to hold variable length data, so
- each data item requires sizeof( size_t ) bytes to hold the data's
- length, hence the sizeof() in the if() condition below. */
- if( xSendLength > ( sbSTREAM_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) )
- {
- /* Back to a string length of 1. */
- xSendLength = sizeof( char );
- }
-
- memset( pcStringToSend, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
-
- for( ux = 0; ux < xSendLength; ux++ )
- {
- pcStringToSend[ ux ] = cNextChar;
-
- cNextChar++;
-
- if( cNextChar > sbASCII_TILDA )
- {
- cNextChar = sbASCII_SPACE;
- }
- }
-
- /* Send the generated string to the buffer. */
- do
- {
- ux = xStreamBufferSend( pxStreamBuffers->xEchoClientBuffer, ( void * ) pcStringToSend, xSendLength, xTicksToWait );
-
- } while( ux == 0 );
-
- /* Wait for the string to be echoed back. */
- memset( pcStringReceived, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
- xStreamBufferReceive( pxStreamBuffers->xEchoServerBuffer, ( void * ) pcStringReceived, xSendLength, portMAX_DELAY );
-
- prvCheckExpectedState( strcmp( pcStringToSend, pcStringReceived ) == 0 );
-
- /* Maintain a count of the number of times this code executes so a
- check task can determine if this task is still functioning as
- expected or not. As there are two client tasks, and the priorities
- used are 0 and 1, the task's priority is used as an index into the
- loop count array. */
- ulEchoLoopCounters[ uxIndex ]++;
-
- /* This stream buffer is just created and deleted to ensure no memory
- leaks. */
- xTempStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
- vStreamBufferDelete( xTempStreamBuffer );
-
- /* The following are tests for a stream buffer of size one. */
- /* Create a buffer of size one. */
- xTempStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_ONE, sbTRIGGER_LEVEL_1 );
- /* Ensure that the buffer was created successfully. */
- configASSERT( xTempStreamBuffer );
-
- /* Send one byte to the buffer. */
- ux = xStreamBufferSend( xTempStreamBuffer, ( void * ) pcStringToSend, ( size_t ) 1, sbDONT_BLOCK );
- /* Ensure that the byte was sent successfully. */
- configASSERT( ux == 1 );
- /* Try sending another byte to the buffer. */
- ux = xStreamBufferSend( xTempStreamBuffer, ( void * ) pcStringToSend, ( size_t ) 1, sbDONT_BLOCK );
- /* Make sure that send failed as the buffer is full. */
- configASSERT( ux == 0 );
-
- /* Receive one byte from the buffer. */
- memset( pcStringReceived, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
- ux = xStreamBufferReceive( xTempStreamBuffer, ( void * ) pcStringReceived, ( size_t ) 1, sbDONT_BLOCK );
- /* Ensure that the receive was successful. */
- configASSERT( ux == 1 );
- /* Ensure that the correct data was received. */
- configASSERT( pcStringToSend[ 0 ] == pcStringReceived[ 0 ] );
- /* Try receiving another byte from the buffer. */
- ux = xStreamBufferReceive( xTempStreamBuffer, ( void * ) pcStringReceived, ( size_t ) 1, sbDONT_BLOCK );
- /* Ensure that the receive failed as the buffer is empty. */
- configASSERT( ux == 0 );
-
- /* Try sending two bytes to the buffer. Since the size of the
- * buffer is one, we must not be able to send more than one. */
- ux = xStreamBufferSend( xTempStreamBuffer, ( void * ) pcStringToSend, ( size_t ) 2, sbDONT_BLOCK );
- /* Ensure that only one byte was sent. */
- configASSERT( ux == 1 );
-
- /* Try receiving two bytes from the buffer. Since the size of the
- * buffer is one, we must not be able to get more than one. */
- memset( pcStringReceived, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
- ux = xStreamBufferReceive( xTempStreamBuffer, ( void * ) pcStringReceived, ( size_t ) 2, sbDONT_BLOCK );
- /* Ensure that only one byte was received. */
- configASSERT( ux == 1 );
- /* Ensure that the correct data was received. */
- configASSERT( pcStringToSend[ 0 ] == pcStringReceived[ 0 ] );
-
- /* Delete the buffer. */
- vStreamBufferDelete( xTempStreamBuffer );
- }
+ * using the task's parameter. */
+ EchoStreamBuffers_t * pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
+
+ /* Prevent compiler warnings. */
+ ( void ) pvParameters;
+
+ /* Create the buffer into which strings to send to the server will be
+ * created, and the buffer into which strings echoed back from the server will
+ * be copied. */
+ pcStringToSend = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
+ pcStringReceived = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
+
+ configASSERT( pcStringToSend );
+ configASSERT( pcStringReceived );
+
+ for( ; ; )
+ {
+ /* Generate the length of the next string to send. */
+ xSendLength++;
+
+ /* The stream buffer is being used to hold variable length data, so
+ * each data item requires sizeof( size_t ) bytes to hold the data's
+ * length, hence the sizeof() in the if() condition below. */
+ if( xSendLength > ( sbSTREAM_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) )
+ {
+ /* Back to a string length of 1. */
+ xSendLength = sizeof( char );
+ }
+
+ memset( pcStringToSend, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
+
+ for( ux = 0; ux < xSendLength; ux++ )
+ {
+ pcStringToSend[ ux ] = cNextChar;
+
+ cNextChar++;
+
+ if( cNextChar > sbASCII_TILDA )
+ {
+ cNextChar = sbASCII_SPACE;
+ }
+ }
+
+ /* Send the generated string to the buffer. */
+ do
+ {
+ ux = xStreamBufferSend( pxStreamBuffers->xEchoClientBuffer, ( void * ) pcStringToSend, xSendLength, xTicksToWait );
+ } while( ux == 0 );
+
+ /* Wait for the string to be echoed back. */
+ memset( pcStringReceived, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
+ xStreamBufferReceive( pxStreamBuffers->xEchoServerBuffer, ( void * ) pcStringReceived, xSendLength, portMAX_DELAY );
+
+ prvCheckExpectedState( strcmp( pcStringToSend, pcStringReceived ) == 0 );
+
+ /* Maintain a count of the number of times this code executes so a
+ * check task can determine if this task is still functioning as
+ * expected or not. As there are two client tasks, and the priorities
+ * used are 0 and 1, the task's priority is used as an index into the
+ * loop count array. */
+ ulEchoLoopCounters[ uxIndex ]++;
+
+ /* This stream buffer is just created and deleted to ensure no memory
+ * leaks. */
+ xTempStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
+ vStreamBufferDelete( xTempStreamBuffer );
+
+ /* The following are tests for a stream buffer of size one. */
+ /* Create a buffer of size one. */
+ xTempStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_ONE, sbTRIGGER_LEVEL_1 );
+ /* Ensure that the buffer was created successfully. */
+ configASSERT( xTempStreamBuffer );
+
+ /* Send one byte to the buffer. */
+ ux = xStreamBufferSend( xTempStreamBuffer, ( void * ) pcStringToSend, ( size_t ) 1, sbDONT_BLOCK );
+ /* Ensure that the byte was sent successfully. */
+ configASSERT( ux == 1 );
+ /* Try sending another byte to the buffer. */
+ ux = xStreamBufferSend( xTempStreamBuffer, ( void * ) pcStringToSend, ( size_t ) 1, sbDONT_BLOCK );
+ /* Make sure that send failed as the buffer is full. */
+ configASSERT( ux == 0 );
+
+ /* Receive one byte from the buffer. */
+ memset( pcStringReceived, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
+ ux = xStreamBufferReceive( xTempStreamBuffer, ( void * ) pcStringReceived, ( size_t ) 1, sbDONT_BLOCK );
+ /* Ensure that the receive was successful. */
+ configASSERT( ux == 1 );
+ /* Ensure that the correct data was received. */
+ configASSERT( pcStringToSend[ 0 ] == pcStringReceived[ 0 ] );
+ /* Try receiving another byte from the buffer. */
+ ux = xStreamBufferReceive( xTempStreamBuffer, ( void * ) pcStringReceived, ( size_t ) 1, sbDONT_BLOCK );
+ /* Ensure that the receive failed as the buffer is empty. */
+ configASSERT( ux == 0 );
+
+ /* Try sending two bytes to the buffer. Since the size of the
+ * buffer is one, we must not be able to send more than one. */
+ ux = xStreamBufferSend( xTempStreamBuffer, ( void * ) pcStringToSend, ( size_t ) 2, sbDONT_BLOCK );
+ /* Ensure that only one byte was sent. */
+ configASSERT( ux == 1 );
+
+ /* Try receiving two bytes from the buffer. Since the size of the
+ * buffer is one, we must not be able to get more than one. */
+ memset( pcStringReceived, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
+ ux = xStreamBufferReceive( xTempStreamBuffer, ( void * ) pcStringReceived, ( size_t ) 2, sbDONT_BLOCK );
+ /* Ensure that only one byte was received. */
+ configASSERT( ux == 1 );
+ /* Ensure that the correct data was received. */
+ configASSERT( pcStringToSend[ 0 ] == pcStringReceived[ 0 ] );
+
+ /* Delete the buffer. */
+ vStreamBufferDelete( xTempStreamBuffer );
+ }
}
/*-----------------------------------------------------------*/
-static void prvEchoServer( void *pvParameters )
+static void prvEchoServer( void * pvParameters )
{
-size_t xReceivedLength;
-char *pcReceivedString;
-EchoStreamBuffers_t xStreamBuffers;
-TickType_t xTimeOnEntering;
-const TickType_t xTicksToBlock = pdMS_TO_TICKS( 350UL );
-
- /* Prevent compiler warnings about unused parameters. */
- ( void ) pvParameters;
-
- /* Create the stream buffer used to send data from the client to the server,
- and the stream buffer used to echo the data from the server back to the
- client. */
- xStreamBuffers.xEchoClientBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
- xStreamBuffers.xEchoServerBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
- configASSERT( xStreamBuffers.xEchoClientBuffer );
- configASSERT( xStreamBuffers.xEchoServerBuffer );
-
- /* Create the buffer into which received strings will be copied. */
- pcReceivedString = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
- configASSERT( pcReceivedString );
-
- /* Don't expect to receive anything yet! */
- xTimeOnEntering = xTaskGetTickCount();
- xReceivedLength = xStreamBufferReceive( xStreamBuffers.xEchoClientBuffer, ( void * ) pcReceivedString, sbSTREAM_BUFFER_LENGTH_BYTES, xTicksToBlock );
- prvCheckExpectedState( ( ( TickType_t ) ( xTaskGetTickCount() - xTimeOnEntering ) ) >= xTicksToBlock );
- prvCheckExpectedState( xReceivedLength == 0 );
-
- /* Now the stream buffers have been created the echo client task can be
- created. If this server task has the higher priority then the client task
- is created at the lower priority - if this server task has the lower
- priority then the client task is created at the higher priority. */
- if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
- {
- xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbHIGHER_PRIORITY, NULL );
- }
- else
- {
- /* Here prvSingleTaskTests() performs various tests on a stream buffer
- that was created dynamically. */
- prvSingleTaskTests( xStreamBuffers.xEchoClientBuffer );
- xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbLOWER_PRIORITY, NULL );
- }
-
- for( ;; )
- {
- memset( pcReceivedString, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
-
- /* Has any data been sent by the client? */
- xReceivedLength = xStreamBufferReceive( xStreamBuffers.xEchoClientBuffer, ( void * ) pcReceivedString, sbSTREAM_BUFFER_LENGTH_BYTES, portMAX_DELAY );
-
- /* Should always receive data as max delay was used. */
- prvCheckExpectedState( xReceivedLength > 0 );
-
- /* Echo the received data back to the client. */
- xStreamBufferSend( xStreamBuffers.xEchoServerBuffer, ( void * ) pcReceivedString, xReceivedLength, portMAX_DELAY );
- }
+ size_t xReceivedLength;
+ char * pcReceivedString;
+ EchoStreamBuffers_t xStreamBuffers;
+ TickType_t xTimeOnEntering;
+ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 350UL );
+
+ /* Prevent compiler warnings about unused parameters. */
+ ( void ) pvParameters;
+
+ /* Create the stream buffer used to send data from the client to the server,
+ * and the stream buffer used to echo the data from the server back to the
+ * client. */
+ xStreamBuffers.xEchoClientBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
+ xStreamBuffers.xEchoServerBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
+ configASSERT( xStreamBuffers.xEchoClientBuffer );
+ configASSERT( xStreamBuffers.xEchoServerBuffer );
+
+ /* Create the buffer into which received strings will be copied. */
+ pcReceivedString = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
+ configASSERT( pcReceivedString );
+
+ /* Don't expect to receive anything yet! */
+ xTimeOnEntering = xTaskGetTickCount();
+ xReceivedLength = xStreamBufferReceive( xStreamBuffers.xEchoClientBuffer, ( void * ) pcReceivedString, sbSTREAM_BUFFER_LENGTH_BYTES, xTicksToBlock );
+ prvCheckExpectedState( ( ( TickType_t ) ( xTaskGetTickCount() - xTimeOnEntering ) ) >= xTicksToBlock );
+ prvCheckExpectedState( xReceivedLength == 0 );
+
+ /* Now the stream buffers have been created the echo client task can be
+ * created. If this server task has the higher priority then the client task
+ * is created at the lower priority - if this server task has the lower
+ * priority then the client task is created at the higher priority. */
+ if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
+ {
+ xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbHIGHER_PRIORITY, NULL );
+ }
+ else
+ {
+ /* Here prvSingleTaskTests() performs various tests on a stream buffer
+ * that was created dynamically. */
+ prvSingleTaskTests( xStreamBuffers.xEchoClientBuffer );
+ xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbLOWER_PRIORITY, NULL );
+ }
+
+ for( ; ; )
+ {
+ memset( pcReceivedString, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
+
+ /* Has any data been sent by the client? */
+ xReceivedLength = xStreamBufferReceive( xStreamBuffers.xEchoClientBuffer, ( void * ) pcReceivedString, sbSTREAM_BUFFER_LENGTH_BYTES, portMAX_DELAY );
+
+ /* Should always receive data as max delay was used. */
+ prvCheckExpectedState( xReceivedLength > 0 );
+
+ /* Echo the received data back to the client. */
+ xStreamBufferSend( xStreamBuffers.xEchoServerBuffer, ( void * ) pcReceivedString, xReceivedLength, portMAX_DELAY );
+ }
}
/*-----------------------------------------------------------*/
void vPeriodicStreamBufferProcessing( void )
{
-static size_t xNextChar = 0;
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- /* Called from the tick interrupt hook. If the global stream buffer
- variable is not NULL then the prvInterruptTriggerTest() task expects a byte
- to be sent to the stream buffer on each tick interrupt. */
- if( xInterruptStreamBuffer != NULL )
- {
- /* One character from the pcDataSentFromInterrupt string is sent on each
- interrupt. The task blocked on the stream buffer should not be
- unblocked until the defined trigger level is hit. */
- xStreamBufferSendFromISR( xInterruptStreamBuffer, ( const void * ) &( pcDataSentFromInterrupt[ xNextChar ] ), sizeof( char ), &xHigherPriorityTaskWoken );
-
- if( xNextChar < strlen( pcDataSentFromInterrupt ) )
- {
- xNextChar++;
- }
- }
- else
- {
- /* Start at the beginning of the string being sent again. */
- xNextChar = 0;
- }
+ static size_t xNextChar = 0;
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+
+ /* Called from the tick interrupt hook. If the global stream buffer
+ * variable is not NULL then the prvInterruptTriggerTest() task expects a byte
+ * to be sent to the stream buffer on each tick interrupt. */
+ if( xInterruptStreamBuffer != NULL )
+ {
+ /* One character from the pcDataSentFromInterrupt string is sent on each
+ * interrupt. The task blocked on the stream buffer should not be
+ * unblocked until the defined trigger level is hit. */
+ xStreamBufferSendFromISR( xInterruptStreamBuffer, ( const void * ) &( pcDataSentFromInterrupt[ xNextChar ] ), sizeof( char ), &xHigherPriorityTaskWoken );
+
+ if( xNextChar < strlen( pcDataSentFromInterrupt ) )
+ {
+ xNextChar++;
+ }
+ }
+ else
+ {
+ /* Start at the beginning of the string being sent again. */
+ xNextChar = 0;
+ }
}
/*-----------------------------------------------------------*/
-static void prvInterruptTriggerLevelTest( void *pvParameters )
+static void prvInterruptTriggerLevelTest( void * pvParameters )
{
-StreamBufferHandle_t xStreamBuffer;
-size_t xTriggerLevel = 1, xBytesReceived;
-const size_t xStreamBufferSizeBytes = ( size_t ) 9, xMaxTriggerLevel = ( size_t ) 7, xMinTriggerLevel = ( size_t ) 2;
-const TickType_t xReadBlockTime = 5, xCycleBlockTime = pdMS_TO_TICKS( 100 );
-uint8_t ucRxData[ 9 ];
-BaseType_t xErrorDetected = pdFALSE;
-#ifndef configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN
- const size_t xAllowableMargin = ( size_t ) 0;
-#else
- const size_t xAllowableMargin = ( size_t ) configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN;
-#endif
-
- /* Remove compiler warning about unused parameter. */
- ( void ) pvParameters;
-
- for( ;; )
- {
- for( xTriggerLevel = xMinTriggerLevel; xTriggerLevel < xMaxTriggerLevel; xTriggerLevel++ )
- {
- /* This test is very time sensitive so delay at the beginning to ensure
- the rest of the system is up and running before starting. Delay between
- each loop to ensure the interrupt that sends to the stream buffer
- detects it needs to start sending from the start of the strin again.. */
- vTaskDelay( xCycleBlockTime );
-
- /* Create the stream buffer that will be used from inside the tick
- interrupt. */
- memset( ucRxData, 0x00, sizeof( ucRxData ) );
- xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
- configASSERT( xStreamBuffer );
-
- /* Now the stream buffer has been created it can be assigned to the
- file scope variable, which will allow the tick interrupt to start
- using it. */
- taskENTER_CRITICAL();
- {
- xInterruptStreamBuffer = xStreamBuffer;
- }
- taskEXIT_CRITICAL();
-
- xBytesReceived = xStreamBufferReceive( xStreamBuffer, ( void * ) ucRxData, sizeof( ucRxData ), xReadBlockTime );
-
- /* Set the file scope variable back to NULL so the interrupt doesn't
- try to use it again. */
- taskENTER_CRITICAL();
- {
- xInterruptStreamBuffer = NULL;
- }
- taskEXIT_CRITICAL();
-
- /* Now check the number of bytes received equals the trigger level,
- except in the case that the read timed out before the trigger level
- was reached. */
- if( xTriggerLevel > xReadBlockTime )
- {
- /* Trigger level was greater than the block time so expect to
- time out having received xReadBlockTime bytes. */
- if( xBytesReceived > xReadBlockTime )
- {
- /* Received more bytes than expected. That could happen if
- this task unblocked at the right time, but an interrupt
- added another byte to the stream buffer before this task was
- able to run. */
- if( ( xBytesReceived - xReadBlockTime ) > xAllowableMargin )
- {
- xErrorDetected = pdTRUE;
- }
- }
- else if( xReadBlockTime != xBytesReceived )
- {
- /* It is possible the interrupt placed an item in the stream
- buffer before this task called xStreamBufferReceive(), but
- if that is the case then xBytesReceived will only every be
- 0 as the interrupt will only have executed once. */
- if( xBytesReceived != 1 )
- {
- xErrorDetected = pdTRUE;
- }
- }
- }
- else if( xTriggerLevel < xReadBlockTime )
- {
- /* Trigger level was less than the block time so we expect to
- have received the trigger level number of bytes - could be more
- though depending on other activity between the task being
- unblocked and the task reading the number of bytes received. It
- could also be less if the interrupt already put something in the
- stream buffer before this task attempted to read it - in which
- case the task would have returned the available bytes immediately
- without ever blocking - in that case the bytes received will
- only ever be 1 as the interrupt would not have executed more
- than one in that time unless this task has too low a priority. */
- if( xBytesReceived < xTriggerLevel )
- {
- if( xBytesReceived != 1 )
- {
- xErrorDetected = pdTRUE;
- }
- }
- else if( ( xBytesReceived - xTriggerLevel ) > xAllowableMargin )
- {
- xErrorDetected = pdTRUE;
- }
- }
- else
- {
- /* The trigger level equalled the block time, so expect to
- receive no greater than the block time. It could also be less
- if the interrupt already put something in the stream buffer
- before this task attempted to read it - in which case the task
- would have returned the available bytes immediately without ever
- blocking - in that case the bytes received would only ever be 1
- because the interrupt is not going to execute twice in that time
- unless this task is running a too low a priority. */
- if( xBytesReceived < xReadBlockTime )
- {
- if( xBytesReceived != 1 )
- {
- xErrorDetected = pdTRUE;
- }
- }
- else if( ( xBytesReceived - xReadBlockTime ) > xAllowableMargin )
- {
- xErrorDetected = pdTRUE;
- }
- }
-
- if( xBytesReceived > sizeof( ucRxData ) )
- {
- xErrorDetected = pdTRUE;
- }
- else if( memcmp( ( void * ) ucRxData, ( const void * ) pcDataSentFromInterrupt, xBytesReceived ) != 0 )
- {
- /* Received data didn't match that expected. */
- xErrorDetected = pdTRUE;
- }
-
- if( xErrorDetected == pdFALSE )
- {
- /* Increment the cycle counter so the 'check' task knows this test
- is still running without error. */
- ulInterruptTriggerCounter++;
- }
-
- /* Tidy up ready for the next loop. */
- vStreamBufferDelete( xStreamBuffer );
- }
- }
+ StreamBufferHandle_t xStreamBuffer;
+ size_t xTriggerLevel = 1, xBytesReceived;
+ const size_t xStreamBufferSizeBytes = ( size_t ) 9, xMaxTriggerLevel = ( size_t ) 7, xMinTriggerLevel = ( size_t ) 2;
+ const TickType_t xReadBlockTime = 5, xCycleBlockTime = pdMS_TO_TICKS( 100 );
+ uint8_t ucRxData[ 9 ];
+ BaseType_t xErrorDetected = pdFALSE;
+
+ #ifndef configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN
+ const size_t xAllowableMargin = ( size_t ) 0;
+ #else
+ const size_t xAllowableMargin = ( size_t ) configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN;
+ #endif
+
+ /* Remove compiler warning about unused parameter. */
+ ( void ) pvParameters;
+
+ for( ; ; )
+ {
+ for( xTriggerLevel = xMinTriggerLevel; xTriggerLevel < xMaxTriggerLevel; xTriggerLevel++ )
+ {
+ /* This test is very time sensitive so delay at the beginning to ensure
+ * the rest of the system is up and running before starting. Delay between
+ * each loop to ensure the interrupt that sends to the stream buffer
+ * detects it needs to start sending from the start of the strin again.. */
+ vTaskDelay( xCycleBlockTime );
+
+ /* Create the stream buffer that will be used from inside the tick
+ * interrupt. */
+ memset( ucRxData, 0x00, sizeof( ucRxData ) );
+ xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
+ configASSERT( xStreamBuffer );
+
+ /* Now the stream buffer has been created it can be assigned to the
+ * file scope variable, which will allow the tick interrupt to start
+ * using it. */
+ taskENTER_CRITICAL();
+ {
+ xInterruptStreamBuffer = xStreamBuffer;
+ }
+ taskEXIT_CRITICAL();
+
+ xBytesReceived = xStreamBufferReceive( xStreamBuffer, ( void * ) ucRxData, sizeof( ucRxData ), xReadBlockTime );
+
+ /* Set the file scope variable back to NULL so the interrupt doesn't
+ * try to use it again. */
+ taskENTER_CRITICAL();
+ {
+ xInterruptStreamBuffer = NULL;
+ }
+ taskEXIT_CRITICAL();
+
+ /* Now check the number of bytes received equals the trigger level,
+ * except in the case that the read timed out before the trigger level
+ * was reached. */
+ if( xTriggerLevel > xReadBlockTime )
+ {
+ /* Trigger level was greater than the block time so expect to
+ * time out having received xReadBlockTime bytes. */
+ if( xBytesReceived > xReadBlockTime )
+ {
+ /* Received more bytes than expected. That could happen if
+ * this task unblocked at the right time, but an interrupt
+ * added another byte to the stream buffer before this task was
+ * able to run. */
+ if( ( xBytesReceived - xReadBlockTime ) > xAllowableMargin )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+ else if( xReadBlockTime != xBytesReceived )
+ {
+ /* It is possible the interrupt placed an item in the stream
+ * buffer before this task called xStreamBufferReceive(), but
+ * if that is the case then xBytesReceived will only every be
+ * 0 as the interrupt will only have executed once. */
+ if( xBytesReceived != 1 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+ }
+ else if( xTriggerLevel < xReadBlockTime )
+ {
+ /* Trigger level was less than the block time so we expect to
+ * have received the trigger level number of bytes - could be more
+ * though depending on other activity between the task being
+ * unblocked and the task reading the number of bytes received. It
+ * could also be less if the interrupt already put something in the
+ * stream buffer before this task attempted to read it - in which
+ * case the task would have returned the available bytes immediately
+ * without ever blocking - in that case the bytes received will
+ * only ever be 1 as the interrupt would not have executed more
+ * than one in that time unless this task has too low a priority. */
+ if( xBytesReceived < xTriggerLevel )
+ {
+ if( xBytesReceived != 1 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+ else if( ( xBytesReceived - xTriggerLevel ) > xAllowableMargin )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+ else
+ {
+ /* The trigger level equalled the block time, so expect to
+ * receive no greater than the block time. It could also be less
+ * if the interrupt already put something in the stream buffer
+ * before this task attempted to read it - in which case the task
+ * would have returned the available bytes immediately without ever
+ * blocking - in that case the bytes received would only ever be 1
+ * because the interrupt is not going to execute twice in that time
+ * unless this task is running a too low a priority. */
+ if( xBytesReceived < xReadBlockTime )
+ {
+ if( xBytesReceived != 1 )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+ else if( ( xBytesReceived - xReadBlockTime ) > xAllowableMargin )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ }
+
+ if( xBytesReceived > sizeof( ucRxData ) )
+ {
+ xErrorDetected = pdTRUE;
+ }
+ else if( memcmp( ( void * ) ucRxData, ( const void * ) pcDataSentFromInterrupt, xBytesReceived ) != 0 )
+ {
+ /* Received data didn't match that expected. */
+ xErrorDetected = pdTRUE;
+ }
+
+ if( xErrorDetected == pdFALSE )
+ {
+ /* Increment the cycle counter so the 'check' task knows this test
+ * is still running without error. */
+ ulInterruptTriggerCounter++;
+ }
+
+ /* Tidy up ready for the next loop. */
+ vStreamBufferDelete( xStreamBuffer );
+ }
+ }
}
/*-----------------------------------------------------------*/
BaseType_t xAreStreamBufferTasksStillRunning( void )
{
-static uint32_t ulLastEchoLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
-static uint32_t ulLastNonBlockingRxCounter = 0;
-static uint32_t ulLastInterruptTriggerCounter = 0;
-BaseType_t x;
-
- for( x = 0; x < sbNUMBER_OF_ECHO_CLIENTS; x++ )
- {
- if( ulLastEchoLoopCounters[ x ] == ulEchoLoopCounters[ x ] )
- {
- xErrorStatus = pdFAIL;
- }
- else
- {
- ulLastEchoLoopCounters[ x ] = ulEchoLoopCounters[ x ];
- }
- }
-
- if( ulNonBlockingRxCounter == ulLastNonBlockingRxCounter )
- {
- xErrorStatus = pdFAIL;
- }
- else
- {
- ulLastNonBlockingRxCounter = ulNonBlockingRxCounter;
- }
-
- if( ulLastInterruptTriggerCounter == ulInterruptTriggerCounter )
- {
- xErrorStatus = pdFAIL;
- }
- else
- {
- ulLastInterruptTriggerCounter = ulInterruptTriggerCounter;
- }
-
- #if( configSUPPORT_STATIC_ALLOCATION == 1 )
- {
- static uint32_t ulLastSenderLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
-
- for( x = 0; x < sbNUMBER_OF_SENDER_TASKS; x++ )
- {
- if( ulLastSenderLoopCounters[ x ] == ulSenderLoopCounters[ x ] )
- {
- xErrorStatus = pdFAIL;
- }
- else
- {
- ulLastSenderLoopCounters[ x ] = ulSenderLoopCounters[ x ];
- }
- }
- }
- #endif /* configSUPPORT_STATIC_ALLOCATION */
-
- return xErrorStatus;
+ static uint32_t ulLastEchoLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
+ static uint32_t ulLastNonBlockingRxCounter = 0;
+ static uint32_t ulLastInterruptTriggerCounter = 0;
+ BaseType_t x;
+
+ for( x = 0; x < sbNUMBER_OF_ECHO_CLIENTS; x++ )
+ {
+ if( ulLastEchoLoopCounters[ x ] == ulEchoLoopCounters[ x ] )
+ {
+ xErrorStatus = pdFAIL;
+ }
+ else
+ {
+ ulLastEchoLoopCounters[ x ] = ulEchoLoopCounters[ x ];
+ }
+ }
+
+ if( ulNonBlockingRxCounter == ulLastNonBlockingRxCounter )
+ {
+ xErrorStatus = pdFAIL;
+ }
+ else
+ {
+ ulLastNonBlockingRxCounter = ulNonBlockingRxCounter;
+ }
+
+ if( ulLastInterruptTriggerCounter == ulInterruptTriggerCounter )
+ {
+ xErrorStatus = pdFAIL;
+ }
+ else
+ {
+ ulLastInterruptTriggerCounter = ulInterruptTriggerCounter;
+ }
+
+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ static uint32_t ulLastSenderLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
+
+ for( x = 0; x < sbNUMBER_OF_SENDER_TASKS; x++ )
+ {
+ if( ulLastSenderLoopCounters[ x ] == ulSenderLoopCounters[ x ] )
+ {
+ xErrorStatus = pdFAIL;
+ }
+ else
+ {
+ ulLastSenderLoopCounters[ x ] = ulSenderLoopCounters[ x ];
+ }
+ }
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+
+ return xErrorStatus;
}
/*-----------------------------------------------------------*/