• No results found

Task Activation and Termination

Chapter 4: Tasks

4.2 Task Activation and Termination

The OSEK/VDX OS provides multiple services through which tasks can be activated, termi-nated, and queried. The first API service, ActivateTask(), was demonstrated in the prior exampleIOSampleKeypad. The prototype for ActivateTask() follows.

StatusType ActivateTask(TaskType task);

The argument passed to this service is the name of the task to be activated as it appears in the OIL configuration file. The OSEK/VDX OS kernel performs the following functions when it is invoked.

1. If the system is operating in extended status mode, the service first checks to make sure that the task being activated is a valid task. If the task is invalid, the service returns the errorE_OS_ID.

2. If the task is currently in the SUSPENDED state, the service moves the task into the READY state. At this point, the scheduler is invoked if the OS is in a preemptive mode. Invocation of the scheduler is discussed in greater detail in “Scheduling” later in this chapter.

3. If the conformance class is level 2 (BCC2 or ECC2) and the task is capable of multiple activations, the service ensures that the maximum number of activations have not been exceeded and the task is not in the SUSPENDED state before a request is queued by the OS for later processing. If the maximum has been exceeded and the system is operating in extended status mode, the E_OS_LIMIT error is returned and the activation is ignored.

4. If the task is an extended task, all of its events are cleared.

5. If the system is operating in standard status mode or the service is successful in extended status mode, E_OK is returned.

This API service routine can be called from a task, an interrupt service routine, or Startu-pHook(). In IOSampleKeypad, shown in Listing 4.1, ActivateTask() is invoked whenever a key is pressed on the keypad, starting the task that processed the key press. The task acti-vated,ProcessKeyPress (Listing 4.3), is in the module cardgame.c.

42

Chapter 4: Tasks

Listing 4.3 Key press processing task.

This task performs the following functions.

1. Determines whether the display needs to be blanked, and blanks it if necessary.

2. Adds the key character to the global buffer.

3. Stores the desired character to the display by activating the next task.

The first two functions use normal C library functions. The third function uses another OSEK/VDX API service, ChainTask().

StatusType ChainTask(TaskType task);

This API service performs a function similar to the combination of ActivateTask() and TerminateTask() (discussed later). When this service completes, the scheduler is run and the next highest priority task is moved to the RUNNING state. This might or might not be the task that was requested in this service. If ChainTask() is invoked in standard status mode, it never returns to the calling task. If it is invoked in extended status mode, the following occurs.

1. If the task name sent as the argument is invalid, the service returns the E_OS_ID error.

2. If too many activations of the task have been requested, the E_OS_LIMIT error is returned.

3. If the calling task still occupies OSEK/VDX resources, the E_OS_RESOURCE error is returned.

TASK(ProcessKeyPress) {

switch(keyValue){

case '#':

if(blankState == TRUE){

strcpy(displayBuffer,"\f");

blankState == FALSE;

} else{

blankState = TRUE;

strcpy(displayBuffer,"#");

} break;

default:

blankState = FALSE;

displayBuffer[0] = keyValue;

displayBuffer[1] = 0;

}

ChainTask(OutputDisplay);

}

Task Activation and Termination

43

This service can only be invoked from a task and cannot be invoked from a hook routine or an interrupt service routine.

In the example routine, ProcessKeyPress adds the value identified as output to the display into a queue and chains OutputDisplay, which sends the characters in the queue to the dis-play. OutputDisplay is shown in Listing 4.4 and is included in dispdrv.c.

Listing 4.4 OutputDisplay task.

OutputDisplay is very specific to the hardware used in this example. In this case, I have an 80-character display arranged as four rows of 20 characters, using a Hitachi HD44780 LCD controller. This task calls two specific functions: PackDisplay() and OutputNewDisplay(). PackDisplay() packs the message into the display buffer, blanks and scrolls the display, and moves the cursor. OutputNewDisplay() sends the entire buffer to the display. These functions are also in dispdrv.c, but they are not discussed here because they are specific to the control-ler used.

When invoked, OutputDisplay flushes the queue filled by the previous task to the display and invokes the API service TerminateTask(), which terminates the task and executes the scheduler to determine which task to run next.

StatusType TerminateTask(void);

When invoked, TerminateTask() performs the following steps.

1. If the system is operating in extended status mode, it checks to see whether an OSEK/VDX resource is still occupied by the task (resources are discussed in a later chapter). If a resource is still occupied, the service returns the E_OS_RESOURCE error. If the system is oper-ating in standard status mode and a resource is still occupied, the behavior is undefined.

2. The service terminates the calling task, frees the microcontroller resources occupied by the task, then invokes the scheduler to select the next task to run.

3. If the termination was successful, this service never returns to the calling task.

TerminateTask() is only available from within a task and cannot be invoked either in a hook routine or during an interrupt service routine.

IMPORTANT: All tasks MUST end in either ChainTask() or TerminateTask(). If a task terminates using a normal C return, the behavior of the system is undefined and will more than likely cause the entire system to reset.

TASK(OutputDisplay) {

PackDisplay(displayBuffer);

OutputNewDisplay();

TerminateTask();

}

44

Chapter 4: Tasks