\r
***************************************************************************\r
\r
- Please ensure to read the configuration and relevant port sections of the \r
+ Please ensure to read the configuration and relevant port sections of the\r
online documentation.\r
\r
+++ http://www.FreeRTOS.org +++\r
- Documentation, latest information, license and contact details. \r
+ Documentation, latest information, license and contact details.\r
\r
+++ http://www.SafeRTOS.com +++\r
A version that is certified for use in safety critical systems.\r
***************************************************************************\r
*/\r
\r
-/*\r
-Changes from V1.00:\r
- \r
- + Call to portRESTORE_CONTEXT has been removed. The first context\r
- switch is now performed within sPortStartScheduler().\r
-\r
-Changes from V1.01:\r
-\r
- + More use of 8bit data types.\r
- + Function name prefixes changed where the data type returned has changed.\r
- + configUSE_TRACE_FACILITY is no longer defined by default.\r
-\r
-Changes from V1.2.0\r
-\r
- + Introduced ucTopReadyPriority. This tracks the highest priority ready\r
- queue that contains a valid TCB and thus makes the context switch\r
- slightly faster.\r
-\r
- + prvAddTaskToReadyQueue() has been made a macro.\r
-\r
-Changes from V1.2.6\r
-\r
- + Added conditional compilation directives.\r
- + Extended API.\r
- + Rearranged function order.\r
- + Creating a task now causes a context switch if the task being created\r
- has a higher priority than the calling task - assuming the kernel is\r
- running.\r
- + vTaskDelete() now only causes a context switch if the calling task is\r
- the task being deleted.\r
-\r
-Changes from V2.0.0\r
-\r
- + Allow the type of the tick count to be 16 or 32 bits.\r
- + Introduce xPendingReadyList feature to allow the time interrupts have to\r
- be disabled to be minimised.\r
- + Remove the #if( INCLUDE_vTaskSuspendAll ) statements. vTaskSuspendAll()\r
- is now always included as it is used by the scheduler itself.\r
-\r
-Changes from V2.1.0\r
-\r
- + Bug fix - pxCurrentTCB is now initialised before the call to\r
- prvInitializeTaskLists(). Previously pxCurrentTCB could be accessed\r
- while null.\r
-\r
-Changed from V2.1.1\r
-\r
- + Change to where lStackSize is declared within sTaskCreate() to prevent\r
- compiler warnings with 8051 port.\r
-\r
-Changes from V2.2.0\r
-\r
- + Explicit use of 'signed' qualifier on portCHAR types added.\r
- + Changed odd calculation of initial pxTopOfStack value when\r
- portSTACK_GROWTH < 0.\r
- + Removed pcVersionNumber definition.\r
-\r
-Changes from V2.5.3\r
-\r
- + cTaskResumeAll() modified to ensure it can be called prior to the task\r
- lists being initialised.\r
-\r
-Changes from V2.5.5\r
-\r
- + Added API function vTaskDelayUntil().\r
- + Added INCLUDE_vTaskDelay conditional compilation.\r
-\r
-Changes from V2.6.0\r
-\r
- + Updated the vWriteTraceToBuffer macro to always be 4 byte aligned so it\r
- can be used on ARM architectures.\r
- + tskMAX_TASK_NAME_LEN definition replaced with the port specific\r
- configMAX_TASK_NAME_LEN definition.\r
- + Removed the call to strcpy when copying across the task name into the\r
- TCB.\r
- + Added ucTasksDeleted variable to prevent vTaskSuspendAll() being called\r
- too often in the idle task.\r
-\r
-Changes between V3.0.0 and V2.6.1\r
-\r
- + When resuming the scheduler a yield is performed if either a tick has\r
- been missed, or a task is moved from the pending ready list into a ready\r
- list. Previously a yield was not performed on this second condition.\r
- + Introduced the type portBASE_TYPE. This necessitates several API\r
- changes.\r
- + Removed the sUsingPreemption variable. The constant defined in\r
- portmacro.h is now used directly.\r
- + The idle task can now include an optional hook function - and no longer\r
- completes its time slice if other tasks with equal priority to it are\r
- ready to run.\r
- + See the FreeRTOS.org documentation for more information on V2.x.x to\r
- V3.x.x modifications.\r
-\r
-Changes from V3.1.1\r
-\r
- + Modified vTaskPrioritySet() and vTaskResume() to allow these functions to\r
- be called while the scheduler is suspended.\r
- + Corrected the task ordering within event lists.\r
-\r
-Changes from V3.2.0\r
-\r
- + Added function xTaskGetCurrentTaskHandle().\r
-\r
-Changes from V3.2.4\r
-\r
- + Changed the volatile declarations on some variables to reflect the \r
- changes to the list definitions.\r
- + Changed the order of the TCB definition so there is commonality between\r
- the task control block and a co-routine control block.\r
- + Allow the scheduler to be started even if no tasks other than the idle\r
- task has been created. This allows co-routines to run even when no tasks\r
- have been created.\r
- + The need for a context switch is now signalled if a task woken by an \r
- event has a priority greater or equal to the currently running task.\r
- Previously this was only greater than.\r
-\r
-Changes from V4.0.0\r
-\r
- + Added the xMissedYield handling.\r
-\r
-Changes from V4.0.1\r
-\r
- + The function vTaskList() now suspends the scheduler rather than disabling\r
- interrupts during the creation of the task list. \r
- + Allow a task to delete itself by passing in its own handle. Previously \r
- this could only be done by passing in NULL.\r
- + The tick hook function is now called only within a tick isr. Previously\r
- it was also called when the tick function was called during the scheduler\r
- unlocking process.\r
-\r
-Changes from V4.0.3\r
-\r
- + Extra checks have been placed in vTaskPrioritySet() to avoid unnecessary\r
- yields.\r
-\r
-Changed from V4.0.4\r
-\r
- + Bug fix: The 'value' of the event list item is updated when the priority\r
- of a task is changed. Previously only the priority of the TCB itself was\r
- changed.\r
- + When resuming a task a check is first made to see if the task is actually\r
- suspended.\r
- + vTaskPrioritySet() and vTaskResume() no longer use the event list item.\r
- This has not been necessary since V4.0.1 when the xMissedYield handling\r
- was added.\r
- + Implement xTaskResumeFromISR().\r
-\r
-Changes from V4.0.5\r
-\r
- + Added utility functions and xOverflowCount variable to facilitate the\r
- queue.c changes.\r
-\r
-Changes from V4.1.2\r
- \r
- + Tasks that block on events with a timeout of portMAX_DELAY are now\r
- blocked indefinitely if configINCLUDE_vTaskSuspend is defined. \r
- Previously portMAX_DELAY was just the longest block time possible.\r
-\r
-Changes from V4.1.3\r
-\r
- + Very small change made to xTaskCheckForTimeout() as a result of the \r
- SafeRTOS testing. This corrects the case where the function can return an\r
- invalid value - but only in an extremely unlikely scenario.\r
-\r
-Changes since V4.3.1:\r
-\r
- + Added xTaskGetSchedulerState() function.\r
- + Added prvIsTaskSuspended() to take into account the Occurrence of\r
- vTaskResume() or vTaskResumeFromISR() being called passing in the\r
- handle of a task that appears in the Suspended list only because it\r
- is blocked on an event without a timeout being specified.\r
- + Updated xTaskCheckForTimeout() to take into account that tasks blocked\r
- using the Suspended list should never time out.\r
-*/\r
\r
#include <stdio.h>\r
#include <stdlib.h>\r
\r
#endif\r
\r
+/*-----------------------------------------------------------*/\r
+\r
/*\r
* Macro that writes a trace of scheduler activity to a buffer. This trace\r
* shows which task is running when and is very useful as a debugging tool.\r
#define vWriteTraceToBuffer()\r
\r
#endif\r
-\r
+/*-----------------------------------------------------------*/\r
\r
/*\r
* Place the task represented by pxTCB into the appropriate ready queue for\r
uxTopReadyPriority = pxTCB->uxPriority; \\r
} \\r
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \\r
-} \r
+}\r
+/*-----------------------------------------------------------*/ \r
\r
/*\r
* Macro that looks at the list of tasks that are currently delayed to see if\r
{ \\r
vListRemove( &( pxTCB->xEventListItem ) ); \\r
} \\r
- prvAddTaskToReadyQueue( pxTCB ); \\r
+ prvAddTaskToReadyQueue( pxTCB ); \\r
} \\r
-} \r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Call the stack overflow hook function if the stack of the task being swapped\r
+ * out is currently overflowed, or looks like it might have overflowed in the\r
+ * past.\r
+ *\r
+ * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check\r
+ * the current stack state only - comparing the current top of stack value to\r
+ * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1\r
+ * will also cause the last few stack bytes to be checked to ensure the value\r
+ * to which the bytes were set when the task was created have not been \r
+ * overwritten. Note this second test does not guarantee that an overflown\r
+ * stack will always be recognised.\r
+ */\r
+\r
+#if( configCHECK_FOR_STACK_OVERFLOW == 0 )\r
+\r
+ /* FreeRTOSConfig.h is not set to check for stack overflows. */\r
+ #define taskCHECK_FOR_STACK_OVERFLOW()\r
+\r
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */\r
+\r
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH >= 0 ) )\r
+\r
+ /* This is an invalid setting. */\r
+ #error configCHECK_FOR_STACK_OVERFLOW can only be set to a non zero value on architectures where the stack grows down from high memory.\r
+\r
+#endif /* ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH >= 0 ) */\r
+\r
+#if( configCHECK_FOR_STACK_OVERFLOW == 1 )\r
+\r
+ /* Only the current stack state is to be checked. */\r
+ #define taskCHECK_FOR_STACK_OVERFLOW() \\r
+ { \\r
+ extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); \\r
+ \\r
+ /* Is the currently saved stack pointer within the stack limit? */ \\r
+ if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \\r
+ { \\r
+ vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName ); \\r
+ } \\r
+ }\r
+\r
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */\r
+\r
+#if( configCHECK_FOR_STACK_OVERFLOW > 1 )\r
+\r
+ /* Both the current statck state and the stack fill bytes are to be checked. */\r
+ #define taskCHECK_FOR_STACK_OVERFLOW() \\r
+ { \\r
+ extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); \\r
+ static const unsigned portCHAR ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \\r
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \\r
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \\r
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \\r
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \\r
+ \\r
+ /* Is the currently saved stack pointer within the stack limit? */ \\r
+ if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \\r
+ { \\r
+ vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName ); \\r
+ } \\r
+ \\r
+ /* Has the extremity of the task stack ever been written over? */ \\r
+ if( memcmp( pxCurrentTCB->pxStack, ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \\r
+ { \\r
+ vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName ); \\r
+ } \\r
+ }\r
+\r
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */\r
+/*-----------------------------------------------------------*/\r
\r
/*\r
* Several functions take an xTaskHandle parameter that can optionally be NULL,\r
* This function determines the 'high water mark' of the task stack by\r
* determining how much of the stack remains at the original preset value.\r
*/\r
-#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxGetStackHighWaterMark == 1 ) )\r
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
\r
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte );\r
\r
\r
\r
\r
-\r
-\r
/*-----------------------------------------------------------\r
* TASK CREATION API documented in task.h\r
*----------------------------------------------------------*/\r
\r
taskENTER_CRITICAL();\r
{\r
- /* Ensure a yield is performed if the current task is being \r
+ /* Ensure a yield is performed if the current task is being\r
deleted. */\r
if( pxTaskToDelete == pxCurrentTCB )\r
{\r
taskEXIT_CRITICAL();\r
\r
/* Force a reschedule if we have just deleted the current task. */\r
- if( xSchedulerRunning != pdFALSE ) \r
+ if( xSchedulerRunning != pdFALSE )\r
{\r
if( ( void * ) pxTaskToDelete == NULL )\r
{\r
{\r
/* The priority change may have readied a task of higher\r
priority than the calling task. */\r
- if( uxNewPriority > uxCurrentPriority ) \r
+ if( uxNewPriority > uxCurrentPriority )\r
{\r
if( pxTask != NULL )\r
{\r
\r
taskENTER_CRITICAL();\r
{\r
- /* Ensure a yield is performed if the current task is being \r
+ /* Ensure a yield is performed if the current task is being\r
suspended. */\r
if( pxTaskToSuspend == pxCurrentTCB )\r
{\r
{\r
xList *pxTemp;\r
\r
- /* Tick count has overflowed so we need to swap the delay lists. \r
- If there are any items in pxDelayedTaskList here then there is \r
+ /* Tick count has overflowed so we need to swap the delay lists.\r
+ If there are any items in pxDelayedTaskList here then there is\r
an error! */\r
pxTemp = pxDelayedTaskList;\r
pxDelayedTaskList = pxOverflowDelayedTaskList;\r
{\r
++uxMissedTicks;\r
\r
- /* The tick hook gets called at regular intervals, even if the \r
+ /* The tick hook gets called at regular intervals, even if the\r
scheduler is locked. */\r
#if ( configUSE_TICK_HOOK == 1 )\r
{\r
return;\r
}\r
\r
+ taskCHECK_FOR_STACK_OVERFLOW();\r
+\r
/* Find the highest priority queue that contains ready tasks. */\r
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )\r
{\r
\r
\r
#if ( INCLUDE_vTaskSuspend == 1 )\r
- { \r
+ { \r
if( xTicksToWait == portMAX_DELAY )\r
{\r
/* Add ourselves to the suspended task list instead of a delayed task\r
#endif\r
/*-----------------------------------------------------------*/\r
\r
-#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxGetStackHighWaterMark == 1 ) )\r
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
+\r
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte )\r
{\r
register unsigned portSHORT usCount = 0;\r
\r
return usCount;\r
}\r
+\r
#endif\r
/*-----------------------------------------------------------*/\r
\r
-#if ( INCLUDE_uxGetStackHighWaterMark == 1 )\r
- unsigned portBASE_TYPE uxGetStackHighWaterMark( void )\r
+#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )\r
+\r
+ unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void )\r
{\r
return usTaskCheckFreeStackSpace( pxCurrentTCB->pxStack );\r
}\r
+\r
#endif\r
/*-----------------------------------------------------------*/\r
\r