mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 01:28:32 -04:00
Add tickless idle support in Cortex-M ports.
Change CCS R4 directory name.
This commit is contained in:
parent
6ec4c7cecb
commit
e03ab659f3
21 changed files with 2395 additions and 596 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
|
@ -40,7 +40,7 @@
|
|||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
|
@ -50,21 +50,21 @@
|
|||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, training, latest information,
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, training, latest information,
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -74,6 +74,7 @@ all the API functions to use the MPU wrappers. That should only be done when
|
|||
task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
|
@ -82,39 +83,40 @@ task.h is included from an application file. */
|
|||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/*
|
||||
* Macro to define the amount of stack available to the idle task.
|
||||
* Defines the size, in words, of the stack allocated to the idle task.
|
||||
*/
|
||||
#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
|
||||
/*
|
||||
* Task control block. A task control block (TCB) is allocated to each task,
|
||||
* and stores the context of the task.
|
||||
* Task control block. A task control block (TCB) is allocated for each task,
|
||||
* and stores task state information, including a pointer to the task's context
|
||||
* (the task's run time environment, including register values)
|
||||
*/
|
||||
typedef struct tskTaskControlBlock
|
||||
{
|
||||
volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */
|
||||
volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
|
||||
|
||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */
|
||||
#endif
|
||||
|
||||
xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */
|
||||
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. */
|
||||
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
|
||||
#endif
|
||||
|
||||
xListItem xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
|
||||
xListItem xEventListItem; /*< Used to reference a task from an event list. */
|
||||
unsigned portBASE_TYPE uxPriority; /*< The priority of the task. 0 is the lowest priority. */
|
||||
portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */
|
||||
signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */
|
||||
|
||||
#if ( portSTACK_GROWTH > 0 )
|
||||
portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
|
||||
portSTACK_TYPE *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
|
||||
#endif
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
unsigned portBASE_TYPE uxCriticalNesting;
|
||||
unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
|
||||
#endif
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
unsigned portBASE_TYPE uxTCBNumber; /*< This stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
|
||||
unsigned portBASE_TYPE uxTaskNumber; /*< This stores a number specifically for use by third party trace code. */
|
||||
unsigned portBASE_TYPE uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
|
||||
unsigned portBASE_TYPE uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
|
||||
#endif
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
@ -126,15 +128,15 @@ typedef struct tskTaskControlBlock
|
|||
#endif
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */
|
||||
unsigned long ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
|
||||
#endif
|
||||
|
||||
} tskTCB;
|
||||
|
||||
|
||||
/*
|
||||
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||
* than file scope.
|
||||
* Some kernel aware debuggers require the data the debugger needs access to to
|
||||
* be global, rather than file scope.
|
||||
*/
|
||||
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||
#define static
|
||||
|
@ -144,7 +146,6 @@ typedef struct tskTaskControlBlock
|
|||
PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
|
||||
|
||||
/* Lists for ready and blocked tasks. --------------------*/
|
||||
|
||||
PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
|
||||
PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */
|
||||
PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
|
||||
|
@ -166,9 +167,9 @@ PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been r
|
|||
#endif
|
||||
|
||||
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
|
||||
|
||||
PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL;
|
||||
|
||||
|
||||
PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
|
||||
|
||||
#endif
|
||||
|
||||
/* File private variables. --------------------------------*/
|
||||
|
@ -182,7 +183,7 @@ PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsi
|
|||
PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
|
||||
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
|
||||
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U;
|
||||
PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY;
|
||||
PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY;
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
|
||||
|
@ -211,10 +212,13 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 0
|
||||
/*
|
||||
* uxTopReadyPriority holds the priority of the highest priority ready
|
||||
* state task.
|
||||
*/
|
||||
|
||||
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
|
||||
performed in a generic way that is not optimised to any particular
|
||||
microcontroller architecture. */
|
||||
|
||||
/* uxTopReadyPriority holds the priority of the highest priority ready
|
||||
state task. */
|
||||
#define taskRECORD_READY_PRIORITY( uxPriority ) \
|
||||
{ \
|
||||
if( ( uxPriority ) > uxTopReadyPriority ) \
|
||||
|
@ -241,26 +245,46 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
|
|||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Define away portRESET_READY_PRIORITY() as it is not required in this
|
||||
configuration. */
|
||||
/* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
|
||||
they are only required when a port optimised method of task selection is
|
||||
being used. */
|
||||
#define taskRESET_READY_PRIORITY( uxPriority )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
|
||||
|
||||
#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
|
||||
performed in a way that is tailored to the particular microcontroller
|
||||
architecture being used. */
|
||||
|
||||
/* A port optimised version is provided. Call the port defined macros. */
|
||||
#define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
|
||||
{ \
|
||||
unsigned portBASE_TYPE uxTopPriority; \
|
||||
\
|
||||
/* Find the highest priority queue that contains ready tasks. */ \
|
||||
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
||||
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
|
||||
{ \
|
||||
unsigned portBASE_TYPE uxTopPriority; \
|
||||
\
|
||||
/* Find the highest priority queue that contains ready tasks. */ \
|
||||
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
|
||||
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
||||
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* A port optimised version is provided, call it only if the TCB being reset
|
||||
is being referenced from a ready list. If it is referenced from a delayed
|
||||
or suspended list then it won't be in a ready list. */
|
||||
#define taskRESET_READY_PRIORITY( uxPriority ) \
|
||||
{ \
|
||||
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \
|
||||
{ \
|
||||
portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*
|
||||
|
@ -270,9 +294,9 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType )
|
|||
* executing task, then it will only be rescheduled after the currently
|
||||
* executing task has been rescheduled.
|
||||
*/
|
||||
#define prvAddTaskToReadyQueue( pxTCB ) \
|
||||
traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
|
||||
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
|
||||
#define prvAddTaskToReadyQueue( pxTCB ) \
|
||||
traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
|
||||
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
|
||||
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -348,7 +372,7 @@ portTickType xItemValue; \
|
|||
/* Callback function prototypes. --------------------------*/
|
||||
extern void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName );
|
||||
extern void vApplicationTickHook( void );
|
||||
|
||||
|
||||
/* File private functions. --------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -488,7 +512,7 @@ tskTCB * pxNewTCB;
|
|||
#else
|
||||
{
|
||||
pxTopOfStack = pxNewTCB->pxStack;
|
||||
|
||||
|
||||
/* Check the alignment of the stack buffer is correct. */
|
||||
configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
|
||||
|
||||
|
@ -526,7 +550,7 @@ tskTCB * pxNewTCB;
|
|||
required.*/
|
||||
*pxCreatedTask = ( xTaskHandle ) pxNewTCB;
|
||||
}
|
||||
|
||||
|
||||
/* We are going to manipulate the task queues to add this task to a
|
||||
ready list, so must make sure no interrupts occur. */
|
||||
taskENTER_CRITICAL();
|
||||
|
@ -630,7 +654,7 @@ tskTCB * pxNewTCB;
|
|||
scheduler for the TCB and stack. */
|
||||
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
|
||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
||||
}
|
||||
|
||||
/* Is the task waiting on an event also? */
|
||||
|
@ -725,6 +749,9 @@ tskTCB * pxNewTCB;
|
|||
both lists. */
|
||||
if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
/* The current task must be in a ready list, so there is
|
||||
no need to check, and the port reset macro can be called
|
||||
directly. */
|
||||
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
|
||||
}
|
||||
|
||||
|
@ -775,6 +802,9 @@ tskTCB * pxNewTCB;
|
|||
both lists. */
|
||||
if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
/* The current task must be in a ready list, so there is
|
||||
no need to check, and the port reset macro can be called
|
||||
directly. */
|
||||
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
|
||||
}
|
||||
prvAddCurrentTaskToDelayedList( xTimeToWake );
|
||||
|
@ -794,7 +824,7 @@ tskTCB * pxNewTCB;
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_eTaskStateGet == 1 )
|
||||
|
||||
|
||||
eTaskState eTaskStateGet( xTaskHandle pxTask )
|
||||
{
|
||||
eTaskState eReturn;
|
||||
|
@ -818,7 +848,7 @@ tskTCB * pxNewTCB;
|
|||
|
||||
if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
|
||||
{
|
||||
/* The task being queried is referenced from one of the Blocked
|
||||
/* The task being queried is referenced from one of the Blocked
|
||||
lists. */
|
||||
eReturn = eBlocked;
|
||||
}
|
||||
|
@ -826,7 +856,7 @@ tskTCB * pxNewTCB;
|
|||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
else if( pxStateList == &xSuspendedTaskList )
|
||||
{
|
||||
/* The task being queried is referenced from the suspended
|
||||
/* The task being queried is referenced from the suspended
|
||||
list. */
|
||||
eReturn = eSuspended;
|
||||
}
|
||||
|
@ -835,7 +865,7 @@ tskTCB * pxNewTCB;
|
|||
#if ( INCLUDE_vTaskDelete == 1 )
|
||||
else if( pxStateList == &xTasksWaitingTermination )
|
||||
{
|
||||
/* The task being queried is referenced from the deleted
|
||||
/* The task being queried is referenced from the deleted
|
||||
tasks list. */
|
||||
eReturn = eDeleted;
|
||||
}
|
||||
|
@ -882,7 +912,7 @@ tskTCB * pxNewTCB;
|
|||
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
unsigned portBASE_TYPE uxCurrentPriority;
|
||||
unsigned portBASE_TYPE uxCurrentPriority, uxPriorityUsedOnEntry;
|
||||
portBASE_TYPE xYieldRequired = pdFALSE;
|
||||
|
||||
configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
|
||||
|
@ -938,7 +968,10 @@ tskTCB * pxNewTCB;
|
|||
xYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Remember the ready list the task might be referenced from
|
||||
before its uxPriority member is changed so the
|
||||
taskRESET_READY_PRIORITY() macro can function correctly. */
|
||||
uxPriorityUsedOnEntry = pxTCB->uxPriority;
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
|
@ -971,7 +1004,7 @@ tskTCB * pxNewTCB;
|
|||
can do this even if the scheduler is suspended. */
|
||||
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
portRESET_READY_PRIORITY( uxCurrentPriority, uxTopReadyPriority );
|
||||
taskRESET_READY_PRIORITY( uxPriorityUsedOnEntry );
|
||||
}
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
|
@ -983,6 +1016,10 @@ tskTCB * pxNewTCB;
|
|||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
/* Remove compiler warning about unused parameter when the port
|
||||
optimised task selection is not being used. */
|
||||
( void ) uxPriorityUsedOnEntry;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1011,7 +1048,7 @@ tskTCB * pxNewTCB;
|
|||
/* Remove task from the ready/delayed list and place in the suspended list. */
|
||||
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
|
||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
||||
}
|
||||
|
||||
/* Is the task waiting on an event also? */
|
||||
|
@ -1228,7 +1265,7 @@ portBASE_TYPE xReturn;
|
|||
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() != pdFALSE )
|
||||
|
@ -1266,6 +1303,30 @@ void vTaskSuspendAll( void )
|
|||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
portTickType xTaskGetExpectedIdleTime( void )
|
||||
{
|
||||
portTickType xReturn;
|
||||
|
||||
if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
|
||||
{
|
||||
xReturn = 0;
|
||||
}
|
||||
else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
|
||||
{
|
||||
/* There are other idle priority tasks in the ready state. If
|
||||
time slicing is used then the very next tick interrupt must be
|
||||
processed. */
|
||||
xReturn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = xNextTaskUnblockTime - xTickCount;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xTaskResumeAll( void )
|
||||
{
|
||||
register tskTCB *pxTCB;
|
||||
|
@ -1488,7 +1549,7 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
|
|||
/* Divide ulTotalRunTime by 100 to make the percentage caluclations
|
||||
simpler in the prvGenerateRunTimeStatsForTasksInList() function. */
|
||||
ulTotalRunTime /= 100UL;
|
||||
|
||||
|
||||
/* Run through all the lists that could potentially contain a TCB,
|
||||
generating a table of run timer percentages in the provided
|
||||
buffer. */
|
||||
|
@ -1551,8 +1612,15 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
|
|||
configASSERT( ( xIdleTaskHandle != NULL ) );
|
||||
return xIdleTaskHandle;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
void vTaskStepTick( portTickType xTicksToJump )
|
||||
{
|
||||
configASSERT( xTicksToJump <= xNextTaskUnblockTime );
|
||||
xTickCount += xTicksToJump;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
|
||||
|
@ -1566,6 +1634,7 @@ tskTCB * pxTCB;
|
|||
/* Called by the portable layer each time a tick interrupt occurs.
|
||||
Increments the tick then checks to see if the new tick value will cause any
|
||||
tasks to be unblocked. */
|
||||
traceTASK_INCREMENT_TICK( xTickCount );
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
++xTickCount;
|
||||
|
@ -1577,17 +1646,17 @@ tskTCB * pxTCB;
|
|||
If there are any items in pxDelayedTaskList here then there is
|
||||
an error! */
|
||||
configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );
|
||||
|
||||
|
||||
pxTemp = pxDelayedTaskList;
|
||||
pxDelayedTaskList = pxOverflowDelayedTaskList;
|
||||
pxOverflowDelayedTaskList = pxTemp;
|
||||
xNumOfOverflows++;
|
||||
|
||||
|
||||
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
|
||||
{
|
||||
/* The new current delayed list is empty. Set
|
||||
xNextTaskUnblockTime to the maximum possible value so it is
|
||||
extremely unlikely that the
|
||||
extremely unlikely that the
|
||||
if( xTickCount >= xNextTaskUnblockTime ) test will pass until
|
||||
there is an item in the delayed list. */
|
||||
xNextTaskUnblockTime = portMAX_DELAY;
|
||||
|
@ -1629,8 +1698,6 @@ tskTCB * pxTCB;
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
traceTASK_INCREMENT_TICK( xTickCount );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -1732,17 +1799,17 @@ void vTaskSwitchContext( void )
|
|||
else
|
||||
{
|
||||
traceTASK_SWITCHED_OUT();
|
||||
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
{
|
||||
unsigned long ulTempCounter;
|
||||
|
||||
|
||||
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
|
||||
portALT_GET_RUN_TIME_COUNTER_VALUE( ulTempCounter );
|
||||
#else
|
||||
ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
#endif
|
||||
|
||||
|
||||
/* Add the amount of time the task has been running to the accumulated
|
||||
time so far. The time the task started running was stored in
|
||||
ulTaskSwitchedInTime. Note that there is no overflow protection here
|
||||
|
@ -1752,12 +1819,12 @@ void vTaskSwitchContext( void )
|
|||
ulTaskSwitchedInTime = ulTempCounter;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
taskFIRST_CHECK_FOR_STACK_OVERFLOW();
|
||||
taskSECOND_CHECK_FOR_STACK_OVERFLOW();
|
||||
|
||||
|
||||
taskSELECT_HIGHEST_PRIORITY_TASK();
|
||||
|
||||
|
||||
traceTASK_SWITCHED_IN();
|
||||
}
|
||||
}
|
||||
|
@ -1782,6 +1849,8 @@ portTickType xTimeToWake;
|
|||
exclusive access to the ready lists as the scheduler is locked. */
|
||||
if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
/* The current task must be in a ready list, so there is no need to
|
||||
check, and the port reset macro can be called directly. */
|
||||
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
|
||||
}
|
||||
|
||||
|
@ -1826,7 +1895,7 @@ portTickType xTimeToWake;
|
|||
designed for use by kernel code, and has special calling requirements -
|
||||
it should be called from a critical section. */
|
||||
|
||||
|
||||
|
||||
/* Place the event list item of the TCB in the appropriate event list.
|
||||
In this case it is assume that this is the only task that is going to
|
||||
be waiting on this event list, so the faster vListInsertEnd() function
|
||||
|
@ -1838,6 +1907,8 @@ portTickType xTimeToWake;
|
|||
function is called form a critical section. */
|
||||
if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
/* The current task must be in a ready list, so there is no need to
|
||||
check, and the port reset macro can be called directly. */
|
||||
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
|
||||
}
|
||||
|
||||
|
@ -1846,7 +1917,7 @@ portTickType xTimeToWake;
|
|||
xTimeToWake = xTickCount + xTicksToWait;
|
||||
prvAddCurrentTaskToDelayedList( xTimeToWake );
|
||||
}
|
||||
|
||||
|
||||
#endif /* configUSE_TIMERS */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -1865,7 +1936,7 @@ portBASE_TYPE xReturn;
|
|||
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.
|
||||
|
||||
|
||||
This function assumes that a check has already been made to ensure that
|
||||
pxEventList is not empty. */
|
||||
pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
|
@ -1966,7 +2037,7 @@ void vTaskMissedYield( void )
|
|||
{
|
||||
unsigned portBASE_TYPE uxReturn;
|
||||
tskTCB *pxTCB;
|
||||
|
||||
|
||||
if( xTask != NULL )
|
||||
{
|
||||
pxTCB = ( tskTCB * ) xTask;
|
||||
|
@ -1976,7 +2047,7 @@ void vTaskMissedYield( void )
|
|||
{
|
||||
uxReturn = 0U;
|
||||
}
|
||||
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
#endif
|
||||
|
@ -1986,7 +2057,7 @@ void vTaskMissedYield( void )
|
|||
void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
|
||||
if( xTask != NULL )
|
||||
{
|
||||
pxTCB = ( tskTCB * ) xTask;
|
||||
|
@ -2057,6 +2128,48 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
|||
vApplicationIdleHook();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||
{
|
||||
portTickType xExpectedIdleTime;
|
||||
/* If the expected idle time is 1 then the idle time would end at
|
||||
the end of the current time slice. The idle time must be at least
|
||||
2 to ensure any pended ticks between this point and the tick being
|
||||
stopped can be legitimately stepped over when the tick suppression
|
||||
routines returns. */
|
||||
const portTickType xMinimumExpectedIdleTime = ( portTickType ) 2;
|
||||
|
||||
/* Don't enter low power if there are still tasks waiting
|
||||
deletion. */
|
||||
if( uxTasksDeleted == 0 )
|
||||
{
|
||||
/* It is not desirable to suspend then resume the scheduler on
|
||||
each iteration of the idle task. Therefore, a preliminary
|
||||
test of the expected idle time is performed without the
|
||||
scheduler suspended. The result here is not necessarily
|
||||
valid. */
|
||||
xExpectedIdleTime = xTaskGetExpectedIdleTime();
|
||||
|
||||
if( xExpectedIdleTime >= xMinimumExpectedIdleTime )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Now the scheduler is suspended, the expected idle
|
||||
time can be sampled again, and this time its value can
|
||||
be used. */
|
||||
configASSERT( xNextTaskUnblockTime >= xTickCount );
|
||||
xExpectedIdleTime = xTaskGetExpectedIdleTime();
|
||||
|
||||
if( xExpectedIdleTime >= xMinimumExpectedIdleTime )
|
||||
{
|
||||
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
|
||||
}
|
||||
}
|
||||
xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */
|
||||
|
||||
|
@ -2144,7 +2257,7 @@ static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const
|
|||
void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
|
||||
if( xTaskToModify == pxCurrentTCB )
|
||||
{
|
||||
xTaskToModify = NULL;
|
||||
|
@ -2304,8 +2417,8 @@ tskTCB *pxNewTCB;
|
|||
{
|
||||
usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
sprintf( pcStatusString, ( char * ) "%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( ( char * ) pcWriteBuffer, ( char * ) pcStatusString );
|
||||
|
||||
|
@ -2349,7 +2462,7 @@ tskTCB *pxNewTCB;
|
|||
{
|
||||
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED
|
||||
{
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage );
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage );
|
||||
}
|
||||
#else
|
||||
{
|
||||
|
@ -2365,7 +2478,7 @@ tskTCB *pxNewTCB;
|
|||
consumed less than 1% of the total run time. */
|
||||
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED
|
||||
{
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter );
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter );
|
||||
}
|
||||
#else
|
||||
{
|
||||
|
@ -2516,12 +2629,12 @@ tskTCB *pxNewTCB;
|
|||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
|
||||
|
||||
/* If the task being modified is in the ready state it will need to
|
||||
be moved in to a new list. */
|
||||
be moved into a new list. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
|
||||
{
|
||||
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
|
||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
||||
}
|
||||
|
||||
/* Inherit the priority before being moved into the new list. */
|
||||
|
@ -2556,7 +2669,7 @@ tskTCB *pxNewTCB;
|
|||
Remove ourselves from the ready list we currently appear in. */
|
||||
if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
|
||||
{
|
||||
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
|
||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
||||
}
|
||||
|
||||
/* Disinherit the priority before adding the task into the new
|
||||
|
@ -2589,21 +2702,40 @@ tskTCB *pxNewTCB;
|
|||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
|
||||
void vTaskExitCritical( void )
|
||||
{
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
void vTaskExitCritical( void )
|
||||
{
|
||||
if( pxCurrentTCB->uxCriticalNesting > 0U )
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
( pxCurrentTCB->uxCriticalNesting )--;
|
||||
|
||||
if( pxCurrentTCB->uxCriticalNesting == 0U )
|
||||
if( pxCurrentTCB->uxCriticalNesting > 0U )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
( pxCurrentTCB->uxCriticalNesting )--;
|
||||
|
||||
if( pxCurrentTCB->uxCriticalNesting == 0U )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TICKLESS_IDLE == 1 )
|
||||
|
||||
unsigned portBASE_TYPE uxTaskPendingTicksGet( portBASE_TYPE xResetOnExit )
|
||||
{
|
||||
unsigned portBASE_TYPE uxReturn;
|
||||
|
||||
uxReturn = uxMissedTicks;
|
||||
|
||||
if( xResetOnExit == pdTRUE )
|
||||
{
|
||||
uxMissedTicks = 0;
|
||||
}
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue