The tasking library enables your application to employ multiple tasks. Tasks are typically used for processing that may suspend execution while other activities occur. For example, you may have a protocol-processing task, a user-interface task, and a data-acquisition task.

Each task has its own task stack, which is used to store local variables and function-return information. The task stack is also used to store the CPU execution context when the task isn't executing. The CPU execution context of a task varies between machine architectures; it is typically the subset of the CPU register values that enable a task to be descheduled at any point during its execution.

The process of changing the CPU registers from one task to another is termed taskswitching}. Task switching occurs when a CTL function is called, either from a task or from an interrupt service routine (ISR), and there is a runnable task with higher priority than the executing task. Task switching also occurs when there is a runnable task of the same priority as the executing task, if the executing task has exceeded its time-slice period. If you have more than one runnable task of the same priority, the next task (modulo priority) after the executing task is selected. This is sometimes called round-robin scheduling.

There is a single task list and it is kept in priority-sorted order. The task list is updated when tasks are created and deleted, and when their priority changes. The task list is traversed when a CTL function is called that could change the execution state of a task. While the task list is modified or traversed, global interrupts are disabled. Consequently, the length of the interrupt-disable period depends on the number of tasks in the task list, and the priority and type of the task affected by the CTL operation.

If you require a simple, deterministic (sometimes called real-time) system, you should ensure that each task has a unique priority. The task switching will always select the highest-priority task that is runnable.

CTL has a pointer to the executing task. There must always be a task executing; if there isn't, a CTL error is signaled. Typically, there will be an idle task that loops and, perhaps, puts the CPU into power-saving mode.

Global interrupts will be enabled when a task switch occurs, so you can safely call tasking library functions while interrupts are disabled.

Task synchronization and resource allocation

The CTL provides several mechanisms to synchronize execution of tasks, to serialize resource access, and to provide high-level communication.

Note that all task synchronization is priority based, i.e., the highest-priority task that is waiting will be scheduled first.

Timer support

If your application can provide a periodic timer interrupt, you can use the timer facility of the CTL. This facility enables time slicing of equal-priority tasks, allows tasks to delay, and provides a timeout capability when waiting for something. The timer is a software counter that is incremented by your timer interrupt. The counter is typically a millisecond counter, but you can change the timer's increment to reduce the interrupt frequency.

Memory allocation support

The CTL provides a simple memory block allocator that can be used in situations for which the standard C malloc and free functions are either too slow or may block the calling task.

C library support

The CTL provides the functions required of the CrossWorks C library for multi-threading.