Index

Cooperating Sequential Tasks

  1. Introduction
    1. Arduino
    2. Interrupts
  2. Simple Tasks
  3. Multiple Tasks
  4. Communicating Tasks
  5. Communicating Values
  6. Synchronising Tasks
  7. Buffered Communication
  8. Multiple Senders
  9. Conditional Tasks
  10. Transput
  11. Implementation
    1. Common Data
    2. Tasks
    3. task_builder
    4. task
    5. channel
    6. virtual_machine
    7. set
    8. queue
    9. clock
    10. standard
    11. Adjusting Limits
images/13-1.png

Implementation



The multitasking library is available here. The following documentation assumes a basic knowledge of the C++ language used by the Arduino.

The library interface Tasks.h and its implementation Tasks.cpp provide all of the functions and types demonstrated in the previous examples. These are supported by a number of other components. The complete set of source files, each with its own header file, is listed below with a brief description of its purpose. More detailed descriptions can be found in the following sections. Note: All of the declarations of the functions, types, variables and constants that are not exposed by Tasks.h are defined within a private namespace called tasks_system to avoid name conflicts with declarations in Arduino programs using the library.

System Structure Overview

The main components of the system are shown in the diagram below. When tasks are defined during execution of the Arduino setup function, calls to new_task, action, send_to etc, send information to the task_builder component. This saves information in three arrays called code, tasks and channels, which will later be used by a virtual_machine to execute the task definitions. The virtual_machine maintains a queue of active tasks and a set of waiting tasks. Every time the Arduino loop function calls run_system the task at the front of the queue is executed until it has to wait for communication to take place, for a condition to become true, or is paused for some interval. When one of these things happens it is removed from the active_queue and either attached to a channel that is not yet ready to send a signal, or placed in the set of waiting tasks. The virtual_machine periodically checks the waiting_set to see which tasks can resume execution. When a task is ready to resume execution, it is placed at the back of the active_queue to await further execution.

images/13-2.png

System Limits

There are a number of limits built-in to the library implementation. At best, exceeding these limits will result in anomalous program behaviour, as there is no mechanism available within the Arduino for generating error messages that would not conflict with the normal use of hardware features, e.g. serial communication.

• The total number of tasks must be no greater than max_tasks defined in task.h. Set to 10.

• The total number of channels must be no greater than max_channels defined in channel.h. Set to 10.

• The number of actions defined in all tasks, plus the number of parameters passed to these actions, plus the number of tasks must be no greater than code_size defined in virtual_machine.h. Set to 100.

• The numeric values of parameters to action functions such as pause are represented as signed 16-bit integers. This limits the maximum duration of a pause to 32.767 seconds.

The values of the constants defining these limits can be increased at the cost of using more of the Arduino's dynamic RAM. The maximum number of tasks is limited to 16 by the current implementation of the set type described below.

System State

Common Data

Most of the library components need to access to common data describing the state of the tasks being executed. The variables which maintain this state are defined in Tasks.cpp as members of the tasks_system namespace used by all components. These variables are accessed as external variables (C++ extern) when required elsewhere.

Components

Tasks

Provides the functions used to describe tasks in Arduino programs.

task_builder

Stores the information necessary to execute the tasks described in programs. The stored information represents the tasks themselves, the code to be executed by the virtual_machine and details of the channels used for communication.

virtual_machine

Executes tasks based on the code stored by the task_builder. Each task is associated with an index into the stored code. This index serves the purpose of a virtual program counter and keeps track of the next action to be executed by each task.

task

Maintains all the information required to keep track of the current state of each task.

channel

Maintains all the information needed for tasks to communicate with each other.

set

Represents sets of tasks and operations on them.

queue

Represents task queues required for scheduling task execution.

clock

Provides a 1 millisecond clock used to implement the pause action.

standard

Provides some Serial functions, mainly used for debugging purposes.