El AVR es una arquitectura RISC, por lo que tiene un manejo bastante básico del hardware de las interrupciones. La mayoría de los procesadores se meten con la pila durante las interrupciones, aunque hay un par, especialmente ARM y PowerPC, que utilizan diferentes métodos.
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 solo un simple GOTO:
- Terminar la instrucción actual.
- Deshabilita la bandera de interrupción global.
- Empuje la dirección de la siguiente instrucción en la pila.
- Copie la dirección en el vector de interrupción correcto (de acuerdo con la interrupción que ocurrió) en el contador del programa.
Ahora en este punto, el hardware ha hecho todo lo que va a hacer. El software tiene que estar escrito correctamente para no romper cosas. Por lo general, los siguientes pasos son a lo largo de estas líneas.
Empuje el registro de estado en la pila. (Esto debe hacerse primero antes de cambiarlo).
Empuje cualquier registro de CPU que se (o pueda) cambiar en la pila. El modelo de programación define qué registros que deben guardarse de esta manera. El modelo de programación lo define el compilador.
Ahora se puede ejecutar el código de interrupción de trabajo. Para responder el caso en la cuestión de llamar a una función, simplemente hace lo que siempre hace, empuja el valor de retorno en la pila y luego lo vuelve a abrir cuando termina. Esto no afecta a ninguno de estos valores anteriores que guardamos en la pila hasta ahora.
- Ejecute el código de trabajo ISR.
Ahora hemos terminado y queremos volver de la interrupción. Primero tenemos que hacer la limpieza del software.
- Pop los registros de la CPU que empujamos en el paso 6.
- Vuelva a colocar el valor de estado guardado en el registro de estado. Después de esto, debemos tener cuidado de no ejecutar ninguna instrucción que pueda cambiar el registro de estado.
Ejecute la instrucción RTI. El hardware realiza estos pasos para esta instrucción:
a. Habilite la bandera de interrupción global. (Tenga en cuenta que al menos una instrucción debe ejecutarse antes de que se cumpla la próxima interrupción. Esto evita que las interrupciones intensas bloqueen completamente el trabajo en segundo plano).
si. Introduzca la dirección de retorno guardada en la PC.
Ahora volvemos al código normal.
Tenga en cuenta que hay algunos puntos en los que debemos ser muy cuidadosos, especialmente en relación con el registro de estado y guardar registros que podrían modificarse. Afortunadamente, si está utilizando un compilador de C, todo esto se maneja debajo de las cubiertas.
Además, debes observar la profundidad de tu stack. En cualquier momento cuando las interrupciones están habilitadas, un ISR podría usar más de la pila de lo que es obvio al mirar el código local. Por supuesto, esto realmente no surge mucho a menos que esté llevando su memoria al límite.
Aquí hay un enlace que describe este proceso si desea una referencia.