mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 09:38:32 -04:00
Added xQueueSendToBack, xQueueSendToFront, xQueuePeek and xSemaphoreCreateMutex - along with GenQTest.c to demonstrate their usage.
This commit is contained in:
parent
ac14fdb0b7
commit
60338bd872
18 changed files with 2005 additions and 367 deletions
|
@ -19,13 +19,13 @@
|
|||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes FreeRTOS.org, without being obliged to provide
|
||||
the source code for any proprietary components. See the licensing section
|
||||
the source code for any proprietary components. See the licensing section
|
||||
of http://www.FreeRTOS.org for full details of how and when the exception
|
||||
can be applied.
|
||||
|
||||
***************************************************************************
|
||||
See http://www.FreeRTOS.org for documentation, latest information, license
|
||||
and contact details. Please ensure to read the configuration and relevant
|
||||
See http://www.FreeRTOS.org for documentation, latest information, license
|
||||
and contact details. Please ensure to read the configuration and relevant
|
||||
port sections of the online documentation.
|
||||
|
||||
Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
|
||||
|
@ -37,8 +37,8 @@
|
|||
#define INC_FREERTOS_H
|
||||
|
||||
|
||||
/*
|
||||
* Include the generic headers required for the FreeRTOS port being used.
|
||||
/*
|
||||
* Include the generic headers required for the FreeRTOS port being used.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
|
||||
|
@ -58,7 +58,7 @@
|
|||
|
||||
|
||||
/*
|
||||
* Check all the required application specific macros have been defined.
|
||||
* Check all the required application specific macros have been defined.
|
||||
* These macros are application specific and (as downloaded) are defined
|
||||
* within FreeRTOSConfig.h.
|
||||
*/
|
||||
|
@ -111,4 +111,19 @@
|
|||
#error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_MUTEXES
|
||||
#define configUSE_MUTEXES 0
|
||||
#endif
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
/* xTaskGetCurrentTaskHandle is used by the priority inheritance mechanism
|
||||
within the mutex implementation so must be available if mutexes are used. */
|
||||
#undef INCLUDE_xTaskGetCurrentTaskHandle
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#else
|
||||
#ifndef INCLUDE_xTaskGetCurrentTaskHandle
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* INC_FREERTOS_H */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -54,6 +54,13 @@ typedef xQueueHandle xSemaphoreHandle;
|
|||
* as we don't want to actually store any data - we just want to know if the
|
||||
* queue is empty or full.
|
||||
*
|
||||
* This type of semaphore can be used for pure synchronisation between tasks or
|
||||
* between an interrupt and a task. The semaphore need not be given back once
|
||||
* obtained, so one task/interrupt can continuously 'give' the semaphore while
|
||||
* another continuously 'takes' the semaphore. For this reason this type of
|
||||
* semaphore does not use a priority inheritance mechanism. For an alternative
|
||||
* that does use priority inheritance see xSemaphoreCreateMutex().
|
||||
*
|
||||
* @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle.
|
||||
*
|
||||
* Example usage:
|
||||
|
@ -205,7 +212,7 @@ typedef xQueueHandle xSemaphoreHandle;
|
|||
* \defgroup xSemaphoreGive xSemaphoreGive
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreGive( xSemaphore ) xQueueSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME )
|
||||
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
|
@ -218,6 +225,9 @@ typedef xQueueHandle xSemaphoreHandle;
|
|||
* <i>Macro</i> to release a semaphore. The semaphore must of been created using
|
||||
* vSemaphoreCreateBinary (), and obtained using xSemaphoreTake ().
|
||||
*
|
||||
* Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
|
||||
* must not be used with this macro.
|
||||
*
|
||||
* This macro can be used from an ISR.
|
||||
*
|
||||
* @param xSemaphore A handle to the semaphore being released. This is the
|
||||
|
@ -285,8 +295,52 @@ typedef xQueueHandle xSemaphoreHandle;
|
|||
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreGiveFromISR( xSemaphore, xTaskPreviouslyWoken ) xQueueSendFromISR( ( xQueueHandle ) xSemaphore, NULL, xTaskPreviouslyWoken )
|
||||
#define xSemaphoreGiveFromISR( xSemaphore, xTaskPreviouslyWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) xSemaphore, NULL, xTaskPreviouslyWoken, queueSEND_TO_BACK )
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
* <pre>xSemaphoreCreateMutex( xSemaphoreHandle xSemaphore )</pre>
|
||||
*
|
||||
* <i>Macro</i> that implements a mutex semaphore by using the existing queue
|
||||
* mechanism.
|
||||
*
|
||||
* This type of semaphore uses a priority inheritance mechanism so a task
|
||||
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
|
||||
* semaphore it is no longer required.
|
||||
*
|
||||
* Mutex type semaphores cannot be used from within interrupt service routines.
|
||||
*
|
||||
* See xSemaphoreCreateBinary() for an alternative implemnetation that can be
|
||||
* used for pure synchronisation (where one task or interrupt always 'gives' the
|
||||
* semaphore and another always 'takes' the semaphore) and from within interrupt
|
||||
* service routines.
|
||||
*
|
||||
* @param xSemaphore Handle to the created mutex semaphore. Should be of type
|
||||
* xSemaphoreHandle.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
xSemaphoreHandle xSemaphore;
|
||||
|
||||
void vATask( void * pvParameters )
|
||||
{
|
||||
// Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
|
||||
// This is a macro so pass the variable in directly.
|
||||
vSemaphoreCreateMutex( xSemaphore );
|
||||
|
||||
if( xSemaphore != NULL )
|
||||
{
|
||||
// The semaphore was created successfully.
|
||||
// The semaphore can now be used.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreCreateMutex() xQueueCreateMutex()
|
||||
|
||||
|
||||
#endif
|
||||
#endif /* SEMAPHORE_H */
|
||||
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ void vTaskDelay( portTickType xTicksToDelay );
|
|||
* \defgroup vTaskDelayUntil vTaskDelayUntil
|
||||
* \ingroup TaskCtrl
|
||||
*/
|
||||
void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );
|
||||
void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement );
|
||||
|
||||
/**
|
||||
* task. h
|
||||
|
@ -894,7 +894,7 @@ inline void vTaskIncrementTick( void );
|
|||
* portTICK_RATE_MS can be used to convert kernel ticks into a real time
|
||||
* period.
|
||||
*/
|
||||
void vTaskPlaceOnEventList( xList *pxEventList, portTickType xTicksToWait );
|
||||
void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait );
|
||||
|
||||
/*
|
||||
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
|
||||
|
@ -911,7 +911,7 @@ void vTaskPlaceOnEventList( xList *pxEventList, portTickType xTicksToWait );
|
|||
* @return pdTRUE if the task being removed has a higher priority than the task
|
||||
* making the call, otherwise pdFALSE.
|
||||
*/
|
||||
signed portBASE_TYPE xTaskRemoveFromEventList( const xList *pxEventList );
|
||||
signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList );
|
||||
|
||||
/*
|
||||
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
|
||||
|
@ -944,13 +944,13 @@ xTaskHandle xTaskGetCurrentTaskHandle( void );
|
|||
/*
|
||||
* Capture the current time status for future reference.
|
||||
*/
|
||||
void vTaskSetTimeOutState( xTimeOutType *pxTimeOut );
|
||||
void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut );
|
||||
|
||||
/*
|
||||
* Compare the time status now with that previously captured to see if the
|
||||
* timeout has expired.
|
||||
*/
|
||||
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType * const pxTicksToWait );
|
||||
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait );
|
||||
|
||||
/*
|
||||
* Shortcut used by the queue implementation to prevent unnecessary call to
|
||||
|
@ -964,6 +964,18 @@ void vTaskMissedYield( void );
|
|||
*/
|
||||
portBASE_TYPE xTaskGetSchedulerState( void );
|
||||
|
||||
/*
|
||||
* Raises the priority of the mutex holder to that of the calling task should
|
||||
* the mutex holder have a priority less than the calling task.
|
||||
*/
|
||||
void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder );
|
||||
|
||||
/*
|
||||
* Set the priority of a task back to its proper priority in the case that it
|
||||
* inherited a higher priority while it was holding a semaphore.
|
||||
*/
|
||||
void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder );
|
||||
|
||||
#endif /* TASK_H */
|
||||
|
||||
|
||||
|
|
|
@ -51,18 +51,18 @@ void portSWITCH_CONTEXT( void );
|
|||
*/
|
||||
void portFIRST_CONTEXT( void );
|
||||
|
||||
#define portSWITCH_CONTEXT()
|
||||
// asm { mov ax, seg pxCurrentTCB }
|
||||
// asm { mov ds, ax }
|
||||
// asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */
|
||||
// asm { mov es:0x2[ bx ], ss }
|
||||
// asm { mov es:[ bx ], sp }
|
||||
// asm { call far ptr vTaskSwitchContext } /* Perform the switch. */
|
||||
// asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */
|
||||
// asm { mov ds, ax }
|
||||
// asm { les bx, dword ptr pxCurrentTCB }
|
||||
// asm { mov ss, es:[ bx + 2 ] }
|
||||
// asm { mov sp, es:[ bx ] }
|
||||
#define portSWITCH_CONTEXT() \
|
||||
asm { mov ax, seg pxCurrentTCB } \
|
||||
asm { mov ds, ax } \
|
||||
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
|
||||
asm { mov es:0x2[ bx ], ss } \
|
||||
asm { mov es:[ bx ], sp } \
|
||||
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
|
||||
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
|
||||
asm { mov ds, ax } \
|
||||
asm { les bx, dword ptr pxCurrentTCB } \
|
||||
asm { mov ss, es:[ bx + 2 ] } \
|
||||
asm { mov sp, es:[ bx ] }
|
||||
|
||||
#define portFIRST_CONTEXT() \
|
||||
asm { mov ax, seg pxCurrentTCB } \
|
||||
|
@ -70,7 +70,7 @@ void portFIRST_CONTEXT( void );
|
|||
asm { les bx, dword ptr pxCurrentTCB } \
|
||||
asm { mov ss, es:[ bx + 2 ] } \
|
||||
asm { mov sp, es:[ bx ] } \
|
||||
asm { pop bx } \
|
||||
asm { pop bp } \
|
||||
asm { pop di } \
|
||||
asm { pop si } \
|
||||
asm { pop ds } \
|
||||
|
|
259
Source/queue.c
259
Source/queue.c
|
@ -70,9 +70,9 @@ Changes from V4.1.2:
|
|||
|
||||
Changes from V4.1.3:
|
||||
|
||||
+ Modified xQueueSend() and xQueueReceive() to handle the (very unlikely)
|
||||
case whereby a task unblocking due to a temporal event can remove/send an
|
||||
item from/to a queue when a higher priority task is still blocked on the
|
||||
+ Modified xQueueSend() and xQueueReceive() to handle the (very unlikely)
|
||||
case whereby a task unblocking due to a temporal event can remove/send an
|
||||
item from/to a queue when a higher priority task is still blocked on the
|
||||
queue. This modification is a result of the SafeRTOS testing.
|
||||
*/
|
||||
|
||||
|
@ -90,6 +90,15 @@ Changes from V4.1.3:
|
|||
#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
|
||||
#define queueERRONEOUS_UNBLOCK ( -1 )
|
||||
|
||||
/* For internal use only. */
|
||||
#define queueSEND_TO_BACK ( 0 )
|
||||
#define queueSEND_TO_FRONT ( 1 )
|
||||
|
||||
/* Effectively make a union out of the xQUEUE structure. */
|
||||
#define pxMutexHolder pcTail
|
||||
#define uxQueueType pcHead
|
||||
#define queueQUEUE_IS_MUTEX NULL
|
||||
|
||||
/*
|
||||
* Definition of the queue used by the scheduler.
|
||||
* Items are queued by copy, not reference.
|
||||
|
@ -109,8 +118,8 @@ typedef struct QueueDefinition
|
|||
unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
|
||||
unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
|
||||
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
} xQUEUE;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -127,12 +136,13 @@ typedef xQUEUE * xQueueHandle;
|
|||
* functions are documented in the API header file.
|
||||
*/
|
||||
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
|
||||
signed portBASE_TYPE xQueueSend( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );
|
||||
signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
|
||||
unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle pxQueue );
|
||||
void vQueueDelete( xQueueHandle xQueue );
|
||||
signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken );
|
||||
signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );
|
||||
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
|
||||
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition );
|
||||
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
|
||||
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );
|
||||
xQueueHandle xQueueCreateMutex( void );
|
||||
|
||||
#if configUSE_CO_ROUTINES == 1
|
||||
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
|
||||
|
@ -166,20 +176,15 @@ static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue );
|
|||
static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue );
|
||||
|
||||
/*
|
||||
* Macro that copies an item into the queue. This is done by copying the item
|
||||
* byte for byte, not by reference. Updates the queue state to ensure it's
|
||||
* integrity after the copy.
|
||||
* Copies an item into the queue, either at the front of the queue or the
|
||||
* back of the queue.
|
||||
*/
|
||||
#define prvCopyQueueData( pxQueue, pvItemToQueue ) \
|
||||
{ \
|
||||
memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); \
|
||||
++( pxQueue->uxMessagesWaiting ); \
|
||||
pxQueue->pcWriteTo += pxQueue->uxItemSize; \
|
||||
if( pxQueue->pcWriteTo >= pxQueue->pcTail ) \
|
||||
{ \
|
||||
pxQueue->pcWriteTo = pxQueue->pcHead; \
|
||||
} \
|
||||
}
|
||||
static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition );
|
||||
|
||||
/*
|
||||
* Copies an item out of a queue.
|
||||
*/
|
||||
static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -248,7 +253,49 @@ size_t xQueueSizeInBytes;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xQueueSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
||||
xQueueHandle xQueueCreateMutex( void )
|
||||
{
|
||||
xQUEUE *pxNewQueue;
|
||||
|
||||
/* Allocate the new queue structure. */
|
||||
pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
|
||||
if( pxNewQueue != NULL )
|
||||
{
|
||||
/* Information required for priority inheritance. */
|
||||
pxNewQueue->pxMutexHolder = NULL;
|
||||
pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
|
||||
|
||||
/* Queues used as a mutex no data is actually copied into or out
|
||||
of the queue. */
|
||||
pxNewQueue->pcWriteTo = NULL;
|
||||
pxNewQueue->pcReadFrom = NULL;
|
||||
|
||||
/* Each mutex has a length of 1 (like a binary semaphore) and
|
||||
an item size of 0 as nothing is actually copied into or out
|
||||
of the mutex. */
|
||||
pxNewQueue->uxMessagesWaiting = 0;
|
||||
pxNewQueue->uxLength = 1;
|
||||
pxNewQueue->uxItemSize = 0;
|
||||
pxNewQueue->xRxLock = queueUNLOCKED;
|
||||
pxNewQueue->xTxLock = queueUNLOCKED;
|
||||
|
||||
/* Ensure the event queues start with the correct state. */
|
||||
vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
|
||||
vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
|
||||
|
||||
/* Start with the semaphore in the expected state. */
|
||||
xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );
|
||||
}
|
||||
|
||||
return pxNewQueue;
|
||||
}
|
||||
|
||||
#endif /* configUSE_MUTEXES */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
|
||||
{
|
||||
signed portBASE_TYPE xReturn = pdPASS;
|
||||
xTimeOutType xTimeOut;
|
||||
|
@ -285,15 +332,15 @@ xTimeOutType xTimeOut;
|
|||
queue being modified here. Places where the event list is modified
|
||||
include:
|
||||
|
||||
+ xQueueSendFromISR(). This checks the lock on the queue to see if
|
||||
it has access. If the queue is locked then the Tx lock count is
|
||||
+ xQueueGenericSendFromISR(). This checks the lock on the queue to see
|
||||
if it has access. If the queue is locked then the Tx lock count is
|
||||
incremented to signify that a task waiting for data can be made ready
|
||||
once the queue lock is removed. If the queue is not locked then
|
||||
a task can be moved from the event list, but will not be removed
|
||||
from the delayed list or placed in the ready list until the scheduler
|
||||
is unlocked.
|
||||
|
||||
+ xQueueReceiveFromISR(). As per xQueueSendFromISR().
|
||||
+ xQueueReceiveFromISR(). As per xQueueGenericSendFromISR().
|
||||
*/
|
||||
|
||||
/* If the queue is already full we may have to block. */
|
||||
|
@ -390,7 +437,7 @@ xTimeOutType xTimeOut;
|
|||
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
|
||||
{
|
||||
/* There is room in the queue, copy the data into the queue. */
|
||||
prvCopyQueueData( pxQueue, pvItemToQueue );
|
||||
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
|
||||
xReturn = pdPASS;
|
||||
|
||||
/* Update the TxLock count so prvUnlockQueue knows to check for
|
||||
|
@ -425,16 +472,16 @@ xTimeOutType xTimeOut;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken )
|
||||
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )
|
||||
{
|
||||
/* Similar to xQueueSend, except we don't block if there is no room in the
|
||||
queue. Also we don't directly wake a task that was blocked on a queue
|
||||
read, instead we return a flag to say whether a context switch is required
|
||||
or not (i.e. has a task with a higher priority than us been woken by this
|
||||
post). */
|
||||
/* Similar to xQueueGenericSend, except we don't block if there is no room
|
||||
in the queue. Also we don't directly wake a task that was blocked on a
|
||||
queue read, instead we return a flag to say whether a context switch is
|
||||
required or not (i.e. has a task with a higher priority than us been woken
|
||||
by this post). */
|
||||
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
|
||||
{
|
||||
prvCopyQueueData( pxQueue, pvItemToQueue );
|
||||
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
|
||||
|
||||
/* If the queue is locked we do not alter the event list. This will
|
||||
be done when the queue is unlocked later. */
|
||||
|
@ -467,13 +514,14 @@ signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItem
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xQueueReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
|
||||
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
|
||||
{
|
||||
signed portBASE_TYPE xReturn = pdTRUE;
|
||||
xTimeOutType xTimeOut;
|
||||
signed portCHAR *pcOriginalReadPosition;
|
||||
|
||||
/* This function is very similar to xQueueSend(). See comments within
|
||||
xQueueSend() for a more detailed explanation.
|
||||
/* This function is very similar to xQueueGenericSend(). See comments
|
||||
within xQueueGenericSend() for a more detailed explanation.
|
||||
|
||||
Make sure other tasks do not access the queue. */
|
||||
vTaskSuspendAll();
|
||||
|
@ -493,6 +541,17 @@ xTimeOutType xTimeOut;
|
|||
leave with nothing? */
|
||||
if( xTicksToWait > ( portTickType ) 0 )
|
||||
{
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
|
||||
{
|
||||
portENTER_CRITICAL();
|
||||
vTaskPriorityInherit( ( xTaskHandle * const ) pxQueue->pxMutexHolder );
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
|
@ -522,18 +581,39 @@ xTimeOutType xTimeOut;
|
|||
{
|
||||
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
pxQueue->pcReadFrom += pxQueue->uxItemSize;
|
||||
if( pxQueue->pcReadFrom >= pxQueue->pcTail )
|
||||
/* Remember our read position in case we are just peeking. */
|
||||
pcOriginalReadPosition = pxQueue->pcReadFrom;
|
||||
|
||||
prvCopyDataFromQueue( pxQueue, pvBuffer );
|
||||
|
||||
if( xJustPeeking == pdFALSE )
|
||||
{
|
||||
pxQueue->pcReadFrom = pxQueue->pcHead;
|
||||
/* We are actually removing data. */
|
||||
--( pxQueue->uxMessagesWaiting );
|
||||
|
||||
/* Increment the lock count so prvUnlockQueue knows to check for
|
||||
tasks waiting for space to become available on the queue. */
|
||||
++( pxQueue->xRxLock );
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
|
||||
{
|
||||
/* Record the information required to implement
|
||||
priority inheritance should it become necessary. */
|
||||
pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
--( pxQueue->uxMessagesWaiting );
|
||||
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
|
||||
|
||||
/* Increment the lock count so prvUnlockQueue knows to check for
|
||||
tasks waiting for space to become available on the queue. */
|
||||
++( pxQueue->xRxLock );
|
||||
xReturn = pdPASS;
|
||||
else
|
||||
{
|
||||
/* We are not removing the data, so reset our read
|
||||
pointer. */
|
||||
pxQueue->pcReadFrom = pcOriginalReadPosition;
|
||||
}
|
||||
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -563,21 +643,15 @@ xTimeOutType xTimeOut;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken )
|
||||
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
/* We cannot block from an ISR, so check there is data available. */
|
||||
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
/* Copy the data from the queue. */
|
||||
pxQueue->pcReadFrom += pxQueue->uxItemSize;
|
||||
if( pxQueue->pcReadFrom >= pxQueue->pcTail )
|
||||
{
|
||||
pxQueue->pcReadFrom = pxQueue->pcHead;
|
||||
}
|
||||
prvCopyDataFromQueue( pxQueue, pvBuffer );
|
||||
--( pxQueue->uxMessagesWaiting );
|
||||
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
|
||||
|
||||
/* If the queue is locked we will not modify the event list. Instead
|
||||
we update the lock count so the task that unlocks the queue will know
|
||||
|
@ -636,6 +710,57 @@ void vQueueDelete( xQueueHandle pxQueue )
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
|
||||
{
|
||||
if( pxQueue->uxItemSize == 0 )
|
||||
{
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
|
||||
{
|
||||
/* The mutex is no longer being held. */
|
||||
vTaskPriorityDisinherit( ( xTaskHandle * const ) pxQueue->pxMutexHolder );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if( xPosition == queueSEND_TO_BACK )
|
||||
{
|
||||
memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
|
||||
pxQueue->pcWriteTo += pxQueue->uxItemSize;
|
||||
if( pxQueue->pcWriteTo >= pxQueue->pcTail )
|
||||
{
|
||||
pxQueue->pcWriteTo = pxQueue->pcHead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
|
||||
pxQueue->pcReadFrom -= pxQueue->uxItemSize;
|
||||
if( pxQueue->pcReadFrom < pxQueue->pcHead )
|
||||
{
|
||||
pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
|
||||
}
|
||||
}
|
||||
|
||||
++( pxQueue->uxMessagesWaiting );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
|
||||
{
|
||||
if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
|
||||
{
|
||||
pxQueue->pcReadFrom += pxQueue->uxItemSize;
|
||||
if( pxQueue->pcReadFrom >= pxQueue->pcTail )
|
||||
{
|
||||
pxQueue->pcReadFrom = pxQueue->pcHead;
|
||||
}
|
||||
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvUnlockQueue( xQueueHandle pxQueue )
|
||||
{
|
||||
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
|
||||
|
@ -722,7 +847,7 @@ signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQue
|
|||
signed portBASE_TYPE xReturn;
|
||||
|
||||
/* If the queue is already full we may have to block. A critical section
|
||||
is required to prevent an interrupt removing something from the queue
|
||||
is required to prevent an interrupt removing something from the queue
|
||||
between the check to see if the queue is full and blocking on the queue. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
|
@ -754,19 +879,19 @@ signed portBASE_TYPE xReturn;
|
|||
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
|
||||
{
|
||||
/* There is room in the queue, copy the data into the queue. */
|
||||
prvCopyQueueData( pxQueue, pvItemToQueue );
|
||||
prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
|
||||
xReturn = pdPASS;
|
||||
|
||||
/* Were any co-routines waiting for data to become available? */
|
||||
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
|
||||
{
|
||||
/* In this instance the co-routine could be placed directly
|
||||
into the ready list as we are within a critical section.
|
||||
Instead the same pending ready list mechansim is used as if
|
||||
/* In this instance the co-routine could be placed directly
|
||||
into the ready list as we are within a critical section.
|
||||
Instead the same pending ready list mechanism is used as if
|
||||
the event were caused from within an interrupt. */
|
||||
if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
|
||||
{
|
||||
/* The co-routine waiting has a higher priority so record
|
||||
/* The co-routine waiting has a higher priority so record
|
||||
that a yield might be appropriate. */
|
||||
xReturn = errQUEUE_YIELD;
|
||||
}
|
||||
|
@ -790,7 +915,7 @@ signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, port
|
|||
signed portBASE_TYPE xReturn;
|
||||
|
||||
/* If the queue is already empty we may have to block. A critical section
|
||||
is required to prevent an interrupt adding something to the queue
|
||||
is required to prevent an interrupt adding something to the queue
|
||||
between the check to see if the queue is empty and blocking on the queue. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
|
@ -835,9 +960,9 @@ signed portBASE_TYPE xReturn;
|
|||
/* Were any co-routines waiting for space to become available? */
|
||||
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
|
||||
{
|
||||
/* In this instance the co-routine could be placed directly
|
||||
into the ready list as we are within a critical section.
|
||||
Instead the same pending ready list mechansim is used as if
|
||||
/* In this instance the co-routine could be placed directly
|
||||
into the ready list as we are within a critical section.
|
||||
Instead the same pending ready list mechanism is used as if
|
||||
the event were caused from within an interrupt. */
|
||||
if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
|
||||
{
|
||||
|
@ -866,9 +991,9 @@ signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvIt
|
|||
exit without doing anything. */
|
||||
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
|
||||
{
|
||||
prvCopyQueueData( pxQueue, pvItemToQueue );
|
||||
prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
|
||||
|
||||
/* We only want to wake one co-routine per ISR, so check that a
|
||||
/* We only want to wake one co-routine per ISR, so check that a
|
||||
co-routine has not already been woken. */
|
||||
if( !xCoRoutinePreviouslyWoken )
|
||||
{
|
||||
|
|
157
Source/tasks.c
157
Source/tasks.c
|
@ -229,10 +229,6 @@ Changes since V4.3.1:
|
|||
#define configMAX_TASK_NAME_LEN 16
|
||||
#endif
|
||||
|
||||
#ifndef INCLUDE_xTaskGetCurrentTaskHandle
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 0
|
||||
#endif
|
||||
|
||||
#ifndef configIDLE_SHOULD_YIELD
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
#endif
|
||||
|
@ -261,9 +257,16 @@ typedef struct tskTaskControlBlock
|
|||
xListItem xEventListItem; /*< List item used to place the TCB in event lists. */
|
||||
unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */
|
||||
portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */
|
||||
unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */
|
||||
signed portCHAR pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */
|
||||
unsigned portSHORT usStackDepth; /*< Total depth of the stack (when empty). This is defined as the number of variables the stack can hold, not the number of bytes. */
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */
|
||||
#endif
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
unsigned portBASE_TYPE uxBasePriority;
|
||||
#endif
|
||||
|
||||
} tskTCB;
|
||||
|
||||
/*lint -e956 */
|
||||
|
@ -429,7 +432,7 @@ register tskTCB *pxTCB; \
|
|||
* Utility to ready a TCB for a given task. Mainly just copies the parameters
|
||||
* into the TCB structure.
|
||||
*/
|
||||
static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStackDepth, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority );
|
||||
static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority );
|
||||
|
||||
/*
|
||||
* Utility to ready all the lists used by the scheduler. This is called
|
||||
|
@ -485,7 +488,7 @@ static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );
|
|||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
static void prvListTaskWithinSingleList( signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus );
|
||||
static void prvListTaskWithinSingleList( const signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus );
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -496,7 +499,7 @@ static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );
|
|||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR *pucStackByte );
|
||||
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte );
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -524,7 +527,9 @@ signed portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, const signed portCHAR
|
|||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
tskTCB * pxNewTCB;
|
||||
static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberate - this is guarded before use. */
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberate - this is guarded before use. */
|
||||
#endif
|
||||
|
||||
/* Allocate the memory required by the TCB and stack for the new task.
|
||||
checking that the allocation was successful. */
|
||||
|
@ -535,7 +540,7 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
|||
portSTACK_TYPE *pxTopOfStack;
|
||||
|
||||
/* Setup the newly allocated TCB with the initial state of the task. */
|
||||
prvInitialiseTCBVariables( pxNewTCB, usStackDepth, pcName, uxPriority );
|
||||
prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority );
|
||||
|
||||
/* Calculate the top of stack address. This depends on whether the
|
||||
stack grows from high memory to low (as per the 80x86) or visa versa.
|
||||
|
@ -543,7 +548,7 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
|||
required by the port. */
|
||||
#if portSTACK_GROWTH < 0
|
||||
{
|
||||
pxTopOfStack = pxNewTCB->pxStack + ( pxNewTCB->usStackDepth - 1 );
|
||||
pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
|
||||
}
|
||||
#else
|
||||
{
|
||||
|
@ -593,9 +598,13 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
|||
uxTopUsedPriority = pxNewTCB->uxPriority;
|
||||
}
|
||||
|
||||
/* Add a counter into the TCB for tracing only. */
|
||||
pxNewTCB->uxTCBNumber = uxTaskNumber;
|
||||
uxTaskNumber++;
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
{
|
||||
/* Add a counter into the TCB for tracing only. */
|
||||
pxNewTCB->uxTCBNumber = uxTaskNumber;
|
||||
uxTaskNumber++;
|
||||
}
|
||||
#endif
|
||||
|
||||
prvAddTaskToReadyQueue( pxNewTCB );
|
||||
|
||||
|
@ -695,7 +704,7 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
|||
|
||||
#if ( INCLUDE_vTaskDelayUntil == 1 )
|
||||
|
||||
void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement )
|
||||
void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
|
||||
{
|
||||
portTickType xTimeToWake;
|
||||
portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
|
||||
|
@ -867,13 +876,22 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
|||
/* If null is passed in here then we are changing the
|
||||
priority of the calling function. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTask );
|
||||
uxCurrentPriority = pxTCB->uxPriority;
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
uxCurrentPriority = pxTCB->uxBasePriority;
|
||||
}
|
||||
#else
|
||||
{
|
||||
uxCurrentPriority = pxTCB->uxPriority;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( uxCurrentPriority != uxNewPriority )
|
||||
{
|
||||
/* The priority change may have readied a task of higher
|
||||
priority than the calling task. */
|
||||
if( uxNewPriority > pxCurrentTCB->uxPriority )
|
||||
if( uxNewPriority > uxCurrentPriority )
|
||||
{
|
||||
if( pxTask != NULL )
|
||||
{
|
||||
|
@ -891,7 +909,26 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
|||
xYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
pxTCB->uxPriority = uxNewPriority;
|
||||
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
/* Only change the priority being used if the task is not
|
||||
currently using an inherited priority. */
|
||||
if( pxTCB->uxBasePriority == pxTCB->uxPriority )
|
||||
{
|
||||
pxTCB->uxPriority = uxNewPriority;
|
||||
}
|
||||
|
||||
/* The base priority gets set whatever. */
|
||||
pxTCB->uxBasePriority = uxNewPriority;
|
||||
}
|
||||
#else
|
||||
{
|
||||
pxTCB->uxPriority = uxNewPriority;
|
||||
}
|
||||
#endif
|
||||
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxNewPriority );
|
||||
|
||||
/* If the task is in the blocked or suspended list we need do
|
||||
|
@ -1051,7 +1088,7 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
|||
{
|
||||
/* We cannot access the delayed or ready lists, so will hold this
|
||||
task pending until the scheduler is resumed, at which point a
|
||||
yield will be preformed if necessary. */
|
||||
yield will be performed if necessary. */
|
||||
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
|
@ -1457,7 +1494,7 @@ void vTaskSwitchContext( void )
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskPlaceOnEventList( xList *pxEventList, portTickType xTicksToWait )
|
||||
void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait )
|
||||
{
|
||||
portTickType xTimeToWake;
|
||||
|
||||
|
@ -1527,7 +1564,7 @@ portTickType xTimeToWake;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xTaskRemoveFromEventList( const xList *pxEventList )
|
||||
signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
|
||||
{
|
||||
tskTCB *pxUnblockedTCB;
|
||||
portBASE_TYPE xReturn;
|
||||
|
@ -1574,14 +1611,14 @@ portBASE_TYPE xReturn;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskSetTimeOutState( xTimeOutType *pxTimeOut )
|
||||
void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
|
||||
{
|
||||
pxTimeOut->xOverflowCount = xNumOfOverflows;
|
||||
pxTimeOut->xTimeOnEntering = xTickCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType * const pxTicksToWait )
|
||||
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
|
||||
|
@ -1701,10 +1738,8 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
|||
|
||||
|
||||
|
||||
static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStackDepth, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority )
|
||||
static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority )
|
||||
{
|
||||
pxTCB->usStackDepth = usStackDepth;
|
||||
|
||||
/* Store the function name in the TCB. */
|
||||
strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned portSHORT ) configMAX_TASK_NAME_LEN );
|
||||
pxTCB->pcTaskName[ ( unsigned portSHORT ) configMAX_TASK_NAME_LEN - ( unsigned portSHORT ) 1 ] = '\0';
|
||||
|
@ -1716,6 +1751,11 @@ static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStack
|
|||
}
|
||||
|
||||
pxTCB->uxPriority = uxPriority;
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
pxTCB->uxBasePriority = uxPriority;
|
||||
}
|
||||
#endif
|
||||
|
||||
vListInitialiseItem( &( pxTCB->xGenericListItem ) );
|
||||
vListInitialiseItem( &( pxTCB->xEventListItem ) );
|
||||
|
@ -1831,7 +1871,7 @@ tskTCB *pxNewTCB;
|
|||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
static void prvListTaskWithinSingleList( signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus )
|
||||
static void prvListTaskWithinSingleList( const signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus )
|
||||
{
|
||||
volatile tskTCB *pxNextTCB, *pxFirstTCB;
|
||||
static portCHAR pcStatusString[ 50 ];
|
||||
|
@ -1853,7 +1893,7 @@ tskTCB *pxNewTCB;
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR *pucStackByte )
|
||||
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte )
|
||||
{
|
||||
register unsigned portSHORT usCount = 0;
|
||||
|
||||
|
@ -1933,4 +1973,63 @@ tskTCB *pxNewTCB;
|
|||
|
||||
#endif
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
||||
void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )
|
||||
{
|
||||
tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
|
||||
|
||||
if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
|
||||
{
|
||||
/* Adjust the mutex holder state to account for its new priority. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
|
||||
|
||||
/* If the task being modified is in the read state it will need to
|
||||
be moved in to a new list. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) )
|
||||
{
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Inherit the priority before being moved into the new list. */
|
||||
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just inherit the priority. */
|
||||
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
||||
void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder )
|
||||
{
|
||||
tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
|
||||
|
||||
if( pxMutexHolder != NULL )
|
||||
{
|
||||
if( pxTCB->uxPriority != pxTCB->uxBasePriority )
|
||||
{
|
||||
/* We must be the running task to be able to give the mutex back.
|
||||
Remove ourselves from the ready list we currently appear in. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Disinherit the priority before adding ourselves into the new
|
||||
ready list. */
|
||||
pxTCB->uxPriority = pxTCB->uxBasePriority;
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue