7
\$\begingroup\$

I am using the PIC18F13K22 and Microchip's C18 compiler in MPLABX. The PIC kept resetting, when it was about to jump into the interrupt service routine (ISR). I was able to trace the problem down to the declaration of an array:

UINT16 rom periods[] = {64000,59412,55438,51962, ...} // 1024 Values

If I shrink the size of the array down to a few items, the PIC is running without resetting continuously.

Now I am wondering why the large array causes a reset. And even more interesting for me: can I declare somehow a dataset containing these 1024 values?


The requested Section Info:

              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
\$\endgroup\$
8
\$\begingroup\$

There is no inherent reason this array should cause a reset. You are apparently declaring 2 kBytes of constants in program memory. That PIC has 8 kBytes of program memory, so that should be OK.

More likely, there is a bug elsewhere. This array is probably the largest thing the linker has to place, so all the code not at specific fixed addresses will likely move around as the array size is changed, which can make some bugs appear and disappear.

It might be useful to show the "Section Info" part of the linker MAP file so we can see what ended up where. Also, try stepping thru this with the simulator and see if you end up executing unintended locations or something.

Added:

From the "rom" keyword, you obviously intended this array to be in program memory. Make really sure the C compiler understood this correctly. I use C18 infrequently and don't remember what the correct incantations are to define constants in program memory. If the compiler didn't put it there, all manner of strange things could happen. Again, the linker map file would clear this up.

Added 2:

Now that we have a linker map file, we can see the problem. 1024 words of 16 bits each is 2048 bytes, which is 800h. There is only one section anywhere near that size, and it is exactly 800h bytes, so the compiler did understand to put it in program memory. However, note that it is placed at address 8. That is the single or high priority interrupt vector address. This array also overlaps the low priority interrupt address at 16, so either way interrupts can't be used with where this array got placed.

The fact that the linker placed the array where it did means that nothing else was claiming the fixed address of either interrupt vector. I don't use C for interrupt routines, but this tells me that the C compiler doesn't understand that your interrupt routine actually is a interrupt routine, or it wasn't included in the link.

I don't know what you called the interrupt routine module, but is it listed at all in the link map? If so, then you forgot to mutter the correct incantation so that the compiler knows its a interrupt routine and thereby force it to a particular address. If not, then it isn't being inluded in the link somehow. This can happen if you put all the object files in a library so the linker can pick what it wants and there are no missing externals to the interrupt module. That can happen with a interrupt module since it is never called explicitly. In that case the interrupt module object file must be given to the linker explicitly.

\$\endgroup\$
  • \$\begingroup\$ I added the section info. '.romdata_Main.o' 2024 bytes are placed at address 0x0008. Isn't that the interrupt vector address? That would explain why it is resetting when an interrupt is risen... \$\endgroup\$ – PetPaulsen Jun 1 '12 at 14:23
  • \$\begingroup\$ Thank you so much! Now I am at least able to work around this problem. \$\endgroup\$ – PetPaulsen Jun 1 '12 at 15:01
0
\$\begingroup\$

Because of Olin's answer I was able to eliminate the problem.

As Olin has written, the linker places the array at address 0x08. This is the interrupt vector address.

A 'workaround' is now to explicitly place code at address 0x08, that jumps to the ISR. (Inspired by the C18 user's guide page 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)
{
  /* ... */
}

or even simpler:

#pragma code high_vector=0x08
#pragma interrupt isr
void isr()
{
  /* ... */
}
\$\endgroup\$
  • 1
    \$\begingroup\$ It's the linker that places the array at 8, not the compiler. However, like I said, I don't use a compiler for interrupt code, but I am surprised the compiler doesn't put the routine or at least a stub at the fixed interrupt vector for you. But, if you can place the asm stub at 8, why can't you place the interrupt routine itself at 8 instead using the same mechanism? That way you shouldn't need a stub at all. \$\endgroup\$ – Olin Lathrop Jun 1 '12 at 15:02
  • \$\begingroup\$ @Olin Lathrop - You are right ... I can place the isr at 0x08. No need for a stub. But still wierd, that I have to say the linker that I dont want the interrupt vector to be overriden by some data. \$\endgroup\$ – PetPaulsen Jun 1 '12 at 15:10
  • \$\begingroup\$ You're not really telling the linker that you don't want the interrupt vector overriden, but rather in this one case that you want this code at a particular address. If you don't say that, the linker is free to put things wherever, which in this case happened to result with your array at 8. There could just as well have been something else there. This problem had nothing to do with your array, but that you didn't nail down where the interrupt routine needed to go. \$\endgroup\$ – Olin Lathrop Jun 1 '12 at 16:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.