Introduction
As outlined in the programming guide, the ESP-IDF FreeRTOS derivate introduces a small but significant change to the vanilla FreeRTOS round robin scheduler: Tasks in the ESP-IDF FreeRTOS are designed to run on a particular core.
Saying this, the ESP-IDF FreeRTOS has the notion of a PRO_CPU and an APP_CPU:
The vanilla FreeRTOS is designed to run on a single core. However the ESP32 is dual core containing a Protocol CPU (known as CPU 0 or PRO_CPU ) and an Application CPU (known as CPU 1 or APP_CPU ). The two cores are identical in practice and share the same memory. This allows the two cores to run tasks interchangeably between them.
Illustration of FreeRTOS Ready Task List Data Structure in ESP-IDF
Arduino on ESP32
As you might have imagined already, the Arduino program will be started as a FreeRTOS task. By using the CPU pinning outlined above, the environment will ensure that the well known main()
and loop()
functions of Arduino Core will execute on the same CPU core, which is CPU 1 by default, see https://github.com/espressif/arduino-esp32/blob/1.0.1/cores/esp32/main.cpp:
#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
Take care!
The cool thing about this design choice is that it will give you a breakfast for free as basic programs written for Arduino will still run contained to a single CPU core, so they will not experience being scheduled between both CPU cores.
In that way, these programs will provide a fully linear execution flow behaving like being executed on AVRs or other less-featured microcontrollers as usual. Otherwise, you would have to protect each and every variable in your program sketch against memory corruption and race conditions.
Saying that, you will nevertheless have to Protect code when accessing shared resources like bus peripherals and other hardware attached to the board, especially when involving ISRs.
Do it yourself
If you want to spawn tasks on a specific core on your own behalf, these tutorials will get you started: