Gran matriz en C18 provoca el reinicio del dispositivo

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?


La información de la sección solicitada:

              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

Respuestas (2)

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í.

Agregado:

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.

Añadido 2:

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.

Agregué la información de la sección. '.romdata_Main.o' 2024 bytes se colocan en la dirección 0x0008. ¿No es esa la dirección del vector de interrupción? Eso explicaría por qué se reinicia cuando se produce una interrupción...
¡Muchas gracias! Ahora al menos puedo solucionar este problema .

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()
{
  /* ... */
}
Es el enlazador el que coloca la matriz en 8, no el compilador. Sin embargo, como dije, no uso un compilador para el código de interrupción, pero me sorprende que el compilador no coloque la rutina o al menos un código auxiliar en el vector de interrupción fijo para usted. Pero, si puede colocar el stub de asm en 8, ¿por qué no puede colocar la rutina de interrupción en 8 en lugar de usar el mismo mecanismo? De esa manera, no debería necesitar un talón en absoluto.
@Olin Lathrop - Tienes razón... Puedo colocar el isr en 0x08. No hay necesidad de un talón. Pero aún extraño, tengo que decirle al enlazador que no quiero que el vector de interrupción sea anulado por algunos datos.
En realidad, no le está diciendo al enlazador que no desea que se anule el vector de interrupción, sino que, en este caso, desea este código en una dirección particular. Si no dice eso, el enlazador es libre de poner las cosas donde sea, lo que en este caso resultó con su matriz en 8. Bien podría haber algo más allí. Este problema no tenía nada que ver con su matriz, pero no determinó dónde debía ir la rutina de interrupción.