ETRS906 - Temps reel - Travaux Pratiques PDF

Title ETRS906 - Temps reel - Travaux Pratiques
Author Jean Orlando RABEMANANJARA
Course Microelettronica
Institution Università degli Studi di Palermo
Pages 17
File Size 1.1 MB
File Type PDF
Total Downloads 14
Total Views 127

Summary

Lavoro pratica per il funzionamento di un motore stm32 ...


Description

Travaux Pratiques Système d’exploitation Temps réel FreeRTOS sur Microprocesseur

Objectifs : Ces travaux pratiques permettront de découvrir la mise en œuvre du système d’exploitation Temps Réel FreeRTOS sur STM32. ■ ■ ■

Matériel utilisé : Nucléo 64 STM32F446 et Discovery STM32F746, câble Réseau, Switch. Logiciels utilisés : Atollic Truestudio (Eclipse Based IDE), Percepio Tracealyser Ressources disponibles : Moodle Science Bourget

1 Mise en place 1.1 Réalisation d’un projet pour STM32F446 Nous souhaitons réaliser un projet « Hello_World » [Led Blinking de 500ms] sur la User LED (PIN PA5). Avec STM32ubeMX, configurer le projet. Avec Atollic TrueSTUDIO, compiler, debugger et tester. Modifier votre projet pour rajouter l’information d’un changement d’état de la LED sur le liaison série. Pour afficher les éléments sur l’UART2, il faut ouvrir un terminal dans TrueSTUDIO : View > Terminal > Open Terminal. Pour la vitesse de transmission, vérifier les paramètres de connexions que vous avez mis dans STM32Cube MX à la génération du projet.

Afin d’améliorer le débogage dans TrueSTUDIO, il est important de modifier le paramètre d’optimisation du compilateur : Clic droit sur le projet > Properties > C/C++ Build > settings > Tool Settings > C Compiler > Optimization > Optimization level > Optimize for Debug.

| 1

1.2 Réalisation d’un projet FreeRTOS Nous souhaitons modifier ce projet pour réaliser la même application mais avec FreeRTOS. Dans Atollic, ouvrir le fichier « Hello_World.ioc » pour modifier la configuration du projet. Regénerer le code et mofifier le code de votre tâche pour votre application.

1.3 Outil d’analyse temps réel : Percepio Tracealyser Percepio Tracealyser [ www.percepio.com ] est un outil de log et de visualisation de ce qu’il se passe pendant l’exécution d’une application FreeRTOS.

1.3.1 Schéma de fonctionnement

Figure 1 : Fonctionnement de Percepio Tracealyser Chaque évènement du noyau de FreeRTOS : tick, accès Sémaphore, accès Queues, changement de contexte, etc… est stocké dans une zone de mémoire RAM grâce au « Snapshot Trace Recorder ». Le « Snapshot Trace Recorder » est un code qui doit être positionné dans le microcontrôleur au préalable. La zone mémoire de stockage peut fonctionner soit en buffer circulaire, soit en buffer à utilisation unique. Le buffer circulaire permet d’écraser les vielles sauvegardes d’évènements et donc de faire une photographie (snapshot) à n’importe quel moment de l’exécution du programme. Le buffer unique s’arrête lorsqu’il est plein. Cela permet de visualiser uniquement les évènements depuis le démarrage du système.

1.3.2 Installation de Tracealyser for FreeRTOS Application Nous installons d’abord le logiciel Tracealyser (.exe et licence disponible sur Moodle) qui correspond à cette partie du schéma précédent. :

Figure 2 : Tracealyser

| 2

1.3.3 Intégration du TraceRecoder dans le µC Nous intégrons maintenant les librairies « Trace Recorder » dans le noyau pour réaliser le log des évènements. Cette intégration correspond à cette partie du schéma précédent. :

Figure 3 : Trace Recorder La méthode d’intégration est la suivante : 1

2

3

4

5

Dans STM32CubeMX, activer la possibilité de générer des traces avec FreeRTOS : Onglet Configuration > FreeRTOS > Config Parameters > USE_TRACE_FACILITY > Enable. Générer à nouveau le projet. Sur votre PC, localiser la librairie Trace Recorder : C:\Program Files\Percepio\Tracealyzer 4\FreeRTOS\TraceRecorder. Intégrer cette librairie (le dossier TraceRecorder) dans le dossier Middleware (à côté de FreeRTOS) de votre projet. Supprimer le dossier « streamports ». Vérifier que le dossier TraceRecoder n’est pas exclu de la compilation : Dans TrueSTUDIO : Clic Droit sur le dossier TraceRecorder > Propriétés > décocher « exclude ressources from build ». Ajouter les chemins pour les includes des dossiers « config » et « include » : Clic droit sur le projet > Properties > C/C++ Build > Settings > Onglet Tool Settings > C Compiler > Directories > Add Include Path Dans trcConfig.h, configurer TRC_CFG_HARDWARE_PORT and TRC_CFG_FREERTOS_VERSION, et remplacer le #error "Trace Recorder: Please include your processor's header file here and remove this line." par l’include de votre microcontrôleur : #include "stm32f4xx.h". Ce fichier se situe dans Drivers > CMSIS > Device > ST > STM32F4xx > Include > stm32f4x Dans FreeRTOSConfig.h, intégrer le code suivant à la fin : #if ( configUSE_TRACE_FACILITY == 1 ) #include "trcRecorder.h" #endif

6

Appeler la fonction vTraceEnable(TRC_START) après toutes les initialisations matérielles et avant le lancement du séquenceur du RTOS.

1.3.4 Installation de « Percepio exporter » dans TrueSTUDIO Percepio Exporter est un plugin de TrueSTUDIO permettant de récupérer les données (évènements) stockés en RAM pe ndant l’exécution du programme. Cela correspond à cette partie sur le schéma précédent :

Figure 4 : Percepio Exporter Une fois les données rapatriées sur le PC, elles seront affichées par le logiciel Percepio Tracealyser.

| 3

Dans TrueSTUDIO, installer le plugin Percepio Exporter : Help > Eclipse Marketplace > Find : Percepio > Percepio Exporter Spécifier le « Tracealyser Path » (lieu de l’exécutable Tracealyser.exe) et le « Trace Directory » (lieu d’enregistrement des traces) : Percepio > Preferences

1.4 Interface utilisateur Un microcontrôleur ne possède pas de sortie standard (écran). Nous redéfinissons donc une fonction printf [ PRINTF ] qui effectuera une écriture sur le liaison série.

1.4.1 Mettre en place un printf via l’UART Dans main.c #include #include #define PRINTF(...)

VirtualCOM_Transmit(__VA_ARGS__)

Dans main.c /* USER CODE BEGIN 0 */ void VirtualCOM_Transmit( char *format, ... ){ char buffer[128]; uint32_t i=0; va_list args; va_start(args, format); vsprintf(buffer,format,args); for(i=0;iSR) & UART_FLAG_TXE) == 0 ); huart2.Instance->DR=buffer[i]; } va_end(args); }

Dans votre projet « Hello_World », réaliser un PRINTF au lieu de faire appel à la fonction HAL_USART_Transmit().

1.5 Création d’un template A partir de ce projet « Hello_World », nous allons créer un template (sauvegarde) que vous pourrez réutiliser pour tous les autres projets. Voici la démarche pour faire une copie (que vous nommerez « STM32F446_Template_FreeRTOS » ) de ce projet : Créer un nouveau dossier « STM32F446_Template_FreeRTOS » dans votre Workspace. Dans le Project Explorer de TrueSTUDIO : Clic droit sur le projet > Copier Dans un emplacement libre du Project Explorer de TrueSTUDIO : Clic droit > Coller > Choisir le dossier créer précédemment ET modifier le nom du projet par « STM32F446_Template_FreeRTOS »

1.6 Création d’évènement Tracealyser Tracealyser relève les évènements que lui retourne FreeRTOS. Il est possible d’en rajouter logiciellement à l’aide du code suivant :

| 4

traceString myChannel = xTraceRegisterString("UART2");

vTracePrint(myChannel, "Start UART Transmit"); vTracePrintF(myChannel, "i=%d",nombre);

// Déclaration

// Exemple 1 utilisation // Exemple 2 utilisation

Mettre un évènement avant l’écriture sur le port série et après. Visualiser ces évènements dans Tracealyser pour (par exemple) mesurer le temps d’écriture d’une chaine de caractère sur la liaison série.

1.7 Getting Started 1.7.1 CMSIS RTOS api Versus FreeRTOS api 1.7.2 Percepio Graph

1.8 Compte rendu et notation 1.8.1 Interprétation des résultats A chaque demande « Interpréter vos résultats » (icône ci-contre), vous devrez expliquez clairement : ■ ■ ■ ■ ■ ■ ■

La problématique initiale et les tâches présentes Le pourcentage de CPU utilisé L’ordonnancement des taches dans Tracealyser Les rythmes d’affichage sur la liaison série Le contenu de l’affichage sur la liaison série La précision des résultats et des temps obtenus par rapport à ceux attendus La solution éventuelle au problème soulevé par le cas étudié.

1.8.2 Validation de vos manipulations A chaque demande « Faites valider vos résultats », (icone ci-contre), vous devez appeler l’enseignant pour vérifier les résultats de la manipulation. La clarté de votre démonstration est prise en compte.

1.8.3 Notation Le compte rendu des questions sera déposé à mon bureau (en main propre, dans mon casier, ou à notre secrétariat au 2ème étage) à 12h à la date précisée par l’enseignant au début des Travaux Pratiques. Celui-ci sera réalisé en version informatique, imprimé et relié. Il devra être présenté comme un rapport complet (introduction, présentation, conclusion…) et la mise en page devra être soignée. La notation du compte rendu, ainsi que les notes d’avancement donneront lieu à une note sur 20 qui constitueront votre note de Travaux Pratiques.

| 5

2 Etude des ordonnancements 2.1 COOPERATIF 2.1.1 Tache infinie Dans STM32CubeMX : Reconfigurer le noyau FreeRTOS avec USE_PREEMPTION = Disable pour passer le séquenceur en mode coopératif. Vérifier dans votre projet que le fichier FreeRTOSConfig.h a bien été mise à jour (Macro ConfigUSE_PREEMPTION) Créer 3 taches : Task Name Task1 Task2 Task3

Priority osPriorityNormal osPriorityNormal osPriorityNormal

Stack 128 128 128

Entry Function functionTask1 functionTask2 functionTask3

Dans TrueSTUDIO : Implémenter chacune des « functionTaskx() » avec le code d’exemple suivant, permettant d’écrire le nom de la tâche qui s’exécute, associé à une temporisation logicielle : void functionTask1(void const * argument) { /* USER CODE BEGIN 5 */ uint32_t i=0; /* Infinite loop */ for(;;) { PRINTF("Task1\r\n"); for(i=0;i FreeRTOS Tasks List. Activez le « Stack Checking) en cliquant sur l’icône afin d’avoir les valeurs de « Min Free Stack ». Attention, les termes « Start of the Stack » et « Top of the Stack » sont très maladroitement choisis dans le Debugger. « Start of the Stack » = pxStack et « Top of Stack » = pxTopOfStack.

Dessiner la stack d’une des tâches de l’application avec laquelle vous travaillez et donner les valeurs réelles des adresses. Vous calculerez l’adresse de début de pile. Reconfigurer le noyau FreeRTOS avec CHECK_FOR_STACK_OVERFLOW = Option2 pour valider l’appel de la fonction utilisateur « vApplicationStackOverflowHook ( )» lors d’un débordement de pile fait par une tâche. Implémenter « vApplicationStackOverflowHook ( )» afin qu’il affiche sur le terminal le nom de la tâche pour qui la stack a débordée. En étudiant la documentation de FreeRTOS, expliquer le mécanisme de surveillance de la pile. Visualiser la zone mémoire de la pile avec View > Memory Browser et justifier les valeurs de « Min Free Stack » de FreeRTOS Tasks List. Afin de faire évoluer l’utilisation de la pile, nous allons utiliser une fonction récursive qui sera appelée depuis une tache. for(;;)

{ PRINTF("Task1\r\n); growStack();

} void growStack(void){ PRINTF("Appel growStack"); return growStack(); }

Avec FreeRTOS Tasks List, analyser l’évolution de la pile à chaque appel de la fonction growStack(). Question 9 :

Interpréter vos résultats.

| 9

Validation 2 :

Faites valider vos résultats

Pour notre utilisation, il est important d’augmenter la taille de la pile. En effet, de nombreux appels aux fonctions PRINTF sont très consommateurs de mémoire RAM (Stack). Dans CubeMX, modifier la valeur de MINIMUM_STACK_SIZE en passant à 256.

3.6 Passage de paramètres à une tâche Lors de la création d’une tache, le second paramètre de la fonction « osThreadCreate( … , void * argument) » est un pointeur. Celui-ci est passé à la fonction de la tâche à exécuter : void functionTask1(void const * argument) En testant la valeur passée, nous pouvons faire des actions spécifiques. Réaliser l’application suivante, qui affichera un texte (paramètre de la fonction PRINTF) différent suivant que cela soit la « Task1_Low » ou la « Task2_Low » qui est exécutée. Task Name Task1_Low

Priority osPriorityLow

Stack 256

Entry Function functionTask1

Task2_Low

osPriorityLow

256

functionTask2

Code Infinite Loop PRINTF(text); osDelay(5); PRINTF(text); osDelay(5);

text = Task1 RUNNING, si « Task1_Low » est en cours d’exécution text = Task2 RUNNING, si « Task2_Low » est en cours d’exécution

■ ■

Validation 3 :

Faites valider vos résultats

4 Protection des sections critiques 4.1 Protection des sections critiques 4.1.1 Désactivation des interruptions La première méthode sera la désactivation des interruptions. Nous symboliserons la SECTION CRITIQUE par une boucle d’attente. Dans la réalité, une section critique doit être courte, mais dans notre cas, cela nous permettra de bien voir le fonctionnement du problème. Nous utiliserons les tâches suivantes : Task Name Task1_Low

Priority osPriorityLow

Stack 256

Entry Function functionTask1

Task2_High

osPriorityHigh

256

functionTask2

Code Infinite Loop PRINTF(«Début SECTION CRITIQUE\r\n »); for(i=0;i System > NVIC , démasquer la source d’interruption et spécifier une priorité. Dans TrueSTUDIO, implémenter la fonction : ISR Name void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

Code ...

Fonctionnement des interruptions dans le STM32. 1. La liste des vecteurs d’interruption est dans le fichier Startup > startup_stm32f446xx.s. On remarque que lorsqu’une interruption externe sur les PIN 10 à 15 intervient, cela appelle l’ISR (fonction d’interruption) EXTI15_10_IRQHandler. 2. Cette fonction EXTI15_10_IRQHandler est écrite dans le fichier Src > stm32f4xx_it.c. Elle fait appel à la fonction HAL_GPIO_EXTI_IRQHandler( … ) écrite dans le fichier Drivers > STM32F4xx_HAL_Driver > Src > stm32f4xx_hal_gpio.c. Qui fait elle-même appel à la fonction __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) écrite dans le même fichier. C’est cette fonction __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) qu’il faut réécrire. 3. L’attribut __weak signifie que si on réécrit cette fonction (avec le même nom) ailleurs dans notre programme, celle qui a l’attribut ___weak sera ignorée. Si vous souhaitez implémenter un code spécifique, vous devez donc réécrire cette fonction dans votre fichier main.c. Les priorités des IT sont différentes des priorités des tâches. Une IT (même de faible priorité) est obligatoirement plus prioritaire qu’une tâche (même de forte priorité). Les valeurs élevées donnent des faibles priorités. Les faibles valeurs sont les priorités les plus fortes (0 est la plus forte priorité pour les IT). C’est le raisonnement inverse pour les tâches de FreeRTOS !

Réaliser cette application.

| 13

Il n’y a rien à faire valider pour cette partie.

7.1.2 Visionnage dans Tracealyser : Tracealyser ne permet pas par défaut de voir les interruptions car les ISR ne sont pas des tâches FreeRTOS. Pour voir les ISR dans Tracealyser, il faut utiliser les fonctions de l’API Trace Recoder : ■

traceHandle xTraceSetISRProperties(const char* name, uint8_t priority) void vTraceStoreISRBegin(traceHandle handle);



void vTraceStoreISREnd(int isTaskSwitchRequired)



Vous trouverez des informations complémentaires dans l’aide de Tracealyser : Tracealyser > Trace Recorder Librairie > Recorder API. Faire apparaître les interruptions du bouton poussoir dans tracealyser.

Validation 8 :

Faites valider vos résultats.

7.2 Synchronisation des tâches par une interruption Une propriété importante des routines d’interruptions est qu’elles doivent être les plus courtes possibles. En effet, une ISR étant exécutée avec une priorité très élevée, elle empêche donc les autres tâches de s’exécuter. Néanmoins certaines applications demandent un traitement long. Dans ce cas, il est important de séparer la partie urgente (de forte priorité) qui sera faite dans l’ISR, de la partie traitement (de plus faible priorité) qui sera faite dans une tâche. Il s’agit donc d’un cas de synchronisation (entre une ISR et une tâche) que nous pouvons traiter avec des sémaphores binaires. Pour déclencher une interruption, il faut que le périphérique matériel concerné génère un évènement : Overflow pour un Timer, réception d’un caractère pour un UART, fin de conversion pour un ADC… En travaux Pratiques, il est intéressant de s’affranchir des évènements des périphériques et d’utiliser un moyen logiciel pour déclencher les interruptions. Le cœur ARM Cortex M associé à la librairie CMSIS nous fournit une méthode simple pour cela, il suffit d’utiliser la fonction : void NVIC_SetPendingIRQ(IRQn_Type IRQn) // Genère un IT

Où IRQn est le numéro de l’interruption que vous pouvez trouver dans : Drivers > CMSIS > ST > STM32F4xx > Include > stm32f446xx.h Le « Code Infinite Loop » donné ci-dessous est partiel et doit être complété dans TrueSTUDIO.

| 14

Dans CubeMX : Task Name Priority Generateur_IT osPriorityNormal

Stack Entry Function 256 functionGenerateurIT

Traitement_IT

osPriorityNormal

256

functionTraitementIT

Task1_Low Task2_Low

osPriorityLow osPriorityLow

256 256

function_Task1 function_Task2

Code Infinite Loop PRINTF("Génération IT\r\n"); NVIC_SetPendingIRQ (...) osDelayUntil(&lastWakeUpTime,50); PRINTF("IT (Traitement long)\r\n"); for(i=0;i...


Similar Free PDFs