Systèmes d'exploitation en temps réel (RTOS) et applications

Par Lim Jia Zhi, Senior Embedded Software Engineer

Avec la contribution de Rédacteurs nord-américains de DigiKey

Qu'est-ce qu'un RTOS ?

Un système d'exploitation en temps réel (RTOS) est un système d'exploitation (OS) léger, utilisé pour faciliter le fonctionnement multitâche et l'intégration des tâches dans les conceptions où les ressources et le temps sont limités, ce qui est généralement le cas dans les systèmes embarqués. En outre, le terme « temps réel » suggère la prévisibilité/le déterminisme du temps d'exécution plutôt que la vitesse brute. Ainsi, on peut généralement démontrer qu'un RTOS répond aux exigences de temps réel dur en raison de son déterminisme.

Les concepts clés des RTOS sont les suivants :

Tâche

Les tâches (que l'on pourrait également appeler processus/threads) sont des fonctions indépendantes fonctionnant en boucles infinies, généralement chacune responsable d'une fonctionnalité. Les tâches sont exécutées de manière indépendante dans leur propre pile mémoire (isolation spatiale) et temps (isolation temporelle). L'isolation spatiale entre les tâches peut être garantie grâce à l'utilisation d'une unité de protection de la mémoire (MPU) matérielle, qui restreint la zone de mémoire accessible et déclenche des exceptions d'erreur en cas de violation d'accès. Normalement, les périphériques internes sont mappés en mémoire, de sorte qu'une unité MPU peut être utilisée pour restreindre l'accès aux périphériques également.

Les tâches peuvent se trouver dans différents états :

  • Bloqué - La tâche est en attente d'un événement (par exemple, temporisation de retard, disponibilité des données/ressources)
  • Prêt – La tâche est prête à être exécutée sur le processeur mais ne s'exécute pas car le processeur est utilisé par une autre tâche
  • En cours d'exécution – La tâche est assignée comme étant en cours d'exécution sur le processeur

Planificateur

Les planificateurs dans les RTOS contrôlent quelle tâche doit être exécutée sur le processeur, et différents algorithmes de planification sont disponibles. Normalement, ils présentent les états suivants :

  • Préemptif – L'exécution d'une tâche peut être interrompue si une autre tâche avec un niveau de priorité supérieur est prête
  • Coopératif – Le changement de tâche ne se produira que si la tâche en cours d'exécution s'interrompt

La planification préemptive permet à des tâches avec un niveau de priorité supérieur d'interrompre une tâche moins importante afin de répondre à des contraintes en temps réel, mais elle s'accompagne d'une surcharge lors du changement de contexte.

Communications inter-tâches (ITC)

Les tâches multiples doivent normalement partager des informations ou des événements entre elles. Le moyen le plus simple de partager est de lire/écrire directement les variables globales partagées dans la RAM, mais cela n'est pas souhaitable en raison du risque de corruption des données causé par une condition de concurrence. Une meilleure solution consiste à lire/écrire des variables statiques spécifiques au fichier, accessibles via les fonctions setter et getter. Les conditions de concurrence peuvent être évitées en désactivant les interruptions ou en utilisant un objet d'exclusion mutuelle (mutex) dans la fonction setter/getter. La méthode la plus efficace consiste à utiliser des objets RTOS à sécurité thread, tels que la file d'attente de messages, pour transmettre des informations entre les tâches.

Outre le partage d'informations, les objets RTOS sont également capables de synchroniser l'exécution des tâches car celles-ci peuvent être bloquées en attente de la disponibilité des objets RTOS. La plupart des RTOS ont des objets tels que :

  • File d'attente des messages
    • File d'attente FIFO (First-in-first-out) pour la transmission des données
    • Les données peuvent être envoyées par copie ou par référence (pointeur)
    • Utilisée pour envoyer des données entre les tâches ou entre l'interruption et la tâche
  • Sémaphore
    • Peut être traité comme un compteur de référence pour enregistrer la disponibilité d'une ressource particulière
    • Peut être un sémaphore binaire ou de comptage
    • Utilisé pour surveiller l'utilisation des ressources ou synchroniser l'exécution des tâches
  • Mutex
    • Semblable à un sémaphore binaire, généralement utilisé pour surveiller l'utilisation d'une seule ressource (MUTual EXclusion, exclusion mutuelle)
    • Le mutex FreeRTOS est fourni avec un mécanisme d'héritage de priorité pour éviter le problème d'inversion de priorité (condition où une tâche haute priorité attend une tâche de moindre priorité).
  • Boîte aux lettres
    • Emplacement de stockage simple pour partager une seule variable
    • Peut être considérée comme une file d'attente à élément unique
  • Groupe d'événements
    • Groupe de conditions (disponibilité du sémaphore, file d'attente, indicateur d'événement, etc.)
    • La tâche peut être bloquée et attendre qu'une condition de combinaison spécifique soit remplie
    • Disponible dans Zephyr en tant qu'API d'interrogation, dans FreeRTOS en tant que QueueSets

Tick système

Les RTOS ont besoin d'une base de temps pour mesurer le temps, normalement sous la forme d'une variable de compteur de ticks système incrémentée dans une interruption de temporisateur matériel périodique. Avec le tick système, une application peut maintenir plus de services basés sur le temps (intervalle d'exécution des tâches, temps d'attente, découpage du temps) en utilisant un seul temporisateur matériel. Cependant, un taux de tick plus élevé ne fait qu'augmenter la résolution de la base de temps du RTOS, et n'accélère pas l'exécution du logiciel.

Pourquoi utiliser des RTOS

Organisation

Les applications peuvent toujours être écrites sans système d'exploitation, mais à mesure que la complexité du code augmente, le fait d'avoir une sorte de structure aidera à gérer les différentes parties de l'application, en les maintenant séparées. De plus, grâce à une méthode de développement structurée et à un langage de conception familier, un nouveau membre de l'équipe peut comprendre le code et contribuer au projet plus rapidement. RFCOM Technologies développe des applications utilisant différents microcontrôleurs comme l'Hercules de Texas Instruments, le RL78 et le RX de Renesas et le STM32 de STMicroelectronics sur un RTOS différent. Des modèles de conception similaires permettent de développer des applications sur différents microcontrôleurs et même sur un RTOS différent.

Modularité

Diviser pour mieux régner. En séparant les fonctionnalités dans différentes tâches, de nouvelles fonctionnalités peuvent être ajoutées facilement sans interrompre d'autres fonctionnalités, à condition que la nouvelle fonctionnalité ne surcharge pas les ressources partagées comme le processeur et les périphériques. Le développement sans RTOS se fait normalement dans une grande boucle infinie où toutes les fonctionnalités font partie de la boucle. Une modification d'une fonctionnalité de la boucle aura un impact sur les autres fonctionnalités, rendant le logiciel difficile à modifier et à maintenir.

Pilotes et piles de communications

De nombreux pilotes ou piles supplémentaires, comme les piles BLE, TCP/IP, USB et les bibliothèques graphiques, sont développés/portés pour/vers les RTOS existants. Un développeur d'applications peut se concentrer sur une couche application du logiciel et réduire considérablement les délais de commercialisation.

Conseils

Allocation statique

L'utilisation de l'allocation statique de la mémoire pour les objets RTOS signifie la réservation d'une pile mémoire en RAM pour chaque objet RTOS pendant le temps de compilation. Un exemple de fonction d'allocation statique dans FreeRTOS est xTaskCreateStatic(). Cela garantit qu'un objet RTOS peut être créé avec succès, et permet d'éviter le traitement lié à l'échec potentiel de l'allocation et de rendre l'application plus déterministe.

Pour ce qui est de décider de la taille de la pile nécessaire pour une tâche, la tâche peut être exécutée avec une pile plus grande (plus que suffisante) et l'utilisation de la pile peut être vérifiée en cours d'exécution pour déterminer la limite supérieure. Un outil d'analyse statique de la pile est également disponible.

Couche d'abstraction du système d'exploitation (OSAL) et abstraction significative

Tout comme la couche d'abstraction matérielle (HAL), l'utilisation de la couche d'abstraction RTOS permet la migration aisée des logiciels d'application vers d'autres RTOS. Les fonctionnalités des RTOS sont assez similaires, donc la création d'une couche OSAL ne devrait pas être trop compliquée. Par exemple :

Utilisation directe de l'API FreeRTOS :

if( xSemaphoreTake( spiMutex, ( TickType_t ) 10 ) == pdTRUE ) { //dosomething }

Intégration de l'API RTOS dans la couche OSAL :

if( osalSemTake( spiMutex, 10 ) == true) { //dosomething }

Utilisation de la couche d'abstraction sur les communications inter-tâches pour rendre le code plus lisible et minimiser la portée d'un objet RTOS :

if( isSpiReadyWithinMs( 10 ) ) { //doSomething }

De plus, l'abstraction permet également à un programmeur de changer l'objet RTOS utilisé en dessous (par exemple, de mutex à sémaphore de comptage) s'il y a plus d'un module SPI disponible. Les couches d'abstraction OSAL et autres facilitent également les tests logiciels en simplifiant l'insertion de fonctions fictives pendant les tests unitaires.

Sélection d'intervalle tick

Dans l'idéal, un taux de tick plus bas est préférable car il y a moins de surcharge. Pour sélectionner un taux de tick approprié, le développeur peut énumérer les contraintes de temps des modules d'une application (intervalle de répétition, durée du délai d'attente, etc.). Si certains modules particuliers ont besoin d'un petit intervalle, il est possible d'envisager d'avoir une interruption de temporisateur dédiée pour les modules particuliers plutôt que d'augmenter le taux de tick du RTOS. Si la fonction haute fréquence est très courte (par exemple, écrire dans un registre pour allumer/éteindre une LED), elle peut être effectuée dans une routine de service d'interruption (ISR), sinon le traitement différé des interruptions peut être utilisé. Le traitement différé des interruptions est une technique qui consiste à différer le calcul des interruptions dans une tâche RTOS. La routine ISR ne fait que générer un événement via l'objet RTOS, puis la tâche RTOS est débloquée par l'événement et effectue le calcul.

Suppression des ticks pour les applications basse consommation

Le mode Tickless Idle désactive l'interruption des ticks lorsque le système reste inactif pendant une longue période. Un moyen significatif de réduire la consommation d'énergie pour les microprogrammes embarqués est de mettre le système en mode basse consommation le plus longtemps possible. Le mode Tickless Idle est mis en œuvre en désactivant l'interruption de tick périodique, puis en mettant en place un compte à rebours qui s'interrompt lorsqu'une tâche bloquée est sur le point de s'exécuter. Si aucune tâche n'est en attente d'une temporisation, l'interruption tick peut être bloquée indéfiniment jusqu'à ce qu'une autre interruption se produise (par exemple, si un bouton est enfoncé). Par exemple, dans le cas d'une balise Bluetooth Low Energy (BLE), le microcontrôleur peut être placé en veille profonde entre les intervalles d'annonce. Comme illustré à la Figure 1, la balise est placée en mode de veille profonde la plupart du temps, avec une consommation en dizaines de µA.

Graphique de la consommation de courant d'une balise BLE (cliquez pour agrandir)Figure 1 : Consommation de courant d'une balise BLE. (Source de l'image : RFCOM)

Conclusion

Un RTOS fournit des fonctionnalités telles que des planificateurs, des tâches et des objets RTOS de communications inter-tâches, ainsi que des pilotes et des piles de communications. Il permet aux développeurs de se concentrer sur la couche application du logiciel embarqué et de concevoir des logiciels multitâches facilement et rapidement. Cependant, comme tout autre outil, il doit être utilisé correctement pour apporter une valeur ajoutée. Pour créer des logiciels embarqués sûrs, sécurisés et efficaces, les développeurs doivent savoir quand utiliser les fonctionnalités RTOS et comment configurer les RTOS.

DigiKey logo

Avertissement : les opinions, convictions et points de vue exprimés par les divers auteurs et/ou participants au forum sur ce site Web ne reflètent pas nécessairement ceux de DigiKey ni les politiques officielles de la société.

À propos de l'auteur

Image of Lim Jia Zhi

Lim Jia Zhi, Senior Embedded Software Engineer

Lim Jia Zhi is an embedded software engineer, holds a degree in Electrical and Electronics Engineering. He has developed software for devices in IoT solution covering edge gateway and battery-powered edge devices, and also involved in developing safety-critical embedded software. Actively learning ways to design efficient and reliable embedded system, like using design pattern and tools, and having software development lifecycle. (jia.zhi.lim@rfcom-tech.com (+65) 6635 4217)

À propos de l'éditeur

Rédacteurs nord-américains de DigiKey