¿Por qué mis interrupciones no están anidadas en un controlador ATSAM?

2

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.

    
pregunta vsz

2 respuestas

1

Esto se debe a que NVIC no forma parte de Atmel, sino que es parte de la IP proporcionada por ARM. Por lo tanto, encontrará toda la documentación sobre esta parte en el sitio web de ARM para su núcleo específico enlace

    
respondido por el Tom L.
1
  

Configurar una interrupción para que tenga una prioridad más alta que otra, aún no permite interrumpir la prioridad más baja.

Carful: Cortex-M usa 0 como la prioridad más alta , y num-of-prorities-minus-1 como la prioridad más baja . De forma predeterminada, todas las interrupciones tienen la prioridad 0 , por lo tanto, a menos que inicialice correctamente el NVIC utilizando un número mayor en NVIC_SetPriority() , no obtendrá interrupciones anidadas.

En su ejemplo, la interrupción SERCOM no puede preceder al temporizador. Tendría que establecer los SERCOM en cero (o algo más pequeño que 3) y el TEMPORIZADOR en la prioridad 3.

    
respondido por el Turbo J

Lea otras preguntas en las etiquetas