Selaa lähdekoodia

freertos: Refactor port_systick

This commit refactors port_systick.c so that all ports (RISC-V vs Xtensa) of
all FreeRTOS implementations (IDF vs Amazon SMP FreeRTOS) use the same set of
tick interrupt functions. Thus, these funcitons are now common:

- vPortSetupTimer() to setup the tick interrupt's timer
- xPortSysTickHandler() that is called on each tick interrupt
Darian Leung 2 vuotta sitten
vanhempi
sitoutus
76d4c9f592

+ 2 - 143
components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c

@@ -27,6 +27,7 @@
 #include "esp_log.h"
 #include "FreeRTOS.h"       /* This pulls in portmacro.h */
 #include "task.h"
+#include "port_systick.h"
 #include "portmacro.h"
 #include "esp_memory_utils.h"
 #ifdef CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
@@ -98,127 +99,6 @@ void vPortSetStackWatchpoint(void *pxStackStart)
     esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_CPU_WATCHPOINT_STORE);
 }
 
-// ---------------------- Tick Timer -----------------------
-
-BaseType_t xPortSysTickHandler(void);
-
-#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
-
-#ifdef CONFIG_FREERTOS_CORETIMER_0
-    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
-#endif
-#ifdef CONFIG_FREERTOS_CORETIMER_1
-    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
-#endif
-
-#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) {
-        periph_module_enable(PERIPH_SYSTIMER_MODULE);
-        systimer_hal_init(&systimer_hal);
-        systimer_hal_tick_rate_ops_t ops = {
-            .ticks_to_us = systimer_ticks_to_us,
-            .us_to_ticks = systimer_us_to_ticks,
-        };
-        systimer_hal_set_tick_rate_ops(&systimer_hal, &ops);
-        systimer_ll_set_counter_value(systimer_hal.dev, SYSTIMER_COUNTER_OS_TICK, 0);
-        systimer_ll_apply_counter_value(systimer_hal.dev, SYSTIMER_COUNTER_OS_TICK);
-
-        for (cpuid = 0; cpuid < SOC_CPU_CORES_NUM; cpuid++) {
-            systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_COUNTER_OS_TICK, cpuid, false);
-        }
-
-        for (cpuid = 0; cpuid < portNUM_PROCESSORS; ++cpuid) {
-            uint32_t alarm_id = SYSTIMER_ALARM_OS_TICK_CORE0 + cpuid;
-
-            /* configure the timer */
-            systimer_hal_connect_alarm_counter(&systimer_hal, alarm_id, SYSTIMER_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_COUNTER_OS_TICK, cpuid, true);
-            if (cpuid == 0) {
-                systimer_hal_enable_alarm_int(&systimer_hal, alarm_id);
-                systimer_hal_enable_counter(&systimer_hal, SYSTIMER_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_COUNTER_OS_TICK, 1000000UL / CONFIG_FREERTOS_HZ / 2);
-#endif
-            }
-        }
-    } else {
-        uint32_t alarm_id = SYSTIMER_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_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_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_SYSTIMER
-
 
 
 /* ---------------------------------------------- Port Implementations -------------------------------------------------
@@ -562,28 +442,6 @@ void vPortTLSPointersDelCb( void *pxTCB )
 }
 #endif // CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
 
-// -------------------- Tick Handler -----------------------
-
-extern void esp_vApplicationIdleHook(void);
-extern void esp_vApplicationTickHook(void);
-
-BaseType_t xPortSysTickHandler(void)
-{
-#if configBENCHMARK
-    portbenchmarkIntLatency();
-#endif //configBENCHMARK
-    traceISR_ENTER(SYSTICK_INTR_ID);
-    BaseType_t ret = xTaskIncrementTick();
-    //Manually call the IDF tick hooks
-    esp_vApplicationTickHook();
-    if (ret != pdFALSE) {
-        portYIELD_FROM_ISR();
-    } else {
-        traceISR_EXIT();
-    }
-    return ret;
-}
-
 // ------------------- Hook Functions ----------------------
 
 void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
@@ -608,6 +466,7 @@ void vApplicationTickHook( void )
 }
 #endif
 
+extern void esp_vApplicationIdleHook(void);
 #if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
 /*
 By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle

+ 2 - 160
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c

@@ -9,6 +9,7 @@
 #include <string.h>
 #include "FreeRTOS.h"
 #include "task.h"   //For vApplicationStackOverflowHook
+#include "port_systick.h"
 #include "portmacro.h"
 #include "spinlock.h"
 #include "xt_instr_macros.h"
@@ -174,141 +175,6 @@ void vPortSetStackWatchpoint( void *pxStackStart )
     esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, 32, ESP_CPU_WATCHPOINT_STORE);
 }
 
-// ---------------------- 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);
-
-#ifdef CONFIG_FREERTOS_CORETIMER_0
-    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
-#endif
-#ifdef CONFIG_FREERTOS_CORETIMER_1
-    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
-#endif
-
-/**
- * @brief Initialize CCONT timer to generate the tick interrupt
- *
- */
-void vPortSetupTimer(void)
-{
-    /* Init the tick divisor value */
-    _xt_tick_divisor_init();
-
-    _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) {
-        periph_module_enable(PERIPH_SYSTIMER_MODULE);
-        systimer_hal_init(&systimer_hal);
-        systimer_hal_tick_rate_ops_t ops = {
-            .ticks_to_us = systimer_ticks_to_us,
-            .us_to_ticks = systimer_us_to_ticks,
-        };
-        systimer_hal_set_tick_rate_ops(&systimer_hal, &ops);
-        systimer_ll_set_counter_value(systimer_hal.dev, SYSTIMER_COUNTER_OS_TICK, 0);
-        systimer_ll_apply_counter_value(systimer_hal.dev, SYSTIMER_COUNTER_OS_TICK);
-
-        for (cpuid = 0; cpuid < SOC_CPU_CORES_NUM; cpuid++) {
-            systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_COUNTER_OS_TICK, cpuid, false);
-        }
-
-        for (cpuid = 0; cpuid < portNUM_PROCESSORS; ++cpuid) {
-            uint32_t alarm_id = SYSTIMER_ALARM_OS_TICK_CORE0 + cpuid;
-
-            /* configure the timer */
-            systimer_hal_connect_alarm_counter(&systimer_hal, alarm_id, SYSTIMER_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_COUNTER_OS_TICK, cpuid, true);
-            if (cpuid == 0) {
-                systimer_hal_enable_alarm_int(&systimer_hal, alarm_id);
-                systimer_hal_enable_counter(&systimer_hal, SYSTIMER_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_COUNTER_OS_TICK, 1000000UL / CONFIG_FREERTOS_HZ / 2);
-#endif
-            }
-        }
-    } else {
-        uint32_t alarm_id = SYSTIMER_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_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_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
-
 
 
 /* ---------------------------------------------- Port Implementations -------------------------------------------------
@@ -749,31 +615,6 @@ void vPortTLSPointersDelCb( void *pxTCB )
 }
 #endif // CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
 
-// -------------------- Tick Handler -----------------------
-
-extern void esp_vApplicationIdleHook(void);
-extern void esp_vApplicationTickHook(void);
-
-BaseType_t xPortSysTickHandler(void)
-{
-    portbenchmarkIntLatency();
-    traceISR_ENTER(SYSTICK_INTR_ID);
-    BaseType_t ret;
-    esp_vApplicationTickHook();
-    if (portGET_CORE_ID() == 0) {
-        // FreeRTOS SMP requires that only core 0 calls xTaskIncrementTick()
-        ret = xTaskIncrementTick();
-    } else {
-        ret = pdFALSE;
-    }
-    if (ret != pdFALSE) {
-        portYIELD_FROM_ISR();
-    } else {
-        traceISR_EXIT();
-    }
-    return ret;
-}
-
 // ------------------- Hook Functions ----------------------
 
 #include <stdlib.h>
@@ -795,6 +636,7 @@ void  __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c
 }
 #endif
 
+extern void esp_vApplicationIdleHook(void);
 #if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
 /*
 By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle

+ 12 - 0
components/freertos/linker_common.lf

@@ -80,3 +80,15 @@ entries:
     if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
         port_common:vApplicationGetIdleTaskMemory (default)
         port_common:vApplicationGetTimerTaskMemory (default)
+
+    # ------------------------------------------------------------------------------------------------------------------
+    # port_systick.c
+    #   - Default: Place all functions in internal RAM.
+    #   - CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH: Place functions in flash if they are never called from an ISR
+    #     context (directly or indirectly).
+    # ------------------------------------------------------------------------------------------------------------------
+    port_systick(noflash_text)
+    if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
+        if FREERTOS_SYSTICK_USES_SYSTIMER = y:
+            port_systick:vSystimerSetup (default)
+        port_systick:vPortSetupTimer (default)

+ 0 - 2
components/freertos/linker_smp.lf

@@ -208,7 +208,6 @@ entries:
         # - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
         # --------------------------------------------------------------------------------------------------------------
         if IDF_TARGET_ARCH_XTENSA = y:
-            port:vPortSetupTimer (default)
             port:xPortStartScheduler (default)
             port:vPortEndScheduler (default)
             port:pvPortMalloc (default)
@@ -226,7 +225,6 @@ entries:
         # - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
         # --------------------------------------------------------------------------------------------------------------
         if IDF_TARGET_ARCH_RISCV = y:
-            port:vPortSetupTimer (default)
             port:xPortStartScheduler (default)
             port:vPortEndScheduler (default)
             port:pvPortMalloc (default)

+ 85 - 64
components/freertos/port_systick.c

@@ -4,61 +4,47 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+#include "sdkconfig.h"
+#include <stdint.h>
 #include <stdlib.h>
-#include <string.h>
 #include "FreeRTOS.h"
 #include "task.h"
-#include "esp_intr_alloc.h"
-#include "esp_err.h"
-#include "esp_log.h"
-#include "esp_private/systimer.h"
-#include "esp_private/periph_ctrl.h"
-#include "sdkconfig.h"
-#ifdef CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
-#include "soc/periph_defs.h"
-#include "hal/systimer_hal.h"
-#include "hal/systimer_ll.h"
-#endif
 
-#ifdef CONFIG_PM_TRACE
-#include "esp_private/pm_trace.h"
-#endif //CONFIG_PM_TRACE
+#if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
+    #if CONFIG_FREERTOS_CORETIMER_0
+        #define SYSTICK_INTR_ID     (ETS_INTERNAL_TIMER0_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF)
+    #else /* CONFIG_FREERTOS_CORETIMER_1 */
+        #define SYSTICK_INTR_ID     (ETS_INTERNAL_TIMER1_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF)
+    #endif
+#else /* CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER */
+        #define SYSTICK_INTR_ID     (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE)
+#endif /* CONFIG_FREERTOS_SYSTICK_USES_CCOUNT */
 
 BaseType_t xPortSysTickHandler(void);
 
-#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
-extern void _frxt_tick_timer_init(void);
-extern void _xt_tick_divisor_init(void);
-
-#ifdef CONFIG_FREERTOS_CORETIMER_0
-    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
-#endif
-#ifdef CONFIG_FREERTOS_CORETIMER_1
-    #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
-#endif
-
-/**
- * @brief Initialize CCONT timer to generate the tick interrupt
- *
- */
-void vPortSetupTimer(void)
-{
-    /* Init the tick divisor value */
-    _xt_tick_divisor_init();
-
-    _frxt_tick_timer_init();
-}
+/* --------------------------------------------- SYSTIMER Implementation -----------------------------------------------
+ * Implementation of a tick interrupt using the SYSTIMER perpiheral
+ * Todo: Abstract setup and operation in a separate SYSTIMER driver (IDF-6976)
+ * ------------------------------------------------------------------------------------------------------------------ */
 
+#if CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
 
-#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
+#include "soc/periph_defs.h"
+#include "hal/systimer_hal.h"
+#include "hal/systimer_ll.h"
+#include "esp_err.h"
+#include "esp_intr_alloc.h"
+#include "esp_private/systimer.h"
+#include "esp_private/periph_ctrl.h"
+#ifdef CONFIG_PM_TRACE
+#include "esp_private/pm_trace.h"
+#endif //CONFIG_PM_TRACE
 
 _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)
+static uint32_t s_handled_systicks[configNUM_CORES] = { 0 };
 
 /**
  * @brief Set up the systimer peripheral to generate the tick interrupt
@@ -67,7 +53,7 @@ static uint32_t s_handled_systicks[portNUM_PROCESSORS] = { 0 };
  * 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)
+void vSystimerSetup(void)
 {
     unsigned cpuid = xPortGetCoreID();
 #ifdef CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3
@@ -124,7 +110,7 @@ void vPortSetupTimer(void)
  * 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)
+void SysTickIsrHandler(void *arg)
 {
     uint32_t cpuid = xPortGetCoreID();
     systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg;
@@ -155,11 +141,31 @@ IRAM_ATTR void SysTickIsrHandler(void *arg)
     ESP_PM_TRACE_EXIT(TICK, cpuid);
 #endif
 }
+#endif /* CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER */
 
-#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
+/* ------------------------------------------------ Common Port Tick ---------------------------------------------------
+ * Tick related functions common across all ports
+ * ------------------------------------------------------------------------------------------------------------------ */
 
+/**
+ * @brief Initialize the tick interrupt timer
+ *
+ * - CCOUNT timer is used if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT is set
+ * - SYSTIMER is used if CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER is set
+ */
+void vPortSetupTimer(void)
+{
+    #if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
+        extern void _frxt_tick_timer_init(void);
+        extern void _xt_tick_divisor_init(void);
+        /* Init the tick divisor value */
+        _xt_tick_divisor_init();
+        _frxt_tick_timer_init();
+    #else /* CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER */
+        vSystimerSetup();
+    #endif /* CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER */
+}
 
-extern void esp_vApplicationTickHook(void);
 /**
  * @brief Handler of SysTick
  *
@@ -176,29 +182,44 @@ BaseType_t xPortSysTickHandler(void)
     traceISR_ENTER(SYSTICK_INTR_ID);
 
     // Call IDF Tick Hook
+    extern void esp_vApplicationTickHook(void);
     esp_vApplicationTickHook();
 
     // Call FreeRTOS Increment tick function
     BaseType_t xSwitchRequired;
-#if ( configNUM_CORES > 1 )
-    /*
-    For SMP, xTaskIncrementTick() will internally enter a critical section. But only core 0 calls xTaskIncrementTick()
-    while core 1 should call xTaskIncrementTickOtherCores().
-    */
-    if (xPortGetCoreID() == 0) {
-        xSwitchRequired = xTaskIncrementTick();
-    } else {
-        xSwitchRequired = xTaskIncrementTickOtherCores();
-    }
-#else // configNUM_CORES > 1
-    /*
-    Vanilla (single core) FreeRTOS expects that xTaskIncrementTick() cannot be interrupted (i.e., no nested interrupts).
-    Thus we have to disable interrupts before calling it.
-    */
-    UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
-    xSwitchRequired = xTaskIncrementTick();
-    portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
-#endif
+    #if CONFIG_FREERTOS_SMP
+        // Amazon SMP FreeRTOS requires that only core 0 calls xTaskIncrementTick()
+        #if ( configNUM_CORES > 1 )
+            if (portGET_CORE_ID() == 0) {
+                xSwitchRequired = xTaskIncrementTick();
+            } else {
+                xSwitchRequired = pdFALSE;
+            }
+        #else /* configNUM_CORES > 1 */
+            xSwitchRequired = xTaskIncrementTick();
+        #endif /* configNUM_CORES > 1 */
+    #else /* !CONFIG_FREERTOS_SMP */
+        #if ( configNUM_CORES > 1 )
+            /*
+            Multi-core IDF FreeRTOS requires that...
+                - core 0 calls xTaskIncrementTick()
+                - core 1 calls xTaskIncrementTickOtherCores()
+            */
+            if (xPortGetCoreID() == 0) {
+                xSwitchRequired = xTaskIncrementTick();
+            } else {
+                xSwitchRequired = xTaskIncrementTickOtherCores();
+            }
+        #else /* configNUM_CORES > 1 */
+            /*
+            Vanilla (single core) FreeRTOS expects that xTaskIncrementTick() cannot be interrupted (i.e., no nested
+            interrupts). Thus we have to disable interrupts before calling it.
+            */
+            UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+            xSwitchRequired = xTaskIncrementTick();
+            portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
+        #endif /* configNUM_CORES > 1 */
+    #endif /* !CONFIG_FREERTOS_SMP */
 
     // Check if yield is required
     if (xSwitchRequired != pdFALSE) {