Start
Task
Function
Scheduling
and Timeslice
Task
Context
Task
Control Block
Global
Variables
Memory
Management
API
Assembly
Functions
Give
it a Try
Enhancements
References,
Sources & PDF
TASK
CONTEXT
An important consideration
is how to maintain the tasks context so that
畫xec can return control to a previously stopped task.
Because 畫xec normally regains control through a timer
interrupt, and that interrupt already saves the CPU
states (e.g., the register values) on the stack, it
is sufficient to only save the stack pointer of an
interrupted task at the time the handler was entered.
To resume a task, 畫xec
reloads the stack pointer and uses the ReturnFromInterrupt
instruction to restore control to the stopped task.
From a tasks point of view, a timer interrupt
hits, and some time later, the interrupt handler returns
and execution continues. The fact that other tasks
get a chance to execute while the task is stopped
is invisible to the task.
There is one additional
place where the task context must be savedwhen
a task voluntarily gives up control using the UEXC_Defer
function. In this case, UEXC_Defer constructs an interrupt-stack
frame so that no special case handling is needed to
resume the task.
This scheme doesnt
work with processors using a separate interrupt stack
from the user stack. Also, if a multitasking executive
provides resource-waiting functions (semaphores, mailboxes,
etc.), there are other places where task context must
be saved.
In these scenarios, its
simpler to save the entire CPU context in the task
data structure and not rely on the interrupt stack.
Since 畫xec does not provide resource-waiting functions,
and since most small microcontrollers dont use
a separate interrupt stack, using the interrupt-stack
frame to save the tasks context is fast and
effective.
CODE COMMUNICATION
Most of the 畫xec routines
are written in C. A small number are in assembly,
mostly to manipulate interrupt-stack frames.
The format of passing
arguments between routines is compiler-dependent,
so we opted to use global variables to pass information
between the assembly and C routines (of course, C
routines calling other C routines use the standard
C calling format).
Only two global variables
are needed. There are some minor differences in how
each compiler handles global names. For example, some
compilers prepend an underscore before a global name
if its to be used by an assembly module, but
these differences are easy to handle.
INTERRUPTS
Interrupts must be carefully
enabled and disabled inside 畫xec. If this is done
improperly, unpredictable results occur.
For example, if interrupts
are left enabled while global data structures are
being manipulated, a data structure may be in an inconsistent
state and further accesses in an interrupt handler
will crash the system. Of course, if interrupts are
inadvertently disabled when resuming a task, the timer
interrupt is also disabled and multitasking will stop.
A simple enhancement
is to use the watchdog timer presented in most microcontrollers
to detect these kinds of system-crash errors. However,
you need to have a mechanism for the system to either
restart itself or report the errors.