HardwareSerial problem_Teensy 4.1

danieltsz

Well-known member
I encountered some errors using the hardware serial of Teensy 4.1.
When Teensy boot, my code always checks if Serial (in my case, Serial8) is available, but when I'm parsing the received data, it shows no value, and it will stock my Teensy until watchdog resets, and it will continue until infinity.

Here is a sample code of what I'm doing
Code:
String test = "";

int findDelimiter;
String Value = "";

#include "Watchdog_t4.h"
//WatchDog_1
WDT_T4<WDT1> wdt;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  Serial8.begin(9600);
  Serial.setTimeout(100);

  //Set Watchdog
  WDT_timings_t config;
  //Use WatchDog_1
  config.trigger = 5;  /* in seconds, 0->128 */
  config.timeout = 10; /* in seconds, 0->128 */
  wdt.begin(config);

  //start
  Serial.println("Begin");
}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial8.available() > 0) {
    while (Serial8.available()) {
      test = Serial8.readString();
    }
    
    //print what you read in Hardware Serial
    Serial.print(F("SerialData Received: "));
    Serial.println(test);
    Serial.flush();

    //print the location of delimiter
    findDelimiter = test.indexOf(",");
    Serial.print(F("Delimiter Location : "));
    Serial.println(findDelimiter);
    Serial.println();
    Serial.flush();

    //print the data starting from zero to delimiter location
    Value = test.substring(0, findDelimiter);  //rtcSync          //wpControl
    Serial.print(F("Data Received      : "));
    Serial.println(Value);
    Serial.println();
    Serial.flush();
  }
  wdt.feed();
}

Then this will be the result
UART_error.PNG


As you can see, it always reboots and stocks at printing "delimiter location", not going to "data received" of my code.

I also tried to test all of my hardware serial using this code:
Code:
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.setTimeout(100);
  Serial1.begin(9600);
  Serial1.setTimeout(100);
  Serial2.begin(9600);
  Serial2.setTimeout(100);
  Serial3.begin(9600);
  Serial3.setTimeout(100);
  Serial4.begin(9600);
  Serial4.setTimeout(100);
  Serial5.begin(9600);
  Serial5.setTimeout(100);
  Serial6.begin(9600);
  Serial6.setTimeout(100);
  Serial7.begin(9600);
  Serial7.setTimeout(100);
  Serial8.begin(9600);
  Serial8.setTimeout(100);

  Serial.print("Test Serial : ");
  Serial.println(Serial.available());

  Serial.print("Test Serial1: ");
  Serial.println(Serial1.available());

  Serial.print("Test Serial2: ");
  Serial.println(Serial2.available());

  Serial.print("Test Serial3: ");
  Serial.println(Serial3.available());

  Serial.print("Test Serial4: ");
  Serial.println(Serial4.available());

  Serial.print("Test Serial5: ");
  Serial.println(Serial5.available());

  Serial.print("Test Serial6: ");
  Serial.println(Serial6.available());

  Serial.print("Test Serial7: ");
  Serial.println(Serial7.available());

  Serial.print("Test Serial8: ");
  Serial.println(Serial8.available());
}

void loop() {
  // put your main code here, to run repeatedly:
}

And here is the result:
UART_error1.PNG


As you can see, at the start of the program, Serial8.available is already = 1.

I noticed when I pressed the program button for 15 seconds, all hardware serial "resets" but it also erased my program and went back to blinking the built-in LED program. Is there any other way I can write in my program before "void loop" to reset the hardware serial?
 
Not sure what 'of import' changed in the code below {added some intermediate printing} - but with a JUMPER on Serial 8 Rx<>TX, i.e. pin 34 and 35 this code.
The Serial8 Jumper is providing known proper UART Serial8 connectivity and data for sure though.
Where is the external connect to Serial8 at 9600 baud coming from? Shared Ground to device?
C:
String test = "";

int findDelimiter;
String Value = "";

#include "Watchdog_t4.h"
//WatchDog_1
WDT_T4<WDT1> wdt;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  Serial8.begin(9600);
  Serial.setTimeout(100);

  //Set Watchdog
  WDT_timings_t config;
  //Use WatchDog_1
  config.trigger = 5;  /* in seconds, 0->128 */
  config.timeout = 10; /* in seconds, 0->128 */
  wdt.begin(config);

  //start
  Serial.println("  >>>  Begin @setup()");
  Serial8.println("Start,End");
}

elapsedMillis aTime;
void loop() {
  // put your main code here, to run repeatedly:
  if (Serial8.available() > 0) {
    Serial.print(Serial8.available());
    Serial.print('\t');
    while (Serial8.available()) {
      test = Serial8.readString();
      Serial.println(test);
    }

    //print what you read in Hardware Serial
    Serial.print(F("SerialData Received: "));
    Serial.println(test);
    Serial.flush();

    //print the location of delimiter
    findDelimiter = test.indexOf(",");
    Serial.print(F("Delimiter Location : "));
    Serial.println(findDelimiter);
    Serial.println();
    Serial.flush();

    //print the data starting from zero to delimiter location
    Value = test.substring(0, findDelimiter);  //rtcSync          //wpControl
    Serial.print(F("Data Received      : "));
    Serial.println(Value);
    Serial.println();
    Serial.flush();
  }
  wdt.feed();
  if ( aTime > 3000 ) {
    Serial8.println("Start,End");
    aTime = 0;
  }
}

This is showing:
>>> Begin @setup()

1 Start,End

SerialData Received: Start,End

Delimiter Location : 5

Data Received : Start

1 Start,End

SerialData Received: Start,End

Delimiter Location : 5

Data Received : Start

1 Start,End

SerialData Received: Start,End

Delimiter Location : 5

Data Received : Start

// ...
 
My Teensy is connected only to a breadboard, with no wires attached. I'm just trying to test my Teensy board using 150mhz nonstop to monitor the internal temperature but I noticed yesterday it started to reboot non-stop.
 
Something odd for sure - nothing like that seen here at default 600 MHz - even without the recurring Serial8.print()'s in loop(). If not connected there should be nothing coming for Serial8.available() - unless it is picking up noise from the non functional breadboard?

If possible do the loopback as noted in p#2 connecting pins 34&35 and occasionally feeding Serial8.print()'s to capture that back as posted there.

The T_4.1 loop() will be running 5-10 or more Million times per second - not sure if the wdt.feed(); is handling that well? Some watchdogs panic if called too often (less than a certain time) as it suggests the code isn't running in a controlled fashion - though that doesn't seem to be the case here.

The p#2 output shown indicates "1" for serial8.available() because it triggers on the first input character. At 'slow' 9600 it takes over 10 ms to get the full 11 character print of the string in p#2 example. Just over 1ms per character - perhaps the Serial.setTimeout(100); could be reduced to "2" if that is specifying 100ms.

It is possible if there is noise sending phantom characters that the 100ms timeout is continuously getting characters within the 100ms and never returning and the watchdog is not being fed and causing a reset?

To see where the code might be Crashing add this to setup() after Serial.begin() and have SerMon online for sure to not have it skipped.
if ( Serial && CrashReport ) { // Make sure Serial is alive and there is a CrashReport stored. Serial.print(CrashReport); // Once called any crash data is cleared // In this case USB Serial is used - but any Stream capable output will work : SD Card or other UART Serial }
Not sure if that code reports watchdog triggered resets?
 
Hi sir thank you for your feedback, on my original program, i use Teensy's internal RTC, and every 5seconds, i feed the watchdog.

I will try your suggestion and post it here. Thank you very much
 
And if I may add, I use 150mhz to reduce the internal temperature. My project is to be installed outside, to monitor the weather condition in our Country (huge project for next year, using Teensy 4.1 if I can port all of my program from Arduino Mega to Teensy 4.1). Based on some documents, using 600mhz make teensy board last for around 3years and I want to avoid that 😅
 
A long shot, but maybe it is being impacted by the IO pins used for external memory on the bottom of the board.

That is the RX pin for Serial 8 (USART 5), can either be on pin 34 or on pin 48, which is one of the memory pins.

The Teensy startup code (starup.c) in the configure_external_ram() function configures this pad which is the chip select for the RAM
setup on bottom of board.
Code:
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_24 = 0x1B0F9; // 100K pullup, strong drive, max speed, hyst
    IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_24 = 8 | 0x10; // ALT1 = FLEXSPI2_A_SS0_B (RAM)
The code then tries to see if there is any memory mounted there...

Why I mention this as a long shot, the hardware setup for Serial8 has:
Code:
{{34,1, &IOMUXC_LPUART5_RX_SELECT_INPUT, 1}, {48, 2, &IOMUXC_LPUART5_RX_SELECT_INPUT, 0}},

This line says there are two possible RX pins as I mentioned, 34 which is our default (first item), and 41. But it also tells me,
that hardware wise, when Serial8 is enabled the default is pin 48. We do switch the input select to 1 during our Serial8.begin() call, but wondering if maybe a character made it in during the switch.

I probably simple work around is simply do:
Code:
Serial8.begin(9600);
while (Serial8.read() != -1) {}

Wondering if this was intended?
Serial8.begin(9600); Serial.setTimeout(100);
I am guessing you intended to do:
Code:
Serial8.setTimeout(100);
Without it I believe the timeout is one second.
 
Added this on two T_4.1's: {1 with and 1 without} PSRAM and there are no chars printed here - added in setup() to current p#2 code:
int c; while ( (c = Serial8.read()) != -1) { Serial.println(c, HEX); }

Wondering if this was intended?
I am guessing you intended to do:
Code:
Serial8.setTimeout(100);
Without it I believe the timeout is one second.
Funny - read right over that "missing 8" even though it was commented on.
So, if 1 second allows @danieltsz phantom chars to appear it could be sitting 'forever' as each 'phantom char' arrives?
The one second does delay the return of "test = Serial8.readString();" waiting for other chars to return even with wired jumper RX<>TX.
> that delay of 1000ms goes to 2ms with this long enough for a 9600 baud char to appear: Serial8.setTimeout(2);
 
Thank you very much for your feedback. Now I don't see any phantom data coming from Serial8, but is it possible to add this line of code after setting the Serial Hardware? Does it clear any data from Serial Hardware during setup()?
Code:
Serial8.begin(9600);
Serial8.setTimeout(2);

if(Serial8.available()>0){
Serial8.clear();
}
 
Not sure if it matters in this case, but there is a minor difference between using:
Code:
Serial8.clear();

and:
Code:
while (Serial.read() != -1) {}

The clear simply sets the head of the queue to the end of the queue:
C++:
void HardwareSerial::clear(void)
{
    // BUGBUG:: deal with FIFO
    rx_buffer_head_ = rx_buffer_tail_;
    if (rts_pin_baseReg_) rts_assert();
}

Where as the read loop, detects when the head==tail case and then check the hardware FIFO queue for any unread data and then reads the data out of the fifo. That was added later on, when people were running into issues where their last character was not available to read for one character period.
 
Back
Top