Fix buffer clean up in \FreeRTOS_Plus_TCP_Minimal_Windows_Simulator\demo_logging.c.

Update queue code to allow an overwrite operation on a queue that is in a queue set, and add prvTestQueueOverwriteWithQueueSet() to test function.
Update Eclipse Win32 project to bring it closer the the Visual Studio equivalent.
pull/4/head
Richard Barry 7 years ago
parent ff74e7aa63
commit 9ed3a9fe18

@ -296,8 +296,8 @@ HANDLE xCurrentTask;
if( xLength2 < 0 ) if( xLength2 < 0 )
{ {
/* Clean up. */ /* Clean up. */
xLength2 = sizeof( cPrintString ) - 1 - xLength; xLength2 = dlMAX_PRINT_STRING_LENGTH - 1 - xLength;
cPrintString[ sizeof( cPrintString ) - 1 ] = '\0'; cPrintString[ dlMAX_PRINT_STRING_LENGTH - 1 ] = '\0';
} }
xLength += xLength2; xLength += xLength2;

@ -1,9 +1,14 @@
Changes since V2.0.0 release Changes since V2.0.0 release
+ Added FREERTOS_SO_WAKEUP_CALLBACK option so a callback can be executed + Update FreeRTOS_gethostbyname() to allow an IP address to be passed in -
when data arrives. in which case it is just returned as a uint32_t.
+ Improve print output when using WinPCap to assist in selecting the + Introduce ipconfigSOCKET_HAS_USER_WAKE_CALLBACK to FreeRTOS_Sockets.c to
correct network interface. allow a user supposed callback function to be executed when socket events
occur in the same way that the socket semaphore is currently used.
+ Update xNetworkBuffersInitialise() to ensure the semaphore created by the
function is not accessed until after the NULL check.
+ Improve print messages output by the Win32 port layer version of
prvPrintAvailableNetworkInterfaces().
Changes between 160908 and 160919 releases: Changes between 160908 and 160919 releases:

@ -138,9 +138,17 @@ static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived,
/* /*
* Increase test coverage by occasionally change the priorities of the two tasks * Increase test coverage by occasionally change the priorities of the two tasks
* relative to each other. */ * relative to each other.
*/
static void prvChangeRelativePriorities( void ); static void prvChangeRelativePriorities( void );
/*
* Queue overwrites can only be performed on queues of length of one, requiring
* a special test function so a queue of length 1 can temporarily be added to a
* set.
*/
static void prvTestQueueOverwriteWithQueueSet( void );
/* /*
* Local pseudo random number seed and return functions. Used to avoid calls * Local pseudo random number seed and return functions. Used to avoid calls
* to the standard library. * to the standard library.
@ -599,6 +607,71 @@ uint32_t ulTxValueSnapshot = ulISRTxValue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTestQueueOverwriteWithQueueSet( void )
{
uint32_t ulValueToSend = 0, ulValueReceived = 0;
QueueHandle_t xQueueHandle = NULL, xReceivedHandle = NULL;
const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
/* Create a queue that has a length of one - a requirement in order to call
xQueueOverwrite. This will get deleted again when this test completes. */
xQueueHandle = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
if( xQueueHandle != NULL )
{
xQueueAddToSet( xQueueHandle, xQueueSet );
/* Add an item to the queue then ensure the queue set correctly
indicates that one item is available, and that that item is indeed the
queue written to. */
xQueueSend( xQueueHandle, ( void * ) &ulValueToSend, 0 );
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
{
/* Expected one item in the queue set. */
xQueueSetTasksStatus = pdFAIL;
}
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
if( xReceivedHandle != xQueueHandle )
{
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
held in the queue set. */
xQueueSetTasksStatus = pdFAIL;
}
/* Now overwrite the value in the queue and ensure the queue set state
doesn't change as the number of items in the queues within the set have
not changed. */
ulValueToSend++;
xQueueOverwrite( xQueueHandle, ( void * ) &ulValueToSend );
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
{
/* Still expected one item in the queue set. */
xQueueSetTasksStatus = pdFAIL;
}
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
if( xReceivedHandle != xQueueHandle )
{
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
held in the queue set. */
xQueueSetTasksStatus = pdFAIL;
}
/* Also ensure the value received from the queue is the overwritten
value, not the value originally written. */
xQueueReceive( xQueueHandle, &ulValueReceived, queuesetDONT_BLOCK );
if( ulValueReceived != ulValueToSend )
{
/* Unexpected value recevied from the queue. */
xQueueSetTasksStatus = pdFAIL;
}
/* Clean up. */
xQueueRemoveFromSet( xQueueHandle, xQueueSet );
vQueueDelete( xQueueHandle );
}
}
/*-----------------------------------------------------------*/
static void prvSetupTest( void ) static void prvSetupTest( void )
{ {
BaseType_t x; BaseType_t x;
@ -675,6 +748,11 @@ uint32_t ulValueToSend = 0;
xQueueSetTasksStatus = pdFAIL; xQueueSetTasksStatus = pdFAIL;
} }
/* Testing the behaviour of queue sets when a queue overwrite operation is
performed on a set member requires a special test as overwrites can only
be performed on queues that have a length of 1. */
prvTestQueueOverwriteWithQueueSet();
/* Resume the task that writes to the queues. */ /* Resume the task that writes to the queues. */
vTaskResume( xQueueSetSendingTask ); vTaskResume( xQueueSetSendingTask );

@ -172,7 +172,7 @@ BaseType_t xNextByte = 0;
continuing to look for the end of the string. */ continuing to look for the end of the string. */
xNextByte++; xNextByte++;
configASSERT( xNextByte < sizeof( cRxBuffer ) ); configASSERT( ( size_t ) xNextByte < sizeof( cRxBuffer ) );
} }
} }
} }
@ -193,7 +193,7 @@ static BaseType_t xCallCount = 0;
/* Send the next four bytes to the stream buffer. */ /* Send the next four bytes to the stream buffer. */
xStreamBufferSendFromISR( xStreamBuffer, xStreamBufferSendFromISR( xStreamBuffer,
( void * ) ( pcStringToSend + xNextByteToSend ), ( const void * ) ( pcStringToSend + xNextByteToSend ),
xBytesToSend, xBytesToSend,
NULL ); NULL );

@ -141,8 +141,8 @@ static void prvDemonstrateTaskStateAndHandleGetFunctions( void );
static void prvDemonstratePendingFunctionCall( void ); static void prvDemonstratePendingFunctionCall( void );
/* /*
* The function that is pended by prvDemonstratePendingFunctionCall(). * The function that is pended by prvDemonstratePendingFunctionCall().
*/ */
static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 ); static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 );
/* /*

@ -56,7 +56,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156304</id> <id>1519407948166</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -65,7 +65,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156307</id> <id>1519407948169</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -74,7 +74,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156310</id> <id>1519407948172</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -83,7 +83,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156313</id> <id>1519407948176</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -92,7 +92,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156316</id> <id>1519407948179</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -101,7 +101,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156319</id> <id>1519407948183</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -110,7 +110,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156323</id> <id>1519407948186</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -119,7 +119,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156327</id> <id>1519407948190</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -128,7 +128,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156330</id> <id>1519407948195</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -137,7 +137,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156333</id> <id>1519407948199</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -146,7 +146,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156337</id> <id>1519407948202</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -155,7 +155,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156340</id> <id>1519407948213</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -164,7 +164,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156343</id> <id>1519407948216</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -173,7 +173,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156347</id> <id>1519407948224</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -182,7 +182,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156350</id> <id>1519407948228</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -191,7 +191,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156353</id> <id>1519407948231</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -200,7 +200,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156356</id> <id>1519407948235</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -209,7 +209,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156359</id> <id>1519407948237</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -218,7 +218,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156362</id> <id>1519407948240</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -227,7 +227,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156366</id> <id>1519407948242</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -236,7 +236,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>1507735156369</id> <id>1519407948269</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -244,6 +244,42 @@
<arguments>1.0-name-matches-false-false-MessageBufferDemo.c</arguments> <arguments>1.0-name-matches-false-false-MessageBufferDemo.c</arguments>
</matcher> </matcher>
</filter> </filter>
<filter>
<id>1519407948274</id>
<name>Standard_Demo_Tasks</name>
<type>5</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-StreamBufferDemo.c</arguments>
</matcher>
</filter>
<filter>
<id>1519407948277</id>
<name>Standard_Demo_Tasks</name>
<type>5</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-StreamBufferInterrupt.c</arguments>
</matcher>
</filter>
<filter>
<id>1519407948281</id>
<name>Standard_Demo_Tasks</name>
<type>5</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-MessageBufferDemo.c</arguments>
</matcher>
</filter>
<filter>
<id>1519407948286</id>
<name>Standard_Demo_Tasks</name>
<type>5</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-MessageBufferAMP.c</arguments>
</matcher>
</filter>
<filter> <filter>
<id>0</id> <id>0</id>
<name>FreeRTOS_Source/portable</name> <name>FreeRTOS_Source/portable</name>

@ -114,6 +114,12 @@ uses the same semantics as the standard C assert() macro. */
extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName ); extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ ) #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ )
#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 1
#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 )
extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer );
#define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer )
#endif /* configINCLUDE_MESSAGE_BUFFER_AMP_DEMO */
/* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */ /* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */
#include "trcRecorder.h" #include "trcRecorder.h"

@ -26,81 +26,87 @@
*/ */
/****************************************************************************** /******************************************************************************
* NOTE 1: The Win32 port is a simulation (or is that emulation?) only! Do not * NOTE 1: Windows will not be running the FreeRTOS demo threads continuously, so
* expect to get real time behaviour from the Win32 port or this demo * do not expect to get real time behaviour from the FreeRTOS Windows port, or
* application. It is provided as a convenient development and demonstration * this demo application. Also, the timing information in the FreeRTOS+Trace
* test bed only. This was tested using Windows XP on a dual core laptop. * logs have no meaningful units. See the documentation page for the Windows
* * port for further information:
* Windows will not be running the FreeRTOS simulator threads continuously, so
* the timing information in the FreeRTOS+Trace logs have no meaningful units.
* See the documentation page for the Windows simulator for an explanation of
* the slow timing:
* http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html * http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html
* - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT -
* *
* NOTE 2: This project provides two demo applications. A simple blinky style * NOTE 2: This project provides two demo applications. A simple blinky style
* project, and a more comprehensive test and demo application. The * project, and a more comprehensive test and demo application. The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
* between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
* in main.c. This file implements the simply blinky style version. * in main.c. This file implements the simply blinky version. Console output
* is used in place of the normal LED toggling.
* *
* NOTE 3: This file only contains the source code that is specific to the * NOTE 3: This file only contains the source code that is specific to the
* basic demo. Generic functions, such FreeRTOS hook functions, are defined * basic demo. Generic functions, such FreeRTOS hook functions, are defined
* in main.c. * in main.c.
****************************************************************************** ******************************************************************************
* *
* main_blinky() creates one queue, and two tasks. It then starts the * main_blinky() creates one queue, one software timer, and two tasks. It then
* scheduler. * starts the scheduler.
* *
* The Queue Send Task: * The Queue Send Task:
* The queue send task is implemented by the prvQueueSendTask() function in * The queue send task is implemented by the prvQueueSendTask() function in
* this file. prvQueueSendTask() sits in a loop that causes it to repeatedly * this file. It uses vTaskDelayUntil() to create a periodic task that sends
* block for 200 (simulated as far as the scheduler is concerned, but in * the value 100 to the queue every 200 milliseconds (please read the notes
* reality much longer - see notes above) milliseconds, before sending the * above regarding the accuracy of timing under Windows).
* value 100 to the queue that was created within main_blinky(). Once the *
* value is sent, the task loops back around to block for another 200 * The Queue Send Software Timer:
* (simulated) milliseconds. * The timer is an auto-reload timer with a period of two seconds. The timer's
* callback function writes the value 200 to the queue. The callback function
* is implemented by prvQueueSendTimerCallback() within this file.
* *
* The Queue Receive Task: * The Queue Receive Task:
* The queue receive task is implemented by the prvQueueReceiveTask() function * The queue receive task is implemented by the prvQueueReceiveTask() function
* in this file. prvQueueReceiveTask() sits in a loop where it repeatedly * in this file. prvQueueReceiveTask() waits for data to arrive on the queue.
* blocks on attempts to read data from the queue that was created within * When data is received, the task checks the value of the data, then outputs a
* main_blinky(). When data is received, the task checks the value of the * message to indicate if the data came from the queue send task or the queue
* data, and if the value equals the expected 100, outputs a message. The * send software timer.
* 'block time' parameter passed to the queue receive function specifies that *
* the task should be held in the Blocked state indefinitely to wait for data * Expected Behaviour:
* to be available on the queue. The queue receive task will only leave the * - The queue send task writes to the queue every 200ms, so every 200ms the
* Blocked state when the queue send task writes to the queue. As the queue * queue receive task will output a message indicating that data was received
* send task writes to the queue every 200 (simulated - see notes above) * on the queue from the queue send task.
* milliseconds, the queue receive task leaves the Blocked state every 200 * - The queue send software timer has a period of two seconds, and is reset
* milliseconds, and therefore outputs a message every 200 milliseconds. * each time a key is pressed. So if two seconds expire without a key being
* pressed then the queue receive task will output a message indicating that
* data was received on the queue from the queue send software timer.
*
* NOTE: Console input and output relies on Windows system calls, which can
* interfere with the execution of the FreeRTOS Windows port. This demo only
* uses Windows system call occasionally. Heavier use of Windows system calls
* can crash the port.
*/ */
/* Standard includes. */ /* Standard includes. */
#include <stdio.h> #include <stdio.h>
#include <conio.h>
/* Kernel includes. */ /* Kernel includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "timers.h"
#include "semphr.h" #include "semphr.h"
/* Priorities at which the tasks are created. */ /* Priorities at which the tasks are created. */
#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* The rate at which data is sent to the queue. The 200ms value is converted /* The rate at which data is sent to the queue. The times are converted from
to ticks using the portTICK_PERIOD_MS constant. */ milliseconds to ticks using the pdMS_TO_TICKS() macro. */
#define mainQUEUE_SEND_FREQUENCY_MS ( 200 / portTICK_PERIOD_MS ) #define mainTASK_SEND_FREQUENCY_MS pdMS_TO_TICKS( 200UL )
#define mainTIMER_SEND_FREQUENCY_MS pdMS_TO_TICKS( 2000UL )
/* The number of items the queue can hold. This is 1 as the receive task /* The number of items the queue can hold at once. */
will remove items as they are added, meaning the send task should always find #define mainQUEUE_LENGTH ( 2 )
the queue empty. */
#define mainQUEUE_LENGTH ( 1 )
/* Values passed to the two tasks just to check the task parameter /* The values sent to the queue receive task from the queue send task and the
functionality. */ queue send software timer respectively. */
#define mainQUEUE_SEND_PARAMETER ( 0x1111UL ) #define mainVALUE_SENT_FROM_TASK ( 100UL )
#define mainQUEUE_RECEIVE_PARAMETER ( 0x22UL ) #define mainVALUE_SENT_FROM_TIMER ( 200UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -110,17 +116,28 @@ functionality. */
static void prvQueueReceiveTask( void *pvParameters ); static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters ); static void prvQueueSendTask( void *pvParameters );
/*
* The callback function executed when the software timer expires.
*/
static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The queue used by both tasks. */ /* The queue used by both tasks. */
static QueueHandle_t xQueue = NULL; static QueueHandle_t xQueue = NULL;
/* A software timer that is started from the tick hook. */
static TimerHandle_t xTimer = NULL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*** SEE THE COMMENTS AT THE TOP OF THIS FILE ***/
void main_blinky( void ) void main_blinky( void )
{ {
const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS;
/* Create the queue. */ /* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) ); xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
if( xQueue != NULL ) if( xQueue != NULL )
{ {
@ -129,11 +146,23 @@ void main_blinky( void )
xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */ xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
"Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
( void * ) mainQUEUE_RECEIVE_PARAMETER, /* The parameter passed to the task - just to check the functionality. */ NULL, /* The parameter passed to the task - not used in this simple case. */
mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */ mainQUEUE_RECEIVE_TASK_PRIORITY,/* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */ NULL ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, ( void * ) mainQUEUE_SEND_PARAMETER, mainQUEUE_SEND_TASK_PRIORITY, NULL ); xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
/* Create the software timer, but don't start it yet. */
xTimer = xTimerCreate( "Timer", /* The text name assigned to the software timer - for debug only as it is not used by the kernel. */
xTimerPeriod, /* The period of the software timer in ticks. */
pdTRUE, /* xAutoReload is set to pdTRUE. */
NULL, /* The timer's ID is not used. */
prvQueueSendTimerCallback );/* The function executed when the timer expires. */
if( xTimer != NULL )
{
xTimerStart( xTimer, 0 );
}
/* Start the tasks and timer running. */ /* Start the tasks and timer running. */
vTaskStartScheduler(); vTaskStartScheduler();
@ -151,65 +180,86 @@ void main_blinky( void )
static void prvQueueSendTask( void *pvParameters ) static void prvQueueSendTask( void *pvParameters )
{ {
TickType_t xNextWakeTime; TickType_t xNextWakeTime;
const unsigned long ulValueToSend = 100UL; const TickType_t xBlockTime = mainTASK_SEND_FREQUENCY_MS;
const TickType_t xBlockTime = pdMS_TO_TICKS( mainQUEUE_SEND_FREQUENCY_MS ); const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TASK;
/* Remove compiler warning in the case that configASSERT() is not /* Prevent the compiler warning about the unused parameter. */
defined. */
( void ) pvParameters; ( void ) pvParameters;
/* Check the task parameter is as expected. */
configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_SEND_PARAMETER );
/* Initialise xNextWakeTime - this only needs to be done once. */ /* Initialise xNextWakeTime - this only needs to be done once. */
xNextWakeTime = xTaskGetTickCount(); xNextWakeTime = xTaskGetTickCount();
for( ;; ) for( ;; )
{ {
/* Place this task in the blocked state until it is time to run again. /* Place this task in the blocked state until it is time to run again.
The block time is specified in ticks, the constant used converts ticks The block time is specified in ticks, pdMS_TO_TICKS() was used to
to ms. While in the Blocked state this task will not consume any CPU convert a time specified in milliseconds into a time specified in ticks.
time. */ While in the Blocked state this task will not consume any CPU time. */
vTaskDelayUntil( &xNextWakeTime, xBlockTime ); vTaskDelayUntil( &xNextWakeTime, xBlockTime );
/* Send to the queue - causing the queue receive task to unblock and /* Send to the queue - causing the queue receive task to unblock and
toggle the LED. 0 is used as the block time so the sending operation write to the console. 0 is used as the block time so the send operation
will not block - it shouldn't need to block as the queue should always will not block - it shouldn't need to block as the queue should always
be empty at this point in the code. */ have at least one space at this point in the code. */
xQueueSend( xQueue, &ulValueToSend, 0U ); xQueueSend( xQueue, &ulValueToSend, 0U );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle )
{
const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TIMER;
/* This is the software timer callback function. The software timer has a
period of two seconds and is reset each time a key is pressed. This
callback function will execute if the timer expires, which will only happen
if a key is not pressed for two seconds. */
/* Avoid compiler warnings resulting from the unused parameter. */
( void ) xTimerHandle;
/* Send to the queue - causing the queue receive task to unblock and
write out a message. This function is called from the timer/daemon task, so
must not block. Hence the block time is set to 0. */
xQueueSend( xQueue, &ulValueToSend, 0U );
}
/*-----------------------------------------------------------*/
static void prvQueueReceiveTask( void *pvParameters ) static void prvQueueReceiveTask( void *pvParameters )
{ {
unsigned long ulReceivedValue; uint32_t ulReceivedValue;
/* Remove compiler warning in the case that configASSERT() is not /* Prevent the compiler warning about the unused parameter. */
defined. */
( void ) pvParameters; ( void ) pvParameters;
/* Check the task parameter is as expected. */
configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_RECEIVE_PARAMETER );
for( ;; ) for( ;; )
{ {
/* Wait until something arrives in the queue - this task will block /* Wait until something arrives in the queue - this task will block
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
FreeRTOSConfig.h. */ FreeRTOSConfig.h. It will not use any CPU time while it is in the
Blocked state. */
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY ); xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
/* To get here something must have been received from the queue, but /* To get here something must have been received from the queue, but
is it the expected value? If it is, toggle the LED. */ is it an expected value? Normally calling printf() from a task is not
if( ulReceivedValue == 100UL ) a good idea. Here there is lots of stack space and only one task is
using console IO so it is ok. However, note the comments at the top of
this file about the risks of making Windows system calls (such as
console output) from a FreeRTOS task. */
if( ulReceivedValue == mainVALUE_SENT_FROM_TASK )
{ {
/* Normally calling printf() from a task is not a good idea. Here printf( "Message received from task\r\n" );
there is lots of stack space and only one task is using console IO }
so it is ok. */ else if( ulReceivedValue == mainVALUE_SENT_FROM_TIMER )
printf( "Message received\r\n" ); {
fflush( stdout ); printf( "Message received from software timer\r\n" );
ulReceivedValue = 0U;
} }
else
{
printf( "Unexpected message\r\n" );
}
fflush( stdout );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

@ -102,6 +102,8 @@
#include "AbortDelay.h" #include "AbortDelay.h"
#include "MessageBufferDemo.h" #include "MessageBufferDemo.h"
#include "StreamBufferDemo.h" #include "StreamBufferDemo.h"
#include "StreamBufferInterrupt.h"
#include "MessageBufferAMP.h"
/* Priorities at which the tasks are created. */ /* Priorities at which the tasks are created. */
#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) #define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
@ -204,6 +206,8 @@ int main_full( void )
vStartMessageBufferTasks(); vStartMessageBufferTasks();
vStartStreamBufferTasks(); vStartStreamBufferTasks();
vStartStreamBufferInterruptDemo();
vStartMessageBufferAMPTasks();
#if( configUSE_PREEMPTION != 0 ) #if( configUSE_PREEMPTION != 0 )
{ {
@ -342,10 +346,28 @@ const TickType_t xCycleFrequency = pdMS_TO_TICKS( 2500UL );
{ {
pcStatusMessage = "Error: Abort delay"; pcStatusMessage = "Error: Abort delay";
} }
else if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS )
{
pcStatusMessage = "Error: Stream buffer interrupt";
}
else if( xAreMessageBufferAMPTasksStillRunning() != pdPASS )
{
pcStatusMessage = "Error: Message buffer AMP";
}
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
else if( xAreStaticAllocationTasksStillRunning() != pdPASS )
{
pcStatusMessage = "Error: Static allocation";
}
#endif /* configSUPPORT_STATIC_ALLOCATION */
/* This is the only task that uses stdout so its ok to call printf() /* This is the only task that uses stdout so its ok to call printf()
directly. */ directly. */
printf( ( char * ) "%s - %u\r\n", pcStatusMessage, ( unsigned int ) xTaskGetTickCount() ); printf( "%s - tick count %u - free heap %u - min free heap %u\r\n", pcStatusMessage,
xTaskGetTickCount(),
xPortGetFreeHeapSize(),
xPortGetMinimumEverFreeHeapSize() );
fflush( stdout ); fflush( stdout );
} }
} }
@ -454,6 +476,10 @@ TaskHandle_t xTimerTask;
level functionality. */ level functionality. */
vPeriodicStreamBufferProcessing(); vPeriodicStreamBufferProcessing();
/* Writes a string to a string buffer four bytes at a time to demonstrate
a stream being sent from an interrupt to a task. */
vBasicStreamBufferSendFromISR();
/* For code coverage purposes. */ /* For code coverage purposes. */
xTimerTask = xTimerGetTimerDaemonTaskHandle(); xTimerTask = xTimerGetTimerDaemonTaskHandle();
configASSERT( uxTaskPriorityGetFromISR( xTimerTask ) == configTIMER_TASK_PRIORITY ); configASSERT( uxTaskPriorityGetFromISR( xTimerTask ) == configTIMER_TASK_PRIORITY );

@ -752,13 +752,23 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
{ {
traceQUEUE_SEND( pxQueue ); traceQUEUE_SEND( pxQueue );
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
#if ( configUSE_QUEUE_SETS == 1 ) #if ( configUSE_QUEUE_SETS == 1 )
{ {
UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
if( pxQueue->pxQueueSetContainer != NULL ) if( pxQueue->pxQueueSetContainer != NULL )
{ {
if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )
{
/* Do not notify the queue set as an existing item
was overwritten in the queue so the number of items
in the queue has not changed. */
mtCOVERAGE_TEST_MARKER();
}
else if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )
{ {
/* The queue is a member of a queue set, and posting /* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to to the queue set caused a higher priority task to
@ -805,6 +815,8 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
} }
#else /* configUSE_QUEUE_SETS */ #else /* configUSE_QUEUE_SETS */
{ {
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
/* If there was a task waiting for data to arrive on the /* If there was a task waiting for data to arrive on the
queue then unblock it now. */ queue then unblock it now. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )

Loading…
Cancel
Save