Skip to content
Konstantin Khait edited this page Jul 22, 2026 · 1 revision

il2

TASKS

Tasks are sequential programming routines similar to procedures and functions that allow you coding your computing and control algorithms with minimum change, but with a support of parallel execution. In Loviisa OS the tasks shall periodically yield to others otherwise it will capture a control and prevent execution of other tasks and event handlers.

Tasks require special syntax for declaration that simplifies its usage and doesn't need a lot of attention from the application programmer.

Each task has its own context. Context is a set of variables that can be used wherever within the task and cannot be used from outside of it. Local variables shall not be used within the task except really local ones, i.e. variables that are local for a single block like loop counters, intermediate computation data etc. All other data items shall be located in the task context.

Context variables are to be defined between LVS_TASK_CONTEXT_START and LVS_TASK_CONTEXT_END declarations like below:

LVS_TASK_CONTEXT_START(my_task)

int i;

char* string;

LVS_TASK_CONTEXT_END(my_task)

Context items can be accessed from within the task with using following macro: LVS_CTX(member):

LVS_CTX(i) += 1;

for (LVS_CTX(i) = 0; LVS_CTX(i) < 10; LVS_CTX(i)++)

Empty context must be declared if the given task needs no data.

Task contains two sections: initialization that executes once upon the task start and cyclic that continuously repeats all the time while task execution is in progress. The sections is declared consequently as:

LVS_TASK_INIT(task_name)

Content of the task initialization section

LVS_TASK_START(task_name)

Content of the cyclic section

LVS_TASK_END(task_name)

Both sections can access task context elements using LVS_CTX() macro. Cyclic section executes repeatedly, once it achieves LVS_TASK_END it restarts from LVS_TASK_START after yield all events being scheduled by that moment. Therefore if task duration is short enough, an application developer should not take care of how to avoid blocking of the execution and do pre-emption with another task.

Tasks are not started and stopped automatically. To start a task, you must call LVS_TASK_START(task, param); from wherever you need. Task must be started just once, because normally tasks are not re-enterable (potentially tasks not using context data can be re-enterable, but this mode is complex and not recommended). Attempt to start the task that is already started will be ignored. You may get task running status at any time with LVS_IS_TASK_RUNNING(task_name).

If a task shall be launched from the file other than the file where it is defined, use LVS_USE_TASK(task_name) to declare the task.

Parameter, transferred to the task at start is void* pointer and available in the task body using LVS_TASK_PARAM(task_name) macro call. Also a task counts number of loops of its cyclic section, this value is available as LVS_TASK_COUNTER(task_name).

It is recommended to program tasks that never need restart or end of execution. However if task needs to be stopped, it may call LVS_TASK_EXIT(task_name) within its body.

Please be aware that all task management macros can only be used directly between task init - start - end declarations, but not in functions that called by a task.

If you use long loops that takes time in a task, you shall insert LVS_TASK_YIELD(task_name) to the loop body to pass other events and tasks while your loop is executed. Loviisa is using cooperative multitasking, so tasks cannot be switched until LVS_TASK_END or LVS_TASK_YIELD is achieved (or wait primitives are used).

LOOPS

Loop is a simplified form of task that has no context and initialization section. Loop is started with:

LVS_LOOP_START(task_name)

and ended with:

LVS_LOOP_END(task_name)

To launch the loop it is required to call LVS_LOOP_RUN(task_name, param). You should also refer to the loop with LVS_USE_LOOP(task_name) if it is defined in another file or later in C code.

LVS_TASK_PARAM, LVS_TASK_COUNTER and LVS_TASK_EXIT can be used for loops the same way to full size tasks.

In contrast to tasks, loops are basically re-enterable if not using static variables and not protected against being run again while execution. If you want to use loop re-enterable, you shall pass dynamically allocated parameters to it. Loops can return results sending events.

Clone this wiki locally