Teensy 2 vs Teensy 3 GCC error with C99 struct init by member name

Status
Not open for further replies.

stevech

Well-known member
In the Arduino IDE, when teensy 2 is chosen, the struct initializer by name per the C99 standard does not work. It does work when the teensy 3 is chosen (different command line). Same issue in VM. Of course, different versions of GCC are used for Teensy 2 and Teensy 3. But the target core shouldn't matter to this issue on struct init by member name per C99.

I noted, in the GCC command line args, that Teensy 2 uses -std=c++0x whereas Teensy 3 uses -std=gnu++0x. I don't know if that's relevant.

Struct init by name in C99, example compiles OK with teensy 3 but not the GCC command line used by Teensy 2.
Code:
struct foo_t
{
   int me;
};
struct foo_t  =
{
    .me = 123;
};
 
The GCC used for AVR is rather old (4.3.2, released on August 27th, 2008), and it is what is shipped with the Arduino 1.0.5 release. The GCC used for ARM is 4.7.2 (released on September 20, 2012 from the FSF, and Paul got it with CodeSourcery mods for the ARM environment).

The current release from the FSF is 4.8.2 with 4.8.3 and 4.9.0 coming soon. The difference between -std=c++0x and -std=gnu++0x is that -std=gnu++0x allows GNU extensions. Also note that by default, the Arduino enviornment uses C++, which probably does not have the support for C99 named initialization (C99 is the C standard).
 
Last edited:
So there's no easy change to the Teensy 2 GCC command line so it can compile the struct initializer as Teensy 3 does without error?
 
Probably not an easy change for most folk. Here is a discussion on 2012 in the Arduino group about this: http://forum.arduino.cc/index.php?topic=125500.0.

Here is one link for AVR tools that run on Eclipse: https://infernoembedded.com/products/avr-tools. You would either need to move over to Eclipse or retrofit it into the current IDE setup.

Here is a list of differences with the newer compiler on AVR's (note, the progmem stuff will probably mean going through the whole set of libraries that you use): https://github.com/arduino/Arduino/issues/1208

This site actually goes into detail how to update your IDE to use the new compiler: http://andybrown.me.uk/wk/2012/04/28/avr-gcc-4-7-0-and-avr-libc-1-8-0-compiled-for-windows/. Presumably once you do this, you will not be able to install any more Teensy releases. So you would need to install the standard 1.0.5 release, install the new Teensy release, and then reinstall the 4.7 compiler.
 
If you are trying to do what I think you are, I have wrestled with this mess; what I call missing "sparse init" of structs in C++; to the point of physical sickening. I despair that C++ will EVER standardize something as simple and elegant as C99's named struct element init. Even C++14 stonewalls it. There is, however, a way to accomplish pretty much the same effect in classic C++. It is very portable. Any compiler implementing at least as far back as C++98, and even well before that, will do it. Remember, a struct in C++ has all the capabilities of a class. What follows is more verbose and not quite as efficient, depending on how good the compiler's optimization is, but it works.
Code:
struct foo_t
{
  int me;
  int me2;
  int me3;
  foo_t& set_me(int me) { this->me = me; return *this; }
  foo_t& set_me2(int me2) { this->me2 = me2; return *this; }
  foo_t& set_me3(int me3) { this->me3 = me3; return *this; }
};

foo_t foo;

foo.set_me3(3).set_me(1);

This leaves .me2 zeroed by the static init and selectively sets .me and .me3. If gcc is run with -O2 optimization, the calls to set_me3 and set_me are inlined very efficiently into single-instruction indexed stores. That's not quite as efficient as fully static initing of everything, but it's close.

Note: the setter methods return instance references specifically so that you will be able to chain them arbitrarily.

Note 2: you can even apply the setters on temporaries; e.g.:
Code:
std::cout << foo_t().set_me(123).me << '\n';
and
Code:
foo_t* p;
std::cout << (p = new foo_t())->set_me(123).me << '\n';
delete p;
 
Named struct member initialization works fine with Teensy3 and it's GCC command line for a C++ program.
Does not work with the Teensy 2 and it's GCC command line for C++.

Since I don't use Teensy 2 much.. I'll deal with it. Seems like Teensy 2 frozen in time. That's OK for me.

Your work-around shown above is a bit too esoteric for me. I really dislike how obtuse C++ can get to be. In the real world, code has to be obvious to be maintainable.
 
Last edited:
So there's no easy change to the Teensy 2 GCC command line so it can compile the struct initializer as Teensy 3 does without error?

You could replace 1.0.5's AVR toolchain with the toolchain from these:

http://downloads.arduino.cc/arduino-avr-toolchain-nightly-gcc-4.8.1-windows.zip
http://downloads.arduino.cc/arduino-avr-toolchain-nightly-gcc-4.8.1-macosx.zip
http://downloads.arduino.cc/arduino-avr-toolchain-nightly-gcc-4.8.1-linux32.tgz
http://downloads.arduino.cc/arduino-avr-toolchain-nightly-gcc-4.8.1-linux64.tgz

Just extract this zip file, find "avr" in hardware/tools. Replace the "avr" in hardware/tools in 1.0.5 with the "avr" directory from this new one.

I recently did this on the Linux 64 bit version, and I tested 4 libraries on Teensy 2.0. It seems to work fine. Compiled size is smaller, speed is similar to slightly improved, but sometimes more RAM is used.

Seems like Teensy 2 frozen in time. That's OK for me.

Most new development by PJRC is going into Teensy 3.1. But some stuff is still being done on 2.0. Just a couple weeks ago a fix for auto-reboot if the watchdog is active was added (fixes auto-reboot using the Entropy library). Over the last few days I've been putting a lot of time into fixing the SPI library compatibility problem, which of course I'll implement for 2.0 and 3.x.

But other than bug fixes, pretty much all new development is going into 3.1.
 
Product-wise, I can tell you PJRC has production of Teensy 2.0 and Teensy++ 2.0 scheduled well into 2015.

As long as a good number of people still want them, and Atmel keeps making the chips, we'll continue keeping Teensy 2.0 and Teensy++ 2.0 available.

Rumor has it Atmel has stopped all new AVR development. I've heard they plan to keep the chips selling for 10 years. This is all unofficial rumors... but I'd be curious to hear if anyone knows anything more definitive?
 
Rumor has it Atmel has stopped all new AVR development. I've heard they plan to keep the chips selling for 10 years. This is all unofficial rumors... but I'd be curious to hear if anyone knows anything more definitive?

Really? First I've heard of that. I think Microchip would be interested to know the answer to that too.
 
Well, I suspect that the whole Arduino, Teensy 2.x, etc. market represents a rather small fraction of the total AVR's produced in a year, and what is driving the chip production is the usage in embedded commercial projects. If Atmel isn't getting new design wins, and existing customers are moving to another chips, it will be too expensive to continue production. It is the nature of single source processor designs.
 
Sounds to me like Paul is saying Atmel isn't stopping PRODUCTION of AVR. They are stopping NEW DEVELOPMENT. Makes sense to me. There are some great AVR chips; for example no ARM can match the low power state some of them have. We're taking nanoamps in some cases. But they've got the segment covered. Can't see much point in multiplying the selection of parts any more. As for technical advances, I mean really who cares if they make an AVR that's twice as fast for example? If you want speed, you go ARM.
 
Last edited:
Well I wouldn't put much R&D into 8-bit micros of any class, but it sort of sounds like AVR32 is a dead path. Perhaps it is dead already, not sure I haven't followed it. Not that I would blame them, ARM has taken the 32-bit mindshare.
 
Status
Not open for further replies.
Back
Top