📄 tasks.c
字号:
else if( pxTask == NULL )
{
/* Setting our own priority down means there may now be another
task of higher priority that is ready to execute. */
xYieldRequired = pdTRUE;
}
#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
nothing more than change it's priority variable. However, if
the task is in a ready list it needs to be removed and placed
in the queue appropriate to its new priority. */
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
{
/* The task is currently in its ready list - remove before adding
it to it's new ready list. As we are in a critical section we
can do this even if the scheduler is suspended. */
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
}
if( xYieldRequired == pdTRUE )
{
portYIELD_WITHIN_API();
}
}
}
portEXIT_CRITICAL();
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
void vTaskSuspend( xTaskHandle pxTaskToSuspend )
{
tskTCB *pxTCB;
portENTER_CRITICAL();
{
/* Ensure a yield is performed if the current task is being
suspended. */
if( pxTaskToSuspend == pxCurrentTCB )
{
pxTaskToSuspend = NULL;
}
/* If null is passed in here then we are suspending ourselves. */
pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );
traceTASK_SUSPEND( pxTCB );
/* Remove task from the ready/delayed list and place in the suspended list. */
vListRemove( &( pxTCB->xGenericListItem ) );
/* Is the task waiting on an event also? */
if( pxTCB->xEventListItem.pvContainer )
{
vListRemove( &( pxTCB->xEventListItem ) );
}
vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
}
portEXIT_CRITICAL();
/* We may have just suspended the current task. */
if( ( void * ) pxTaskToSuspend == NULL )
{
portYIELD_WITHIN_API();
}
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
{
portBASE_TYPE xReturn = pdFALSE;
const tskTCB * const pxTCB = ( tskTCB * ) xTask;
/* Is the task we are attempting to resume actually in the
suspended list? */
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
{
/* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
{
/* Is it in the suspended list because it is in the
Suspended state? It is possible to be in the suspended
list because it is blocked on a task with no timeout
specified. */
if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE )
{
xReturn = pdTRUE;
}
}
}
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
void vTaskResume( xTaskHandle pxTaskToResume )
{
tskTCB *pxTCB;
/* Remove the task from whichever list it is currently in, and place
it in the ready list. */
pxTCB = ( tskTCB * ) pxTaskToResume;
/* The parameter cannot be NULL as it is impossible to resume the
currently executing task. */
if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
{
portENTER_CRITICAL();
{
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
{
traceTASK_RESUME( pxTCB );
/* As we are in a critical section we can access the ready
lists even if the scheduler is suspended. */
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
/* We may have just resumed a higher priority task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
/* This yield may not cause the task just resumed to run, but
will leave the lists in the correct state for the next yield. */
portYIELD_WITHIN_API();
}
}
}
portEXIT_CRITICAL();
}
}
#endif
/*-----------------------------------------------------------*/
#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
{
portBASE_TYPE xYieldRequired = pdFALSE;
tskTCB *pxTCB;
pxTCB = ( tskTCB * ) pxTaskToResume;
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
{
traceTASK_RESUME_FROM_ISR( pxTCB );
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
}
else
{
/* 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 performed if necessary. */
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}
}
return xYieldRequired;
}
#endif
/*-----------------------------------------------------------
* PUBLIC SCHEDULER CONTROL documented in task.h
*----------------------------------------------------------*/
void vTaskStartScheduler( void )
{
portBASE_TYPE xReturn;
/* Add the idle task at the lowest priority. */
xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), ( xTaskHandle * ) NULL );
if( xReturn == pdPASS )
{
/* Interrupts are turned off here, to ensure a tick does not occur
before or during the call to xPortStartScheduler(). The stacks of
the created tasks contain a status word with interrupts switched on
so interrupts will automatically get re-enabled when the first task
starts to run.
STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE
DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */
portDISABLE_INTERRUPTS();
xSchedulerRunning = pdTRUE;
xTickCount = ( portTickType ) 0;
/* If configGENERATE_RUN_TIME_STATS is defined then the following
macro must be defined to configure the timer/counter used to generate
the run time counter time base. */
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
/* Setting up the timer tick is hardware specific and thus in the
portable interface. */
if( xPortStartScheduler() )
{
/* Should not reach here as if the scheduler is running the
function will not return. */
}
else
{
/* Should only reach here if a task calls xTaskEndScheduler(). */
}
}
}
/*-----------------------------------------------------------*/
void vTaskEndScheduler( void )
{
/* Stop the scheduler interrupts and call the portable scheduler end
routine so the original ISRs can be restored if necessary. The port
layer must ensure interrupts enable bit is left in the correct state. */
portDISABLE_INTERRUPTS();
xSchedulerRunning = pdFALSE;
vPortEndScheduler();
}
/*----------------------------------------------------------*/
void vTaskSuspendAll( void )
{
/* A critical section is not required as the variable is of type
portBASE_TYPE. */
++uxSchedulerSuspended;
}
/*----------------------------------------------------------*/
signed portBASE_TYPE xTaskResumeAll( void )
{
register tskTCB *pxTCB;
signed portBASE_TYPE xAlreadyYielded = pdFALSE;
/* It is possible that an ISR caused a task to be removed from an event
list while the scheduler was suspended. If this was the case then the
removed task will have been added to the xPendingReadyList. Once the
scheduler has been resumed it is safe to move all the pending ready
tasks from this list into their appropriate ready list. */
portENTER_CRITICAL();
{
--uxSchedulerSuspended;
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 )
{
portBASE_TYPE xYieldRequired = pdFALSE;
/* Move any readied tasks from the pending list into the
appropriate ready list. */
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL )
{
vListRemove( &( pxTCB->xEventListItem ) );
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
/* If we have moved a task that has a priority higher than
the current task then we should yield. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
xYieldRequired = pdTRUE;
}
}
/* If any ticks occurred while the scheduler was suspended then
they should be processed now. This ensures the tick count does not
slip, and that any delayed tasks are resumed at the correct time. */
if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
{
while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
{
vTaskIncrementTick();
--uxMissedTicks;
}
/* As we have processed some ticks it is appropriate to yield
to ensure the highest priority task that is ready to run is
the task actually running. */
#if configUSE_PREEMPTION == 1
{
xYieldRequired = pdTRUE;
}
#endif
}
if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )
{
xAlreadyYielded = pdTRUE;
xMissedYield = pdFALSE;
portYIELD_WITHIN_API();
}
}
}
}
portEXIT_CRITICAL();
return xAlreadyYielded;
}
/*-----------------------------------------------------------
* PUBLIC TASK UTILITIES documented in task.h
*----------------------------------------------------------*/
portTickType xTaskGetTickCount( void )
{
portTickType xTicks;
/* Critical section required if running on a 16 bit processor. */
portENTER_CRITICAL();
{
xTicks = xTickCount;
}
portEXIT_CRITICAL();
return xTicks;
}
/*-----------------------------------------------------------*/
unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
{
/* A critical section is not required because the variables are of type
portBASE_TYPE. */
return uxCurrentNumberOfTasks;
}
/*-----------------------------------------------------------*/
#if ( configUSE_TRACE_FACILITY == 1 )
void vTaskList( signed char *pcWriteBuffer )
{
unsigned portBASE_TYPE uxQueue;
/* This is a VERY costly function that should be used for debug only.
It leaves interrupts disabled for a LONG time. */
vTaskSuspendAll();
{
/* Run through all the lists that could potentially contain a TCB and
report the task name, state and stack high water mark. */
pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
uxQueue = uxTopUsedPriority + 1;
do
{
uxQueue--;
if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
{
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -