Función llamada en ISR y directiva de superposición -Keil / 8051 core

Mi código C tiene un ISR, donde se debe tomar una decisión para ejecutar una función "A" en particular. Ahora sé que no es bueno ejecutar una función en un ISR. Pero en este caso de mi aplicación, no veo otra salida. Después de llamar a la función "A", noté un salto repentino en el tamaño de los datos consumidos y la repentina ADVERTENCIA L15 explicada en KEIL EXPLICACIÓN DE LA ADVERTENCIA .

Estoy seguro de que la función "A" no se ejecuta de forma reentrante, pero seguro que consume memoria física; tanto la función "A" como las funciones a las que llama. (Esto creo que se refiere a las variables declaradas en las funciones).

En primer lugar, ¿hay alguna forma de evitar esa sesión en el espacio de la memoria de datos?

En segundo lugar, quiero aplicar el método 2 como se muestra en la explicación de Keil. Pero no sé cómo y dónde insertar exactamente la directiva OVERLAY en mi código. ¿En la inicialización? ¿En la función Declaración? ¿Antes de la definición de la función? ¿Donde exactamente?

EJEMPLO DE ADVERTENCIA en mi Código

*** WARNING L15: MULTIPLE CALL TO FUNCTION
NAME:    _IECLOC_FUN/DATA_ACCESS
CALLER1: ?C_C51STARTUP
CALLER2: TIMER_ISR/TIMER

ADVERTENCIA SIGNIFICADO

Se agradecerán correcciones, sugerencias, ejemplos de código y enlaces. Espero que esta pregunta sea clara.

Gracias a todos.

Respuestas (2)

Comprenda que con Keil en los núcleos 8051, las variables locales de la subrutina y cualquier argumento de entrada más allá de lo que cabría en los registros, el compilador asigna RAM para la ubicación de estos. El enlazador luego tiene un trabajo complicado que hace para analizar la estructura completa del árbol de llamadas de su programa y optimizar el grupo de memoria asignado para estos propósitos para minimizar la cantidad de RAM requerida. Esta minimización utiliza la exclusión mutua entre las secuencias de llamada de código para determinar qué partes del grupo de memoria se pueden compartir entre rutas de código que no se superponen en el flujo de ejecución.

Cuando inyecta una llamada ISR en la combinación del árbol de llamadas de código, el enlazador no puede determinar desde qué punto puede entrar en juego la interrupción. Podría llegar en cualquier momento durante cualquiera de las rutas de exclusión mutua que el enlazador encontró en el código principal normal. Esto significa que el enlazador tiene que extraer la subrutina del grupo de uso compartido y asignar espacio de datos específicamente para las variables locales de la subrutina y tal vez incluso algunos de sus argumentos de entrada. Sin esto, los grupos de memoria compartida de otras rutas de ejecución de código mutuamente excluyentes se contaminarían y el programa colapsaría con toda su gloria.

El desafío al codificar en un núcleo 8051 es tratar de alejarse de los diseños que usan muchas variables locales, tienen muchos argumentos de entrada y tienen contextos de llamadas que se comparten entre el código principal y las interrupciones. Realmente tiene que limitar las libertades que obtiene con otras arquitecturas que tienen una pila que se usa para pasar argumentos de subrutinas y variables locales. Keil eligió no implementar todo en la pila y, por lo tanto, produjo un conjunto de herramientas que ofrece rendimiento y optimización de primera clase en la industria para la arquitectura 8051. Y por esa razón es importante adaptar un estilo de codificación que se ajuste al esquema de Keil.

En su caso, realmente recomiendo que reconsidere su determinación de que esta subrutina debe llamarse tanto desde el contexto de línea principal como desde el contexto de interrupción. Intenta encontrar una técnica de diseño que evite esto y tu vida será mucho más simple.

@Micheal Karas.......... ¿Alguna sugerencia de técnica de diseño?
Ya se los di. Deja de llamar funciones desde interrupciones. Si no puede hacer eso en absoluto, minimice o mejor elimine las variables locales en las subrutinas llamadas desde el contexto de interrupción. Minimice o, mejor aún, elimine los argumentos de llamada en las rutinas llamadas desde el contexto de interrupción. Haga que la subrutina llamada sea plana en el sentido de que no llama a otras subrutinas o funciones de biblioteca.

La OVERLAYdirectiva es un comando para el enlazador y no entra en su código fuente en absoluto. Puede colocar directivas en la línea de comandos de BL51, pero para cualquier cosa que no sea trivial, generalmente es mejor colocarlas en un archivo de comando del vinculador separado y pasar ese archivo al vinculador usando la sintaxis en la línea de comando BL51 @<commandfile>.

Consulte la referencia de línea de comandos para BL51 aquí .

¡tararear! ¡Esto va más profundo de lo que pensaba!