¿Existen pautas disponibles para la cantidad de código que se debe tener en una sección crítica del procesamiento impulsado por interrupciones?
Mi regla general personal es que la parte crítica (es decir, entre deshabilitar interrupciones y habilitar interrupciones) de cualquier procesamiento controlado por interrupción no debe tener más de una docena de líneas de código (incluidas las de cualquier función/biblioteca/macro llamada ), y que el procesamiento debe ser lo más lineal posible.
Esperaría algo como:
disable_interrupts
if error_condition:
set_error_flag
else:
small_data_transfer
set_ready_flag
enable_interrupts
Sin embargo, me han pedido que analice un proyecto existente en el que algunas de las interrupciones tienen controladores en los que los gráficos de llamadas no caben en una hoja de A1 (todas en la sección crítica).
Para aclarar, este es un proyecto "bare metal" sin OS/Scheduler implementado, y todos los controladores de interrupciones comienzan deshabilitando todas las interrupciones, es decir, los autores originales consideraron que cada operación en cada ISR es crítica (incluso la limpieza está dentro de una sección de activación/desactivación). Hay una multitud de interrupciones y dependencias de hardware pero, por lo que puedo ver, algunos de los ISR ejecutarán miles de líneas dentro de la sección "crítica".
Sé que esto es un problema y realmente necesita ser reescrito por completo, pero no puedo encontrar ningún estándar, incluido MISRA, que pueda señalar en lugar de simplemente decir " en mi experiencia ", para convencer a la gerencia del proyecto que debo señalar. algunos estándares aceptados.
Entonces, de ahí mi pregunta: ¿alguien puede indicarme algún estándar o guía que pueda usar para respaldar mi experiencia? (O, por supuesto, estoy totalmente equivocado).
En general, la distribución del tiempo de CPU entre el código ISR y el código no ISR depende mucho de la aplicación.
Si la mayor parte del trabajo se realiza en código que no es ISR, entonces sí, por lo general desea mantener los ISR lo más cortos posible (pero no más cortos, parafraseando una cita famosa).
Sin embargo, he visto (y creado) aplicaciones DSP en tiempo real en las que el 90% del trabajo se realiza en el ISR, y el código que no es ISR solo maneja tareas que no son críticas en cuanto al tiempo, como configuración, estado y interfaz de usuario.
Cualquiera de los enfoques es perfectamente válido en sistemas profundamente integrados.
La pauta general es que las secciones críticas deben ser lo más cortas posible.
Lo que realmente debe hacer es tener en cuenta la longitud de la sección crítica cuando verifique la capacidad de programación del conjunto de tareas. Hacer eso depende de cómo programe las tareas, pero creo que podría ser tan simple como agregar el tiempo de ejecución de la sección crítica al tiempo de ejecución de cada tarea de menor prioridad.
Creo que debe considerar el tiempo de ejecución del código ininterrumpible con el tiempo de respuesta más rápido (latencia) y la variabilidad de ese tiempo (inestabilidad) que necesita del microcontrolador. Puede que no sea intuitivo qué es eso; puede ser algo que es 'urgente' pero no 'importante'.
Por ejemplo, un controlador que diseñé hace algunos años necesitaba manejar entradas RS-232, actualizar la salida usando el algoritmo de control, controlar el ADC de doble pendiente, escanear una pantalla LED y un teclado (incluido el antirrebote), escribir en una EEPROM lenta, y para controlar un beeper electromagnético (y probablemente un par de otras cosas que he olvidado). Resultó que el tiempo de respuesta más crítico fue la interrupción periódica del pitido (cada 250 useg), seguida de la pantalla LED, principalmente por razones estéticas. Entonces, si el 10% de fluctuación en el conmutador de pitido era aceptable, eso es 25 useg de código ininterrumpido (que no eran muchas instrucciones, pero suficientes para hacer que ciertas cosas fueran atómicas). Ese procesador en particular admitía interrupciones anidadas, por lo que IIRC I terminó haciendo que el código de interrupción periódica volviera a entrar después de la primera sección.
Si está aplazando las interrupciones pendientes durante largas secciones de código, puede estar bien, si sus requisitos de latencia y fluctuación son bastante relajados en relación con el tiempo de ejecución de las "partes críticas".
Mi enfoque habitual es minimizar el tiempo de ejecución del código en los ISR y volver lo más rápido posible (tal vez rellenando cosas como tokens de eventos de entrada rebotados en colas circulares, establecer banderas y salir). Por ejemplo, si es necesario ejecutar un algoritmo de control complejo cada 200 mseg con un jitter máximo de 20 mseg, configuraría un indicador cada 200 mseg en la interrupción del temporizador y sondearía ese indicador fuera del ISR.
Además de cumplir con los requisitos de diseño, este enfoque mejora la confiabilidad.
En cuanto a encontrar algún tipo de directriz que establezca esto... sugiero mirar algunas de las directrices de software críticas para la seguridad. Es posible que no lo encuentre declarado directamente, pero puede inferirlo de otras declaraciones. UL1998 IEC 60730, etc. Este documento de la FAA establece:
Las interrupciones y su efecto sobre los datos deben recibir atención especial en áreas críticas para la seguridad. El análisis debe verificar que las interrupciones y las rutinas de manejo de interrupciones no alteren los elementos de datos críticos utilizados por otras rutinas.
y
De particular interés para la seguridad es garantizar la integridad de los datos críticos de seguridad para que no se modifiquen o sobrescriban inadvertidamente. Por ejemplo, verifique si el procesamiento de interrupciones interfiere con los datos críticos de seguridad.
Ambos se vuelven más difíciles a medida que aumenta el tamaño del código de interrupción.
Las interrupciones frecuentes cortas (en relación con la latencia y la fluctuación máximas) se pueden analizar como una disminución efectiva de la velocidad del procesador en lugar de tener que lidiar con las peores situaciones acumuladas de interrupciones largas en los momentos más críticos, lo que también aboga por una ejecución rápida como código simple dentro de ISR.
Para mí, evitar las interrupciones de anidamiento no parece tan malo o incluso absurdo. De hecho, las interrupciones anidadas pueden causar más problemas de los que resuelven.
Me refiero específicamente a la memoria utilizada para guardar/restaurar contexto al entrar/salir del ISR. Comúnmente, en arquitecturas simples, cada ISR guardará todo el contexto requerido del código que interrumpió, por ejemplo, en la pila del procesador. Al desarrollar el software, es necesario tener en cuenta esta memoria.
Si, por ejemplo, ISR A requiere 10 bytes de contexto para guardar/restaurar, ISR B necesita 15 e ISR C necesita 12 bytes, el cálculo/estimación simplemente es:
En cualquier lugar durante la ejecución de secciones no críticas, cualquiera de los ISR puede activarse. Ahora, si no se permite anidar los ISR , la memoria máxima requerida para el contexto es max( 10, 15, 12 )
= 15 bytes. Si cada uno de los ISR puede interrumpir cualquier otro de esos 3 ISR, el peor de los casos será 10 + 15 + 12
= 37 bytes de contexto que deben almacenarse al mismo tiempo . Entonces, en cada instante durante la ejecución (de código no atómico), debe haber al menos suficiente memoria disponible para esos 37 bytes de contexto, frente a 15 en el caso de no anidamiento.
Por supuesto, cuantos más ISR se unan al "juego de anidamiento", más visible se vuelve el problema.
Si tiene varias tareas que se ejecutan simultáneamente y los ISR guardan el contexto en la pila actual de cualquier código que estén interrumpiendo, debe tener en cuenta el tamaño de contexto del peor de los casos por tarea .
Este argumento, por supuesto, depende de la arquitectura HW que esté utilizando. Puede que no sea aplicable si el controlador de interrupción/HW es más avanzado y tiene características especiales para manejar el cambio de contexto hacia/desde ISR.
Aparte de eso, los ISR complejos tienden a requerir más datos de contexto para guardar/restaurar que los simples, por lo que generalmente se recomiendan ISR pequeños y concisos porque brindan múltiples beneficios:
Al final, si todos los ISR se reducen al mínimo, como cuando solo se establece una bandera, la pregunta de si permitir o no anidar ISR puede responderse claramente a favor de no anidar porque el beneficio de anidar ISR se desvanece.
connor lobo
connor lobo
david tweed
steve barnes
Cuchara
david tweed
steve barnes
david tweed
steve barnes
david tweed
steve barnes
Rdo