Go Down

Topic: mini RTOS [sic] (Read 4 times) previous topic - next topic

westfw

Off in the "millis broken" discussion, there has been talk of a mini-RTOS for scheduling time-based functions.  I think that an actual multi-processing OS is overkill for most such applications, and very difficult to get working well on a system with as little ram as an ATmega168.
However, a simpler scheme might be pretty easy to implement.  Consider something like the following:
Code: [Select]

setup() {
 sched_once(timesup, 3*ONEMINUTE);  // Run "timesup" in three minutes
 sched_periodic(blinker, ONESEC);       // Run "blinker" every second
}
loop() {
 sched_check();  // check and maybe run scheduled tasks
 // other code, hopefully not taking too long.

It's certainly not "real time."  It's not preemptive.  It's not a real operating system at all.
It's dependent on well-behaved co-operative tasks and code ("cooperative mutitasking")
It doesn't allow tasks to "block" on arbitrary events.
OTOH, it'd be really simple to implement, not use very much memory (flash OR ram), and some very large systems indeed run pretty well with similar limitations.


ccarlson

As long as the compiler supports function pointers, something like this could work splendidly, in my opinion.

(I'm at the office now, or I'd check it out myself.  I really need to get a job where tinkering with Arduino is acceptable....)

mem

#2
Aug 04, 2008, 03:57 pm Last Edit: Aug 04, 2008, 04:10 pm by mem Reason: 1
I implemented something along these lines a while ago but have not had the time to write it up.

It's a library called dateTimeAlarm that works alongside the dateTime library I posted here: http://www.arduino.cc/playground/Code/DateTime

The posted code adds timekeeping without requiring a real time clock.

The (as yet) unposted Alarm library adds the ability to schedule tasks at specific times or after specific delays from seconds to days. The library has a delay function  that can be a  number of milliseconds or a specific second, minute, hour or day.  But the key functionality is a set of Alarms that are handled by user callback functions that are serviced while any of the library delay functions are executing. The scheduling is co-operative and handled on a first come first serve basis. These alarm callbacks can be set for a specific time of day or after a specific interval has elapsed.

Here is a fragment of a sketch by way of example

Code: [Select]

#include <DateTime.h>
#include <DateTimeAlarms.h>

AlarmID_t Alarm9,Alarm10,Timer11;  // id to identify what triggered alarm if callbacks are shared

void OnAlarm(AlarmID_t Sender){
 // callback for time of day alarms
 if( Sender ==  Alarm9) {
   Serial.print("Alarm9: ");        
   dtAlarms.setValue(Alarm9, DateTime.now() + 9 ); // reset alarm to trigger at the time that is 9 seconds from now
 }
 else  if( Sender ==  Alarm12)
 {
   Serial.print("Alarm12: ");    
   dtAlarms.setValue(Alarm12(AlarmHMS(12,0,0),); // reset alarm to trigger at noon
 }    
}

void OnTimer(AlarmID_t Sender){
 // callback for time delay alarm
 Serial.print("Timer11: 11 sec timer: ");    
 dtAlarms.setValue(Timer11, 11 ); // delay another 11 seconds
}

void setup(){
 Serial.begin(19200);
 Alarm9 = dtAlarms.createAlarm( DateTime.now() + 9, OnAlarm); // trigger 9 seconds from now
 Alarm12 = dtAlarms.createAlarm(AlarmHMS(12,0,0), OnAlarm); // trigger at mid day
 Timer11 = dtAlarms.createTimer( 11, OnTimer); // trigger in 11 seconds
}

void  loop(){  
 
 dtAlarms.waitUntilThisSecond(0); //  this code blocks waiting for start of the next minute, background alarms are still serviced
 digitalWrite(13, HIGH);
 dtAlarms.delay(2000);  // note we call the alarm delay to service the background alarms
 digitalWrite(13,LOW);  
 dtAlarms.delay(2000); // delay is in milliseconds , all other alarm values are seconds
}


If there is interest in this I will knuckle under and post the code. I would very much welcome volunteers to help me document the usage.

mellis

mem: that looks very cool.

I think even a simplified version would be useful.  That is, something that allows scheduling an event in N seconds (or milliseconds) and something that allows scheduling an event every N seconds (or milliseconds).  You don't necessarily need to allow the user to create Alarm instances: there could just be a single global one that allows registration of multiple callbacks.

mem

Quote
mem: that looks very cool.

I think even a simplified version would be useful.  That is, something that allows scheduling an event in N seconds (or milliseconds) and something that allows scheduling an event every N seconds (or milliseconds).  You don't necessarily need to allow the user to create Alarm instances: there could just be a single global one that allows registration of multiple callbacks.


That functionality would certainly simplify the usage (and the effort to write it up), particularly if  the library could ignore time of day and just handle the duration of the alarm from the time its set.

How many alarms would you suggest. I would like to avoid the overhead of malloc if I can , and the number could be easily changed by the user in a re-compile where desired. Do you think I can get away with say six different alarms by default? (a repeating alarm uses the same resource as a one-shot alarm, so its just  a question of how many different alarm values)

Go Up