#define traceTASK_SWITCHED_OUT()\r
#endif\r
\r
+#ifndef traceTASK_PRIORITY_INHERIT\r
+ /* Called when a task attempts to take a mutex that is already held by a\r
+ lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task\r
+ that holds the mutex. uxInheritedPriority is the priority the mutex holder\r
+ will inherit (the priority of the task that is attempting to obtain the\r
+ muted. */\r
+ #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority )\r
+#endif\r
+\r
+#ifndef traceTASK_PRIORITY_DISINHERIT\r
+ /* Called when a task releases a mutex, the holding of which had resulted in\r
+ the task inheriting the priority of a higher priority task. \r
+ pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the\r
+ mutex. uxOriginalPriority is the task's configured (base) priority. */\r
+ #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority )\r
+#endif\r
+\r
#ifndef traceBLOCKING_ON_QUEUE_RECEIVE\r
/* Task is about to block because it cannot read from a\r
queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore\r
#endif\r
\r
#ifndef traceQUEUE_CREATE_FAILED\r
- #define traceQUEUE_CREATE_FAILED()\r
+ #define traceQUEUE_CREATE_FAILED( ucQueueType )\r
#endif\r
\r
#ifndef traceCREATE_MUTEX\r
#define queueSEND_TO_BACK ( 0 )\r
#define queueSEND_TO_FRONT ( 1 )\r
\r
+/* For internal use only. These definitions *must* match those in queue.c. */\r
+#define queueQUEUE_TYPE_BASE ( 0U )\r
+#define queueQUEUE_TYPE_MUTEX ( 1U )\r
+#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( 2U )\r
+#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( 3U )\r
+#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( 4U )\r
\r
/**\r
* queue. h\r
* \defgroup xQueueCreate xQueueCreate\r
* \ingroup QueueManagement\r
*/\r
-xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );\r
+#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE )\r
\r
/**\r
* queue. h\r
* For internal use only. Use xSemaphoreCreateMutex() or\r
* xSemaphoreCreateCounting() instead of calling these functions directly.\r
*/\r
-xQueueHandle xQueueCreateMutex( void );\r
+xQueueHandle xQueueCreateMutex( unsigned char ucQueueType );\r
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );\r
\r
/*\r
void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcName );\r
#endif\r
\r
-/* Not a public API function, hence the 'Restricted' in the name. */\r
+/*\r
+ * Generic version of the queue creation function, which is in turn called by \r
+ * any queue, semaphore or mutex creation function or macro.\r
+ */\r
+xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType );\r
+\r
+/* \r
+ * Not a public API function, hence the 'Restricted' in the name. \r
+ */\r
void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait );\r
\r
\r
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary\r
* \ingroup Semaphores\r
*/\r
-#define vSemaphoreCreateBinary( xSemaphore ) { \\r
- ( xSemaphore ) = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \\r
- if( ( xSemaphore ) != NULL ) \\r
- { \\r
- xSemaphoreGive( ( xSemaphore ) ); \\r
- } \\r
- }\r
+#define vSemaphoreCreateBinary( xSemaphore ) \\r
+ { \\r
+ ( xSemaphore ) = xQueueGenericCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \\r
+ if( ( xSemaphore ) != NULL ) \\r
+ { \\r
+ xSemaphoreGive( ( xSemaphore ) ); \\r
+ } \\r
+ }\r
\r
/**\r
* semphr. h\r
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex\r
* \ingroup Semaphores\r
*/\r
-#define xSemaphoreCreateMutex() xQueueCreateMutex()\r
+#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )\r
\r
\r
/**\r
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex\r
* \ingroup Semaphores\r
*/\r
-#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex()\r
+#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )\r
\r
/**\r
* semphr. h\r
*/\r
signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) PRIVILEGED_FUNCTION;\r
\r
+/*\r
+ * Get the uxTCBNumber assigned to the task referenced by the xTask parameter.\r
+ */\r
+unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask );\r
+\r
+/* \r
+ * Set the uxTCBNumber of the task referenced by the xTask parameter to\r
+ * ucHandle.\r
+ */\r
+void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle );\r
+\r
+\r
#ifdef __cplusplus\r
}\r
#endif\r
#define queueDONT_BLOCK ( ( portTickType ) 0U )\r
#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U )\r
\r
+/* These definitions *must* match those in queue.h. */\r
+#define queueQUEUE_TYPE_BASE ( 0U )\r
+#define queueQUEUE_TYPE_MUTEX ( 1U )\r
+#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( 2U )\r
+#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( 3U )\r
+#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( 4U )\r
+\r
/*\r
* Definition of the queue used by the scheduler.\r
* Items are queued by copy, not reference.\r
\r
signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */\r
signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */\r
+ \r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ unsigned char ucQueueNumber;\r
+ unsigned char ucQueueType;\r
+ #endif\r
\r
} xQUEUE;\r
/*-----------------------------------------------------------*/\r
* include the API header file (as it defines xQueueHandle differently). These\r
* functions are documented in the API header file.\r
*/\r
-xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;\r
+xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) PRIVILEGED_FUNCTION;\r
signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;\r
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;\r
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;\r
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;\r
-xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;\r
+xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) PRIVILEGED_FUNCTION;\r
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;\r
portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;\r
portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;\r
signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
+unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
+unsigned char ucQueueGetQueueType( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;\r
\r
/*\r
* Co-routine queue functions differ from task queue functions. Co-routines are\r
* PUBLIC QUEUE MANAGEMENT API documented in queue.h\r
*----------------------------------------------------------*/\r
\r
-xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )\r
+xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )\r
{\r
xQUEUE *pxNewQueue;\r
size_t xQueueSizeInBytes;\r
xQueueHandle xReturn = NULL;\r
\r
+ /* Remove compiler warnings about unused parameters should \r
+ configUSE_TRACE_FACILITY not be set to 1. */\r
+ ( void ) ucQueueType;\r
+\r
/* Allocate the new queue structure. */\r
if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )\r
{\r
pxNewQueue->uxItemSize = uxItemSize;\r
pxNewQueue->xRxLock = queueUNLOCKED;\r
pxNewQueue->xTxLock = queueUNLOCKED;\r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ {\r
+ pxNewQueue->ucQueueType = ucQueueType;\r
+ }\r
+ #endif /* configUSE_TRACE_FACILITY */\r
\r
/* Likewise ensure the event queues start with the correct state. */\r
vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
}\r
else\r
{\r
- traceQUEUE_CREATE_FAILED();\r
+ traceQUEUE_CREATE_FAILED( ucQueueType );\r
vPortFree( pxNewQueue );\r
}\r
}\r
\r
#if ( configUSE_MUTEXES == 1 )\r
\r
- xQueueHandle xQueueCreateMutex( void )\r
+ xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )\r
{\r
xQUEUE *pxNewQueue;\r
\r
+ /* Prevent compiler warnings about unused parameters if\r
+ configUSE_TRACE_FACILITY does not equal 1. */\r
+ ( void ) ucQueueType;\r
+ \r
/* Allocate the new queue structure. */\r
pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );\r
if( pxNewQueue != NULL )\r
pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;\r
pxNewQueue->xRxLock = queueUNLOCKED;\r
pxNewQueue->xTxLock = queueUNLOCKED;\r
+ \r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ {\r
+ pxNewQueue->ucQueueType = ucQueueType;\r
+ }\r
+ #endif\r
\r
/* Ensure the event queues start with the correct state. */\r
vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
\r
+ traceCREATE_MUTEX( pxNewQueue );\r
+\r
/* Start with the semaphore in the expected state. */\r
xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );\r
-\r
- traceCREATE_MUTEX( pxNewQueue );\r
}\r
else\r
{\r
{\r
xQueueHandle pxHandle;\r
\r
- pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );\r
+ pxHandle = xQueueGenericCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );\r
\r
if( pxHandle != NULL )\r
{\r
}\r
/*-----------------------------------------------------------*/\r
\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+ unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue )\r
+ {\r
+ return pxQueue->ucQueueNumber;\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+\r
+ unsigned char ucQueueGetQueueType( xQueueHandle pxQueue )\r
+ {\r
+ return pxQueue->ucQueueType;\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )\r
{\r
if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )\r
#define tskDELETED_CHAR ( ( signed char ) 'D' )\r
#define tskSUSPENDED_CHAR ( ( signed char ) 'S' )\r
\r
-/*\r
- * Macros and private variables used by the trace facility.\r
- */\r
-#if ( configUSE_TRACE_FACILITY == 1 )\r
-\r
- #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) )\r
- PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer;\r
- PRIVILEGED_DATA static signed char *pcTraceBufferStart;\r
- PRIVILEGED_DATA static signed char *pcTraceBufferEnd;\r
- PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE;\r
- static unsigned portBASE_TYPE uxPreviousTask = 255U;\r
- PRIVILEGED_DATA static char pcStatusString[ 50 ];\r
-\r
-#endif\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * Macro that writes a trace of scheduler activity to a buffer. This trace\r
- * shows which task is running when and is very useful as a debugging tool.\r
- * As this macro is called each context switch it is a good idea to undefine\r
- * it if not using the facility.\r
- */\r
-#if ( configUSE_TRACE_FACILITY == 1 )\r
-\r
- #define vWriteTraceToBuffer() \\r
- { \\r
- if( xTracing != pdFALSE ) \\r
- { \\r
- if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \\r
- { \\r
- if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \\r
- { \\r
- uxPreviousTask = pxCurrentTCB->uxTCBNumber; \\r
- *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \\r
- pcTraceBuffer += sizeof( unsigned long ); \\r
- *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \\r
- pcTraceBuffer += sizeof( unsigned long ); \\r
- } \\r
- else \\r
- { \\r
- xTracing = pdFALSE; \\r
- } \\r
- } \\r
- } \\r
- }\r
-\r
-#else\r
-\r
- #define vWriteTraceToBuffer()\r
-\r
-#endif\r
/*-----------------------------------------------------------*/\r
\r
/*\r
priority of the calling function. */\r
pxTCB = prvGetTCBFromHandle( pxTask );\r
\r
- traceTASK_PRIORITY_SET( pxTask, uxNewPriority );\r
+ traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );\r
\r
#if ( configUSE_MUTEXES == 1 )\r
{\r
#endif\r
/*----------------------------------------------------------*/\r
\r
-#if ( configUSE_TRACE_FACILITY == 1 )\r
-\r
- void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize )\r
- {\r
- configASSERT( pcBuffer );\r
- configASSERT( ulBufferSize );\r
-\r
- taskENTER_CRITICAL();\r
- {\r
- pcTraceBuffer = ( signed char * )pcBuffer;\r
- pcTraceBufferStart = pcBuffer;\r
- pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE );\r
- xTracing = pdTRUE;\r
- }\r
- taskEXIT_CRITICAL();\r
- }\r
-\r
-#endif\r
-/*----------------------------------------------------------*/\r
-\r
-#if ( configUSE_TRACE_FACILITY == 1 )\r
-\r
- unsigned long ulTaskEndTrace( void )\r
- {\r
- unsigned long ulBufferLength;\r
-\r
- taskENTER_CRITICAL();\r
- xTracing = pdFALSE;\r
- taskEXIT_CRITICAL();\r
-\r
- ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart );\r
-\r
- return ulBufferLength;\r
- }\r
-\r
-#endif\r
-/*----------------------------------------------------------*/\r
-\r
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )\r
\r
xTaskHandle xTaskGetIdleTaskHandle( void )\r
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );\r
\r
traceTASK_SWITCHED_IN();\r
- vWriteTraceToBuffer();\r
}\r
}\r
/*-----------------------------------------------------------*/\r
{\r
xMissedYield = pdTRUE;\r
}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+ unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask )\r
+ {\r
+ unsigned portBASE_TYPE uxReturn;\r
+ tskTCB *pxTCB;\r
+ \r
+ if( xTask != NULL )\r
+ {\r
+ pxTCB = ( tskTCB * ) xTask;\r
+ uxReturn = pxTCB->uxTCBNumber;\r
+ }\r
+ else\r
+ {\r
+ uxReturn = 0U;\r
+ }\r
+ \r
+ return uxReturn;\r
+ }\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+ void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )\r
+ {\r
+ tskTCB *pxTCB;\r
+ \r
+ if( xTask != NULL )\r
+ {\r
+ pxTCB = ( tskTCB * ) xTask;\r
+ pxTCB->uxTCBNumber = uxHandle;\r
+ }\r
+ }\r
+#endif\r
+\r
\r
/*\r
* -----------------------------------------------------------\r
{\r
volatile tskTCB *pxNextTCB, *pxFirstTCB;\r
unsigned short usStackRemaining;\r
+ PRIVILEGED_DATA static char pcStatusString[ 50 ];\r
\r
/* Write the details of all the TCB's in pxList into the buffer. */\r
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );\r
/* Just inherit the priority. */\r
pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
}\r
+\r
+ traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );\r
}\r
}\r
\r
Remove ourselves from the ready list we currently appear in. */\r
vListRemove( &( pxTCB->xGenericListItem ) );\r
\r
- /* Disinherit the priority before adding ourselves into the new\r
+ /* Disinherit the priority before adding the task into the new\r
ready list. */\r
+ traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );\r
pxTCB->uxPriority = pxTCB->uxBasePriority;\r
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );\r
prvAddTaskToReadyQueue( pxTCB );\r