Changes between Version 24 and Version 25 of IOC_T06


Ignore:
Timestamp:
Mar 19, 2026, 10:13:43 PM (7 months ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • IOC_T06

    v24 v25  
    115115
    116116Chaque tâche est représentée par
    117 - une fonction `loop_Tache()` qui code son comportement qui sera appelée dans la fonction `loop()`.
    118 - une seconde fonction `setup_Tache()` qui initialise les ressources de la tâche (périphériques) et l'état interne.
    119 - une structure contenant l'état interne et le contexte d'exécution représenté par une variable globale sous forme d'une structure `Tache_t`. Cette structure est passée en argument de la tâche des fonctions `setup_Tache()` et `loop_Tache()`.
    120 
    121 Les fonctions `loop_Tache()` et `setup_Tache()` peuvent avoir des variables locales mais leur état n'est pas conservé entre deux instances d'exécutions.
    122 Elles peuvent aussi avoir des variables static mais ces variables ont une valeur unique même si la tâche est en plusieurs exemplaires et que donc elle utilise la même fonction `loop_Tache()`. Les variables static ne sont pas conseillées parce qu'elles ne peuvent être initialisées dans la fonction `setup_Tache()`. Expliquez pourquoi dans le CR pour vérifier que vous avez compris.
     117- une fonction `step_Tache()` qui code son comportement qui sera appelée dans la fonction `loop()`.
     118- une seconde fonction `init_Tache()` qui initialise les ressources de la tâche (périphériques) et l'état interne.
     119- une structure contenant l'état interne et le contexte d'exécution représenté par une variable globale sous forme d'une structure `Tache_t`. Cette structure est passée en argument de la tâche des fonctions `init_Tache()` et `step_Tache()`.
     120
     121Les fonctions `step_Tache()` et `init_Tache()` peuvent avoir des variables locales mais leur état n'est pas conservé entre deux instances d'exécutions.
     122Elles peuvent aussi avoir des variables static mais ces variables ont une valeur unique même si la tâche est en plusieurs exemplaires et que donc elle utilise la même fonction `step_Tache()`. Les variables static ne sont pas conseillées parce qu'elles ne peuvent être initialisées dans la fonction `init_Tache()`. Expliquez pourquoi dans le CR pour vérifier que vous avez compris.
    123123
    124124La structure contexte ressemble à :
    … …  
    132132
    133133
    134 C'est la fonction `setup_Tache()`qui initialise le contexte avec des paramètres.
    135 {{{#!c
    136 void setup_Tache(struct Tache_s *ctx, params...) {
     134C'est la fonction `init_Tache()`qui initialise le contexte avec des paramètres.
     135{{{#!c
     136void init_Tache(struct Tache_s *ctx, params...) {
    137137   // Initialisation du contexte}
    138138   ctx->etat = etat_initial;  //  reçu dans les paramètres
    … …  
    141141}}}
    142142
    143 La fonction `loop()` demande donc l'exécution des fonctions `loop_Tache()` à tour de rôle.
     143La fonction `loop()` demande donc l'exécution des fonctions `step_Tache()` à tour de rôle.
    144144Les tâches n'ont pas le droit de conserver le processeur, sinon cela crée un blocage du système (une famine pour les autres tâches).
    145145Cela signifie qu'il est interdit de faire des boucles d'attente d'un événement.
    … …  
    149149
    150150{{{#!c
    151 void loop_Tache(tache_t *ctx, connectors....) {   
     151void step_Tache(tache_t *ctx, connectors....) {   
    152152   // test de la condition d'exécution, si absent on SORT
    153153   if (evement_attendu_absent) return;
    … …  
    195195// --------------------------------------------------------------------------------------------------------------------
    196196#define MAX_WAIT_FOR_TIMER 2
    197 unsigned int waitFor(int timer, unsigned long period){
    198   static unsigned long waitForTimer[MAX_WAIT_FOR_TIMER];  // il y a autant de timers que de tâches périodiques
    199   unsigned long newTime = micros() / period;              // numéro de la période modulo 2^32
    200   int delta = newTime - waitForTimer[timer];              // delta entre la période courante et celle enregistrée
    201   if ( delta < 0 ) delta = 1 + newTime;                   // en cas de dépassement du nombre de périodes possibles sur 2^32
    202   if ( delta ) waitForTimer[timer] = newTime;             // enregistrement du nouveau numéro de période
    203   return delta;
     197unsigned long waitFor(int timer, unsigned long period) {
     198    static unsigned long last_period[MAX_WAIT_FOR_TIMER];  // il y a autant de timers que de tâches
     199    unsigned long current = micros() / period;             // numéro de période
     200    unsigned long delta   = current - last_period[timer];  // gère le wrap-around
     201    if (delta) last_period[timer] = current;               // mise à jour si déclenchement
     202    return delta;                                          // nombre de periode depuis le dernier appel
    204203}
    205204
    … …  
    213212};
    214213
    215 void setup_Led( struct Led_s * ctx, int timer, unsigned long period, byte pin) {
     214void init_Led( struct Led_s * ctx, int timer, unsigned long period, byte pin) {
    216215  ctx->timer = timer;
    217216  ctx->period = period;
    … …  
    222221}
    223222
    224 void loop_Led( struct Led_s * ctx) {
     223void step_Led( struct Led_s * ctx) {
    225224  if (!waitFor(ctx->timer, ctx->period)) return;          // sort s'il y a moins d'une période écoulée
    226225  digitalWrite(ctx->pin,ctx->etat);                       // ecriture
    … …  
    232231struct Mess_s {
    233232  int timer;                                              // numéro de timer utilisé par WaitFor
    234   unsigned long period;                                             // periode d'affichage
     233  unsigned long period;                                   // periode d'affichage
    235234  char mess[20];
    236235} ;
    237236
    238 void setup_Mess( struct Mess_s * ctx, int timer, unsigned long period, const char * mess) {
     237void init_Mess( struct Mess_s * ctx, int timer, unsigned long period, const char * mess) {
    239238  ctx->timer = timer;
    240239  ctx->period = period;
    … …  
    243242}
    244243
    245 void loop_Mess(struct Mess_s *ctx) {
     244void step_Mess(struct Mess_s *ctx) {
    246245  if (!(waitFor(ctx->timer,ctx->period))) return;         // sort s'il y a moins d'une période écoulée
    247246  Serial.println(ctx->mess);                              // affichage du message
    248247}
    249248
    250 //--------- Déclaration des tâches
     249//--------- Déclaration des contexte de tâches
    251250
    252251struct Led_s Led1;
    … …  
    256255
    257256void setup() {
    258   setup_Led(&Led1, 0, 100000, LED_BUILTIN);                        // Led est exécutée toutes les 100ms
    259   setup_Mess(&Mess1, 1, 1000000, "bonjour");              // Mess est exécutée toutes les secondes
     257  init_Led(&Led1, 0, 100000, LED_BUILTIN);               // Led est exécutée toutes les 100ms
     258  init_Mess(&Mess1, 1, 1000000, "bonjour");              // Mess est exécutée toutes les secondes
    260259}
    261260
    262261void loop() {
    263   loop_Led(&Led1);                                       
    264   loop_Mess(&Mess1);
     262  step_Led(&Led1);                                       
     263  step_Mess(&Mess1);
    265264}
    266265                                     
    … …  
    298297> En conséquence, vous devez modifier une ligne et en ajouter une :
    299298> * au début du fichier modifier (4 → 16) : `#define OLED_RESET     16   // Reset pin...``
    300 > * Dans la fonction setup() ou setup_oled() (au début avant le begin de oled) : `Wire.begin(4, 15); // pins SDA , SCL`
     299> * Dans la fonction setup() ou init_oled() (au début avant le begin de oled) : `Wire.begin(4, 15); // pins SDA , SCL`
    301300> En outre l'adresse de l'OLED sur le bus I2C est 0x3C (vers la ligne 60) du programme de test.
    302301 
    … …  
    328327struct mailbox_s mb = {.state = EMPTY};
    329328
    330 void loop_T1(... mailbox_t * mb ...) {
     329void step_T1(... mailbox_t * mb ...) {
    331330  if (mb->state != EMPTY) return; // attend que la mailbox soit vide
    332331  mb->val = 42;
    … …  
    334333}
    335334
    336 void loop_T2(... mailbox_t * mb ...) {
     335void step_T2(... mailbox_t * mb ...) {
    337336  if (mb->state != FULL) return; // attend que la mailbox soit pleine
    338337  // usage de mb->val
    … …  
    357356Ici, il faut créer une fonction `SerialEvent()` qui sera invoqué lors de la réception d'un caractère par le port série.
    358357
    359 Dans ce système, la fonction ISR sera comme une fonction loop_Tache.
     358Dans ce système, la fonction ISR sera comme une fonction step_Tache.
    360359
    361360**Question**