¿Cómo puedo decirle al compilador XC8 de Microchip que estoy usando un controlador de interrupción personalizado? ¡Intenta colocar otro código en la dirección 4!

3

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ón0queguardalosbitsrelevantesdelregistroSTATUSantesdesaltaralcó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?

    
pregunta pipe

1 respuesta

8

intentry

La solución se llama intentry y es el nombre de una sección generada por el compilador. El manual dice:

  

intentry : contiene el código de entrada para la rutina de servicio de interrupción que está vinculado al vector de interrupción. Este código guarda los registros necesarios y salta al código de interrupción principal en el caso de dispositivos de rango medio; para dispositivos de rango medio mejorados, este psect contendrá el cuerpo de la función de interrupción. Este psect debe estar vinculado en el vector de interrupción.

Esto no suena muy atractivo, y no es obvio que pueda colocar su propio código en esa sección. Sin embargo, si lo hace, el enlazador ya está configurado para colocarlo en la dirección correcta y, lo más importante, sabe que no debe colocar el código otro allí.

Para usarlo, escribe tu código de esta manera:

; This is the main interrupt handler. It is placed at address 4.
PSECT intentry,class=CODE,delta=2,space=0
    movwf   isr_temp_w
    swapf   STATUS,w
    clrf    STATUS           ; Switch to bank 0
    movwf   isr_temp_status
    ...
    swapf   isr_temp_status,w
    movwf   STATUS
    swapf   isr_temp_w,f
    swapf   isr_temp_w,w
    retfie

Simple! El enlazador se encarga del resto. Con o sin la opción Indicadores de condición de restablecimiento de la copia de seguridad , el código de inicio ahora evita el controlador personalizado:

No estoy seguro de que esta sea la solución correcta , ni que sea la solución only , pero es la solución una .

    
respondido por el pipe

Lea otras preguntas en las etiquetas