Go Down

Topic: Compliling error when it all seems ok (Read 2908 times) previous topic - next topic

RonaldPoFo

Wow, had to read that a few times to get around it XD Thanks for the explanation Tom Carpenter, just a couple things I don't get:

Quote
the vector table at the beginning to the hardware serial interrupt vector code
What are those??
Quote
By removing either of the Serial.print() calls, the length of the loop() function is reduced in size by just enough that the compiler can make the jump.
So a program could not compile because it's too long even though there is more than enough memory?
Quote
adding more code made the PCREL error go away as well
Without deleting the Serial.print()s?

Tom Carpenter

#16
Jan 02, 2013, 09:19 pm Last Edit: Jan 02, 2013, 09:30 pm by Tom Carpenter Reason: 1

Quote
adding more code made the PCREL error go away as well
Without deleting the Serial.print()s?

Yeah, weird huh.



A vector table in this context is a series of lines of code stored at specific memory addresses at the beginning of the program that instruct the AVR what part code to execute in the event of an interrupt occuring.
This is the one from your code (you don't have to read through it, I'm just posting it as an example):
Code: [Select]
00000000 <__vectors>:
      0: 04 c1       rjmp .+520     ; 0x20a <__dtors_end>
      2: 00 00       nop

      4: 2f c1       rjmp .+606     ; 0x264 <__bad_interrupt>
      6: 00 00       nop

      8: 2d c1       rjmp .+602     ; 0x264 <__bad_interrupt>
      a: 00 00       nop

      c: 2b c1       rjmp .+598     ; 0x264 <__bad_interrupt>
      e: 00 00       nop

     10: 29 c1       rjmp .+594     ; 0x264 <__bad_interrupt>
     12: 00 00       nop

     14: 27 c1       rjmp .+590     ; 0x264 <__bad_interrupt>
     16: 00 00       nop

     18: 25 c1       rjmp .+586     ; 0x264 <__bad_interrupt>
     1a: 00 00       nop

     1c: 23 c1       rjmp .+582     ; 0x264 <__bad_interrupt>
     1e: 00 00       nop

     20: 21 c1       rjmp .+578     ; 0x264 <__bad_interrupt>
     22: 00 00       nop

     24: 1f c1       rjmp .+574     ; 0x264 <__bad_interrupt>
     26: 00 00       nop

     28: 1d c1       rjmp .+570     ; 0x264 <__bad_interrupt>
     2a: 00 00       nop

     2c: 1b c1       rjmp .+566     ; 0x264 <__bad_interrupt>
     2e: 00 00       nop

     30: 19 c1       rjmp .+562     ; 0x264 <__bad_interrupt>
     32: 00 00       nop

     34: 17 c1       rjmp .+558     ; 0x264 <__bad_interrupt>
     36: 00 00       nop

     38: 15 c1       rjmp .+554     ; 0x264 <__bad_interrupt>
     3a: 00 00       nop

     3c: 13 c1       rjmp .+550     ; 0x264 <__bad_interrupt>
     3e: 00 00       nop

     40: 11 c1       rjmp .+546     ; 0x264 <__bad_interrupt>
     42: 00 00       nop

     44: 0f c1       rjmp .+542     ; 0x264 <__bad_interrupt>
     46: 00 00       nop

     48: 0d c1       rjmp .+538     ; 0x264 <__bad_interrupt>
     4a: 00 00       nop

     4c: 0b c1       rjmp .+534     ; 0x264 <__bad_interrupt>
     4e: 00 00       nop

     50: 09 c1       rjmp .+530     ; 0x264 <__bad_interrupt>
     52: 00 00       nop

     54: 07 c1       rjmp .+526     ; 0x264 <__bad_interrupt>
     56: 00 00       nop

     58: 05 c1       rjmp .+522     ; 0x264 <__bad_interrupt>
     5a: 00 00       nop

     5c: 0c 94 f2 0d jmp 0x1be4 ; 0x1be4 <__vector_23>

     60: 01 c1       rjmp .+514     ; 0x264 <__bad_interrupt>
     62: 00 00       nop

     64: 1f c7       rjmp .+3646   ; 0xea4 <__vector_25>
     66: 00 00       nop

     68: 0c 94 96 08 jmp 0x112c ; 0x112c <__vector_26>

     6c: fb c0       rjmp .+502     ; 0x264 <__bad_interrupt>
     6e: 00 00       nop

     70: f9 c0       rjmp .+498     ; 0x264 <__bad_interrupt>
     72: 00 00       nop

     74: f7 c0       rjmp .+494     ; 0x264 <__bad_interrupt>
     76: 00 00       nop

     78: f5 c0       rjmp .+490     ; 0x264 <__bad_interrupt>
     7a: 00 00       nop

     7c: f3 c0       rjmp .+486     ; 0x264 <__bad_interrupt>
     7e: 00 00       nop

     80: f1 c0       rjmp .+482     ; 0x264 <__bad_interrupt>
     82: 00 00       nop

     84: ef c0       rjmp .+478     ; 0x264 <__bad_interrupt>
     86: 00 00       nop

     88: ed c0       rjmp .+474     ; 0x264 <__bad_interrupt>
     8a: 00 00       nop

     8c: eb c0       rjmp .+470     ; 0x264 <__bad_interrupt>
     8e: 00 00       nop

     90: 49 c7       rjmp .+3730   ; 0xf24 <__vector_36>
     92: 00 00       nop

     94: 0c 94 d5 08 jmp 0x11aa ; 0x11aa <__vector_37>

     98: e5 c0       rjmp .+458     ; 0x264 <__bad_interrupt>
     9a: 00 00       nop

     9c: e3 c0       rjmp .+454     ; 0x264 <__bad_interrupt>
     9e: 00 00       nop

     a0: e1 c0       rjmp .+450     ; 0x264 <__bad_interrupt>
     a2: 00 00       nop

     a4: df c0       rjmp .+446     ; 0x264 <__bad_interrupt>
     a6: 00 00       nop

     a8: dd c0       rjmp .+442     ; 0x264 <__bad_interrupt>
     aa: 00 00       nop

     ac: db c0       rjmp .+438     ; 0x264 <__bad_interrupt>
     ae: 00 00       nop

     b0: d9 c0       rjmp .+434     ; 0x264 <__bad_interrupt>
     b2: 00 00       nop

     b4: d7 c0       rjmp .+430     ; 0x264 <__bad_interrupt>
     b6: 00 00       nop

     b8: d5 c0       rjmp .+426     ; 0x264 <__bad_interrupt>
     ba: 00 00       nop

     bc: d3 c0       rjmp .+422     ; 0x264 <__bad_interrupt>
     be: 00 00       nop

     c0: d1 c0       rjmp .+418     ; 0x264 <__bad_interrupt>
     c2: 00 00       nop

     c4: cf c0       rjmp .+414     ; 0x264 <__bad_interrupt>
     c6: 00 00       nop

     c8: cd c0       rjmp .+410     ; 0x264 <__bad_interrupt>
     ca: 00 00       nop

     cc: 6b c7       rjmp .+3798   ; 0xfa4 <__vector_51>
     ce: 00 00       nop

     d0: 0c 94 14 09 jmp 0x1228 ; 0x1228 <__vector_52>

     d4: c7 c0       rjmp .+398     ; 0x264 <__bad_interrupt>
     d6: 00 00       nop

     d8: a5 c7       rjmp .+3914   ; 0x1024 <__vector_54>
     da: 00 00       nop

     dc: 0c 94 53 09 jmp 0x12a6 ; 0x12a6 <__vector_55>

     e0: c1 c0       rjmp .+386     ; 0x264 <__bad_interrupt>
     e2: 00 00       nop


... Other code in here ...


00000264 <__bad_interrupt>:
    264: cd ce       rjmp .-614     ; 0x0 <__vectors>


There is one line for each of the ATMega2560's 56 interrupt sources. Each one is made up of exactly 4 bytes (2 words), which are usually either a single JMP instruction (4bytes long) or an RJMP (2 bytes, with a NOP to make it up to 4). Those which are labelled __bad_interrupt are ones which your code hasn't implemented, which means that if for some reason the processor arrives there an error must have occurred. To handle the error it jumps to a function called __bad_interrupt, which in the case of your program does the standard thing which is to the restart the program from the beginning.

Here is the one the error mentioned, __vector_26
Code: [Select]
     68: 0c 94 96 08 jmp 0x112c ; 0x112c <__vector_26>
Notice how it neets to jump from the current line (0x0068 written on the left) to the location where the interrupt code is stored (0x112c). A JMP statement specifies an exact program memory location to move to, but it can only reference up to a 16bit address. What happens if the code is at address 0x10000? or higher? It can't get there. An Atmega has 256k of flash, but the instruction can only address 64k, so the compiler has to be careful where it places code.

You may think it is daft not being able to address all the flash, but there is actually an instruction which can. The atmega2560 has an instruction called EIJMP which is capable of addressing all of the program memory, in fact it can address up to 4MB of flash. However, it is not possible to use that instruction in the vector table as it takes 10 bytes of program memory to use it, but there is only space for 4bytes in the vector table.
Just for fun, this is how it would have to use EIJMP to get to address 0x10000. Each instructions used is 2 bytes long, and there are 5 in total which makes 10bytes.
Code: [Select]
ldi r16,0x01 ; Set up EIND and Z-pointer
out EIND,r16
ldi r30,0x00
ldi r31,0x00
eijmp ; Jump to 0x010000


Something about your code must have made the compiler for whatever reason put the interrupt code at an address >0xFFFF
~Tom~

RonaldPoFo

Thanks a lot for your time and super explanation, I really appreciate it!!
Quote
Something about your code must have made the compiler for whatever reason put the interrupt code at an address >0xFFFF
So probably my not defined returns, right. I mean, could a perfectly debugged code not compile because casually the length between two vectors is two big?

dc42

A good explanation, which also explains why the code compiled OK for me with a Uno as target - the Uno has only 32K of flash, so a JMP instruction can reach the entire address space.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Go Up