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.
This commit is contained in:
Richard Barry 2015-03-04 17:45:18 +00:00
parent 7d169cef52
commit 96e72413f7
12 changed files with 362 additions and 20 deletions

View File

@ -395,6 +395,7 @@ static void prvQueueSetReceivingTask( void *pvParameters )
{ {
uint32_t ulReceived; uint32_t ulReceived;
QueueHandle_t xActivatedQueue; QueueHandle_t xActivatedQueue;
TickType_t xBlockTime;
/* Remove compiler warnings. */ /* Remove compiler warnings. */
( void ) pvParameters; ( void ) pvParameters;
@ -405,14 +406,28 @@ QueueHandle_t xActivatedQueue;
for( ;; ) 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. */ /* Wait for a message to arrive on one of the queues in the set. */
xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY ); xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY );
configASSERT( xActivatedQueue );
if( xActivatedQueue == NULL ) if( xActivatedQueue == NULL )
{ {
/* This should not happen as an infinite delay was used. */ if( xBlockTime != 0 )
xQueueSetTasksStatus = pdFAIL; {
/* This should not happen as an infinite delay was used. */
xQueueSetTasksStatus = pdFAIL;
}
} }
else else
{ {
@ -432,11 +447,11 @@ QueueHandle_t xActivatedQueue;
prvCheckReceivedValue( ulReceived ); prvCheckReceivedValue( ulReceived );
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
}
if( xQueueSetTasksStatus == pdPASS ) if( xQueueSetTasksStatus == pdPASS )
{ {
ulCycleCounter++; ulCycleCounter++;
}
} }
} }
} }
@ -604,8 +619,7 @@ static BaseType_t xQueueToWriteTo = 0;
{ {
ulISRTxValue++; ulISRTxValue++;
/* If the Tx value has wrapped then set it back to its /* If the Tx value has wrapped then set it back to its initial value. */
initial value. */
if( ulISRTxValue == 0UL ) if( ulISRTxValue == 0UL )
{ {
ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE; ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;

View File

@ -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 <stdlib.h>
#include <limits.h>
/* 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;
}
/*-----------------------------------------------------------*/

View File

@ -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 */

View File

@ -148,6 +148,7 @@
<ClCompile Include="..\Common\Minimal\QPeek.c" /> <ClCompile Include="..\Common\Minimal\QPeek.c" />
<ClCompile Include="..\Common\Minimal\QueueOverwrite.c" /> <ClCompile Include="..\Common\Minimal\QueueOverwrite.c" />
<ClCompile Include="..\Common\Minimal\QueueSet.c" /> <ClCompile Include="..\Common\Minimal\QueueSet.c" />
<ClCompile Include="..\Common\Minimal\QueueSetPolling.c" />
<ClCompile Include="..\Common\Minimal\semtest.c" /> <ClCompile Include="..\Common\Minimal\semtest.c" />
<ClCompile Include="..\Common\Minimal\TaskNotify.c" /> <ClCompile Include="..\Common\Minimal\TaskNotify.c" />
<ClCompile Include="..\Common\Minimal\timerdemo.c" /> <ClCompile Include="..\Common\Minimal\timerdemo.c" />

View File

@ -142,6 +142,9 @@
<ClCompile Include="..\Common\Minimal\TaskNotify.c"> <ClCompile Include="..\Common\Minimal\TaskNotify.c">
<Filter>Demo App Source\Common Demo Tasks</Filter> <Filter>Demo App Source\Common Demo Tasks</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Common\Minimal\QueueSetPolling.c">
<Filter>Demo App Source\Common Demo Tasks</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="FreeRTOSConfig.h"> <ClInclude Include="FreeRTOSConfig.h">

View File

@ -139,6 +139,7 @@
#include "EventGroupsDemo.h" #include "EventGroupsDemo.h"
#include "IntSemTest.h" #include "IntSemTest.h"
#include "TaskNotify.h" #include "TaskNotify.h"
#include "QueueSetPolling.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 )
@ -214,9 +215,10 @@ int main_full( void )
vStartDynamicPriorityTasks(); vStartDynamicPriorityTasks();
vStartQueueSetTasks(); vStartQueueSetTasks();
vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY ); vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );
xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
vStartEventGroupTasks(); vStartEventGroupTasks();
vStartInterruptSemaphoreTasks(); vStartInterruptSemaphoreTasks();
vStartQueueSetPollingTask();
xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
#if( configUSE_PREEMPTION != 0 ) #if( configUSE_PREEMPTION != 0 )
{ {
@ -336,6 +338,10 @@ const TickType_t xCycleFrequency = 2500 / portTICK_PERIOD_MS;
{ {
pcStatusMessage = "Error: Queue overwrite"; 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() /* This is the only task that uses stdout so its ok to call printf()
directly. */ directly. */
@ -417,6 +423,7 @@ TaskHandle_t xTimerTask;
/* Write to a queue that is in use as part of the queue set demo to /* Write to a queue that is in use as part of the queue set demo to
demonstrate using queue sets from an ISR. */ demonstrate using queue sets from an ISR. */
vQueueSetAccessQueueSetFromISR(); vQueueSetAccessQueueSetFromISR();
vQueueSetPollingInterruptAccess();
/* Exercise event groups from interrupts. */ /* Exercise event groups from interrupts. */
vPeriodicEventGroupsProcessing(); vPeriodicEventGroupsProcessing();

View File

@ -139,7 +139,7 @@ EventGroupHandle_t xEventGroupCreate( void )
{ {
EventGroup_t *pxEventBits; EventGroup_t *pxEventBits;
pxEventBits = pvPortMalloc( sizeof( EventGroup_t ) ); pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
if( pxEventBits != NULL ) if( pxEventBits != NULL )
{ {
pxEventBits->uxEventBits = 0; pxEventBits->uxEventBits = 0;

View File

@ -719,6 +719,10 @@ extern "C" {
#define mtCOVERAGE_TEST_MARKER() #define mtCOVERAGE_TEST_MARKER()
#endif #endif
#ifndef mtCOVERAGE_TEST_DELAY
#define mtCOVERAGE_TEST_DELAY()
#endif
#ifndef portASSERT_IF_IN_ISR #ifndef portASSERT_IF_IN_ISR
#define portASSERT_IF_IN_ISR() #define portASSERT_IF_IN_ISR()
#endif #endif

View File

@ -128,6 +128,10 @@ ListItem_t * const pxIndex = pxList->pxIndex;
listGET_OWNER_OF_NEXT_ENTRY(). */ listGET_OWNER_OF_NEXT_ENTRY(). */
pxNewListItem->pxNext = pxIndex; pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious; pxNewListItem->pxPrevious = pxIndex->pxPrevious;
/* Only used during decision coverage testing. */
mtCOVERAGE_TEST_DELAY();
pxIndex->pxPrevious->pxNext = pxNewListItem; pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem; pxIndex->pxPrevious = pxNewListItem;
@ -214,6 +218,9 @@ List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; 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. */ /* Make sure the index is left pointing to a valid item. */
if( pxList->pxIndex == pxItemToRemove ) if( pxList->pxIndex == pxItemToRemove )
{ {

View File

@ -115,6 +115,10 @@ typedef unsigned long UBaseType_t;
#define portYIELD() vPortGenerateSimulatedInterrupt( portINTERRUPT_YIELD ) #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 vPortCloseRunningThread( void *pvTaskToDelete, volatile BaseType_t *pxPendYield );
void vPortDeleteThread( void *pvThreadToDelete ); void vPortDeleteThread( void *pvThreadToDelete );
#define portCLEAN_UP_TCB( pxTCB ) vPortDeleteThread( pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortDeleteThread( pxTCB )

View File

@ -2565,12 +2565,19 @@ BaseType_t xReturn;
/* The data copied is the handle of the queue that contains data. */ /* The data copied is the handle of the queue that contains data. */
xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); 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 */ if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
xReturn = pdTRUE; {
/* The task waiting has a higher priority. */
xReturn = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
} }
else else
{ {
@ -2579,7 +2586,7 @@ BaseType_t xReturn;
} }
else else
{ {
mtCOVERAGE_TEST_MARKER(); ( pxQueueSetContainer->xTxLock )++;
} }
} }
else else

View File

@ -3321,9 +3321,8 @@ TCB_t *pxTCB;
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
{ {
/* The new current delayed list is empty. Set /* The new current delayed list is empty. Set xNextTaskUnblockTime to
xNextTaskUnblockTime to the maximum possible value so it is the maximum possible value so it is extremely unlikely that the
extremely unlikely that the
if( xTickCount >= xNextTaskUnblockTime ) test will pass until if( xTickCount >= xNextTaskUnblockTime ) test will pass until
there is an item in the delayed list. */ there is an item in the delayed list. */
xNextTaskUnblockTime = portMAX_DELAY; xNextTaskUnblockTime = portMAX_DELAY;