Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« on: June 27, 2012, 05:19:50 am » |
leOS, standing for little embedded Operating System, is a scheduler/taskmanager (a prototype of an OS) for Arduino boards and Atmel microcontrollers that can manage background tasks. leOS can start new tasks, pause and resume them and delete them too. All is done using a scheduler that can start tasks without the partecipation of the user so that the tasks will appear trasparents at the main loop. To be honest, it should more correct to say that leOS is actually something that is halfway a simple prototype of an real-time operating system (RTOS) and a scheduler. In fact it doesnt have the methods to give a task a tick of time to run itself and a preemptive sistem to stop them, freeze their state and resume them in a later moment; but it’s something that is more complex and efficient of several other schedulers that just use millis() to schedule when launch a task because i.e. leOS isn’t affected by the use of delay() in the main loop. It uses an interrupt driven scheduler (based on an 8-bit timer of the micro, usually Timer 2) that checks is time has come to start an active task. The user can choose the interval time from 1 to 3600000 ms (1 hour at the moment, the max value can be changed). The library offers 4 methods to manage tasks: addTask(function, interval) pauseTask(function) restartTask(function) removeTask(function) addTasK add the "function" in the scheduler with interval "interval". pauseTask and restartTask halts and resume the execution of a task, removeTask removes a task from the scheduler. The library should run on several micros albeit it has been tested only on Arduino/Atmega328 at the moment. More info and the code are available here: http://www.leonardomiliani.com/?p=516&lang=enleOS is at a very early stage, comments, suggestions and critics are welcome  EDIT: a stable version is attached at this post EDIT2: if someone has found this lib usefull,I publish for him the new version 0.1.1, that let the user chooses between 32-bit & 64-bit counters (the first ones consume much less Flash memory), it's compatible with Atmega32U4 (Arduino Leonardo), can manage one-time tasks, can modify a running task. EDIT3: leOS is now updated to version 0.1.3. I've introduced the ability to add a paused task at the scheduler, so that it won't start running immediately after adding. This is useful i.e. if your task drives something like a LED or a transistor and you want to choose the right moment to start the action. So the new sintax of the method addTask is now as follow: addTask(function, interval[, status]); with status that can be: PAUSED: to add a task in paused mode, so that it won't start until the user won't use the restartTask() method; SCHEDULED (default option): a task that start running immediately ONETIME: a task that will have to be run only once Thank you for your feedback. N.B.: starting from v. 0.1.3 the library will be available only from my web site, due to the fact that in this manner I can keep track of the whole number of downloads
|
|
|
|
« Last Edit: September 16, 2012, 04:44:19 am by leo72 »
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 249
Posts: 16579
Available for Design & Build services
|
 |
« Reply #1 on: June 27, 2012, 03:09:07 pm » |
So one would do things like read buttons, watch the state of data, etc. and then call one of the functions to make some recurring task (or one-time tasks too I suppose) occur/stop occurring, etc?
|
|
|
|
|
Logged
|
|
|
|
|
Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« Reply #2 on: June 27, 2012, 03:17:01 pm » |
Yes, I've designed it to be indipendent so it can run tasks in the background without interfering with the main loop. If you want to see more clearly what leOS can do, try the sketch with 3 LEDs. You'll see that a LED is driven by the main loop, the other 2 are flashed by 2 indipendent tasks. In the main loop there's also a piece of code that every 10 seconds pauses a task and then resumes it again. //include the OS #include "leOS.h"
leOS myOS; //create a new istance of the class leOS
//variabiles to control the LEDs byte led1Status = 0; byte led2Status = 0; byte led3Status = 0; const byte LED1 = 7; const byte LED2 = 8; const byte LED3 = 9; byte counter = 10; char direction = -1;
//program setup void setup() { myOS.begin(); //initialize the scheduler pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); //add the tasks at the scheduler myOS.addTask(flashLed1, 600); myOS.addTask(flashLed2, 350); }
//main loop void loop() { digitalWrite(LED2, led2Status); led2Status ^= 1; delay(1000); //every 10 secs pause/restart the second task counter += direction; if (counter == 0) { myOS.pauseTask(flashLed1); //pause the task direction = 1; } if (counter == 10) { myOS.restartTask(flashLed1); //restart the task direction = -1; } }
//first task void flashLed1() { led1Status^=1; digitalWrite(LED1, led1Status); }
//second task void flashLed2() { led3Status^=1; digitalWrite(LED3, led3Status); }
Let me show you another example. This is the sketch BlinkWithoutMillis (funny name, isn't it  ): //include the OS #include "leOS.h"
leOS myOS; //create a new istance of the class leOS
//variabiles to control the LEDs byte led1Status = 0; const byte LED1 = 13;
//program setup void setup() { myOS.begin(); //initialize the scheduler pinMode(LED1, OUTPUT); //add the tasks at the scheduler myOS.addTask(flashLed1, 1000); }
//main loop void loop() { //empty }
//flashing task void flashLed1() { led1Status^=1; digitalWrite(LED1, led1Status); }
You can see that the main loop doesn't contain ANY code, by the way the led on the thirtheen pin will flash every 1 second.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 2
|
 |
« Reply #3 on: July 03, 2012, 10:50:04 am » |
Really looks useful to me. It might be better to rename it to a taskmanager? Or can we expect more functionality soon? edit: What I'm trying to say is, an abstract layer like this for timer interrupts can be quite useful for the beginners. Will definetly check it out myself as well.
|
|
|
|
« Last Edit: July 03, 2012, 11:14:08 am by Riemer »
|
Logged
|
|
|
|
|
Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« Reply #4 on: July 03, 2012, 12:15:51 pm » |
Thanks, Riemer, for your appreciation  It isn't a real OS, I know... But more sophisticated than other schedulers or taskmanagers that use millis(). And it's simpler than an [RT]OS that store and restore the task's status into the stack. I chose leOS because it's a pun with my nick, leo  And maybe there could be some improvements, who knows about that? BTW, here is version 0.1.0. It's fully compatible with Arduino Leonardo and its Atmega32U4. Moreover, leOS 0.1.0 supports one-time tasks (a task that should be executed only 1 time and then removed from the scheduler) and the ability to modify the interval and the type of the task. Info on the README file, and more examples in the package.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 4
Posts: 873
|
 |
« Reply #5 on: July 09, 2012, 06:11:21 pm » |
Technically speacking this is a "IO thin-callbacks scheduler".
this project may be interesting as an easy demonstration of "IO Callback function (1) scheduling" performed into FIFO way, extremely easy to understand and extremely short in his implementation: it sounds good for arduino =P
(1) what Leo is calling "task" is much more similar to a "IO callback function", a thin thread of code which, if it invoked, will try to put or to get any chunk of bytes on or from some IO-port, performing its job without requiring any additional structure.
|
|
|
|
|
Logged
|
|
|
|
|
Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« Reply #6 on: July 12, 2012, 03:27:58 pm » |
this project may be interesting as an easy demonstration of "IO Callback function (1) scheduling" performed into FIFO way, extremely easy to understand and extremely short in his implementation: it sounds good for arduino =P
Thank you for your appreciation
|
|
|
|
|
Logged
|
|
|
|
|
Rapa Nui
Offline
God Member
Karma: 17
Posts: 915
Pukao hats cleaning services
|
 |
« Reply #7 on: July 12, 2012, 04:17:47 pm » |
Hi, nice effort! I've seen the code - and let me kindly ask you following:
1. why we need to deal with float in: //set the initial value of the counter depending on the prescaler _starter = 256 - (int)((float)F_CPU * 0.001 / prescaler); would not be better to do it as #define _starter 256-F_CPU/1000/prescaler or something like that? 2. the clock limitation (1,4,8,16MHz) - that is related to point 1. only, so when I'll find a good _starter (in order to get 1ms timer interrupt) I can use ie 22.11MHz as well, I guess 3. would it be possible to use it outside the arduino environment as well? P.
|
|
|
|
« Last Edit: July 12, 2012, 04:41:17 pm by pito »
|
Logged
|
|
|
|
|
Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« Reply #8 on: July 13, 2012, 06:27:36 am » |
Hi, nice effort! I've seen the code - and let me kindly ask you following:
1. why we need to deal with float in: //set the initial value of the counter depending on the prescaler _starter = 256 - (int)((float)F_CPU * 0.001 / prescaler); would not be better to do it as #define _starter 256-F_CPU/1000/prescaler or something like that?
The basic core of leOS (the management of Timer 2) derives from another project of mine, swRTC, a library to implement a software RTC in an Atmel MCU using only a timer. That code was inspired by MsTimer library, from which I initially studied and replicated the formulas to computer the timer prescaler and other things. Your notice is interesting, no need to use floats there  2. the clock limitation (1,4,8,16MHz) - that is related to point 1. only, so when I'll find a good _starter (in order to get 1ms timer interrupt) I can use ie 22.11MHz as well, I guess
Yeah. I just put several checks to get an initial value for the timer that could give 1 overflow per millisecond. But, due to the fact that usually internal oscillators or external resonators are not as precise as their nominal clock, I should find a formula that could try to reach the nearest value to obtain 1 overflow/ms. 3. would it be possible to use it outside the arduino environment as well? P.
If you want to know if the library can be compiled inside other IDEs the answer is: I don't know. At the moment I only use the Arduino IDE, so the library has been written using parts from the Arduino core. But I think that you could convert it to be Arduino IDE indipendent: the timer's setting is made using directly the MCU's registers, I think there a just few things to check that could not work
|
|
|
|
|
Logged
|
|
|
|
|
Buena Vista, CO
Offline
Full Member
Karma: 0
Posts: 157
Arduino rocks
|
 |
« Reply #9 on: August 26, 2012, 01:39:38 pm » |
This is really helpful! however the ONETIME keyword does not work. I'm starting task1 to happen every two seconds. Task2 is onetime and I restart is each time task1 happens. However, task2 happens continually.
Jim
|
|
|
|
|
Logged
|
8000ft above the average
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 21
|
 |
« Reply #10 on: August 26, 2012, 04:26:24 pm » |
Looks cool. I was looking at your source and wondering: - Why don't you make a 'task' struct. That would be a more intuitive approach in your library because you would only need one array instead of four or five distinct arrays for each task.
- Why don't you allocate the array(s) to dynamic memory so that you can resize it in addTask() (and possibly removeTask()) as necessary. Is there a good reason to be limited to 9 tasks?
- In your source there are two places where you slide all of the array elements over to fill in a gap (in removeTask() and ISR() interrupt handler when cleaning out one time functions). I recommend you either break the common code out into a common function or just call removeTask() from ISR(). It will make your code easier to read and it will do magical things to your code size.
- I see that you declare
const uint8_t ONETIME=2; const uint8_t SCHEDULED=1;
inside your header, but you never actually bother to use them anywhere in the code. Better than arbitrary constant ints would be to use an enum, that way using the name in place of the raw integer is enforced by the compiler.
|
|
|
|
|
Logged
|
|
|
|
|
Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« Reply #11 on: August 30, 2012, 09:17:30 am » |
This is really helpful! however the ONETIME keyword does not work. I'm starting task1 to happen every two seconds. Task2 is onetime and I restart is each time task1 happens. However, task2 happens continually.
Jim
I apologize if I answer your question only today but I forgot to follow this thread  Can you provide the sketch you're using? Which platoform are you using? Which version of the Arduino IDE? Thank you for you feedback. EDIT: I found a little bug in the management of onetime pads... can you try the new version 0.1.2? http://www.leonardomiliani.com/?p=516&lang=en
|
|
|
|
« Last Edit: August 30, 2012, 09:57:48 am by leo72 »
|
Logged
|
|
|
|
|
Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« Reply #12 on: August 30, 2012, 09:25:56 am » |
@runnerup: I appreciate your comments. This is a kind of pre-stable release. leOS works and is sufficiently stable and usable for using it in everyday's sketches, but it can be improved in a lot of thing. My wills are to review the leOS source to improve it, as soon as possibile.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 1
Posts: 167
|
 |
« Reply #13 on: September 06, 2012, 06:09:13 am » |
Hi, I haven´t still had time to look at the code, but i still have two questions. - Is LeOS able to keep up with realtime, does it have any kind of RTC feature?
- Does LeOS have limitations in terms of number of tasks it can manage?
Regards
|
|
|
|
|
Logged
|
|
|
|
|
Italy
Offline
Brattain Member
Karma: 219
Posts: 16547
Don't know what I do
|
 |
« Reply #14 on: September 06, 2012, 06:19:25 am » |
Is LeOS able to keep up with realtime, does it have any kind of RTC feature?[/li][/list]
At the momento, it doesn't. To make a very good real-time software we have to use the built-in RTC (Real-TimeCounter) module with an external crystal, so that we can set the timer 2 to work in asynchronous mode. (i.e. in my "Micrologio" project, that is available on my website) Does LeOS have limitations in terms of number of tasks it can manage?[/li][/list]
The limitations are set by SRAM memory. By default leOS can manage up to 10 tasks: you can change this value in the source of the library.
|
|
|
|
|
Logged
|
|
|
|
|
|