Strange error message

Can someone please explain to me what this error message means so I'll have a clue as to what is going on.

The error is:

c:/program files (x86)/arduino-1.5.6-r2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o: In function __vector_default': (.vectors+0x3c): relocation truncated to fit: R_AVR_13_PCREL against symbol__vector_15' defined in .text section in c:/program files (x86)/arduino-1.5.6-r2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o

I don't have any idea what it means, so any hints would help. Mostly, I would really like to understand what the message means. For instance, what is this (.vectors+0x3c): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_15' defined in .text section all about? Relocation... Huh?

Has anyone ever seen this before? Anyone on the arduino team perhaps? Someone has to know what it means. Right? :roll_eyes:

Does anyone know at what stage this error occured ? Does anyone know what the program was ? Does anyone know what board was being used ? Someone must know. Right ? (hint)

Sorry for not replying sooner. The point is moot. I found out what was causing the error, and to answer your questions; The error occured at compile time, I beleive at the linker stage (not positve about that). I'm using a Mega2560 r2 and the latest IDE 1.5.6 r2. The program is a pool controller that uses the following libraries: DallasTemperature, OneWire, I2C, glcd and a modified (by me) version of DS1307. The sketch is large and will not fit here in the forum. I was going to put all the relative files in a zip to post however, I discovered the cause of the error. It is related to the glcd library and one of it's included fonts (Arial_bold_14.h). Once I changed the font everything's ok. If someone is really curious and likes to figure out problems, I'll take the time to zip all the files and post. There is still one thing I would like to know for future reference. What the error message means. I use interrupts in my sketch, but they have nothing to do with the glcd library or its fonts. Does it have something to do with the fonts being located in progmem? If so, why does it work after only changing the font used?

What I was asking in my OP wasn't "why isn't my code working?". It was "What does this error message mean?". For instance, you don't need to see any code to know what this error means,

error: new declaration 'uint8_t foo(uint8_t)' error: ambiguates old declaration 'void foo(uint8_t)'

Anyway the point is moot now, it's working. It's just curiosity that interests me.

Thanks for the reply. DJ

Is your code over or close to 64K, I’ll assume it is.

(.vectors+0x3c): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_15’ defined in .text section

Your PROGMEM data ( or simply a large sketch ), like whats defined in Arial_Bold_14.h is pushing some ISR vectors into far memory.

AVR pointers are 16 bits, far memory requires 18 bits to address fully. You can only read half the Mega using conventional pointers.

Your vector is placed in far memory, thus given a 32 bit pointer, however vectors only support 16 bit pointer addresses causing the truncation. The result is, the ISR cannot be reached.

I recently helped someone out with a similar problem, a way to locate the PROGMEM data in far memory instead of the vector can be found here: http://forum.arduino.cc/index.php?topic=232724.msg1680144#msg1680144

Thank you pYro!

I thought it had something to do with progmem. When I first saw the error message the "relocation" part caught my attention. I thought, why would anything need to be relocated and what would cause such an event? The only large things in my code are the fonts and some text arrays (also in progmem). That's where I started to debug. I needed the text arrays so I started with the fonts and Arial_bold_14 was the largest, so I started there and viola... fixed.

The sketch without that particular font is ~28K. It wouldn't compile with the font so I didn't get a size, but the font is 8712 bytes so, just over 36.5K with it. That still seems like it shouldn't be a problem. I'm also using ~2100 bytes SRAM (only 26%). That shouldn't have any bearing on flash memory should it?

At least I was on the right path. I'll try putting the fonts and text in far memory and see if it works. Thanks again for confirming my conclusion. This isn't the first (and won't be the last) time you've helped me with your insight. :)

DJ

With a smaller sketch it can still occur.

I did a quick search and someone has posted a nice answer:

http://stackoverflow.com/a/15782933: The AVR devices support two kinds of jump/call instructions: JMP vs. RJMP, and CALL vs. RCALL. The R variants make calls relative to the current location and are more efficient both in usage of program memory and execution time. This comes at a cost though: RJMP and RCALL can only be used for addresses in the range of +/-4kb from their location in program memory. This is never a problem on devices with no more than 8kb of program memory because the whole 8kb range can be addressed from any location via RCALL or RJMP.

On devices with more than 8kb of program memory, however, this is not true for all possible locations. Therefore, if the linker decides it can put the code to be called within the +/-4kb range from the RJMP/RCALL there will be no problem, but if the linker fails to (re-)locate the code to be within that range, RJMP/RCALL cannot be used to reach the code's new address, the address is thus truncated (just like when doing uint16_t value = 12345; uint8_t truncatedValue = value; in C) and the generated code breaks.

The ISR is called from the vector table using the relative versions.

So, is placing the progmem stuff in far memory going to be the solution here? Is this really being caused by progmem forcing the relacation, or are my ISR's the problem? I'm using attachInterrupt() instead of directly setting the registers. I haven't looked into what attachInterrupt() does under the hood. I've had sketches >70K running no problem. Why the relocation of vectors in particular? Aren't where the vectors are placed in memory set according to fuses, or did I misunderstand the data sheet? I'd hate to change all the progmem code, then later find out that wasn't the root cause.

Thanks again for your replies, DJ

Putting the data in far progmem could solve it. The data at the moment is probably sitting between the interrupt vector table and the actual ISR. As the data size is greater than 4Kb, the RJMP, and RCALL instructions fail.

When the data is moved into far memory, the linker could take the opportunity and move the ISR closer, within range.

There are many memory sections available for use, you could possibly declare your ISR to be inside a closer section. If all else fails, you can use AVR studio /manually edit command lines and specify the locations you want your data sections, even create new ones. A section could be created at the end of near memory for your data, avoiding the far memory overhead, and remaining compatible with current near progmem helper functions.

Would it make a difference if I didn't use attachInterrupt() and instead set the registers myself and used ISR() for my interrupts? Or is that the same thing attachIterrupt() does? The reason I ask is because changing the interrupt code would be easier than changing the progmem code (fewer lines of code to edit).

DJ

Would it make a difference if I didn't use attachInterrupt() and instead set the registers myself

I do not think so, the linker decides where everything goes, which happens after the code is compiled. This is only a guess, give it a try.

Specifying where my isr's are to be placed looks like the simplest solution however, for some reason my atmel studio got screwed up (I don't know how) and it can't find the arduino files at compile time so I can't compile arduino sketches now. :0 I've completely uninstalled atmel studio, visual micro for atmel and ardiuno IDE, deleted the folders for all three, re-downloaded and installed all three and still have the same problem. I noticed in the output window the errors it refers to are looking in the sam folders not the avr ones. I have the correct board, port and IDE set. In fact I checked all the settings and nothing is set for the sam. The weird thing is, I can write and compile arduino libraries just fine. :~ I'm probably getting quite off topic here so I'll stop now.

DJ

Delete the temp compile folder, If I compile for Due then switch to an AVR, the SAM files can sometimes cause errors.

Is this the interrupt: Timer/Counter2 Compare Match B

Can you post the interrupt function.

No timer interrupts. External and pin change interrupt only. Thanks for the tip on atmel studio. I will definately try that. I like atmel studio MUCH more than the arduino IDE.

There’s 4 external interrupts (INT0, INT1, INT4, INT5 used for trackball directions) and 1 pin change interrupt PCINT0 with two pins being used (1 for a button under the trackball and 1 for an RTC irq). Trackball.xxxxx is a struct to hold relavant info. UP, DOWN etc. are const uint8_t’s assigned to bit values.

void isrUp(void)
{
    static uint8_t upDir = 0;
    upDir++;
    if (4 < upDir)
    {
        upDir = 0;
        Trackball.directFlags = UP;
        Trackball.dataAvailable = true;
    }
}

void isrDown(void)
{
    static uint8_t downDir = 0;
    downDir++;
    if (4 < downDir)
    {
        downDir = 0;
        Trackball.directFlags = DOWN;
        Trackball.dataAvailable = true;
    }
}

void isrLeft(void)
{
    static uint8_t leftDir = 0;
    leftDir++;
    if (4 < leftDir)
    {
        leftDir = 0;
        Trackball.directFlags = LEFT;
        Trackball.dataAvailable = true;
    }
}

void isrRight(void)
{
    static uint8_t rightDir = 0;
    rightDir++;
    if (4 < rightDir)
    {
        rightDir = 0;
        Trackball.directFlags = RIGHT;
        Trackball.dataAvailable = true;
    }
}

ISR(PCINT0_vect)
{
    static uint8_t prevState = 0x03;
    uint8_t currentState = (0x03 & PINB);
    if ((0x02 == (0x02 & prevState)) && ((0x02 & prevState) != (0x02 & currentState)))
    {
        NONATOMIC_BLOCK(NONATOMIC_RESTORESTATE)
        {
            DS1307.update();
        }
    }
    if ((0x01 == (0x01 & prevState)) && ((0x01 & prevState) != (0x01 & currentState)))
    {
        Trackball.directFlags |= (BUTTON | BTN_DOWN);
        Trackball.buttonPress = true;
        Trackball.dataAvailable = true;
    }
    if ((0x00 == (0x01 & prevState)) && ((0x01 & prevState) != (0x01 & currentState)))
    {
        Trackball.directFlags |= BTN_UP;
        if (BTN_DOWN == (BTN_DOWN & Trackball.directFlags))
        {
            Trackball.buttonPress = true;
        }
        Trackball.dataAvailable = true;
    }
    prevState = (0x03 & currentState);
}

For instance, what is this (.vectors+0x3c): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_15' defined in .text section all about? Relocation... Huh?

The compiler generates .o files from the source files. The .o files use relative addresses. The linker combines the .o files, and converts the relative addresses to absolute addresses. This involves relocating data, from where a .o file thinks it is (the relative address) to where it really is, at run time (the absolute address).

The linker for the Arduino can only relocate blocks of data that are smaller than some (relatively large) size. When there is some issue with the data, that makes the linker think it is larger than it really is, the linker can not relocate that much data, so, it relocates when it can, and ignores (truncates) the rest of the data.

@PaulS

Thank you for the what and why of this error message. This answered my questions from the OP of this thread. I know I should have posted code with my questions and I was going to shortly after I posted. But when I anylized the error message some more it led me to check the progmem area and what was in it. That led me to the cause. I do thank you for the explaination. I always like to know what exactly an error message means and possible causes. Even if some of the possible causes don't apply to my particular case, it's good to be aware for future reference and avoidance.

I'm going to look into pYro_65's suggestion of assigning the data ISR's to an area of memory. I need to get my atmel studio working with arduino sketches again to accomplish that. Which is what I'm going to do try to figure out next. BTW is it possible to assign data to an area of memory as pYro_65 suggested in the arduino IDE?

Thanks for your time guys. This forum is always helpful. DigitalJohnson

DigitalJohnson: BTW is it possible to assign data to an area of memory as pYro_65 suggested in the arduino IDE?

Yes, http://www.nongnu.org/avr-libc/user-manual/mem_sections.html

Once again, thank you pYro_65. You're so helpful. :D I gave it a cursory read and it looks like that's the ticket. I'll spend some more time going over the details before I give it a try. From what I've read so far I'm guessing the .init3 section is where I need to place my ISR's. Is that correct? I know I need to RTFM. But just so I can browse a little before hand, where can I find the .text and .init sections. I'd like to see if I'm getting in over my head or not. I'm usually up for a good challenge. ;)

DJ

I just had a go myself,
here is a sketch that replicates the Arduino setup, just smaller ( compiled size ).

init is run before setup, just like Arduinos default.

I could have used .init3 for init, however setup must be after .init6 so global libraries can construct. Including wiring.c is just a hack to avoid copying some code.

int main() __attribute__ ((naked));
__attribute__ ((naked)) __attribute__ ((section (".init7"))) void init();
#include "wiring.c"
__attribute__ ((naked)) __attribute__ ((section (".init8")))  void setup();

int main(){

  #if defined(USBCON)
  	USBDevice.attach();
  #endif
 
  while( true ){
    loop();
    if (serialEventRun) serialEventRun();
  }
  return 0;
}

void setup(){

}

void loop(){

}