Add tickless idle support in Cortex-M ports.

Change CCS R4 directory name.
This commit is contained in:
Richard Barry 2012-10-16 07:55:40 +00:00
parent 6ec4c7cecb
commit e03ab659f3
21 changed files with 2395 additions and 596 deletions

View file

@ -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
/*-----------------------------------------------------------*/