From 9e75a9ea52f38df40565e0eb9ac9332233c79ce9 Mon Sep 17 00:00:00 2001 From: rtel Date: Mon, 26 Feb 2018 21:22:44 +0000 Subject: [PATCH] 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. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2530 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../demo_logging.c | 4 +- .../Source/FreeRTOS-Plus-TCP/History.txt | 13 +- FreeRTOS/Demo/Common/Minimal/QueueSet.c | 80 ++++++- .../Common/Minimal/StreamBufferInterrupt.c | 4 +- FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo | Bin 44032 -> 49664 bytes FreeRTOS/Demo/WIN32-MSVC/main_full.c | 4 +- FreeRTOS/Demo/WIN32-MingW/.project | 78 +++++-- FreeRTOS/Demo/WIN32-MingW/FreeRTOSConfig.h | 6 + FreeRTOS/Demo/WIN32-MingW/main_blinky.c | 204 +++++++++++------- FreeRTOS/Demo/WIN32-MingW/main_full.c | 28 ++- FreeRTOS/Source/queue.c | 16 +- 11 files changed, 325 insertions(+), 112 deletions(-) diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.c index 447aeef36..41cd548ea 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.c @@ -296,8 +296,8 @@ HANDLE xCurrentTask; if( xLength2 < 0 ) { /* Clean up. */ - xLength2 = sizeof( cPrintString ) - 1 - xLength; - cPrintString[ sizeof( cPrintString ) - 1 ] = '\0'; + xLength2 = dlMAX_PRINT_STRING_LENGTH - 1 - xLength; + cPrintString[ dlMAX_PRINT_STRING_LENGTH - 1 ] = '\0'; } xLength += xLength2; diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt index 727bf3c84..fd3ba86fa 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt @@ -1,9 +1,14 @@ Changes since V2.0.0 release - + Added FREERTOS_SO_WAKEUP_CALLBACK option so a callback can be executed - when data arrives. - + Improve print output when using WinPCap to assist in selecting the - correct network interface. + + Update FreeRTOS_gethostbyname() to allow an IP address to be passed in - + in which case it is just returned as a uint32_t. + + Introduce ipconfigSOCKET_HAS_USER_WAKE_CALLBACK to FreeRTOS_Sockets.c to + 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: diff --git a/FreeRTOS/Demo/Common/Minimal/QueueSet.c b/FreeRTOS/Demo/Common/Minimal/QueueSet.c index 9f346bb5a..528ec06c0 100644 --- a/FreeRTOS/Demo/Common/Minimal/QueueSet.c +++ b/FreeRTOS/Demo/Common/Minimal/QueueSet.c @@ -138,9 +138,17 @@ static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, /* * Increase test coverage by occasionally change the priorities of the two tasks - * relative to each other. */ + * relative to each other. + */ 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 * 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 ) { BaseType_t x; @@ -675,6 +748,11 @@ uint32_t ulValueToSend = 0; 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. */ vTaskResume( xQueueSetSendingTask ); diff --git a/FreeRTOS/Demo/Common/Minimal/StreamBufferInterrupt.c b/FreeRTOS/Demo/Common/Minimal/StreamBufferInterrupt.c index 772d5b4c6..112dbf30c 100644 --- a/FreeRTOS/Demo/Common/Minimal/StreamBufferInterrupt.c +++ b/FreeRTOS/Demo/Common/Minimal/StreamBufferInterrupt.c @@ -172,7 +172,7 @@ BaseType_t xNextByte = 0; continuing to look for the end of the string. */ 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. */ xStreamBufferSendFromISR( xStreamBuffer, - ( void * ) ( pcStringToSend + xNextByteToSend ), + ( const void * ) ( pcStringToSend + xNextByteToSend ), xBytesToSend, NULL ); diff --git a/FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo b/FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo index e28c889a4361b37bc393c0bd7bcd6217117df43c..87d803022f5336a90ac661e095bfa862fae8593d 100644 GIT binary patch delta 4753 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 - 1507735156304 + 1519407948166 Standard_Demo_Tasks 5 @@ -65,7 +65,7 @@ - 1507735156307 + 1519407948169 Standard_Demo_Tasks 5 @@ -74,7 +74,7 @@ - 1507735156310 + 1519407948172 Standard_Demo_Tasks 5 @@ -83,7 +83,7 @@ - 1507735156313 + 1519407948176 Standard_Demo_Tasks 5 @@ -92,7 +92,7 @@ - 1507735156316 + 1519407948179 Standard_Demo_Tasks 5 @@ -101,7 +101,7 @@ - 1507735156319 + 1519407948183 Standard_Demo_Tasks 5 @@ -110,7 +110,7 @@ - 1507735156323 + 1519407948186 Standard_Demo_Tasks 5 @@ -119,7 +119,7 @@ - 1507735156327 + 1519407948190 Standard_Demo_Tasks 5 @@ -128,7 +128,7 @@ - 1507735156330 + 1519407948195 Standard_Demo_Tasks 5 @@ -137,7 +137,7 @@ - 1507735156333 + 1519407948199 Standard_Demo_Tasks 5 @@ -146,7 +146,7 @@ - 1507735156337 + 1519407948202 Standard_Demo_Tasks 5 @@ -155,7 +155,7 @@ - 1507735156340 + 1519407948213 Standard_Demo_Tasks 5 @@ -164,7 +164,7 @@ - 1507735156343 + 1519407948216 Standard_Demo_Tasks 5 @@ -173,7 +173,7 @@ - 1507735156347 + 1519407948224 Standard_Demo_Tasks 5 @@ -182,7 +182,7 @@ - 1507735156350 + 1519407948228 Standard_Demo_Tasks 5 @@ -191,7 +191,7 @@ - 1507735156353 + 1519407948231 Standard_Demo_Tasks 5 @@ -200,7 +200,7 @@ - 1507735156356 + 1519407948235 Standard_Demo_Tasks 5 @@ -209,7 +209,7 @@ - 1507735156359 + 1519407948237 Standard_Demo_Tasks 5 @@ -218,7 +218,7 @@ - 1507735156362 + 1519407948240 Standard_Demo_Tasks 5 @@ -227,7 +227,7 @@ - 1507735156366 + 1519407948242 Standard_Demo_Tasks 5 @@ -236,7 +236,7 @@ - 1507735156369 + 1519407948269 Standard_Demo_Tasks 5 @@ -244,6 +244,42 @@ 1.0-name-matches-false-false-MessageBufferDemo.c + + 1519407948274 + Standard_Demo_Tasks + 5 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-StreamBufferDemo.c + + + + 1519407948277 + Standard_Demo_Tasks + 5 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-StreamBufferInterrupt.c + + + + 1519407948281 + Standard_Demo_Tasks + 5 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-MessageBufferDemo.c + + + + 1519407948286 + Standard_Demo_Tasks + 5 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-MessageBufferAMP.c + + 0 FreeRTOS_Source/portable diff --git a/FreeRTOS/Demo/WIN32-MingW/FreeRTOSConfig.h b/FreeRTOS/Demo/WIN32-MingW/FreeRTOSConfig.h index 89331b274..f25119d49 100644 --- a/FreeRTOS/Demo/WIN32-MingW/FreeRTOSConfig.h +++ b/FreeRTOS/Demo/WIN32-MingW/FreeRTOSConfig.h @@ -114,6 +114,12 @@ uses the same semantics as the standard C assert() macro. */ extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName ); #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 "trcRecorder.h" diff --git a/FreeRTOS/Demo/WIN32-MingW/main_blinky.c b/FreeRTOS/Demo/WIN32-MingW/main_blinky.c index d04658289..822cbd424 100644 --- a/FreeRTOS/Demo/WIN32-MingW/main_blinky.c +++ b/FreeRTOS/Demo/WIN32-MingW/main_blinky.c @@ -26,81 +26,87 @@ */ /****************************************************************************** - * NOTE 1: The Win32 port is a simulation (or is that emulation?) only! Do not - * expect to get real time behaviour from the Win32 port or this demo - * application. It is provided as a convenient development and demonstration - * test bed only. This was tested using Windows XP on a dual core laptop. - * - * 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: + * NOTE 1: Windows will not be running the FreeRTOS demo threads continuously, so + * do not expect to get real time behaviour from the FreeRTOS Windows port, or + * this demo application. Also, the timing information in the FreeRTOS+Trace + * logs have no meaningful units. See the documentation page for the Windows + * port for further information: * 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 * project, and a more comprehensive test and demo application. The * 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 - * 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 * basic demo. Generic functions, such FreeRTOS hook functions, are defined * in main.c. ****************************************************************************** * - * main_blinky() creates one queue, and two tasks. It then starts the - * scheduler. + * main_blinky() creates one queue, one software timer, and two tasks. It then + * starts the scheduler. * * The Queue Send Task: * The queue send task is implemented by the prvQueueSendTask() function in - * this file. prvQueueSendTask() sits in a loop that causes it to repeatedly - * block for 200 (simulated as far as the scheduler is concerned, but in - * reality much longer - see notes above) milliseconds, before sending the - * 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 - * (simulated) milliseconds. + * this file. It uses vTaskDelayUntil() to create a periodic task that sends + * the value 100 to the queue every 200 milliseconds (please read the notes + * above regarding the accuracy of timing under Windows). + * + * The Queue Send Software Timer: + * 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 is implemented by the prvQueueReceiveTask() function - * in this file. prvQueueReceiveTask() sits in a loop where it repeatedly - * blocks on attempts to read data from the queue that was created within - * main_blinky(). When data is received, the task checks the value of the - * data, and if the value equals the expected 100, outputs a message. The - * '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 - * to be available on the queue. The queue receive task will only leave the - * Blocked state when the queue send task writes to the queue. As the queue - * send task writes to the queue every 200 (simulated - see notes above) - * milliseconds, the queue receive task leaves the Blocked state every 200 - * milliseconds, and therefore outputs a message every 200 milliseconds. + * in this file. prvQueueReceiveTask() waits for data to arrive on the queue. + * When data is received, the task checks the value of the data, then outputs a + * message to indicate if the data came from the queue send task or the queue + * send software timer. + * + * Expected Behaviour: + * - The queue send task writes to the queue every 200ms, so every 200ms the + * queue receive task will output a message indicating that data was received + * on the queue from the queue send task. + * - The queue send software timer has a period of two seconds, and is reset + * 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. */ #include +#include /* Kernel includes. */ #include "FreeRTOS.h" #include "task.h" +#include "timers.h" #include "semphr.h" /* Priorities at which the tasks are created. */ #define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) -/* The rate at which data is sent to the queue. The 200ms value is converted -to ticks using the portTICK_PERIOD_MS constant. */ -#define mainQUEUE_SEND_FREQUENCY_MS ( 200 / portTICK_PERIOD_MS ) +/* The rate at which data is sent to the queue. The times are converted from +milliseconds to ticks using the pdMS_TO_TICKS() macro. */ +#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 -will remove items as they are added, meaning the send task should always find -the queue empty. */ -#define mainQUEUE_LENGTH ( 1 ) +/* The number of items the queue can hold at once. */ +#define mainQUEUE_LENGTH ( 2 ) -/* Values passed to the two tasks just to check the task parameter -functionality. */ -#define mainQUEUE_SEND_PARAMETER ( 0x1111UL ) -#define mainQUEUE_RECEIVE_PARAMETER ( 0x22UL ) +/* The values sent to the queue receive task from the queue send task and the +queue send software timer respectively. */ +#define mainVALUE_SENT_FROM_TASK ( 100UL ) +#define mainVALUE_SENT_FROM_TIMER ( 200UL ) /*-----------------------------------------------------------*/ @@ -110,30 +116,53 @@ functionality. */ static void prvQueueReceiveTask( 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. */ 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 ) { +const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS; + /* Create the queue. */ - xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) ); + xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) ); if( xQueue != NULL ) { /* Start the two tasks as described in the comments at the top of this file. */ - 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. */ - 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. */ - mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */ - NULL ); /* The task handle is not required, so NULL is passed. */ + 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. */ + configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ + NULL, /* The parameter passed to the task - not used in this simple case. */ + mainQUEUE_RECEIVE_TASK_PRIORITY,/* The priority assigned to the task. */ + 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. */ vTaskStartScheduler(); @@ -151,65 +180,86 @@ void main_blinky( void ) static void prvQueueSendTask( void *pvParameters ) { TickType_t xNextWakeTime; -const unsigned long ulValueToSend = 100UL; -const TickType_t xBlockTime = pdMS_TO_TICKS( mainQUEUE_SEND_FREQUENCY_MS ); +const TickType_t xBlockTime = mainTASK_SEND_FREQUENCY_MS; +const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TASK; - /* Remove compiler warning in the case that configASSERT() is not - defined. */ + /* Prevent the compiler warning about the unused parameter. */ ( 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. */ xNextWakeTime = xTaskGetTickCount(); for( ;; ) { /* 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 - to ms. While in the Blocked state this task will not consume any CPU - time. */ + The block time is specified in ticks, pdMS_TO_TICKS() was used to + convert a time specified in milliseconds into a time specified in ticks. + While in the Blocked state this task will not consume any CPU time. */ vTaskDelayUntil( &xNextWakeTime, xBlockTime ); /* 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 - be empty at this point in the code. */ + have at least one space at this point in the code. */ 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 ) { -unsigned long ulReceivedValue; +uint32_t ulReceivedValue; - /* Remove compiler warning in the case that configASSERT() is not - defined. */ + /* Prevent the compiler warning about the unused parameter. */ ( void ) pvParameters; - /* Check the task parameter is as expected. */ - configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_RECEIVE_PARAMETER ); - for( ;; ) { /* Wait until something arrives in the queue - this task will block 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 ); - /* To get here something must have been received from the queue, but - is it the expected value? If it is, toggle the LED. */ - if( ulReceivedValue == 100UL ) + /* To get here something must have been received from the queue, but + is it an expected value? Normally calling printf() from a task is not + 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 ) + { + printf( "Message received from task\r\n" ); + } + else if( ulReceivedValue == mainVALUE_SENT_FROM_TIMER ) { - /* Normally calling printf() from a task is not a good idea. Here - there is lots of stack space and only one task is using console IO - so it is ok. */ - printf( "Message received\r\n" ); - fflush( stdout ); - ulReceivedValue = 0U; + printf( "Message received from software timer\r\n" ); } + else + { + printf( "Unexpected message\r\n" ); + } + + fflush( stdout ); } } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Demo/WIN32-MingW/main_full.c b/FreeRTOS/Demo/WIN32-MingW/main_full.c index 4f3c1676f..b67a6fd0c 100644 --- a/FreeRTOS/Demo/WIN32-MingW/main_full.c +++ b/FreeRTOS/Demo/WIN32-MingW/main_full.c @@ -102,6 +102,8 @@ #include "AbortDelay.h" #include "MessageBufferDemo.h" #include "StreamBufferDemo.h" +#include "StreamBufferInterrupt.h" +#include "MessageBufferAMP.h" /* Priorities at which the tasks are created. */ #define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) @@ -204,6 +206,8 @@ int main_full( void ) vStartMessageBufferTasks(); vStartStreamBufferTasks(); + vStartStreamBufferInterruptDemo(); + vStartMessageBufferAMPTasks(); #if( configUSE_PREEMPTION != 0 ) { @@ -342,10 +346,28 @@ const TickType_t xCycleFrequency = pdMS_TO_TICKS( 2500UL ); { 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() 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 ); } } @@ -454,6 +476,10 @@ TaskHandle_t xTimerTask; level functionality. */ 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. */ xTimerTask = xTimerGetTimerDaemonTaskHandle(); configASSERT( uxTaskPriorityGetFromISR( xTimerTask ) == configTIMER_TASK_PRIORITY ); diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c index 6706629e9..80c976bd3 100644 --- a/FreeRTOS/Source/queue.c +++ b/FreeRTOS/Source/queue.c @@ -752,13 +752,23 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) { traceQUEUE_SEND( pxQueue ); - xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); #if ( configUSE_QUEUE_SETS == 1 ) { + UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; + + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + 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 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 */ { + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + /* If there was a task waiting for data to arrive on the queue then unblock it now. */ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) -- 2.39.5