Arduino · 26 giugno 2012 35

leOS, un semplice SO per Arduino

Vai a leOS2

leOS, acronimo di little embedded Operating System, è un sistema di gestione dell’esecuzione in background di piccole routine con intervalli di lancio personalizzabili mediante l’uso di uno schedulatore che le avvia in maniera indipendente dal ciclo principale del programma. leOS è scritto per le schede Arduino ed i microcontrollori Atmel. leOS è capace di gestire piccoli compiti (o task), avviandoli, arrestandoli, riprendendoli ed eventualmente eliminandoli. Questi task possono compiere piccoli lavori in background (grazie all’uso di interrupt) sollevando l’utente dal dover continuamente controllare tramite millis() se è giunto il momento di effettuare una certa operazione. In realtà leOS si piazza a metà strada tra un sistema operativo in tempo reale (RTOS) ed uno schedulatore (scheduler in inglese). E’ distante dal primo nel senso che non ha nessun metodo per gestire i task con prelazione (preemptive multitasking), ossia assegnare dei tick di tempo per far girare i task per un determinato periodo di tempo e poi interromperli arbitrariamente per riprenderli in un secondo tempo, ma è anche qualcosa di più di altri schedulatori già visti su Arduino perché lavora usando gli interrupt quindi non è interrotto da eventuali blocchi nel codice principale (esempio l’uso di delay). leOS usa il timer 2 per gestire i task dell’utente e, ovviamente, fa perdere le funzionalità PWM sui pin 3 e 11. leOS può eseguire semplici task che non richiedano gravosi impegni di CPU però può risultare utile in tutti quei casi in cui si deve gestire un compito ripetitivo che si vuole rendere indipendente dal loop principale del programma. Per testare leOS basta scaricare il pacchetto allegato e scompattarlo. Dentro trovate una cartella denominata /leOS che dovete copiare all’interno della cartella /libraries contenuta nella cartella dei vostri sketch. Di solito è /home/utente/sketchbook/libraries per gli utenti Linux e /Documenti/Arduino/libraries per gli utenti Windows. Per usare leOS basta includere la sua libreria e creare una nuova istanza della classe leOS:

#include "leOS.h"
leOS myOS;

A questo punto va chiamato nel setup() il metodo begin, che prepara lo schedulatore del leOS, e dopo si possono aggiungere i propri task col metodo .addTask(). Ecco un esempio:

void setup() {
  myOS.begin();
  myOS.addTask(miaFunzione, intervallo[, stato]);
  ....
}

Con miaFunzione indicate la funzione che volete schedulare, con intervallo un numero che indica ogni quanti ms volete far ripetere la vostra funzione (il valore massimo ammesso è 3.600.000 ms, 1 ora, ma è possibile cambiarlo editando il file leOS.cpp).. stato è lo stato del task e può essere: PAUSED, per un task che non deve partire subito dopo essere stato aggiunto; SCHEDULED (opzione predefinita), per un normale task che deve partire subito; ONETIME, per un task che deve essere eseguito solo una volta (leggi più sotto), SCHEDULED_IMMEDIATESTART per un task che deve essere eseguito non appena aggiunto allo scheduler. Per provare leOS ho allegato un piccolo sketch dimostrativo. Per usarlo collegate (con le debite resistenze) 3 led rispettivamente ai pin 7, 8 e 9 e poi caricate lo sketch. Vedrete che ogni led lampeggia con una frequenza differente! Il led collegato al pin 8 è quello gestito dal loop principale, a dimostrazione che ogni task è indipendente dal loop e che nessun task ferma il programma. Ogni 10 secondi il programma arresta un task (un led cessa di lampeggiare) per poi essere ripresto dopo altri 10 secondi. leOS ha altri 3 metodi principal:

myOS.removeTask(nomeFunzione)
myOS.pauseTask(nomeFunzione);
myOS.restartTask(nomeFunzione);

I metodi hanno nomi autoesplicativi ma riassumo brevemente. removeTask serve a rimuovere permanentemente un task dallo scheduler. pauseTask serve a mettere in pausa un task, mentre restartTask serve a farlo ripartire. Lo sketch allegato fa comunque vedere l’uso di questi ultimi due task. Una caratteristica interessante introdotta a partire dalla versione 0.0.7 sono i task monouso, o one-time task. Un one-time task è un compito che deve essere eseguito solo una volta e poi deve essere rimosso dallo scheduler. Questa caratteristica è utile se si deve programmare un’azione da svogersi nel futuro. Per attivare un task di tipo one-time basta aggiungere la parola chiave ONETIME dopo l’intervallo di esecuzione del task:

myOS.addTask(nomeFunzione, intervallo[, ONETIME]);

A partire dalla versione 1.0.0 è stato introdotto un metodo per verificare lo stato di un task:

myOS.getTaskStatus(nomeFunzione);

Esso restituisce lo stato del task con i valori PAUSED, SCHEDULED o ONETIME. L’utente è tenuto a scrivere il suo codice affinché lo stato del task al momento della messa in pausa, della ripartenza o della sua rimozione sia coerente e/o compatibile con il resto del codice e con il circuito collegato. Mi spiego: se al posto di un led, si pilota ad esempio un transistor che alimenta un altro dispositivo bisogna prevedere il fatto che se il pin resta alto ed il transistor in conduzione, che tale stato sia compatibile con il circuito ed il restante codice. Ma mi sembra logico. Aggiornamenti di versione e maggiori info disponibili nei documenti allegati al package. Buon divertimento con leOS!


leOS2

Leggendo alcuni commenti degli utenti che l’hanno usato, uno dei più ricorrenti problemi era l’utilizzo nell’utilizzo del leOS era l’uso in abbinamento ad altre librerie che usano il timer 2: ciò è impossibile perché un timer può essere impostato per un solo compito. Studiando un po’ l’architettura dei microcontrollori che normalmente uso, ho pensato di utilizzare il WatchDog Timer, WDT. Questo circuito, che contiene un contatore, viene normalmente usato per resettare il microcontrollore se l’utente non provvede a resettarlo prima che sia trascorso il tempo preimpostato. Il WatchDog è utile nel caso di applicazioni critiche in cui lo sketch non deve bloccarsi durante l’esecuzione, sia per errori logici che per loop causati da eventi esterni (ad esempio, dati che dovrebbero arrivare da una connessione ethernet o seriale). Il WatchDog è particolare perché utilizza come sorgente di clock un oscillatore interno a 128 kHz e quindi lavora in modo indipendente dal clock di sistema; inoltre può non solo resettare il microcontrollore ma anche sollevare un interrupt. Sfruttando quest’ultima possibilità, possiamo impostarlo come generatore di interrupt ed inserire nella corrispondente ISR lo schedulatore del leOS: in questo modo lo schedulatore non occuperà nessun timer del microcontrollore. E’ così che è nato leOS2. Per utilizzare leOS2 basta copiarlo nella cartella /libraries, contenuta all’interno della propria cartella degli sketch, e poi aggiungere al proprio sketch l’inclusione della libreria ed una nuova istanza di leOS2:

#include "leOS2.h"
leOS2 myOS;

A questo punto si può utilizzare leOS2 come il suo predecessore. Sono cambiati solo un paio di metodi, addTask e modifyTask. Vediamoli in dettaglio. Essendo il leOS2 basato sul WDT, ci sono delle limitazioni sugli intervalli impostabili per l’esecuzione di un task. Siccome il WDT ha un clock fisso e solo alcuni prescaler, il minimo intervallo temporale selezionabile è 16 millisecondi, che rappresentano un “tick”: per questo motivo anche gli intervalli devono essere multipli di questo valore. addTask e modifyTask perciò non accettano più l’intervallo specificato in millisecondi ma in tick, per cui addTask(funzione, 100) non aggiunge un task da eseguire ogni 100 ms ma ogni 100 tick, ossia 1600 ms. Per aiutare nella conversione, se non si vuole eseguire la conversione in anticipo (basta uno spostamento dei bit a destra di 4 posizioni, es.: variabile>>4) si può usare la nuova funzione convertMs() che accetta in ingresso il numero di millisecondi e restituisce il corrispondente numero di tick. Esempi:

myOS.addTask(funzione1, 10); //aggiunge un task da eseguire ogni 160 ms (10*16 ms)
myOS.addTask(funzione2, myOS.convertMs(160)); //come sopra, ma la conversione è fatta dal sistema
myOS.modifyTask(funzione1, myOS.convertMs(300)); //reimposta funzione1 a 300 ms

Gli altri metodi del leOS sono rimasti uguali. Visto che il leOS2 modifca il WatchDog, non si può usare la corrispondente libreria per gestire il reset del microcontrollore. A tale scopo ho aggiunto il metodo reset() che resetta il microcontrollore immediatamente:

myOS.reset(); //resetta il microcontrollore

leOS2 supporta quasi tutti i microcontrollori utilizzabili con l’IDE di Arduino, sia tramite il core originale sia con core addizionali (esempio: core Tiny per i microcontrollori Attiny). L’unico microcontrollore non compatibile è l’Atmega8/A per via del fatto che Atmel lo ha dotato di un WDT che non può sollavere interrupt. Nel caso in cui si usi questa MCU è necessario quindi utilizzare leOS versione 1.

leOS2 – IMPORTANTE PER GLI UTENTI DELLA ARDUINO MEGA/MEGA2560
Il bootloader originale delle schede Arduino MEGA e MEGA2560 non disattiva il watchdog al riavvio del microcontrollore per cui si incorre in un reset infinito che blocca il chip. Per evitare questo problema, se si vuole usare il leOS2 bisogna sostituire il bootloader con uno aggiornato che è esente da questo problema. Il bootloader è prelevabile da questa pagina.

leOS
leOS
leOS_1.2.1.zip
Version: 1.2.1
2.1 MiB
6034 Downloads
Dettagli...
leOS2
leOS2
leOS2_2.3.1.zip
Version: 2.3.1
1.9 MiB
6594 Downloads
Dettagli...