Pregunta inicial
Tengo una pregunta general sobre el manejo de interrupciones en microcontroladores. Estoy usando el MSP430, pero creo que la pregunta puede extenderse a otras unidades de control de usuario. Me gustaría saber si es o no una buena práctica habilitar / deshabilitar las interrupciones a lo largo del código. Quiero decir, si tengo una parte del código que no será sensible a las interrupciones (o, lo que es peor, no debe escuchar las interrupciones, por cualquier motivo), es mejor:
- Deshabilite las interrupciones antes y luego vuelva a habilitarlas después de la sección crítica.
- Coloque un indicador dentro del ISR respectivo y (en lugar de deshabilitar la interrupción), establezca el indicador en falso antes de la sección crítica y restablézcalo en verdadero, justo después. Para evitar que el código del ISR se ejecute.
- Ninguno de los dos, ¡las sugerencias son bienvenidas!
Actualización: interrupciones y gráficos de estado
Voy a proporcionar una situación específica. Supongamos que queremos implementar un gráfico de estado, que está compuesto por 4 bloques:
- Transiciones / Efecto.
- Condiciones de salida.
- actividad de entrada.
- hacer actividad.
Esto es lo que un profesor nos enseñó en la universidad. Probablemente, no es la mejor manera de hacerlo 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;
(...)
}
}
Supongamos también que desde, por ejemplo, STATE_A
, quiero ser sensible a una interrupción proveniente de un conjunto de botones (con el sistema debouce, etc., etc.). Cuando alguien presiona uno de estos botones, se genera una interrupción y la bandera relacionada 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 se puede actualizar con un nuevo valor antes de 200 ms.
Esto es lo que te estoy preguntando a ti (ya mí :) por supuesto)
¿Debo habilitar la interrupción en la actividad de OD de STATE_A
y deshabilitarla antes de irme?
/* 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 ejecute el bloque 1 (transición / efectos) en la próxima iteración, estoy seguro de que las condiciones verificadas a lo largo de las transiciones no provienen de una interrupción posterior que haya sobrescrito el valor anterior de buttonPressed
que necesito (aunque es imposible que esto suceda porque deben transcurrir 250 ms)