Error compiling for board Teensy 3.2 / 3.1.

Status
Not open for further replies.

alexandros

Well-known member
I'm trying to use an MPU-9250 by Sparkfun (https://www.sparkfun.com/products/13762) with a Teensy 3.2, but I can'y upload the code. I'm using the I2C example sketch that comes with its library (https://github.com/sparkfun/SparkFun_MPU-9250_Breakout_Arduino_Library), and even though it compiles fine on an Arduino UNO, with the Teensy 3.2 I get the following errors:
Code:
/home/alexandros/Arduino/libraries/SparkFun_MPU-9250_Breakout_Arduino_Library/src/MPU9250.cpp: In member function 'void MPU9250::magCalMPU9250(float*, float*)':
/home/alexandros/Arduino/libraries/SparkFun_MPU-9250_Breakout_Arduino_Library/src/MPU9250.cpp:608:48: error: narrowing conversion of '32768' from 'int' to 'int16_t {aka short int}' inside { } [-Wnarrowing]
   int16_t mag_max[3]  = {0x8000, 0x8000, 0x8000},
                                                ^
/home/alexandros/Arduino/libraries/SparkFun_MPU-9250_Breakout_Arduino_Library/src/MPU9250.cpp:608:48: error: narrowing conversion of '32768' from 'int' to 'int16_t {aka short int}' inside { } [-Wnarrowing]
/home/alexandros/Arduino/libraries/SparkFun_MPU-9250_Breakout_Arduino_Library/src/MPU9250.cpp:608:48: error: narrowing conversion of '32768' from 'int' to 'int16_t {aka short int}' inside { } [-Wnarrowing]
/home/alexandros/Arduino/libraries/SparkFun_MPU-9250_Breakout_Arduino_Library/src/MPU9250.cpp: In member function 'uint8_t MPU9250::writeByteWire(uint8_t, uint8_t, uint8_t)':
/home/alexandros/Arduino/libraries/SparkFun_MPU-9250_Breakout_Arduino_Library/src/MPU9250.cpp:734:10: warning: converting to non-pointer type 'uint8_t {aka unsigned char}' from NULL [-Wconversion-null]
   return NULL;
          ^
Error compiling for board Teensy 3.2 / 3.1.
As a side note, I'm using the Audio board at the same time (I'm planning to use both simultaneously, for now I'm just trying to upload this example code and I'm using the board for its pull-up resistors on the I2C pins of the Teensy). I don't think that's the problem though, the IDE can't even compile the sketch for the Teensy.
It seems like there are some stuff in the library that need to be changed, but why would this sketch run fine on an Arduino and won't compile with a Teensy?
 
Should be an easy fix:
Line 608:
Code:
 int16_t mag_max[3] = {0x8000, 0x8000, 0x8000},

a value of 0x8000 which is 32768 will not fit into an int16_t value... Probably change to maybe: -32767

Likewise the warning line:
Code:
 return NULL;

Change NULL to 0.
 
Should be an easy fix:
Line 608:
Code:
 int16_t mag_max[3] = {0x8000, 0x8000, 0x8000},

a value of 0x8000 which is 32768 will not fit into an int16_t value... Probably change to maybe: -32767

Likewise the warning line:
Code:
 return NULL;

Change NULL to 0.

Ok, makes sense. But why does the same code compile with an Arduino and doesn't with a Teensy? An int16_t should be the same for both hardware, shouldn't it?
 
technically yes, but NULL should be replaced with 0, or nullptr if it’s a pointer. the values are specified in “int”, which on arduino is 16bits, so yeah, int16_t on arduino is int, and 32768 will be 0 as it rolls over.

teensy is a 32bit arm controller, where “int” is 32 bits. writing the actual value 32768 wont work in conversion because
int is no longer 16bit when on teensy.

we use the specific primitive types to make the code more portable between different microcontrollers.

just specifying int wont make it work on all playforms unless that platform had ints representing 16bits, so only 16bit platforms would be working
 
technically yes, but NULL should be replaced with 0, or nullptr if it’s a pointer. the values are specified in “int”, which on arduino is 16bits, so yeah, int16_t on arduino is int, and 32768 will be 0 as it rolls over.

teensy is a 32bit arm controller, where “int” is 32 bits. writing the actual value 32768 wont work in conversion because
int is no longer 16bit when on teensy.

we use the specific primitive types to make the code more portable between different microcontrollers.

just specifying int wont make it work on all playforms unless that platform had ints representing 16bits, so only 16bit platforms would be working
So specifying an int16_t specifies an int of 16 bits, right? According to what you say, doesn't this make it microcontroller agnostic, and possible to work on different hardware?
If I have to change this value, what should I change it to? Kurt E suggested -32767, but you say that on 16bits microcontrollers the provided value would roll back to 0. So, which should it be, -32767 or 0?
 
it will roll to 0 if its unsigned, sorry, my fault. int16_t is signed

if i were to try it, i would change all instances of “int” to “int16_t”, and stop using NULL, it’s deprecated, use 0 like Kurt said

but like i said on arduino

int and int16_t is same (except duo perhaps)
but on teensy
int is actually int32_t
 
Just to get this right, int16_t forces a 16bit int, so 32768 and in case a microcontroller is greater than 16bits (like the Teensy), it won't roll back to -32767 (or should it be -32768, int goes from -32768 to 32767, right?). So I should hard-code this value to the lowest value of a 16it int?
I'll give it a try and see.

Thanks
 
32768 should roll to -32767 but yeah, int16_t will use the same primitive as was implied with arduino using “int”. This makes the code cross-platform compatible. You don’t necessarily need to touch any values, just change the primitive type to int16_t, the value will work as normal after

on a 64bit microcontroller, an “int” is 64bits, keep that in mind, int16_t would work on all 8,16,32,64, etc controllers
 
32768 should roll to -32767 but yeah, int16_t will use the same primitive as was implied with arduino using “int”. This makes the code cross-platform compatible. You don’t necessarily need to touch any values, just change the primitive type to int16_t, the value will work as normal after

on a 64bit microcontroller, an “int” is 64bits, keep that in mind, int16_t would work on all 8,16,32,64, etc controllers
But the code chunk that produces the error is this:
Code:
int16_t mag_max[3]  = {0x8000, 0x8000, 0x8000};
The data type is defined as an int16_t which, according to what you say should be cross-platform, right?

I also wrote a small C++ test program to see to what value 0x8000 rolls back in case of int16_t. This is the code:
Code:
#include <iostream>
using namespace std;

int main() {
        int intTest1 = 0x8000;
        int16_t intTest2 = 0x8000;
        cout << "Value of int is " << intTest1 << endl;
        cout << "Value of int16_t is " << intTest2 << endl;

        return 0;
}
And this is the output:
Code:
Value of int is 32768
Value of int16_t is -32768
It looks like 0x8000 rolls back to -32768, not to -32767. Anyway, I tried replacing the values in the source code of the library (the first code snippet of this post) with both these values. The compilation goes a bit further, but now I'm getting this error:
Code:
/home/alexandros/Arduino/libraries/SparkFun_MPU-9250_Breakout_Arduino_Library/src/quaternionFilters.cpp:38:14: warning: 'zeta' defined but not used [-Wunused-variable]
 static float zeta = sqrt(3.0f / 4.0f) * GyroMeasDrift;
              ^
Archiving built core (caching) in: /tmp/arduino_cache_324536/core/core_teensy_avr_teensy31_usb_serial,speed_96,opt_o2std,keys_en-us_f961348f132d4832999f6e924916bc9d.a
/home/alexandros/Applications/arduino-1.8.4/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/lib/armv7e-m/libc.a(lib_a-signalr.o): In function `_kill_r':
signalr.c:(.text._kill_r+0x10): undefined reference to `_kill'
/home/alexandros/Applications/arduino-1.8.4/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/lib/armv7e-m/libc.a(lib_a-signalr.o): In function `_getpid_r':
signalr.c:(.text._getpid_r+0x0): undefined reference to `_getpid'
collect2: error: ld returned 1 exit status
Error compiling for board Teensy 3.2 / 3.1.
Is this getting any closer?
 
The value of 0x8000 is 32768 - as a 32 bit number - that doesn't fit in a signed 16 bit integer as stored - that is what the compiler is saying.

A signed int16 can go from -32768 to 32767. In an unsigned 16 bit integer it is 0 to 65535 where ZERO is the 65536th value it can hold. In the case of signed 16 bit values the ZERO value takes from the HIGH/positive side, so 32768 is not valid in a 16 bit signed int as stored and the compiler can/will not create it.
 
But why does the same code compile with an Arduino and doesn't with a Teensy?

Teensy is using gcc 5.4. Arduino is using gcc 4.8.

Starting with gcc version 5, this was turned from a warning to an error when C++11 or later dialect is in use. We're using C++14 on Teensy 3.x.

I'm looking through gcc documenation now to see if there's any way to tell gcc 5 to only give a warning (but of course, stay on C++14). So far, not having much success other than -Wno-narrowing, which has the undesirable effect of no warning printed at all.

Arduino is going to upgrade to gcc 5.4 soon, probably with version 1.8.6. It's already on their github repository. When they start using gcc 5.4, this will (probably) become an error for all Arduino boards too.
 
After much searching & trial-and-error, I haven't found any way to turn the narrowing conversion error back to merely a warning. I asked on Twitter just now. Maybe someone who knows gcc better will answer? Maybe MichaelMeissner will see this thread and comment?

I really don't want to start using -Wno-narrowing with Teensy, but if that's the only option perhaps it's better than having so much old & poorly written but otherwise good code not compile?
 
Oh, might have just found the answer buried in this thread. Going to try adding -Wno-error=narrowing which looks like it can give us the behavior we want, so this kind of code still gives a warning but will actually compile.


EDIT: yes, this seems to solve the problem. I'm putting it in. Will be in 1.42-beta6 coming soon.
 
Last edited:
I'm glad you found the solution. I would have had to go source diving for it. Since I work on the backend, I tend to ignore new warnings/errors in the front end. And looking at the source, it is a C++ only error.
 
@alexandros - If you're still watching this thread, any chance I can talk you into giving the original library a try with 1.42-beta7?

https://forum.pjrc.com/threads/52583-Teensyduino-1-42-Beta-7

I put in a change that's supposed to allow poorly coded libraries like this one to compile, as they do on 8 bit AVR. I checked it here, but would be really nice if you could confirm whether it fully solves the problem as you originally encountered...
 
Status
Not open for further replies.
Back
Top