New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
USB serial repeated write calls cause race condition with autoflush #583
Comments
Please confirm if the issue still happens on Teensyduino 1.54 ? If so, can you give me a complete program I can copy into the Arduino IDE to quickly reproduce the bug without guesswork? |
This program appears to demonstrate the bug I experienced. The output is erratic when the delay is set to 73us ( void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
char msg[] = "abcdefghijklmnopqrstuvwxyz";
int count = 0;
while (count<20) {
Serial.write(msg+count, 5);
delayMicroseconds(73);
count++;
}
Serial.println();
delay(250);
} I can verify this is an issue in 1.54 in the next few days, but seeing that usb_serial.c is the same between versions I suspect the bug is still there. |
I can confirm this. On Windows, output of serial monitor is:
|
Tried with Coolterm. Same issue, so it is not TD serial monitor related. |
If i add some DSB to schedule transfer and move the interrupt disable to the beginning, it changes its behavior: Unfortunately, i have to pause now, can't dig deeper for today. |
output, then:
|
I’m not sure if it’s related to this or not, but I ran into a similar issue just yesterday when using Serial.write and I wasn’t sure if it was just my setup or not. While trying to emulate a 9 byte protocol I noticed that the receiving application started getting extra bytes from seemingly nowhere thus shifting the 9 byte protocol by one or several bytes. Eventually it would add enough phantom bytes to wrap around back to valid data and the cycle would repeat itself. |
Paul, I assume you can use a hardware debugger. Sometimes flash content is output to serial (wrong pointer). It should be easy / possible with a debugger to find the location where an address is assigned from the flash. |
With this program, you can see easyly what happens:
|
A working fix is to replace timer_start_oneshot(); with usb_serial_flush_output(); in usb_serial_write() I know that's not ideal and not wanted.. but it may help to find the problem. |
I am worried this fix may create new problems. It leaves tx_noautoflush set while waiting for buffers, even through a yield() call. |
Yup , I thought about yield, too. Perhaps switch autoflush on for yield? |
At least it shows what the problem is. |
Does setting it at the first line inside the loop, and clearing it right before calling yield() still fix the problem? |
Tried that. Autoflush needs be disabled for the transmit after the inner while loop, too. so, disabling again after the inner while loop works. |
Eh,. No. After >50 lines i see still garbage. |
Please try with demo from here: #583 (comment) |
This works:
|
I've committed a fix. Please let me know if this fully solves all the problems you're seeing? |
Thanks for the quick responses -- I will not be able to test this fix until after the weekend but will update you then |
Looks good now. |
I've seen the random Windows memory bug a couple times too. Kinda makes me wonder if we've stumbled upon a security vulnerability in Windows? |
Me too. But so far it appears to me it prints memory contents of the current program only. |
It hasn't fixed my issue, but I believe it's more so a problem with how I'm interfacing to the receiving application than anything else. I'm using dual serial, so one is open in Teensyduino and the other is routed through Parallels Desktop to a serial port on a Windows virtual machine. The serial port is then opened in Trinamics TMCL-IDE, I haven't experienced this before so more than likely it's a product of the routing. |
The fix appears to have solved the original issue I was seeing. Thanks to everyone here for helping address it so quickly! |
When repeatedly calling
Serial.write()
at an interval close toTRANSMIT_FLUSH_TIMEOUT
, I've found that messages are occasionally lost and phantom bytes are transmitted in their place. These bytes are always a subset of bytes sent in a previous transmission.I believe that the autoflush is triggering in the middle of
Serial.write()
. This would causetx_head
(inusb_serial.c
) in to be incremented as new bytes are being written to the old buffer, and on the next autoflush, garbage data from the new buffer is sent instead.I have not had the time to replicate this issue in a simpler program, but have worked around it by calling the following prior to calling
Serial.write()
to kill the autoflush timer. The delay was necessary otherwise the timer would still occasionally interrupt after having calledSerial.write()
.Issue occurred on a Teensy 4.1 running Teensyduino 1.53.
The text was updated successfully, but these errors were encountered: