Teensy 4.1: Wire for I2C causes crash after boot, only in PlatformIO

I have a project. Things are working fine. I want to add an I2C device, so I include <Wire.h> and write code that references that. As soon as I load that hex, the loader LED on the board blinks 7 times, which according to docs here, happens either due to HW error or “processor reboots due to fault or other error handling”.

Happened the first time a few weeks ago, I thought it was just some problem with the particular hardware I was using, so I moved on to something else.

Now I’m back at that point with a different piece of I2C hardware entirely, and it’s the same story. If my project includes code that references Wire, even if that code is never called, the hex will not boot and I’ll get the 7 blink error.

I know that you’re going to tell me “run Scanner.ino” so I installed Arduino IDE / Teensyduino, and did just that. Boots and runs fine, no issue.

Thinking it’s something weird with my project specifically, I create a new PlatformIO project and copy the Scanner.ino code into it. This causes the “7 blinks of crashing” problem.

Here’s the code, it’s copied directly from I2CScanner Sketch page, the only change I made was to use Serial5 to send the console over a hardware UART instead of the USB UART because I prefer to use a dedicated console instead of playing the “re-open Serial Monitor every time” game.

#include <Arduino.h>
#include <Wire.h>
 
void setup()
{
  Wire.begin();
 
  Serial5.begin(9600);
  // while (!Serial); 
  Serial5.println("\nI2C Scanner");
}
  
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial5.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial5.print("I2C device found at address 0x");
      if (address<16)
        Serial5.print("0");
      Serial5.print(address,HEX);
      Serial5.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial5.print("Unknown error at address 0x");
      if (address<16)
        Serial5.print("0");
      Serial5.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial5.println("No I2C devices found\n");
  else
    Serial5.println("done\n");
 
  delay(5000);
}

Any ideas would be appreciated. It’s got to be something particular that PIO is doing; the same code on the same hardware works when compiled in Teensyduino.

Compiling in Arduino gets me the following: note this hex WORKS

Memory Usage on Teensy 4.1:
  FLASH: code:13172, data:5304, headers:9168   free for files:8098820
   RAM1: variables:5952, code:10096, padding:22672   free for local variables:485568
   RAM2: variables:12416  free for malloc/new:511872

Here’s the PIO compilation output for version info and the like; note this hex does NOT work:

Processing teensy41 (platform: teensy; board: teensy41; framework: arduino)
--------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/teensy/teensy41.html
PLATFORM: Teensy (5.0.0) > Teensy 4.1
HARDWARE: IMXRT1062 600MHz, 512KB RAM, 7.75MB Flash
DEBUG: Current (jlink) External (jlink)
PACKAGES:
 - framework-arduinoteensy @ 1.159.0 (1.59)
 - tool-teensy @ 1.159.0 (1.59)
 - toolchain-gccarmnoneeabi-teensy @ 1.110301.0 (11.3.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 92 compatible libraries
Scanning dependencies...
Dependency Graph
|-- Wire @ 1.0
Building in debug mode
Compiling .pio\build\teensy41\src\main.cpp.o
Linking .pio\build\teensy41\firmware.elf
Calculating size .pio\build\teensy41\firmware.elf
Checking size .pio\build\teensy41\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
Building .pio\build\teensy41\firmware.hex
teensy_size: Memory Usage on Teensy 4.1:
teensy_size:   FLASH: code:12532, data:5304, headers:8784   free for files:8099844
teensy_size:    RAM1: variables:5952, code:9584, padding:23184   free for local variables:485568        
teensy_size:    RAM2: variables:12416  free for malloc/new:511872
===================================== [SUCCESS] Took 2.25 seconds =====================================

Looks like the PlatformIO output file is a bit smaller, could it be missing something? (I know .hex format is ASCII so size difference is not 1:1 with the firmware, but the PIO hex file is 2,880 bytes smaller. I’m not sure if I can upload these but I’d be glad to if anyone needs them.

Any suggestions would be greatly appreciated!

follow-up: I think this may be similar to the cached copy of WireIMXRT.cpp issue as described here:

I did a “full clean” and now the platformIO build works; the memory usage info appears correct:

teensy_size: Memory Usage on Teensy 4.1:
teensy_size:   FLASH: code:13172, data:5304, headers:9168   free for files:8098820
teensy_size:    RAM1: variables:5952, code:10096, padding:22672   free for local variables:485568    
teensy_size:    RAM2: variables:12416  free for malloc/new:511872

I thought that creating an entirely new project would imply a clean was done, but it seems like that’s not the case somehow…

So that fixed the Scanner project. If I go back to my own project, running a full clean doesn’t fix the issue - still digging into that one.

Full Clean wasn’t fixing it on my other project so I kept poking at it.
I realized that I had explicitly included Wire.h before the library file for the hardware (in this case Adafruit_AHTX0.h, which uses their Sensor library.) Turns out that file in turn includes <Wire.h>; normally I would expect this not to be a problem, but I think it might influence some sort of build order.

I removed the explicit #include <Wire.h>, and then some combination of Full Clean and rebuild operations after that seem to have done it?

So if it is a rogue copy of the Wire code as described in the other thread, I’d like to know how to get rid of it entirely, because I don’t entirely trust the “Full Clean” at this point.

Real issue seems to be that selecting “Run without Debugging” from the menu (or pressing Control-F5) runs the “pre-debug” step, which still … builds debug.
And for some reason, this has been working fine for everything else, but once you bring Wire into the equation, that’s no longer fine.

But if you choose “Build” it runs the “build” command, which … works fine. And that’s what I’d finally done right this time.

  • I’d expect the IDE option labelled “Run without Debugging” to execute platformio run instead of platformio debug, since that’s … what it says. shrug

  • Is there any keyboard shortcut for the actual Build command? (edit: yes, control-alt-B) hunting for the tiny icon with no text label (next to half a dozen other tiny icons without text labels) isn’t ideal. (edit: I found out how to edit settings.json and add a label. And in the process, I found the buttons on the top of the editor, and from the tooltip there I discovered Control-Alt-B exists. Success!)

Solution: platformio debug was not building properly once <Wire.h> comes into play; use Build aka platformio run instead and it works.