freertos(esp32s3): SysTick uses systimer

This commit is contained in:
Konstantin Kondrashov 2021-08-04 20:33:44 +08:00 committed by Zim Kalinowski
parent b5f9149399
commit 29f581fc70
23 changed files with 315 additions and 121 deletions

View File

@ -151,16 +151,17 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
// The lowest RAM address used for IDs (pointers)
#define SYSVIEW_RAM_BASE (SOC_DROM_LOW)
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#ifdef CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER
#if CONFIG_FREERTOS_CORETIMER_0
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
#endif
#if CONFIG_FREERTOS_CORETIMER_1
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
#endif
#elif CONFIG_IDF_TARGET_ESP32C3
#define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
#endif
#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
#define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE)
#endif // CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER
// SystemView is single core specific: it implies that SEGGER_SYSVIEW_LOCK()
// disables IRQs (disables rescheduling globally). So we can not use finite timeouts for locks and return error

View File

@ -854,7 +854,7 @@ static void reset_task(void* arg)
ESP_LOGI(TAG, "Start reset task");
while (!cmd_stop_reset_task) {
esp_efuse_utility_reset();
vTaskDelay(1);
vTaskDelay(2);
}
vTaskDelete(NULL);
}

View File

@ -31,7 +31,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#if __XTENSA__
#if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
#include "freertos/xtensa_timer.h"
#include "xtensa/core-macros.h"
#endif
@ -68,7 +68,7 @@
#define MHZ (1000000)
#if __XTENSA__
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
/* CCOMPARE update timeout, in CPU cycles. Any value above ~600 cycles will work
* for the purpose of detecting a deadlock.
*/
@ -78,7 +78,7 @@
* than this. This is to prevent setting CCOMPARE below CCOUNT.
*/
#define CCOMPARE_MIN_CYCLES_IN_FUTURE 1000
#endif
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
/* When light sleep is used, wake this number of microseconds earlier than
* the next tick.
@ -184,7 +184,7 @@ static const char* s_mode_names[] = {
};
#endif // WITH_PROFILING
#if __XTENSA__
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
/* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU.
* Used in conjunction with cross-core interrupt to update CCOMPARE on the other CPU.
*/
@ -197,7 +197,7 @@ static uint32_t s_ccount_div;
static uint32_t s_ccount_mul;
static void update_ccompare(void);
#endif // __XTENSA__
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
static const char* TAG = "pm";
@ -425,7 +425,7 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p
esp_timer_private_update_apb_freq(apb_ticks_per_us);
}
#if __XTENSA__
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
#ifdef XT_RTOS_TIMER_INT
/* Calculate new tick divisor */
_xt_tick_divisor = ticks_per_us * MHZ / XT_TICK_PER_SEC;
@ -462,7 +462,7 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p
s_ccount_div = 0;
ESP_PM_TRACE_EXIT(CCOMPARE_UPDATE, core_id);
}
#endif // __XTENSA__
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
}
/**
@ -484,7 +484,7 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
portEXIT_CRITICAL_ISR(&s_switch_lock);
return;
}
#if __XTENSA__
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
if (s_need_update_ccompare[core_id]) {
s_need_update_ccompare[core_id] = false;
}
@ -529,7 +529,7 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
portEXIT_CRITICAL_ISR(&s_switch_lock);
}
#if __XTENSA__
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
/**
* @brief Calculate new CCOMPARE value based on s_ccount_{mul,div}
*
@ -550,7 +550,7 @@ static void IRAM_ATTR update_ccompare(void)
}
}
}
#endif // __XTENSA__
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
static void IRAM_ATTR leave_idle(void)
{
@ -656,7 +656,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
/* Adjust RTOS tick count based on the amount of time spent in sleep */
vTaskStepTick(slept_ticks);
#if __XTENSA__
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
/* Trigger tick interrupt, since sleep time was longer
* than portTICK_PERIOD_MS. Note that setting INTSET does not
* work for timer interrupt, and changing CCOMPARE would clear
@ -666,7 +666,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime )
while (!(XTHAL_GET_INTERRUPT() & BIT(XT_TIMER_INTNUM))) {
;
}
#elif __riscv
#else
portYIELD_WITHIN_API();
#endif
}
@ -810,7 +810,7 @@ void IRAM_ATTR esp_pm_impl_isr_hook(void)
* from happening in this section, since they will also call into esp_pm_impl_isr_hook.
*/
uint32_t state = portENTER_CRITICAL_NESTED();
#if __XTENSA__ && (portNUM_PROCESSORS == 2)
#if defined(CONFIG_FREERTOS_SYSTICK_USES_CCOUNT) && (portNUM_PROCESSORS == 2)
if (s_need_update_ccompare[core_id]) {
update_ccompare();
s_need_update_ccompare[core_id] = false;
@ -819,7 +819,7 @@ void IRAM_ATTR esp_pm_impl_isr_hook(void)
}
#else
leave_idle();
#endif // portNUM_PROCESSORS == 2
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT && portNUM_PROCESSORS == 2
portEXIT_CRITICAL_NESTED(state);
ESP_PM_TRACE_EXIT(ISR_HOOK, core_id);
}

View File

@ -110,7 +110,7 @@ void IRAM_ATTR esp_restart_noos(void)
// Reset timer/spi/uart
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG,
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST);
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST);
REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0);
// Reset dma
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);

View File

@ -94,7 +94,7 @@ void IRAM_ATTR esp_restart_noos(void)
// Reset timer/spi/uart
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG,
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST);
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST);
REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0);
// Reset dma
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);

View File

@ -103,7 +103,7 @@ void IRAM_ATTR esp_restart_noos(void)
// Reset timer/spi/uart
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG,
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST);
SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST);
REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0);
// Reset dma

View File

@ -133,7 +133,7 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
&timer_alarm_isr, NULL, &s_timer_interrupt_handle);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (%#x)", err);
ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%x)", err);
goto err_intr_alloc;
}
@ -155,7 +155,7 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
err = esp_intr_enable(s_timer_interrupt_handle);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "esp_intr_enable failed (%#x)", err);
ESP_EARLY_LOGE(TAG, "esp_intr_enable failed (0x%x)", err);
goto err_intr_en;
}
return ESP_OK;

View File

@ -6,8 +6,7 @@ endif()
idf_build_get_property(target IDF_TARGET)
# should test arch here not target, TODO ESP32-C3 IDF-1754
if(NOT "${target}" STREQUAL "esp32c3" AND NOT "${target}" STREQUAL "esp32h2")
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
set(srcs
"port/xtensa/port.c"
"port/xtensa/portasm.S"
@ -25,10 +24,10 @@ if(NOT "${target}" STREQUAL "esp32c3" AND NOT "${target}" STREQUAL "esp32h2")
include/freertos
port/xtensa/include/freertos
port/xtensa
port/priv_include
.)
set(required_components app_trace esp_timer)
else() # RISC-V
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
set(srcs
"port/riscv/port.c"
"port/riscv/portasm.S")
@ -41,13 +40,14 @@ else() # RISC-V
include/freertos
port/riscv/include/freertos
port/riscv
port/priv_include
.)
set(required_components app_trace esp_timer)
endif()
list(APPEND srcs
"port/port_common.c"
"port/port_systick.c"
"croutine.c"
"event_groups.c"
"list.c"
@ -62,8 +62,11 @@ if(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY)
list(APPEND srcs "port/xtensa/xtensa_loadstore_handler.S")
endif()
# esp_timer is required by FreeRTOS because we use esp_tiemr_get_time() to do profiling
# app_trace is required by FreeRTOS headers only when CONFIG_APPTRACE_SV_ENABLE=y,
# but requirements can't depend on config options, so always require it.
# REQUIRES can't depend on config options, so always require it.
set(required_components app_trace esp_timer)
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ${include_dirs}
PRIV_INCLUDE_DIRS ${private_include_dirs}

View File

@ -18,9 +18,23 @@ menu "FreeRTOS"
hex
default 0x7FFFFFFF
config FREERTOS_TICK_SUPPORT_CORETIMER
bool
default y if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2
config FREERTOS_TICK_SUPPORT_SYSTIMER
bool
default y if !FREERTOS_TICK_SUPPORT_CORETIMER
# ESP32-S3, ESP32-C3 and ESP32-H2 can use Systimer for FreeRTOS SysTick
# ESP32S2 also has SYSTIMER but it can not be used for the FreeRTOS SysTick because:
# - It has only one counter, which already in use esp_timer.
# A counter for SysTick should be stall in debug mode but work esp_timer.
# - It is not possible to allocate two handlers for esp_timer and SysTick.
choice FREERTOS_CORETIMER
prompt "Xtensa timer to use as the FreeRTOS tick source"
default FREERTOS_CORETIMER_0
default FREERTOS_CORETIMER_0 if FREERTOS_TICK_SUPPORT_CORETIMER
default FREERTOS_CORETIMER_SYSTIMER_LVL1 if FREERTOS_TICK_SUPPORT_SYSTIMER
help
FreeRTOS needs a timer with an associated interrupt to use as
the main tick source to increase counters, run timers and do
@ -29,16 +43,38 @@ menu "FreeRTOS"
config FREERTOS_CORETIMER_0
bool "Timer 0 (int 6, level 1)"
depends on FREERTOS_TICK_SUPPORT_CORETIMER
help
Select this to use timer 0
config FREERTOS_CORETIMER_1
bool "Timer 1 (int 15, level 3)"
depends on FREERTOS_TICK_SUPPORT_CORETIMER
help
Select this to use timer 1
config FREERTOS_CORETIMER_SYSTIMER_LVL1
bool "SYSTIMER 0 (level 1)"
depends on FREERTOS_TICK_SUPPORT_SYSTIMER
help
Select this to use systimer with the 1 interrupt priority.
config FREERTOS_CORETIMER_SYSTIMER_LVL3
bool "SYSTIMER 0 (level 3)"
depends on FREERTOS_TICK_SUPPORT_SYSTIMER
help
Select this to use systimer with the 3 interrupt priority.
endchoice
config FREERTOS_SYSTICK_USES_SYSTIMER
bool
default y if FREERTOS_CORETIMER_SYSTIMER_LVL1 || FREERTOS_CORETIMER_SYSTIMER_LVL3
config FREERTOS_SYSTICK_USES_CCOUNT
bool
default y if FREERTOS_CORETIMER_0 || FREERTOS_CORETIMER_1
config FREERTOS_OPTIMIZED_SCHEDULER
bool "Enable FreeRTOS pĺatform optimized scheduler"
depends on FREERTOS_UNICORE
@ -343,6 +379,7 @@ menu "FreeRTOS"
config FREERTOS_RUN_TIME_STATS_USING_CPU_CLK
bool "Use CPU Clock for run time stats"
depends on FREERTOS_SYSTICK_USES_CCOUNT
help
CPU Clock will be used as the clock source for the generation of run
time stats. The CPU Clock has a frequency dependent on

View File

@ -7,7 +7,7 @@ ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE
endif
COMPONENT_ADD_INCLUDEDIRS := include port/xtensa/include
COMPONENT_PRIV_INCLUDEDIRS := include/freertos port/xtensa/include/freertos port/xtensa .
COMPONENT_PRIV_INCLUDEDIRS := include/freertos port/xtensa/include/freertos port/xtensa port/priv_include .
COMPONENT_SRCDIRS += port port/xtensa
ifndef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY

View File

@ -0,0 +1,172 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
#include "soc/cpu.h"
#include "FreeRTOS.h"
#include "task.h"
#include "esp_intr_alloc.h"
#include "esp_err.h"
#include "esp_log.h"
#include "sdkconfig.h"
#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
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
void SysTickIsrHandler(void *arg);
#ifdef CONFIG_FREERTOS_UNICORE
static uint32_t s_handled_systicks[1] = { 0 };
#else
static uint32_t s_handled_systicks[2] = { 0 };
#endif
#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
#ifdef CONFIG_FREERTOS_UNICORE
const unsigned max_cpu = 1;
#else
const unsigned max_cpu = 2;
#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 < max_cpu; ++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);
// 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);
}
}
} 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
/**
* @brief Handler of SysTick
*
* The function is called from:
* - _frxt_timer_int for xtensa with CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
* - SysTickIsrHandler for xtensa with CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
* - SysTickIsrHandler for riscv
*/
BaseType_t xPortSysTickHandler(void)
{
portbenchmarkIntLatency();
traceISR_ENTER(SYSTICK_INTR_ID);
BaseType_t ret = xTaskIncrementTick();
if(ret != pdFALSE) {
portYIELD_FROM_ISR();
} else {
traceISR_EXIT();
}
return ret;
}

View File

@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set up the SysTick interrupt
*/
void vPortSetupTimer(void);
#ifdef __cplusplus
}
#endif

View File

@ -91,6 +91,7 @@
#include "riscv/riscv_interrupts.h"
#include "riscv/interrupt.h"
#include "port_systick.h"
#include "esp_system.h"
#include "esp_intr_alloc.h"
#include "esp_private/crosscore_int.h"
@ -115,8 +116,6 @@ StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOIN
static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
static void vPortSysTickHandler(void *arg);
static void vPortSetupTimer(void);
static void prvTaskExitError(void);
extern void esprv_intc_int_set_threshold(int); // FIXME, this function is in ROM only
@ -141,27 +140,6 @@ void vPortExitCritical(void)
}
}
/**
* @brief Set up the systimer peripheral to generate the tick interrupt
*
*/
void vPortSetupTimer(void)
{
/* 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, ESP_INTR_FLAG_IRAM, vPortSysTickHandler, &systimer_hal, NULL));
/* configure the timer */
systimer_hal_init(&systimer_hal);
systimer_hal_connect_alarm_counter(&systimer_hal, SYSTIMER_LL_ALARM_OS_TICK_CORE0, SYSTIMER_LL_COUNTER_OS_TICK);
systimer_hal_enable_counter(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK);
systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, 0, true);
systimer_hal_set_alarm_period(&systimer_hal, SYSTIMER_LL_ALARM_OS_TICK_CORE0, 1000000UL / CONFIG_FREERTOS_HZ);
systimer_hal_select_alarm_mode(&systimer_hal, SYSTIMER_LL_ALARM_OS_TICK_CORE0, SYSTIMER_ALARM_MODE_PERIOD);
systimer_hal_enable_alarm_int(&systimer_hal, SYSTIMER_LL_ALARM_OS_TICK_CORE0);
}
void prvTaskExitError(void)
{
/* A function that implements a task must not exit or attempt to return to
@ -293,35 +271,13 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
return (StackType_t *)frame;
}
IRAM_ATTR void vPortSysTickHandler(void *arg)
{
systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg;
systimer_ll_clear_alarm_int(systimer_hal->dev, SYSTIMER_LL_ALARM_OS_TICK_CORE0);
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_ENTER(TICK, xPortGetCoreID());
#endif
if (!uxSchedulerRunning) {
return;
}
if (xTaskIncrementTick() != pdFALSE) {
vPortYieldFromISR();
}
#ifdef CONFIG_PM_TRACE
ESP_PM_TRACE_EXIT(TICK, xPortGetCoreID());
#endif
}
BaseType_t xPortStartScheduler(void)
{
uxInterruptNesting = 0;
uxCriticalNesting = 0;
uxSchedulerRunning = 0;
/* Setup the hardware to generate the tick. */
vPortSetupTimer();
esprv_intc_int_set_threshold(1); /* set global INTC masking level */

View File

@ -50,6 +50,7 @@ Should be included by all Xtensa generic and RTOS port-specific sources.
#include <xtensa/corebits.h>
#include <xtensa/config/system.h>
#include "sdkconfig.h"
/*
Include any RTOS specific definitions that are needed by this header.
@ -145,7 +146,9 @@ May be coded in or called from C or assembly, per ABI conventions.
RTOS may optionally define XT_TICK_PER_SEC in its own way (eg. macro).
*/
// void XT_RTOS_TIMER_INT(void)
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
#define XT_RTOS_TIMER_INT _frxt_timer_int
#endif
#define XT_TICK_PER_SEC configTICK_RATE_HZ
/*

View File

@ -130,25 +130,16 @@
#include "esp32s3/spiram.h"
#endif
#include "port_systick.h"
#include "esp_private/startup_internal.h" // [refactor-todo] for g_spiram_ok
#include "esp_app_trace.h" // [refactor-todo] for esp_app_trace_init
/* Defined in portasm.h */
extern void _frxt_tick_timer_init(void);
/* Defined in xtensa_context.S */
extern void _xt_coproc_init(void);
static const char* TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
// for now maintain the same log output
#if CONFIG_FREERTOS_CORETIMER_0
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
#endif
#if CONFIG_FREERTOS_CORETIMER_1
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
#endif
_Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_AFFINITY value");
/*-----------------------------------------------------------*/
@ -303,11 +294,8 @@ BaseType_t xPortStartScheduler( void )
_xt_coproc_init();
#endif
/* Init the tick divisor value */
_xt_tick_divisor_init();
/* Setup the hardware to generate the tick. */
_frxt_tick_timer_init();
vPortSetupTimer();
port_xSchedulerRunning[xPortGetCoreID()] = 1;
@ -319,23 +307,6 @@ BaseType_t xPortStartScheduler( void )
}
/*-----------------------------------------------------------*/
BaseType_t xPortSysTickHandler( void )
{
BaseType_t ret;
portbenchmarkIntLatency();
traceISR_ENTER(SYSTICK_INTR_ID);
ret = xTaskIncrementTick();
if( ret != pdFALSE )
{
portYIELD_FROM_ISR();
} else {
traceISR_EXIT();
}
return ret;
}
void vPortYieldOtherCore( BaseType_t coreid ) {
esp_crosscore_int_send_yield( coreid );
}

View File

@ -270,6 +270,7 @@ _frxt_int_exit:
*
**********************************************************************************************************
*/
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
.globl _frxt_timer_int
.type _frxt_timer_int,@function
.align 4
@ -321,7 +322,7 @@ _frxt_timer_int:
s32i a3, sp, 8
#endif
/* Call the FreeRTOS tick handler (see port.c). */
/* Call the FreeRTOS tick handler (see port_systick.c). */
#ifdef __XTENSA_CALL0_ABI__
call0 xPortSysTickHandler
#else
@ -347,6 +348,7 @@ _frxt_timer_int:
#endif // CONFIG_PM_TRACE
RET(16)
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
/*
**********************************************************************************************************
@ -358,6 +360,7 @@ _frxt_timer_int:
*
**********************************************************************************************************
*/
#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
.globl _frxt_tick_timer_init
.type _frxt_tick_timer_init,@function
.align 4
@ -391,6 +394,7 @@ _frxt_tick_timer_init:
#endif
RET(16)
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
/*
**********************************************************************************************************

View File

@ -289,9 +289,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
rsil a3, \level - 1 /* lower interrupt level by 1 */
#endif
#ifdef XT_RTOS_TIMER_INT
movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */
wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */
beq a3, a4, 7f /* if timer interrupt then skip table */
#else
wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */
#endif // XT_RTOS_TIMER_INT
find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */
@ -316,6 +320,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
j .L_xt_user_int_&level& /* check for more interrupts */
#endif
#ifdef XT_RTOS_TIMER_INT
7:
.ifeq XT_TIMER_INTPRI - \level
@ -335,6 +340,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
call4 XT_RTOS_TIMER_INT
#endif
.endif
#endif // XT_RTOS_TIMER_INT
#ifdef XT_USE_SWPRI
j 8f

View File

@ -124,6 +124,11 @@ __attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(s
dev->target_conf[alarm_id].target_period = period;
}
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
{
return dev->target_conf[alarm_id].target_period;
}
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
{
dev->comp_load[alarm_id].val = 0x01;

View File

@ -124,6 +124,11 @@ __attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(s
dev->target_conf[alarm_id].target_period = period;
}
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
{
return dev->target_conf[alarm_id].target_period;
}
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
{
dev->comp_load[alarm_id].val = 0x01;

View File

@ -135,6 +135,11 @@ __attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(s
dev->target_conf[alarm_id].target_period = period;
}
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
{
return dev->target_conf[alarm_id].target_period;
}
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
{
(void)dev;

View File

@ -125,6 +125,11 @@ __attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(s
dev->target_conf[alarm_id].target_period = period;
}
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id)
{
return dev->target_conf[alarm_id].target_period;
}
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id)
{
dev->comp_load[alarm_id].val = 0x01;

View File

@ -251,6 +251,7 @@ static void get_time_task(void *pvParameters)
// although exit flag is set in another task, checking (exit_flag == false) is safe
while (exit_flag == false) {
gettimeofday(&tv_time, NULL);
vTaskDelay(1500 / portTICK_PERIOD_MS);
}
xSemaphoreGive(*sema);
vTaskDelete(NULL);
@ -259,13 +260,9 @@ static void get_time_task(void *pvParameters)
static void start_measure(int64_t* sys_time, int64_t* real_time)
{
struct timeval tv_time;
int64_t t1, t2;
do {
t1 = esp_timer_get_time();
gettimeofday(&tv_time, NULL);
t2 = esp_timer_get_time();
} while (t2 - t1 > 40);
*real_time = t2;
// there shouldn't be much time between gettimeofday and esp_timer_get_time
gettimeofday(&tv_time, NULL);
*real_time = esp_timer_get_time();
*sys_time = (int64_t)tv_time.tv_sec * 1000000L + tv_time.tv_usec;
}
@ -301,7 +298,7 @@ static void measure_time_task(void *pvParameters)
int64_t sys_time_us[2] = { main_sys_time_us[0], 0};
// although exit flag is set in another task, checking (exit_flag == false) is safe
while (exit_flag == false) {
esp_rom_delay_us(2 * 1000000); // 2 sec
vTaskDelay(2000 / portTICK_PERIOD_MS);
start_measure(&sys_time_us[1], &real_time_us[1]);
result_adjtime_correction_us[1] += calc_correction("measure", sys_time_us, real_time_us);
@ -322,7 +319,7 @@ static void measure_time_task(void *pvParameters)
vTaskDelete(NULL);
}
TEST_CASE("test time adjustment happens linearly", "[newlib][timeout=35]")
TEST_CASE("test time adjustment happens linearly", "[newlib][timeout=15]")
{
exit_flag = false;
@ -335,8 +332,8 @@ TEST_CASE("test time adjustment happens linearly", "[newlib][timeout=35]")
xTaskCreatePinnedToCore(get_time_task, "get_time_task", 4096, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
xTaskCreatePinnedToCore(measure_time_task, "measure_time_task", 4096, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
printf("start waiting for 30 seconds\n");
vTaskDelay(30000 / portTICK_PERIOD_MS);
printf("start waiting for 10 seconds\n");
vTaskDelay(10000 / portTICK_PERIOD_MS);
// set exit flag to let thread exit
exit_flag = true;

View File

@ -0,0 +1,4 @@
CONFIG_IDF_TARGET="esp32s3"
TEST_COMPONENTS=esp_pm
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y