-
Notifications
You must be signed in to change notification settings - Fork 7.5k
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
ESP32C3M1: Serial.print() calls when not connected to USB cause delays. #6983
Comments
Issue confirmed. I Can see the issue using a ESP32-C3 DevKitM-1 v1.0. Note:I see that the issue occurs even with the USB plugged in, but the IDE Monitor is on the UART port instrad of on the CDC, as we can see in the UART output. When the USB CDC Port isn't open, the issue occurs, independently is the USB is plugged or not. If the skecth is uploaded with This makes it clear that USB CDC has some issue when its buffer gets full and it is still closed or unplugged. This is the sketch used: #include <Wire.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 8 //6
#define NEOPIXEL_PIN LED_PIN
Adafruit_NeoPixel pixels(1, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial0.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
uint32_t now = millis();
Serial.print("Red... ");
// drawMessage("Test Red LED");
pixels.setPixelColor(0, pixels.Color(64, 0, 0));
pixels.show();
delay(500);
Serial.print("Green... ");
// drawMessage("Test Green LED");
pixels.setPixelColor(0, pixels.Color(0, 64, 0));
pixels.show();
delay(500);
Serial.print("Blue... ");
// drawMessage("Test Blue LED");
pixels.setPixelColor(0, pixels.Color(0, 0, 64));
pixels.show();
delay(500);
Serial.print("White... ");
// drawMessage("Test Whitish LED");
pixels.setPixelColor(0, pixels.Color(64, 64, 64));
pixels.show();
delay(500);
Serial.print("Off... ");
pixels.clear();
pixels.show();
delay(500);
Serial.println("Done. Looping");
Serial0.printf("\n========================\nLoop time = %d\n", millis()-now);
} UART OUPUT:
|
The delay comes from the timeout here (I think) To (temporarily) solve the problem we could use a check whether the USB is connected or not before every write to the USB... To fix it even more temporarily you could use |
What do we think a good solution would be? In my own code I attempted using
which I thought would prevent the timeout (with the possible exception of a print in progress during disconnect, and/or log statements I have no control over). Reading In general doing a good race-free job of quickly skipping writes when nothing is reading them (but blocking when something is) seems a bit tricky? |
On Sep 6, 2022, at 10:32 PM, Daniel Egnor ***@***.***> wrote:
In general doing a good race-free job of quickly skipping writes when nothing is reading them (but blocking when something is) seems a bit tricky?
I noticed this issue right away with my C3Mini custom board. I've never noticed it with any other ESP32 or Arduino. I assume that there is a fix that works for all those.
My problem is that I can easily prevent the calling of Serial.print() in my code. But I have little control over all the libraries that do a lot of printing directly. This makes my program run quickly when attached to a Serial Monitor and over a minute slower, when not attached.
|
Anything with an offboard USB-serial converter won't have the problem, and something like the SAMD51 will be a completely different driver stack. As far as I can tell, all ESP32s which use the hardware USB-CDC implementation (as opposed to software USB -- but see #6762 (comment)) will use the same code and presumably have the same problem? I actually recall having a similar problem with the SAMD51 and fixing it with judicious
Agreed, the ESP32 ecosystem encourages subsystem logging. Which normally I enjoy! But not here. Would something like |
There is no API to know that the C3 is plugged or not to the USB. It must be implemented in order to solve this issue. |
My ideal general-purpose console interface (as opposed to using a serial port for structured data transfer) would do this:
The first two can be achieved with the existing interface, the others would require some work or a wrapper of some kind. |
At this point in time, Arduino only can tell when USB is just plugged and also replugged by using Events. This limitation is in Hardware Level and for its register. Therefore, IDF can't help. |
That's indeed my current workaround but it's not great in a lot of cases because if the buffer fills during normal operation it drops everything. If you happen to have a burst of printout, it gets truncated, which can be very confusing to see in the output. (Also if two threads try to use the port at the same time-- more common than one might think due to logging from worker threads-- it completely skips the second write, since the timeout applies to mutex acquisition as well as buffer writing.)
[edit] I see. From the technical reference: I actually think a reasonable timeout on USB buffer retrieval (which could be fairly short) would be more effective than a timeout on FIFO insertion. The USB-level timeout would detect port disconnect/closure/backpressure fairly quickly, at which point all FIFO data could be discarded until the buffer is finally emptied or the port reconnected. FIFO level timeouts have the problem that they trigger either on USB disconnect/closure/backpressure or the FIFO filling from a burst write, even if USB is working perfectly. FIFO level timeouts also need to re-timeout for every write operation. FIFO level timeouts also have no obvious correct timeout level, since it depends on how much is being written. There might still be some issues coming up with the appropriate USB-level timeout, but it would certainly be an improvement. (Obviously, implementing this would be a bunch of work, so I'm not complaining that it's not top priority... and indeed a drop-everything timeout works for most general-console-logging cases... I still want my "*** X lines lost ***" message but I also want a pony and world peace so what/ever!) |
Yes, I agree it is not great, but even when it is plugged and the buffer is full, after the time out, it also drops all data. |
If necessary, it is possible to change RX or TX Buffer sizes. Default size for both is 256 bytes. @egnor - The current Arduino driver already uses a software Rx/Tx buffer that is used to send/get data to/from USB CDC based on Interrupts generated by USB EndPoints. Therefore, the timeout is used to read/write from/to theses buffers. |
|
Do you mean And
This is specifically the timeout writing the FIFO, not USB RX and TX. (It's also used for some lock acquisition but I think that's incidental here.) Am I misreading the code? Or looking at the wrong code? |
USB ISR will read asynchronously TX Buffer as it transmits the data, thus, the time out may help the buffering writing process, while it is done by Arduino or other task. |
@mahboud - Please let me know if we can close this issue, once the specific solution to the issue you proposed is in |
I'll give that a try later today.
My custom boards, in production use, are never connected to USB (serial). They are only charged via USB. That's why having long delays added when USB serial isn't connected makes my device unusable. Removing the timeout may help. It may even be better if I could turn off Serial completely.
Let me ask this: do the ESP_LOGE() and similar calls also go through the same path as Serial.print()? Some of the libraries I use call ESP_LOGE() and ESP_DRAM_LOGE().
mahboud
… On Sep 8, 2022, at 6:54 PM, Rodrigo Garcia ***@***.***> wrote:
@mahboud <https://github.com/mahboud> - Please let me know if we can close this issue, once the specific solution to the issue you proposed is in
#6983 (comment) <#6983 (comment)>
—
Reply to this email directly, view it on GitHub <#6983 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAM4MB75FAWQXMQWIGXZJHDV5KKDZANCNFSM53RFG5UQ>.
You are receiving this because you were mentioned.
|
It is possible. Do you build your application using Arduino IDE? There is an option in the IDE to turn off USB CDC.
No. ESP_LOGE()/ESP_DRAM_LOGE() are IDF calls that use other method. |
Are you sure? I thought this code redefined arduino-esp32/cores/esp32/esp32-hal-log.h Line 209 in 37cbaec
Note that you can turn off debug logging to the serial console with |
Both
Serial.setDebugOutput(false);
and
Serial.setTxTimeoutMs(0);
Work well to remove the delay I was experiencing. Thank you.
… On Sep 8, 2022, at 6:54 PM, Rodrigo Garcia ***@***.***> wrote:
@mahboud - Please let me know if we can close this issue, once the specific solution to the issue you proposed is in
#6983 (comment)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.
|
Same issue on the S3 |
Confirmed on S3. |
the T-DisplayS3 from TTGO. |
Should be possible to monitor the 5V line to detect if there is a USB connection if running from a LiPo battery. |
As said in #6983 (comment), a workaround is to do this: void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.setTxTimeoutMs(0); // <<<====== solves this issue of delay
} |
Hi |
If someone sees similar behavior while sending ESP Now messages, this could well be the culprit. I just managed to increase message throughput from 3 per second to 850 per second just by applying the suggested work-around. |
Hi, did you manage to solve your problem? I tried with both USB-OTG and Hardware CDC USB modes. @SuGlider Are you familiar with the issue I'm describing? |
Board
ESP32C3M1
Device Description
Custom board:
Hardware Configuration
GPIO 18 & 19 are connected to USB. USB is used to program the device and to monitor Serial.print output.
Version
v2.0.3
IDE Name
Arduino
Operating System
MacOS 10.15.7
Flash frequency
40Mhz
PSRAM enabled
yes
Upload speed
115200
Description
USB is used to program the device and to monitor Serial.print output. However, when the device is unplugged, and the Serial.print() lines are left in the code, they cause delays of a second or so. Plugging back in will make the delays go away. If I remove the Serial.print() lines, it makes the delays disappear too.
Sketch
Debug Message
Other Steps to Reproduce
Run the sketch. While the device is plugged into a computer with Arduino, the lights flash faster. When you unplug the USB cable the lights slow down.
With more or longer Serial.print output, the delay can be more than a second.
That same code above is running on the two boards in this video. When you plug the USB in, you can see that the flash rate increases on the one plugged in.
IMG_7923.mov
I have checked existing issues, online documentation and the Troubleshooting Guide
The text was updated successfully, but these errors were encountered: