Sorry about all the 3.2 questions..

jim lee

Well-known member
Randomly getting this error message. (Yes randomly, changing random things in the source causes it to come and go.)

Here's the error
Code:
/Applications/Teensyduino.app/Contents/Java/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /Applications/Teensyduino.app/Contents/Java/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m/nofp/libc.a(libc_a-writer.o): in function `_write_r':
(.text._write_r+0x14): undefined reference to `_write'
collect2: error: ld returned 1 exit status
Error compiling for board Teensy 3.2 / 3.1.

Here's the code

Code:
#include <blinker.h>
#include <serialStr.h>
#include <multiMap.h>
#include <cstdlib>


#define OIL_PIN      20
#define TEMP_PIN     21
#define TACH_IN_PIN  22
#define TACH_OUT_PIN 23

#define TACH_START   500

blinker     tach(TACH_OUT_PIN);
serialStr   serialMgr;
float       RPM;
multiMap    RPMMapper;

void setup() {
  
   Serial.begin(9600);
   serialMgr.setCallback(gotCmd);
   /*
   RPMMapper.addPoint(0,800);
   RPMMapper.addPoint(500,40);
   RPMMapper.addPoint(1000,21.5);
   RPMMapper.addPoint(1500,12.4);
   RPMMapper.addPoint(2000,9.072000);
   RPMMapper.addPoint(3000,6.1);
   RPMMapper.addPoint(4000,4.57);
 
   RPMMapper.addPoint(0,500);
   RPMMapper.addPoint(500,8.5);
   RPMMapper.addPoint(1000,4.0);
   RPMMapper.addPoint(2000,1.73);
   RPMMapper.addPoint(3000,1.18);
   RPMMapper.addPoint(4000,0.899);
   */
   RPMMapper.addPoint(200,55);
   RPMMapper.addPoint(500,22);
   RPMMapper.addPoint(1000,10.5);
   RPMMapper.addPoint(1500,6);
   RPMMapper.addPoint(2000,4.5);
   RPMMapper.addPoint(2500,3.65);
   RPMMapper.addPoint(3000,3.0);
   RPMMapper.addPoint(3500,2.635);
   RPMMapper.addPoint(4000,2.27);
   setTach(0);
   //tach.setOnOff(true);
}


void setTach(float inRPM) {

   float outVal;

   outVal = RPMMapper.map(inRPM);
   if (inRPM>200) {
      tach.setPeriod(outVal);
      tach.setPercent(50);
      if (!tach.running()) {
         tach.setOnOff(true);
      }
   } else {
      tach.setOnOff(false);
   }
   RPM = inRPM;
}


void gotCmd(char* inStr) {
  
   setTach(atof(inStr));
   //tach.setPeriod(atof(inStr));
   //tach.setPercent(50);
   //Serial.println(atof(inStr));
}



void loop() {

   idle();
}

Adding #include <cstdlib> made if go away for a day. It's uneplicably come back but If I change one atof() to an atoi() it tends to go away.

I know, we all want the simplest code and here I have..

Code:
void setup() {
   float x = atof("4.3");
}

void loop() { }

This is giving..

Code:
forum_post: In function 'void setup()':
forum_post:2: warning: unused variable 'x'
    2 |    float x = atof("4.3");
      |          ^
/Applications/Teensyduino.app/Contents/Java/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /Applications/Teensyduino.app/Contents/Java/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m/nofp/libc.a(libc_a-writer.o): in function `_write_r':
(.text._write_r+0x14): undefined reference to `_write'
collect2: error: ld returned 1 exit status
Error compiling for board Teensy 3.2 / 3.1.

I'm really wondering what I did.

Thanks millions!

-jim lee
 
The warning in your little atof() program just means that you are computing "x", but not using it anywhere. The program below uses "x" in a print statement, which also resolves the missing _write(). I haven't run this program on 3.2, but I'm pretty sure it will run correctly.

Code:
void setup() {
  Serial.begin(9600);
  while (!Serial && millis() < 3000) {}
  float x = atof("4.3");
  Serial.println(x);
}

void loop() { }
 
Well, this doesn't even use the Serial stuff. And it has the error. So this can't be right.

Code:
void setup() {
   float x = atof("4.3");
}

void loop() { }

Code:
/Applications/Teensyduino.app/Contents/Java/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /Applications/Teensyduino.app/Contents/Java/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m/nofp/libc.a(libc_a-writer.o): in function `_write_r':
(.text._write_r+0x14): undefined reference to `_write'
collect2: error: ld returned 1 exit status
Error compiling for board Teensy 3.2 / 3.1.

-jim lee
 
Indeed it's not quite right. It's also (probably) not ever going to be fixed, since all new development is on Teensy 4.x.

I'm not 100% certain why this happens (and also unlikely time will be invested to really dig into the reason why), but I suspect it's related to upgrading to newer gcc toolchains which come with newer libc. We did a pretty incredible amount of optimization for less memory usage and also better performance, using the old toolchain. The net result it we're left with a situation where "trivial" programs which don't actually use the core library features don't compile because some aspect of the newer toolchain libc wants that _write() function on trivial programs which shouldn't need it.

You could try installing an older version of the software which had the earlier toolchain. In Arduino 2.3.x this is very easy... just search "teensy" in Boards Manager, and then use the drop-down list of versions to change which version of Teensy's software is installed. However, it only goes back to 1.56, which was the first version released when Arduino released IDE 2.0.
 
Well, this doesn't even use the Serial stuff. And it has the error. So this can't be right.

Code:
void setup() {
   float x = atof("4.3");
}

void loop() { }

It's the absence of Serial that causes the issue. Just add a Serial.print(), which brings in _write(), to resolve the error.
 
I tested it again and something a little more curious happens. "Serial.print()" fails? "Serial.println()" or Serial.printf" does not fail.
This fails to compile:
Code:
//**************************************************************************
void setup() {
//  while (!Serial1 && millis() < 5000) {} //wait for Serial Monitor
   float x = atof("4.3");
Serial.print(""); // Fails
//Serial.println(""); // passes
//Serial.printf(""); // passes
}

void loop() { }
//**************************************************************************
The next two do not:
Code:
//**************************************************************************
void setup() {
//  while (!Serial1 && millis() < 5000) {} //wait for Serial Monitor
   float x = atof("4.3");
//Serial.print(""); // Fails
Serial.println(""); // passes
//Serial.printf(""); // passes as well
}

void loop() { }
//**************************************************************************
Using Arduino 1.8.19 and TD1.60B4 set to compile for Teensy 3.2.
Seems odd, but is probably for reasons stated by @PaulStoffregen :unsure:
 
The compiler can recognize Serial.print("") actually does nothing, so it effectively deletes the function call and doesn't put any code into your program. Remember, we put ~10 years of work into heavily optimizing Teensy 3.x for speed and smaller code size. A lot of effort went into structuring the core library in ways to best allow the compiler to optimize.

But it's not smart enough to analyze the complex Serial.printf("") function.

Serial.println("") does actually transmit 2 bytes, CR and LF. The compiler can't delete it.
 
So the 4.x optimisations are mixed in with the old 3.2 stuff? Sigh.. I'm currently using teensy 1.59 & the 1.8.19 IDE for writing this stuff. I'd figured I was back far enough. Guess not.

I totally understand why you are not interested in putting time into a dead product. Double sigh.. I so loved the 5V tolerant pins.

Thanks again for looking into this. At least there was something going on and I wasn't just going crazy seeing stuff.

I guess I'll go buy a handfull of 4.x chips and see if I can make them go.

-jim lee
 
Did you consider adding a dummy stub like this
Code:
int _write(int file, char *data, int len)
{ return 0; }
 
Back
Top