Question initiale
J'ai une question générale sur la gestion des interruptions dans les microcontrôleurs. J'utilise le MSP430, mais je pense que la question peut être étendue à d'autres uC. Je voudrais savoir si c'est une bonne pratique d'activer / désactiver fréquemment les interruptions le long du code. Je veux dire, si j'ai une partie de code qui ne sera pas sensible aux interruptions (ou pire encore, ne doit pas écouter les interruptions, pour une raison quelconque), est-il préférable de:
- Désactivez les interruptions avant, puis réactivez-les après la section critique.
- Placez un indicateur à l'intérieur de l'ISR respectif et (au lieu de désactiver l'interruption), définissez l'indicateur sur false avant la section critique et réinitialisez-le sur true, juste après. Pour empêcher l'exécution du code de l'ISR.
- Aucun des deux, les suggestions sont donc les bienvenues!
Mise à jour: interruptions et diagrammes d'état
Je vais fournir une situation spécifique. Supposons que nous voulons implémenter un graphique d'état, qui est composé de 4 blocs:
- Transitions / effet.
- Conditions de sortie.
- Activité d'entrée.
- Faites de l'activité.
C'est ce qu'un professeur nous a enseigné à l'université. Probablement, la meilleure façon de le faire est de suivre ce schéma:
while(true) {
/* Transitions/Effects */
//----------------------------------------------------------------------
next_state = current_state;
switch (current_state)
{
case STATE_A:
if(EVENT1) {next_state = STATE_C}
if(d == THRESHOLD) {next_state = STATE_D; a++}
break;
case STATE_B:
// transitions and effects
break;
(...)
}
/* Exit activity -> only performed if I leave the state for a new one */
//----------------------------------------------------------------------
if (next_state != current_state)
{
switch(current_state)
{
case STATE_A:
// Exit activity of STATE_A
break;
case STATE_B:
// Exit activity of STATE_B
break;
(...)
}
}
/* Entry activity -> only performed the 1st time I enter a state */
//----------------------------------------------------------------------
if (next_state != current_state)
{
switch(next_state)
{
case STATE_A:
// Entry activity of STATE_A
break;
case STATE_B:
// Entry activity of STATE_B
break;
(...)
}
}
current_state = next_state;
/* Do activity */
//----------------------------------------------------------------------
switch (current_state)
{
case STATE_A:
// Do activity of STATE_A
break;
case STATE_B:
// Do activity of STATE_B
break;
(...)
}
}
Supposons également que, par exemple STATE_A
, je veux être sensible à une interruption provenant d'un ensemble de boutons (avec système debouce, etc., etc.). Lorsque quelqu'un appuie sur l'un de ces boutons, une interruption est générée et l'indicateur lié au port d'entrée est copié dans une variable buttonPressed
. Si le rebounce est réglé sur 200 ms d'une manière ou d'une autre (horloge de surveillance, minuterie, compteur, ...), nous sommes sûrs qu'il buttonPressed
ne peut pas être mis à jour avec une nouvelle valeur avant 200 ms. C'est ce que je vous demande (et moi-même :) bien sûr)
Dois-je activer l'interruption de l'activité DO STATE_A
et la désactiver avant de quitter?
/* Do activity */
//-------------------------------------
switch (current_state)
{
case STATE_A:
// Do activity of STATE_A
Enable_ButtonsInterrupt(); // and clear flags before it
// Do fancy stuff and ...
// ... wait until a button is pressed (e.g. LPM3 of the MSP430)
// Here I have my buttonPressed flag ready!
Disable_ButtonsInterrupt();
break;
case STATE_B:
// Do activity of STATE_B
break;
(...)
}
D'une manière que je suis sûr que la prochaine fois que j'exécute le bloc 1 (transition / effets) à la prochaine itération, je suis sûr que les conditions vérifiées le long des transitions ne proviennent pas d'une interruption ultérieure qui a écrasé la valeur précédente de buttonPressed
celle-ci. besoin (bien qu'il soit impossible que cela se produise car 250 ms doivent s'écouler).