Questão inicial
Eu tenho uma pergunta geral sobre o manuseio de interrupções em microcontroladores. Estou usando o MSP430, mas acho que a pergunta pode ser estendida a outros UCs. Gostaria de saber se é uma boa prática ativar / desativar as interrupções com frequência ao longo do código. Quero dizer, se eu tenho uma parte do código que não será sensível a interrupções (ou, pior ainda, não deve ouvir interrupções, por qualquer motivo), é melhor:
- Desative as interrupções antes e depois as reative após a seção crítica.
- Coloque um sinalizador dentro do respectivo ISR e (em vez de desativar a interrupção), defina o sinalizador como false antes da seção crítica e redefina-o para true, logo após. Para impedir que o código do ISR seja executado.
- Nenhum dos dois, então sugestões são bem-vindas!
Atualização: interrupções e gráficos de estado
Vou fornecer uma situação específica. Vamos supor que queremos implementar um gráfico de estados, composto por 4 blocos:
- Transições / Efeito.
- Condições de saída.
- Atividade de entrada.
- Faça atividade.
Isso é o que um professor nos ensinou na universidade. Provavelmente, não é a melhor maneira de fazer isso, seguindo este esquema:
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;
(...)
}
}
Suponhamos também que, digamos STATE_A, eu queira ser sensível a uma interrupção vinda de um conjunto de botões (com sistema de desacoplamento, etc. etc.). Quando alguém pressiona um desses botões, uma interrupção é gerada e o sinalizador relacionado à porta de entrada é copiado em uma variável buttonPressed. Se o debounce estiver definido para 200 ms de alguma forma (watchdog timer, timer, counter, ...), temos certeza de que buttonPressednão será possível atualizar com um novo valor antes de 200 ms. É isso que estou perguntando a você (e a mim mesmo :), é claro)
Preciso ativar a interrupção na atividade DO STATE_Ae desativar antes de sair?
/* 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;
(...)
}
De uma maneira que tenho certeza de que na próxima vez em que executo o bloco 1 (transição / efeitos) na próxima iteração, tenho certeza de que as condições verificadas ao longo das transições não são provenientes de uma interrupção subsequente que substituiu o valor anterior buttonPresseddaquele precisa (embora seja impossível que isso aconteça porque 250 ms devem decorrer).