How does FreeRTOS in ESP-IDF differ from standard ("vanilla") FreeRTOS in ways that matter when you create a task?
The stack size passed to xTaskCreate is in bytes, not words; the kernel schedules tasks across two cores unless built single-core; and your program starts in app_main, which ESP-IDF already runs as a task, instead of you calling vTaskStartScheduler().
| Vanilla FreeRTOS | ESP-IDF FreeRTOS | |
|---|---|---|
| Stack depth unit | Words (4 bytes each on a 32-bit CPU) | Bytes |
| Cores | One | Two on the ESP32; tasks without a fixed core can run on either |
| Program start | main() creates tasks, then calls vTaskStartScheduler() |
Scheduler is already running; ESP-IDF calls app_main() from its main task |
| Priorities | Set by configMAX_PRIORITIES |
25 levels, 0-24; the main task runs at 1 |
The stack unit is the one that bites. Code copied from a vanilla FreeRTOS example that asks for 1024 gets 4 KB there but only 1 KB on ESP-IDF, and printf alone can use more than that. The assignment code comments stack_depth = 4096 as bytes "unlike vanilla FreeRTOS" for this reason.
Because the scheduler is already running when app_main is called, a task created there with priority 10 starts immediately, before xTaskCreate even returns, since it outranks the main task at priority 1.
Go deeper:
ESP-IDF — FreeRTOS (IDF) — the full list of differences, including the dual-core scheduler and stack units.
Wikipedia — Symmetric multiprocessing — the model behind ESP-IDF's dual-core scheduler: identical cores sharing one memory and one task list.