warnings on other AVRs are errors on Teensy/Teensy++

bperrybap

Well-known member
Paul,
It appears that Teensy turns on this option:
-std=c++0x

which is not used on the other AVR cores.
I'm guessing that is creating this "issue".

I accidentally ran into this with some openGLCD code.
The code is from the GLCDv3 library and I have a compatibility mode
that allows most existing GLCDv3 code to work.
The module in question actually has many warnings in it, some quite
severe.
Normally I would fix them, in fact I have but because I ship
modified and unmodified GLCDv3 examples, to demonstrate how "un-modified" GLCDv3
code can run on openGLCD, I ran into this issue.
The unmodified GLCDv3 module with the questionable code actually compiles
and runs on the other AVR processors but not on Teensy/Teensy++
Ironically, it also builds on Teensy3.

To see the issue you can go get the latest openGLCD build from the openGLCD bitbucket site
https://bitbucket.org/bperrybap/openglcd/downloads/openGLCD-v0.8a-7-g9b22651.zip
(Not sure if the direct download like will work)

Then select this example:
openGLCD->GLCDv3demos->GLCDv3->GLCD_BigDemo

A few of the warning are errors with Teensy/Teensy++

The updated/clean version of the same code is:
openGLCD->GLCDv3demos->openGLCD->GLCD_BigDemo
And obviously it works with no issues as the code has been updated & corrected.

Not sure what the answer is, Just wanted to let you know
about this compatibility difference.

--- bill
 
Yes, I turned on the c++0x stuff quite some time ago, as part of the overhaul of the String class.

The main motivation was get rvalue refs, which really speed up common usage of the string class and avoid excessive malloc & free calls that fragment the memory. When you assign one String equal to some temporary string (perhaps concatenating stuff), the rvalue ref lets the library just "steal" the buffer from the string that's about no longer exist and give it to the one receiving the data. Without this (eg, on all official Arduino boards), the assignment involves calling malloc for the string receiving the data, then a memcpy of all the data, and finally free() on the temporary string. The extra CPU time isn't great, but worst of all, this malloc/free usage pattern leaves a big hole in the heap. The C++0x rvalue ref was made to allow C++ objects that allocate memory to be more efficient in exactly this way.

One side effect, which rarely comes up, is some things that were only warnings become errors in C++0x. I think this is the second time I've ever heard of it happening.

I can take a look if you like. But the choice is going to be either fixing the code generating the warning/error, or turning off c++0x and losing rvalue refs that greatly benefit String usage.
 
A bit more information on this as I'm still trying to track down what is really going on here.
It turns out that there is no warning that changes to an error.
(The code has so many warnings that I that it was a warning turning in to an error)
It is just that certain combinations of compiler version and options create a new error.
It is due to some pretty ugly/awful code. (I didn't write it).
Of course I've fixed it, (it needed many other updates to work on non AVR processors)
but like I said I was trying to show how old existing working GLCDv3 code could work "as is"
using the GLCDv3 compatibility mode.
I didn't want to go in an modify it other than changing the includes for this type of demonstration.

First off, it only happens on a newer AVR compiler than what ships with the IDE.
So most users will never see this.

Next, it relates to some twisted uses of initialization of an array/structure that uses the
random() function. I didn't even think that this type of initialization was even possible in C.

Here is one example of the code that has the issue:

Code:
char tracker[8][5] = {
// Bitmap,  Xpos,   Ypos,          Speed
  {PLAYER,  15,     32,            0}  ,
  {ROCK2,   119,    random(0, 56), random(25, 75)}  ,
  {ROCK5,   119,    random(0, 56), random(25, 75)}  ,
  {ROCK8,   119,    random(0, 56), random(25, 75)}  ,
  {ROCK1,   119,    random(0, 56), random(25, 75)}  ,
  {ROCK3,   119,    random(0, 56), random(25, 75)}  ,
  {BONUS,   119,    random(0, 56), random(25, 75)}
};

The issue is that random() returns a long which is bigger than a char.

On the older AVR compiler (4.3.2) that ships with the 1.0.5 IDE all AVR processors get no warning.

The newer AVR compiler (4.5.3) on IDE 1.0.5 when building for teensy/teensy++ returns this error:
Code:
Rocket:78: error: narrowing conversion of ‘random(0l, 56l)’ from ‘long int’ to ‘char’ inside { }
While the non Teensy processors on the new compiler don't even get a warning.

What is still confusing to me is that on IDE 022 all AVRs get this error when using the newer compiler.
There may be some goofy math.h macros in the Arduino code interacting with this as well.

I'm still trying to track it completely down.

--- bill
 
Ok,
So here is a boiled down examle of some code that "works" on non Teensy AVR boards that fails to compile on Teensy.

Code:
int8_t foo[] = { 0x92 };

void setup() { } 
void loop() { }

Apparently hex constants are treated as "ints".
I just ran into this in the Talkie library (cool library that bit bangs out speech)
as I was trying to get it working on Teensy.

You can get around the issue with explicit casts, which I guess I will put into the code
as I try to bring it up on Teensy.
Code:
int8_t foo[] = { (int8_t)0x92 };

void setup() { } 
void loop() { }

--- bill
 
Note, that if you store 0x92 into a int8_t (i.e. signed char), when you read it back, you will get -110 and not 146. I suspect you should use an unsigned type (uint8_t), if you are going to use constants like this.

ARM compilers default to plain char having the range 0..255, while AVR compilers default to plain char having the range -128..127. You probably should audit your code to remove any places where you used plain chars, that were not actually holding characters, such as the common Print functions which use C++'s ability to have multiple declarations of a function with different types of arguments to specify that when given a char argument will print it as a character, while given an integer argument, will print it as a decimal constant.

Another thing to consider is the 'int' type on AVR is 16-bits, while it is 32-bits on ARM processors.
 
Last edited:
I've been considering whether to change Teensy3 to use signed char. All AVR boards do, and Arduino documentation is all based on signed char. Arduino Due uses unsigned char, just like Teensy3.

At this point, I'm still undecided.....
 
Back
Top