⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tasks.c

📁 modbus开发程序包
💻 C
📖 第 1 页 / 共 4 页
字号:
			prvDeleteTCB( ( tskTCB * ) pxTCB );

		}



		while( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )

		{

			listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xSuspendedTaskList );

			vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );



			prvDeleteTCB( ( tskTCB * ) pxTCB );

		}		



		while( !listLIST_IS_EMPTY( &xPendingReadyList ) )

		{

			listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xPendingReadyList );

			vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );



			prvDeleteTCB( ( tskTCB * ) pxTCB );

		}		

	}



#endif

/*-----------------------------------------------------------*/



void vTaskSwitchContext( void )

{

	if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )

	{

		/* The scheduler is currently suspended - do not allow a context

		switch. */

		xMissedYield = pdTRUE;

		return;

	}



	/* Find the highest priority queue that contains ready tasks. */

	while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )

	{

		--uxTopReadyPriority;

	}



	/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the

	same priority get an equal share of the processor time. */

	listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );

	vWriteTraceToBuffer();

}

/*-----------------------------------------------------------*/



void vTaskPlaceOnEventList( xList *pxEventList, portTickType xTicksToWait )

{

portTickType xTimeToWake;



	/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE

	SCHEDULER SUSPENDED. */



	/* Place the event list item of the TCB in the appropriate event list.

	This is placed in the list in priority order so the highest priority task

	is the first to be woken by the event. */

	vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) );



	/* Calculate the time at which the task should be woken if the event does

	not occur.  This may overflow but this doesn't matter. */

	xTimeToWake = xTickCount + xTicksToWait;



	/* We must remove ourselves from the ready list before adding ourselves

	to the blocked list as the same list item is used for both lists.  We have

	exclusive access to the ready lists as the scheduler is locked. */

	vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );



	listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );



	if( xTimeToWake < xTickCount )

	{

		/* Wake time has overflowed.  Place this item in the overflow list. */

		vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );

	}

	else

	{

		/* The wake time has not overflowed, so we can use the current block list. */

		vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );

	}

}

/*-----------------------------------------------------------*/



signed portBASE_TYPE xTaskRemoveFromEventList( const xList *pxEventList )

{

tskTCB *pxUnblockedTCB;

portBASE_TYPE xReturn;



	/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE

	SCHEDULER SUSPENDED.  It can also be called from within an ISR. */



	/* The event list is sorted in priority order, so we can remove the

	first in the list, remove the TCB from the delayed list, and add

	it to the ready list.

	

	If an event is for a queue that is locked then this function will never

	get called - the lock count on the queue will get modified instead.  This

	means we can always expect exclusive access to the event list here. */

	pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );

	vListRemove( &( pxUnblockedTCB->xEventListItem ) );



	if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )

	{

		vListRemove( &( pxUnblockedTCB->xGenericListItem ) );

		prvAddTaskToReadyQueue( pxUnblockedTCB );

	}

	else

	{

		/* We cannot access the delayed or ready lists, so will hold this

		task pending until the scheduler is resumed. */

		vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );

	}



	if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )

	{

		/* Return true if the task removed from the event list has

		a higher priority than the calling task.  This allows

		the calling task to know if it should force a context

		switch now. */

		xReturn = pdTRUE;

	}

	else

	{

		xReturn = pdFALSE;

	}



	return xReturn;

}

/*-----------------------------------------------------------*/



void vTaskSetTimeOutState( xTimeOutType *pxTimeOut )

{

    pxTimeOut->xOverflowCount = xNumOfOverflows;

    pxTimeOut->xTimeOnEntering = xTickCount;

}

/*-----------------------------------------------------------*/



portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType *pxTicksToWait )

{

portBASE_TYPE xReturn;



    if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xTickCount > pxTimeOut->xTimeOnEntering ) )

    {

        /* The tick count is greater than the time at which vTaskSetTimeout() 

		was called, but has also overflowed since vTaskSetTimeOut() was called.

        It must have wrapped all the way around and gone past us again. This

        passed since vTaskSetTimeout() was called. */

        xReturn = pdTRUE;

    }

    else if( ( xTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )

    {

        /* Not a genuine timeout. Adjust parameters for time remaining. */

        *pxTicksToWait -= ( xTickCount - pxTimeOut->xTimeOnEntering );

        vTaskSetTimeOutState( pxTimeOut );

        xReturn = pdFALSE;

    }

    else

    {

        xReturn = pdTRUE;

    }



    return xReturn;

}

/*-----------------------------------------------------------*/



void vTaskMissedYield( void )

{

	xMissedYield = pdTRUE;

}



/*

 * -----------------------------------------------------------

 * The Idle task.

 * ----------------------------------------------------------

 *

 * The portTASK_FUNCTION() macro is used to allow port/compiler specific

 * language extensions.  The equivalent prototype for this function is:

 *

 * void prvIdleTask( void *pvParameters );

 *

 */

static portTASK_FUNCTION( prvIdleTask, pvParameters )

{

	/* Stop warnings. */

	( void ) pvParameters;



	for( ;; )

	{

		/* See if any tasks have been deleted. */

		prvCheckTasksWaitingTermination();



		#if ( configUSE_PREEMPTION == 0 )

		{

			/* If we are not using preemption we keep forcing a task switch to

			see if any other task has become available.  If we are using

			preemption we don't need to do this as any task becoming available

			will automatically get the processor anyway. */

			taskYIELD();	

		}

		#endif



		#if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )

		{

			/* When using preemption tasks of equal priority will be

			timesliced.  If a task that is sharing the idle priority is ready

			to run then the idle task should yield before the end of the

			timeslice.

			

			A critical region is not required here as we are just reading from

			the list, and an occasional incorrect value will not matter.  If

			the ready list at the idle priority contains more than one task

			then a task other than the idle task is ready to execute. */

			if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )

			{

				taskYIELD();

			}

		}

		#endif



		#if ( configUSE_IDLE_HOOK == 1 )

		{

			extern void vApplicationIdleHook( void );



			/* Call the user defined function from within the idle task.  This

			allows the application designer to add background functionality

			without the overhead of a separate task.

			NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,

			CALL A FUNCTION THAT MIGHT BLOCK. */

			vApplicationIdleHook();

		}

		#endif

	}

} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */















/*-----------------------------------------------------------

 * File private functions documented at the top of the file.

 *----------------------------------------------------------*/







static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStackDepth, 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';



	/* This is used as an array index so must ensure it's not too large. */

	if( uxPriority >= configMAX_PRIORITIES )

	{

		uxPriority = configMAX_PRIORITIES - 1;

	}



	pxTCB->uxPriority = uxPriority;



	vListInitialiseItem( &( pxTCB->xGenericListItem ) );

	vListInitialiseItem( &( pxTCB->xEventListItem ) );



	/* Set the pxTCB as a link back from the xListItem.  This is so we can get

	back to	the containing TCB from a generic item in a list. */

	listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );



	/* Event lists are always in priority order. */

	listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority );

	listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );

}

/*-----------------------------------------------------------*/



static void prvInitialiseTaskLists( void )

{

unsigned portBASE_TYPE uxPriority;



	for( uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++ )

	{

		vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) );

	}



	vListInitialise( ( xList * ) &xDelayedTaskList1 );

	vListInitialise( ( xList * ) &xDelayedTaskList2 );

	vListInitialise( ( xList * ) &xPendingReadyList );



	#if ( INCLUDE_vTaskDelete == 1 )

	{

		vListInitialise( ( xList * ) &xTasksWaitingTermination );

	}

	#endif



	#if ( INCLUDE_vTaskSuspend == 1 )

	{

		vListInitialise( ( xList * ) &xSuspendedTaskList );

	}

	#endif



	/* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList

	using list2. */

	pxDelayedTaskList = &xDelayedTaskList1;

	pxOverflowDelayedTaskList = &xDelayedTaskList2;

}

/*-----------------------------------------------------------*/



static void prvCheckTasksWaitingTermination( void )

{							

	#if ( INCLUDE_vTaskDelete == 1 )

	{				

		portBASE_TYPE xListIsEmpty;



		/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called

		too often in the idle task. */

		if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 )

		{

			vTaskSuspendAll();

				xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );				

			xTaskResumeAll();



			if( !xListIsEmpty )

			{

				tskTCB *pxTCB;



				portENTER_CRITICAL();

				{			

					pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );

					vListRemove( &( pxTCB->xGenericListItem ) );

					--uxCurrentNumberOfTasks;

					--uxTasksDeleted;

				}

				portEXIT_CRITICAL();



				prvDeleteTCB( pxTCB );

			}

		}

	}

	#endif

}

/*-----------------------------------------------------------*/



static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth )

{

tskTCB *pxNewTCB;



	/* Allocate space for the TCB.  Where the memory comes from depends on

	the implementation of the port malloc function. */

	pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) );



	if( pxNewTCB != NULL )

	{

		/* Allocate space for the stack used by the task being created.

		The base of the stack memory stored in the TCB so the task can

		be deleted later if required. */

		pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMalloc( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) );



		if( pxNewTCB->pxStack == NULL )

		{

			/* Could not allocate the stack.  Delete the allocated TCB. */

			vPortFree( pxNewTCB );			

			pxNewTCB = NULL;			

		}		

		else

		{

			/* Just to help debugging. */

			memset( pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof( portSTACK_TYPE ) );

		}

	}



	return pxNewTCB;

}

/*-----------------------------------------------------------*/



#if ( configUSE_TRACE_FACILITY == 1 )



	static void prvListTaskWithinSingleList( signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus )

	{

	volatile tskTCB *pxNextTCB, *pxFirstTCB;

	static portCHAR pcStatusString[ 50 ];

	unsigned portSHORT usStackRemaining;



		/* Write the details of all the TCB's in pxList into the buffer. */

		listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );

		do

		{

			listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );

			usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned portCHAR * ) pxNextTCB->pxStack );

			sprintf( pcStatusString, ( portCHAR * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber );

			strcat( ( portCHAR * ) pcWriteBuffer, ( portCHAR * ) pcStatusString );



		} while( pxNextTCB != pxFirstTCB );

	}



#endif

/*-----------------------------------------------------------*/



#if ( configUSE_TRACE_FACILITY == 1 )

	unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR *pucStackByte )

	{

	register unsigned portSHORT usCount = 0;



		while( *pucStackByte == tskSTACK_FILL_BYTE )

		{

			pucStackByte -= portSTACK_GROWTH;

			usCount++;

		}



		usCount /= sizeof( portSTACK_TYPE );



		return usCount;

	}

#endif

/*-----------------------------------------------------------*/







#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )



	static void prvDeleteTCB( tskTCB *pxTCB )

	{

		/* Free up the memory allocated by the scheduler for the task.  It is up to

		the task to free any memory allocated at the application level. */

		vPortFree( pxTCB->pxStack );

		vPortFree( pxTCB );

	}



#endif





/*-----------------------------------------------------------*/



#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 )



	xTaskHandle xTaskGetCurrentTaskHandle( void )

	{

	xTaskHandle xReturn;



		portENTER_CRITICAL();

		{

			xReturn = ( xTaskHandle ) pxCurrentTCB;

		}

		portEXIT_CRITICAL();



		return xReturn;

	}



#endif











⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -