El AVR es una arquitectura RISC, por lo que tiene un manejo bastante básico de las interrupciones por hardware. La mayoría de los procesadores manipulan la pila durante las interrupciones, aunque hay un par, sobre todo ARM y PowerPC, que utilizan métodos diferentes.
En cualquier caso, esto es lo que hace el AVR para las interrupciones:
Cuando se produce una interrupción, el hardware del procesador realiza estos pasos, que no son un simple GOTO:
- Termina la instrucción actual.
- Desactivar la bandera de interrupción global.
- Empuja la dirección de la siguiente instrucción en la pila.
- Copiar la dirección en el vector de interrupción correcto (según la interrupción que se produjo) en el contador de programa.
En este punto, el hardware ha hecho todo lo que iba a hacer. El software tiene que ser escrito correctamente para no romper las cosas. Por lo general, los siguientes pasos son a lo largo de estas líneas.
-
Empuja el registro de estado a la pila. (Esto debe hacerse primero antes de modificarlo).
-
Coloca en la pila cualquier registro de la CPU que vaya a ser (o pueda ser) modificado. Los registros que deben ser guardados de esta manera son definidos por el modelo de programación. El modelo de programación lo define el compilador.
Ahora se puede ejecutar el código de interrupción de trabajo. Para responder al caso en la pregunta de llamar a una función, sólo hace lo que siempre hace, empujar el valor de retorno en la pila, y luego pop de nuevo cuando se hace. Esto no afecta a ninguno de los valores anteriores que hemos guardado en la pila hasta ahora.
- Ejecuta el código de trabajo ISR.
Ahora hemos terminado y queremos volver de la interrupción. Primero tenemos que hacer la limpieza del software.
- Despliega los registros de la CPU que empujamos en el paso 6.
- Vuelve a introducir el valor de estado guardado en el registro de estado. Después de esto tenemos que tener cuidado de no ejecutar ninguna instrucción que pueda cambiar el registro de estado.
-
Ejecuta la instrucción RTI. El hardware realiza estos pasos para esta instrucción:
a. Habilitar la bandera de interrupción global. (Tenga en cuenta que debe ejecutarse al menos una instrucción antes de que se respete la siguiente interrupción. Esto evita que las interrupciones pesadas bloqueen completamente el trabajo en segundo plano).
b. Introduzca la dirección de retorno guardada en el PC.
Ahora volvemos al código normal.
Tenga en cuenta que hay algunos puntos en los que tenemos que ser muy cuidadosos, en particular en torno al registro de estado y a los registros de ahorro que podrían ser modificados. Afortunadamente, si estás usando un compilador de C, todo esto se maneja bajo las cubiertas.
Además, hay que vigilar la profundidad de la pila. En cualquier momento en que las interrupciones estén habilitadas, un ISR podría usar más de la pila de lo que es obvio mirando el código local. Por supuesto, esto no se presenta mucho a menos que estés llevando la memoria a sus límites.
Aquí es un enlace que describe este proceso si quieres una referencia.
0 votos
La respuesta de abajo es estupenda, sólo ten en cuenta que el compilador no puede inlinear las llamadas de interrupción porque... Son llamadas de interrupción :D
1 votos
@VladimirCravero Me refería a inline las funciones llamadas dentro de la interrupción (si llamo a foo() en la ISR ¿se inlinea para que no sea realmente una llamada a una función?)
0 votos
Así que la respuesta de abajo no responde a tu pregunta, ¿o sí? caveman explica lo que ocurre cuando se produce una interrupción, pero no lo que ocurre cuando se llama a una función en un contexto interrumpido. la respuesta a esto último sería: nada especial, se llama a la función y ya está. la magia ocurre cuando se dispara la interrupción, lo que ocurre después (antes del iret) es simplemente código normal, normalmente no interrumpible.
0 votos
@VladimirCravero sí lo hace (indirectamente). Me refería a cómo se modificaba la pila para un ISR, pensando que había que modificarla para usar funciones en primer lugar. Voy a suponer que las funciones funcionan exactamente igual después de la configuración del ISR.
0 votos
Bien, lo tienes entonces. después del salto al vector de interrupción todo está bien y puedes ir por donde quieras.
0 votos
Incluso hay una parte en la respuesta donde digo "Para responder al caso en la pregunta de llamar a una función"... Está ahí desde el momento original de la publicación.