Estoy usando el compilador PIC18F13K22 y C18 de Microchip en MPLABX. El PIC siguió reiniciando, cuando estaba a punto de saltar a la rutina de servicio de interrupción (ISR). Pude rastrear el problema hasta la declaración de una matriz:
UINT16 rom periods[] = {64000,59412,55438,51962, ...} // 1024 Values
Si reduzco el tamaño de la matriz a unos pocos elementos, el PIC se ejecuta sin reiniciarse continuamente.
Ahora me pregunto por qué la matriz grande provoca un reinicio. Y aún más interesante para mí: ¿puedo declarar de alguna manera un conjunto de datos que contenga estos 1024 valores?
Section Type Address Location Size(Bytes)
--------- --------- --------- --------- ---------
_entry_scn code 0x000000 program 0x000006
.cinit romdata 0x000006 program 0x000002
.romdata_Main.o romdata 0x000008 program 0x000800
.code_Main.o code 0x000808 program 0x000124
_cinit_scn code 0x00092c program 0x00009e
.code_Debug.o code 0x0009ca program 0x000080
.code_Signal.o code 0x000a4a program 0x000040
PROG code 0x000a8a program 0x00003c
.code_t0open.o code 0x000ac6 program 0x000038
.code_ADC.o code 0x000afe program 0x000032
.stringtable romdata 0x000b30 program 0x000026
.code code 0x000b56 program 0x000020
_startup_scn code 0x000b76 program 0x00001c
.code___init.o code 0x000b92 program 0x000002
.romdata_t0open.o romdata 0x000b94 program 0x000000
.idata___init.o_i romdata 0x000b94 program 0x000000
.idata_t0open.o_i romdata 0x000b94 program 0x000000
.romdata_Debug.o romdata 0x000b94 program 0x000000
.idata_Debug.o_i romdata 0x000b94 program 0x000000
.romdata___init.o romdata 0x000b94 program 0x000000
.romdata_Signal.o romdata 0x000b94 program 0x000000
.idata_Signal.o_i romdata 0x000b94 program 0x000000
.idata_Main.o_i romdata 0x000b94 program 0x000000
.romdata_ADC.o romdata 0x000b94 program 0x000000
.idata_ADC.o_i romdata 0x000b94 program 0x000000
.code_c018i.o code 0x000b94 program 0x000000
.romdata_c018i.o romdata 0x000b94 program 0x000000
.idata_c018i.o_i romdata 0x000b94 program 0x000000
.config_300001_Main.o romdata 0x300001 program 0x000001
.config_300002_Main.o romdata 0x300002 program 0x000001
.config_300003_Main.o romdata 0x300003 program 0x000001
.config_300005_Main.o romdata 0x300005 program 0x000001
.config_300006_Main.o romdata 0x300006 program 0x000001
MATH_DATA udata 0x000000 data 0x000014
.tmpdata udata 0x000014 data 0x000000
.stack udata 0x000060 data 0x000050
.udata_c018i.o udata 0x0000b0 data 0x00000a
.udata_Signal.o udata 0x0000ba data 0x000002
.idata_c018i.o idata 0x0000bc data 0x000000
.udata_ADC.o udata 0x0000bc data 0x000000
.idata_ADC.o idata 0x0000bc data 0x000000
.udata_Main.o udata 0x0000bc data 0x000000
.idata_Main.o idata 0x0000bc data 0x000000
.idata_Signal.o idata 0x0000bc data 0x000000
.udata_Debug.o udata 0x0000bc data 0x000000
.idata_Debug.o idata 0x0000bc data 0x000000
.udata_t0open.o udata 0x0000bc data 0x000000
.idata_t0open.o idata 0x0000bc data 0x000000
.udata___init.o udata 0x0000bc data 0x000000
.idata___init.o idata 0x0000bc data 0x000000
SFR_UNBANKED0 udata 0x000f68 data 0x000098
No hay ninguna razón inherente por la que esta matriz deba provocar un reinicio. Aparentemente, está declarando 2 kBytes de constantes en la memoria del programa. Ese PIC tiene 8 kBytes de memoria de programa, por lo que debería estar bien.
Lo más probable es que haya un error en otra parte. Esta matriz es probablemente lo más grande que el enlazador tiene que colocar, por lo que todo el código que no esté en direcciones fijas específicas probablemente se moverá a medida que se cambia el tamaño de la matriz, lo que puede hacer que aparezcan y desaparezcan algunos errores.
Puede ser útil mostrar la parte "Información de la sección" del archivo MAP del enlazador para que podamos ver qué terminó dónde. Además, intente pasar por esto con el simulador y vea si termina ejecutando ubicaciones no deseadas o algo así.
De la palabra clave "rom", obviamente tenía la intención de que esta matriz estuviera en la memoria del programa. Asegúrese de que el compilador de C haya entendido esto correctamente. Uso C18 con poca frecuencia y no recuerdo cuáles son los encantamientos correctos para definir constantes en la memoria del programa. Si el compilador no lo puso allí, podrían suceder todo tipo de cosas extrañas. Nuevamente, el archivo del mapa del enlazador aclararía esto.
Ahora que tenemos un archivo de mapa del enlazador, podemos ver el problema. 1024 palabras de 16 bits cada una son 2048 bytes, que son 800h. Solo hay una sección cerca de ese tamaño, y tiene exactamente 800 h bytes, por lo que el compilador entendió que debía colocarla en la memoria del programa. Sin embargo, tenga en cuenta que se coloca en la dirección 8. Esa es la dirección del vector de interrupción de prioridad única o alta. Esta matriz también se superpone a la dirección de interrupción de baja prioridad en 16, por lo que las interrupciones de cualquier manera no se pueden usar con el lugar donde se colocó esta matriz.
El hecho de que el enlazador colocó la matriz donde lo hizo significa que nada más estaba reclamando la dirección fija de cualquiera de los vectores de interrupción. No uso C para las rutinas de interrupción, pero esto me dice que el compilador de C no entiende que su rutina de interrupción en realidad es una rutina de interrupción, o que no se incluyó en el enlace.
No sé cómo llamaste al módulo de rutina de interrupción, pero ¿está incluido en el mapa de enlaces? Si es así, entonces olvidó murmurar el conjuro correcto para que el compilador sepa que es una rutina de interrupción y, por lo tanto, lo fuerce a una dirección en particular. Si no, entonces no se incluye en el enlace de alguna manera. Esto puede suceder si coloca todos los archivos de objetos en una biblioteca para que el enlazador pueda elegir lo que quiera y no falten elementos externos al módulo de interrupción. Eso puede suceder con un módulo de interrupción ya que nunca se llama explícitamente. En ese caso, el archivo de objeto del módulo de interrupción debe entregarse explícitamente al enlazador.
Debido a la respuesta de Olin, pude eliminar el problema.
Como ha escrito Olin, el enlazador coloca la matriz en la dirección 0x08. Esta es la dirección del vector de interrupción.
Una 'solución alternativa' ahora es colocar explícitamente el código en la dirección 0x08, que salta a la ISR. (Inspirado en la página 29 de la guía del usuario del C18 ):
void isr(void);
#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
_asm GOTO isr _endasm
}
#pragma code
#pragma interrupt isr
void isr (void)
{
/* ... */
}
o incluso más simple:
#pragma code high_vector=0x08
#pragma interrupt isr
void isr()
{
/* ... */
}
PetPaulsen
PetPaulsen