Can't Solve relocation truncated to fit: R_AVR_7_PCREL against `no symbol'

I am coding on at Mega2560 using Arduino 1.8.12 IDE. I am continuously fighting the appearance of this error message: relocation truncated to fit: R_AVR_7_PCREL against `no symbol' Collect2.exe: error: ld returned 1 exist status.

I have looked at dozens of individuals with this issue but no Arduino specific IDE resolutions. This issue is fatal to my development activities. I understand it is related to relative jumps and calls but I do not know what to do to fix code areas to overcome the linker bug.

Any help would be greatly appreciated.

Without posting your code (using code tags!) only you know what your code is doing. Help everyone out by reading the sticky post at the top of the forum about how to properly post a question, including code, and people will help you.

Thank you for guiding me - my apologies.

So this is the complete diagnostic error I receive:

_C:\Users\Steve\AppData\Local\Temp\ccUM1tzL.ltrans0.ltrans.o: In function main':**_ <em>**<artificial>:(.text.startup+0x1e1c): relocation truncated to fit: R_AVR_7_PCREL against no symbol'
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino Mega or Mega 2560.

I have attached my code.

The purpose of the code and electronics is to monitor PH/Temperature from industrial serial sensors and alert the user when a programmed limit is exceeded. My system uses an Arduino Mega with a custom adapter shield board connected <Ezo_uart.h>. This board reads the PH and temperature from two sensors. Also, there is an I2C 4x20 LCD <LiquidCrystal_I2C.h>, a 4x4 matrix keypad <Keypad4x4.H>, 4ea 8 digit 7-segment (with decimal points) serial display modules<LedControl.h>. Finally, there is a R/Y/G with audible alarm signal tower the board drives to alert when PH is out of range.

One critical feature of the code is access to a serial port multiplexer daughter board which is mounted on the shield board. This board uses digital port pins to mux the RX/TX pins to serial port 1. Connected to this board are PH sensors which require nearly 1 second to poll. At present the code to read these sensors blocks waiting for the reply. In lieu of rewriting the driver that came with the mux board, I opted to use MsTimer2 to update the channel number in sequence and read the data. This was to restore responsiveness to the Loop the remaining code suffered from the blocking action of the sensor driver. My initial problem with the error message (R_AVR_7_PCREL) ocurred shortly after I added the MsTimer2 functionality. When I removed the timer to continue development the error disappeared. It was reappeared at various times as I add code.

My code is a bit scattered and there is a lot of trial and error code to be culled out. This is the primary reason I did not post code; however, I understand the need and have attached the ZIP of the current code state.

Thank you in advance for any assistance you can render. I plan to start a new sketch in lieu of an affirmative resolution so I can finish the program's functionality.

sketch_feb23a 20200317B.zip (22.2 KB)

I have paired down the code and isolated a single line that causes the issue.

At the end of SETUP() is the following code:

  phDisp.setMenu(1);
  phDisp.setParams(2,MAJOR_VER, MINOR_VER);
  phDisp.updateLCD();

  phDisp.setBarValue(0, 3.1419);
//  phDisp.updateLED();

if the last line is un-commented, the error appears.

The modified code that exhibits this behavior is attached.

sketch_feb23a 20200317C.zip (26.9 KB)

When I try to compile that code, I get tons of warnings, notes, etc.

You also can not compare strings like this

if(Modules[theChan].get_name() == "RT2") sysData.ch2TempValue = theReading;

You have to use strcmp()

Thank you Edison.

I have gone through a considerable rewrite to eliminate code I suspect as the cause of this error. To my delight all was going well until today. I added a module called sensorDriver and the error has returned! If I comment out the call to sensorDriver(scCODE) in loop() the error goes away.

I have a lot of time and schedule invested in this project. Is this issue resolvable and is there a defined circumstance that I can identify and avoid that causes the problem?

PLEASE HELP! I am tempted to scrap the Arduino IDE and convert to direct Atmel Studio. If there is no good solution to eliminate this error I would greatly appreciate any advice on taking this project out of the Ardiono IDE environment.

Thank you in advance.

I have attached my new code.

void loop() 
{
  // Read all Sensor Data
//  Serial.println("EZO Driver");
//  ezoDriver();
//  delay(1000);
	
	sysProc();
	sensorDriver(scREAD);

sketch_feb23a 20200323A.zip (33.3 KB)

I have isolated the cause of the issue to a section of code that previously did not cause any issues but now if left in the code causes the error.

The checkLimits method of the Sensor class has Callback function pointers that are executed if initialized and if conditions warrant. This code has worked flawlessly up till today. Now, I have to comment out all of them to get the code to compile error free.

void Sensor::checkLimits(void)
{
  /*
  Serial.print("Sensor: Check Limits: Value = ");
  Serial.print(_value);
  Serial.print(" Sensor is ");
  Serial.println(this->_name);
  */
  if(_loLimEn)
  {
    _loFault = 0;
    if(_value < _loLim) _loFault |= WARNMASK;
    else if(_value < _loloLim) _loFault |= CRITMASK;
  } else {
    _loFault = 0;
  }

  if(_hiLimEn)
  {
    _hiFault = 0;
    if(_value > _hiLim) _hiFault |= WARNMASK;
    else if(_value > _hihiLim) _hiFault |= CRITMASK;
  } else {
    _hiFault = 0;
  }
/*
  if((loLimCB != 0) && (_loFault & WARNMASK)) loLimCB(_name);
  if((loloLimCB != 0) && (_loFault & CRITMASK)) loloLimCB(_name);
  if((hiLimCB != 0) && (_hiFault & WARNMASK)) hiLimCB(_name);
  if((hihiLimCB != 0) && (_hiFault & CRITMASK)) hihiLimCB(_name);

  if((noFaultCB != 0) && (_loFault == 0) && (_hiFault == 0)) noFaultCB(_name);
*/

//  Serial.println(_loFault);
//  Serial.println(_hiFault);
}


[/code/

If you are using the Mega 2560, you should not be using the String class. It is everywhere in your code. That class uses dynamic memory allocation which will fragment your memory and eventually lead to problems. Did you write the Senor class? It should be using regular c-strings, not the String class.

I had no idea the String class fragmented memory. That is unfortunate. Yes, I wrote the Sensor Class. I will take on the task of removing all String operations.

Thank you so much!!

Problem solved! Thank you blh64. I have removed all use of the String class in my Atmega 2560 project. I no longer get the R_AVR_7_PCREL message.

It's BACK!!

This error: R_AVR_7_PCREL keeps popping up its ugly head from time to time in my code. I will make some changes, the error appears; I figure out another way to accomplish the same logic and it goes away.

Is there not a diagnostic capability that points to the root cause of such an error.

Many times it is when I add a Serial.print statement. But just now I added the a block of general code with strcpy, strcat, sprintf, etc. to form c-strings.

I added the following case statement to an existing module: updateLCD()

These variables are declared:

	char pLine[50];
	char tLine[20], t2Line[20], t3Line[20], t4Line[20];
	_alarmRec * ptr;
			    case 53:
				//                                     12345678901234567890
// {	420	,	0	,	53	,	56	},  //	"%s %s %s" P1S+ HNN.NNN LNN.NNN
// {	420	,	1	,	53	,	56	},  //	"%s %s %s" T1S+ HNN.NNN LNN.NNN
// {	420	,	2	,	53	,	56	},  //	"%s %s %s" P2S+ HNN.NNN LNN.NNN
// {	420	,	3	,	53	,	56	},  //	"%s %s %s" T2S+ HNN.NNN LNN.NNN
					ptr = &(sensors[menus[i].lineNum].alarm);
					if(menus[i].lineNum == P1) sprintf(tLine,"P1");
					if(menus[i].lineNum == T1) sprintf(tLine,"T1");
					if(menus[i].lineNum == P2) sprintf(tLine,"P2");
					if(menus[i].lineNum == T2) sprintf(tLine,"T2");
					if(thePars[1] == 0) {	// SIREN
						if(ptr->enab) {
							strcat(tLine,"S+");
							if(ptr->hiSiren.enab) strcpy(t2Line,"H"); else strcpy(t2Line,"h");
							dtostrf(ptr->hiSiren.lim,6,3,t4Line);
							strcat(t2Line,t4Line);
							if(ptr->loSiren.enab) strcpy(t3Line,"L"); else strcpy(t3Line,"l");
							dtostrf(ptr->loSiren.lim,6,3,t4Line);
							strcat(t3Line,t4Line);
						} else {
							strcat(tLine,"S-");
							sprintf(t2Line," DISABLED");
							sprintf(t3Line," ");
						}
					}
					if(thePars[1] == 1) {	// RED
						if(ptr->enab) {
							strcat(tLine,"S+");
							if(ptr->hiRed.enab) strcpy(t2Line,"H"); else strcpy(t2Line,"h");
							dtostrf(ptr->hiRed.lim,6,3,t4Line);
							strcat(t2Line,t4Line);
							if(ptr->loRed.enab) strcpy(t3Line,"L"); else strcpy(t3Line,"l");
							dtostrf(ptr->loRed.lim,6,3,t4Line);
							strcat(t3Line,t4Line);
						} else {
							strcat(tLine,"S-");
							sprintf(t2Line," DISABLED");
							sprintf(t3Line," ");
						}
					}
					if(thePars[10] == 2) {	// YELLOW
						if(ptr->enab) {
							strcat(tLine,"S+");
							if(ptr->hiYellow.enab) strcpy(t2Line,"H"); else strcpy(t2Line,"h");
							dtostrf(ptr->hiYellow.lim,6,3,t4Line);
							strcat(t2Line,t4Line);
							if(ptr->loYellow.enab) strcpy(t3Line,"L"); else strcpy(t3Line,"l");
							dtostrf(ptr->loYellow.lim,6,3,t4Line);
							strcat(t3Line,t4Line);
						} else {
							strcat(tLine,"S-");
							sprintf(t2Line," DISABLED");
							sprintf(t3Line," ");
						}
					}
					if(thePars[1] == 3) {	// GREEN
						if(ptr->enab) {
							strcat(tLine,"S+");
							if(ptr->hiGreen.enab) strcpy(t2Line,"H"); else strcpy(t2Line,"h");
							dtostrf(ptr->hiGreen.lim,6,3,t4Line);
							strcat(t2Line,t4Line);
							if(ptr->loGreen.enab) strcpy(t3Line,"L"); else strcpy(t3Line,"l");
							dtostrf(ptr->loGreen.lim,6,3,t4Line);
							strcat(t3Line,t4Line);
						} else {
							strcat(tLine,"S-");
							sprintf(t2Line," DISABLED");
							sprintf(t3Line," ");
						}
					}
					snprintf(pLine, 21, lines[getMenuLine(menus[i].lineRec)].data, tLine,t2Line,t3Line);
					break;

Any help in being able to find the root cause of this particular problem as well as an education on how I can research and locate the root cause myself would be GREATLY appreciated!!

Thank you

PH Meter 20200430A.zip (236 KB)

I found the following article regarding a bug with libavr and gcc (AVR relocation truncations workaround - Wikistix). libm uses RJMP and RCALL instructions which under certain circumstances results in linker errors and thus the R_AVR_7_PCREL error.

I claims that I need to control the link order passing libm before libgcc.

So, in the Arduino IDE toolchain I need to change the avr-g++ command to the follwing:

/usr/pkg/bin/avr-g++ -mmcu=atmega2560 -I. -DF_CPU=16000000 -DARDUINO=105 -I/home/stix/src/arduino-1.0.5/hardware/arduino/cores/arduino -I/home/stix/src/arduino-1.0.5/libraries/LiquidCrystal -I/home/stix/src/arduino-1.0.5/libraries/Wire -I/home/stix/src/arduino-1.0.5/libraries/utility/twi  -I../libraries/DS1307RTC -I../libraries/OneWire -I../libraries/Time -I/home/stix/src/arduino-1.0.5/libraries/LiquidCrystal/utility/ -I/home/stix/src/arduino-1.0.5/libraries/Wire/utility/ -I/home/stix/src/arduino-1.0.5/libraries/utility/twi/utility/ -I../libraries/DS1307RTC/utility/ -I../libraries/OneWire/utility/ -I../libraries/Time/utility/ -I/home/stix/src/arduino-1.0.5/hardware/arduino/variants/mega -Os -mno-short-calls -o applet/thermo.elf applet/thermo.cpp -L. applet/core.a -nodefaultlibs -Wl,--gc-sections -lm -lgcc -lc -lgcc

Can someone point my nose in the right direction?

Thank you.

I have never done it, but this article talks a lot about how you can customize the command line.