El controlador de interrupción de un ATSAMD21 (basado en un Cortex-M0 +) se llama NVIC (controlador de interrupción de vector anidado), por lo que esperaba que fuera fácil anidar las interrupciones.
La documentación no menciona cómo una interrupción puede interrumpir otra interrupción. En realidad, no dice mucho sobre las interrupciones, ya que ni siquiera tienen sus registros en la lista, solo se mencionan en el capítulo "Procesador y arquitectura", a diferencia de otros periféricos que tienen sus propios capítulos.
Buscando en los encabezados y en el depurador, encontré los siguientes registros utilizados por el controlador de interrupción:
- habilitar registro. Cada una de las 28 posibles interrupciones tiene un poco aquí.
- registro pendiente. igual que arriba
- registro de prioridad.
Configurar una interrupción para que tenga una prioridad más alta que otra, aún no permite interrumpir la prioridad más baja.
Las notas de aplicación sobre interrupciones no mencionan ninguna forma de anidar las interrupciones, está bastante escrito que:
Dentro de un ISR, las interrupciones están deshabilitadas. Por lo tanto no hagas nada eso requiere una interrupción para ser reparado.
EDIT : gracias a señalarme la documentación ARM, donde se indica que las interrupciones de mayor prioridad siempre se anticipan a las interrupciones de menor prioridad. Sin embargo, algunos experimentos muestran que no ocurre en mi tablero o que demora demasiado.
Configuración experimental
Los enlaces a esta pregunta mostraron que las declaraciones que interrumpen el anidamiento no solo son posibles, sino que en realidad son la única opción para los procesadores Cortex-M0. Sin embargo, mis experimentos muestran lo contrario.
En una interrupción por desbordamiento del temporizador, lo primero que hago es verificar el valor del temporizador, obteniendo así la latencia de la interrupción (+ los pocos relojes necesarios para leer el temporizador). Calculo el máximo de esta latencia durante un período de al menos un minuto.
-
Si solo tengo este temporizador en funcionamiento, tengo tiempos por debajo de 1.5 µs
-
Si inicio varios remitentes SPI (SERCOM), todos los que transmiten continuamente (todo lo que hacen en su interrupción de transmisión es buscar el siguiente byte), mido 4.2 µs
-
Si pongo un código de pérdida de tiempo deliberado (algunas operaciones de punto flotante) en dos de las interrupciones de transmisión de SERCOM, ¡mido 140 µs!
-
Si pongo la interrupción del temporizador en la prioridad 0 (la más alta) y todos los SERCOM en la prioridad 3, ¡mido 70 µs! La mitad del tiempo que medí cuando todas las interrupciones tenían la misma prioridad. Esto también parece mostrar que la interrupción del SERCOM nunca fue interrumpida por la interrupción del temporizador.
-
Si duplico las operaciones de punto flotante en las interrupciones SERCOM, la latencia en el peor de los casos en la interrupción del temporizador es de casi 140 µs, lo que indicaría que no están interrumpidas.
-
Si pongo un bucle sin fin después de las operaciones de flotación, el tiempo sigue siendo de 140 µs, por lo que el bucle sin fin se interrumpe. (Y no se optimizó a distancia; si configuro todas las prioridades de interrupción de nuevo en el mismo valor, se atascará en el bucle infinito)
EDIT Mi error fue que, aunque configuré las prioridades en las interrupciones SERCOM, no las configuré en todas. Las prioridades de interrupción de SERCOM se deben establecer individualmente. Cerrando la pregunta, ya que creo que se desvió demasiado de su concepto original para tener esto publicado como respuesta.