Просмотр исходного кода

freertos-smp: Fix build test errors for esp32s2 and esp32s3

This commit fixes build test errors for esp32s2 and esp32s3 with
FreeRTOS SMP enabled.
Sudeep Mohanty 3 лет назад
Родитель
Сommit
c5d6f97331

+ 3 - 0
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h

@@ -356,6 +356,9 @@ static inline bool IRAM_ATTR xPortCanYield(void)
     return ((ps_reg & PS_INTLEVEL_MASK) == 0);
 }
 
+// Added for backward compatibility with IDF
+#define portYIELD_WITHIN_API()                      vTaskYieldWithinAPI()
+
 // ----------------------- System --------------------------
 
 void vPortSetStackWatchpoint(void *pxStackStart);

+ 112 - 0
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c

@@ -27,6 +27,7 @@
 #include "esp_task_wdt.h"
 #include "esp_heap_caps_init.h"
 #include "esp_freertos_hooks.h"
+#include "esp_intr_alloc.h"
 #if CONFIG_SPIRAM
 /* Required by esp_psram_extram_reserve_dma_pool() */
 #include "esp_psram.h"
@@ -38,6 +39,12 @@
 #ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
 #include "esp_gdbstub.h"                    /* Required by esp_gdbstub_init() */
 #endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
+#ifdef CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
+#include "soc/periph_defs.h"
+#include "soc/system_reg.h"
+#include "hal/systimer_hal.h"
+#include "hal/systimer_ll.h"
+#endif // CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
 
 /*
 OS state variables
@@ -148,6 +155,9 @@ void vPortSetStackWatchpoint( void *pxStackStart )
 
 // ---------------------- Tick Timer -----------------------
 
+BaseType_t xPortSysTickHandler(void);
+
+#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
 extern void _frxt_tick_timer_init(void);
 extern void _xt_tick_divisor_init(void);
 
@@ -163,6 +173,108 @@ void vPortSetupTimer(void)
     _frxt_tick_timer_init();
 }
 
+#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
+
+_Static_assert(SOC_CPU_CORES_NUM <= SOC_SYSTIMER_ALARM_NUM - 1, "the number of cores must match the number of core alarms in SYSTIMER");
+
+void SysTickIsrHandler(void *arg);
+
+static uint32_t s_handled_systicks[portNUM_PROCESSORS] = { 0 };
+
+#define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE)
+
+/**
+ * @brief Set up the systimer peripheral to generate the tick interrupt
+ *
+ * Both timer alarms are configured in periodic mode.
+ * It is done at the same time so SysTicks for both CPUs occur at the same time or very close.
+ * Shifts a time of triggering interrupts for core 0 and core 1.
+ */
+void vPortSetupTimer(void)
+{
+    unsigned cpuid = xPortGetCoreID();
+#ifdef CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3
+    const unsigned level = ESP_INTR_FLAG_LEVEL3;
+#else
+    const unsigned level = ESP_INTR_FLAG_LEVEL1;
+#endif
+    /* Systimer HAL layer object */
+    static systimer_hal_context_t systimer_hal;
+    /* set system timer interrupt vector */
+    ESP_ERROR_CHECK(esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE + cpuid, ESP_INTR_FLAG_IRAM | level, SysTickIsrHandler, &systimer_hal, NULL));
+
+    if (cpuid == 0) {
+        systimer_hal_init(&systimer_hal);
+        systimer_ll_set_counter_value(systimer_hal.dev, SYSTIMER_LL_COUNTER_OS_TICK, 0);
+        systimer_ll_apply_counter_value(systimer_hal.dev, SYSTIMER_LL_COUNTER_OS_TICK);
+
+        for (cpuid = 0; cpuid < SOC_CPU_CORES_NUM; cpuid++) {
+            systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, cpuid, false);
+        }
+
+        for (cpuid = 0; cpuid < portNUM_PROCESSORS; ++cpuid) {
+            uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid;
+
+            /* configure the timer */
+            systimer_hal_connect_alarm_counter(&systimer_hal, alarm_id, SYSTIMER_LL_COUNTER_OS_TICK);
+            systimer_hal_set_alarm_period(&systimer_hal, alarm_id, 1000000UL / CONFIG_FREERTOS_HZ);
+            systimer_hal_select_alarm_mode(&systimer_hal, alarm_id, SYSTIMER_ALARM_MODE_PERIOD);
+            systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, cpuid, true);
+            if (cpuid == 0) {
+                systimer_hal_enable_alarm_int(&systimer_hal, alarm_id);
+                systimer_hal_enable_counter(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK);
+#ifndef CONFIG_FREERTOS_UNICORE
+                // SysTick of core 0 and core 1 are shifted by half of period
+                systimer_hal_counter_value_advance(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, 1000000UL / CONFIG_FREERTOS_HZ / 2);
+#endif
+            }
+        }
+    } else {
+        uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid;
+        systimer_hal_enable_alarm_int(&systimer_hal, alarm_id);
+    }
+}
+
+/**
+ * @brief Systimer interrupt handler.
+ *
+ * The Systimer interrupt for SysTick works in periodic mode no need to calc the next alarm.
+ * If a timer interrupt is ever serviced more than one tick late, it is necessary to process multiple ticks.
+ */
+IRAM_ATTR void SysTickIsrHandler(void *arg)
+{
+    uint32_t cpuid = xPortGetCoreID();
+    systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg;
+#ifdef CONFIG_PM_TRACE
+    ESP_PM_TRACE_ENTER(TICK, cpuid);
+#endif
+
+    uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid;
+    do {
+        systimer_ll_clear_alarm_int(systimer_hal->dev, alarm_id);
+
+        uint32_t diff = systimer_hal_get_counter_value(systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK) / systimer_ll_get_alarm_period(systimer_hal->dev, alarm_id) - s_handled_systicks[cpuid];
+        if (diff > 0) {
+            if (s_handled_systicks[cpuid] == 0) {
+                s_handled_systicks[cpuid] = diff;
+                diff = 1;
+            } else {
+                s_handled_systicks[cpuid] += diff;
+            }
+
+            do {
+                xPortSysTickHandler();
+            } while (--diff);
+        }
+    } while (systimer_ll_is_alarm_int_fired(systimer_hal->dev, alarm_id));
+
+#ifdef CONFIG_PM_TRACE
+    ESP_PM_TRACE_EXIT(TICK, cpuid);
+#endif
+}
+
+#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
+
 // --------------------- App Start-up ----------------------
 
 static const char *TAG = "cpu_start";