Teensy 4.0 HELP!

gary-864

New member
Looks like case of static init order messed up with the new gcc 11.3 toolchain not using const init for hardware serial.

Simple solution is to revert to Teensyduino 1.57, the last version to use the old gcc 5.4 toolchain. If using Arduino IDE 2, just use Boards Manager to install version 1.57.2.

screenshot.png

This problem has already been fixed on github. Here's the changes.

https://github.com/PaulStoffregen/cores/commit/5b6d81b05a5df51bb8b2734c2f5b4f55ba4f2af2

So far there is no release with this fix, so applying it isn't simple. But eventually version 1.59 will release with this and other fixes for gcc 11.3 problems we didn't catch before 1.58 was released.
 
Last edited:
Paul, thanks for you reply, I did as instructed, it no longer enters a reboot loop, but the code doesn't run. I put a coupe of debug statements in Setup(). It doesn't get that far.

Thanks.
 
Recommend adding begin() functions and move all the serial init stuff from the constructors to the begin() functions (so the constructors have no real code, just initialize member variables). Then you can have much easiest observability of what's going wrong.
 
Your global declaration of
Code:
PL_Light light;
PL_Radio radio;
calls the the constructors of light and radio very early in the startup process, when not all of the hardware is initialized yet. Accessing hardware in constructors is kind of gambling and may or may not work depending on the actual startup code. Simple things like pinMode usually work, other stuff may or may not work. (Of course normal c++ code not accessing any hardware works in constructors). TD 1.59 improves in early constructing objects like Serial, Wire etc, so you can use them in constructors of global objects. However the current core on gitHub (1.59 beta + some changes) won't fix your issue completely.

Generally it is much better to not do any hardware related stuff in constructors but use begin functions instead. (This is why you see all those begin functions in Arduino Libraries).

Attached, your code with added begin() functions which starts up without problem (didn't test any functionality so far)

Edit: Oh, crosspost :)

Edit2: Sorry, in the zip file you need to rename main.cpp to your Radio.ino if you are using the Ardiuino IDE, forgot to do this before posting.
 

Attachments

  • radio.zip
    6.8 KB · Views: 96
Last edited:
Yes I would confirm that the only things you should be doing in constructors is initializing member variables, nothing that relies on other classes to be in a working state.

One invaluable technique is to auto-call a setup function in business logic, like

Code:
class Example
{
public:
  Example(SomeOtherClass * pointer) :
    otherClassObject(pointer),
    initialized(false)
  {
  }

  void BusinessLogicMethod()
  {
    EnsureInitialized();
    // now the business logic here
    // .....
  }

private:
  bool initialized;
  SomeOtherClass * otherClassObject;

  inline void EnsureInitialized()  // worthwhile inlining I think
  {
    if (!initialized)
    {
      Setup();
      initialized = true;
    }
  }

  void Setup()
  {
     // use the values stored in the initializer here to fire up the object proper.
  }
};

This general rule applies unless you never statically allocate objects, or have control order the order of static initialization.

So you can avoid statically declaring objects and call new on your top level object in setup(), setting just one global variable to point to it. Then all your costructors are known to be called after main().
 
Last edited:
luni & MarkT.

Thank you very much for the explanation and modded code. I've tested and it now uploads and runs as expected.

I still have a lot to learn, and I really appreciate you help and assistance.

Thank you!!
 
Back
Top