Por lo que he leído en internet debemos responder a las interrupciones lo más rápido posible, al programar microcontroladores; y que se deben evitar las banderas porque tienden a agravarse con el tiempo.
Pero la forma más rápida de responder a una interrupción es utilizando una bandera (sólo hay que cambiar el valor booleano de la variable y continuar el código dentro de la función principal). ¿Cómo resolver este problema? ¿Debería usarse una máquina de estado en cualquier interrupción para evitar las banderas o eso no importa?
Respuestas
¿Demasiados anuncios?Diseñar según las reglas generales que has encontrado en Internet es una mala idea. La forma correcta es comprender los problemas, ellos hacen concesiones inteligentes.
No hay nada de malo en que un sistema tome una interrupción, borre la condición del hardware, y luego establezca una bandera para que el código en primer plano haga el resto del procesamiento cuando lo haga. El peligro en esto es que el código en primer plano podría no llegar a hacerlo en un tiempo, y si la misma condición ocurre de nuevo antes de eso, la información podría perderse. O, si algo necesita ser manejado con baja latencia o jitter, entonces probablemente quieras manejarlo en la rutina de interrupción.
Otra vez, comprender las compensaciones. El código de interrupción se ejecuta inmediatamente después de que se produzca la condición, a expensas de todo lo demás que el procesador tenga que hacer en ese momento. ¿Merece la pena? Eso depende. ¿Cuánto retraso puedes tolerar en el manejo de la condición? ¿Qué importancia tiene que el código en primer plano no se retrase? Debería ser obvio que no hay una respuesta única y universal a esto. Depende en gran medida de la aplicación concreta.
Por ejemplo, si parte del trabajo de los procesadores es responder a un flujo de comandos en serie que se le envía a 115,2 kbaudios, entonces los bytes se pueden recibir tan rápido como cada 87 µs. La rutina de interrupción podría simplemente establecer una bandera para que la rutina en primer plano sepa que debe leer un byte de la UART, pero eso requeriría que el código en primer plano comprobara la bandera al menos cada 87 µs. En muchos casos, eso sería difícil. Una buena compensación para muchos casos (de nuevo, esto podría no ajustarse a ningún caso en particular) sería que la rutina de interrupción tomara el byte de la UART, borrara la condición de hardware, y metiera el byte en un FIFO de software. El código de primer plano entonces vacía el FIFO como puede, probablemente en ráfagas entre la realización de otras tareas que pueden tomar más tiempo que el tiempo del byte de 87 µs.
Por otro lado, la rutina de interrupción de un botón de usuario puede realizar sólo el rebote y establecer una bandera cuando el botón está en un nuevo estado. El sistema sólo necesita responder al botón en tiempo humano, que puede ser de muchos milisegundos. Si el código de primer plano comprueba todos los eventos al menos cada pocos milisegundos, entonces no hay necesidad de que la rutina de interrupción haga más procesamientos que los descritos.
En general, la rutina de interrupción debería hacer cualquier procesamiento inmediatamente sensible a la latencia o al jitter que deba realizarse debido al evento, y luego establecer el estado para que el procesamiento que pueda responder más lentamente pueda realizarse más tarde desde el código de primer plano. Sin embargo, de nuevo, no te limites a usar esto como regla general. Entiende el porqué. Entonces no necesitarás ninguna regla general.
No, no es necesario responder a las interrupciones lo antes posible. Supongamos que tienes una interrupción que te indica cuando el buffer de transmisión de la UART está vacío. Si no tienes nada que necesites enviar entonces puedes esperar todo el tiempo que quieras para atender esa interrupción.
Creo que lo que has leído es que las rutinas de servicio de interrupción deben ser lo más cortas posible. Esto es generalmente cierto, porque tener rutinas de servicio de interrupción largas puede retrasar la respuesta a otras interrupciones o causar jitter en el tiempo de respuesta.
No sé a qué te refieres con "banderas". Si te refieres a una variable estática, entonces no debería haber ningún problema en escribir en dicha variable dentro de un ISR y utilizar su valor fuera del ISR. Sin embargo, si tienes una compartido una variable que puede ser modificada tanto dentro como fuera de un ISR, entonces puedes tener problemas. La forma más sencilla de manejar esto es deshabilitar todas las interrupciones cada vez que cualquier pieza de código modifique la variable compartida, y hacer esto tan rápido como sea posible.
Te he dado respuestas muy simples, aunque el campo de la multitarea en los sistemas embebidos incluye muchas soluciones posibles a estos problemas. A menos que puedas hacer una pregunta más específica, será difícil darte mejores respuestas.