📄 tasks.c
字号:
/* FreeRTOS V3.2.4 - Copyright (C) 2003-2005 Richard Barry. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA A special exception to the GPL can be applied should you wish to distribute a combined work that includes FreeRTOS, without being obliged to provide the source code for any proprietary components. See the licensing section of http://www.FreeRTOS.org for full details of how and when the exception can be applied. *************************************************************************** See http://www.FreeRTOS.org for documentation, latest information, license and contact details. Please ensure to read the configuration and relevant port sections of the online documentation. ****************************************************************************//*Changes from V1.00: + Call to portRESTORE_CONTEXT has been removed. The first context switch is now performed within sPortStartScheduler().Changes from V1.01: + More use of 8bit data types. + Function name prefixes changed where the data type returned has changed. + configUSE_TRACE_FACILITY is no longer defined by default.Changes from V1.2.0 + Introduced ucTopReadyPriority. This tracks the highest priority ready queue that contains a valid TCB and thus makes the context switch slightly faster. + prvAddTaskToReadyQueue() has been made a macro.Changes from V1.2.6 + Added conditional compilation directives. + Extended API. + Rearranged function order. + Creating a task now causes a context switch if the task being created has a higher priority than the calling task - assuming the kernel is running. + vTaskDelete() now only causes a context switch if the calling task is the task being deleted.Changes from V2.0.0 + Allow the type of the tick count to be 16 or 32 bits. + Introduce xPendingReadyList feature to allow the time interrupts have to be disabled to be minimised. + Remove the #if( INCLUDE_vTaskSuspendAll ) statements. vTaskSuspendAll() is now always included as it is used by the scheduler itself.Changes from V2.1.0 + Bug fix - pxCurrentTCB is now initialised before the call to prvInitializeTaskLists(). Previously pxCurrentTCB could be accessed while null.Changed from V2.1.1 + Change to where lStackSize is declared within sTaskCreate() to prevent compiler warnings with 8051 port.Changes from V2.2.0 + Explicit use of 'signed' qualifier on portCHAR types added. + Changed odd calculation of initial pxTopOfStack value when portSTACK_GROWTH < 0. + Removed pcVersionNumber definition.Changes from V2.5.3 + cTaskResumeAll() modified to ensure it can be called prior to the task lists being initialised.Changes from V2.5.5 + Added API function vTaskDelayUntil(). + Added INCLUDE_vTaskDelay conditional compilation.Changes from V2.6.0 + Updated the vWriteTraceToBuffer macro to always be 4 byte aligned so it can be used on ARM architectures. + tskMAX_TASK_NAME_LEN definition replaced with the port specific configMAX_TASK_NAME_LEN definition. + Removed the call to strcpy when copying across the task name into the TCB. + Added ucTasksDeleted variable to prevent vTaskSuspendAll() being called too often in the idle task.Changes between V3.0.0 and V2.6.1 + When resuming the scheduler a yield is performed if either a tick has been missed, or a task is moved from the pending ready list into a ready list. Previously a yield was not performed on this second condition. + Introduced the type portBASE_TYPE. This necessitates several API changes. + Removed the sUsingPreemption variable. The constant defined in portmacro.h is now used directly. + The idle task can now include an optional hook function - and no longer completes its time slice if other tasks with equal priority to it are ready to run. + See the FreeRTOS.org documentation for more information on V2.x.x to V3.x.x modifications.Changes from V3.1.1 + Modified vTaskPrioritySet() and vTaskResume() to allow these functions to be called while the scheduler is suspended. + Corrected the task ordering within event lists.Changes from V3.2.0 + Added function xTaskGetCurrentTaskHandle().*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "FreeRTOS.h"#include "task.h"/* * Macro to define the amount of stack available to the idle task. */#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE/* * Default a definitions for backwards compatibility with old * portmacro.h files. */#ifndef configMAX_TASK_NAME_LEN #define configMAX_TASK_NAME_LEN 16#endif#ifndef INCLUDE_xTaskGetCurrentTaskHandle #define INCLUDE_xTaskGetCurrentTaskHandle 0#endif#ifndef configIDLE_SHOULD_YIELD #define configIDLE_SHOULD_YIELD 1#endif#if configMAX_TASK_NAME_LEN < 1 #undef configMAX_TASK_NAME_LEN #define configMAX_TASK_NAME_LEN 1#endif/* * Task control block. A task control block (TCB) is allocated to each task, * and stores the context of the task. */typedef struct tskTaskControlBlock{ 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. */ portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ 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. */ signed portCHAR pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ unsigned portSHORT usStackDepth; /*< Total depth of the stack (when empty). This is defined as the number of variables the stack can hold, not the number of bytes. */} tskTCB;/*lint -e956 */volatile tskTCB * volatile pxCurrentTCB = NULL; /* Lists for ready and blocked tasks. --------------------*/static volatile xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */static volatile xList xDelayedTaskList1; /*< Delayed tasks. */static volatile xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */static volatile xList *pxDelayedTaskList; /*< Points to the delayed task list currently being used. */static volatile xList *pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */static volatile xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready queue when the scheduler is resumed. */#if ( INCLUDE_vTaskDelete == 1 ) static volatile xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0;#endif#if ( INCLUDE_vTaskSuspend == 1 ) static volatile xList xSuspendedTaskList; /*< Tasks that are currently suspended. */#endif/* File private variables. --------------------------------*/static unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0;static volatile portTickType xTickCount = ( portTickType ) 0;static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY;static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY;static signed portBASE_TYPE xSchedulerRunning = pdFALSE;static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0;/* Debugging and trace facilities private variables and macros. ------------*//* * The value used to fill the stack of a task when the task is created. This * is used purely for checking the high water mark for tasks. */#define tskSTACK_FILL_BYTE ( 0xa5 )/* * Macros used by vListTask to indicate which state a task is in. */#define tskBLOCKED_CHAR ( ( signed portCHAR ) 'B' )#define tskREADY_CHAR ( ( signed portCHAR ) 'R' )#define tskDELETED_CHAR ( ( signed portCHAR ) 'D' )#define tskSUSPENDED_CHAR ( ( signed portCHAR ) 'S' )/* * Macros and private variables used by the trace facility. */#if ( configUSE_TRACE_FACILITY == 1 ) #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned portLONG ) ( sizeof( unsigned portLONG ) + sizeof( unsigned portLONG ) ) ) static volatile signed portCHAR * volatile pcTraceBuffer; static signed portCHAR *pcTraceBufferStart; static signed portCHAR *pcTraceBufferEnd; static signed portBASE_TYPE xTracing = pdFALSE;#endif/* * Macro that writes a trace of scheduler activity to a buffer. This trace * shows which task is running when and is very useful as a debugging tool. * As this macro is called each context switch it is a good idea to undefine * it if not using the facility. */#if ( configUSE_TRACE_FACILITY == 1 ) #define vWriteTraceToBuffer() \ { \ if( xTracing ) \ { \ static unsigned portBASE_TYPE uxPreviousTask = 255; \ \ if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ { \ if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ { \ uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ *( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) xTickCount; \ pcTraceBuffer += sizeof( unsigned portLONG ); \ *( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) uxPreviousTask; \ pcTraceBuffer += sizeof( unsigned portLONG ); \ } \ else \ { \ xTracing = pdFALSE; \ } \ } \ } \ }#else #define vWriteTraceToBuffer()#endif/* * Place the task represented by pxTCB into the appropriate ready queue for * the task. It is inserted at the end of the list. One quirk of this is * that if the task being inserted is at the same priority as the currently * executing task, then it will only be rescheduled after the currently * executing task has been rescheduled. */#define prvAddTaskToReadyQueue( pxTCB ) \{ \ listSET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ), 0 ); \ if( pxTCB->uxPriority > uxTopReadyPriority ) \ { \ uxTopReadyPriority = pxTCB->uxPriority; \ } \ vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \} /* * Macro that looks at the list of tasks that are currently delayed to see if * any require waking. * * Tasks are stored in the queue in the order of their wake time - meaning * once one tasks has been found whose timer has not expired we need not look * any further down the list. */#define prvCheckDelayedTasks() \{ \register tskTCB *pxTCB; \ \ while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \ { \ if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \ { \ break; \ } \ vListRemove( &( pxTCB->xGenericListItem ) ); \ /* Is the task waiting on an event also? */ \ if( pxTCB->xEventListItem.pvContainer ) \ { \ vListRemove( &( pxTCB->xEventListItem ) ); \ } \ prvAddTaskToReadyQueue( pxTCB ); \ } \} /* * Several functions take an xTaskHandle parameter that can optionally be NULL, * where NULL is used to indicate that the handle of the currently executing * task should be used in place of the parameter. This macro simply checks to * see if the parameter is NULL and returns a pointer to the appropriate TCB. */#define prvGetTCBFromHandle( pxHandle ) ( ( pxHandle == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) pxHandle )/* File private functions. --------------------------------*//* * Utility to ready a TCB for a given task. Mainly just copies the parameters * into the TCB structure. */static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStackDepth, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority );/* * Utility to ready all the lists used by the scheduler. This is called * automatically upon the creation of the first task. */static void prvInitialiseTaskLists( void );/* * The idle task, which as all tasks is implemented as a never ending loop. * The idle task is automatically created and added to the ready lists upon * creation of the first user task. * * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific * language extensions. The equivalent prototype for this function is: * * void prvIdleTask( void *pvParameters ); * */static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );/* * Utility to free all memory allocated by the scheduler to hold a TCB, * including the stack pointed to by the TCB. * * This does not free memory allocated by the task itself (i.e. memory * allocated by calls to pvPortMalloc from within the tasks application code). */#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) ) static void prvDeleteTCB( tskTCB *pxTCB );#endif/* * Used only by the idle task. This checks to see if anything has been placed * in the list of tasks waiting to be deleted. If so the task is cleaned up * and its TCB deleted. */static void prvCheckTasksWaitingTermination( void );/* * Allocates memory from the heap for a TCB and associated stack. Checks the * allocation was successful. */static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );/* * Called from vTaskList. vListTasks details all the tasks currently under * control of the scheduler. The tasks may be in one of a number of lists. * prvListTaskWithinSingleList accepts a list and details the tasks from * within just that list. * * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM * NORMAL APPLICATION CODE. */#if ( configUSE_TRACE_FACILITY == 1 ) static void prvListTaskWithinSingleList( signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -