task_pinning.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /*
  2. * arch/esp32/task_pinning.c
  3. *
  4. * Pins all FreeRTOS tasks with no explicit core affinity (tskNO_AFFINITY) to
  5. * core 0, keeping core 1 exclusively for the Arduino loop (loopTask) where
  6. * LoRa packet processing runs.
  7. *
  8. * Background:
  9. * On ESP32-S3 (dual-core), ARDUINO_RUNNING_CORE=1 pins loopTask to core 1.
  10. * However, ESP-IDF v4 creates MQTT task with tskNO_AFFINITY, so FreeRTOS
  11. * may schedule them on core 1 under load, preempting LoRa processing.
  12. *
  13. * ESP-IDF v4 provides no public API to change a task's core affinity after
  14. * creation (vTaskCoreAffinitySet is IDF v5+ only), and esp_mqtt_client_config_t
  15. * has no core selection field in IDF v4. The linker --wrap mechanism is the
  16. * only way to intercept xTaskCreatePinnedToCore at the call site inside
  17. * precompiled library code.
  18. *
  19. * It's intentionally do not filtered by task name — this keeps the approach
  20. * robust against internal ESP-IDF task name changes and also catches any
  21. * other library tasks that may happen to be created with tskNO_AFFINITY.
  22. * Core 1 is reserved exclusively for loopTask (LoRa / application logic).
  23. *
  24. * Mechanism:
  25. * -Wl,--wrap=xTaskCreatePinnedToCore redirects every call to
  26. * xTaskCreatePinnedToCore (including the xTaskCreate macro which expands to
  27. * it with tskNO_AFFINITY) through __wrap_xTaskCreatePinnedToCore below.
  28. * Tasks that are already explicitly pinned to a core are passed through
  29. * unchanged.
  30. *
  31. * Verified task layout after this patch:
  32. * core 0: mqtt_task(5), httpd(2), tiT/LwIP(18), wifi(23), esp_timer(22), ipc0(24)
  33. * core 1: loopTask(1), ipc1(24), IDLE1(0)
  34. *
  35. * Note: this file is compiled only for [esp32_base] targets (IDF v4).
  36. * ESP32-C6 uses pioarduino (IDF v5) where vTaskCoreAffinitySet() is available.
  37. */
  38. #include "freertos/FreeRTOS.h"
  39. #include "freertos/task.h"
  40. /* The real function, renamed by the linker to __real_xTaskCreatePinnedToCore. */
  41. extern BaseType_t __real_xTaskCreatePinnedToCore(
  42. TaskFunction_t pvTaskCode,
  43. const char * const pcName,
  44. const uint32_t usStackDepth,
  45. void * const pvParameters,
  46. UBaseType_t uxPriority,
  47. TaskHandle_t * const pvCreatedTask,
  48. const BaseType_t xCoreID
  49. );
  50. BaseType_t __wrap_xTaskCreatePinnedToCore(
  51. TaskFunction_t pvTaskCode,
  52. const char * const pcName,
  53. const uint32_t usStackDepth,
  54. void * const pvParameters,
  55. UBaseType_t uxPriority,
  56. TaskHandle_t * const pvCreatedTask,
  57. const BaseType_t xCoreID
  58. ) {
  59. /* Pin all tasks with no affinity to core 0. */
  60. BaseType_t core = (xCoreID == tskNO_AFFINITY) ? 0 : xCoreID;
  61. return __real_xTaskCreatePinnedToCore(
  62. pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask, core
  63. );
  64. }