forked from espressif/esp-idf
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
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "FreeRTOS.h" /* This pulls in portmacro.h */
|
#include "FreeRTOS.h" /* This pulls in portmacro.h */
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "port_systick.h"
|
||||||
#include "portmacro.h"
|
#include "portmacro.h"
|
||||||
#include "esp_memory_utils.h"
|
#include "esp_memory_utils.h"
|
||||||
#ifdef CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
|
#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);
|
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 -------------------------------------------------
|
/* ---------------------------------------------- Port Implementations -------------------------------------------------
|
||||||
@@ -562,28 +442,6 @@ void vPortTLSPointersDelCb( void *pxTCB )
|
|||||||
}
|
}
|
||||||
#endif // CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
|
#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 ----------------------
|
// ------------------- Hook Functions ----------------------
|
||||||
|
|
||||||
void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
|
void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
|
||||||
@@ -608,6 +466,7 @@ void vApplicationTickHook( void )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern void esp_vApplicationIdleHook(void);
|
||||||
#if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
#if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||||
/*
|
/*
|
||||||
By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle
|
By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h" //For vApplicationStackOverflowHook
|
#include "task.h" //For vApplicationStackOverflowHook
|
||||||
|
#include "port_systick.h"
|
||||||
#include "portmacro.h"
|
#include "portmacro.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "xt_instr_macros.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);
|
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 -------------------------------------------------
|
/* ---------------------------------------------- Port Implementations -------------------------------------------------
|
||||||
@@ -749,31 +615,6 @@ void vPortTLSPointersDelCb( void *pxTCB )
|
|||||||
}
|
}
|
||||||
#endif // CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
|
#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 ----------------------
|
// ------------------- Hook Functions ----------------------
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -795,6 +636,7 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern void esp_vApplicationIdleHook(void);
|
||||||
#if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
#if CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
|
||||||
/*
|
/*
|
||||||
By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle
|
By default, the port uses vApplicationMinimalIdleHook() to run IDF style idle
|
||||||
|
@@ -80,3 +80,15 @@ entries:
|
|||||||
if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
|
if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
|
||||||
port_common:vApplicationGetIdleTaskMemory (default)
|
port_common:vApplicationGetIdleTaskMemory (default)
|
||||||
port_common:vApplicationGetTimerTaskMemory (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)
|
||||||
|
@@ -208,7 +208,6 @@ entries:
|
|||||||
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
|
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
|
||||||
# --------------------------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------------------------
|
||||||
if IDF_TARGET_ARCH_XTENSA = y:
|
if IDF_TARGET_ARCH_XTENSA = y:
|
||||||
port:vPortSetupTimer (default)
|
|
||||||
port:xPortStartScheduler (default)
|
port:xPortStartScheduler (default)
|
||||||
port:vPortEndScheduler (default)
|
port:vPortEndScheduler (default)
|
||||||
port:pvPortMalloc (default)
|
port:pvPortMalloc (default)
|
||||||
@@ -226,7 +225,6 @@ entries:
|
|||||||
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
|
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
|
||||||
# --------------------------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------------------------
|
||||||
if IDF_TARGET_ARCH_RISCV = y:
|
if IDF_TARGET_ARCH_RISCV = y:
|
||||||
port:vPortSetupTimer (default)
|
|
||||||
port:xPortStartScheduler (default)
|
port:xPortStartScheduler (default)
|
||||||
port:vPortEndScheduler (default)
|
port:vPortEndScheduler (default)
|
||||||
port:pvPortMalloc (default)
|
port:pvPortMalloc (default)
|
||||||
|
@@ -4,61 +4,47 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.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
|
#if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
|
||||||
#include "esp_private/pm_trace.h"
|
#if CONFIG_FREERTOS_CORETIMER_0
|
||||||
#endif //CONFIG_PM_TRACE
|
#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);
|
BaseType_t xPortSysTickHandler(void);
|
||||||
|
|
||||||
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
|
/* --------------------------------------------- SYSTIMER Implementation -----------------------------------------------
|
||||||
extern void _frxt_tick_timer_init(void);
|
* Implementation of a tick interrupt using the SYSTIMER perpiheral
|
||||||
extern void _xt_tick_divisor_init(void);
|
* Todo: Abstract setup and operation in a separate SYSTIMER driver (IDF-6976)
|
||||||
|
* ------------------------------------------------------------------------------------------------------------------ */
|
||||||
|
|
||||||
#ifdef CONFIG_FREERTOS_CORETIMER_0
|
#if CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
|
||||||
#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
|
|
||||||
|
|
||||||
/**
|
#include "soc/periph_defs.h"
|
||||||
* @brief Initialize CCONT timer to generate the tick interrupt
|
#include "hal/systimer_hal.h"
|
||||||
*
|
#include "hal/systimer_ll.h"
|
||||||
*/
|
#include "esp_err.h"
|
||||||
void vPortSetupTimer(void)
|
#include "esp_intr_alloc.h"
|
||||||
{
|
#include "esp_private/systimer.h"
|
||||||
/* Init the tick divisor value */
|
#include "esp_private/periph_ctrl.h"
|
||||||
_xt_tick_divisor_init();
|
#ifdef CONFIG_PM_TRACE
|
||||||
|
#include "esp_private/pm_trace.h"
|
||||||
_frxt_tick_timer_init();
|
#endif //CONFIG_PM_TRACE
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#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");
|
_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);
|
void SysTickIsrHandler(void *arg);
|
||||||
|
|
||||||
static uint32_t s_handled_systicks[portNUM_PROCESSORS] = { 0 };
|
static uint32_t s_handled_systicks[configNUM_CORES] = { 0 };
|
||||||
|
|
||||||
#define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set up the systimer peripheral to generate the tick interrupt
|
* @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.
|
* 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.
|
* Shifts a time of triggering interrupts for core 0 and core 1.
|
||||||
*/
|
*/
|
||||||
void vPortSetupTimer(void)
|
void vSystimerSetup(void)
|
||||||
{
|
{
|
||||||
unsigned cpuid = xPortGetCoreID();
|
unsigned cpuid = xPortGetCoreID();
|
||||||
#ifdef CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3
|
#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.
|
* 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.
|
* 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();
|
uint32_t cpuid = xPortGetCoreID();
|
||||||
systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg;
|
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);
|
ESP_PM_TRACE_EXIT(TICK, cpuid);
|
||||||
#endif
|
#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
|
* @brief Handler of SysTick
|
||||||
*
|
*
|
||||||
@@ -176,29 +182,44 @@ BaseType_t xPortSysTickHandler(void)
|
|||||||
traceISR_ENTER(SYSTICK_INTR_ID);
|
traceISR_ENTER(SYSTICK_INTR_ID);
|
||||||
|
|
||||||
// Call IDF Tick Hook
|
// Call IDF Tick Hook
|
||||||
|
extern void esp_vApplicationTickHook(void);
|
||||||
esp_vApplicationTickHook();
|
esp_vApplicationTickHook();
|
||||||
|
|
||||||
// Call FreeRTOS Increment tick function
|
// Call FreeRTOS Increment tick function
|
||||||
BaseType_t xSwitchRequired;
|
BaseType_t xSwitchRequired;
|
||||||
#if ( configNUM_CORES > 1 )
|
#if CONFIG_FREERTOS_SMP
|
||||||
/*
|
// Amazon SMP FreeRTOS requires that only core 0 calls xTaskIncrementTick()
|
||||||
For SMP, xTaskIncrementTick() will internally enter a critical section. But only core 0 calls xTaskIncrementTick()
|
#if ( configNUM_CORES > 1 )
|
||||||
while core 1 should call xTaskIncrementTickOtherCores().
|
if (portGET_CORE_ID() == 0) {
|
||||||
*/
|
xSwitchRequired = xTaskIncrementTick();
|
||||||
if (xPortGetCoreID() == 0) {
|
} else {
|
||||||
xSwitchRequired = xTaskIncrementTick();
|
xSwitchRequired = pdFALSE;
|
||||||
} else {
|
}
|
||||||
xSwitchRequired = xTaskIncrementTickOtherCores();
|
#else /* configNUM_CORES > 1 */
|
||||||
}
|
xSwitchRequired = xTaskIncrementTick();
|
||||||
#else // configNUM_CORES > 1
|
#endif /* configNUM_CORES > 1 */
|
||||||
/*
|
#else /* !CONFIG_FREERTOS_SMP */
|
||||||
Vanilla (single core) FreeRTOS expects that xTaskIncrementTick() cannot be interrupted (i.e., no nested interrupts).
|
#if ( configNUM_CORES > 1 )
|
||||||
Thus we have to disable interrupts before calling it.
|
/*
|
||||||
*/
|
Multi-core IDF FreeRTOS requires that...
|
||||||
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
- core 0 calls xTaskIncrementTick()
|
||||||
xSwitchRequired = xTaskIncrementTick();
|
- core 1 calls xTaskIncrementTickOtherCores()
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
|
*/
|
||||||
#endif
|
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
|
// Check if yield is required
|
||||||
if (xSwitchRequired != pdFALSE) {
|
if (xSwitchRequired != pdFALSE) {
|
||||||
|
Reference in New Issue
Block a user