Continue working on queue set implementation and testing.

This commit is contained in:
Richard Barry
2013-02-08 15:50:14 +00:00
parent 4e5090e061
commit 232a5b3433
6 changed files with 329 additions and 103 deletions

File diff suppressed because it is too large Load Diff

View File

@ -69,9 +69,10 @@
#ifndef QUEUE_WAIT_MULTIPLE_H
#define QUEUE_WAIT_MULTIPLE_H
void vStartQueueSetTasks( unsigned portBASE_TYPE uxPriority );
void vStartQueueSetTasks( void );
portBASE_TYPE xAreQueueSetTasksStillRunning( void );
void vQueueSetWriteToQueueFromISR( void );
#endif
#endif /* QUEUE_WAIT_MULTIPLE_H */

Binary file not shown.

View File

@ -130,7 +130,6 @@
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
#define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY )
#define mainQUEUE_SET_TASK_PRIORITY ( tskIDLE_PRIORITY )
#define mainTIMER_TEST_PERIOD ( 50 )
@ -167,7 +166,7 @@ int main( void )
vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
vStartCountingSemaphoreTasks();
vStartDynamicPriorityTasks();
vStartQueueSetTasks( mainQUEUE_SET_TASK_PRIORITY );
vStartQueueSetTasks();
/* The suicide tasks must be created last as they need to know how many
tasks were running prior to their creation. This then allows them to
@ -406,6 +405,10 @@ void vApplicationTickHook( void )
/* Call the periodic timer test, which tests the timer API functions that
can be called from an ISR. */
vTimerPeriodicISRTests();
/* Write to a queue that is in use as part of the queue set demo to
demonstrate using queue sets from an ISR. */
vQueueSetWriteToQueueFromISR();
}
/*-----------------------------------------------------------*/

View File

@ -91,10 +91,17 @@ typedef void * xQueueHandle;
/**
* Type by which queue sets are referenced. For example, a call to
* xQueueSetCreate() returns an xQueueSet variable that can then be used as a
* parameter to xQueueReadMultiple(), xQueueAddToQueueSet(), etc.
* parameter to xQueueBlockMultiple(), xQueueAddToQueueSet(), etc.
*/
typedef void * xQueueSetHandle;
/**
* Queue sets can contain both queues and semaphores, so the
* xQueueSetMemberHandle is defined as a type to be used where a parameter or
* return value can be either an xQueueHandle or an xSemaphoreHandle.
*/
typedef void * xQueueSetMemberHandle;
/* For internal use only. */
#define queueSEND_TO_BACK ( 0 )
#define queueSEND_TO_FRONT ( 1 )
@ -1305,7 +1312,7 @@ xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned
* A queue set must be explicitly created using a call to xQueueSetCreate()
* before it can be used. Once created, standard FreeRTOS queues and semaphores
* can be added to the set using calls to xQueueAddToQueueSet().
* xQueueReadMultiple() is then used to determine which, if any, of the queues
* xQueueBlockMultiple() is then used to determine which, if any, of the queues
* or semaphores contained in the set is in a state where a queue read or
* semaphore take operation would be successful.
*
@ -1349,10 +1356,8 @@ xQueueSetHandle xQueueSetCreate( unsigned portBASE_TYPE uxEventQueueLength );
* See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
* function.
*
* @param xQueue The handle of the queue or semaphore being added to the
* queue set. Variables of type xSemaphoreHandle can be safely added to a
* queue set but may require casting to an xQueueHandle type to avoid compiler
* warnings.
* @param xQueueOrSemaphore The handle of the queue or semaphore being added to
* the queue set (cast to an xQueueSetMemberHandle type).
*
* @param xQueueSet The handle of the queue set to which the queue or semaphore
* is being added.
@ -1362,7 +1367,7 @@ xQueueSetHandle xQueueSetCreate( unsigned portBASE_TYPE uxEventQueueLength );
* queue set because it is already a member of a different queue set then pdFAIL
* is returned.
*/
portBASE_TYPE xQueueAddToQueueSet( xQueueHandle xQueue, xQueueSetHandle xQueueSet );
portBASE_TYPE xQueueAddToQueueSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet );
/*
* Removes a queue or semaphore from a queue set.
@ -1370,9 +1375,8 @@ portBASE_TYPE xQueueAddToQueueSet( xQueueHandle xQueue, xQueueSetHandle xQueueSe
* See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
* function.
*
* @param xQueue The handle of the queue or semaphore being removed from the
* queue set. Variables of type xSemaphoreHandle can be safely used but may
* require casting to an xQueueHandle type to avoid compiler warnings.
* @param xQueueOrSemaphore The handle of the queue or semaphore being removed
* from the queue set (cast to an xQueueSetMemberHandle type).
*
* @param xQueueSet The handle of the queue set in which the queue or semaphore
* is included.
@ -1381,10 +1385,10 @@ portBASE_TYPE xQueueAddToQueueSet( xQueueHandle xQueue, xQueueSetHandle xQueueSe
* then pdPASS is returned. If the queue was not in the queue set then pdFAIL
* is returned.
*/
portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetHandle xQueueSet, xQueueHandle xQueue );
portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet );
/*
* xQueueReadMultiple() allows a task to block (pend) on a read operation on
* xQueueBlockMultiple() allows a task to block (pend) on a read operation on
* all the queues and semaphores in a queue set simultaneously.
*
* See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
@ -1405,12 +1409,13 @@ portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetHandle xQueueSet, xQueueHandle
* of the queue set to be ready for a successful queue read or semaphore take
* operation.
*
* @return xQueueReadMultiple() will return the handle of a queue contained
* in the queue set that contains data, or the handle of a semaphore contained
* @return xQueueBlockMultiple() will return the handle of a queue (cast to
* a xQueueSetMemberHandle type) contained in the queue set that contains data,
* or the handle of a semaphore (cast to a xQueueSetMemberHandle type) contained
* in the queue set that is available, or NULL if no such queue or semaphore
* exists before before the specified block time expires.
*/
xQueueHandle xQueueReadMultiple( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks );
xQueueSetMemberHandle xQueueBlockMultiple( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks );
/* Not public API functions. */
void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait );

View File

@ -1,7 +1,7 @@
/*
FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd.
FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
@ -42,7 +42,7 @@
FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
@ -52,17 +52,17 @@
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest versions, license
and contact details.
http://www.FreeRTOS.org - Documentation, training, latest versions, license
and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under
provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com.
*/
@ -148,15 +148,22 @@ typedef struct QueueDefinition
/*-----------------------------------------------------------*/
/*
* Inside this file xQueueHandle is a pointer to a xQUEUE structure.
* To keep the definition private the API header file defines it as a
* pointer to void.
* Inside this file xQueueHandle and xQueueSetHandle are both pointers to xQUEUE
* structures. To keep the definition private the API header file defines both
* as pointers to void.
*/
typedef xQUEUE * xQueueHandle;
typedef xQUEUE * xQueueSetHandle;
/**
* Queue sets can contain both queues and semaphores, so the
* xQueueSetMemberHandle is defined as a type to be used where a parameter or
* return value can be either an xQueueHandle or an xSemaphoreHandle.
*/
typedef xQUEUE * xQueueSetMemberHandle;
/*
* In order to implement strict data hiding, the queue.h header file defines
* In order to implement strict data hiding, the queue.h header file defines
* xQueueHandle and xQueueSetHandle as pointers to void. In this file
* xQueueHandle and xQueueSetHandle are defined as pointers to xQUEUE objects.
* Therefore the queue.h header file cannot be included in this source file,
@ -185,9 +192,9 @@ unsigned char ucQueueGetQueueType( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
portBASE_TYPE xQueueGenericReset( xQueueHandle pxQueue, portBASE_TYPE xNewQueue ) PRIVILEGED_FUNCTION;
xTaskHandle xQueueGetMutexHolder( xQueueHandle xSemaphore ) PRIVILEGED_FUNCTION;
xQueueSetHandle xQueueSetCreate( unsigned portBASE_TYPE uxEventQueueLength ) PRIVILEGED_FUNCTION;
xQueueHandle xQueueReadMultiple( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) PRIVILEGED_FUNCTION;
portBASE_TYPE xQueueAddToQueueSet( xQueueHandle xQueue, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetHandle xQueueSet, xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
xQueueSetMemberHandle xQueueBlockMultiple( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) PRIVILEGED_FUNCTION;
portBASE_TYPE xQueueAddToQueueSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
/*
* Co-routine queue functions differ from task queue functions. Co-routines are
@ -266,7 +273,7 @@ static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
* Checks to see if a queue is a member of a queue set, and if so, notifies
* the queue set that the queue contains data.
*/
static portBASE_TYPE prvCheckForMembershipOfQueueSet( xQUEUE *pxQueue, portBASE_TYPE xCopyPosition );
static portBASE_TYPE prvNotifyQueueSetContainer( xQUEUE *pxQueue, portBASE_TYPE xCopyPosition );
#endif
/*-----------------------------------------------------------*/
@ -361,7 +368,7 @@ xQueueHandle xReturn = NULL;
pxNewQueue->uxLength = uxQueueLength;
pxNewQueue->uxItemSize = uxItemSize;
xQueueGenericReset( pxNewQueue, pdTRUE );
#if ( configUSE_TRACE_FACILITY == 1 )
{
pxNewQueue->ucQueueType = ucQueueType;
@ -640,12 +647,15 @@ xTimeOutType xTimeOut;
{
#if ( configUSE_QUEUE_SETS == 1 )
{
if( prvCheckForMembershipOfQueueSet( pxQueue, xCopyPosition ) == pdTRUE )
if( pxQueue->pxQueueSetContainer != NULL )
{
/* The queue is a member of a queue set, and posting to
the queue set caused a higher priority task to unblock.
A context switch is required. */
portYIELD_WITHIN_API();
if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
{
/* The queue is a member of a queue set, and posting to
the queue set caused a higher priority task to unblock.
A context switch is required. */
portYIELD_WITHIN_API();
}
}
}
#endif /* configUSE_QUEUE_SETS */
@ -985,7 +995,16 @@ unsigned portBASE_TYPE uxSavedInterruptStatus;
{
if( pxQueue->pxQueueSetContainer != NULL )
{
xQueueGenericSendFromISR( pxQueue->pxQueueSetContainer, &pxQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK );
if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
{
/* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to
unblock. A context switch is required. */
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
}
}
#endif /* configUSE_QUEUE_SETS */
@ -1068,7 +1087,7 @@ signed char *pcOriginalReadPosition;
{
traceQUEUE_PEEK( pxQueue );
/* The data is not being removed, so reset the read
/* The data is not being removed, so reset the read
pointer. */
pxQueue->pcReadFrom = pcOriginalReadPosition;
@ -1084,17 +1103,6 @@ signed char *pcOriginalReadPosition;
portYIELD_WITHIN_API();
}
}
else
{
#if ( configUSE_QUEUE_SETS == 1 )
{
if( pxQueue->pxQueueSetContainer != NULL )
{
xQueueGenericSend( pxQueue->pxQueueSetContainer, &pxQueue, 0, queueSEND_TO_BACK );
}
}
#endif /* configUSE_QUEUE_SETS */
}
}
taskEXIT_CRITICAL();
@ -1379,10 +1387,11 @@ static void prvUnlockQueue( xQueueHandle pxQueue )
{
if( pxQueue->pxQueueSetContainer != NULL )
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
xQueueGenericSendFromISR( pxQueue->pxQueueSetContainer, &pxQueue, &xHigherPriorityTaskWoken, queueSEND_TO_BACK );
if( xHigherPriorityTaskWoken != pdFALSE )
if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
{
/* The queue is a member of a queue set, and posting to
the queue set caused a higher priority task to unblock.
A context switch is required. */
vTaskMissedYield();
}
}
@ -1784,11 +1793,11 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 )
portBASE_TYPE xQueueAddToQueueSet( xQueueHandle xQueue, xQueueSetHandle xQueueSet )
portBASE_TYPE xQueueAddToQueueSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
{
portBASE_TYPE xReturn;
if( xQueue->pxQueueSetContainer != NULL )
if( xQueueOrSemaphore->pxQueueSetContainer != NULL )
{
xReturn = pdFAIL;
}
@ -1796,7 +1805,7 @@ signed portBASE_TYPE xReturn;
{
taskENTER_CRITICAL();
{
xQueue->pxQueueSetContainer = xQueueSet;
xQueueOrSemaphore->pxQueueSetContainer = xQueueSet;
}
taskEXIT_CRITICAL();
xReturn = pdPASS;
@ -1810,11 +1819,11 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 )
portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetHandle xQueueSet, xQueueHandle xQueue )
portBASE_TYPE xQueueRemoveFromQueueSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
{
portBASE_TYPE xReturn;
if( xQueue->pxQueueSetContainer != xQueueSet )
if( xQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
{
xReturn = pdFAIL;
}
@ -1822,7 +1831,7 @@ signed portBASE_TYPE xReturn;
{
taskENTER_CRITICAL();
{
xQueue->pxQueueSetContainer = NULL;
xQueueOrSemaphore->pxQueueSetContainer = NULL;
}
taskEXIT_CRITICAL();
xReturn = pdPASS;
@ -1836,10 +1845,10 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 )
xQueueHandle xQueueReadMultiple( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )
xQueueSetMemberHandle xQueueBlockMultiple( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )
{
xQueueHandle xReturn = NULL;
xQueueSetMemberHandle xReturn = NULL;
xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE );
return xReturn;
}
@ -1849,23 +1858,23 @@ signed portBASE_TYPE xReturn;
#if ( configUSE_QUEUE_SETS == 1 )
static portBASE_TYPE prvCheckForMembershipOfQueueSet( xQUEUE *pxQueue, portBASE_TYPE xCopyPosition )
static portBASE_TYPE prvNotifyQueueSetContainer( xQUEUE *pxQueue, portBASE_TYPE xCopyPosition )
{
xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
portBASE_TYPE xReturn = pdFALSE;
if( pxQueueSetContainer != NULL )
configASSERT( pxQueueSetContainer );
configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
{
if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
{
prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The task waiting has a higher priority */
xReturn = pdTRUE;
}
/* The task waiting has a higher priority */
xReturn = pdTRUE;
}
}
}