Go Down

Topic: a_coos - another cooperative OS for Arduino (Read 157 times) previous topic - next topic

akouz

Dear Arduino Fans,


a_coos is yet another simple cooperative OS for Arduino. It is available at GitHub. It is similar to SCoop, but a_coos does not use any assembler code at all. It relies on a standard C library <setjmp.h> for task context switching.

I use cooperative OS of that kind for many years. Recently I ported it to Arduino and tested on Arduino Nano.

a_coos uses Timer0 to create 1 ms time ticks. Tasks release control to OS by macro COOS_DELAY(dly), where dly specifies how many millisecond should pass before OS returns control to the task.

A simple test sketch demonstrate a_coos usage. The sketch consists of two independent tasks, coos_task0() and coos_task1(). During Arduino setup stage those tasks are registered by OS, after that OS scheduler switches control between registered tasks.


Code: [Select]

#include "coos.h"

int led = 13;

// -------------------------------------------------------
// Task 0 sets led OFF every 0.5 sec
// -------------------------------------------------------
void coos_task0(void)
{
  while(1)
  {
    digitalWrite(led, LOW);
    COOS_DELAY(500);          // 500 ms = 0.5 sec
  }
}
// -------------------------------------------------------
// Task 1 sets led ON every 0.650 sec
// -------------------------------------------------------
void coos_task1(void)
{
  COOS_DELAY(100);   
  while(1)
  {
    digitalWrite(led, HIGH);
    COOS_DELAY(650);   
  }
}
// -------------------------------------------------------
// Setup
// -------------------------------------------------------
void setup()
{
  pinMode(led, OUTPUT);
  coos.register_task(coos_task0);
  coos.register_task(coos_task1);
}

// -------------------------------------------------------
// Main loop
// -------------------------------------------------------
void loop()
{
  coos.run_scheduler();  // Coos scheduler is an endless loop itself
}

Robin2

These things emerge from time to time.

I suspect they all use more code cycles to achieve the same effect as the Blink Without Delay concept as illustrated in several things at a time. And they are inevitably less transparent to the user when they don't do what s/he thinks they should.

...R

kowalski

The major difference between Threads and the Blink Without Delay (BWD) pattern is the ability for periodic functions to maintain local state (e.g. stack) and loop without return. The BWD is a busy wait pattern and spins. Correctly constructed thread scheduler should allow power down while waiting for delayed threads.

I would like to see an example for a_coos where the delayed function uses local variable. Right now it looks like the context may be removed on the setjmp/longjmp.

I have done a similar implementation of threads for Cosa with stack allocation and power down by the main thread.
Please see Cosa Nucleo library for more details.

Alternative solutions with very low overhead is ProtoThreads where only the thread state is maintained.

Please see the Cosa Thread and ProtoThread Blink examples for usage pattern.

Cheers!


akouz

There is no problems to use local variables in a_coos. Off course, if you wish to keep content of such a variable intact after suspending to control to kernel then you should declare that variable as static.

Main restriction is that COOS_DELAY(val) must be used only in the task function itself. It is not possible to use it in functions called from the task.

When compare to other approaches, please do not mistake a_coos as a pseudo-OS, such as proto-threads, etc. It is a real operating system, task context is stored when control is released to OS and then restored when OS returns control to the task. But context store/restore is made without a single line of assembler code; a_coos rely on service provided by a standard (but rarely used) C library.  It makes it highly portable too.

Being a real OS, a_coos is extremely simple to grasp and to use. Being a cooperative OS, it is suitable even for crippled microcontrollers, such as PIC16, where preemptive OS cannot be implemented at all.

Robin2

#4
Jun 28, 2015, 01:10 pm Last Edit: Jun 28, 2015, 01:14 pm by Robin2
The BWD is a busy wait pattern and spins. Correctly constructed thread scheduler should allow power down while waiting for delayed threads.
Which uses the most CPU cycles ?

If the thread scheduler allows for power-down does it save its state to EEPROM ?
It would also be possible to do that with BWD.

When compare to other approaches, please do not mistake a_coos as a pseudo-OS, such as proto-threads, etc. It is a real operating system,
For me the fact that the Arduino does NOT have an OS is a major attraction. If you want an OS use a RaspberryPi - which is probably cheaper as well as significantly more capable.


...R

bobcousins

There is no problems to use local variables in a_coos. Off course, if you wish to keep content of such a variable intact after suspending to control to kernel then you should declare that variable as static.
I like it! Very lightweight but also powerful.

Quote
When compare to other approaches, please do not mistake a_coos as a pseudo-OS, such as proto-threads, etc. It is a real operating system, task context is stored when control is released to OS and then restored when OS returns control to the task. But context store/restore is made without a single line of assembler code; a_coos rely on service provided by a standard (but rarely used) C library.  It makes it highly portable too.
Hmm, portable I agree, I think to be "highly portable" it would need to abstract out the use of timer registers specific to AVR.

If I get round to it I will try it on Due or maybe Neutrino if it arrives soon :)

Please don't PM me asking for help. Ask questions in the forum.

Go Up