Question: Any changes for HW Serial LC in TD 1.54?

larry_berlin

Well-known member
Hello,

are there any changes for hardware serials in TD 1.54 to former versions? Arduino 1.8.15 is used.
Reason to ask is, when I compile a sketch in TD 1.54 the hw serial communiction to an external sensor doesn't work any more. Same sketch in former version of TD works (I still have the old hex file).
Uploading to the same hardware (with teensy LC) works. New compiled version doesn't work. No compiler errors so far.

I know forum rule, but can't post source, because to complex and not open to public.

Therefor this question. Maybe I can strip down an example sketch later on and post here to show the problem.

Meanwhile any ideas?
 
Sorry have no idea with so limited information.

So far the only thing I know is that some Hardware Serial does not work.
Might help to know additional things like:
What sensor?
What speed?
Which Hardware Serial?
How is it built?
Did you change any of the core files in previous releases.
What release did it work in?
...

Also does not work? Nothing sent? Nothing received back? Wrong Baud? You are trying to use RTS/CTS and not working? Anything special like Half Duplex?

Sorry I know that is not much help. But no idea on where to start looking.
 
I tested 1.54 just now with File > Examples > Teensy > USB_Serial > USBtoSerial and a FTDI TTL level USB serial cable connected to pins 0 & 1. Seems to work fine.

DSC_1546_web.jpg


I know forum rule, but can't post source, because to complex and not open to public.

If you want me (or anyone) to investigate, you really need to whittle your program down to a small & public program which demonstrates the problem.
 
Sorry have no idea with so limited information.

So far the only thing I know is that some Hardware Serial does not work.
Might help to know additional things like:
What sensor?
What speed?
Which Hardware Serial?
How is it built?
Did you change any of the core files in previous releases.
What release did it work in?
...

Also does not work? Nothing sent? Nothing received back? Wrong Baud? You are trying to use RTS/CTS and not working? Anything special like Half Duplex?

Sorry I know that is not much help. But no idea on where to start looking.

Thank you for care.
a few answers before I dig deeper and ty to present an example to demonstrate (hopefully today evening UTC+1)
- external gas sensor connected (can't deliver details)
- speed 19200 baud
- SERIAL1, but SERIAL2 and 3 has also to be examinated (also used in some cases)
- no changes in any core file from my site
- hex file wich works is dated 08/20/2020 I asume TD1.53 with Arduino 1.8.13
- no RTS/CTS
- no half duplex
- I use Serial1.flush() after Serial1.print(), might this be a problem?

Also today evening will also try to check RX and TX with a scope.
 
@KurtE
Sorry, I may be absolutly wrong regarding this, but I saw you provided half duplex support in September 2020 to hardwareserial, suspicious to me.
Can you please take a look on this if it is tested for T LC, and has no impact to older versions?

Thank you for your efforts.
 
I saw you provided half duplex support in September 2020 to hardwareserial, suspicious to me.
Can you please take a look on this if it is tested for T LC, and has no impact to older versions?

You said in msg #5 your use has "no half duplex". In msg #3, I tested the 1.54 with USBtoSerial example (which uses ordinary full duplex) on Teensy LC. I typed words in Arduino and clicked "Send" to see them appear in another terminal emulator window for the FTDI cable, and in that other window I typed and saw the characters appear in the Arduino Serial Monitor as I pressed each key. Is that not confirmation enough ordinary full duplex is indeed working?


- I use Serial1.flush() after Serial1.print(), might this be a problem?

I ran another quick test, using the same hardware as you can see in the photo on msg #3. Serial1.flush() appears to work fine.

screenshot.png
 
Last edited:
For one more quick Serial1.flush() test, I added digitalWrite to pin 13, to check whether it really is waiting until the last stop bit is transmitted.

Here's the code I ran:

Code:
void setup() {
  Serial1.begin(115200);
  pinMode(13, OUTPUT);
}

void loop() {
  static int count=0;
  digitalWrite(13, HIGH);
  Serial1.printf("count = %d\r\n", count++);
  Serial1.flush();
  digitalWrite(13, LOW);
  delay(250);
}

This is what my oscilloscope sees. The yellow trace is pin 13. Green is pin1 (TX1).

file.png

Every indication is Serial1 is working properly on Teensy LC.



Edit: here's the test setup on my workbench.

sc.jpg
 
Last edited:
@PaulStoffregen
first of all, thank you very much for the tests you have done.
I am still at work and have to my equipment at home no access, so will do the promised checks from my side this evening.
I don't say this problem must be affiliated to TD, but I try to solve it for my. The thing that makes me worry is same hardware works with old hex file and not with a new compiled.
 
If you believe the problem is with the serial code in Teensyduino 1.54, you need to craft a test program to demonstrate the problem. You may have indeed found an obscure bug. But as you can see in these tests, everything appears to be working properly. If it is a serial bug, the only way it's going to be found & fixed with with a reproducible test case.

Over and over again on this forum, we see reports like this which start with a conclusion that some particular thing is wrong, but eventually the cause of the problem turns out to be something completely different. We had one just a few days ago about the SD library supposedly not working with the Ethernet library with a W5500 ethernet shield. Indeed 1.54 completely replaced the old SD library with SdFat and a compatibility layer, so I wanted to get to the bottom of that problem. Turns out it wasn't the SD library at all, but a combination of issues with how HTTP connections are terminated (maybe only in the test program) *and* a flakey SD card. Two problems at once is so much more than merely twice as hard.

Often times we've seen tough problems where a buffer overflow or other memory corruption appears to manifest as a hardware serial problem, typically where variables used with the serial code get corrupted but any sign of trouble is delayed until much later when the serial interrupt code tries to use those variables. We've also occasionally seen issues, especially on Teensy LC, where stack usage was overflowing into memory used for variables, but there too the problems tend to manifest later and in different places depending on what other code uses the corrupted data. New libraries in 1.54 may be using more or less memory, causing the relative layout of variables and data to be different than with 1.53. I'm not saying I believe that may be the problem, only that we've seen this sort of thing before and in so many cases an initial hunch about what was the cause of the problem turned out to be the effect of a problem but not the cause.

We really do try to help on this forum. I and others often do run test programs and get to the bottom of bugs. But there's only so much that can be done by blind guesswork, and I believe we've done about as much of that as possible. It's really time for a small but complete program to demonstrate the problem.
 
@PaulStoffregen
you are right about everything you have written. Yesterday evening I wanted to get possible hints from the forum in order to be able to search more precisely today.

Tonight I tried to dig deeper into the problem. The following are the findings:

The problem in my code is on the receiving side of the UART (I connected a terminal program on the PC using an FDDI bridge). Unfortunately, I was unable to recreate the problem using a reduced sample code. Here is the sample code (for the sake of completeness) I used (not very elegant), but it works fine and I can't complain.

Code:
String inputbuffer = "";                       // Inputpuffer UART's

void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);                     // init Ausgang LED
  digitalWrite(LED_BUILTIN, LOW);                   // LED auf Board definitiv ausschalten 
  
  Serial.begin(9600);                               // init USB

  Serial1.begin(19200);                             // init 1. serielle HW-Schnittstelle 19200 baud, für O2-Sensor 1
  Serial1.setTimeout(60);                           // timeout für HW-UART setzen
}

void loop() {
  // put your main code here, to run repeatedly:
  char incommingbyte;
  
  delay(1000);
  Serial1.clear();                               // UART-Eingangspuffer sicher leeren
  Serial1.print(F("start\r"));                   // start
  Serial1.flush();

  digitalWrite(LED_BUILTIN, HIGH);                // show we expect input
  delay(6000);                                    // time to type on terminal max. 20 char
  digitalWrite(LED_BUILTIN, LOW);                 // input window ends

  inputbuffer = "";                              // Eingabestring auf init
    while (Serial1.available() > 0) {      // UART-Eingangspuffer auslesen bis <CR>
      incommingbyte = (char)Serial1.read();
      if (incommingbyte != '\r')  {
        inputbuffer += incommingbyte;     // Puffer aufbauen
        if (inputbuffer.length() > 20) { break; }  // Endlosschleife und Überlauf abfangen
      }
      else { break; }                              // aufhören wenn wenn <CR> erreicht ist
    }

  if (inputbuffer.length() > 0) {
    Serial.println(inputbuffer);              // give recieved string to serial monitor
  }

  delay(6000);                             // wait for next try
}


But what I found out is that there is a dependency between the optimization levels and the function of my code. If I compile with "Fast" my code no longer works, but if I compile with "Smallest Code" and my code works again like a miracle.

This is memory consumption with "Smallest Code":
Code:
Der Sketch verwendet 45060 Bytes (70%) des Programmspeicherplatzes. Das Maximum sind 63488 Bytes.
Globale Variablen verwenden 3884 Bytes (47%) des dynamischen Speichers, 4308 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.

This is memory consumption with "Fast" (but not working):
Code:
Der Sketch verwendet 54940 Bytes (86%) des Programmspeicherplatzes. Das Maximum sind 63488 Bytes.
Globale Variablen verwenden 5952 Bytes (72%) des dynamischen Speichers, 2240 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.

Unfortunately, it is beyond my knowledge to research more deeply into the causes.
 
When I compile it, i get completely different numbers for size:
Code:
Der Sketch verwendet 11032 Bytes (17%) des Programmspeicherplatzes. Das Maximum sind 63488 Bytes.
Globale Variablen verwenden 2064 Bytes (25%) des dynamischen Speichers, 6128 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.
So, whats wrong with your setup? Which USB mode do you use?
 
What means "does not work" exactly? Does it behave different? Or does it not work at all?

I do not receive anything on the UART, although it can be proven that it was sent.
Ich empfange nichts auf der UART, obwohl es nachweißlich abgesendet wurde.

When I read out the receive buffer, it appears empty (or possibly filled with non-printable characters), but correct characters have been sent.
Wenn ich den Empfangspuffer auslese, erscheint dieser leer (oder ist möglicherweise mit nicht druckbaren Zeichen gefüllt), es sind aber korrekte Zeichen gesendet worden.

So it does not crash, but returns incorrect reception values.
Es stürzt also nicht ab, sondern gibt falsche Empfangswerte zurück.
 
When I compile it, i get completely different numbers for size:
Code:
Der Sketch verwendet 11032 Bytes (17%) des Programmspeicherplatzes. Das Maximum sind 63488 Bytes.
Globale Variablen verwenden 2064 Bytes (25%) des dynamischen Speichers, 6128 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.
So, whats wrong with your setup? Which USB mode do you use?

Frank
the posted example code works and the memory values do not belong to this sketch, but to my "problem code", which I am not allowed to publish.
der gepostete Beispiecode funktionert und die Speicherwerte sind nicht zu diesen Sketch gehörig, sondern zu meinem "Problemcode", welchen ich nicht veröffentlichen darf.
 
No, there are commandline-tools - but they are not simple to use if you are not used to ..
DOn't know if it is a memory issue or not, but you must keep in mind that it needs stack too, and you don't see the stack usage in the summary. That's why I asked.
 
You did not mention that.
But ok, if it works now, everything is ok?

I did mention, but possibly it was not clear enough. English is not my mother tounge.
My code works with "Smallest Code" opt. level. For me okay so far, but it might be good to know the reason.
 
I'm confused. Does the code on msg #11 behave differently when compiled with different optimization? Or does that statement only apply to the large program we can't see?
 
He said "Unfortunately, I was unable to recreate the problem using a reduced sample code.".
So, I think the small programm works. (Have not tried it)
 
Ok. I'm not going to put more time into this (unless a reproducible test program is posted).

But I will quickly mention a common problem when code works with one optimization but fails with another is lack of "volatile" on variables which change, like anything shared between the main program and interrupts. As part of its optimization work, the compiler will often change the order which variables are written, or in some cases not even write them to memory at all in cases where nothing else to uses the data. The optimizer considers only the final result. When the order of steps matters, you need "volatile" on variables.

On Teensy 4.x, you also sometimes need "DSB" instructions, because the hardware also does these sorts of memory access optimizations. But with Teensy LC the memory access hardware is simple. Only the compiler adds quite a lot of complexity.
 
@PaulStoffregen
Thank you very much for your efforts in this case and in general for the teensy product family.
All hints are very much appreciated. My code really has 2 variables which are changed in interrupt service routines, but these are already declared as volatile.

Just for thought, in my non-working compiled code (option "Fast") there are 2240 bytes in RAM available for stack and heap. I have 2 strings with a maximum of 37 bytes each and do not call any further functions in functions (except functions from libraries) The libraries used are:
#include <ADC.h>
#include <Wire.h>
#include <avr / pgmspace.h>
#include <TeensyMAC.h>
#include <Snooze.h>
#include "MCP47X6.h"

I don't expect PJRC to invest time in research here, but another forum participant may want to question it.
 
Back
Top