Merge branch 'feature/esp_timer_uses_shared_isr' into 'master'

esp_timer: Adds TASK and ISR AFFINITY to core options

Closes IDFGH-9053

See merge request espressif/esp-idf!21923
This commit is contained in:
Konstantin Kondrashov 2023-03-07 13:38:23 +08:00
commit cf68a4c136
12 changed files with 339 additions and 82 deletions

View File

@ -14,7 +14,7 @@
# esp_timer has to be initialized early, since it is used by several other components
100: esp_timer_startup_init in components/esp_timer/src/esp_timer.c on BIT(0)
100: esp_timer_startup_init in components/esp_timer/src/esp_timer.c on CONFIG_ESP_TIMER_ISR_AFFINITY
# esp_sleep doesn't have init dependencies
105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0)

View File

@ -30,7 +30,7 @@ menu "High resolution timer (esp_timer)"
Note that this is not the same as FreeRTOS timer task. To configure
FreeRTOS timer task size, see "FreeRTOS timer task stack size" option
in "FreeRTOS" menu.
in "FreeRTOS".
config ESP_TIMER_INTERRUPT_LEVEL
int "Interrupt level"
@ -41,6 +41,69 @@ menu "High resolution timer (esp_timer)"
It sets the interrupt level for esp_timer ISR in range 1..3.
A higher level (3) helps to decrease the ISR esp_timer latency.
config ESP_TIMER_SHOW_EXPERIMENTAL
bool "show esp_timer's experimental features"
help
This shows some hidden features of esp_timer.
Note that they may break other features, use them with care.
config ESP_TIMER_TASK_AFFINITY
hex
default 0x0 if ESP_TIMER_TASK_AFFINITY_CPU0
default 0x1 if ESP_TIMER_TASK_AFFINITY_CPU1
default FREERTOS_NO_AFFINITY if ESP_TIMER_TASK_AFFINITY_NO_AFFINITY
choice ESP_TIMER_TASK_AFFINITY
prompt "esp_timer task core affinity"
default ESP_TIMER_TASK_AFFINITY_CPU0
help
The default settings: timer TASK on CPU0 and timer ISR on CPU0.
Other settings may help in certain cases, but note that they may break
other features, use them with care.
- "CPU0": (default) esp_timer task is processed by CPU0.
- "CPU1": esp_timer task is processed by CPU1.
- "No affinity": esp_timer task can be processed by any CPU.
config ESP_TIMER_TASK_AFFINITY_CPU0
bool "CPU0"
config ESP_TIMER_TASK_AFFINITY_CPU1
bool "CPU1"
depends on !FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL
config ESP_TIMER_TASK_AFFINITY_NO_AFFINITY
bool "No affinity"
depends on !FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL
endchoice
config ESP_TIMER_ISR_AFFINITY
hex
default 0x1 if ESP_TIMER_ISR_AFFINITY_CPU0
default 0x2 if ESP_TIMER_ISR_AFFINITY_CPU1
default FREERTOS_NO_AFFINITY if ESP_TIMER_ISR_AFFINITY_NO_AFFINITY
choice ESP_TIMER_ISR_AFFINITY
prompt "timer interrupt core affinity"
default ESP_TIMER_ISR_AFFINITY_CPU0
help
The default settings: timer TASK on CPU0 and timer ISR on CPU0.
Other settings may help in certain cases, but note that they may break
other features, use them with care.
- "CPU0": (default) timer interrupt is processed by CPU0.
- "CPU1": timer interrupt is processed by CPU1.
- "No affinity": timer interrupt can be processed by any CPU. It helps
to reduce latency but there is a disadvantage it leads to the timer ISR
running on every core. It increases the CPU time usage for timer ISRs
by N on an N-core system.
config ESP_TIMER_ISR_AFFINITY_CPU0
bool "CPU0"
config ESP_TIMER_ISR_AFFINITY_CPU1
bool "CPU1"
depends on !FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL
config ESP_TIMER_ISR_AFFINITY_NO_AFFINITY
bool "No affinity"
depends on !FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL
endchoice
config ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
bool "Support ISR dispatch method"
default n

View File

@ -98,6 +98,11 @@ esp_err_t esp_timer_early_init(void);
* Before calling this function, esp_timer_early_init must be called by the
* startup code.
*
* This function will be called from startup code on every core
* if CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY is enabled,
* It allocates the timer ISR on MULTIPLE cores and
* creates the timer task which can be run on any core.
*
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if allocation has failed

View File

@ -15,6 +15,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_ipc.h"
#include "esp_timer.h"
#include "esp_timer_impl.h"
@ -479,37 +480,58 @@ esp_err_t esp_timer_early_init(void)
return ESP_OK;
}
esp_err_t esp_timer_init(void)
static esp_err_t init_timer_task(void)
{
esp_err_t err;
esp_err_t err = ESP_OK;
if (is_initialized()) {
return ESP_ERR_INVALID_STATE;
}
int ret = xTaskCreatePinnedToCore(&timer_task, "esp_timer",
ESP_TASK_TIMER_STACK, NULL, ESP_TASK_TIMER_PRIO, &s_timer_task, PRO_CPU_NUM);
ESP_EARLY_LOGE(TAG, "Task is already initialized");
err = ESP_ERR_INVALID_STATE;
} else {
int ret = xTaskCreatePinnedToCore(
&timer_task, "esp_timer",
ESP_TASK_TIMER_STACK, NULL, ESP_TASK_TIMER_PRIO,
&s_timer_task, CONFIG_ESP_TIMER_TASK_AFFINITY);
if (ret != pdPASS) {
ESP_EARLY_LOGE(TAG, "Not enough memory to create timer task");
err = ESP_ERR_NO_MEM;
goto out;
}
err = esp_timer_impl_init(&timer_alarm_handler);
if (err != ESP_OK) {
goto out;
}
return err;
}
return ESP_OK;
out:
static void deinit_timer_task(void)
{
if (s_timer_task) {
vTaskDelete(s_timer_task);
s_timer_task = NULL;
}
return ESP_ERR_NO_MEM;
}
ESP_SYSTEM_INIT_FN(esp_timer_startup_init, BIT(0), 100)
esp_err_t esp_timer_init(void)
{
esp_err_t err = ESP_OK;
#ifndef CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY
err = init_timer_task();
#else
/* This function will be run on all cores if CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY is enabled,
* We do it that way because we need to allocate the timer ISR on MULTIPLE cores.
* timer task will be created by CPU0.
*/
if (xPortGetCoreID() == 0) {
err = init_timer_task();
}
#endif // CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY
if (err == ESP_OK) {
err = esp_timer_impl_init(&timer_alarm_handler);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "ISR init failed");
deinit_timer_task();
}
}
return err;
}
ESP_SYSTEM_INIT_FN(esp_timer_startup_init, CONFIG_ESP_TIMER_ISR_AFFINITY, 100)
{
return esp_timer_init();
}
@ -539,9 +561,7 @@ esp_err_t esp_timer_deinit(void)
#endif
esp_timer_impl_deinit();
vTaskDelete(s_timer_task);
s_timer_task = NULL;
deinit_timer_task();
return ESP_OK;
}

View File

@ -83,8 +83,15 @@ typedef struct {
static const char* TAG = "esp_timer_impl";
#define NOT_USED 0xBAD00FAD
/* Interrupt handle returned by the interrupt allocator */
static intr_handle_t s_timer_interrupt_handle;
#ifdef CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY
#define ISR_HANDLERS (portNUM_PROCESSORS)
#else
#define ISR_HANDLERS (1)
#endif
static intr_handle_t s_timer_interrupt_handle[ISR_HANDLERS] = { NULL };
/* Function from the upper layer to be called when the interrupt happens.
* Registered in esp_timer_impl_init.
@ -180,10 +187,47 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
static void IRAM_ATTR timer_alarm_isr(void *arg)
{
#if ISR_HANDLERS == 1
/* Clear interrupt status */
REG_WRITE(INT_CLR_REG, TIMG_LACT_INT_CLR);
/* Call the upper layer handler */
(*s_alarm_handler)(arg);
#else
static volatile uint32_t processed_by = NOT_USED;
static volatile bool pending_alarm = false;
/* CRITICAL section ensures the read/clear is atomic between cores */
portENTER_CRITICAL_ISR(&s_time_update_lock);
if (REG_GET_FIELD(INT_ST_REG, TIMG_LACT_INT_ST)) {
// Clear interrupt status
REG_WRITE(INT_CLR_REG, TIMG_LACT_INT_CLR);
// Is the other core already processing a previous alarm?
if (processed_by == NOT_USED) {
// Current core is not processing an alarm yet
processed_by = xPortGetCoreID();
do {
pending_alarm = false;
// Clear interrupt status
REG_WRITE(INT_CLR_REG, TIMG_LACT_INT_CLR);
portEXIT_CRITICAL_ISR(&s_time_update_lock);
(*s_alarm_handler)(arg);
portENTER_CRITICAL_ISR(&s_time_update_lock);
// Another alarm could have occurred while were handling the previous alarm.
// Check if we need to call the s_alarm_handler again:
// 1) if the alarm has already been fired, it helps to handle it immediately without an additional ISR call.
// 2) handle pending alarm that was cleared by the other core in time when this core worked with the current alarm.
} while (REG_GET_FIELD(INT_ST_REG, TIMG_LACT_INT_ST) || pending_alarm);
processed_by = NOT_USED;
} else {
// Current core arrived at ISR but the other core is still handling a previous alarm.
// Once we already cleared the ISR status we need to let the other core know that it was.
// Set the flag to handle the current alarm by the other core later.
pending_alarm = true;
}
}
portEXIT_CRITICAL_ISR(&s_time_update_lock);
#endif // ISR_HANDLERS != 1
}
void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
@ -232,18 +276,26 @@ esp_err_t esp_timer_impl_early_init(void)
esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
{
s_alarm_handler = alarm_handler;
if (s_timer_interrupt_handle[(ISR_HANDLERS == 1) ? 0 : xPortGetCoreID()] != NULL) {
ESP_EARLY_LOGE(TAG, "timer ISR is already initialized");
return ESP_ERR_INVALID_STATE;
}
const int interrupt_lvl = (1 << CONFIG_ESP_TIMER_INTERRUPT_LEVEL) & ESP_INTR_FLAG_LEVELMASK;
esp_err_t err = esp_intr_alloc(INTR_SOURCE_LACT,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM | interrupt_lvl,
&timer_alarm_isr, NULL, &s_timer_interrupt_handle);
int isr_flags = ESP_INTR_FLAG_INTRDISABLED
| ((1 << CONFIG_ESP_TIMER_INTERRUPT_LEVEL) & ESP_INTR_FLAG_LEVELMASK)
| ESP_INTR_FLAG_IRAM;
esp_err_t err = esp_intr_alloc(INTR_SOURCE_LACT, isr_flags,
&timer_alarm_isr, NULL,
&s_timer_interrupt_handle[(ISR_HANDLERS == 1) ? 0 : xPortGetCoreID()]);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%0x)", err);
ESP_EARLY_LOGE(TAG, "Can not allocate ISR handler (0x%0x)", err);
return err;
}
if (s_alarm_handler == NULL) {
s_alarm_handler = alarm_handler;
/* In theory, this needs a shared spinlock with the timer group driver.
* However since esp_timer_impl_init is called early at startup, this
* will not cause issues in practice.
@ -256,10 +308,14 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
// from a slow_clk frequency instead of the APB frequency.
uint32_t slowclk_ticks_per_us = esp_clk_slowclk_cal_get() * TICKS_PER_US;
REG_SET_FIELD(RTC_STEP_REG, TIMG_LACT_RTC_STEP_LEN, slowclk_ticks_per_us);
}
ESP_ERROR_CHECK( esp_intr_enable(s_timer_interrupt_handle) );
err = esp_intr_enable(s_timer_interrupt_handle[(ISR_HANDLERS == 1) ? 0 : xPortGetCoreID()]);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Can not enable ISR (0x%0x)", err);
}
return ESP_OK;
return err;
}
void esp_timer_impl_deinit(void)
@ -267,10 +323,14 @@ void esp_timer_impl_deinit(void)
REG_WRITE(CONFIG_REG, 0);
REG_SET_BIT(INT_CLR_REG, TIMG_LACT_INT_CLR);
/* TODO: also clear TIMG_LACT_INT_ENA; however see the note in esp_timer_impl_init. */
esp_intr_disable(s_timer_interrupt_handle);
esp_intr_free(s_timer_interrupt_handle);
s_timer_interrupt_handle = NULL;
for (unsigned i = 0; i < ISR_HANDLERS; i++) {
if (s_timer_interrupt_handle[i] != NULL) {
esp_intr_disable(s_timer_interrupt_handle[i]);
esp_intr_free(s_timer_interrupt_handle[i]);
s_timer_interrupt_handle[i] = NULL;
}
}
s_alarm_handler = NULL;
}
/* FIXME: This value is safe for 80MHz APB frequency, should be modified to depend on clock frequency. */

View File

@ -36,8 +36,15 @@
static const char *TAG = "esp_timer_systimer";
#define NOT_USED 0xBAD00FAD
/* Interrupt handle returned by the interrupt allocator */
static intr_handle_t s_timer_interrupt_handle;
#ifdef CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY
#define ISR_HANDLERS (portNUM_PROCESSORS)
#else
#define ISR_HANDLERS (1)
#endif
static intr_handle_t s_timer_interrupt_handle[ISR_HANDLERS] = { NULL };
/* Function from the upper layer to be called when the interrupt happens.
* Registered in esp_timer_impl_init.
@ -91,10 +98,47 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
static void IRAM_ATTR timer_alarm_isr(void *arg)
{
#if ISR_HANDLERS == 1
// clear the interrupt
systimer_ll_clear_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER);
/* Call the upper layer handler */
(*s_alarm_handler)(arg);
#else
static volatile uint32_t processed_by = NOT_USED;
static volatile bool pending_alarm = false;
/* CRITICAL section ensures the read/clear is atomic between cores */
portENTER_CRITICAL_ISR(&s_time_update_lock);
if (systimer_ll_is_alarm_int_fired(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER)) {
// Clear interrupt status
systimer_ll_clear_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER);
// Is the other core already processing a previous alarm?
if (processed_by == NOT_USED) {
// Current core is not processing an alarm yet
processed_by = xPortGetCoreID();
do {
pending_alarm = false;
// Clear interrupt status
systimer_ll_clear_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER);
portEXIT_CRITICAL_ISR(&s_time_update_lock);
(*s_alarm_handler)(arg);
portENTER_CRITICAL_ISR(&s_time_update_lock);
// Another alarm could have occurred while were handling the previous alarm.
// Check if we need to call the s_alarm_handler again:
// 1) if the alarm has already been fired, it helps to handle it immediately without an additional ISR call.
// 2) handle pending alarm that was cleared by the other core in time when this core worked with the current alarm.
} while (systimer_ll_is_alarm_int_fired(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER) || pending_alarm);
processed_by = NOT_USED;
} else {
// Current core arrived at ISR but the other core is still handling a previous alarm.
// Once we already cleared the ISR status we need to let the other core know that it was.
// Set the flag to handle the current alarm by the other core later.
pending_alarm = true;
}
}
portEXIT_CRITICAL_ISR(&s_time_update_lock);
#endif // ISR_HANDLERS != 1
}
void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
@ -148,53 +192,55 @@ esp_err_t esp_timer_impl_early_init(void)
esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
{
s_alarm_handler = alarm_handler;
const int interrupt_lvl = (1 << CONFIG_ESP_TIMER_INTERRUPT_LEVEL) & ESP_INTR_FLAG_LEVELMASK;
#if SOC_SYSTIMER_INT_LEVEL
int int_type = 0;
#else
int int_type = ESP_INTR_FLAG_EDGE;
#endif // SOC_SYSTIMER_INT_LEVEL
esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM | int_type | interrupt_lvl,
&timer_alarm_isr, NULL, &s_timer_interrupt_handle);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%x)", err);
goto err_intr_alloc;
if (s_timer_interrupt_handle[(ISR_HANDLERS == 1) ? 0 : xPortGetCoreID()] != NULL) {
ESP_EARLY_LOGE(TAG, "timer ISR is already initialized");
return ESP_ERR_INVALID_STATE;
}
int isr_flags = ESP_INTR_FLAG_INTRDISABLED
| ((1 << CONFIG_ESP_TIMER_INTERRUPT_LEVEL) & ESP_INTR_FLAG_LEVELMASK)
#if !SOC_SYSTIMER_INT_LEVEL
| ESP_INTR_FLAG_EDGE
#endif
| ESP_INTR_FLAG_IRAM;
esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE, isr_flags,
&timer_alarm_isr, NULL,
&s_timer_interrupt_handle[(ISR_HANDLERS == 1) ? 0 : xPortGetCoreID()]);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%x)", err);
return err;
}
if (s_alarm_handler == NULL) {
s_alarm_handler = alarm_handler;
/* TODO: if SYSTIMER is used for anything else, access to SYSTIMER_INT_ENA_REG has to be
* protected by a shared spinlock. Since this code runs as part of early startup, this
* is practically not an issue.
*/
systimer_hal_enable_alarm_int(&systimer_hal, SYSTIMER_ALARM_ESPTIMER);
err = esp_intr_enable(s_timer_interrupt_handle);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "esp_intr_enable failed (0x%x)", err);
goto err_intr_en;
}
return ESP_OK;
err_intr_en:
systimer_ll_enable_alarm(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER, false);
/* TODO: may need a spinlock, see the note related to SYSTIMER_INT_ENA_REG in systimer_hal_init */
systimer_ll_enable_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER, false);
esp_intr_free(s_timer_interrupt_handle);
err_intr_alloc:
s_alarm_handler = NULL;
err = esp_intr_enable(s_timer_interrupt_handle[(ISR_HANDLERS == 1) ? 0 : xPortGetCoreID()]);
if (err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Can not enable ISR (0x%0x)", err);
}
return err;
}
void esp_timer_impl_deinit(void)
{
esp_intr_disable(s_timer_interrupt_handle);
systimer_ll_enable_alarm(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER, false);
/* TODO: may need a spinlock, see the note related to SYSTIMER_INT_ENA_REG in systimer_hal_init */
systimer_ll_enable_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_ESPTIMER, false);
esp_intr_free(s_timer_interrupt_handle);
s_timer_interrupt_handle = NULL;
for (unsigned i = 0; i < ISR_HANDLERS; i++) {
if (s_timer_interrupt_handle[i] != NULL) {
esp_intr_disable(s_timer_interrupt_handle[i]);
esp_intr_free(s_timer_interrupt_handle[i]);
s_timer_interrupt_handle[i] = NULL;
}
}
s_alarm_handler = NULL;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -1177,4 +1177,43 @@ TEST_CASE("Test ESP_TIMER_ISR, stop API cleans alarm reg if ISR timer list is em
vSemaphoreDelete(done);
printf("timer deleted\n");
}
#ifndef CONFIG_FREERTOS_UNICORE
static void task_callback3(void* arg)
{
int *data = (int *)arg;
++*data;
esp_rom_printf("callback from CPU%d\n", xPortGetCoreID());
#if defined(CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY) || defined(CONFIG_ESP_TIMER_ISR_AFFINITY_CPU1)
TEST_ASSERT_EQUAL_INT(1, xPortGetCoreID());
#endif // CONFIG_ESP_TIMER_AFFINITY_NO_AFFINITY
}
TEST_CASE("Test that CPU1 can handle esp_timer ISR even when CPU0 is blocked", "[esp_timer][isr_dispatch]")
{
int data = 0;
esp_timer_handle_t timer;
const esp_timer_create_args_t timer_args = {
.callback = &task_callback3,
.dispatch_method = ESP_TIMER_ISR,
.arg = &data,
.name = "test",
};
TEST_ESP_OK(esp_timer_create(&timer_args, &timer));
TEST_ESP_OK(esp_timer_start_periodic(timer, 10000));
portDISABLE_INTERRUPTS();
TEST_ASSERT_EQUAL_INT(0, xPortGetCoreID());
esp_rom_printf("CPU%d is blocked\n", xPortGetCoreID());
esp_rom_delay_us(100000);
esp_rom_printf("CPU%d is released\n", xPortGetCoreID());
portENABLE_INTERRUPTS();
TEST_ESP_OK(esp_timer_stop(timer));
TEST_ESP_OK(esp_timer_dump(stdout));
TEST_ASSERT_INT_WITHIN(3, 10, data);
TEST_ESP_OK(esp_timer_delete(timer));
}
#endif // not CONFIG_FREERTOS_UNICORE
#endif // CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD

View File

@ -10,6 +10,10 @@ CONFIGS = [
pytest.param('single_core', marks=[pytest.mark.esp32]),
pytest.param('freertos_compliance', marks=[pytest.mark.esp32]),
pytest.param('isr_dispatch_esp32', marks=[pytest.mark.esp32]),
pytest.param('cpu1_esp32', marks=[pytest.mark.esp32]),
pytest.param('any_cpu_esp32', marks=[pytest.mark.esp32]),
pytest.param('cpu1_esp32s3', marks=[pytest.mark.esp32s3]),
pytest.param('any_cpu_esp32s3', marks=[pytest.mark.esp32s3]),
]

View File

@ -0,0 +1,5 @@
CONFIG_IDF_TARGET="esp32"
CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y
CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL=y
CONFIG_ESP_TIMER_TASK_AFFINITY_NO_AFFINITY=y
CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY=y

View File

@ -0,0 +1,5 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y
CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL=y
CONFIG_ESP_TIMER_TASK_AFFINITY_NO_AFFINITY=y
CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY=y

View File

@ -0,0 +1,5 @@
CONFIG_IDF_TARGET="esp32"
CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y
CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL=y
CONFIG_ESP_TIMER_TASK_AFFINITY_CPU1=y
CONFIG_ESP_TIMER_ISR_AFFINITY_CPU1=y

View File

@ -0,0 +1,5 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y
CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL=y
CONFIG_ESP_TIMER_TASK_AFFINITY_CPU1=y
CONFIG_ESP_TIMER_ISR_AFFINITY_CPU1=y