ARDUINO multi-core support/questions
-
- Posts: 35
- Joined: Sun May 20, 2018 9:16 pm
ARDUINO multi-core support/questions
Hi,
I've been working on a project where a number of network and realtime things are going on and sometimes seem to be interfering with each other.
ON ARDUINO
1. If you don't do anything, are tasks automatically getting executed on both cores, switching between them as time is available or are some things assigned to specific cores when they are created?
2. Is there a way to get a list of all tasks and priorities? I tried some of the freeRTOS calls a few months ago but none of them would compile in Arduino. Has this changed or is there a trick to getting it to work on arduino? I suspect some background tasks have the wrong priorities.
3. Is there a way to get the network stuff (WiFi, Bluetooth) running on one core and your arduino code on another?
4. If you setup your own tasks on timers and have loop() empty, is there a way to lower the priority of loop() so it only runs when nothing else is?
I'm doing some experiments with xTaskCreatePinnedToCore but without some way to see the priorities of all the background tasks it's hard to tune the code.
I've been working on a project where a number of network and realtime things are going on and sometimes seem to be interfering with each other.
ON ARDUINO
1. If you don't do anything, are tasks automatically getting executed on both cores, switching between them as time is available or are some things assigned to specific cores when they are created?
2. Is there a way to get a list of all tasks and priorities? I tried some of the freeRTOS calls a few months ago but none of them would compile in Arduino. Has this changed or is there a trick to getting it to work on arduino? I suspect some background tasks have the wrong priorities.
3. Is there a way to get the network stuff (WiFi, Bluetooth) running on one core and your arduino code on another?
4. If you setup your own tasks on timers and have loop() empty, is there a way to lower the priority of loop() so it only runs when nothing else is?
I'm doing some experiments with xTaskCreatePinnedToCore but without some way to see the priorities of all the background tasks it's hard to tune the code.
Re: ARDUINO multi-core support/questions
Howdy Greg,
It seems to me that you are progressing past the Arduino layer into native ESP-IDF. If it were me, I'd probably look at writing native ESP-IDF applications. Do realize that the Arduino APIs can still be leveraged in an ESP-IDF based app by using the Arduino as an ESP-IDF component.
It seems to me that you are progressing past the Arduino layer into native ESP-IDF. If it were me, I'd probably look at writing native ESP-IDF applications. Do realize that the Arduino APIs can still be leveraged in an ESP-IDF based app by using the Arduino as an ESP-IDF component.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
-
- Posts: 35
- Joined: Sun May 20, 2018 9:16 pm
Re: ARDUINO multi-core support/questions
Hi kolban,
I plan to dump arduino at sometime in the near future, but for the moment I am on Arduino because the code I have needs to run on some other arduino platforms for a bit longer.
Also right now I'm using www.blynk.cc as an app-based controller and I don't think it can run on the native IDF.
I'm actually working on a replacement for blynk as well as phasing out other arduino platforms on my project, so I hope to be able to switch to the native platform soon.
Also, I have to make sure all the code is debugged and reasonably stable before porting it, so I have to stay on Arduino till that's done.
I plan to dump arduino at sometime in the near future, but for the moment I am on Arduino because the code I have needs to run on some other arduino platforms for a bit longer.
Also right now I'm using www.blynk.cc as an app-based controller and I don't think it can run on the native IDF.
I'm actually working on a replacement for blynk as well as phasing out other arduino platforms on my project, so I hope to be able to switch to the native platform soon.
Also, I have to make sure all the code is debugged and reasonably stable before porting it, so I have to stay on Arduino till that's done.
Re: ARDUINO multi-core support/questions
I am on vacation so dont have my code or pc with me, but you all wifi are running on one core and arduino code on the other core by default, there is a function call to see which core the current function is running on, you can also write functions to run on a specific core.
Re: ARDUINO multi-core support/questions
Working with arduino-esp32 is similar to working with esp-idf because are used pre-compiled esp-idf libraries, so you can assume few things:
1. all tasks are working the same way like in freeRTOS,
2. setup and loop are functions in looper task where setup is called only one time and then loop is called in while(1) loop; now answering point 4 you can choose 2 paths:
- prepare all your variables and create tasks you need in setup and at the end in setup just delete this task since you dont need it and you can free about 7kB heap (vTaskDelete(NULL)), or:
- prepare all your variables and create tasks you need with priority 6+ in setup and in loop add some delay, this way IDLE task its job.
You can create only one task in setup and other tasks you need you can create whenever you need it.
3. im not 100% sure, but you can easy assume that wifi and bt tasks are running on core 0 and looper task (loop) is running on core 1, why? because devs working on API for esp32, in this case me-no-dev which is maintaining arduino-esp32, are good programmers and follow most the time some paths; since wifi and bt by default are running on core 0 in esp-idf i dont see logic that would make them to change it in arduino
4. when i have to debug tasks information i like to pick at this code, here is all i need:
https://github.com/nkolban/ESP32_Explor ... M_JSON.cpp
You can even compile and see how it works (just im not sure if it still works with master esp-idf):
1. all tasks are working the same way like in freeRTOS,
2. setup and loop are functions in looper task where setup is called only one time and then loop is called in while(1) loop; now answering point 4 you can choose 2 paths:
- prepare all your variables and create tasks you need in setup and at the end in setup just delete this task since you dont need it and you can free about 7kB heap (vTaskDelete(NULL)), or:
- prepare all your variables and create tasks you need with priority 6+ in setup and in loop add some delay, this way IDLE task its job.
You can create only one task in setup and other tasks you need you can create whenever you need it.
3. im not 100% sure, but you can easy assume that wifi and bt tasks are running on core 0 and looper task (loop) is running on core 1, why? because devs working on API for esp32, in this case me-no-dev which is maintaining arduino-esp32, are good programmers and follow most the time some paths; since wifi and bt by default are running on core 0 in esp-idf i dont see logic that would make them to change it in arduino
4. when i have to debug tasks information i like to pick at this code, here is all i need:
https://github.com/nkolban/ESP32_Explor ... M_JSON.cpp
You can even compile and see how it works (just im not sure if it still works with master esp-idf):
-
- Posts: 35
- Joined: Sun May 20, 2018 9:16 pm
Re: ARDUINO multi-core support/questions
Hi chegewara,
Thanks for the useful information!
There's a couple of weird things I'm trying to figure out, mostly related to networking. My Arduino code has loop() running on a strict schedule of 100hz where it reads the current time and returns if it's not time to run. Inside loop() it does about 4ms of processing including calling blynk (see https://www.blynk.cc/) so there is about 6ms of unused time every loop. Here's the weird stuff.
1. when sending 130 bytes of data out TCP 100 times a second, I see occasional stalls in the data of up to a second followed by data bursts of several thousand bytes on wireshark. According to wireshark there are no transmission errors and no flow control going on. Seems like the ESP32 just stops sending for a bit and then starts back up. If TCP is running on core 0 and my code (including blynk) is on core 1, why would this happen?
2. In a really small test program, I find that I can send data out bluetooth serial (130 bytes, 100 times a second) and it comes through to my PC very fast and steady. However if I start up blynk, the bluetooth serial starts to stutter and slows way down. Not sure why this would happen if bluetooth is on one core and blynk is on the other.
As far as I know, blynk doesn't use any FreeRTOS calls when setting up it's timers and other tasks, which I assume would put all its tasks on core 1?
It would be a big help if there was a way to get a task list when the ESP32 is running arduino.
Thanks for the useful information!
There's a couple of weird things I'm trying to figure out, mostly related to networking. My Arduino code has loop() running on a strict schedule of 100hz where it reads the current time and returns if it's not time to run. Inside loop() it does about 4ms of processing including calling blynk (see https://www.blynk.cc/) so there is about 6ms of unused time every loop. Here's the weird stuff.
1. when sending 130 bytes of data out TCP 100 times a second, I see occasional stalls in the data of up to a second followed by data bursts of several thousand bytes on wireshark. According to wireshark there are no transmission errors and no flow control going on. Seems like the ESP32 just stops sending for a bit and then starts back up. If TCP is running on core 0 and my code (including blynk) is on core 1, why would this happen?
2. In a really small test program, I find that I can send data out bluetooth serial (130 bytes, 100 times a second) and it comes through to my PC very fast and steady. However if I start up blynk, the bluetooth serial starts to stutter and slows way down. Not sure why this would happen if bluetooth is on one core and blynk is on the other.
As far as I know, blynk doesn't use any FreeRTOS calls when setting up it's timers and other tasks, which I assume would put all its tasks on core 1?
It would be a big help if there was a way to get a task list when the ESP32 is running arduino.
-
- Posts: 35
- Joined: Sun May 20, 2018 9:16 pm
Re: ARDUINO multi-core support/questions
P.S. Is there an arduino accessable FreeRTOS call to just sleep the current task for some number of miliseconds?
After seeing how loop() is implemented, it's always in an endless loop that the OS is going to have to preempt to let other tasks run. Seems like it would be good to actually suspend the loop task when I don't need it to be doing anything.
After seeing how loop() is implemented, it's always in an endless loop that the OS is going to have to preempt to let other tasks run. Seems like it would be good to actually suspend the loop task when I don't need it to be doing anything.
Re: ARDUINO multi-core support/questions
Would the Arduino API delay() function not do what we want?
https://www.arduino.cc/reference/en/lan ... ime/delay/
https://www.arduino.cc/reference/en/lan ... ime/delay/
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
-
- Posts: 35
- Joined: Sun May 20, 2018 9:16 pm
Re: ARDUINO multi-core support/questions
delay() is not good for this purpose because it's a blocking delay. I haven't checked the implementation but I believe it just spins in a loop till the delay is over, so it's actually burning cpu cycles meaning that the RTOS has to pre-empt the task to do something else. In other words, the RTOS thinks the loop task is doing something, so it is required to give it CPU time to run and pre-empt it when an equal or higher priority task needs to run.
Also, if you were using delay() or some other blocking method and loop() task priority was set high, it's possible that no other task would get to run. Not sure about FreeRTOS but a lot of RTOS I've worked with will not preempt a high priority task to run a low one (probably why in arduino the loop task is set to priority 1)
What we really want to do is tell the RTOS "this task can be completely suspended for X miliseconds" so instead of burning CPU time spinning in a delay loop, the cycles are given to all the other tasks.
I did some messing with vTaskDelay() and it appears to actually suspend the task, vTaskDelayUntil I haven't tried but it should let you program a task to execute on a specific schedule.
It looks like the "tick" these functions use is 1ms on the ESP32, so you can only schedule in increments of 1ms, not sure how much "wobble" there is in the resume time. I'm going to do some testing.
Also, if you were using delay() or some other blocking method and loop() task priority was set high, it's possible that no other task would get to run. Not sure about FreeRTOS but a lot of RTOS I've worked with will not preempt a high priority task to run a low one (probably why in arduino the loop task is set to priority 1)
What we really want to do is tell the RTOS "this task can be completely suspended for X miliseconds" so instead of burning CPU time spinning in a delay loop, the cycles are given to all the other tasks.
I did some messing with vTaskDelay() and it appears to actually suspend the task, vTaskDelayUntil I haven't tried but it should let you program a task to execute on a specific schedule.
It looks like the "tick" these functions use is 1ms on the ESP32, so you can only schedule in increments of 1ms, not sure how much "wobble" there is in the resume time. I'm going to do some testing.
Re: ARDUINO multi-core support/questions
Howdy Greg,
Your thinking is solid. I had a look at the Arduino ESP32 source ... see:
https://github.com/espressif/arduino-es ... misc.c#L52
It appears that delay() maps 1-1 with FreeRTOS vTaskDelay().
Your thinking is solid. I had a look at the Arduino ESP32 source ... see:
https://github.com/espressif/arduino-es ... misc.c#L52
It appears that delay() maps 1-1 with FreeRTOS vTaskDelay().
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Who is online
Users browsing this forum: Majestic-12 [Bot] and 73 guests