Task Management Internals

Task States

From a µC/OS-III user point of view, a task can be in any one of five states as shown in the figure below. Internally, µC/OS-III does not need to keep track of the dormant state and the other states are tracked slightly differently. The actual µC/OS-III states will be discussed after a discussion on task states from the user’s point of view. The figure below also shows which µC/OS-III functions are used to move from one state to another. The diagram is actually simplified as state transitions are a bit more complicated than this.

Figure - Five basic states of a task

(1) The Dormant state corresponds to a task that resides in memory but has not been made available to µC/OS-III.

A task is made available to µC/OS-III by calling a function to create the task, OSTaskCreate(). The task code actually resides in code space but µC/OS-III needs to be informed about it.

When it is no longer necessary for µC/OS-III to manage a task, your code can call the task delete function, OSTaskDel()OSTaskDel() does not actually delete the code of the task, it is simply not eligible to access the CPU.

(2) A task is in the Ready state when it is ready-to-run. There can be any number of tasks ready and µC/OS-III keeps track of all ready tasks in a ready list (discussed later). This list is sorted by priority.

(3) The most important ready-to-run task is placed in the Running state. On a single CPU, only one task can be running at any given time.

The task selected to run on the CPU is switched in by µC/OS-III when the application code calls OSStart(), or when µC/OS-III calls either OSIntExit() or OS_TASK_SW().

As previously discussed, tasks must wait for an event to occur. A task waits for an event by calling one of the functions that brings the task to the pending state if the event has not occurred.

(4) Tasks in the Pending state are placed in a special list called a pend-list (or wait list) associated with the event the task is waiting for. When waiting for the event to occur, the task does not consume CPU time. When the event occurs, the task is placed back into the ready list and µC/OS-III decides whether the newly readied task is the most important ready-to-run task. If this is the case, the currently running task will be preempted (placed back in the ready list) and the newly readied task is given control of the CPU. In other words, the newly readied task will run immediately if it is the most important task.

Note that the OSTaskSuspend() function unconditionally blocks a task and this task will not actually wait for an event to occur but in fact, waits until another task calls OSTaskResume() to make the task ready-to-run.

(5) Assuming that CPU interrupts are enabled, an interrupting device will suspend execution of a task and execute an Interrupt Service Routine (ISR). ISRs are typically events that tasks wait for. Generally speaking, an ISR should simply notify a task that an event occurred and let the task process the event. ISRs should be as short as possible and most of the work of handling the interrupting devices should be done at the task level where it can be managed by µC/OS-III. ISRs are only allowed to make “Post” calls (i.e., OSFlagPost()OSQPost()OSSemPost()OSTaskQPost() and OSTaskSemPost()). The only post call not allowed to be made from an ISR is OSMutexPost() since mutexes, as will be addressed later, are assumed to be services that are only accessible at the task level.

As the state diagram indicates, an interrupt can interrupt another interrupt. This is called interrupt nesting and most processors allow this. However, interrupt nesting easily leads to stack overflow if not managed properly.


Internally, µC/OS-III keeps track of task states using the state machine shown in the figure below. The task state is actually maintained in a variable that is part of a data structure associated with each task, the task’s TCB. The task state diagram was referenced throughout the design of µC/OS-III when implementing most of µC/OS-III’s services. The number in parentheses is the state number of the task and thus, a task can be in any one of eight (8) states (see os.h, OS_TASK_STATE_??? ).

Note that the diagram does not keep track of a dormant task, as a dormant task is not known to µC/OS-III. Also, interrupts and interrupt nesting is tracked differently as will be explained further in the text.

This state diagram should be quite useful to understand how to use several functions and their impact on the state of tasks. In fact, I’d highly recommend that the reader bookmark the page of the diagram.

Figure - µC/OS-III’s internal task state machine

(1) A task is in State 0 when a task is ready-to-run. Every task “wants” to be ready-to-run as that is the only way it gets to perform their duties.

(2) A task can decide to wait for time to expire by calling either OSTimeDly() or OSTimeDlyHMSM(). When the time expires or the delay is cancelled (by calling OSTimeDlyResume()), the task returns to the ready state.

(3) A task can wait for an event to occur by calling one of the pend (i.e., wait) functions (OSFlagPend()OSMutexPend()OSQPend()OSSemPend()OSTaskQPend(), or OSTaskSemPend()), and specify to wait forever for the event to occur. The pend terminates when the event occurs (i.e., a task or an ISR performs a “post”), the awaited object is deleted or, another task decides to abort the pend.

(4) A task can wait for an event to occur as indicated, but specify that it is willing to wait a certain amount of time for the event to occur. If the event is not posted within that time, the task is readied, then the task is notified that a timeout occurred. Again, the pend terminates when the event occurs (i.e., a task or an ISR performs a “post”), the object awaited is deleted or, another task decides to abort the pend.

(5) A task can suspend itself or another task by calling OSTaskSuspend(). The only way the task is allowed to resume execution is by calling OSTaskResume(). Suspending a task means that a task will not be able to run on the CPU until it is resumed. If a task suspends itself then it must be resumed by another task.

(6) A delayed task can also be suspended by another task. In this case, the effect is additive. In other words, the delay must complete (or be resumed by OSTimeDlyResume()) and the suspension must be removed (by another task which would call OSTaskResume()) in order for the task to be able to run.

(7) A task waiting on an event to occur may be suspended by another task. Again, the effect is additive. The event must occur and the suspension removed (by another task) in order for the task to be able to run. Of course, if the object that the task is pending on is deleted or, the pend is aborted by another task, then one of the above two condition is removed. The suspension, however, must be explicitly removed.

(8) A task can wait for an event, but only for a certain amount of time, and the task could also be suspended by another task. As one might expect, the suspension must be removed by another task (or the same task that suspended it in the first place), and the event needs to either occur or timeout while waiting for the event.


Task Control Blocks

A task control block (TCB) is a data structure used by kernels to maintain information about a task. Each task requires its own TCB and, for µC/OS-III, the user assigns the TCB in user memory space (RAM). The address of the task’s TCB is provided to µC/OS-III when calling task-related services (i.e., OSTask???() functions). The task control block data structure is declared in os.h as shown in the listing below. Note that the fields are actually commented in os.h, and some of the fields are conditionally compiled based on whether or not certain features are desired. Both are not shown here for clarity.

Also, it is important to note that even when the user understands what the different fields of the OS_TCB do, the application code must never directly access these (especially change them). In other words, OS_TCB fields must only be accessed by µC/OS-III and not the code.

Listing - OS_TCB Data Structure
struct os_tcb {
    CPU_STK             *StkPtr;
    void                *ExtPtr;
    CPU_CHAR            *NamePtr;
    CPU_STK             *StkLimitPtr; 
    OS_TCB              *NextPtr;
    OS_TCB              *PrevPtr;
    OS_TCB              *TickNextPtr;
    OS_TCB              *TickPrevPtr;
    OS_TICK_LIST        *TickListPtr;                   
    CPU_STK             *StkBasePtr;
    OS_TLS               TLS_Tbl[OS_CFG_TLS_TBL_SIZE]
    OS_TASK_PTR          TaskEntryAddr;
    void                *TaskEntryArg;
    OS_TCB              *PendNextPtr;
    OS_TCB              *PendPrevPtr;
    OS_PEND_OBJ         *PendObjPtr;
    OS_STATE             PendOn;
    OS_STATUS            PendStatus;
    OS_STATE             TaskState;
    OS_PRIO              Prio;
    OS_PRIO              BasePrio;
    OS_MUTEX            *MutexGrpHeadPtr;
    CPU_STK_SIZE         StkSize;
    OS_OPT               Opt;
    CPU_TS               TS;
    CPU_INT08U           SemID;
    OS_SEM_CTR           SemCtr;
    OS_TICK              TickRemain;
    OS_TICK              TickCtrPrev;
    OS_TICK              TimeQuanta;
    OS_TICK              TimeQuantaCtr;
    void                *MsgPtr;
    OS_MSG_SIZE          MsgSize;
    OS_MSG_Q             MsgQ;
    CPU_TS               MsgQPendTime;
    CPU_TS               MsgQPendTimeMax;
    OS_REG               RegTbl[OS_TASK_REG_TBL_SIZE];
    OS_FLAGS             FlagsPend;
    OS_FLAGS             FlagsRdy;
    OS_OPT               FlagsOpt;
    OS_MON_DATA          MonData;
    OS_NESTING_CTR       SuspendCtr;
    OS_CPU_USAGE         CPUUsage;
    OS_CPU_USAGE         CPUUsageMax;
    OS_CTX_SW_CTR        CtxSwCtr;
    CPU_TS               CyclesDelta;
    CPU_TS               CyclesStart;
    OS_CYCLES            CyclesTotal;
    OS_CYCLES            CyclesTotalPrev;
    CPU_TS               SemPendTime;
    CPU_TS               SemPendTimeMax;
    CPU_STK_SIZE         StkUsed;
    CPU_STK_SIZE         StkFree;
    CPU_TS               IntDisTimeMax;
    CPU                  SchedLockTimeMax;
    OS_TCB               DbgPrevPtr;
    OS_TCB               DbgNextPtr;
    CPU_CHAR             DbgNamePtr;
    CPU_INT08U           TaskID;
};


.StkPtr

This field contains a pointer to the current top-of-stack for the task. µC/OS-III allows each task to have its own stack and each stack can be any size. .StkPtr should be the only field in the OS_TCB data structure accessed from assembly language code (for the context-switching code). This field is therefore placed as the first entry in the structure making access easier from assembly language code (it will be at offset zero in the data structure).

.ExtPtr

This field contains a pointer to a user-definable data area used to extend the TCB as needed. This pointer is provided as an argument passed in OSTaskCreate(). This pointer is easily accessible from assembly language since it always follows the .StkPtr. .ExtPtr can be used to add storage for saving the context of a FPU (Floating-Point Unit) if the processor you are using has a FPU.

.NamePtr

This pointer allows a name (an ASCII string) to be assigned to each task. Having a name is useful when debugging, since it is user friendly compared to displaying the address of the OS_TCB. Storage for the ASCII string is assumed to be in user space, either in code memory (ASCII string declared as a const) or in RAM.

.StkLimitPtr

The field contains a pointer to a location in the task’s stack to set a watermark limit for stack growth and is determined from the value of the “stk_limit” argument passed to OSTaskCreate(). Some processors have special registers that automatically check the value of the stack pointer at run-time to ensure that the stack does not overflow. .StkLimitPtr may be used to set this register during a context switch. Alternatively, if the processor does not have such a register, this can be “simulated” in software. However, this is not as reliable as a hardware solution. If this feature is not used then you can set the value of “stk_limit” can be set to 0 when calling OSTaskCreate(). See also Detecting Task Stack Overflows).

.NextPtr and .PrevPtr

These pointers are used to doubly link OS_TCBs in the ready list. A doubly linked list allows OS_TCBs to be quickly inserted and removed from the list.

.TickNextPtr and .TickPrevPtr

These pointers are used to doubly link OS_TCBs in the list of tasks waiting for time to expire or to timeout from pend calls. Again, a doubly linked list allows OS_TCBs to be quickly inserted and removed from the list.

.TickListPtr

This pointer points to one of two tick lists: either the list of tasks delayed waiting for time to expire (OSTickListDly) or tasks pending on an object with a timeout (OSTickListTimeout). This field is used to easily remove the OS_TCB from the list.

.StkBasePtr

This field points to the base address of the task’s stack. The stack base is typically the lowest address in memory where the stack for the task resides. A task stack is declared as follows:

CPU_STK MyTaskStk[???];

CPU_STK is the data type you must use to declare task stacks and ??? is the size of the stack associated with the task. The base address is always &MyTaskStk[0].

.TLS_Tbl[]

This field typically contains an array of pointers and is used by compilers for thread safety as described in Chapter 20, “Thread Safety of the Compiler’s Run-Time Library”).

.TaskEntryAddr

This field contains the entry address of the task. As previously mentioned, a task is declared as shown below and this field contains the address of MyTask.

void MyTask (void *p_arg);

.TaskEntryArg

This field contains the value of the argument that is passed to the task when the task starts. As previously mentioned, a task is declared as shown below and this field contains the value of p_arg.

void MyTask (void *p_arg);

.PendNextPtr and .PendPrevPtr

These two pointers are used to doubly link the OS_TCB in a wait list for a kernel object such as a semaphore, event flag group, mutex or message queue.  This is further described in Chapter 10, “Pend Lists”.

.PendObjPtr

Is a pointer to the kernel object pended on.  This is further described in Chapter 10, “Pend Lists”.
 

.PendOn

This field indicates what the task is pending on and contains one of the following values declared in os.h:

OS_TASK_PEND_ON_NOTHING
OS_TASK_PEND_ON_FLAG
OS_TASK_PEND_ON_TASK_Q
OS_TASK_PEND_ON_MUTEX
OS_TASK_PEND_ON_Q
OS_TASK_PEND_ON_SEM
OS_TASK_PEND_ON_TASK_SEM
OS_TASK_PEND_ON_COND_VAR 

.PendStatus

This field indicates the outcome of a pend and contains one of the values declared in os.h:

OS_STATUS_PEND_OK
OS_STATUS_PEND_ABORT
OS_STATUS_PEND_DEL
OS_STATUS_PEND_TIMEOUT
 

.TaskState

This field indicates the current state of a task and contains one of the eight (8) task states that a task can be in. These states are declared in os.h:

OS_TASK_STATE_RDY
OS_TASK_STATE_DLY
OS_TASK_STATE_PEND
OS_TASK_STATE_PEND_TIMEOUT
OS_TASK_STATE_SUSPENDED
OS_TASK_STATE_DLY_SUSPENDED
OS_TASK_STATE_PEND_SUSPENDED
OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED
 

.Prio

This field contains the current priority of a task. .Prio is a value between 0 and OS_CFG_PRIO_MAX-1. In fact, the idle task is the only task at priority OS_CFG_PRIO_MAX-1.

.BasePrio

This field contains the base priority of a task. .BasePrio is a value between 0 and OS_CFG_PRIO_MAX-1. This field is used to correctly propagate mutex owner priorities to prevent priority inversion.

.MutexGrpHeadPtr

This field is a pointer to a list of mutexes that this task owns.

.StkSize

This field contains the size (in number of CPU_STK elements) of the stack associated with the task. Recall that a task stack is declared as follows:

CPU_STK MyTaskStk[???];

.StkSize is the number of elements in the above array.

.Opt

This field saves the “options” passed to OSTaskCreate() when the task is created as shown below. Note that task options are additive.

OS_OPT_TASK_NONE
OS_OPT_TASK_STK_CHK
OS_OPT_TASK_STK_CLR
OS_OPT_TASK_SAVE_FP

.PendDataTblEntries

This field works with the .PendDataTblPtr and indicates the number of objects a task is pending on at the same time.

.TS

This field is used to store a “time stamp” of when an event that the task was waiting on occurred. When the task resumes execution, this time stamp is returned to the caller.

.SemID

This field is used by third-party tools such TraceAlyzer by Percepio.

.SemCtr

This field contains a semaphore counter associated with the task. Each task has its own built-in semaphore. An ISR or another task can signal a task using this semaphore. .SemCtr is therefore used to keep track of how many times the task is signaled. .SemCtr is used by OSTaskSem???() services.

.TickRemain

This field contains the number of ticks remaining before the task is removed from either the delayed or timeout list. As of V3.04.00, the value of this field is relative (it used to be absolute) since these lists are now implemented as delta-lists. In other words, this field does not contain absolute time remaining until the delay or timeout expires.

.TickCtrPrev

This field is used to keep track of the previous value of OSTickCtr in order to be able to implement the periodic mode for OSTimeDly().

.TimeQuanta and .TimeQuantaCtr

These fields are used for time slicing. When multiple tasks are ready-to-run at the same priority, .TimeQuanta determines how much time (in ticks) the task will execute until it is preempted by µC/OS-III so that the next task at the same priority gets a chance to execute. .TimeQuantaCtr keeps track of the remaining number of ticks for this to happen and is loaded with .TimeQuanta at the beginning of the task’s time slice.

.MsgPtr

When a message is sent to a task, this field contains the message received. This field only exists in a TCB if message queue services (OS_CFG_Q_EN is set to DEF_ENABLED in os_cfg.h), or task message queue services, are enabled (OS_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg.h) at compile time.

.MsgSize

When a message is sent to a task, this field contains the size (in number of bytes) of the message received. This field only exists in a TCB if message queue services (OS_CFG_Q_EN is set to DEF_ENABLED in os_cfg.h), or task message queue services, (OS_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg.h) are enabled at compile time.

.MsgQ

µC/OS-III allows tasks or ISRs to send messages directly to tasks. Because of this, a message queue is actually built into each TCB. This field only exists in a TCB if task message queue services are enabled at compile time (OS_CFG_TASK_Q_EN is set to DEF_ENABLED in os_cfg.h). .MsgQ is used by the OSTaskQ???() services.

.MsgQPendTime

This field contains the amount of time it took for a message to arrive. When OSTaskQPost() is called, the current time stamp is read and stored in the message. When OSTaskQPend() returns, the current time stamp is read again and the difference between the two times is stored in this variable. A debugger or µC/Probe can be used to indicate the time taken for a message to arrive by displaying this field.

This field is only available if setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg.h.

.MsgQPendTimeMax

This field contains the maximum amount of time it takes for a message to arrive. It is a peak detector of the value of .MsgQPendTime. The peak can be reset by calling OSStatReset().

This field is only available if setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg.h.

.RegTbl[]

This field contains a table of “registers” that are task-specific. These registers are different than CPU registers. Task registers allow for the storage of such task-specific information as task ID, “errno” common in some software components, and more. Task registers may also store task-related data that needs to be associated with the task at run time. Note that the data type for elements of this array is OS_REG, which can be declared at compile time to be nearly anything. However, all registers must be of this data type. This field only exists in a TCB if task registers are enabled at compile time (OS_CFG_TASK_REG_TBL_SIZE is greater than 0 in os_cfg.h).

.FlagsPend

When a task pends on event flags, this field contains the event flags (i.e., bits) that the task is pending on. This field only exists in a TCB if event flags services are enabled at compile time (OS_CFG_FLAG_EN is set to DEF_ENABLED in os_cfg.h).

.FlagsRdy

This field contains the event flags that were posted and that the task was waiting on. In other words, it allows a task to know which event flags made the task ready-to-run. This field only exists in a TCB if event flags services are enabled at compile time (OS_CFG_FLAG_EN is set to DEF_ENABLED in os_cfg.h).

.FlagsOpt

When a task pends on event flags, this field contains the type of pend (pend on any event flag bit specified in .FlagsPend or all event flag bits specified in .FlagsPend). This field only exists in a TCB if event flags services are enabled at compile time (OS_CFG_FLAG_EN is set to DEF_ENABLED in os_cfg.h). There can be up to eight main values as shown below plus add-on options. Possible values are:

OS_OPT_PEND_FLAG_CLR_ALL
OS_OPT_PEND_FLAG_CLR_ANY
OS_OPT_PEND_FLAG_CLR_AND
OS_OPT_PEND_FLAG_CLR_OR
OS_OPT_PEND_FLAG_SET_ALL
OS_OPT_PEND_FLAG_SET_ANY
OS_OPT_PEND_FLAG_SET_AND
OS_OPT_PEND_FLAG_SET_OR

You can also ‘add’ OS_OPT_PEND_FLAG_CONSUME and either OS_OPT_PEND_BLOCKING or OS_OPT_PEND_NON_BLOCKING to the above options.

.MonData

Monitor data associated with a task.

.SuspendCtr

This field is used by OSTaskSuspend() and OSTaskResume() to keep track of how many times a task is suspended. Task suspension can be nested. When .SuspendCtr is 0, all suspensions are removed. This field only exists in a TCB if task suspension is enabled at compile time (OS_CFG_TASK_SUSPEND_EN is set to DEF_ENABLED in os_cfg.h).

.CPUUsage

This field is computed by OS_StatTask() if OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg.h. .CPUUsage contains the CPU usage of a task in percent (0 to 100%). As of version V3.03.00, .CPUUsage is multiplied by 100. In other words, 10000 represents 100.00%.

.CPUUsageMax

This field contains the maximum (i.e., peak detector) CPU usage in percentage for the task and is only available if setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg.h.

This field is computed by OS_StatTask(). As of version V3.03.00, .CPUUsageMax represents percentage multiplied by 100. In other words, 10000 represents 100.00%.

The peak can be reset by calling OSStatReset().

.CtxSwCtr

This field keeps track of how often the task has executed (not how long it has executed). This field is generally used by debuggers or run-time monitors to see if a task is executing (the value of this field would be non-zero and would be incrementing). The field is enabled at compile time when OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg.h.

.CyclesDelta

.CyclesDelta is computed during a context switch and contains the value of the current time stamp (obtained by calling OS_TS_GET()) minus the value of .CyclesStart. This field is generally used by debuggers or a run-time monitor to see how long a task had control of the CPU until it got switched out. The field is enabled at compile time when OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg.h.

.CyclesStart

This field is used to measure how long a task had control of the CPU. .CyclesStart is updated when µC/OS-III performs a context switch. .CyclesStart contains the value of the current time stamp (it calls OS_TS_GET()) when a task is switched-in. The field is enabled at compile time when OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg.h.

.CyclesTotal

This field accumulates the value of .CyclesDelta, so it contains the total execution time of a task during a set period of time. .CyclesTotal is used by OS_StatTask() to determine CPU usage on a per-task basis. This is typically a 32-bit value because of the accumulation of cycles over time. On the other hand, using a 64-bit value ensures that we can accumulate CPU cycles for almost 600 years even if the CPU is running at 1 GHz! Of course, it’s assumed that the compiler supports 64-bit data types. The field is enabled at compile time when OS_CFG_TASK_PROFILE_EN is set to DEF_ENABLED in os_cfg.h.. .CyclesTotal is used by OS_StatTask() to determine CPU usage on a per-task basis.

.SemPendTime

This field contains the amount of time taken for the semaphore to be signaled. When OSTaskSemPost() is called, the current time stamp is read and stored in the OS_TCB (see .TS). When OSTaskSemPend() returns, the current time stamp is read again and the difference between the two times is stored in this variable. This field can be displayed by a debugger or µC/Probe to indicate how much time it took for the task to be signaled.

This field is only available when setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg.h.

.SemPendTimeMax

This field contains the maximum amount of time it took for the task to be signaled. It is a peak detector of the value of .SemPendTime. The peak can be reset by calling OSStatReset().

This field is only available if setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg.h.

.StkUsed and .StkFree

µC/OS-III is able to compute (at run time) the amount of stack space a task actually uses and how much stack space remains. This is accomplished by a function called OSTaskStkChk(). Stack usage computation assumes that the task’s stack is “cleared” when the task is created. In other words, when calling OSTaskCreate(), it is expected that the following options be specified: OS_TASK_OPT_STK_CLR and OS_TASK_OPT_STK_CHK. OSTaskCreate() will then clear all the RAM used for the task’s stack.

µC/OS-III provides an internal task called OS_StatTask() that checks the stack of each of the tasks at run-time. OS_StatTask() typically runs at a low priority so that it does not interfere with the application code. OS_StatTask() saves the value computed for each task in the TCB of each task in these fields, which represents the maximum number of stack bytes used and the amount of stack space still unused by the task. These fields only exist in a TCB if the statistic task is enabled at compile time (OS_CFG_STAT_TASK_STK_CHK_EN is set to DEF_ENABLED in os_cfg.h).

.IntDisTimeMax

This field keeps track of the maximum interrupt disable time of the task. The field is updated only if µC/CPU supports interrupt disable time measurements. This field is available only if setting OS_CFG_TASK_PROFILE_EN to DEF_ENABLED in os_cfg.h and µC/CPU’s CPU_CFG_INT_DIS_MEAS_EN is defined in cpu_cfg.h.

.SchedLockTimeMax

The field keeps track of the maximum scheduler lock time of the task. In other words, the maximum amount of time the task locks the scheduler.

This field is available only if you set OS_CFG_TASK_PROFILE_EN to DEF_ENABLED and OS_CFG_SCHED_LOCK_TIME_MEAS_EN is set to DEF_ENABLED in os_cfg.h.

.DbgNextPtr

This field contains a pointer to the next OS_TCB in a doubly linked list of OS_TCBs. OS_TCBs are placed in this list by OSTaskCreate(). This field is only present if OS_CFG_DBG_EN is set to DEF_ENABLED in os_cfg.h.

.DbgPrevPtr

This field contains a pointer to the previous OS_TCB in a doubly linked list of OS_TCBs. OS_TCBs are placed in this list by OSTaskCreate(). This field is only present if OS_CFG_DBG_EN is set to DEF_ENABLED in os_cfg.h.

.DbgNamePtr

This field contains a pointer to the name of the object that the task is pending on when the task is pending on either an event flag group, a semaphore, a mutual exclusion semaphore or a message queue. This information is quite useful during debugging and thus, this field is only present if OS_CFG_DBG_EN is set to DEF_ENABLED in os_cfg.h.

.TaskID

This field is used by third-party tools such as TraceAlyzer by Percepio.