Wstępne pytanie
Mam ogólne pytanie dotyczące obsługi przerwań w mikrokontrolerach. Korzystam z MSP430, ale myślę, że pytanie to może zostać rozszerzone na inne komputery PC. Chciałbym wiedzieć, czy dobrą praktyką jest włączanie / wyłączanie przerwań często w kodzie. Mam na myśli, jeśli mam część kodu, która nie będzie wrażliwa na przerwania (lub, co gorsza, nie może słuchać przerwań, z jakiegokolwiek powodu), czy lepiej:
- Wyłącz przerwania przed, a następnie włącz je ponownie po sekcji krytycznej.
- Umieść flagę wewnątrz odpowiedniego ISR i (zamiast wyłączania przerwania) ustaw flagę na false przed sekcją krytyczną i zresetuj ją do true zaraz po niej. Aby zapobiec wykonaniu kodu ISR.
- Żadna z tych dwóch, więc sugestie są mile widziane!
Aktualizacja: zakłócenia i wykresy stanów
Podam konkretną sytuację. Załóżmy, że chcemy zaimplementować wykres stanu, który składa się z 4 bloków:
- Przejścia / efekt.
- Warunki wyjścia.
- Aktywność wstępna.
- Wykonuj aktywność.
Tego nauczył nas profesor na uniwersytecie. Prawdopodobnie nie najlepszym sposobem jest wykonanie tego schematu:
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;
(...)
}
}
Załóżmy również, że od, powiedzmy STATE_A
, chcę być wrażliwy na przerwanie pochodzące od zestawu przycisków (z systemem debouce itp.). Gdy ktoś naciśnie jeden z tych przycisków, generowane jest przerwanie, a flaga związana z portem wejściowym jest kopiowana do zmiennej buttonPressed
. Jeśli odbijanie jest w jakiś sposób ustawione na 200 ms (watchdog timer, timer, counter, ...), jesteśmy pewni, że buttonPressed
nie można go zaktualizować o nową wartość przed 200 ms. O to proszę ciebie (i siebie :) oczywiście)
Czy muszę włączyć przerwanie aktywności DO STATE_A
i wyłączyć przed odejściem?
/* 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;
(...)
}
W taki sposób, że jestem pewien, że następnym razem, gdy wykonam blok 1 (przejście / efekty) przy następnej iteracji, jestem pewien, że warunki sprawdzone wzdłuż przejść nie pochodzą z kolejnego przerwania, które zastąpiło poprzednią wartość buttonPressed
tego I potrzeba (chociaż nie jest to możliwe, ponieważ musi upłynąć 250 ms).