The scheduler is run whenever a task is not running. It's purpose is to determine which tasks are available to be run and to run them.
This scheduler is structured as a loop, which runs through all of the tasks created by OSCreateTask. For each task, the following pseudocode is performed:
// Check the timeout value if PCBTimeoutVal==0 if PCBCurrentTime==0 Run Task Look at next task // Compare the message mask and message source temp=PCBMessSrc AND PCBMessMask if temp==PCBMessMask Run Task Look at next task // The AND operation has the effect of checking to see if the process // has received messages from AT LEAST the tasks specified in the // message mask For example, if the message mask specified that // the task was waiting on tasks 1 and 2 (0x06) and it received // messages from 1,2, and 3, the AND operations yields // 0x06 (0x06 AND 0x0e), the same as the message mask.
The effect of the scheduler's layout is that timeout takes precedence over messaging. If the task's timeout value is set to any number other than 0, that task becomes eligible to run everytime that number of milliseconds transpires.
Note also that the message source is not cleared when a task is run. Once a task is scheduled, it must run OSGetMessageSrc or OSGetMess to clear the message source byte.Table 1 describes some sample message masks and timeout values, and their effects.
|Table 1: Sample scheduling of tasks|
(For the examples below, assume we are scheduling task 0.)
|30||0xff||Task runs every 30 milliseconds without any consideration of messages|
|0||0x02||Task runs once it receives a message from task 1|
|0||0x0e||Task runs once it receives a message from tasks 1,2, and 3|
|30||0x02||Task runs every 30 milliseconds and whenever it receives a message from task 1|
|0||0xff||Task never runs|
|0||0x00||Task runs everytime the scheduler examines it. Note that this is a way to specify high priority tasks which we want to run at every opportunity.|
Because the scheduler itself takes a certain amount of time to run, a certain portion of the system's time is spent finding runnable tasks. This overhead scales with the number of tasks running and is described in table 2. Conditions under which a task is run are highlighted in red.
|Table 2: Cycle count per task in scheduler loop|
|Timeout in use but not time to run, message mask does not match source yet||23|
|Timeout not in use and message mask does not compare with source||20|
|Timeout not in use, but message mask compares with source||75|
|Timeout in use and time to run||72|
The scheduler does some error checking. Since an error in a real-time system is fatal, all of these errors cause a system halt. The errors are as follows:
Normal tasks have task numbers associated with them, allowing them to send messages. However, ISRs are not real tasks, and do not have task numbers under which to send messages. Two means of passing messages from an ISR to a task are available and are discussed below.Method 1: ISRSendMess
An OS call, ISRSendMess, exists which allows an ISR to send a message. However, in order to use this, a task ID must be designated for the ISR. This task is NOT created with OSCreateTask and must not correspond to the task number of any existing task. The call to ISRSendMess is similar to that for OSSendMess, except that the task number given to the ISR must also be specified. This has the advantage of affecting the PCBMessSrc bytes but has the disadvantage of taking up a task number.Method 2: Shared memory
With the exception of the 144 bytes of OS memory, the SRAM is available to user programs. An area of memory can be designated through which messages are passed.