2017-10-06 8 views
1

Je suis confronté à un comportement étrange dans mon programme. Pour le contexte, je programme un microcontrôleur STM32F469. L'IDE utilisé est SW4STM32 (avec la version Eclipse Neon (4.6.3)).STM32F4, comportement étrange entre un gestionnaire IRQ et une fonction avec des variables partagées

Pour aller directement au point, voici ce que j'ai:

void foo(void){ 
    while(1){ 
     if(var.x == 1){ 
      var.x = 0; 
      var.y = 1; 

      // Some irrelevant calculus 

      var.y = 0; 
     } 
    } 

La fonction foo() n'a rien de particulier. Cela fonctionne, entre autres choses non pertinentes ici, avec une variable globale (struct) var.

void interruption(void){ 
    if(var.x == 0 && var.y == 0){ 
     // Some irrelevant calculus 
     var.x = 1; 
    } 
} 

Comme son nom l'indique, la fonction interruption() est un ISR (Interruption du service de routine). L'interruption associée à cette ISR est augmentée approximativement toutes les 16ms. Il fonctionne avec la même variable globale (struct) var.

Enfin, voici mon main:

int main(void) 
{ 
    myStruct var; 
    var.x = 0; 
    var.y = 0; 

    // Some initialization (the ISR for example) 

    foo(); 
} 

Ok, donc ce que je ne comprends pas est que le processus ne fonctionne que s'il y a « quelque chose » entre la boucle while et la condition if, par exemple : un retard ou l'interrupteur d'un état de la broche dans la fonction foo():

void foo(void){ 
    **Place something here to make the process work, a 1ms delay for example** 
    while(1){ 
     if(var.x == 1){ 
      var.x = 0; 
      var.y = 1; 

      // Some irrelevant calculus 

      var.y = 0; 
     } 
    } 

Juste pour être précis: quand il ne fonctionne pas, cela signifie que ni mon programme passe par le if condition dans l'ISR ni la condition if dans la fonction foo(). Quand cela fonctionne, le programme passe par les deux (if condition).

Le fait que les deux de la condition if sont faux signifie que:

  1. var.x == 0
  2. Ces deux valeurs sont vraies en dehors la condition if. La chose est, et c'est là que quelque chose ne va pas ici, normalement ces valeurs ne sont rencontrées que dans la condition if de la fonction foo(). Et si je suis dans cet état, var.ya pour être égal à 0 à la fin de cette condition.

var est actuellement utilisé nulle part ailleurs. Donc, ma question est, avez-vous des explications sur ce phénomène?

Merci!

Répondre

1

La mise en cache du registre est probablement active. Assurez-vous que vos globales sont déclarées comme volatile (voir https://barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword). Fondamentalement, le code généré ne pense pas que var.x peut changer en dehors de la fonction en cours. Le mot clé volatile indique au générateur de code qu'il doit supposer que la valeur est modifiée par une action asynchrone (ISR, gestionnaire de signal, autre thread, etc.).

Oh, et je suppose que la langue cible est C ou C++ puisque le langage définit le mot-clé volatile.

+0

Je n'ai jamais complètement compris comment, pourquoi et quand le mot-clé 'volatile' devrait être utilisé (comme votre article l'indique). Maintenant je sais. Il a résolu le problème. Merci ! – vionyst

+0

@ D.Shawley ce n'est pas suffisant dans votre cas !!! Cela doit aussi être atomique. volatile ne fait rien d'autre que des charges et des réserves de l'objet, mais pas l'atomicité. Il vérifie la valeur et prend l'action pour la valeur qui pourrait être entre temps modifiée (entre charger/modifier/stocker). –