FreeRTOS
FreeRTOS est un système d'exploitation temps réel (RTOS) faible empreinte, portable, préemptif et Open source pour microcontrôleur. Il a été porté sur plus de 40 architectures différentes. Créé en 2003 par Richard Barry et la FreeRTOS Team, il est aujourd’hui parmi les plus utilisés dans le marché des systèmes d'exploitation temps réel.
FreeRTOS | |
Famille | Système d'exploitation temps réel |
---|---|
Type de noyau | Micronoyau |
État du projet | En développement |
Dépôt | github.com/FreeRTOS/FreeRTOS |
Plates-formes | ARM (ARM7, ARM9, Cortex-M3, Cortex-M4, Cortex-A), Atmel AVR, AVR32 (en), HCS12 (en), MicroBlaze, MSP430, Microcontrôleur PIC, Renesas H8/S, SuperH, RX, x86, 8052, Motorola ColdFire, V850 (en), 78K0R, Fujitsu MB91460 series, Fujitsu MB96340 series, Nios II (en) |
Entreprise / Développeur |
Amazon, Richard Barry et FreeRTOS Team |
Licence | MIT, précédemment GNU GPL modifiée |
États des sources | Logiciel libre pour système embarqué |
Écrit en | C |
Dernière version stable | 202012.00-LTS ()[1] |
Site web | www.freertos.org |
FreeRTOS est disponible gratuitement sous une licence MIT depuis le 29 novembre 2017[2]. Les versions précédentes étaient disponibles sous licence GPL modifiée et utilisable sans paiement de redevances, cette licence n’oblige pas les développeurs à publier le code de leurs logiciels applicatifs mais impose de garder le noyau de FreeRTOS Open Source. Une licence commerciale avec le support ad hoc (OpenRTOS) est également proposée par la société High Integrity Systems.
Le nombre de tâches exécutées simultanément et leur priorité ne sont limités que par le matériel. L'ordonnancement est un système de file d'attente basé sur les Sémaphores et les Mutex. Il est basé sur le modèle Round-Robin avec gestion des priorités. Conçu pour être très compact, il n'est composé que de quelques fichiers en langage C, et n'implémente aucun pilote matériel.
Les domaines d'applications sont assez larges, car les principaux avantages de FreeRTOS sont l’exécution temps réel, un code source ouvert et une taille très faible. Il est donc utilisé principalement pour les systèmes embarqués qui ont des contraintes d'espace pour le code, mais aussi pour des systèmes de traitement vidéo et des applications réseau qui ont des contraintes de temps réel.
Définition
FreeRTOS un système d'exploitation temps réel libre et open source[3] originellement développé par Real Time Engineers Ltd[4].
En 2017, le projet et son équipe de développeurs ont été acquis par Amazon[5]. Une version spécifique de FreeRTOS appelée Amazon FreeRTOS a d'ailleurs été créée, incluant une série de librairies facilitant l'intégration avec le cloud Amazon AWS.
Il a été porté sur plus de 40 architectures et 15 chaînes de compilation différentes[6]. En 2019, il a été téléchargé plus de 185 500 fois[6].
Sa conception est volontairement minimaliste pour qu'il puisse être installé sur de petits systèmes. L'image binaire du noyau pèse entre 4KB et 9KB[7] (4,3 KB compilé sur ARM7). Le kit minimal ne compte que quelques fonctions pour gérer les tâches et la mémoire[3]. De plus, les files d'attente, les sémaphores et les mutex sont implémentés[3].
Le noyau de la version 7.3.0 n'est composé que de cinq fichiers codés en langage C. Des sections en Assembleur permettent d'assurer la compatibilité de FreeRTOS avec les différentes architectures matérielles.
Un nombre illimité de tâches peut être exécuté simultanément et sans contrainte[3].
Architecture
FreeRTOS a été conçu pour être très léger, de 4 kio à 9 kio[7] pour une image binaire classique du noyau RTOS. Le noyau lui-même n'est composé que de trois fichiers source écrit en langage C.
L’ordonnanceur
L'ordonnancement des tâches a pour but principal de décider parmi les tâches qui sont dans l'état « prêt », laquelle exécuter. Pour faire ce choix, l'ordonnanceur de FreeRTOS se base uniquement sur la priorité des tâches[8].
Les tâches en FreeRTOS se voient assignées à leur création, un niveau de priorité représenté par un nombre entier. Le niveau le plus bas vaut zéro et il doit être strictement réservé pour la tâche Idle[9]. L'utilisateur a la possibilité de surcharger ce niveau avec une priorité personnalisée en modifiant la constante : tskIDLE_PRIORITY. Le nombre maximum de niveaux de priorités est défini par la constante : tskMAX_PRIORITIES. Plusieurs tâches peuvent appartenir à un même niveau de priorité[10].
Dans FreeRTOS Il n'y a aucun mécanisme automatique de gestion des priorités. La priorité d'une tâche ne pourra être changée qu'à la demande explicite du développeur[9].
Les tâches sont de simples fonctions qui généralement s’exécutent en boucle infinie[11] et qui suivent la structure générique suivante :
void vATaskFunction( void *pvParameters )
{
for( ;; )
{
-- Ajouter le code de votre tâche ici --
}
}
Dans le cas d'un micro-contrôleur possédant un seul cœur, il y aura à tout moment une seule tâche en exécution[12]. L’ordonnanceur garantira toujours que la tâche de plus haute priorité pouvant s’exécuter sera sélectionnée pour entrer dans l'état d’exécution[8]. Si deux tâches partagent le même niveau de priorité et sont toutes les deux capables de s'exécuter, alors les deux tâches s'exécuteront en alternance par rapport aux réveils de l’ordonnanceur (round robin)[8].
Afin de choisir la tâche à exécuter, l'ordonnanceur doit lui-même s'exécuter et préempter la tâche en état d'exécution. Afin d'assurer le réveil de l'ordonnanceur, FreeRTOS définit une interruption périodique nommé la "tick interrupt"[8]. Cette interruption s'exécute infiniment selon une certaine fréquence qui est définie dans le fichier FreeRTOSConfig.h par la constante :
configTICK_RATE_HZ /* Fréquence d’exécution de la "tick interrupt" en Hz. */
Cette constante décrit alors la période de temps allouée au minimum pour chaque tâche ou expliqué autrement, l'intervalle séparant deux réveils de l’ordonnanceur[8].
Comme décrit dans cette section, FreeRTOS est donc un RTOS qui utilise un ordonnancement préemptif pour gérer les tâches. Néanmoins il peut aussi utiliser optionnellement (si la directive lui est donnée) l'ordonnancement coopératif[13]. Dans ce mode d'ordonnancement, un changement de contexte d’exécution a lieu uniquement si la tâche en exécution permet explicitement à une autre tâche de s’exécuter (en appelant un Yield() par exemple) ou alors en entrant dans un état de blocage[13]. Les tâches ne sont donc jamais préemptées. Ce mode d’ordonnancement simplifie beaucoup la gestion des tâches malheureusement il peut mener à un système moins efficace et moins sûr.
FreeRTOS peut aussi utiliser un ordonnancement hybride, utilisant l'ordonnancement préemptif et l’ordonnancement coopératif[13]. Dans ce mode, un changement de contexte d’exécution peut aussi avoir lieu lors de l’événement d'une interruption.
La famine
Dans FreeRTOS, la tâche de plus haute priorité prête à s'exécuter sera toujours sélectionnée par l'ordonnanceur. Ceci peut amener à une situation de famine[14]. En effet, si la tâche de plus haute priorité n'est jamais interrompue, toutes les tâches ayant une priorité inférieure ne s’exécuteront jamais. FreeRTOS n’implémente aucun mécanisme automatique pour prévenir le phénomène de famine[8]. Le développeur doit s'assurer lui-même qu'il n'y ait pas de tâches monopolisant tout le temps d’exécution du micro-contrôleur[15]. Pour cela, il peut placer des événements qui interrompront la tâche de plus haute priorité pour un temps déterminé ou jusqu'à l’avènement d'un autre événement et laissant ainsi le champ libre aux tâches de priorités inférieures pour s’exécuter.
Afin d'éviter la famine, le développeur peut utiliser l'ordonnancement à taux monotones (RMS)[13]. C'est une technique d'assignation de priorité qui attribue à chaque tâche une unique priorité selon sa fréquence d’exécution. La plus grande priorité est attribuée à la tâche de plus grande fréquence d’exécution et la plus petite priorité est attribuée à la tâche de plus petite fréquence. L'ordonnancement à taux monotones permet de maximiser l'ordonnançabilité des tâches mais cela reste difficile à atteindre du fait de la nature des tâches qui ne sont pas totalement périodiques[13].
La tâche Idle
Un micro-contrôleur doit toujours avoir quelque chose à exécuter[16]. En d'autres termes, il doit toujours y avoir une tâche en exécution. FreeRTOS gère cette situation en définissant la tâche Idle qui est créée au lancement de l’ordonnanceur[16]. La plus petite priorité du noyau est attribué à cette tâche. Malgré cela, la tâche Idle peut avoir plusieurs fonctions à remplir dont :
- Libérer l'espace occupé par une tâche supprimée[16].
- Placer le micro-contrôleur en veille afin d'économiser l'énergie du système lorsqu'aucune tâche applicative n'est en exécution[16].
- Mesurer le taux d'utilisation du processeur[16].
La description des tâches
Dans FreeRTOS, chaque tâche est décrite par un TCB (Task control Block) qui contient toutes les informations nécessaires afin de spécifier et de représenter une tâche[17].
Variables | Description |
---|---|
pxTopOfStack | Pointeur vers le dernier élément placé en haut de la pile |
xGenericListItem | Élément (xListItem) de la liste utilisé pour placer la TCB dans une liste d'états (Prêt, bloqué ou suspendu). |
xEventListItem | Élément (xListItem) de la liste utilisé pour placer la TCB dans une liste d’événements. |
uxPriority | Priorité de la tâche |
pxStack | Pointeur vers le début de la pile du processus |
pxEndOfStack | Pointeur vers la fin de la pile du processus |
uxTCBNumber | Taille de la pile en nombre de variables |
pcTaskName | Nombre s'incrémentant à chaque fois qu'une TCB est créée (utilisé pour le débogage) |
uxBasePriority | La dernière priorité assignée à la tâche |
ulRunTimeCounter | Calcule le temps passé par la tâche dans un état d’exécution |
pxTaskTag | Permet d'ajouter un Tag à une tâche. Le Tag s'utilise pour réaliser des Log via les sorties analogique ou digitales grâce à la fonction traceSWITCHED_IN(). |
uxCriticalNesting | Permet de sauvegarder la profondeur d'imbrication des sections critiques de cette tâche. À chaque fois que la tâche entre dans une section critique, la variable est incrémentée, elle est décrémentée dès que la tâche sort d'une section critique.
Cette variable est nécessaire, car il est possible que la tâche rende la main pendant qu'elle est en section critique. |
Les tâches sous FreeRTOS peuvent exister sous 5 états : "supprimé", "suspendu", "prêt", "bloqué" ou "en exécution"[17].
Dans FreeRTOS, il n'y a aucune variable pour spécifier explicitement l'état d'une tâche, en contrepartie FreeRTOS utilise des listes d'états. La présence de la tâche dans un type de listes d'états détermine son état (prêt, bloqué ou suspendu). Les tâches changeant souvent d'état, l’ordonnanceur n'aura alors qu'à déplacer la tâche (l'élément (xListItem) appartenant à cette même tâche) d'une liste d'états à une autre[17].
À la création d'une tâche, FreeRTOS crée et remplit la TCB correspondant à la tâche, puis il insère directement la tâche dans une "Ready List" (Liste contenant une référence vers toutes les tâches étant dans l'état "Prêt")[17].
FreeRTOS maintient plusieurs "Ready List", une liste existe pour chaque niveau de priorité. Lors du choix de la prochaine tâche à exécuter, l’ordonnanceur analyse les "Ready list" de la plus haute priorité à la plus basse[17].
Plutôt que de définir explicitement un état "en exécution" ou une liste associée à cet état, le noyau FreeRTOS décrit une variable "pxCurrentTCB" qui identifie le processus en exécution. Cette variable pointe vers la TCB correspondant au processus se trouvant dans l'une des 'Ready list'[17].
Une tâche peut se retrouver dans l'état "bloqué" lors de l’accès à une file en lecture/écriture dans le cas où la file est vide/pleine. Chaque opération d'accès à une file est paramétrée avec un timeout (xTicksToWait), Si ce timeout vaut 0 alors la tâche ne se bloque pas et l'opération d'accès à la file est considérée comme échouée. Dans le cas où le timeout n'est pas nul, la tâche se met dans l'état 'bloqué' jusqu'à ce qu'il y ait une modification de la file (par une autre tâche par exemple). Une fois l'opération d'accès à la file possible, la tâche vérifie que son timeout n'est pas expiré et termine avec succès son opération[17].
Une tâche peut être volontairement placée dans l'état "suspendu", elle sera alors totalement ignorée par l’ordonnanceur et ne consommera plus aucune ressource jusqu'à ce qu'elle soit retirée de l'état et remise dans un état "prêt"[18].
Le dernier état que peut prendre une tâche est l'état "supprimé", cet état est nécessaire car une tâche supprimée ne libère pas ses ressources instantanément. Une fois dans l'état "supprimé", la tâche est ignorée par l'ordonnanceur et une autre tâche nommée "IDLE" est chargée de libérer les ressources allouées par les tâches étant en état "supprimé"[17].
La tâche 'IDLE' est créée lors du démarrage de l'ordonnanceur et se voit assigner la plus petite priorité possible ce qui conduit à une libération retardée des ressources lorsque aucune autre tâche est en exécution[19].
Les Listes
Les listes sont les structures de données les plus utilisées dans FreeRTOS. Elles sont utilisées pour organiser et ordonnancer les tâches, ainsi que pour l’implémentation des files[17].
FreeRTOS définit plusieurs structures afin de représenter les listes :
- La structure xLIST représente l'en-tête des listes qui sont créées et utilisées par l'ordonnanceur. Par exemple, les listes des tâches prêtes (une liste par niveau de priorité), la liste des tâches bloquées, etc. Cette structure contient d'une certaine façon les autres structures de listes utilisées par FreeRTOS [17].
La structure xLIST est définie comme suit :
typedef struct xLIST
{
volatile unsigned portBASE_TYPE uxNumberOfItems; /* Le nombre d'éléments dans cette liste. */
volatile xListItem * pxIndex; /* Pointeur utilisé pour parcourir cette liste,
il pointe successivement sur les éléments (xLIST_ITEM)
contenus dans cette liste. */
volatile xMiniListItem xListEnd; /* Élément marquant la fin de cette liste.
Elle contient pour cela la valeur maximale de la variable
xItemValue dans la liste. */
} xList;
- La structure xLIST_ITEM représente les éléments d'une liste (de Type xLIST). Chaque élément d'une liste est liée à une tâche et les différentes variables de la structure xLIST_ITEM servent à organiser les tâches et à les lier entre elles afin de former une liste doublement chaînée[17].
La structure xLIST_ITEM est définie comme suit :
struct xLIST_ITEM
{
portTickType xItemValue; /* Une valeur attribuée à cet élément,
cette valeur est utilisée afin de trier
la liste (de type (xLIST) contenant cet élément (xLIST_ITEM))
dans un ordre décroissant. */
volatile struct xLIST_ITEM * pxNext; /* Pointeur vers le prochain élément (xLIST_ITEM)
dans la liste (xLIST). */
volatile struct xLIST_ITEM * pxPrevious; /* Pointeur vers le précédent élément (xLIST_ITEM)
dans la liste (xLIST). */
void * pvOwner; /* Pointeur vers l'objet contenant cet élément,
cet objet est, dans la plupart des cas, le TCB d'une tâche. */
void * pvContainer; /* Pointeur vers la liste (xLIST) dans laquelle cet
élément est contenu. */
};
- La structure XMiniListItem est une version réduite de XLIST_ITEM. Elle ne dispose pas des variables pvOwner et pvContainer. Elle représente un élément marquant la fin de cette liste.
Les files
Les files sont les mécanismes principaux qui permettent de faire communiquer et synchroniser les tâches entre elles[17].
La structure basique d'une file est décrite comme suit :
typedef struct QueueDefinition
{
signed char *pcHead; /* Pointeur sur l'octet de début de la file
en mémoire */
signed char *pcTail; /* Pointeur sur l'octet de fin de la file
en mémoire (un octet de plus que nécessaire,
car utilisé comme un marqueur de fin). */
signed char *pcWriteTo; /* Pointeur sur le prochain [[octet]] libre dans la
file. */
signed char *pcReadFrom; /* Pointeur sur le dernier octet lu de la file. */
xList xTasksWaitingToSend; /* Liste des tâches (ordonnées par niveau de priorités)
qui sont bloquées en attente d’écriture
sur la file. */
xList xTasksWaitingToReceive; /* Liste des tâches (ordonnées par niveau de priorités)
qui sont bloquées en attente de lecture depuis la
file .*/
volatile unsigned portBASE_TYPE uxMessagesWaiting; /* Nombre d'éléments actuellement contenus
dans la file. */
unsigned portBASE_TYPE uxLength; /* Taille de la file définit comme le nombre
d'éléments maximum qu'elle peut contenir
et non le nombre d'octets. */
unsigned portBASE_TYPE uxItemSize; /* Taille de chaque élément (en octet) que
la file pourra contenir. */
} xQUEUE;
Une file contient un nombre fini d'éléments de taille fixe[20]. La taille physique d'une file est déterminée par le nombre maximum d'éléments qu'elle peut contenir (uxLength) multiplié par la taille en octet de chaque élément (uxItemSize).
Dans FreeRTOS, l'écriture ou l'envoi de données dans une file est effectuée en copiant octet par octet et quel que soit son type[20],[17] car la durée de vie de l'élément sauvegardé est bien souvent inférieure à la durée de vie de la file[17]. À l'instar de l'opération d'écriture, la lecture ou réception de données est également effectuée en copiant octet par octet la donnée qui sera supprimée de la file[20].
Les files sont des objets indépendants, il n'y a aucune assignation ou appartenance à une tâche[20]. Elles sont les structures qui permettent aux tâches de communiquer entre elles. De ce fait, elles peuvent avoir plusieurs tâches en lecture et en écriture simultanément.
Les opérations d'écriture ou de lecture sur les files peuvent être bloquantes ou non-bloquantes. Les opérations non-bloquantes retournent directement le statut réussi ou échoué sur la file. Les opérations bloquantes sont paramétrées avec un timeout qui leur permet de se bloquer et qui détermine le temps maximum pendant lequel elles peuvent rester dans cet état[17].
La gestion des ressources
FreeRTOS utilise les files comme moyen de communication entre les tâches. Cependant, les files gèrent aussi la synchronisation et la concurrence entre les tâches[17]. De ce fait, cette structure est l'élément de base pour la gestion des ressources dans FreeRTOS.
FreeRTOS synchronise les tâches en utilisant principalement deux mécanismes : les Sémaphores et les Mutex[17].
Sémaphores
FreeRTOS permet la création et l'utilisation de Sémaphores à plusieurs éléments[21]. Les sémaphores sont implémentés sous forme de file tel que le nombre d'éléments du sémaphore représente le nombre d'éléments maximum que la file peut contenir. La file représentant le sémaphore ne sauvegarde aucune donnée, elle s'occupe uniquement d'enregistrer le nombre de ses entrées actuellement occupées[17]. La taille des éléments de la file est donc nulle (uxItemSize=0). Un accès au Sémaphore ne fait qu'augmenter ou diminuer le nombre d'entrées occupées dans la file et aucune copie d'élément n'est effectuée[17].
L'API offerte par FreeRTOS pour la gestion des sémaphores fait une différence entre les sémaphores à N éléments et les sémaphore binaires[22]. Les Sémaphores binaires peuvent être vus comme des files ne pouvant contenir qu'un seul élément. Un Sémaphore binaire ne pourra donc être pris qu'une seule fois avant qu'il ne devienne indisponible contrairement au Sémaphore à n éléments qui pourra être pris à plusieurs reprises ce qui permet par exemple, de définir un nombre de ressources disponibles ou alors de compter le nombre d'événements qui doit être encore exécuté[23].
Mutex
Un Mutex est utilisé afin de protéger une ressource partagée.
L’implémentation des Mutex dans FreeRTOS est similaire à celle des Sémaphores binaires (sous la forme d'une file)[24] sauf que la tâche qui prend le Mutex doit obligatoirement le rendre. Cela peut être vu comme l'association d'un jeton à une ressource, une tâche prend le jeton et utilise la ressource puis rend le jeton à la fin, au même moment aucun autre jeton supplémentaire ne pourra être associé à la tâche.
Une autre différence majeure entre les Mutex et les Sémaphores binaires dans FreeRTOS est le système d'héritage de priorité. Quand plusieurs tâches demandent à prendre un Mutex, la priorité du détenteur du Mutex est fixée momentanément à la valeur de la plus haute priorité parmi les tâches qui attendent sa libération. Cette technique a pour effet de prévenir les phénomènes à risques d'inversion de priorité même si cela ne garantit pas une sécurité infaillible face à ces phénomènes.
La gestion des interruptions
Une interruption est un mécanisme purement matériel qui est implémenté et lancé par ce dernier. FreeRTOS ne fait que fournir des méthodes servant à la gestion des interruptions et il peut également lancer des interruptions par appel à une instruction matérielle[25].
FreeRTOS n'impose aux développeurs aucune stratégie spécifique pour la gestion des interruptions mais il offre plusieurs moyens pour que la stratégie choisie puisse être implémentée et maintenue facilement.
Les routines d'interruptions (ISR) sont des fonctions exécutées par le micro-contrôleur lui-même et qui ne peuvent être gérées par FreeRTOS[26], ce qui peut poser certains problèmes. Pour ces raisons, les routines d'interruptions ne peuvent pas utiliser les fonctions habituelles de l'API FreeRTOS que toute autre tâche basique peut utiliser. Néanmoins FreeRTOS définit un groupe de fonctions spécialement conçues pour les ISR, par exemple, une ISR utilisera la fonction xSemaphoreGiveFromISR() plutôt que xSemaphoreGive(), de la même manière, elle utilisera la fonction xQueueReceiveFromISR() plutôt que xQueueReceive().
Afin de spécifier une politique de gestion des interruptions et de gérer l'accès aux fonctions du noyau spécifiques aux ISR, FreeRTOS définit des constantes dans le fichier de configuration FreeRTOSConfig.h :
- configKERNEL_INTERRUPT_PRIORITY : Définit le niveau de priorité de l'interruption temporelle (ang. Tick interrupt) qui est une interruption périodique utilisée pour lancer l'ordonnanceur à chaque intervalle de temps[8].
- configMAX_SYSCALL_INTERRUPT_PRIORITY : Définit le plus haut niveau de priorité pour lequel les fonctions spécifiques aux ISR de FreeRTOS peuvent être utilisées.
La définition de ces deux constantes permet de spécifier une politique de gestion des ISR selon leur niveau de priorités :
- une ISR ayant un niveau de priorité compris entre configKERNEL_INTERRUPT_PRIORITY et configMAX_SYSCALL_INTERRUPT_PRIORITY pourra utiliser les fonctions de l'API spécifique aux ISR, pourra préempter une tâche, mais pas le noyau ni une tâche exécutant une section critique. Elle ne pourra pas être préemptée par l'ordonnanceur car l'interruption du tick timer a une priorité plus basse.
- une ISR ayant un niveau de priorité strictement supérieur à configMAX_SYSCALL_INTERRUPT_PRIORITY pourra préempter l'ordonnanceur, même lors de l’exécution de sections de code critique. En contrepartie elle n'aura plus accès à aucune des fonctions de l'API de FreeRTOS[27].
- une ISR n'utilisant aucune des fonctions de l'API de FreeRTOS peut utiliser n'importe quel niveau de priorité[27].
La définition des deux constantes précédentes ajoute aussi aux ISR la particularité d'imbrication d'interruptions (ang. Interrupt Nesting)[28]. L'imbrication d'interruptions est la possibilité qu'une deuxième interruption ait lieu au même moment que le traitement d'une autre interruption par une ISR. Cette deuxième interruption peut préempter la première si elle dispose d'une priorité plus élevée.
Il est à noter que les priorités des interruptions sont définies par l'architecture du micro-contrôleur. Ce sont des priorités matérielles qui n'ont aucune relation avec les priorités logicielles que l'on peut attribuer aux tâches grâce à FreeRTOS[28].
Les interruptions différées
Comme spécifié précédemment, les ISR sont des sections de code exécutées par le micro-contrôleur et non par FreeRTOS. Ce qui amène à des comportements inattendus du noyau. Pour cette raison, il est nécessaire de réduire au maximum le temps d’exécution d'une ISR. Une stratégie pour réduire le temps d’exécution est d'utiliser les Sémaphores binaires offerts par FreeRTOS. Un Sémaphore binaire peut être utilisé afin de débloquer une tâche à chaque fois qu'une interruption particulière a lieu. Ainsi la partie de code exécutée dans l'ISR pourra être très largement réduite et la gestion de l'interruption reviendra en grande partie à la tâche débloquée. On aura ainsi différé le processus d'interruption vers une simple tâche[29].
Si l'interruption s'avère être critique, alors la priorité de la tâche de gestion de l’interruption pourra être définie de manière à toujours préempter les autres tâches du système[29].
Suspension des interruptions
FreeRTOS permet de protéger des sections de code appartenant à une tâche de tout changement de contexte, d'opération de l’ordonnanceur ou même d'une levée d'interruption, ces portions de code sont appelées sections critiques. L'utilisation de sections critiques peut être efficace pour respecter l'atomicité de certaines instructions. Néanmoins ces sections critiques sont à utiliser avec précaution car pendant leur exécution, le système reste statique et totalement inactif envers d'autres tâches critiques qui seraient bloquées ou alors envers des interruptions signalant des événements extérieurs critiques.
Afin de définir une partie de code comme étant une section critique, il suffit de l'englober entre les deux instructions de début et de fin de section critique : taskENTER_CRITICAL() et taskEXIT_CRITICAL()[30].
La gestion de la mémoire
Le noyau FreeRTOS doit allouer dynamiquement la mémoire RAM à chaque fois qu'une tâche, une file ou un Sémaphore est créé[31]. L'utilisation des traditionnelles méthodes Malloc() et Free() est toujours possible mais elle peut poser quelques problèmes car elles ne sont pas déterministes et elles peuvent souffrir d'une mémoire trop fragmentée. De ce fait, deux méthodes reprenant les mêmes prototypes existent dans FreeRTOS : pvPortMalloc() et vPortFree()[31].
Chacune d'elles est implémentée de trois manières différentes décrites dans les fichiers Heap_1.c, Heap_2.c et Heap_3.c mais l'utilisateur est libre de définir ses propres fonctions[31].
La constante configTOTAL_HEAP_SIZE définie dans le fichier de configuration FreeRTOSConfig.h
La première implémentation
Cette version ne définit pas de méthode pour libérer de l'espace mémoire RAM[31].
La mémoire est divisée en un tableau de taille configTOTAL_HEAP_SIZE (en octets) nommé "la pile FreeRtos"[31].
Lorsque le noyau a besoin d'allouer de la mémoire, il réserve deux espaces libres pour une même tâche. Le premier est utilisé pour la TCB alors que le second représente la file[31]. Dans la mesure où l'espace mémoire des tâches n'est jamais libéré, la pile se remplit jusqu'à épuisement de l'espace disponible.
La deuxième implémentation
Cette représentation se différencie de la première par le fait qu'elle dispose d'une méthode vPortFree() qui libère la mémoire allouée pour une tâche et peut l'allouer de nouveau à une autre tâche[32]. Il faut que la taille du bloc mémoire de la nouvelle tâche soit au maximum égale à la taille du bloc de l'ancienne tâche.
La troisième implémentation
Il ne s'agit ici que d'une redéfinition de Malloc() et Free() mais où la sécurité a été augmentée en suspendant toutes les tâches pendant la durée de l'opération sur la mémoire[33].
Caractéristiques
Architectures matérielles supportées
- Altera : Nios II
- ARM architecture : ARM7, ARM9, ARM Cortex-M0, ARM Cortex-M3, ARM Cortex-M4, ARM Cortex-M7
- Atmel : Atmel AVR, AVR32, SAM3, SAM7, SAM9
- Cortus : APS3
- Cypress : PSoC
- Energy Micro : EFM32
- Espressif Systems : ESP32, ESP8266
- Freescale : Coldfire V1, Coldfire V2, HCS12, Kinetis
- Fujitsu : MB91460 series, MB96340
- IBM : PPC405, PPC404
- Infineon : TriCore, XMC4000
- Intel : x86, 8052
- Microcontrôleur PIC : PIC18, PIC24, dsPIC, PIC32
- Microsemi : SmartFusion
- NXP : LPC2000, LPC1000, LPC4300
- Renesas : 78K0R, RL78, H8/S, RX600, RX200, SuperH, V850
- STMicroelectronics : STM32, STR7, STR9
- Texas Instruments : MSP430, Stellaris, Tiva C
- Xilinx : MicroBlaze
Services fournis et domaines d'application
Grâce à son très faible encombrement mémoire et son portage sur de nombreuses architectures matérielles, FreeRTOS est principalement utilisé comme système d'exploitation embarqué[34]. Il a été implémenté sur des périphériques mobiles et est souvent utilisé sur les processeurs ARM.
Étant un système d'exploitation purement orienté temps réel et livré sans application, il sert souvent de socle pour le développement d'API spécifiques et/ou propriétaires. Il est donc utilisé dans des domaines très variés où la contrainte temps réel est forte comme par exemple : les appareils de surveillance médicale, les outils de contrôle sismique et d'environnement ou encore le pilotage d'appareils et de robots industriels[35]. Ses fonctionnalités de gestion des tâches permettent de garantir l'intégrité des données collectées en temps réel par l'utilisation des plus hauts niveaux de priorités[35].
Le domaine technique dans lequel ce système temps réel est le plus utilisé est le réseau, et plus particulièrement pour la transmission de données sur des réseaux sans fils. Pour des réseaux à très haute fréquence comme le WPAN, sur des architectures matérielles à très faible capacité mémoire, des phénomènes d'overflow interviennent durant les échanges pour des systèmes à boucle unique. Cependant l'implémentation de ces échanges sous forme de différentes tâches complique le développement. Grâce à sa gestion des priorités et son ordonnanceur multitâche, FreeRTOS permet d'éliminer ce type de problèmes[36]. Chaque tâche ayant un bloc réservé, le phénomène d'overflow est supprimé car il n'y a plus de dépassement mémoire par manque de ressources.
Pour les applications de contrôle comme l'eye-tracking à base de matériel embarqué à ressources limitées, FreeRTOS fournit un core pour le système de base gérant le matériel permettant d'y ajouter des applications spécifiques[37]. Là encore c'est surtout l'ordonnanceur et son système de gestion et de priorité des tâches qui est primordial pour ce type d'application. Le firmware de ce périphérique mobile est composée de 3 couches, la HAL qui gère la couche d'abstraction matérielle, la DEL qui gère les composants additionnels au processeur et la TAL qui est la partie tâches qui gère FreeRTOS. Ce type d'application est destinée à s'adapter à l’utilisateur en fonction de ces réactions perçues au travers des mouvements de ses yeux.
FreeRTOS est très utilisé aussi pour l'implémentation de pile réseau et est souvent associé à uIP. Pour les périphériques mobiles comme les téléphones, on peut même le retrouver pour la gestion de la vidéo[38]. On l'utilise aussi souvent pour des implémentations de couche réseau MAC comme le protocole 802.15.4 très utilisé pour les réseaux de capteurs sans fil[36]. Une des forces de FreeRTOS est aussi son aspect open-source et le fait qu'il permet l'implémentation de couches réseaux IP très légères et facilement portable comme uIP ou lwIP[39].
Un autre grand domaine d'application est le réseau de capteurs sans fils. Ces systèmes consistent en un ensemble de capteurs transmettant leurs données à un nœud pour éventuellement les envoyer à un système central. Ce type de réseau est présent dans le domaine médical pour monitorer les patients ou dans l'agriculture pour localiser et surveiller les élevages[40].
FreeRTOS est le système d'exploitation temps réel de prédilection dans ce domaine[réf. nécessaire] car les capteurs consomment très peu d’énergie et disposent de ressources RAM très limitées[41].
La consommation électrique est aussi un argument en faveur de FreeRTOS. Les périphériques mobiles de toutes sortes ont en commun cette contrainte essentielle, et ce système d'exploitation permet un traitement temps réel tout en garantissant un minimum de consommation électrique[42].
Avec la convergence des différentes technologies et leur miniaturisation, FreeRTOS permet d'allier des implémentations de piles réseau simples et efficaces aux besoins d'économie d'énergie. Les nouveaux périphériques mobiles comme les téléphones en sont un bon exemple[39]. Cette solution logicielle permet aussi d'abaisser fortement les coûts de fabrication[43].
Ayant été porté sur beaucoup d'architectures et avec le développement de carte notamment à base de FPGA intégrant des cartes réseau, FreeRTOS permet d'avoir des systèmes avec un système adapté permettant de se focaliser sur les objectifs finaux du projet[44],[45].
Cependant étant sous licence GPL, même s'il permet le développement d'applications propriétaires, son code source doit rester ouvert et il est donc privilégié dans le domaine de la recherche et de l'enseignement[46]. Ses concurrents propriétaires comme QNX sont le plus souvent choisis dans le monde de l'industrie.
Dans le domaine de l'enseignement là aussi, les différentes utilisations sont nombreuses. FreeRTOS est utilisé pour étudier l'implémentation d'ordonnanceur, la gestion de tâches et la programmation modulaire[47]. Il permet également de développer des applications dans le domaine de l'électronique comme la lecture de température et son affichage[48].
FreeRTOS a aussi fait naître des frameworks grâce à son code ouvert, sa faible taille, ses possibilités de mise à l'échelle ainsi que son extensibilité[49]. Certains de ces frameworks sont utilisés dans le secteur automobile[50]
Solutions alternatives
Déclinaisons de FreeRTOS
Le projet FreeRTOS a donné naissance à deux versions de systèmes d'exploitation temps réel basés sur le noyau FreeRTOS : OpenRTOS et SafeRTOS.
OpenRTOS
OpenRTOS est une version commerciale de FreeRTOS, qui inclut une suite de pilotes de connexion USB, un système de fichier FAT ainsi qu'une pile TCP/IP. La licence commerciale libère les utilisateurs de OpenRTOS de l'obligation de publier leurs modifications du noyau FreeRTOS et leur offre le support commercial et les protections nécessaires pour leurs réalisations[51].
OpenRTOS est fourni par A global engineering company sous licence de Real Time Engineers Ltd[6].
SafeRTOS
SafeRTOS est un système d'exploitation temps réel destiné au marché des systèmes critiques. Il a été développé par la société WHIS (WITTENSTEIN high integrity systems) en partenariat avec Real Time Engineers Ltd[52].
SafeRTOS et FreeRTOS partagent le même algorithme d'ordonnancement, la même API, les mêmes exigences en termes de RAM et de ROM et fonctionnent sur les mêmes types de micro-contrôleurs. Cependant ils ont été développés différemment et avec différents objectifs[53],[54].
FreeRTOS a été le sujet d'une étude HAZOP qui a identifié plusieurs faiblesses fonctionnelles et comportementales liées à l'API ou à de possibles erreurs de l'utilisateur du système. Afin de résoudre ces faiblesses, SafeRTOS a été développé à travers un cycle de développement CEI 61508 SIL de niveau 3[54]. SafeRTOS est certifié SIL3 par l'organisme allemand de certification et de normalisation TUV (Technischer Überwachungs-Verein)[55].
Une des grandes particularité de SafeRTOS est son empreinte mémoire ne dépassant pas les 14KB ce qui lui permet de résider directement dans la mémoire ROM d'un micro-contrôleur[54]. De plus, lors de son implémentation en mémoire ROM le code de SafeRTOS ne peut être utilisé que dans sa configuration initiale et ne peut plus être changé, ce qui élimine les possibles défaillances du système liées aux erreurs d'utilisateur et facilite la certification et la validation du système basé sur le noyau SafeRTOS[56].
SafeRTOS est utilisé dans plusieurs systèmes commerciaux, notamment dans certains micro-contrôleurs Stellaris ARM de Texas Instruments[57].
SafeRTOS est fourni par A global engineering company sous licence de Real Time Engineers Ltd[6].
Distinctions
Notes et références
Références
- « Release FreeRTOSv202012.00-LTS », (consulté le )
- (en-US) « Announcing FreeRTOS Kernel Version 10 | Amazon Web Services », Amazon Web Services, (lire en ligne, consulté le )
- Melot 2009+, p. 4
- Contact, Support and Advertising for FreeRTOS
- (en-US) « Announcing Amazon FreeRTOS – Enabling Billions of Devices to Securely Benefit from the Cloud | Amazon Web Services », Amazon Web Services, (lire en ligne, consulté le )
- FreeRTOS, Homepage
- FreeRTOS, Homepage : Why Choose FreeRTOS ? 2007
- Barry 2009, p. 15
- Melot 2009+, p. 08
- Barry 2009, p. 28
- Barry 2009, p. 04
- Barry 2009, p. 05
- Barry 2009, p. 44
- Barry 2009, p. 19
- Melot 2009+, p. 09
- Barry 2009, p. 29
- Svec 2012
- Barry 2009, p. 32
- Barry 2009, p. 42
- Barry 2009, p. 47
- Melot 2009+, p. 12
- Barry 2009, p. 80
- Barry 2009, p. 83
- Barry 2009, p. 105
- Melot 2009+, p. 16
- Melot 2009+, p. 17
- Barry 2009, p. 95
- Barry 2009, p. 94
- Barry 2009, p. 69
- Melot 2009+, p. 18
- Barry 2009, p. 135
- Barry 2009, p. 138
- Barry 2009, p. 139
- Woodcock 2009, p. 24
- Yu 2009, p. 2
- Wauthy 2010, p. 3
- Bulling 2008, p. 3
- Szczesny 2009, p. 3
- Borchert 2012, p. 446
- Schoofs 2009, p. 3
- Chen 2010, p. 3
- Mera 2010
- Borchert 2012, p. 435
- Huangfu 2009, p. 2
- Tardieu 2009, p. 4
- Machanick 2011, p. 2
- Vanhatupa 2010, p. 2
- Salminen 2011, p. 4
- Inam 2011
- Vu 2012, p. 7
- OpenRTOS, Homepage
- SafeRTOS, Homepage
- Yan 2008, p. 3728
- SafeRTOS, Overview
- SafeRTOS, Certification
- Texas Instruments SafeRTOS
- Texas Instruments stellaris
- EETIMES Embedded Market Study 8 avril 2011
Annexes
Bibliographie
- (en) Richard Barry, FreeRTOS - A FREE RTOS for small real time embedded systems, , 112 p. (lire en ligne)
- (en) Richard Barry, Using the FreeRTOS real time kernel - A Practical Guide, , 163 p. (présentation en ligne)
- (en) Amy Brown, Greg Wilson et Christopher Svec, The Architecture of Open Source Applications, vol. 2 : Structure, Scale, and a Few More Fearless Hacks, , 390 p. (ISBN 9781105571817, lire en ligne), chap. 3 (« FreeRTOS »)
- (en) Yan Meng, Johnson Kerry, Brian Simms et Matthew Conforth, « A Generic Architecture of Modular Embedded System for Miniature Mobile Robots », Intelligent Robots and Systems, 2008. IROS 2008. IEEE/RSJ International Conference on, , p. 3725-3730 (ISBN 978-1-4244-2058-2, DOI 10.1109/IROS.2008.4651001)
- (en) Ramon Serna Oliver, Ivan Shcherbakov et Gerhard Fohler, « An Operating System Abstraction Layer for Portable Applications in Wireless Sensor Networks », Proceedings of the 2010 ACM Symposium on Applied Computing, , p. 742-748 (ISBN 978-1-60558-639-7, DOI 10.1145/1774088.1774243)
- (en) João F. Ferreira, Guanhua He et Shengchao Qin, « Automated Verification of the FreeRTOS Scheduler in HIP/SLEEK », Theoretical Aspects of Software Engineering (TASE), 2012 Sixth International Symposium, , p. 51 - 58 (DOI 10.1109/TASE.2012.45)
- (en) Xiaohan Ji, Dapeng Zhang et Chunmeng Wang, « A Watt-hour Meter Reading Device for Electric Energy Allowance », Artificial Intelligence, Management Science and Electronic Commerce (AIMSEC), 2011 2nd International Conference, , p. 3695 - 3697 (DOI 10.1109/AIMSEC.2011.6009920)
- (en) Bo Qu et Daowei Fan, « Design of remote data monitoring and recording system Based on ARM », Industrial and Information Systems (IIS), 2010 2nd International Conference, , p. 252 - 255 (DOI 10.1109/INDUSIS.2010.5565698)
- (en) Zhuan Yu, Jie Wu, MingPu Xie et Yang Kong, « Implementation of distributed high precision real-time data acquisition system », Real Time Conference, 2009. RT '09. 16th IEEE-NPSS, , p. 446 - 449 (DOI 10.1109/RTC.2009.5321600)
- (en) Jinsik Kim et Pai H Chou, « Energy-Efficient Progressive Remote Update for Flash-Based Firmware of Networked Embedded Systems », ACM Transactions on Design Automation of Electronic Systems, , p. 7:1--7:26 (ISSN 1084-4309, DOI 10.1145/1870109.1870116)
- (en) David Déharbe, Stephenson Galvão et Anamaria Martins Moreira, « Formalizing FreeRTOS: First Steps », Formal Methods: Foundations and Applications (Lecture Notes in Computer Science), , p. 101-11703 (ISBN 978-3-642-10451-0, DOI 10.1007/978-3-642-10452-7_8)
- (en) Florin Catalin Braescu, Lavinia Ferariu et Andrei Franciuc, « Monitoring CAN Performances in Distributed Embedded Systems », System Theory, Control, and Computing (ICSTCC), 2011 15th International Conference, , p. 1-6
- (en) Tao Xu, « Performance benchmarking of FreeRTOS and its Hardware Abstraction », Unpublished doctoral thesis, Technical University of Eindhoven,
- (en) Roman Glistvain et Mokhtar Aboelaze, « Romantiki OS – A single stack Multitasking Operating System for Resource Limited Embedded Devices », Informatics and Systems (INFOS), 2010 The 7th International Conference, , p. 1-8
- (en) Rafia Inam, Jukka Maki-Turja, Mikael Sjodin, S. M. H. Ashjaei et Sara Afshar, « Support for Hierarchical Scheduling in FreeRTOS », Emerging Technologies & Factory Automation (ETFA), 2011 IEEE 16th Conference, , p. 1-10 (DOI 10.1109/ETFA.2011.6059016)
- (en) Nicolas Melot, « Operating systems for embedded devices », Study of an operating system: FreeRTOS (Thèse), 2009+, p. 1-39 (lire en ligne)
- (en) Aamir Mahmood et Riku Jãntti, « Time Synchronization Accuracy in Real-time Wireless Sensor Networks », Communications (MICC), 2009 IEEE 9th Malaysia International Conference, , p. 652 - 657 (DOI 10.1109/MICC.2009.5431415)
- (en) Per Lindgren, Johan Eriksson, Simon Aittamaa et Johan Nordlander, « TinyTimber, Reactive Objects in C for Real-Time Embedded Systems », Design, Automation and Test in Europe, 2008. DATE '08, , p. 1382 - 1385 (DOI 10.1109/DATE.2008.4484933)
- (en) Jim Woodcock, Peter Gorm Larsen, Juan Bicarregui et John Fitzgerald, « Formal Methods: Practice and Experience », ACM Comput. Surv. 41, 4, Article 19, , p. 19:1--19:36 (DOI 10.1145/1592434.1592436)
- (en) Dieu-Huong Vu et Toshiaki Aoki, « Faithfully formalizing OSEK/VDX operating system specification », SoICT '12 Proceedings of the Third Symposium on Information and Communication Technology, , p. 13 - 20 (ISBN 978-1-4503-1232-5, DOI 10.1145/2350716.2350721)
- (en) Jean-François Wauthy et Laurent Schumacher, « Implementation of an IEEE 802.15.4-2006 protocol stack on the Texas instrument CC2430 », Proceedings of the 7th ACM workshop on Performance evaluation of wireless ad hoc, sensor, and ubiquitous networks, , p. 33 - 39 (ISBN 978-1-4503-0276-0, DOI 10.1145/1868589.1868596)
- (en) Arto Salminen, Juha-Matti Vanhatupa et Hannu-Matti Järvinen, « Framework for embedded programming course », Proceedings of the 11th Koli Calling International Conference on Computing Education Research, , p. 54 - 59 (ISBN 978-1-4503-1052-9, DOI 10.1145/2094131.2094142)
- (en) Andreas Bulling, Daniel Roggen et Gerhard Tröster, « It's in your eyes: towards context-awareness and mobile HCI using wearable EOG goggles », Proceedings of the 10th international conference on Ubiquitous computing, , p. 84 - 93 (ISBN 978-1-60558-136-1, DOI 10.1145/1409635.1409647)
- (en) Samuel Tardieu et Alexis Polti, « Complementing Ada with other programming languages », Proceedings of the ACM SIGAda annual international conference on Ada and related technologies, , p. 105 - 114 (DOI 10.1145/1653616.1647444)
- (en) Juha-Matti Vanhatupa, Arto Salminen et Hannu-Matti Järvinen, « Organizing and evaluating course on embedded programming », Proceedings of the 10th Koli Calling International Conference on Computing Education Research, , p. 112 - 117 (DOI 10.1145/1930464.1930484)
- (en) David Szczesny, Sebastian Hessel, Felix Bruns et Attila Bilgic, « On-the-fly hardware acceleration for protocol stack processing in next generation mobile devices », Proceedings of the 7th IEEE/ACM international conference on Hardware/software codesign and system synthesis, , p. 155 - 162 (ISBN 978-1-60558-628-1, DOI 10.1145/1629435.1629457)
- (en) Yu-Ting Chen, Ting-Chou Chien et Pai H. Chou, « Enix: a lightweight dynamic operating system for tightly constrained wireless sensor platforms », Proceedings of the 8th ACM Conference on Embedded Networked Sensor Systems, , p. 183 - 196 (DOI 10.1145/1869983.1870002)
- (en) Philip Machanick, « Design principles for contactile computing », Proceedings of the South African Institute of Computer Scientists and Information Technologists Conference on Knowledge, Innovation and Leadership in a Diverse, Multidisciplinary Environment, , p. 306 - 309 (DOI 10.1145/2072221.2072264)
- (en) Wei Huangfu, Limin Sun et Xinyun Zhou, « NISAT: a zero-side-effect testbed for wireless sensor networks », Proceedings of the 7th ACM Conference on Embedded Networked Sensor Systems, , p. 313 - 314 (ISBN 978-1-60558-519-2, DOI 10.1145/1644038.1644077)
- (en) Per Lindgren, Johan Eriksson, Simon Aittamaa et Johan Nordlander, « TinyTimber, reactive objects in C for real-time embedded systems », Proceedings of the conference on Design, automation and test in Europe, , p. 1382 - 1385 (ISBN 978-3-9810801-3-1, DOI 10.1145/1403375.1403708)
- (en) Zhuan Yu; Jie Wu; Mingpu Xie; Yang Kong Yu, Jie Wu, Mingpu Xie et Yang Kong, « Implementation of distributed high precision real-time data acquisition system », Real Time Conference, 2009. RT '09. 16th IEEE-NPSS, , p. 446 - 449 (DOI 10.1109/RTC.2009.5321600)
- (en) D.E. Mera et N.G. Santiago, « Low Power Software Techniques for Embedded Systems Running Real Time Operating Systems », Midwest Symposium on Circuits and Systems (MWSCAS), 2010 53rd IEEE International, , p. 1061 - 1064 (DOI 10.1109/MWSCAS.2010.5548830)
- (en) Anthony Schoofs, Charles Daymand, Robert Sugar, Ulrich Mueller, Andreas Lachenmann, Syed M. Kamran, Alain Gefflaut, Lasse Thiem et Mario Schuster, « Poster abstract: IP-based testbed for herd monitoring », Proceedings of the 2009 International Conference on Information Processing in Sensor Networks, , p. 365--366 (ISBN 978-1-4244-5108-1)
- (en) Christoph Borchert, Daniel Lohmann et Olaf Spinczyk, « CiAO/IP: a highly configurable aspect-oriented IP stack », Proceedings of the 10th international conference on Mobile systems, applications, and services, , p. 435--448 (ISBN 978-1-4503-1301-8, DOI 10.1145/2307636.2307676)