I have longstanding projects running on T3.6 that have been stable but now crash silently after late_startup_hook() and before setup() if compiled under 1.58 or 1.59 beta3.
I tracked my issues to the fact that SPI construction is no longer happening as a constexpr, so the devices do not exist when I call them in the constructors of other objects.
I see that the problem has been recognized, understood, and solved for some libraries:
https://forum.pjrc.com/index.php?threads/problem-with-two-wire-build-between-11-3-1-and-5-4-1.73176/#post-328856
https://forum.pjrc.com/index.php?threads/teensy-4-1-does-not-boot-when-invoking-spi-from-external-class.73154/
Running a slightly modified version of the Teensyduino_Test_constinit_XXX code from one of those threads, I see Wire works correctly on both, but SPI works only on T4 and fails on T3.6.
= = = = = = = = = = = = = = = = = = = =
T4.1
Wire, SPI, and HWSerial all have been fixed:
= = = = = = = = = = = = = = = = = = = =
**startup_late_hook**
Wire: var #1 = 403F0000
Wire: var #2 = 60001F14
Wire1: var #1 = 403F8000
Wire1: var #2 = 60001E74
Wire2: var #1 = 403FC000
Wire2: var #2 = 60001E74
SPI: var #1 = 403A0000
SPI: var #2 = 200004B8
SPI1: var #1 = 4039C000
SPI1: var #2 = 20000448
SPI2: var #1 = 40394000
SPI2: var #2 = 200003D8
Serial: var #1 = 40198000
Serial: var #2 = 20000378
Serial2: var #1 = 40190000
Serial2: var #2 = 20001028
Serial3: var #1 = 40188000
Serial3: var #2 = 20000F68
Serial4: var #1 = 4018C000
Serial4: var #2 = 20000FC8
Serial5: var #1 = 401A0000
Serial5: var #2 = 20001148
Serial6: var #1 = 40184000
Serial6: var #2 = 20000F08
Serial7: var #1 = 4019C000
Serial7: var #2 = 200010E8
Serial8: var #1 = 40194000
Serial8: var #2 = 20001088
**setup**
Wire: var #1 = 403F0000
Wire: var #2 = 60001F14
Wire1: var #1 = 403F8000
Wire1: var #2 = 60001E74
Wire2: var #1 = 403FC000
Wire2: var #2 = 60001E74
SPI: var #1 = 403A0000
SPI: var #2 = 200004B8
SPI1: var #1 = 4039C000
SPI1: var #2 = 20000448
SPI2: var #1 = 40394000
SPI2: var #2 = 200003D8
Serial: var #1 = 40198000
Serial: var #2 = 20000378
Serial2: var #1 = 40190000
Serial2: var #2 = 20001028
Serial3: var #1 = 40188000
Serial3: var #2 = 20000F68
Serial4: var #1 = 4018C000
Serial4: var #2 = 20000FC8
Serial5: var #1 = 401A0000
Serial5: var #2 = 20001148
Serial6: var #1 = 40184000
Serial6: var #2 = 20000F08
Serial7: var #1 = 4019C000
Serial7: var #2 = 200010E8
Serial8: var #1 = 40194000
Serial8: var #2 = 20001088
= = = = = = = = = = = = = = = = =
T3.6
Wire has been fixed, but SPI has not:
= = = == = = = = = = = = = = = =
**startup_late_hook**
Wire: var #1 = 40066000
Wire: var #2 = 2700
Wire1: var #1 = 40067000
Wire1: var #2 = 26C0
Wire2: var #1 = 400E6000
Wire2: var #2 = 26C0
SPI: var #1 = 0
SPI: var #2 = 0
SPI1: var #1 = 0
SPI1: var #2 = 0
SPI2: var #1 = 0
SPI2: var #2 = 0
**setup**
Wire: var #1 = 40066000
Wire: var #2 = 2700
Wire1: var #1 = 40067000
Wire1: var #2 = 26C0
Wire2: var #1 = 400E6000
Wire2: var #2 = 26C0
SPI: var #1 = 4002C000
SPI: var #2 = 2744
SPI1: var #1 = 4002D000
SPI1: var #2 = 27D8
SPI2: var #1 = 400AC000
SPI2: var #2 = 286C
= = = = = = = = = = = = = = = = = = = =
Here is the code that produces this output:
#include <Wire.h>
#include <SPI.h>
// Separate version for T4 vs T3 because T4 has portAddr while T3 has port_addr
#if defined(__IMXRT1062__) // T4
uintptr_t Teensyduino_Test_constinit_Wire(int instance, int index) {
if (instance == 0) {
if (index == -1) return (uintptr_t)("Wire");
if (index == 0) return 2;
if (index == 1) return Wire.portAddr; // probably should decide whether it is portAddr or port_addr and use the same thing everywhere
if (index == 2) return (uintptr_t)&Wire.hardware;
}
if (instance == 1) {
if (index == -1) return (uintptr_t)("Wire1");
if (index == 0) return 2;
if (index == 1) return Wire1.portAddr;
if (index == 2) return (uintptr_t)&Wire2.hardware;
}
if (instance == 2) {
if (index == -1) return (uintptr_t)("Wire2");
if (index == 0) return 2;
if (index == 1) return Wire2.portAddr;
if (index == 2) return (uintptr_t)&Wire2.hardware;
}
#if defined(ARDUINO_TEENSY_MICROMOD)
if (instance == 3) {
if (index == -1) return (uintptr_t)("Wire3");
if (index == 0) return 2;
if (index == 1) return Wire3.port_addr;
if (index == 2) return (uintptr_t)&Wire3.hardware;
}
#endif
return 0;
}
#else // Not T4
uintptr_t Teensyduino_Test_constinit_Wire(int instance, int index) {
if (instance == 0) {
if (index == -1) return (uintptr_t)("Wire");
if (index == 0) return 2;
if (index == 1) return Wire.port_addr;
if (index == 2) return (uintptr_t)&Wire.hardware;
}
if (instance == 1) {
if (index == -1) return (uintptr_t)("Wire1");
if (index == 0) return 2;
if (index == 1) return Wire1.port_addr;
if (index == 2) return (uintptr_t)&Wire2.hardware;
}
if (instance == 2) {
if (index == -1) return (uintptr_t)("Wire2");
if (index == 0) return 2;
if (index == 1) return Wire2.port_addr;
if (index == 2) return (uintptr_t)&Wire2.hardware;
}
#if defined(ARDUINO_TEENSY_MICROMOD)
if (instance == 3) {
if (index == -1) return (uintptr_t)("Wire3");
if (index == 0) return 2;
if (index == 1) return Wire3.port_addr;
if (index == 2) return (uintptr_t)&Wire3.hardware;
}
#endif
return 0;
}
#endif
// constexpr construction of SPI objects on Teensy 4 but not Teensy 3
uintptr_t Teensyduino_Test_constinit_SPI(int instance, int index) {
if (instance == 0) {
if (index == -1) return (uintptr_t)("SPI");
if (index == 0) return 2;
if (index == 1) return SPI.port_addr;
if (index == 2) return SPI.hardware_addr;
}
if (instance == 1) {
if (index == -1) return (uintptr_t)("SPI1");
if (index == 0) return 2;
if (index == 1) return SPI1.port_addr;
if (index == 2) return SPI1.hardware_addr;
}
if (instance == 2) {
if (index == -1) return (uintptr_t)("SPI2");
if (index == 0) return 2;
if (index == 1) return SPI2.port_addr;
if (index == 2) return SPI2.hardware_addr;
}
return 0;
}
// Can't run this section on teensy 3 because T3 HardwareSerial does not have .port_addr or portAddress or .hardware
#if defined(__IMXRT1062__)
uintptr_t Teensyduino_Test_constinit_HardwareSerial(int instance, int index) {
if (instance == 0) {
if (index == -1) return (uintptr_t)("Serial");
if (index == 0) return 2;
if (index == 1) return Serial1.port_addr;
if (index == 2) return (uintptr_t)Serial1.hardware;
}
if (instance == 1) {
if (index == -1) return (uintptr_t)("Serial2");
if (index == 0) return 2;
if (index == 1) return Serial2.port_addr;
if (index == 2) return (uintptr_t)Serial2.hardware;
}
if (instance == 2) {
if (index == -1) return (uintptr_t)("Serial3");
if (index == 0) return 2;
if (index == 1) return Serial3.port_addr;
if (index == 2) return (uintptr_t)Serial3.hardware;
}
if (instance == 3) {
if (index == -1) return (uintptr_t)("Serial4");
if (index == 0) return 2;
if (index == 1) return Serial4.port_addr;
if (index == 2) return (uintptr_t)Serial4.hardware;
}
if (instance == 4) {
if (index == -1) return (uintptr_t)("Serial5");
if (index == 0) return 2;
if (index == 1) return Serial5.port_addr;
if (index == 2) return (uintptr_t)Serial5.hardware;
}
if (instance == 5) {
if (index == -1) return (uintptr_t)("Serial6");
if (index == 0) return 2;
if (index == 1) return Serial6.port_addr;
if (index == 2) return (uintptr_t)Serial6.hardware;
}
if (instance == 6) {
if (index == -1) return (uintptr_t)("Serial7");
if (index == 0) return 2;
if (index == 1) return Serial7.port_addr;
if (index == 2) return (uintptr_t)Serial7.hardware;
}
#if defined(ARDUINO_TEENSY41)
if (instance == 7) {
if (index == -1) return (uintptr_t)("Serial8");
if (index == 0) return 2;
if (index == 1) return Serial8.port_addr;
if (index == 2) return (uintptr_t)Serial8.hardware;
}
#endif
return 0;
}
#endif
void print_info(uintptr_t(*f)(int, int)) {
int instance = 0;
while (1) {
const char* name = (char*)f(instance, -1);
if (!name) break;
int count = f(instance, 0);
for (int i = 1; i <= count; i++) {
uintptr_t n = f(instance, i);
Serial.print(name);
Serial.print(": var #");
Serial.print(i);
Serial.print(" = ");
Serial.println(n, HEX);
}
instance++;
}
}
// must appear separately before the function definition else ld complains about multiple definitions
extern "C" void startup_late_hook();
void startup_late_hook() {
while (!Serial); // wait for serial monitor
delay(15);
Serial.println("startup_late_hook");
print_info(Teensyduino_Test_constinit_Wire);
print_info(Teensyduino_Test_constinit_SPI);
#if defined(__IMXRT1062__)
print_info(Teensyduino_Test_constinit_HardwareSerial);
#endif
}
void setup() {
Serial.println("\nsetup");
print_info(Teensyduino_Test_constinit_Wire);
print_info(Teensyduino_Test_constinit_SPI);
#if defined(__IMXRT1062__)
print_info(Teensyduino_Test_constinit_HardwareSerial);
#endif
}
void loop() {
delay(1);
}
I have longstanding projects running on T3.6 that have been stable but now crash silently after late_startup_hook() and before setup() if compiled under 1.58 or 1.59 beta3.
I tracked my issues to the fact that SPI construction is no longer happening as a constexpr, so the devices do not exist when I call them in the constructors of other objects.
I see that the problem has been recognized, understood, and solved for some libraries:
https://forum.pjrc.com/index.php?threads/problem-with-two-wire-build-between-11-3-1-and-5-4-1.73176/#post-328856
https://forum.pjrc.com/index.php?threads/teensy-4-1-does-not-boot-when-invoking-spi-from-external-class.73154/
Running a slightly modified version of the Teensyduino_Test_constinit_XXX code from one of those threads, I see Wire works correctly on both, but SPI works only on T4 and fails on T3.6.
= = = = = = = = = = = = = = = = = = = =
T4.1
Wire, SPI, and HWSerial all have been fixed:
= = = = = = = = = = = = = = = = = = = =
= = = = = = = = = = = = = = = = =
T3.6
Wire has been fixed, but SPI has not:
= = = == = = = = = = = = = = = =
= = = = = = = = = = = = = = = = = = = =
Here is the code that produces this output: