The CTL enables your application to have multiple tasks. You will typically use a task when you have some algorithmic or protocol processing that suspend it's execution whilst other activities occur. For example you may have a protocol processing task and a user interface task.
A task (sometimes called a thread) is a CPU execution context which is typically a subset of the CPU register state. When a task switch occurs the CPU execution context is saved on to the stack of the current task, a new task is selected to run and its saved CPU execution context is restored. The process of selecting a new task to run is called task switching or (re)scheduling.
A task has a priority associated with it, the lowest priority is 0 the highest is 255. A task is either executing (the current task) or it is queued in the task list. The task list is kept in priority order with the highest priority task at the head of the list. The current task will always have a priority that is greater than or equal to the first runnable task in the task list.
Task switching can be cooperative or preemptive.
Cooperative task switching occurs when the current task calls a CTL function which checks for rescheduling and the next task ready to run is of the same or higher priority than the current task.
Preemptive task switching occurs when an interrupt service routine calls a CTL function which checks for rescheduling and the next task ready to run is of a higher priority then the current task.
Preemptive task switching can also occur when an interrupt service routine calls a CTL function which checks for rescheduling, time slicing is enabled, the time slice period has been exceeded and the next task ready to run is of the same priority as the current task.
There is one executing task and there must always be a task ready to execute i.e. the task list must have a runnable task queued on it. Typically there will always be an idle task that loops and perhaps puts the CPU into a power save mode. A task on the task list is either runnable or waiting for something (e.g. timeout).
When a task switch occurs global interrupts will be enabled. So you can safely call the tasking library functions with interrupts disabled.
The CrossWorks tasking library provides several mechanisms to synchronize execution of tasks and to serialise resource allocation.
Note that all waits on task synchronization objects are priority based i.e. the highest priority task waiting will be scheduled first.
If your application can provide a periodic timer interrupt (for example one that keeps a watch dog alive) then you can use the timer wait facility of the library. This is a simple software counter that is incremented by your timer interrupt. You can use this to specify a wakeup time and to prevent your program waiting forever for something to happen.
On systems that have programmable interrupt controllers the CTL provides functions that enable you to install interrupt service routines as C functions and associate the required hardware priority to their execution. On systems that have fixed interrupt schemes functions are provided that enable you to create interrupt service routines that co-operate with the CTL.
Tasks can synchronize with interrupt service routines using either event sets, semaphores or message queues. Interrupt service routines are allowed to set (and clear) events in an event set, to signal a semphore and to do a non blocking post to a message queue. Interrupt service routines cannot wait for events, wait for a semaphore or use blocking message queue functions.
The CTL provides a simple memory block allocator that can be used in situations where the standard C malloc and free functions are either too slow or may block the calling task.
The CTL provides a task specific errno as well as exclusion mechanisms to enable usage of malloc/free functions in a multi-tasking envrionment.