From 004e0a947eb7b4bcc3e8ac8ebea2b394cabce677 Mon Sep 17 00:00:00 2001 From: rtel Date: Wed, 4 Mar 2015 17:45:18 +0000 Subject: [PATCH] Kernel code: + Added mtCOVERAGE_TEST_DELAY() macro to facilitate getting better code coverage during testing. + Update prvNotifyQueueSetContainer() so it does not call xTaskRemoveFromEventList() if it is called from an interrupt, and the queue is locked. Demo apps: Added QueueSetPolling.c/h demo/test functions. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2331 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- FreeRTOS/Demo/Common/Minimal/QueueSet.c | 34 ++- .../Demo/Common/Minimal/QueueSetPolling.c | 217 ++++++++++++++++++ .../Demo/Common/include/QueueSetPolling.h | 79 +++++++ FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj | 1 + .../Demo/WIN32-MSVC/WIN32.vcxproj.filters | 3 + FreeRTOS/Demo/WIN32-MSVC/main_full.c | 9 +- FreeRTOS/Source/event_groups.c | 2 +- FreeRTOS/Source/include/FreeRTOS.h | 4 + FreeRTOS/Source/list.c | 7 + .../Source/portable/MSVC-MingW/portmacro.h | 4 + FreeRTOS/Source/queue.c | 17 +- FreeRTOS/Source/tasks.c | 5 +- 12 files changed, 362 insertions(+), 20 deletions(-) create mode 100644 FreeRTOS/Demo/Common/Minimal/QueueSetPolling.c create mode 100644 FreeRTOS/Demo/Common/include/QueueSetPolling.h diff --git a/FreeRTOS/Demo/Common/Minimal/QueueSet.c b/FreeRTOS/Demo/Common/Minimal/QueueSet.c index 33e3897b9..883e65371 100644 --- a/FreeRTOS/Demo/Common/Minimal/QueueSet.c +++ b/FreeRTOS/Demo/Common/Minimal/QueueSet.c @@ -395,6 +395,7 @@ static void prvQueueSetReceivingTask( void *pvParameters ) { uint32_t ulReceived; QueueHandle_t xActivatedQueue; +TickType_t xBlockTime; /* Remove compiler warnings. */ ( void ) pvParameters; @@ -405,14 +406,28 @@ QueueHandle_t xActivatedQueue; for( ;; ) { + /* For test coverage reasons, the block time is dependent on the + priority of this task - which changes during the test. When the task + is at the idle priority it polls the queue set. */ + if( uxTaskPriorityGet( NULL ) == tskIDLE_PRIORITY ) + { + xBlockTime = 0; + } + else + { + xBlockTime = portMAX_DELAY; + } + /* Wait for a message to arrive on one of the queues in the set. */ - xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY ); - configASSERT( xActivatedQueue ); + xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY ); if( xActivatedQueue == NULL ) { - /* This should not happen as an infinite delay was used. */ - xQueueSetTasksStatus = pdFAIL; + if( xBlockTime != 0 ) + { + /* This should not happen as an infinite delay was used. */ + xQueueSetTasksStatus = pdFAIL; + } } else { @@ -432,11 +447,11 @@ QueueHandle_t xActivatedQueue; prvCheckReceivedValue( ulReceived ); } taskEXIT_CRITICAL(); - } - if( xQueueSetTasksStatus == pdPASS ) - { - ulCycleCounter++; + if( xQueueSetTasksStatus == pdPASS ) + { + ulCycleCounter++; + } } } } @@ -604,8 +619,7 @@ static BaseType_t xQueueToWriteTo = 0; { ulISRTxValue++; - /* If the Tx value has wrapped then set it back to its - initial value. */ + /* If the Tx value has wrapped then set it back to its initial value. */ if( ulISRTxValue == 0UL ) { ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE; diff --git a/FreeRTOS/Demo/Common/Minimal/QueueSetPolling.c b/FreeRTOS/Demo/Common/Minimal/QueueSetPolling.c new file mode 100644 index 000000000..4126e2430 --- /dev/null +++ b/FreeRTOS/Demo/Common/Minimal/QueueSetPolling.c @@ -0,0 +1,217 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * Tests the use of queue sets. + * + * A receive task creates a number of queues and adds them to a queue set before + * blocking on the queue set receive. A transmit task and (optionally) an + * interrupt repeatedly unblocks the receive task by sending messages to the + * queues in a pseudo random order. The receive task removes the messages from + * the queues and flags an error if the received message does not match that + * expected. The task sends values in the range 0 to + * queuesetINITIAL_ISR_TX_VALUE, and the ISR sends value in the range + * queuesetINITIAL_ISR_TX_VALUE to ULONG_MAX. + */ + + +/* Standard includes. */ +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo includes. */ +#include "QueueSetPolling.h" + +/* The length of each created queue. */ +#define setpollQUEUE_LENGTH 10 + +/* Block times used in this demo. A block time or 0 means "don't block". */ +#define setpollDONT_BLOCK 0 + +/* The ISR sends to the queue every setpollISR_TX_PERIOD ticks. */ +#define queuesetISR_TX_PERIOD ( 50UL ) + +/* + * The task that reads from the queue set. + */ +static void prvQueueSetReceivingTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* The queue that is added to the set. */ +static QueueHandle_t xQueue = NULL; + +/* The handle of the queue set to which the queue is added. */ +static QueueSetHandle_t xQueueSet = NULL; + +/* Set to pdFAIL if an error is detected by any queue set task. +ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */ +static volatile BaseType_t xQueueSetPollStatus = pdPASS; + +/* Counter used to ensure the task is still running. */ +static uint32_t ulCycleCounter = 0; + +/*-----------------------------------------------------------*/ + +void vStartQueueSetPollingTask( void ) +{ + /* Create the queue that is added to the set, the set, and add the queue to + the set. */ + xQueue = xQueueCreate( setpollQUEUE_LENGTH, sizeof( uint32_t ) ); + xQueueSet = xQueueCreateSet( setpollQUEUE_LENGTH ); + xQueueAddToSet( xQueue, xQueueSet ); + + /* Create the task. */ + xTaskCreate( prvQueueSetReceivingTask, "SetPoll", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static void prvQueueSetReceivingTask( void *pvParameters ) +{ +uint32_t ulReceived, ulExpected = 0; +QueueHandle_t xActivatedQueue; + + /* Remove compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Is a message waiting? A block time is not used to ensure the queue + set is polled while it is being written to from an interrupt. */ + xActivatedQueue = xQueueSelectFromSet( xQueueSet, setpollDONT_BLOCK ); + + if( xActivatedQueue != NULL ) + { + /* Reading from the queue should pass with a zero block time as + this task will only run when something has been posted to a task + in the queue set. */ + if( xQueueReceive( xActivatedQueue, &ulReceived, setpollDONT_BLOCK ) != pdPASS ) + { + xQueueSetPollStatus = pdFAIL; + } + + if( ulReceived == ulExpected ) + { + ulExpected++; + } + else + { + xQueueSetPollStatus = pdFAIL; + } + + if( xQueueSetPollStatus == pdPASS ) + { + ulCycleCounter++; + } + } + } +} +/*-----------------------------------------------------------*/ + +void vQueueSetPollingInterruptAccess( void ) +{ +static uint32_t ulCallCount = 0, ulValueToSend = 0; + + /* It is intended that this function is called from the tick hook + function, so each call is one tick period apart. */ + ulCallCount++; + if( ulCallCount > queuesetISR_TX_PERIOD ) + { + ulCallCount = 0; + + if( xQueueSendFromISR( xQueue, ( void * ) &ulValueToSend, NULL ) == pdPASS ) + { + /* Send the next value next time. */ + ulValueToSend++; + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreQueueSetPollTasksStillRunning( void ) +{ +static uint32_t ulLastCycleCounter = 0; + + if( ulLastCycleCounter == ulCycleCounter ) + { + xQueueSetPollStatus = pdFAIL; + } + + ulLastCycleCounter = ulCycleCounter; + + return xQueueSetPollStatus; +} +/*-----------------------------------------------------------*/ + + diff --git a/FreeRTOS/Demo/Common/include/QueueSetPolling.h b/FreeRTOS/Demo/Common/include/QueueSetPolling.h new file mode 100644 index 000000000..315f6cf19 --- /dev/null +++ b/FreeRTOS/Demo/Common/include/QueueSetPolling.h @@ -0,0 +1,79 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef QUEUE_SET_POLLING_H +#define QUEUE_SET_POLLING_H + +void vStartQueueSetPollingTask( void ); +BaseType_t xAreQueueSetPollTasksStillRunning( void ); +void vQueueSetPollingInterruptAccess( void ); + +#endif /* QUEUE_SET_POLLING_H */ + + diff --git a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj index 39234651c..e0a04cabd 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj +++ b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj @@ -148,6 +148,7 @@ + diff --git a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters index d4e210a8d..b7be92210 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters +++ b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters @@ -142,6 +142,9 @@ Demo App Source\Common Demo Tasks + + Demo App Source\Common Demo Tasks + diff --git a/FreeRTOS/Demo/WIN32-MSVC/main_full.c b/FreeRTOS/Demo/WIN32-MSVC/main_full.c index 3f7e0920e..db89451a4 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/main_full.c +++ b/FreeRTOS/Demo/WIN32-MSVC/main_full.c @@ -139,6 +139,7 @@ #include "EventGroupsDemo.h" #include "IntSemTest.h" #include "TaskNotify.h" +#include "QueueSetPolling.h" /* Priorities at which the tasks are created. */ #define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) @@ -214,9 +215,10 @@ int main_full( void ) vStartDynamicPriorityTasks(); vStartQueueSetTasks(); vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY ); - xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); vStartEventGroupTasks(); vStartInterruptSemaphoreTasks(); + vStartQueueSetPollingTask(); + xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); #if( configUSE_PREEMPTION != 0 ) { @@ -336,6 +338,10 @@ const TickType_t xCycleFrequency = 2500 / portTICK_PERIOD_MS; { pcStatusMessage = "Error: Queue overwrite"; } + else if( xAreQueueSetPollTasksStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Queue set polling"; + } /* This is the only task that uses stdout so its ok to call printf() directly. */ @@ -417,6 +423,7 @@ TaskHandle_t xTimerTask; /* Write to a queue that is in use as part of the queue set demo to demonstrate using queue sets from an ISR. */ vQueueSetAccessQueueSetFromISR(); + vQueueSetPollingInterruptAccess(); /* Exercise event groups from interrupts. */ vPeriodicEventGroupsProcessing(); diff --git a/FreeRTOS/Source/event_groups.c b/FreeRTOS/Source/event_groups.c index ebac26884..85dd487aa 100644 --- a/FreeRTOS/Source/event_groups.c +++ b/FreeRTOS/Source/event_groups.c @@ -139,7 +139,7 @@ EventGroupHandle_t xEventGroupCreate( void ) { EventGroup_t *pxEventBits; - pxEventBits = pvPortMalloc( sizeof( EventGroup_t ) ); + pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); if( pxEventBits != NULL ) { pxEventBits->uxEventBits = 0; diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index a149c96d6..55be506ac 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -719,6 +719,10 @@ extern "C" { #define mtCOVERAGE_TEST_MARKER() #endif +#ifndef mtCOVERAGE_TEST_DELAY + #define mtCOVERAGE_TEST_DELAY() +#endif + #ifndef portASSERT_IF_IN_ISR #define portASSERT_IF_IN_ISR() #endif diff --git a/FreeRTOS/Source/list.c b/FreeRTOS/Source/list.c index cd273ad82..ecc2c2b88 100644 --- a/FreeRTOS/Source/list.c +++ b/FreeRTOS/Source/list.c @@ -128,6 +128,10 @@ ListItem_t * const pxIndex = pxList->pxIndex; listGET_OWNER_OF_NEXT_ENTRY(). */ pxNewListItem->pxNext = pxIndex; pxNewListItem->pxPrevious = pxIndex->pxPrevious; + + /* Only used during decision coverage testing. */ + mtCOVERAGE_TEST_DELAY(); + pxIndex->pxPrevious->pxNext = pxNewListItem; pxIndex->pxPrevious = pxNewListItem; @@ -214,6 +218,9 @@ List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; + /* Only used during decision coverage testing. */ + mtCOVERAGE_TEST_DELAY(); + /* Make sure the index is left pointing to a valid item. */ if( pxList->pxIndex == pxItemToRemove ) { diff --git a/FreeRTOS/Source/portable/MSVC-MingW/portmacro.h b/FreeRTOS/Source/portable/MSVC-MingW/portmacro.h index 7f6548193..c0a287558 100644 --- a/FreeRTOS/Source/portable/MSVC-MingW/portmacro.h +++ b/FreeRTOS/Source/portable/MSVC-MingW/portmacro.h @@ -115,6 +115,10 @@ typedef unsigned long UBaseType_t; #define portYIELD() vPortGenerateSimulatedInterrupt( portINTERRUPT_YIELD ) +/* Simulated interrupts return pdFALSE if no context switch should be performed, +or a non-zero number if a context switch should be performed. */ +#define portYIELD_FROM_ISR( x ) return x + void vPortCloseRunningThread( void *pvTaskToDelete, volatile BaseType_t *pxPendYield ); void vPortDeleteThread( void *pvThreadToDelete ); #define portCLEAN_UP_TCB( pxTCB ) vPortDeleteThread( pxTCB ) diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c index 27d3edd6a..b26f6dac7 100644 --- a/FreeRTOS/Source/queue.c +++ b/FreeRTOS/Source/queue.c @@ -2565,12 +2565,19 @@ BaseType_t xReturn; /* The data copied is the handle of the queue that contains data. */ xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); - if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + if( pxQueueSetContainer->xTxLock == queueUNLOCKED ) { - if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) { - /* The task waiting has a higher priority */ - xReturn = pdTRUE; + if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -2579,7 +2586,7 @@ BaseType_t xReturn; } else { - mtCOVERAGE_TEST_MARKER(); + ( pxQueueSetContainer->xTxLock )++; } } else diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index c7b29382d..822338df1 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -3321,9 +3321,8 @@ TCB_t *pxTCB; if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) { - /* The new current delayed list is empty. Set - xNextTaskUnblockTime to the maximum possible value so it is - extremely unlikely that the + /* The new current delayed list is empty. Set xNextTaskUnblockTime to + the maximum possible value so it is extremely unlikely that the if( xTickCount >= xNextTaskUnblockTime ) test will pass until there is an item in the delayed list. */ xNextTaskUnblockTime = portMAX_DELAY; -- 2.39.5