Changes between Version 1 and Version 2 of SysCom19


Ignore:
Timestamp:
Oct 9, 2019, 5:20:36 AM (6 years ago)
Author:
franck
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • SysCom19

    v1 v2  
    3535= Exécution ''multi-tâches''
    3636
    37 == Tâches standards
    38 
    39 Il est possible de programmer des applications multi-tâches coopératives dans l'environnement Arduino sans pour autant disposer des services d'un OS. Le principe a été volontairement simplifié à l'extrême. Ici, toute l'application sera dans un seul fichier et nous n'allons pas utiliser la programmation objet pour ne pas complexifier, mais pour une application plus ambitieuse, ce serait souhaitable pour une meilleure maintenance.
    40 
    41 Une application est composée de plusieurs tâches. Chaque tâche peut être répliquée en plusieurs instances et chaque tâche est exécutée à tour de rôle en temps partagé.
    42 * Une ''instance de tâche'' est une des copies d'une tâche
     37== Principe
     38
     39Il est possible de programmer des applications multi-tâches coopératives dans l'environnement Arduino sans pour autant disposer des services d'un OS. Le principe a été volontairement simplifié à l'extrême. Ici, toute l'application sera dans un seul fichier.
     40Nous n'allons pas utiliser la programmation objet pour ne pas complexifier, mais ce serait possible pour une application plus ambitieuse pour une meilleure maintenance.
     41
     42Une application est composée de plusieurs tâches. Chaque tâche peut être répliquée plusieurs fois dans l'application et chaque réplica de tâche est exécutée à tour de rôle en temps partagé.
     43Les (réplica de) tâches communiquent entre elles par l'intermédiaire de variables globales.
     44
     45Les ISR (Interrupt Service Routine) qui sont des fonctions exécutées lors de la survenue d'interruption sont considérée comme des tâches.
     46
     47== Tâches
    4348
    4449Chaque tâche est représentée par
    4550* une fonction `loop_Tache()` qui code son comportement qui sera appelée dans la fonction `loop()`.
     51  Dans cet exemple l'application a trois tâches : la tâche 1 est répliquée 2 fois et la tâche 2 n'a
    4652  {{{#!c
    4753  loop() {
    48     loop_tache1(args...);
    49     loop_tache1(args...);
    50     loop_tache2(args...);
     54    loop_tache1(args...); // 1er réplica de la tâche 1
     55    loop_tache1(args...); // 2nd réplica de la tache 1
     56    loop_tache2(args...); // unique réplica de la tâche 2
    5157  }
    5258  }}}
    53 * une seconde fonction `setup_Tache()` qui initialise les ressources de la tâche (périphériques) et l'état interne.
    54 
    55 Chaque tâche dispose de trois types de variables internes
     59  La fonction `loop()` demande donc l'exécution des fonctions `loop_Tache()` à tour de rôle.
     60  Les tâches n'ont pas le droit de conserver le processeur sinon cela crée un blocage du système.
     61  Cela signifie qu'il est interdit de faire des boucles d'attente d'un événement.
     62 
     63  La fonction loop() est en fait un ordonnanceur de tâche suivant un algorithme FIFO statique.
     64
     65  La fonction loop() ignore si la tâche est en mesure d'avancer. Les tâches sont toujours "prêtes".
     66  C'est chaque tâche qui doit vérifier si elle peut avancer, par exemple si les données
     67  attendues sont disponible ou si assez de temps c'est écoulé depuis la dernière instance d'exécution.
     68  Si oui elle avance, sinon elle sort immédiatement et la tâche suivante dans la liste est exécutée.
     69
     70* une seconde fonction `setup_Tache()` qui initialise les ressources matérielles assignées de la tâche (périphériques) et l'état interne (voir plus loin).
     71  {{{#!c
     72  setup() {
     73    setup_tache1(args...); // setup du 1er réplica de la tâche 1
     74    setup_tache1(args...); // setup du 2nd réplica de la tache 1
     75    setup_tache2(args...); // setup de l'unique réplica de la tâche 2
     76  }
     77  }}}
     78
     79Chaque tâche (sous-entendu réplica de tâche) dispose de trois types de variables internes
    5680* Variables locales temporaires :[[BR]]
    5781  - Les fonctions `loop_Tache` et `setup_Tache` peuvent avoir des variables locales.
    58     L'état n'est pas conservé entre deux instances d'exécution.
     82    L'état n'est pas conservé entre deux instances d'exécution de la tâche.
    5983* Variables d'état de tâche : [[BR]]
    6084  - Elles peuvent aussi avoir des variables `static`. Ces variables ont une valeur
    61     unique pour toutes les instances de tâche.
     85    unique pour toutes les réplicas d'une tâche.
    6286* Variables de contexte d'exécution :
    63   - Enfin chaque instance de tâche dispose d'une structure contenant son état interne
    64     qui est conservé entre deux instance d'exécution.
     87  - Enfin chaque réplica de tâche dispose d'une structure contenant son état interne,
     88    lequel est conservé entre deux instance d'exécution de la tâche.
    6589    Le contexte d'exécution représenté par une variable globale du programme sous forme d'une structure.
    66     Cette structure est passée en argument de la tâche des fonctions `setup_Tache()` et `loop_Tache`.
     90    Une structure différente est passée en argument de chaque réplica de tâche dans les arguments
     91    des fonctions `setup_Tache()` et `loop_Tache`.
    6792  - La structure contexte ressemble à :
    6893    {{{#!c
     
    7196      int config;       
    7297    };
    73     struct Tache_st T1, T2;  // deux contextes pour deux tâches.
     98    struct Tache_st T1, T2;  // deux contextes pour deux réplicas d'une tâche.
    7499    }}}
    75100
     
    83108}}}
    84109
    85 La fonction `loop()` demande donc l'exécution des fonctions `loop_Tache()` à tour de rôle.
    86 Les tâches n'ont pas le droit de conserver le processeur sinon cela crée un blocage du système.
    87 Cela signifie qu'il est interdit de faire des boucles d'attente d'un événement.
    88 `connectors` sont des pointeurs vers des variables globales utilisées pour la communications inter-tâches.
    89 La structure générale d'une tâche est la suivante :
    90 
     110== Communication entre tâches
     111
     112Les tâches communiquent entre elles par des variables globales de l'application.
     113Chaque tâche reçoit en argument les pointeurs vers les variables qu'elle utilise pour communiquer.
     114Ces pointeurs sont nommés connecteurs (ou ports).
     115
     116La structure forme de la fonction loop d'une tâche est donc :
    91117{{{#!c
    92118void loop_Tache(struct Tache_st *ctx, connectors....) {