mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-12-15 16:15:08 -05:00
Use new QEMU test project to improve stream/message buffer tests (#168)
* Add Eclipse/GCC project that targets the LM3S8962 QEMU model. * Get the Cortex-M QEMU project working. * Continue working on making stream buffer demo more robust and QEMU project. * Rename directory CORTEX_LM3S8986_QEMU to CORTEX_LM3S6965_QEMU. Work on making the Stream Buffer tests more robust. Check in before adding in the trace recorder. * Rename CORTEX_LM3S6969_QEMU to CORTEX_LM3S6969_GCC_QEMU. * Make the StreamBufferDemo.c common demo file (test file) more robust to other test tasks running at an equally high priority. * Work in progress checkin only - comments in main.c are incorrect. * Correct comments at the top of FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/main.c Make the message buffer tests more robust in the case the a message buffer becomes full when prvSenderTask() has a higher priority than the reader task. * Disable trace recorder in the LM3S6965 QEMU demo. * I'm dropping FreeRTOS-Kernel reference update, since this seems to break the CMBC CI. Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com>
This commit is contained in:
parent
157a7fc39f
commit
0e0edd96e8
23 changed files with 4139 additions and 28 deletions
|
|
@ -69,7 +69,17 @@ the Blocked state so it can read the bytes. */
|
|||
|
||||
/* 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. */
|
||||
#define sbSTACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
|
||||
#ifndef configSTREAM_BUFFER_SENDER_TASK_STACK_SIZE
|
||||
#define sbSTACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
|
||||
#else
|
||||
#define sbSTACK_SIZE configSTREAM_BUFFER_SENDER_TASK_STACK_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef configSTREAM_BUFFER_SMALLER_TASK_STACK_SIZE
|
||||
#define sbSMALLER_STACK_SIZE sbSTACK_SIZE
|
||||
#else
|
||||
#define sbSMALLER_STACK_SIZE configSTREAM_BUFFER_SMALLER_TASK_STACK_SIZE
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -148,7 +158,7 @@ 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 = "12345678";
|
||||
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
|
||||
|
|
@ -171,8 +181,8 @@ 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", sbSTACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
|
||||
xTaskCreate( prvEchoServer, "2StrEchoServer", sbSTACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
|
||||
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
|
||||
|
|
@ -192,8 +202,8 @@ StreamBufferHandle_t xStreamBuffer;
|
|||
/* 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", sbSTACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
|
||||
xTaskCreate( prvSenderTask, "Str2Sender", sbSTACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
|
||||
xTaskCreate( prvSenderTask, "Str1Sender", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
|
||||
xTaskCreate( prvSenderTask, "Str2Sender", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
|
||||
}
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
}
|
||||
|
|
@ -599,11 +609,11 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
|||
/* Here prvSingleTaskTests() performs various tests on a stream buffer
|
||||
that was created statically. */
|
||||
prvSingleTaskTests( xStreamBuffer );
|
||||
xTaskCreate( prvReceiverTask, "StrReceiver", sbSTACK_SIZE, ( void * ) xStreamBuffer, sbHIGHER_PRIORITY, NULL );
|
||||
xTaskCreate( prvReceiverTask, "StrReceiver", sbSMALLER_STACK_SIZE, ( void * ) xStreamBuffer, sbHIGHER_PRIORITY, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
xTaskCreate( prvReceiverTask, "StrReceiver", sbSTACK_SIZE, ( void * ) xStreamBuffer, sbLOWER_PRIORITY, NULL );
|
||||
xTaskCreate( prvReceiverTask, "StrReceiver", sbSMALLER_STACK_SIZE, ( void * ) xStreamBuffer, sbLOWER_PRIORITY, NULL );
|
||||
}
|
||||
|
||||
for( ;; )
|
||||
|
|
@ -770,7 +780,6 @@ EchoStreamBuffers_t *pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
|
|||
/* This stream buffer is just created and deleted to ensure no memory
|
||||
leaks. */
|
||||
xTempStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
||||
prvSingleTaskTests( xTempStreamBuffer );
|
||||
vStreamBufferDelete( xTempStreamBuffer );
|
||||
|
||||
/* The following are tests for a stream buffer of size one. */
|
||||
|
|
@ -856,14 +865,14 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 350UL );
|
|||
priority then the client task is created at the higher priority. */
|
||||
if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
|
||||
{
|
||||
xTaskCreate( prvEchoClient, "EchoClient", sbSTACK_SIZE, ( void * ) &xStreamBuffers, sbHIGHER_PRIORITY, NULL );
|
||||
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", sbSTACK_SIZE, ( void * ) &xStreamBuffers, sbLOWER_PRIORITY, NULL );
|
||||
xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbLOWER_PRIORITY, NULL );
|
||||
}
|
||||
|
||||
for( ;; )
|
||||
|
|
@ -914,14 +923,14 @@ static void prvInterruptTriggerLevelTest( void *pvParameters )
|
|||
{
|
||||
StreamBufferHandle_t xStreamBuffer;
|
||||
size_t xTriggerLevel = 1, xBytesReceived;
|
||||
const size_t xStreamBufferSizeBytes = ( size_t ) 8, xMaxTriggerLevel = ( size_t ) 6, xMinTriggerLevel = ( size_t ) 1;
|
||||
const TickType_t xReadBlockTime = 4, xCycleBlockTime = pdMS_TO_TICKS( 100 );
|
||||
uint8_t ucRxData[ 8 ];
|
||||
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;
|
||||
const size_t xAllowableMargin = ( size_t ) 0;
|
||||
#else
|
||||
const size_t xAllowableMargin = ( size_t ) configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN;
|
||||
const size_t xAllowableMargin = ( size_t ) configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN;
|
||||
#endif
|
||||
|
||||
/* Remove compiler warning about unused parameter. */
|
||||
|
|
@ -931,6 +940,12 @@ BaseType_t xErrorDetected = pdFALSE;
|
|||
{
|
||||
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 ) );
|
||||
|
|
@ -963,9 +978,27 @@ BaseType_t xErrorDetected = pdFALSE;
|
|||
{
|
||||
/* Trigger level was greater than the block time so expect to
|
||||
time out having received xReadBlockTime bytes. */
|
||||
if( ( xReadBlockTime - xBytesReceived ) > xAllowableMargin )
|
||||
if( xBytesReceived > xReadBlockTime )
|
||||
{
|
||||
xErrorDetected = pdTRUE;
|
||||
/* 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 )
|
||||
|
|
@ -973,19 +1006,43 @@ BaseType_t xErrorDetected = pdFALSE;
|
|||
/* 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. */
|
||||
if( ( xBytesReceived - xTriggerLevel ) > xAllowableMargin )
|
||||
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 equaled the block time, so expect to
|
||||
receive no greater than the block time, but one or two less is
|
||||
ok due to variations in how far through the time slice the
|
||||
functions get executed. */
|
||||
if( ( xBytesReceived - xReadBlockTime ) > xAllowableMargin )
|
||||
/* 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;
|
||||
}
|
||||
|
|
@ -1010,7 +1067,6 @@ BaseType_t xErrorDetected = pdFALSE;
|
|||
|
||||
/* Tidy up ready for the next loop. */
|
||||
vStreamBufferDelete( xStreamBuffer );
|
||||
vTaskDelay( xCycleBlockTime );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue