Nouvelle librairie multitâche HeliOS pour Arduino AVR, SAM et SAMD • Domotique et objets connectés à faire soi-même

HeliOS est une librairie Open Source développée par Manny Peterson qui permet d’ajouter un système multitâche simple aux micro-contrôleurs Arduino. HeliOS est une librairie totalement écrite en langage C qui est compatible avec le standard de la bibliothèque Arduino. HeliOS est conçu comme une alternative aux systèmes d’exploitation temps réel tels que RTOS ou FreeRTOS.

Contrairement à ce qu’on pourrait penser, HeliOS est bien une librairie. Ce n’est pas un firmware ou un nouvel OS pour micro-contrôleur. La librairie HeliOS offre plusieurs fonctionnalités de planification multitâches et de gestion d’événements non bloquants.

Petit regret, la librairie est uniquement compatible avec les plateformes Arduino AVR, SAM et SAMD. Pour le moment, il n’y a pas de support pour les micro-contrôleurs ESP32, ESP8266 ou STM32. Dommage.

Présentation de HeliOS

Manny Peterson, le principal contributeur du projet vient d’annoncer la disponibilité de HeliOS, un noyau multitâche Open Source et gratuit conçu avec des micro-contrôleurs 8 bits tel que l’Arduino Uno.

HeliOS propose 21 fonctions et implémente une grande variété de fonctionnalités

  • Multitâche coopératif
  • Multitâche événementiel
  • Notification de tâches et messagerie d’événement
  • Minuteries
  • Gestion de la mémoire
  • Non préventif. Le code exécuté n’est jamais bloquant

Il est possible de mélanger les tâches coopératives et événementielles dans HeliOS.

Conçu comme un système d’exploitation pour les appareils embarqués légers, HeliOS se veut compatible avec la plupart des cartes de développement Arduino.

Totalement écrit en language C, il est conforme aux spécifications des librairies Arduino 1.5 Rev 2.2, ce qui signifie qu’il peut être installé directement depuis l’IDE Arduino à l’aide du gestionnaire de bibliothèque.

HeliOS prend également en charge les micro-contrôleurs AVR, SAM et SAM D. D’après Manny Peterson, il sera très facile de porter le code pour le rendre multi-tâche.

Pourquoi HeliOS ?

Il existe déjà de nombreuses solutions de planification de tâches (schedulerBlueFairy, chronos, CoopTask…) et temps réel (RTOS , FreeRTOS).

HeliOS ne vise pas à remplacer ces solutions mais plutôt de proposer une librairie de faible taille offrant des fonctionnalités équivalentes avec une écriture simplifiée.

En effet, d’après Manny, de nombreux projets implémentent ce que l’on appelle une «super boucle». Une super boucle est une boucle qui ne sort jamais (c’est-à-dire while (1) {}) et contient la plupart du code exécuté par le micro-contrôleur. Le problème avec les super boucles est qu’elles peuvent devenir incontrôlables et devenir difficiles à gérer. Cela devient particulièrement difficile étant donné le nombre relativement restreint d’options pour contrôler la synchronisation (par exemple, delay ()). Malheureusement, l’utilisation de delay() pour contrôler la synchronisation signifie également que le micro-contrôleur est incapable d’effectuer d’autres opérations (au moins sans l’aide d’un ISR) jusqu’au retour de delay().

Helios évite ces problèmes.

Un exemple d’application avec HeliOS

Voici un exemple bien connu qui fait clignoter une LED. L’état de la LED est alterné. Entre chaque changement d’état, on attend 1 seconde (1000ms). Sans avoir recourt à une librairie multi-tâche tel qu’un timer, on a pas le choix d’exécuter le code dans la boucle principale loop() ce qui empêche ou ralenti les autres traitements.

Pas génial

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}

Voici maintenant le même code écrit avec HeliOS.

/*
 * Include the standard HeliOS header for Arduino sketches. This header
 * includes the required HeliOS header files automatically.
 */
#include  

/*
 * Declare and initialize an int to maintain the state of
 * the built-in LED.
 */
volatile int ledState = 0;

/*
 * The task definition for taskBlink() which will
 * be executed by HeliOS every 1,000,000 microseconds
 * (1 second).
 */


void setup() {

  /*
   * Declare and initialize an int to hold the
   * task id.
   */
  int id = 0;

  /*
   * Call xHeliOSSetup() to initialize HeliOS and
   * its data structures. xHeliOSSetup() must be
   * called before any other HeliOS function call.
   */
  xHeliOSSetup();

  /*
   * Set the mode of the digital GPIO pin associated
   * with the built-in LED to OUTPUT only.
   */
  pinMode(LED_BUILTIN, OUTPUT);

  /*
   * Add the task taskBlink() to HeliOS by passing
   * xTaskAdd() the friendly name of the task as well
   * as a callback pointer to the task function.
   */
  id = xTaskAdd("TASKBLINK", &taskBlink);

  /*
   * Call xTaskWait() to place taskBlink() into a wait
   * state by passing xTaskWait() the task id. A task
   * must be in a wait state to respond to timer events.
   */
  xTaskWait(id);

  /*
   * Set the timer interval for taskBlink() to 1,000,000 microseconds
   * (1 second). HeliOS automatically begins incrementing
   * the timer for the task once the timer interval is set.
   */
  xTaskSetTimer(id, 1000000);
}

void loop() {

  /*
   * Momentarily pass control to HeliOS by calling the
   * xHeliOSLoop() function call. xHeliOSLoop() should be
   * the only code inside of the sketch's loop() function.
   */
  xHeliOSLoop();
}

Comment fonctionne ce code ?

On créé une variable ledState qui contient l’état de la LED

volatile int ledState = 0;

A chaque fois que la tâche taskBlink est exécutée, on inverse l’état de la variable ledState est on active ou désactive la sortie en fonction de l’état celle-ci.

void taskBlink(int id_) {
  if(ledState) {
    digitalWrite(LED_BUILTIN, LOW);
    ledState = 0;
  } else {
    digitalWrite(LED_BUILTIN, HIGH);
    ledState = 1;
  }
}

Dans le setup(), on initialise la librairie HeliOS et on démarre le planificateur de tâche en appelant la méthode xHeliOSSetup(). On créé une tâche xTaskAdd qui sera exécutera chaque seconde (1 000 000ms) la fonction taskBlink définie précédemment.

void setup() {
  int id = 0; 
  xHeliOSSetup();
  pinMode(LED_BUILTIN, OUTPUT);
  id = xTaskAdd("TASKBLINK", &taskBlink);
  xTaskWait(id);
  xTaskSetTimer(id, 1000000);
}

Pour assurer le fonctionnement de HeliOS, il suffit d’appeler la librairie à chaque passage dans la boucle loop qui n’est plus ralentie par un delay maintenant.

xHeliOSLoop();

L’écriture est assez classique pour une librairie multi-tâche.

Pour le moment il est inutile de tester la librairie sur ESP32 ou ESP8266, vous obtiendrez directement un message d’erreur

#error “HeliOS is currently supported on the Arduino AVR, SAM and SAMD architectures. Other architectures may require porting of HeliOS.”

Liens utiles

Avez-vous aimé cet article ?