Estoy desarrollando un firmware para el microchip PIC16F882 usando el microcontrolador MPLAB X IDE y la versión gratuita de su compilador XC8 C. Tengo un pequeño problema al intentar agregar un controlador de interrupción personalizado.
Porque la versión gratuita del compilador es irrazonablemente incompetente , estoy escribiendo la mayor parte del controlador de interrupciones en el ensamblaje, para poder exprimir los últimos ciclos. Esto funciona muy bien hasta ahora, pero ahora quiero eliminar el último bit de sobrecarga: la envoltura de interrupción incorporada normalmente colocada en la dirección 4 (este PIC tiene un vector de interrupción fijo).
El envoltorio está diseñado para manejar funciones genéricas de C, por lo que dedica un poco de esfuerzo y memoria a guardar datos y registros que no uso.
El manual no es obvio aquí, y he intentado dos cosas:
Aspectos absolutos
MPLAB XC8 puede determinar los límites de direcciones de los psectos absolutos y utiliza esta información para garantizar que el código producido desde la fuente C por el generador de código no use la memoria requerida por el código de ensamblaje. El generador de código reservará cualquier memoria utilizada por el código de ensamblaje antes de compilar la fuente C
.
He modificado su ejemplo para colocar mi controlador de interrupciones en la dirección 4:
PSECT my_isr,class=CODE,delta=2,space=0,abs,ovrld
ORG 4
my_isr:
...
-P spec
Utilizando un indicador de vinculador personalizado, puedo colocar una sección donde lo desee. En lugar de jugar con la directiva ORG 4
, agregué esto a los indicadores del vinculador:
-Pmy_isr=4
El problema: Indicadores de condición de restablecimiento de la copia de seguridad
Ambos colocan correctamente el código en la dirección 4. ¡Problema resuelto!
... no tan rápido ...
Normalmente, la primera instrucción colocada en la dirección 0
por el compilador y el vinculador es un GOTO
a la rutina de inicialización. Entonces, si no hay un controlador de interrupciones, coloca cosas "aleatorias" allí, al parecer, le gusta continuar con tablas y demás.
Si se define un controlador de interrupción en C, la primera instrucción sigue siendo un GOTO
. Luego, en la dirección 4 está el código del envoltorio de interrupción, que eventualmente salta al controlador de interrupción. Esto es completamente como se esperaba.
El problema es con este pequeño botón llamado Indicadores de condición de restablecimiento de la copia de seguridad :
ConservarlosbitsdeESTADOdeapagadoytiempodeesperaalinicio(soloPIC10/12/16).
Cuandoseleccionoeso,elcompiladorinsertaelcódigoenladirección0queguardalosbitsrelevantesdelregistroSTATUS
antesdesaltaralcódigodeinicialización:
0000 0000 NOP
0001 0183 CLRF STATUS
0002 0803 MOVF STATUS,w
0003 00A0 MOVWF ___resetbits
0004 2919 GOTO __initialization
Tenga en cuenta que el código termina en la dirección 4, inclusive .
Si agrego un controlador de interrupción en C, el compilador sabe que la dirección 4 está prohibida, y en su lugar reemplaza el código anterior con un NOP
y un GOTO
:
0000 0000 NOP
0001 2810 GOTO 0x0010
...
0010 0183 CLRF STATUS
0011 0803 MOVF STATUS,w
0012 00A0 MOVWF ___resetbits
0013 2919 GOTO __initialization
Pero si implemento mi propio controlador de interrupciones como se describe anteriormente, al habilitar la opción para guardar el registro de estado, el compilador genera un código en la dirección 0 a 4, que mi código luego sobrescribe rápidamente, lo que lleva a a un lío confuso que no arranca:
0000 0000 NOP
0001 0183 CLRF STATUS
0002 0803 MOVF STATUS,w
0003 00A0 MOVWF ___resetbits
0004 00F0 MOVWF 0x70 ; Oops! Should've been a GOTO!
0005 0E03 SWAPF STATUS,w
...
He intentado usar la directiva GLOBAL
para asegurarme de que mi manejador sea visto por mi main.c
, pero eso solo produce una advertencia de superposición, no una solución real al problema.
¿Cómo le digo al compilador que tengo un controlador de interrupción personalizado?