|
|
@@ -0,0 +1,67 @@
|
|
|
+/*
|
|
|
+ * arch/esp32/task_pinning.c
|
|
|
+ *
|
|
|
+ * Pins all FreeRTOS tasks with no explicit core affinity (tskNO_AFFINITY) to
|
|
|
+ * core 0, keeping core 1 exclusively for the Arduino loop (loopTask) where
|
|
|
+ * LoRa packet processing runs.
|
|
|
+ *
|
|
|
+ * Background:
|
|
|
+ * On ESP32-S3 (dual-core), ARDUINO_RUNNING_CORE=1 pins loopTask to core 1.
|
|
|
+ * However, ESP-IDF v4 creates MQTT task with tskNO_AFFINITY, so FreeRTOS
|
|
|
+ * may schedule them on core 1 under load, preempting LoRa processing.
|
|
|
+ *
|
|
|
+ * ESP-IDF v4 provides no public API to change a task's core affinity after
|
|
|
+ * creation (vTaskCoreAffinitySet is IDF v5+ only), and esp_mqtt_client_config_t
|
|
|
+ * has no core selection field in IDF v4. The linker --wrap mechanism is the
|
|
|
+ * only way to intercept xTaskCreatePinnedToCore at the call site inside
|
|
|
+ * precompiled library code.
|
|
|
+ *
|
|
|
+ * It's intentionally do not filtered by task name — this keeps the approach
|
|
|
+ * robust against internal ESP-IDF task name changes and also catches any
|
|
|
+ * other library tasks that may happen to be created with tskNO_AFFINITY.
|
|
|
+ * Core 1 is reserved exclusively for loopTask (LoRa / application logic).
|
|
|
+ *
|
|
|
+ * Mechanism:
|
|
|
+ * -Wl,--wrap=xTaskCreatePinnedToCore redirects every call to
|
|
|
+ * xTaskCreatePinnedToCore (including the xTaskCreate macro which expands to
|
|
|
+ * it with tskNO_AFFINITY) through __wrap_xTaskCreatePinnedToCore below.
|
|
|
+ * Tasks that are already explicitly pinned to a core are passed through
|
|
|
+ * unchanged.
|
|
|
+ *
|
|
|
+ * Verified task layout after this patch:
|
|
|
+ * core 0: mqtt_task(5), httpd(2), tiT/LwIP(18), wifi(23), esp_timer(22), ipc0(24)
|
|
|
+ * core 1: loopTask(1), ipc1(24), IDLE1(0)
|
|
|
+ *
|
|
|
+ * Note: this file is compiled only for [esp32_base] targets (IDF v4).
|
|
|
+ * ESP32-C6 uses pioarduino (IDF v5) where vTaskCoreAffinitySet() is available.
|
|
|
+ */
|
|
|
+
|
|
|
+#include "freertos/FreeRTOS.h"
|
|
|
+#include "freertos/task.h"
|
|
|
+
|
|
|
+/* The real function, renamed by the linker to __real_xTaskCreatePinnedToCore. */
|
|
|
+extern BaseType_t __real_xTaskCreatePinnedToCore(
|
|
|
+ TaskFunction_t pvTaskCode,
|
|
|
+ const char * const pcName,
|
|
|
+ const uint32_t usStackDepth,
|
|
|
+ void * const pvParameters,
|
|
|
+ UBaseType_t uxPriority,
|
|
|
+ TaskHandle_t * const pvCreatedTask,
|
|
|
+ const BaseType_t xCoreID
|
|
|
+);
|
|
|
+
|
|
|
+BaseType_t __wrap_xTaskCreatePinnedToCore(
|
|
|
+ TaskFunction_t pvTaskCode,
|
|
|
+ const char * const pcName,
|
|
|
+ const uint32_t usStackDepth,
|
|
|
+ void * const pvParameters,
|
|
|
+ UBaseType_t uxPriority,
|
|
|
+ TaskHandle_t * const pvCreatedTask,
|
|
|
+ const BaseType_t xCoreID
|
|
|
+) {
|
|
|
+ /* Pin all tasks with no affinity to core 0. */
|
|
|
+ BaseType_t core = (xCoreID == tskNO_AFFINITY) ? 0 : xCoreID;
|
|
|
+ return __real_xTaskCreatePinnedToCore(
|
|
|
+ pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask, core
|
|
|
+ );
|
|
|
+}
|