Domanda iniziale
Ho una domanda generale sulla gestione degli interrupt nei microcontrollori. Sto usando MSP430, ma penso che la domanda possa essere estesa ad altri UC. Vorrei sapere se è o meno una buona pratica abilitare / disabilitare gli interrupt frequentemente lungo il codice. Voglio dire, se ho una parte di codice che non sarà sensibile agli interrupt (o peggio ancora, non devo ascoltare gli interrupt, per qualsiasi motivo), è meglio:
- Disabilitare gli interrupt prima e quindi riattivarli dopo la sezione critica.
- Inserisci un flag all'interno del rispettivo ISR e (invece di disabilitare l'interrupt), imposta il flag su false prima della sezione critica e ripristinandolo su true, subito dopo. Per impedire l'esecuzione del codice ISR.
- Nessuno dei due, quindi i suggerimenti sono benvenuti!
Aggiornamento: interrupt e grafici di stato
Fornirò una situazione specifica. Supponiamo di voler implementare un diagramma di stato, che è composto da 4 blocchi:
- Transizioni / Effect.
- Condizioni d'uscita
- Attività di ingresso.
- Fai attività.
Questo è ciò che un professore ci ha insegnato all'università. Probabilmente, non il modo migliore per farlo è seguendo questo schema:
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;
(...)
}
}
Supponiamo anche che, per esempio STATE_A
, voglio essere sensibile a un interrupt proveniente da una serie di pulsanti (con sistema di debouce, ecc. Ecc.). Quando qualcuno preme uno di questi pulsanti, viene generato un interrupt e il flag relativo alla porta di input viene copiato in una variabile buttonPressed
. Se il debounce è impostato in qualche modo su 200 ms (timer del watchdog, timer, contatore, ...) siamo sicuri che buttonPressed
non può essere aggiornato con un nuovo valore prima di 200 ms. Questo è quello che ti sto chiedendo (e io stesso :) ovviamente)
Devo abilitare l'interruzione nell'attività DO STATE_A
e disabilitarla prima di partire?
/* 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;
(...)
}
In un modo in cui sono sicuro che la prossima volta che eseguo il blocco 1 (transizione / effetti) alla prossima iterazione, sono sicuro che le condizioni verificate lungo le transizioni non provengono da un interrupt successivo che ha sovrascritto il valore precedente di buttonPressed
quello I necessario (anche se è impossibile che ciò accada perché devono trascorrere 250 ms).