next up previous contents
Next: Real-time Kernel in Embedded Up: Development Techniques Previous: Example of State Machine   Contents

Task Scheduler in Embedded System

An application in real-time embedded system can always be broken down into a number of distinctly different tasks. For example,

Each of the tasks can be represented by a state machine. However, implementing a single sequential loop for the entire application can prove to be a formidable task. This is because of the various time constraints in the tasks -- keyboard has to be scanned, display controlled, input channel monitored, etc.

One method of solving the above problem is to use a simple task scheduler. The various tasks are handled by the scheduler in an orderly manner. This produces the effect of simple multitasking with a single processor. A bonus of using a scheduler is the ease of implementing the sleep mode in microcontrollers which will reduce the power consumption dramatically (from mA to $\mu$A). This is important in battery operated embedded systems.

There are several ways of implementing the scheduler -- preemptive or cooperative, round robin or with priority. In a cooperative or non-preemptive system, tasks cooperate with one another and relinquish control of the CPU themselves. In a preemptive system, a task may be preempted or suspended by different task, either because the latter has a higher priority or the time slice of the former one is used up. Round robin scheduler switches in one task after another in a round robin manner whereas a system with priority will switch in the highest priority task.

For many small microcontroller based embedded systems, a cooperative (or non-preemptive), round robin scheduler is adequate. This is the simplest to implement and it does not take up much memory. Ravindra Karnad has implemented such a scheduler for 8051 and other microcontrollers. In his implementation, all tasks must behave cooperatively. A task waiting for an input event thus cannot have infinite waiting loop such as the following:

While (TRUE)
{
	 Check input
	 ...
	}

This will hog processor time and reprieve others of running. Instead, it may be written as:

	If (input TRUE)
	{
	 ...
	}
	Else (timer[i]=100ms)

In this case, task i will check the input condition every 100 ms, set in the associated timer$[$i$]$. When the condition of input is false, other tasks will have a chance to run.

The job of the scheduler is thus rather simple. When there is clock interrupt, all task timers are decremented. The task whose timer reaches 0 will be run. The greatest virtue of the simple task scheduler ready lies in the smallness of the code, which is of course very important in the case of microcontrollers. The code size ranges from 200 to 400 byes.


next up previous contents
Next: Real-time Kernel in Embedded Up: Development Techniques Previous: Example of State Machine   Contents
Chu Suan Ang 2001-12-17