- Suppression d'une tâche dans FreeRTOS Arduino
- Qu'est-ce que la file d'attente dans FreeRTOS?
- Créer une file d'attente dans FreeRTOS
- Schéma
- Implémentation de FreeRTOS Queue dans Arduino IDE
Dans le didacticiel précédent, nous avons introduit FreeRTOS dans Arduino Uno et créé une tâche pour la LED clignotante. Maintenant, dans ce didacticiel, nous allons nous plonger davantage dans les concepts avancés des API RTOS et en apprendre davantage sur la communication entre différentes tâches. Ici, nous en apprenons également sur Queue pour transférer des données d'une tâche à une autre et démontrons le fonctionnement des API de file d'attente en interfaçant 16x2 LCD et LDR avec l'Arduino Uno.
Avant de discuter des files d'attente, voyons une autre API FreeRTOS qui est utile pour supprimer les tâches une fois le travail assigné terminé. Parfois, la tâche doit être supprimée pour libérer la mémoire allouée. Dans la continuité du didacticiel précédent, nous utiliserons la fonction API vTaskDelete () dans le même code pour supprimer l'une des tâches. Une tâche peut utiliser la fonction API vTaskDelete () pour se supprimer elle-même ou toute autre tâche.
Pour utiliser cette API, vous devez configurer le fichier FreeRTOSConfig.h . Ce fichier est utilisé pour personnaliser FreeRTOS en fonction de l'application. Il est utilisé pour modifier les algorithmes de planification et de nombreux autres paramètres. Le fichier se trouve dans le répertoire Arduino qui est généralement disponible dans le dossier Documents de votre PC. Dans mon cas, il est disponible dans \ Documents \ Arduino \ bibliothèques \ FreeRTOS \ src comme indiqué ci-dessous.
Maintenant, ouvrez ce fichier en utilisant n'importe quel éditeur de texte et recherchez le #define INCLUDE_vTaskDelete et assurez-vous que sa valeur est '1' (1 signifie activer et 0 signifie désactiver). Il vaut 1 par défaut mais le vérifie.
Nous utiliserons fréquemment ce fichier de configuration dans nos prochains tutoriels pour définir les paramètres.
Voyons maintenant comment supprimer une tâche.
Suppression d'une tâche dans FreeRTOS Arduino
Pour supprimer une tâche, nous devons utiliser la fonction API vTaskDelete (). Cela ne prend qu'un seul argument.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: c'est le handle de la tâche qui doit être supprimé. Il est le même que le 6 ème argument xTaskCreate () API. Dans le didacticiel précédent, cet argument est défini sur NULL, mais vous pouvez transmettre l'adresse du contenu de la tâche en utilisant n'importe quel nom. Disons si vous souhaitez définir le handle de tâche pour Task2 qui est déclaré comme
TaskHandle_t any_name; Exemple: TaskHandle_t xTask2Handle;
Maintenant, dans l' API vTaskCreate () set 6 e argument
xTaskCreate (TaskBlink2, "tâche2", 128, NULL, 1, & xTask2Handle);
Le contenu de cette tâche est désormais accessible à l'aide de la poignée que vous avez donnée.
En outre, une tâche peut se supprimer elle-même en passant NULL à la place d'un descripteur de tâche valide.
Si nous voulons supprimer la tâche 3 de la tâche 3 elle-même, vous devez écrire vTaskDelete (NULL); à l'intérieur de la fonction Task3 mais si vous souhaitez supprimer la tâche 3 de la tâche 2, écrivez vTaskDelete (xTask3Handle); à l'intérieur de la fonction task2.
Dans le code du didacticiel précédent, pour supprimer Task2 de task2 elle-même, ajoutez simplement vTaskDelete (NULL); dans la fonction void TaskBlink2 (void * pvParameters) . Ensuite, la fonction ci-dessus ressemblera à ceci
void TaskBlink2 (void * pvParameters) { Serial.println ("Task2 est en cours d'exécution et sur le point d'être supprimé"); vTaskDelete (NULL); pinMode (7, SORTIE); while (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Maintenant, téléchargez le code et observez les voyants et le moniteur série. Vous verrez que le deuxième voyant ne clignote pas maintenant et que la tâche 2 est supprimée après avoir rencontré l'API de suppression.
Ainsi, cette API peut être utilisée pour arrêter l'exécution de la tâche particulière.
Maintenant, commençons par la file d'attente.
Qu'est-ce que la file d'attente dans FreeRTOS?
La file d'attente est la structure de données qui peut contenir le nombre fini d'éléments de taille fixe et elle est exploitée dans le schéma FIFO (premier entré, premier sorti). Les files d'attente fournissent un mécanisme de communication de tâche à tâche, de tâche à interruption et d'interruption à tâche.
Le nombre maximum d'éléments que la file d'attente peut contenir est appelé sa «longueur». La longueur et la taille de chaque élément sont définies lors de la création de la file d'attente.
Un exemple de la façon dont la file d'attente est utilisée pour le transfert de données est bien illustré dans la documentation FreeRTOS qui peut être trouvée ici. Vous pouvez facilement comprendre l'exemple donné.
Après avoir compris les files d'attente, essayons de comprendre le processus de création d'une file d'attente et essayons de l'implémenter dans notre code FreeRTOS.
Créer une file d'attente dans FreeRTOS
Tout d'abord, décrivez l'énoncé du problème à implémenter à l'aide de la file d'attente FreeRTOS et d'Arduino Uno.
Nous voulons imprimer la valeur du capteur LDR sur un écran LCD 16 * 2. Il y a donc deux tâches maintenant
- Task1 obtient des valeurs analogiques de LDR.
- Task2 imprime la valeur analogique sur l'écran LCD.
Donc, ici la file d'attente joue son rôle car d'envoyer les données générées par task1 vers task2. Dans la tâche1, nous enverrons une valeur analogique à la file d'attente et dans la tâche2, nous la recevrons de la file d'attente.
Il existe trois fonctions pour travailler avec les files d'attente
- Créer une file d'attente
- Envoi de données à la file d'attente
- Recevoir des données de la file d'attente
Pour créer une file d'attente, utilisez l' API de la fonction xQueueCreate (). Cela prend deux arguments.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: le nombre maximum d'éléments que la file d'attente en cours de création peut contenir à tout moment.
uxItemSize: la taille en octets de chaque élément de données qui peut être stocké dans la file d'attente.
Si cette fonction renvoie NULL, la file d'attente n'est pas créée en raison d'une mémoire insuffisante et si elle renvoie une valeur non NULL, la file d'attente est créée avec succès. Stockez cette valeur de retour dans une variable pour l'utiliser comme descripteur pour accéder à la file d'attente comme indiqué ci-dessous.
QueueHandle_t queue1; queue1 = xQueueCreate (4, sizeof (entier));
Cela créera une file d'attente de 4 éléments dans la mémoire de tas de taille int (2 octets de chaque bloc) et stockera la valeur de retour dans la variable de handle queue1 .
2. Envoi de données à la file d'attente dans FreeRTOS
Pour envoyer les valeurs à la file d'attente, FreeRTOS dispose de 2 variantes d'API à cet effet.
- xQueueSendToBack (): Utilisé pour envoyer des données à l'arrière (queue) d'une file d'attente.
- xQueueSendToFront (): utilisé pour envoyer des données à l'avant (tête) d'une file d'attente.
Maintenant , xQueueSend () est équivalent à, et exactement le même que, xQueueSendToBack ().
Toutes ces API prennent 3 arguments.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Le descripteur de la file d'attente à laquelle les données sont envoyées (écrites). Cette variable est la même que celle utilisée pour stocker la valeur de retour de l'API xQueueCreate.
pvItemToQueue: un pointeur vers les données à copier dans la file d'attente.
xTicksToWait: durée maximale pendant laquelle la tâche doit rester à l'état Bloqué pour attendre que de l'espace devienne disponible dans la file d'attente.
Définir xTicksToWait sur portMAX_DELAY entraînera l'attente indéfinie de la tâche (sans délai), à condition que INCLUDE_vTaskSuspend soit défini sur 1 dans FreeRTOSConfig.h sinon, vous pouvez utiliser la macro pdMS_TO_TICKS () pour convertir un temps spécifié en millisecondes en un temps spécifié en ticks.
3. Réception des données de la file d'attente dans FreeRTOS
Pour recevoir (lire) un élément d'une file d'attente, xQueueReceive () est utilisé. L'élément reçu est supprimé de la file d'attente.
Cette API prend également trois arguments.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Les premier et troisième arguments sont identiques à l'envoi de l'API. Seul le deuxième argument est différent.
const pvBuffer: un pointeur vers la mémoire dans laquelle les données reçues seront copiées.
J'espère que vous avez compris les trois API. Maintenant, nous allons implémenter ces API dans l'IDE Arduino et essayer de résoudre l'énoncé de problème que nous avons décrit ci-dessus.
Schéma
Voici à quoi cela ressemble sur la maquette:
Implémentation de FreeRTOS Queue dans Arduino IDE
Commençons à écrire du code pour notre application.
1. Tout d'abord, ouvrez Arduino IDE et incluez le fichier d'en-tête Arduino_FreeRTOS.h . Maintenant, si un objet du noyau tel que queue est utilisé, incluez le fichier d'en-tête de celui-ci. Comme nous utilisons un écran LCD 16 * 2, incluez également la bibliothèque.
#include #include
2. Initialisez un descripteur de file d'attente pour stocker le contenu de la file d'attente. Également, initialisez les numéros de broches LCD.
QueueHandle_t queue_1; LCD LiquidCrystal (7, 8, 9, 10, 11, 12);
3. Dans void setup (), initialisez l'écran LCD et le moniteur série avec un débit de 9600 bauds. Créez une file d'attente et deux tâches à l'aide des API respectives. Ici, nous allons créer une file d'attente de taille 4 avec un type entier. Créez une tâche avec des priorités égales et essayez plus tard de jouer avec ce numéro. Enfin, démarrez le planificateur comme indiqué ci-dessous.
void setup () { Serial.begin (9600); lcd.begin (16, 2); queue_1 = xQueueCreate (4, sizeof (int)); if (queue_1 == NULL) { Serial.println ("La file d'attente ne peut pas être créée"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Maintenant, créez deux fonctions TaskDisplay et TaskLDR . Dans la fonction TaskLDR , lisez la broche analogique A0 dans une variable car nous avons LDR connecté à la broche A0 d'Arduino UNO. Envoyez maintenant la valeur stockée dans la variable en la passant dans l' API xQueueSend et envoyez la tâche à l'état de blocage après 1 seconde à l'aide de l' API vTaskDelay () comme indiqué ci-dessous.
void TaskLDR (void * pvParameters) { int current_intensity; while (1) { Serial.println ("Task1"); intensité_courante = lecture analogique (A0); Serial.println (intensité_actuelle); xQueueSend (queue_1, & intensité_courante, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. De même, créez une fonction pour TaskDisplay et recevez les valeurs dans une variable qui est passée à la fonction xQueueReceive . De plus, xQueueReceive () renvoie pdPASS si les données peuvent être reçues avec succès de la file d'attente et renvoie errQUEUE_EMPTY si une file d'attente est vide.
Maintenant, affichez les valeurs sur l'écran LCD en utilisant la fonction lcd.print () .
void TaskDisplay (void * pvParameters) { intensité int = 0; while (1) { Serial.println ("Tâche2"); if (xQueueReceive (queue_1, & intensité, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intensité:"); lcd.setCursor (11, 0); lcd.print (intensité); } } }
C'est ça. Nous avons terminé la partie codage de l'implémentation de la file d'attente. Le code complet avec une vidéo fonctionnelle se trouve à la fin.
Maintenant, connectez l'écran LCD et LDR avec Arduino UNO conformément au schéma de circuit et téléchargez le code. Ouvrez le moniteur série et observez les tâches. Vous verrez que les tâches changent et les valeurs LDR changent en fonction de l'intensité lumineuse.
REMARQUE: la plupart des bibliothèques conçues pour différents capteurs ne sont pas prises en charge par le noyau FreeRTOS en raison de l'implémentation de la fonction de retard dans les bibliothèques. Le retard arrête complètement le processeur, par conséquent, le noyau FreeRTOS cesse également de fonctionner et le code ne s'exécutera plus et il commence à se comporter mal. Nous devons donc faire en sorte que les bibliothèques fonctionnent sans délai avec FreeRTOS.