-
Notifications
You must be signed in to change notification settings - Fork 7.6k
UART Performance issues with 2.0.2 version #6689
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
Comments
Hi, there were issues with SD card in 2.0.2. Please retest this with 2.0.3 which was just released. SD performance issues are fixed there. Thanks In general, there are not any performance issue in other parts you mentioned above (as far as we know) and 2.0.2 is out for quite some time. |
You haven't changed how Serial is handled for 2.0? Any other things I can look for for performance bottlenecks? |
Main difference from Arduino Core 1.0.6 (used in PIO 3.x) to Core 2.0.2 (used in PIO 4.x) is that most Peripherals were refactored to use IDF instead of reading/writing registers directly. Serial is based on IDF now, but I don't think it is a problem for performance. |
PIO is still pointing to arduino-esp32 v1.0.6 (very old). Jumping to 2.0.2 is a huge leap, and yes there were issues with SD card that were solved in 2.0.3. Serial did change but no known issues. Try 2.0.3. |
@handmade0octopus |
Thanks @SuGlider, any idea about increased heap usage? Do you know what sort of things changed in this regards? Does Arduino 2.0 uses any extra xTaskCreate for its internal use that I may stumble upon? |
Regarding Heap, we have changed a few configurations for WiFi in sdkconfig file. Look at #5474 (comment) to see a comparation: Arduino v1.0.6 (v3.3.5-1-g85c43024c) ==> Free memory: 213,900 bytes || Binary Size 692,190 bytes Comparing V2.0.0 with V2.0.1, this sketch has about 74K extra heap and takes about 90K less flash with the compiled binary. |
@SuGlider I really try to port my code but its getting harder every second I look. SD.remove() API has been changed and it requires new things now, I cant use my wifi portal (this may be due to SD card issues). The heap problem was with the Wifi off (not initiated at all) with wifi on usage is similair fortunately but it doesn't work. Is there a full list of functions that has been affected so I can go through and fit them? Even some things doesn't display right (one of my lcd.println(string) is affected - but only single one..). Sorry for my frustration but it seems I am stuck with very old version as trying to find all bugs that update caused it's not feasible. I understand you had to make some changes to make it easy to port to new IDF versions but it's so strange all the performance issues are worse (can't use 2.0.3 for now so I can't check). Also I found the issue I had with large flash size - it was BluetoothSerial.h - once I commented it out flash size was exactly the same. |
@handmade0octopus Just go ahead with 2.0.3. And yes, all the changes are listed in particular releases. Edit: What is the reason you cannot used 2.0.3? Or at least 2.0.2 with manually check out SD fixes? |
@VojtechBartoska PlatformioIO doesn't support it yet. Please don't make out of me chooser beggar, I understand how it sounds. I am more than thankful for all hard work you guys do. I am just trying to use it and it saddens me seeing I have to rewrite code I worked for over 2 years on. SD card isn't the only problem I have, there are many, many more I listed above. I don't know if changing approach on Serial will cause my program to work better, I think those simple read() commands should work as fast as any other - especially that I guard them with Serial.available() everywhere - this just doesn't make any sense to me sorry. |
I'm not expert on PIO, but it seems that there may be a way to setup 2.0.3 in PIO. Check these links: |
@handmade0octopus Welcome to changing major rev numbers (1.X -> 2.X). Before you get too far, I recommend starting a completely separate project. That way you can start with a working base and slowly bring over functionality. Oh and use a VCS system to checkpoint your project. Github Desktop has been handy for me. As a developer I've had to do that several times with various projects. Expect 1 to 2 weeks of work porting it. Or you can stick with 1.0.6. Your choice. |
@handmade0octopus You can use the release 2.0.3 with Platformio.
|
This doesn't work unfortunately. Still loads 2.0.2.
Of course I am prepared to do that, but first I need to understand why my current Serial.available() in a loop and normal writing and reading is not performing as it should. Weather it is something to do with how it is structured or some internal timings. I am just afraid that I will spend those 2 weeks porting it and issue is still persistent. |
Can you give us more information about what you said that available/read/write are not performing as expected? |
You are missing an 's' in platform_packages The correct way would be:
|
@gonzabrusco thanks it worked. But found issue:
Had to change: explicit String(float, unsigned int decimalPlaces = 2);
explicit String(double, unsigned int decimalPlaces = 2); To: explicit String(float, unsigned char decimalPlaces = 2);
explicit String(double, unsigned char decimalPlaces = 2); In WString.h and .cpp or cast second parameter as (uint32_t).. Potential wrapper using old method just calling new ones? Something to consider! I like speed of SD card now, it's faster than before, WiFi connects faster. Still VERY HIGH usage of heap and serial is performing badly. I disabled GPS and it's not issue with it, it has to do something with how I handle LIN connection. I would also reconsider how SD "remove" is handled as "SD.remove(file.name())" doesn't work anymore but leaves people without clue, I would add "change .name() to .path()" in debug messages as people can go around in circles by trying to solve it. Regarding serial I believe it has something to do with .available() method (or how it blocks thread), Ill run some tests and let you know. |
In project Tasmota we migrated since 2.0 alpha was out. Migrating the code from 1.0.x core to 2.0.x gave us better performance and MORE free heap and less flash usage. Migrating was sometimes a pain, using a alpha version... Imho you have librarys or/and in your code stuff which needs to be adopted to work (nice) with 2.0.3. |
Ok I investigated UART thing a little. I will try to explain it to you in minimal simplified code - basically I run a task inside a loop: // serial == Serial2.begin(9600, SERIAL_8E2);
xTaskCreatePinnedToCore(
serialTask,
"serialTask",
8192,
(void*) 0,
8, // I set different priority - no change
NULL,
0); // I set different cores - no change
uint8_t hexAddress[255];
uint8_t response[255];
void serialTask(void* param) {
while(1){
ds2.sendCommand(hexAddress);
uint32_t readResponse = ds2.receiveData(response);
if(readResponse) {
// do stuff
}
delay(1);
}
}
uint8_t DS2::sendCommand(uint8_t command[], uint8_t respLen) {
if(messageSend) {
return 0;
} else {
if(respLen != 0) responseLength = respLen;
timeStamp = millis();
messageSend = true;
respLen= serial.write(data, respLen);
serial.flush(); // Commenting flush off actually improves performance!
return respLen;
}
}
uint8_t DS2::receiveData(uint8_t data[]) {
log_e("Time: %d", millis() - timeStamp); // Here I log what I got below <===
if(messageSend) {
if(readData(data)) {
messageSend = false;
return true;
}
}
return false;
}
boolean DS2::readData(uint8_t data[]) {
uint32_t startTime = millis();
uint8_t availible = serial.available();
if(availible > 2) {
// do stuff
return true;
}
return false;
} I made this simple test setup. Basically on version 1.0.5 I test I have very consistent:
And on 2.0.3 I have:
And if I remove flush() after write it gets even funnier! On 1.0.5 consistent:
On 2.0.3 though:
Hope that helps you to try to tell me to what test next.. To be honest I am lost completely. Looks like new version sends (or receives) data much slower and can't cope with changing serial that fast. |
I think you already know it, but About the performance, I'll test it soon. Arduino Corte Versions 1.0.6 or lower goes directly to the SoC Registers and ISRs. Thus, it may have a faster response. But we have a special API for faster reading/response UART: It will require a change on the logic of your application, but I think it will get the same performance as before. |
Can you roughly explain how is onReceive triggered? Is it triggered when available is bigger than 1? Does it happen on separate thread or its blocking? I will try to write code but it would be useful how should I handle it for my application. Will test and let you know. |
When data arrives to UART, an ISR adds it to the internal RX buffer. The timeout, in Symbols, can be set by Alternatively, if UART receives a stream of data (no pause, no timeout), it will also trigger it for every 120 bytes.
No. It is not triggered based on
non-blocking - asynchronous to Arduino main task execution. List of PRs with information and examples:
OK. Thanks. |
@SuGlider rewriting code soon. Last question, can I use delays and/or semaphores in onReceive()? |
Adding this to 2.0.4 Milestone, when it's released this issue can be retested and probably closed. |
@SuGlider @VojtechBartoska good news. Finally been able to test it (been on holiday). Long story short - onReceive() gave 0 performance increase. But I found that using So you can still use polling with this setup very well. My advice would be to set RX timeout to 1 by default so users can port their code without need of debugging what is going wrong? Heap usage is still big, 50kb is lost somewhere. Also, is there any #define where I can check for arduino version? |
performance issuse with new Arduino version if Webpage is open, image transfer is slow, not Wifi but SD or SD_MMC espressif/arduino-esp32#6689
Interesting... this issue with heap has been fixed a while ago. I think that PIO may not be using the same pre-compiled libraries and compiling options that Arduino IDE uses. |
PIO does use the same pre-compiled libraries. If in doubt the release 2.0.3 from here can be used with the following setup.
|
@Jason2866 I used most recent version using:
So I don't think this is the issue. @SuGlider I could potentially give you access to my private repo so you can download and build beta branch but I would have to trust you that you won't:
|
Wow, I prefer not to have access to private code or sensitive information. Thanks for the trust!
Never! :-) Anyway, I undesrtand that the issue is solved. It that right? |
@SuGlider I plan to release this code MIT at some point in the future so it's not that bad. Also you have your linkedin linked to your github so not hard to find you! Also every code is open source if you know assembler! :D Yes serial issue is fixed, I will keep an eye on heap usage. Is there a chance you could show me how to get certain arduino versions like in example above?
Where to get this number after hash? I want to test different versions to test heap usage, maybe this way I could find version where issues started. Also do I understand correctly |
That number is a github commit number. If you go to the releases page, you will see the 7-digit commit number in the left column under the tag string. Click on it, and you will see the full number (which starts with those 7 digits) in the right side at the top. |
:-) Great!
Happy to know that.
I'm not expert in PIO, but I can tell you that Position the mouse over that link and you will see the full hash number.
|
@SuGlider I meant if value of |
I see. I remember that IDF sets it to 10, for some reason... |
@handmade0octopus @gonzabrusco Please let me know your point of view about this change. Thanks. |
Ok I am doing tests of different versions:
Hard to test as one commit downloads like 1h due to low speed (around 500 kb/s) @SuGlider I have question though, is new Arduino version more optimised for uint32_t size to have faster memory access? If so I can live with this 50 KB of more usage. But is it so? Should we open another issue for this? Not sure how to best use Github. |
No problem for me if the Arduino behaviour stays the same and the setRxTimeout keeps working (I set the timeout to 3 characters for modbus). Just one note, one time I tried setting the timeout to 1 character and I noticed A LOT of false triggers of the callback. With a symbol time of 2 it stopped happening. Maybe at 1 it gets TOO sentitive... not sure if it's the safest default value. |
We have done a few updates to UART in the new Arduino Core 2.0.5 version.
|
A few notes:
Please read this post: #6921 (comment) |
Board
Not board specific
Device Description
Not board specific
Hardware Configuration
Not board specific
Version
v2.0.2
IDE Name
PlatformIO 4.2.0
Operating System
Windows 10
Flash frequency
80MHz
PSRAM enabled
no
Upload speed
921600
Description
I have been using Platformio 3.5.0 without any issues for very long time.
I tried to moving on to version 4.2.0 based off 2.0.2 but it seems it has lots of underlying problems or it requires me to rewrite most of my code.
I can't share all of it as its quite advanced, instead I will provide you with few insights and code that had dramatic performance issues. I run all code on mostly tasks with priority 4-8 and less important ones being on 3 and 2.
Top is version 3.5.0 of Platformio (I don't know exactly which Arduino version it's based off - sorry).

Bottom is version 4.2.0
Note - I left device to run for 5 minutes to make sure test is fair.
Displays are as follows (starting from left top corner):
Log speed - is .CSV logging appending the file with ~30 parameters, speed is in rows/second - as you can see on 3.5.0 it was stable and flat and it's jittery on new version (but it does keep up.
Max heap - I wouldn't worry about this one, but we can see change in max heap and it's much smaller than on previous version.
RPS - it's "responses per second" - basically I use single wire serial connection (LIN type) to gather data from old typ ECU, here my performance is most important and as you can see it doesn't keep up with it. Maybe my code here is wrong as it's very complicated to provide great stability, but I have been using this one for few years and never has issues before.
It's worth mentioning I am using GPS at 5Hz data rate constantly sending data to my second Serial input.
But the worst offender of all is the part of sketch below that I use to transfer data from/to SD card. Below is snippet of function I use to get those performance stats:
Before I managed to get constantly around 71 ms:
But now it's not even funny:
I think SD card handling may have changed so some sort of guide of how to move to new type of handling files would be appreciated.
Sketch
Debug Message
Now on 4.2.0:
The text was updated successfully, but these errors were encountered: