La matriz grande en C18 causa el reinicio del dispositivo

7

Estoy utilizando PIC18F13K22 y Microchip's compilador C18 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 solicitada de la sección:
              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
    
pregunta PetPaulsen

2 respuestas

0

Debido a la 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' ahora es colocar explícitamente el código en la dirección 0x08, que salta al ISR. (Inspirado en la guía del usuario de C18 página 29):

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()
{
  /* ... */
}
    
respondido por el PetPaulsen
8

No hay ninguna razón intrínseca por la que esta matriz cause un reinicio. Aparentemente estás 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.

Más probable, hay un error en otra parte. Esta matriz es probablemente la cosa más grande que tiene que colocar el vinculador, por lo que es probable que todo el código que no se encuentra en direcciones fijas específicas se mueva a medida que se cambie el tamaño de la matriz, lo que puede hacer que algunos errores aparezcan y desaparezcan.

Podría ser útil mostrar la parte "Información de la sección" del archivo MAP del vinculador para que podamos ver qué terminó donde. Además, intente pasar por esto con el simulador y vea si termina ejecutando ubicaciones no intencionadas o algo así.

Añadido:

Desde la palabra clave "rom", obviamente querías 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í, todo tipo de cosas extrañas podrían suceder. Una vez más, el archivo del mapa del vinculador lo aclararía.

Agregado 2:

Ahora que tenemos un archivo de mapa de vinculador, podemos ver el problema. 1024 palabras de 16 bits cada una son 2048 bytes, que es de 800 h. Solo hay una sección en cualquier lugar cerca de ese tamaño, y es exactamente de 800 h de bytes, por lo que el compilador entendió colocarlo 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 simple 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 donde se colocó esta matriz.

El hecho de que el enlazador colocara la matriz donde lo hizo significa que nada más reclamaba la dirección fija de ninguno 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 se llamó el módulo de rutina de interrupción, pero ¿aparece en el mapa de enlaces? Si es así, entonces se olvidó de murmurar el conjuro correcto para que el compilador sepa que es una rutina de interrupción y, por lo tanto, lo obligue a una dirección particular. Si no es así, entonces no está siendo incluido en el enlace de alguna manera. Esto puede suceder si pones todos los archivos de objetos en una biblioteca para que el enlazador pueda elegir lo que quiere y no faltan elementos externos en el 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 vinculador.

    
respondido por el Olin Lathrop

Lea otras preguntas en las etiquetas