circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

December 1998, Issue 101

A Minimalist Multitasking Executive


by Richard Man & Christina Willrich
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 task’s 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 task’s 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 saved—when 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 doesn’t 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, it’s 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 don’t use a separate interrupt stack, using the interrupt-stack frame to save the task’s 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 it’s 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.