Pregunta inicial
Tengo una pregunta general sobre el manejo de las interrupciones en los microcontroladores. Estoy usando el MSP430, pero creo que la pregunta puede ser extendida a otros uCs. Me gustaría saber si es o no una buena práctica para habilitar/deshabilitar las interrupciones con frecuencia a lo largo del código. Quiero decir, si tengo una parte de código que no va a ser sensibles a las interrupciones (o peor aún, no hay que escuchar a las interrupciones, por cualquier razón), es mejor:
- Deshabilitar las interrupciones antes y luego volver a activar después de la sección crítica.
- Poner una bandera en el interior de los respectivos ISR y (en lugar de deshabilitar la interrupción), ajuste el indicador a false antes de la sección crítica y el restablecimiento a la verdadera, justo después. Para impedir que el código de la ISR de ser ejecutado.
- Ninguno de los dos, así que se admiten sugerencias!
Actualización: interrupciones y el estado de los gráficos
Voy a dar una situación específica. Supongamos que queremos implementar un organigrama del estado, el cual está compuesto por 4 bloques:
- Las Transiciones/Efecto.
- Condiciones de salida.
- Actividad de entrada.
- Hacer la actividad.
Esto es lo que un profesor nos enseñó en la universidad. Probablemente, no es la mejor manera de hacerlo es siguiendo 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;
(...)
}
}
También vamos a suponer que, por ejemplo STATE_A
, quiero ser sensibles a una interrupción proveniente de un conjunto de botones (con debouce sistema, etc. etc.). Cuando alguien pulsa uno de estos botones, se genera una interrupción y el indicador relacionado con el puerto de entrada se copia en una variable buttonPressed
. Si el rebote se establece en 200 ms de alguna manera (temporizador de vigilancia, temporizador, contador, ...) estamos seguros de que buttonPressed
no puede ser actualizado con un nuevo valor antes de 200 ms.
Esto es lo que estoy pidiendo a usted (y a mí :) por supuesto)
Necesito habilitar la interrupción en el HACER de la actividad de STATE_A
y desactivar antes de salir?
/* 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 manera que estoy seguro de que la próxima vez que me execxute bloque 1 (transición/efectos) en la siguiente iteración estoy seguro de que las condiciones que se verifican a lo largo de las transiciones no son procedentes de un posterior interrupción que ha sobrescrito el anterior valor de buttonPressed
que necesito (aunque es imposible que esto sucede debido a 250 ms debe transcurrir).