2 * FreeRTOS Kernel V10.0.0
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software. If you wish to use our Amazon
\r
14 * FreeRTOS name, please do so in a fair use way that does not cause confusion.
\r
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
18 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
19 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * http://www.FreeRTOS.org
\r
24 * http://aws.amazon.com/freertos
\r
26 * 1 tab == 4 spaces!
\r
29 /* Standard includes. */
\r
33 /* FreeRTOS includes. */
\r
34 #include "FreeRTOS.h"
\r
36 #include "stream_buffer.h"
\r
38 /* Demo app includes. */
\r
39 #include "StreamBufferDemo.h"
\r
41 /* The number of bytes of storage in the stream buffers used in this test. */
\r
42 #define sbSTREAM_BUFFER_LENGTH_BYTES ( ( size_t ) 30 )
\r
44 /* Start and end ASCII characters used in data sent to the buffers. */
\r
45 #define sbASCII_SPACE 32
\r
46 #define sbASCII_TILDA 126
\r
48 /* Defines the number of tasks to create in this test and demo. */
\r
49 #define sbNUMBER_OF_ECHO_CLIENTS ( 2 )
\r
50 #define sbNUMBER_OF_SENDER_TASKS ( 2 )
\r
52 /* Priority of the test tasks. The send and receive go from low to high
\r
53 priority tasks, and from high to low priority tasks. */
\r
54 #define sbLOWER_PRIORITY ( tskIDLE_PRIORITY )
\r
55 #define sbHIGHER_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
57 /* Block times used when sending and receiving from the stream buffers. */
\r
58 #define sbRX_TX_BLOCK_TIME pdMS_TO_TICKS( 125UL )
\r
60 /* A block time of 0 means "don't block". */
\r
61 #define sbDONT_BLOCK ( 0 )
\r
63 /* The trigger level sets the number of bytes that must be present in the
\r
64 stream buffer before a task that is blocked on the stream buffer is moved out of
\r
65 the Blocked state so it can read the bytes. */
\r
66 #define sbTRIGGER_LEVEL_1 ( 1 )
\r
68 /* The size of the stack allocated to the tasks that run as part of this demo/
\r
69 test. The stack size is over generous in most cases. */
\r
70 #define sbSTACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
\r
72 /*-----------------------------------------------------------*/
\r
75 * Performs various tests that do not require multiple tasks to interact.
\r
77 static void prvSingleTaskTests( StreamBufferHandle_t xStreamBuffer );
\r
80 * Tests sending and receiving various lengths of data via a stream buffer.
\r
81 * The echo client sends the data to the echo server, which then sends the
\r
82 * data back to the echo client, which checks it receives exactly what it
\r
85 static void prvEchoClient( void *pvParameters );
\r
86 static void prvEchoServer( void *pvParameters );
\r
89 * Tasks that send and receive to a stream buffer at a low priority and without
\r
90 * blocking, so the send and receive functions interleave in time as the tasks
\r
91 * are switched in and out.
\r
93 static void prvNonBlockingReceiverTask( void *pvParameters );
\r
94 static void prvNonBlockingSenderTask( void *pvParameters );
\r
97 * A task that creates a stream buffer with a specific trigger level, then
\r
98 * receives a string from an interrupt (the RTOS tick hook) byte by byte to
\r
99 * check it is only unblocked when the specified trigger level is reached.
\r
101 static void prvInterruptTriggerLevelTest( void *pvParameters );
\r
103 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
104 /* This file tests both statically and dynamically allocated stream buffers.
\r
105 Allocate the structures and buffers to be used by the statically allocated
\r
106 objects, which get used in the echo tests. */
\r
107 static void prvReceiverTask( void *pvParameters );
\r
108 static void prvSenderTask( void *pvParameters );
\r
110 static StaticStreamBuffer_t xStaticStreamBuffers[ sbNUMBER_OF_ECHO_CLIENTS ];
\r
111 static uint8_t ucBufferStorage[ sbNUMBER_OF_SENDER_TASKS ][ sbSTREAM_BUFFER_LENGTH_BYTES + 1 ];
\r
112 static uint32_t ulSenderLoopCounters[ sbNUMBER_OF_SENDER_TASKS ] = { 0 };
\r
113 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
115 /*-----------------------------------------------------------*/
\r
117 /* The buffers used by the echo client and server tasks. */
\r
118 typedef struct ECHO_STREAM_BUFFERS
\r
120 /* Handles to the data structures that describe the stream buffers. */
\r
121 StreamBufferHandle_t xEchoClientBuffer;
\r
122 StreamBufferHandle_t xEchoServerBuffer;
\r
123 } EchoStreamBuffers_t;
\r
124 static volatile uint32_t ulEchoLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
\r
126 /* The non-blocking tasks monitor their operation, and if no errors have been
\r
127 found, increment ulNonBlockingRxCounter. xAreStreamBufferTasksStillRunning()
\r
128 then checks ulNonBlockingRxCounter and only returns pdPASS if
\r
129 ulNonBlockingRxCounter is still incrementing. */
\r
130 static volatile uint32_t ulNonBlockingRxCounter = 0;
\r
132 /* The task that receives characters from the tick interrupt in order to test
\r
133 different trigger levels monitors its own behaviour. If it has not detected any
\r
134 error then it increments ulInterruptTriggerCounter to indicate to the check task
\r
135 that it is still operating correctly. */
\r
136 static volatile uint32_t ulInterruptTriggerCounter = 0UL;
\r
138 /* The stream buffer used from the tick interrupt. This sends one byte at a time
\r
139 to a test task to test the trigger level operation. The variable is set to NULL
\r
140 in between test runs. */
\r
141 static volatile StreamBufferHandle_t xInterruptStreamBuffer = NULL;
\r
143 /* The data sent from the tick interrupt to the task that tests the trigger
\r
144 level functionality. */
\r
145 static const char *pcDataSentFromInterrupt = "12345678";
\r
147 /* Data that is longer than the buffer that is sent to the buffers as a stream
\r
148 of bytes. Parts of which are written to the stream buffer to test writing
\r
149 different lengths at different offsets, to many bytes, part streams, streams
\r
150 that wrap, etc.. Two messages are defined to ensure left over data is not
\r
151 accidentally read out of the buffer. */
\r
152 static const char *pc55ByteString = "One two three four five six seven eight nine ten eleven";
\r
153 static const char *pc54ByteString = "01234567891abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ";
\r
155 /*-----------------------------------------------------------*/
\r
157 void vStartStreamBufferTasks( void )
\r
159 StreamBufferHandle_t xStreamBuffer;
\r
161 /* The echo servers sets up the stream buffers before creating the echo
\r
162 client tasks. One set of tasks has the server as the higher priority, and
\r
163 the other has the client as the higher priority. */
\r
164 xTaskCreate( prvEchoServer, "1StrEchoServer", sbSTACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
\r
165 xTaskCreate( prvEchoServer, "2StrEchoServer", sbSTACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
\r
167 /* The non blocking tasks run continuously and will interleave with each
\r
168 other, so must be created at the lowest priority. The stream buffer they
\r
169 use is created and passed in using the task's parameter. */
\r
170 xStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
\r
171 xTaskCreate( prvNonBlockingReceiverTask, "StrNonBlkRx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
\r
172 xTaskCreate( prvNonBlockingSenderTask, "StrNonBlkTx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
\r
174 /* The task that receives bytes from an interrupt to test that it unblocks
\r
175 at a specific trigger level must run at a high priority to minimise the risk
\r
176 of it receiving more characters before it can execute again after being
\r
178 xTaskCreate( prvInterruptTriggerLevelTest, "StrTrig", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
\r
180 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
182 /* The sender tasks set up the stream buffers before creating the
\r
183 receiver tasks. Priorities must be 0 and 1 as the priority is used to
\r
184 index into the xStaticStreamBuffers and ucBufferStorage arrays. */
\r
185 xTaskCreate( prvSenderTask, "Str1Sender", sbSTACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
\r
186 xTaskCreate( prvSenderTask, "Str2Sender", sbSTACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
\r
188 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
190 /*-----------------------------------------------------------*/
\r
192 static void prvSingleTaskTests( StreamBufferHandle_t xStreamBuffer )
\r
194 size_t xReturned, xItem, xExpectedSpace;
\r
195 const size_t xMax6ByteMessages = sbSTREAM_BUFFER_LENGTH_BYTES / 6;
\r
196 const size_t x6ByteLength = 6, x17ByteLength = 17, xFullBufferSize = sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2;
\r
197 uint8_t *pucFullBuffer, *pucData, *pucReadData;
\r
198 TickType_t xTimeBeforeCall, xTimeAfterCall;
\r
199 const TickType_t xBlockTime = pdMS_TO_TICKS( 15 ), xAllowableMargin = pdMS_TO_TICKS( 3 ), xMinimalBlockTime = 2;
\r
200 UBaseType_t uxOriginalPriority;
\r
202 /* Remove warning in case configASSERT() is not defined. */
\r
203 ( void ) xAllowableMargin;
\r
205 /* To minimise stack and heap usage a full size buffer is allocated from the
\r
206 heap, then buffers which hold smaller amounts of data are overlayed with the
\r
207 larger buffer - just make sure not to use both at once! */
\r
208 pucFullBuffer = pvPortMalloc( xFullBufferSize );
\r
209 configASSERT( pucFullBuffer );
\r
211 pucData = pucFullBuffer;
\r
212 pucReadData = pucData + x17ByteLength;
\r
214 /* Nothing has been added or removed yet, so expect the free space to be
\r
215 exactly as created. */
\r
216 xExpectedSpace = xStreamBufferSpacesAvailable( xStreamBuffer );
\r
217 configASSERT( xExpectedSpace == sbSTREAM_BUFFER_LENGTH_BYTES );
\r
218 configASSERT( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
\r
221 /* The buffer is 30 bytes long. 6 5 byte messages should fit before the
\r
222 buffer is completely full. */
\r
223 for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
\r
225 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
\r
227 /* Generate recognisable data to write to the buffer. This is just
\r
228 ascii characters that shows which loop iteration the data was written
\r
229 in. The 'FromISR' version is used to give it some exercise as a block
\r
230 time is not used, so the call must be inside a critical section so it
\r
231 runs with ports that don't support interrupt nesting (and therefore
\r
232 don't have interrupt safe critical sections). */
\r
233 memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
\r
234 taskENTER_CRITICAL();
\r
236 xReturned = xStreamBufferSendFromISR( xStreamBuffer, ( void * ) pucData, x6ByteLength, NULL );
\r
238 taskEXIT_CRITICAL();
\r
239 configASSERT( xReturned == x6ByteLength );
\r
240 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
242 /* The space in the buffer will have reduced by the amount of user data
\r
243 written into the buffer. */
\r
244 xExpectedSpace -= x6ByteLength;
\r
245 xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
\r
246 configASSERT( xReturned == xExpectedSpace );
\r
247 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
248 xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
\r
249 /* +1 as it is zero indexed. */
\r
250 configASSERT( xReturned == ( ( xItem + 1 ) * x6ByteLength ) );
\r
251 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
254 /* Now the buffer should be full, and attempting to add anything will should
\r
256 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
\r
257 xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), sbDONT_BLOCK );
\r
258 configASSERT( xReturned == 0 );
\r
259 ( void ) xReturned; /* In case configASSERT() is not defined. */
\r
261 /* Adding with a timeout should also fail after the appropriate time. The
\r
262 priority is temporarily boosted in this part of the test to keep the
\r
263 allowable margin to a minimum. */
\r
264 uxOriginalPriority = uxTaskPriorityGet( NULL );
\r
265 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
\r
266 xTimeBeforeCall = xTaskGetTickCount();
\r
267 xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), xBlockTime );
\r
268 xTimeAfterCall = xTaskGetTickCount();
\r
269 vTaskPrioritySet( NULL, uxOriginalPriority );
\r
270 configASSERT( ( xTimeAfterCall - xTimeBeforeCall ) >= xBlockTime );
\r
271 configASSERT( ( xTimeAfterCall - xTimeBeforeCall ) < ( xBlockTime + xAllowableMargin ) );
\r
272 configASSERT( xReturned == 0 ); /* In case configASSERT() is not defined. */
\r
273 ( void ) xTimeAfterCall;
\r
274 ( void ) xTimeBeforeCall;
\r
277 /* The buffer is now full of data in the form "000000", "111111", etc. Make
\r
278 sure the data is read out as expected. */
\r
279 for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
\r
281 /* Generate the data that is expected to be read out for this loop
\r
283 memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
\r
285 /* Read the next 6 bytes out. The 'FromISR' version is used to give it
\r
286 some exercise as a block time is not used, so a it must be called from
\r
287 a critical section so this will work on ports that don't support
\r
288 interrupt nesting (so don't have interrupt safe critical sections). */
\r
289 taskENTER_CRITICAL();
\r
291 xReturned = xStreamBufferReceiveFromISR( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, NULL );
\r
293 taskEXIT_CRITICAL();
\r
294 configASSERT( xReturned == x6ByteLength );
\r
296 /* Does the data read out match that expected? */
\r
297 configASSERT( memcmp( ( void * ) pucData, ( void * ) pucReadData, x6ByteLength ) == 0 );
\r
299 /* The space in the buffer will have increased by the amount of user
\r
300 data removed from the buffer. */
\r
301 xExpectedSpace += x6ByteLength;
\r
302 xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
\r
303 configASSERT( xReturned == xExpectedSpace );
\r
304 xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
\r
305 configASSERT( xReturned == ( sbSTREAM_BUFFER_LENGTH_BYTES - xExpectedSpace ) );
\r
308 /* The buffer should be empty again. */
\r
309 configASSERT( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
\r
310 xExpectedSpace = xStreamBufferSpacesAvailable( xStreamBuffer );
\r
311 configASSERT( xExpectedSpace == sbSTREAM_BUFFER_LENGTH_BYTES );
\r
313 /* Reading with a timeout should also fail after the appropriate time. The
\r
314 priority is temporarily boosted in this part of the test to keep the
\r
315 allowable margin to a minimum. */
\r
316 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
\r
317 xTimeBeforeCall = xTaskGetTickCount();
\r
318 xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, xBlockTime );
\r
319 xTimeAfterCall = xTaskGetTickCount();
\r
320 vTaskPrioritySet( NULL, uxOriginalPriority );
\r
321 configASSERT( ( xTimeAfterCall - xTimeBeforeCall ) >= xBlockTime );
\r
322 configASSERT( ( xTimeAfterCall - xTimeBeforeCall ) < ( xBlockTime + xAllowableMargin ) );
\r
323 configASSERT( xReturned == 0 );
\r
326 /* In the next loop 17 bytes are written to then read out on each
\r
327 iteration. As 30 is not divisible by 17 the data will wrap around. */
\r
328 xExpectedSpace = sbSTREAM_BUFFER_LENGTH_BYTES - x17ByteLength;
\r
330 for( xItem = 0; xItem < 100; xItem++ )
\r
332 /* Generate recognisable data to write to the queue. This is just
\r
333 ascii characters that shows which loop iteration the data was written
\r
335 memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x17ByteLength );
\r
336 xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, x17ByteLength, sbDONT_BLOCK );
\r
337 configASSERT( xReturned == x17ByteLength );
\r
339 /* The space in the buffer will have reduced by the amount of user data
\r
340 written into the buffer. */
\r
341 xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
\r
342 configASSERT( xReturned == xExpectedSpace );
\r
343 xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
\r
344 configASSERT( xReturned == x17ByteLength );
\r
345 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
\r
346 configASSERT( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
\r
348 /* Read the 17 bytes out again. */
\r
349 xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x17ByteLength, sbDONT_BLOCK );
\r
350 configASSERT( xReturned == x17ByteLength );
\r
352 /* Does the data read out match that expected? */
\r
353 configASSERT( memcmp( ( void * ) pucData, ( void * ) pucReadData, x17ByteLength ) == 0 );
\r
355 /* Full buffer space available again. */
\r
356 xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
\r
357 configASSERT( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
\r
358 xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
\r
359 configASSERT( xReturned == 0 );
\r
360 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
\r
361 configASSERT( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
\r
364 /* Fill the buffer with one message, check it is full, then read it back
\r
365 again and check the correct data is received. */
\r
366 xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
\r
367 xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
\r
368 configASSERT( memcmp( pc55ByteString, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
\r
370 /* Fill the buffer one bytes at a time. */
\r
371 for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
\r
373 /* Block time is only for test coverage, the task should never actually
\r
375 xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc54ByteString[ xItem ] ), sizeof( char ), sbRX_TX_BLOCK_TIME );
\r
378 /* The buffer should now be full. */
\r
379 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
\r
381 /* Read the message out in one go, even though it was written in individual
\r
382 bytes. Try reading much more data than is actually available to ensure only
\r
383 the available bytes are returned (otherwise this read will write outside of
\r
384 the memory allocated anyway!). */
\r
385 xReturned = xStreamBufferReceive( xStreamBuffer, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, sbRX_TX_BLOCK_TIME );
\r
386 configASSERT( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
\r
387 configASSERT( memcmp( ( const void * ) pc54ByteString, ( const void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
\r
389 /* Now do the opposite, write in one go and read out in single bytes. */
\r
390 xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES, sbRX_TX_BLOCK_TIME );
\r
391 configASSERT( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
\r
392 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
\r
393 configASSERT( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
\r
394 configASSERT( xStreamBufferBytesAvailable( xStreamBuffer ) == sbSTREAM_BUFFER_LENGTH_BYTES );
\r
395 configASSERT( xStreamBufferSpacesAvailable( xStreamBuffer ) == 0 );
\r
397 /* Read from the buffer one byte at a time. */
\r
398 for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
\r
400 /* Block time is only for test coverage, the task should never actually
\r
402 xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sizeof( char ), sbRX_TX_BLOCK_TIME );
\r
403 configASSERT( pc55ByteString[ xItem ] == pucFullBuffer[ 0 ] );
\r
405 configASSERT( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
\r
406 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
\r
408 /* Try writing more bytes than there is space. */
\r
409 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
\r
410 xTimeBeforeCall = xTaskGetTickCount();
\r
411 xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, xMinimalBlockTime );
\r
412 xTimeAfterCall = xTaskGetTickCount();
\r
413 vTaskPrioritySet( NULL, uxOriginalPriority );
\r
414 configASSERT( ( xTimeAfterCall - xTimeBeforeCall ) >= xMinimalBlockTime );
\r
415 configASSERT( ( xTimeAfterCall - xTimeBeforeCall ) < ( xMinimalBlockTime + xAllowableMargin ) );
\r
416 configASSERT( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
\r
417 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
\r
418 configASSERT( xStreamBufferIsEmpty( xStreamBuffer ) == pdFALSE );
\r
420 /* No space now though. */
\r
421 xReturned = xStreamBufferSend( xStreamBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, xMinimalBlockTime );
\r
422 configASSERT( xReturned == 0 );
\r
424 /* Ensure data was written as expected even when there was an attempt to
\r
425 write more than was available. This also tries to read more bytes than are
\r
427 xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, xFullBufferSize, xMinimalBlockTime );
\r
428 configASSERT( memcmp( ( const void * ) pucFullBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
\r
429 configASSERT( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
\r
430 configASSERT( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
\r
432 /* Clean up with data in the buffer to ensure the tests that follow don't
\r
433 see the data (the data should be discarded). */
\r
434 ( void ) xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES / ( size_t ) 2, sbDONT_BLOCK );
\r
435 vPortFree( pucFullBuffer );
\r
436 xStreamBufferReset( xStreamBuffer );
\r
438 /*-----------------------------------------------------------*/
\r
440 static void prvNonBlockingSenderTask( void *pvParameters )
\r
442 StreamBufferHandle_t xStreamBuffer;
\r
443 size_t xNextChar = 0, xBytesToSend, xBytesActuallySent;
\r
444 const size_t xStringLength = strlen( pc54ByteString );
\r
446 /* In this case the stream buffer has already been created and is passed
\r
447 into the task using the task's parameter. */
\r
448 xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
\r
450 /* Keep sending the string to the stream buffer as many bytes as possible in
\r
451 each go. Doesn't block so calls can interleave with the non-blocking
\r
452 receives performed by prvNonBlockingReceiverTask(). */
\r
455 /* The whole string cannot be sent at once, so xNextChar is an index to
\r
456 the position within the string that has been sent so far. How many
\r
457 bytes are there left to send before the end of the string? */
\r
458 xBytesToSend = xStringLength - xNextChar;
\r
460 /* Attempt to send right up to the end of the string. */
\r
461 xBytesActuallySent = xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc54ByteString[ xNextChar ] ), xBytesToSend, sbDONT_BLOCK );
\r
462 configASSERT( xBytesActuallySent <= xBytesToSend );
\r
464 /* Move the index up the string to the next character to be sent,
\r
465 wrapping if the end of the string has been reached. */
\r
466 xNextChar += xBytesActuallySent;
\r
467 configASSERT( xNextChar <= xStringLength );
\r
469 if( xNextChar == xStringLength )
\r
475 /*-----------------------------------------------------------*/
\r
477 static void prvNonBlockingReceiverTask( void *pvParameters )
\r
479 StreamBufferHandle_t xStreamBuffer;
\r
480 size_t xNextChar = 0, xReceiveLength, xBytesToTest, xStartIndex;
\r
481 const size_t xStringLength = strlen( pc54ByteString );
\r
482 char cRxString[ 12 ]; /* Holds received characters. */
\r
483 BaseType_t xNonBlockingReceiveError = pdFALSE;
\r
485 /* In this case the stream buffer has already been created and is passed
\r
486 into the task using the task's parameter. */
\r
487 xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
\r
489 /* Expects to receive the pc54ByteString over and over again. Sends and
\r
490 receives are not blocking so will interleave. */
\r
493 /* Attempt to receive as many bytes as possible, up to the limit of the
\r
495 xReceiveLength = xStreamBufferReceive( xStreamBuffer, ( void * ) cRxString, sizeof( cRxString ), sbDONT_BLOCK );
\r
497 if( xReceiveLength > 0 )
\r
499 /* xNextChar is the index into pc54ByteString that has been received
\r
500 already. If xReceiveLength bytes are added to that, will it go off
\r
501 the end of the string? If so, then first test up to the end of the
\r
502 string, then go back to the start of pc54ByteString to test the
\r
503 remains of the received data. */
\r
504 xBytesToTest = xReceiveLength;
\r
505 if( ( xNextChar + xBytesToTest ) > xStringLength )
\r
507 /* Cap to test the received data to the end of the string. */
\r
508 xBytesToTest = xStringLength - xNextChar;
\r
510 if( memcmp( ( const void * ) &( pc54ByteString[ xNextChar ] ), ( const void * ) cRxString, xBytesToTest ) != 0 )
\r
512 xNonBlockingReceiveError = pdTRUE;
\r
515 /* Then move back to the start of the string to test the
\r
516 remaining received bytes. */
\r
518 xStartIndex = xBytesToTest;
\r
519 xBytesToTest = xReceiveLength - xBytesToTest;
\r
523 /* The string didn't wrap in the buffer, so start comparing from
\r
524 the start of the received data. */
\r
528 /* Test the received bytes are as expected, then move the index
\r
529 along the string to the next expected char to receive. */
\r
530 if( memcmp( ( const void * ) &( pc54ByteString[ xNextChar ] ), ( const void * ) &( cRxString[ xStartIndex ] ), xBytesToTest ) != 0 )
\r
532 xNonBlockingReceiveError = pdTRUE;
\r
535 if( xNonBlockingReceiveError == pdFALSE )
\r
537 /* No errors detected so increment the counter that lets the
\r
538 check task know this test is still functioning correctly. */
\r
539 ulNonBlockingRxCounter++;
\r
542 xNextChar += xBytesToTest;
\r
543 if( xNextChar >= xStringLength )
\r
550 /*-----------------------------------------------------------*/
\r
552 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
554 static void prvSenderTask( void *pvParameters )
\r
556 StreamBufferHandle_t xStreamBuffer, xTempStreamBuffer;
\r
557 static uint8_t ucTempBuffer[ 10 ]; /* Just used to exercise stream buffer creating and deletion. */
\r
558 const TickType_t xTicksToWait = sbRX_TX_BLOCK_TIME, xShortDelay = pdMS_TO_TICKS( 50 );
\r
559 StaticStreamBuffer_t xStaticStreamBuffer;
\r
560 size_t xNextChar = 0, xBytesToSend, xBytesActuallySent;
\r
561 const size_t xStringLength = strlen( pc55ByteString );
\r
563 /* The task's priority is used as an index into the loop counters used to
\r
564 indicate this task is still running. */
\r
565 UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
\r
567 /* Make sure a change in priority does not inadvertently result in an
\r
568 invalid array index. */
\r
569 configASSERT( uxIndex < sbNUMBER_OF_ECHO_CLIENTS );
\r
571 /* Avoid compiler warnings about unused parameters. */
\r
572 ( void ) pvParameters;
\r
574 xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ) / sbNUMBER_OF_SENDER_TASKS, /* The number of bytes in each buffer in the array. */
\r
575 sbTRIGGER_LEVEL_1, /* The number of bytes to be in the buffer before a task blocked to wait for data is unblocked. */
\r
576 &( ucBufferStorage[ uxIndex ][ 0 ] ), /* The address of the buffer to use within the array. */
\r
577 &( xStaticStreamBuffers[ uxIndex ] ) ); /* The static stream buffer structure to use within the array. */
\r
579 /* Now the stream buffer has been created the receiver task can be
\r
580 created. If this sender task has the higher priority then the receiver
\r
581 task is created at the lower priority - if this sender task has the
\r
582 lower priority then the receiver task is created at the higher
\r
584 if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
\r
586 /* Here prvSingleTaskTests() performs various tests on a stream buffer
\r
587 that was created statically. */
\r
588 prvSingleTaskTests( xStreamBuffer );
\r
589 xTaskCreate( prvReceiverTask, "StrReceiver", sbSTACK_SIZE, ( void * ) xStreamBuffer, sbHIGHER_PRIORITY, NULL );
\r
593 xTaskCreate( prvReceiverTask, "StrReceiver", sbSTACK_SIZE, ( void * ) xStreamBuffer, sbLOWER_PRIORITY, NULL );
\r
598 /* The whole string cannot be sent at once, so xNextChar is an index
\r
599 to the position within the string that has been sent so far. How
\r
600 many bytes are there left to send before the end of the string? */
\r
601 xBytesToSend = xStringLength - xNextChar;
\r
603 /* Attempt to send right up to the end of the string. */
\r
604 xBytesActuallySent = xStreamBufferSend( xStreamBuffer, ( void * ) &( pc55ByteString[ xNextChar ] ), xBytesToSend, xTicksToWait );
\r
605 configASSERT( xBytesActuallySent <= xBytesToSend );
\r
607 /* Move the index up the string to the next character to be sent,
\r
608 wrapping if the end of the string has been reached. */
\r
609 xNextChar += xBytesActuallySent;
\r
610 configASSERT( xNextChar <= xStringLength );
\r
612 if( xNextChar == xStringLength )
\r
617 /* Increment a loop counter so a check task can tell this task is
\r
618 still running as expected. */
\r
619 ulSenderLoopCounters[ uxIndex ]++;
\r
621 if( uxTaskPriorityGet( NULL ) == sbHIGHER_PRIORITY )
\r
623 /* Allow other tasks to run. */
\r
624 vTaskDelay( xShortDelay );
\r
627 /* This stream buffer is just created and deleted to ensure no
\r
628 issues when attempting to delete a stream buffer that was
\r
629 created using statically allocated memory. To save stack space
\r
630 the buffer is set to point to the pc55ByteString, which is a const
\r
631 string, but no data is written into the buffer so any valid address
\r
633 xTempStreamBuffer = xStreamBufferCreateStatic( sizeof( ucTempBuffer ), sbTRIGGER_LEVEL_1, ucTempBuffer, &xStaticStreamBuffer );
\r
634 vStreamBufferDelete( xTempStreamBuffer );
\r
638 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
639 /*-----------------------------------------------------------*/
\r
641 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
643 static void prvReceiverTask( void *pvParameters )
\r
645 StreamBufferHandle_t * const pxStreamBuffer = ( StreamBufferHandle_t * ) pvParameters;
\r
646 char cRxString[ 12 ]; /* Large enough to hold a 32-bit number in ASCII. */
\r
647 const TickType_t xTicksToWait = pdMS_TO_TICKS( 5UL );
\r
648 const size_t xStringLength = strlen( pc55ByteString );
\r
649 size_t xNextChar = 0, xReceivedLength, xBytesToReceive;
\r
653 /* Attempt to receive the number of bytes to the end of the string,
\r
654 or the number of byte that can be placed into the rx buffer,
\r
655 whichever is smallest. */
\r
656 xBytesToReceive = configMIN( ( xStringLength - xNextChar ), sizeof( cRxString ) );
\r
660 xReceivedLength = xStreamBufferReceive( pxStreamBuffer, ( void * ) cRxString, xBytesToReceive, xTicksToWait );
\r
662 } while( xReceivedLength == 0 );
\r
664 /* Ensure the received string matches the expected string. */
\r
665 configASSERT( memcmp( ( void * ) cRxString, ( void * ) &( pc55ByteString[ xNextChar ] ), xReceivedLength ) == 0 );
\r
667 /* Move the index into the string up to the end of the bytes
\r
668 received so far - wrapping if the end of the string has been
\r
670 xNextChar += xReceivedLength;
\r
671 if( xNextChar >= xStringLength )
\r
678 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
679 /*-----------------------------------------------------------*/
\r
681 static void prvEchoClient( void *pvParameters )
\r
683 size_t xSendLength = 0, ux;
\r
684 char *pcStringToSend, *pcStringReceived, cNextChar = sbASCII_SPACE;
\r
685 const TickType_t xTicksToWait = pdMS_TO_TICKS( 50 );
\r
686 StreamBufferHandle_t xTempStreamBuffer;
\r
688 /* The task's priority is used as an index into the loop counters used to
\r
689 indicate this task is still running. */
\r
690 UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
\r
692 /* Pointers to the client and server stream buffers are passed into this task
\r
693 using the task's parameter. */
\r
694 EchoStreamBuffers_t *pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
\r
696 /* Prevent compiler warnings. */
\r
697 ( void ) pvParameters;
\r
699 /* Create the buffer into which strings to send to the server will be
\r
700 created, and the buffer into which strings echoed back from the server will
\r
702 pcStringToSend = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
\r
703 pcStringReceived = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
\r
705 configASSERT( pcStringToSend );
\r
706 configASSERT( pcStringReceived );
\r
710 /* Generate the length of the next string to send. */
\r
713 /* The stream buffer is being used to hold variable length data, so
\r
714 each data item requires sizeof( size_t ) bytes to hold the data's
\r
715 length, hence the sizeof() in the if() condition below. */
\r
716 if( xSendLength > ( sbSTREAM_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) )
\r
718 /* Back to a string length of 1. */
\r
719 xSendLength = sizeof( char );
\r
722 memset( pcStringToSend, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
\r
724 for( ux = 0; ux < xSendLength; ux++ )
\r
726 pcStringToSend[ ux ] = cNextChar;
\r
730 if( cNextChar > sbASCII_TILDA )
\r
732 cNextChar = sbASCII_SPACE;
\r
736 /* Send the generated string to the buffer. */
\r
739 ux = xStreamBufferSend( pxStreamBuffers->xEchoClientBuffer, ( void * ) pcStringToSend, xSendLength, xTicksToWait );
\r
741 } while( ux == 0 );
\r
743 /* Wait for the string to be echoed back. */
\r
744 memset( pcStringReceived, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
\r
745 xStreamBufferReceive( pxStreamBuffers->xEchoServerBuffer, ( void * ) pcStringReceived, xSendLength, portMAX_DELAY );
\r
747 configASSERT( strcmp( pcStringToSend, pcStringReceived ) == 0 );
\r
749 /* Maintain a count of the number of times this code executes so a
\r
750 check task can determine if this task is still functioning as
\r
751 expected or not. As there are two client tasks, and the priorities
\r
752 used are 0 and 1, the task's priority is used as an index into the
\r
753 loop count array. */
\r
754 ulEchoLoopCounters[ uxIndex ]++;
\r
756 /* This stream buffer is just created and deleted to ensure no memory
\r
758 xTempStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
\r
759 prvSingleTaskTests( xTempStreamBuffer );
\r
760 vStreamBufferDelete( xTempStreamBuffer );
\r
763 /*-----------------------------------------------------------*/
\r
765 static void prvEchoServer( void *pvParameters )
\r
767 size_t xReceivedLength;
\r
768 char *pcReceivedString;
\r
769 EchoStreamBuffers_t xStreamBuffers;
\r
770 TickType_t xTimeOnEntering;
\r
771 const TickType_t xTicksToBlock = pdMS_TO_TICKS( 350UL );
\r
773 /* Prevent compiler warnings about unused parameters. */
\r
774 ( void ) pvParameters;
\r
776 /* Create the stream buffer used to send data from the client to the server,
\r
777 and the stream buffer used to echo the data from the server back to the
\r
779 xStreamBuffers.xEchoClientBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
\r
780 xStreamBuffers.xEchoServerBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
\r
781 configASSERT( xStreamBuffers.xEchoClientBuffer );
\r
782 configASSERT( xStreamBuffers.xEchoServerBuffer );
\r
784 /* Create the buffer into which received strings will be copied. */
\r
785 pcReceivedString = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
\r
786 configASSERT( pcReceivedString );
\r
788 /* Don't expect to receive anything yet! */
\r
789 xTimeOnEntering = xTaskGetTickCount();
\r
790 xReceivedLength = xStreamBufferReceive( xStreamBuffers.xEchoClientBuffer, ( void * ) pcReceivedString, sbSTREAM_BUFFER_LENGTH_BYTES, xTicksToBlock );
\r
791 configASSERT( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToBlock );
\r
792 configASSERT( xReceivedLength == 0 );
\r
793 ( void ) xTimeOnEntering;
\r
795 /* Now the stream buffers have been created the echo client task can be
\r
796 created. If this server task has the higher priority then the client task
\r
797 is created at the lower priority - if this server task has the lower
\r
798 priority then the client task is created at the higher priority. */
\r
799 if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
\r
801 xTaskCreate( prvEchoClient, "EchoClient", sbSTACK_SIZE, ( void * ) &xStreamBuffers, sbHIGHER_PRIORITY, NULL );
\r
805 /* Here prvSingleTaskTests() performs various tests on a stream buffer
\r
806 that was created dynamically. */
\r
807 prvSingleTaskTests( xStreamBuffers.xEchoClientBuffer );
\r
808 xTaskCreate( prvEchoClient, "EchoClient", sbSTACK_SIZE, ( void * ) &xStreamBuffers, sbLOWER_PRIORITY, NULL );
\r
813 memset( pcReceivedString, 0x00, sbSTREAM_BUFFER_LENGTH_BYTES );
\r
815 /* Has any data been sent by the client? */
\r
816 xReceivedLength = xStreamBufferReceive( xStreamBuffers.xEchoClientBuffer, ( void * ) pcReceivedString, sbSTREAM_BUFFER_LENGTH_BYTES, xTicksToBlock );
\r
818 /* Should always receive data as a delay was used. */
\r
819 configASSERT( xReceivedLength > 0 );
\r
821 /* Echo the received data back to the client. */
\r
822 xStreamBufferSend( xStreamBuffers.xEchoServerBuffer, ( void * ) pcReceivedString, xReceivedLength, portMAX_DELAY );
\r
825 /*-----------------------------------------------------------*/
\r
827 void vPeriodicStreamBufferProcessing( void )
\r
829 static size_t xNextChar = 0;
\r
830 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
832 /* Called from the tick interrupt hook. If the global stream buffer
\r
833 variable is not NULL then the prvInterruptTriggerTest() task expects a byte
\r
834 to be sent to the stream buffer on each tick interrupt. */
\r
835 if( xInterruptStreamBuffer != NULL )
\r
837 /* One character from the pcDataSentFromInterrupt string is sent on each
\r
838 interrupt. The task blocked on the stream buffer should not be
\r
839 unblocked until the defined trigger level is hit. */
\r
840 xStreamBufferSendFromISR( xInterruptStreamBuffer, ( const void * ) &( pcDataSentFromInterrupt[ xNextChar ] ), sizeof( char ), &xHigherPriorityTaskWoken );
\r
842 if( xNextChar < strlen( pcDataSentFromInterrupt ) )
\r
849 /* Start at the beginning of the string being sent again. */
\r
853 /*-----------------------------------------------------------*/
\r
855 static void prvInterruptTriggerLevelTest( void *pvParameters )
\r
857 StreamBufferHandle_t xStreamBuffer;
\r
858 size_t xTriggerLevel = 1, xBytesReceived;
\r
859 const size_t xStreamBufferSizeBytes = ( size_t ) 8, xMaxTriggerLevel = ( size_t ) 6, xMinTriggerLevel = ( size_t ) 1;
\r
860 const TickType_t xReadBlockTime = 4, xCycleBlockTime = pdMS_TO_TICKS( 100 );
\r
861 uint8_t ucRxData[ 8 ];
\r
862 BaseType_t xErrorDetected = pdFALSE;
\r
863 #ifndef configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN
\r
864 const size_t xAllowableMargin = ( size_t ) 0;
\r
866 const size_t xAllowableMargin = ( size_t ) configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN;
\r
869 /* Remove compiler warning about unused parameter. */
\r
870 ( void ) pvParameters;
\r
874 for( xTriggerLevel = xMinTriggerLevel; xTriggerLevel < xMaxTriggerLevel; xTriggerLevel++ )
\r
876 /* Create the stream buffer that will be used from inside the tick
\r
878 xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
\r
879 configASSERT( xStreamBuffer );
\r
881 /* Now the stream buffer has been created it can be assigned to the
\r
882 file scope variable, which will allow the tick interrupt to start
\r
884 taskENTER_CRITICAL();
\r
886 xInterruptStreamBuffer = xStreamBuffer;
\r
888 taskEXIT_CRITICAL();
\r
890 xBytesReceived = xStreamBufferReceive( xStreamBuffer, ( void * ) ucRxData, sizeof( ucRxData ), xReadBlockTime );
\r
892 /* Set the file scope variable back to NULL so the interrupt doesn't
\r
893 try to use it again. */
\r
894 taskENTER_CRITICAL();
\r
896 xInterruptStreamBuffer = NULL;
\r
898 taskEXIT_CRITICAL();
\r
900 /* Now check the number of bytes received equals the trigger level,
\r
901 except in the case that the read timed out before the trigger level
\r
903 if( xBytesReceived < xTriggerLevel )
\r
905 /* This should only happen if the trigger level was greater than
\r
907 if( xTriggerLevel < xReadBlockTime )
\r
909 xErrorDetected = pdTRUE;
\r
912 else if( ( xBytesReceived - xTriggerLevel ) > xAllowableMargin )
\r
914 /* A margin may be required here if there are other high priority
\r
915 tasks prevent the task that reads from the message buffer running
\r
917 xErrorDetected = pdTRUE;
\r
920 if( xBytesReceived > sizeof( ucRxData ) )
\r
922 xErrorDetected = pdTRUE;
\r
924 else if( memcmp( ( void * ) ucRxData, ( const void * ) pcDataSentFromInterrupt, xBytesReceived ) != 0 )
\r
926 /* Received data didn't match that expected. */
\r
927 xErrorDetected = pdTRUE;
\r
930 if( xErrorDetected == pdFALSE )
\r
932 /* Increment the cycle counter so the 'check' task knows this test
\r
933 is still running without error. */
\r
934 ulInterruptTriggerCounter++;
\r
937 /* Tidy up ready for the next loop. */
\r
938 vStreamBufferDelete( xStreamBuffer );
\r
939 vTaskDelay( xCycleBlockTime );
\r
943 /*-----------------------------------------------------------*/
\r
945 BaseType_t xAreStreamBufferTasksStillRunning( void )
\r
947 static uint32_t ulLastEchoLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
\r
948 static uint32_t ulLastNonBlockingRxCounter = 0;
\r
949 static uint32_t ulLastInterruptTriggerCounter = 0;
\r
950 BaseType_t xReturn = pdPASS, x;
\r
952 for( x = 0; x < sbNUMBER_OF_ECHO_CLIENTS; x++ )
\r
954 if( ulLastEchoLoopCounters[ x ] == ulEchoLoopCounters[ x ] )
\r
960 ulLastEchoLoopCounters[ x ] = ulEchoLoopCounters[ x ];
\r
964 if( ulNonBlockingRxCounter == ulLastNonBlockingRxCounter )
\r
970 ulLastNonBlockingRxCounter = ulNonBlockingRxCounter;
\r
973 if( ulLastInterruptTriggerCounter == ulInterruptTriggerCounter )
\r
979 ulLastInterruptTriggerCounter = ulInterruptTriggerCounter;
\r
982 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
984 static uint32_t ulLastSenderLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
\r
986 for( x = 0; x < sbNUMBER_OF_SENDER_TASKS; x++ )
\r
988 if( ulLastSenderLoopCounters[ x ] == ulSenderLoopCounters[ x ] )
\r
994 ulLastSenderLoopCounters[ x ] = ulSenderLoopCounters[ x ];
\r
998 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
1002 /*-----------------------------------------------------------*/
\r