Introduction to Real Time Systems

Download Report

Transcript Introduction to Real Time Systems

µC/OS-III Tasks
Akos Ledeczi
EECE 354, Fall 2012
Vanderbilt University
Multitasking
• Multiple sequential tasks (threads)
• Creates the illusion of having multiple CPUs
• Pro: Helps in creating modular, better
structured code that is simpler to write and
understand
• Con: Brings in unique problems and hard to
find bugs
Tasks
• Run-to-completion
– Must call OSTaskDel() at the end
• Infinite loop
– Inside the loop it MUST call a RT service (function) to
wait for an event and hence, block. Otherwise, it
would be the only task running (not necessarily, if there was a
higher priority task that becomes ready due to an interrupt. For example,
the idle task does not block. But user tasks should not do this. To do
something during idle time, you can hook into the idle task itself.)
• Call any function
– Reentrant functions
Task Creation
• OSTaskCreate()
• 1: stack
• 2: the OS can initialize the stack
with 0s
• 3: the OS puts the CPU registers
on the stack
• 4: and sets the stack pointer (SP)
to this location (top of the stack)
and saves it in the TCB
• 5: the rest of the TCB (Task
Control Block) is initialized
• OSTaskCreateHook()
• TCB is placed in the Ready list
Task-Resource Interaction
•
•
Code. A regular C function, but
not allowed to return.
Priority.
– Lower number = higher priority
– OS_PRIO_MAX: no of levels
– Multiple tasks at the same
priority are allowed
• CPU registers. As if it had the
CPU all to itself.
• Stack.
– Needed for preemptive kernels.
– Store local variables, function
calls, used by ISRs, etc.
– Context switch
– Allocating the stack
• Global variables. Need
protection!
• IO devices. Need protection!
Stack size
• Manual stack size calculation:
– All function call nesting (return address plus all
arguments plus all local variables)
– All ISR nesting (full CPU context and variables used for
each)
– Multiply by 2 to be safe
– Tedious and unreliable
• Dynamic stack size calculation
– Give tasks large stacks and monitor actual usage:
• Initialize stack with zeros
• An extra low priority task can “walk” the stack and store
highest usage for all other tasks
Stack overflow detection
• Hardware support:
– .StkLimitPtr
– Can be set close to the end of the
stack
– Desired value stored in TCB
– OS context switch mechanism takes
care of setting .StkLimitPtr
corresponding to the new Task
• Software:
– .OSTaskSWHook() for CPUs with no
hardware check
– Checked at context switch only, so
user needs to leave enough slack
Task States (conceptual)
• Dormant: OS does not know
about it (yet or any more)
• Ready: all, but the highest
priority task that are available
for running
• Running: highest priority task
available for running
• Pending: waiting for an event
• Interrupted: ISR (possibly
nested). ISR can call scheduler
(OSIntExit(), so the current task
may be switched out. ISRs are
only allowed to make Post calls.
Task States (actual)
• Delay: task call one of the
delay functions
• Pend timeout: the task only
blocks for a max time limit and
then goes back to ready state
• Suspend: task can suspend
itself (or another task) by
OSTaskSuspend(). The only
way to return from one of the
suspended states is by calling
OSTaskResume(). This creates
four new states.
Task Control Block (TCB)
struct os_tcb {
CPU_STK
*StkPtr;
/* Pointer to current top of stack
*/
void
*ExtPtr;
/* Pointer to user definable data for TCB extension
*/
CPU_STK
*StkLimitPtr;
/* Pointer used to set stack 'watermark' limit
*/
OS_TCB
OS_TCB
*NextPtr;
*PrevPtr;
/* Pointer to next
TCB in the TCB list
/* Pointer to previous TCB in the TCB list
*/
*/
OS_TCB
OS_TCB
*TickNextPtr;
*TickPrevPtr;
OS_TICK_SPOKE
*TickSpokePtr;
/* Pointer to tick spoke if task is in the tick list
*/
CPU_CHAR
*NamePtr;
/* Pointer to task name
*/
CPU_STK
*StkBasePtr;
/* Pointer to base address of stack
*/
OS_TASK_PTR
void
TaskEntryAddr;
*TaskEntryArg;
/* Pointer to task entry point address
/* Argument passed to task when it was created
*/
*/
OS_PEND_DATA
OS_OBJ_QTY
*PendDataTblPtr;
PendDataTblEntries;
/* Pointer to list containing objects pended on
/* Size of array of objects to pend on
*/
*/
/* Timestamp
*/
CPU_TS
TS;
Task Control Block (TCB)
#if OS_MSG_EN > 0u
void
OS_MSG_SIZE
#endif
*MsgPtr;
MsgSize;
#if OS_CFG_TASK_Q_EN > 0u
OS_MSG_Q
MsgQ;
#if OS_CFG_TASK_PROFILE_EN > 0u
CPU_TS
MsgQPendTime;
CPU_TS
MsgQPendTimeMax;
#endif
#endif
#if OS_CFG_FLAG_EN > 0u
OS_FLAGS
OS_OPT
OS_FLAGS
#endif
FlagsPend;
FlagsOpt;
FlagsRdy;
/* Message received
*/
/* Message queue associated with task
*/
/* Time it took for signal to be received
/* Max amount of time it took for signal to be received
*/
*/
/* Event flag(s) to wait on
/* Options (See OS_OPT_FLAG_xxx)
/* Event flags that made task ready to run
*/
*/
*/
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
OS_REG
RegTbl[OS_CFG_TASK_REG_TBL_SIZE];
#endif
/* Task specific registers
*/
Task Control Block (TCB)
OS_SEM_CTR
SemCtr;
#if OS_CFG_TASK_PROFILE_EN > 0u
CPU_TS
SemPendTime;
CPU_TS
SemPendTimeMax;
#endif
#if OS_CFG_TASK_SUSPEND_EN > 0u
OS_NESTING_CTR
SuspendCtr;
#endif
CPU_STK_SIZE
StkSize;
#if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
CPU_STK_SIZE
StkUsed;
CPU_STK_SIZE
StkFree;
#endif
OS_OPT
Opt;
/* Task specific semaphore counter
*/
/* Time it took for signal to be received
/* Max amount of time it took for signal to be received
*/
*/
/* Nesting counter for OSTaskSuspend()
*/
/* Size of task stack (in number of stack elements)
*/
/* Number of stack elements used from the stack
/* Number of stack elements free on
the stack
*/
*/
/* Task options as passed by OSTaskCreate()
*/
Task Control Block (TCB)
OS_TICK
OS_TICK
OS_TICK
TickCtrPrev;
TickCtrMatch;
TickRemain;
OS_TICK
OS_TICK
TimeQuanta;
TimeQuantaCtr;
#if OS_CFG_TASK_PROFILE_EN > 0u
OS_CPU_USAGE
CPUUsage;
OS_CTX_SW_CTR
CtxSwCtr;
CPU_TS
CyclesDelta;
CPU_TS
CyclesStart;
OS_CYCLES
CyclesTotal;
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_TS
IntDisTimeMax;
#endif
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
CPU_TS
SchedLockTimeMax;
#endif
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
DELAY / TIMEOUT
Previous time when task was
ready
Absolute time when task is going to be ready
Number of ticks remaining for a match (updated at ...
... run-time by OS_StatTask()
CPU Usage of task (0-100%)
Number of time the task was switched in
value of OS_TS_GET() - .CyclesStart
Snapshot of cycle counter at start of task resumption
Total number of # of cycles the task has been running
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
/* Maximum interrupt disable time
*/
/* Maximum scheduler lock time
*/
Task Control Block (TCB)
OS_STATE
OS_STATUS
OS_STATE
PendOn;
PendStatus;
TaskState;
/* Indicates what task is pending on
/* Pend status
/* See OS_TASK_STATE_xxx
*/
*/
*/
OS_PRIO
Prio;
/* Task priority (0 == highest)
*/
#if OS_CFG_DBG_EN > 0u
OS_TCB
OS_TCB
CPU_CHAR
#endif
};
*DbgPrevPtr;
*DbgNextPtr;
*DbgNamePtr;
Idle Task
void
{
OS_IdleTask (void *p_arg)
while (DEF_ON) {
CPU_CRITICAL_ENTER();
OSIdleTaskCtr++;
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCtr++;
#endif
CPU_CRITICAL_EXIT();
OSIdleTaskHook();
}
}
• Lowest priority task
• Not blocking
• Hook allows the user to
put the processor in a
low power mode, for
example. (interrupts
typically wake up CPU.)
Tick Task
• Hardware timer interrupts current task
• Tick ISR takes care of hardware and OS related
issues and notifies Tick Task (Post)
• ISR returns, depending on priorities Tick Task
runs eventually. Tick Task usually has relatively
high priority.
Tick Task cont’d.
•
•
Tickwheel:
• stores all tasks waiting
for a time event (delayed
or pending with a
timeout)
• Optimized to make task
handling fast: only one of
the spokes needs to be
looked at at any one time
• List is ordered by
CtrMatch so only first
(few) items needs to be
looked at
Tick Task removes tasks
whose delay (timeout)
expired
Statistics Task
• µC/OS-III can provide run time statistics:
– Overall CPU utilization
– Per task CPU utilization
– Per task stack usage
• OS_CFG_STAT_TASK_EN in os_cfg.h
• Must call OSStatTaskCPUUsageInit() at the
beginning of the first task before creating any
more tasks
• Statistics are stored in each task’s TCB
Timer Task
• Timers are countdown counters that perform a user-specific
action via a callback function
• OS_CFG_TMR_EN in os_cgf.h
• Callback is called from the Timer Task context
• Driven by Tick ISR but typically signaled at a lower rate
ISR Handler Task
•
•
•
•
•
µC/OS-III can defer event posts from ISRs if the OF_CFG_ISR_POST_DEFERRED_EN is set
Used when critical sections are handled by locking/unlocking the scheduler (as opposed to
disabling interrupts)
ISR stores posts in a queue, the ISR Handler Task actually make the posts
Has the highest priority (no other task can have it)
Used to minimize interrupt disable time