feat(esp_timer): added kconfig option for placing IRAM code into flash

This commit is contained in:
Marius Vikhammer
2025-03-03 14:16:44 +08:00
parent 3fdcf31857
commit 55be8bdc0d
14 changed files with 123 additions and 82 deletions

View File

@@ -49,7 +49,7 @@ menu "Power Management"
config PM_SLP_IRAM_OPT
bool "Put lightsleep related codes in internal RAM"
depends on SOC_LIGHT_SLEEP_SUPPORTED
depends on SOC_LIGHT_SLEEP_SUPPORTED && ESP_TIMER_IN_IRAM
help
If enabled, about 2.1KB of lightsleep related source code would be in IRAM and chip would sleep
longer for 310us at 160MHz CPU frequency most each time.

View File

@@ -1,5 +1,9 @@
menu "ESP Timer (High Resolution Timer)"
config ESP_TIMER_IN_IRAM
bool "Place esp_timer functions in IRAM" if SPI_FLASH_AUTO_SUSPEND
default y
config ESP_TIMER_PROFILING
bool "Enable esp_timer profiling features"
default n
@@ -25,7 +29,7 @@ menu "ESP Timer (High Resolution Timer)"
help
Configure the stack size of "timer_task" task. This task is used
to dispatch callbacks of timers created using ets_timer and esp_timer
APIs. If you are seing stack overflow errors in timer task, increase
APIs. If you are seeing stack overflow errors in timer task, increase
this value.
Note that this is not the same as FreeRTOS timer task. To configure
@@ -102,7 +106,7 @@ menu "ESP Timer (High Resolution Timer)"
bool "Support ISR dispatch method"
default n
help
Allows using ESP_TIMER_ISR dispatch method (ESP_TIMER_TASK dispatch method is also avalible).
Allows using ESP_TIMER_ISR dispatch method (ESP_TIMER_TASK dispatch method is also available).
- ESP_TIMER_TASK - Timer callbacks are dispatched from a high-priority esp_timer task.
- ESP_TIMER_ISR - Timer callbacks are dispatched directly from the timer interrupt handler.
The ISR dispatch can be used, in some cases, when a callback is very simple

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -19,6 +19,13 @@
#include <stdint.h>
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "sdkconfig.h"
#if CONFIG_ESP_TIMER_IN_IRAM
#define ESP_TIMER_IRAM_ATTR IRAM_ATTR
#else
#define ESP_TIMER_IRAM_ATTR
#endif // CONFIG_ESP_TIMER_IN_IRAM
/**
* @brief Minimal initialization of platform specific layer of esp_timer

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -132,7 +132,7 @@ esp_err_t esp_timer_create(const esp_timer_create_args_t* args,
* But actually in IDF esp_timer_restart is used only in one place, which requires keeping
* in IRAM when PM_SLP_IRAM_OPT = y and ESP_TASK_WDT USE ESP_TIMER = y.
*/
esp_err_t IRAM_ATTR esp_timer_restart(esp_timer_handle_t timer, uint64_t timeout_us)
esp_err_t ESP_TIMER_IRAM_ATTR esp_timer_restart(esp_timer_handle_t timer, uint64_t timeout_us)
{
esp_err_t ret = ESP_OK;
@@ -177,7 +177,7 @@ esp_err_t IRAM_ATTR esp_timer_restart(esp_timer_handle_t timer, uint64_t timeout
return ret;
}
esp_err_t IRAM_ATTR esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us)
esp_err_t ESP_TIMER_IRAM_ATTR esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us)
{
if (timer == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -210,7 +210,7 @@ esp_err_t IRAM_ATTR esp_timer_start_once(esp_timer_handle_t timer, uint64_t time
return err;
}
esp_err_t IRAM_ATTR esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period_us)
esp_err_t ESP_TIMER_IRAM_ATTR esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period_us)
{
if (timer == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -240,7 +240,7 @@ esp_err_t IRAM_ATTR esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t
return err;
}
esp_err_t IRAM_ATTR esp_timer_stop(esp_timer_handle_t timer)
esp_err_t ESP_TIMER_IRAM_ATTR esp_timer_stop(esp_timer_handle_t timer)
{
if (timer == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -291,7 +291,7 @@ esp_err_t esp_timer_delete(esp_timer_handle_t timer)
return err;
}
static IRAM_ATTR esp_err_t timer_insert(esp_timer_handle_t timer, bool without_update_alarm)
static ESP_TIMER_IRAM_ATTR esp_err_t timer_insert(esp_timer_handle_t timer, bool without_update_alarm)
{
#if WITH_PROFILING
timer_remove_inactive(timer);
@@ -319,7 +319,7 @@ static IRAM_ATTR esp_err_t timer_insert(esp_timer_handle_t timer, bool without_u
return ESP_OK;
}
static IRAM_ATTR esp_err_t timer_remove(esp_timer_handle_t timer)
static ESP_TIMER_IRAM_ATTR esp_err_t timer_remove(esp_timer_handle_t timer)
{
esp_timer_dispatch_t dispatch_method = timer->flags & FL_ISR_DISPATCH_METHOD;
timer_list_lock(dispatch_method);
@@ -344,7 +344,7 @@ static IRAM_ATTR esp_err_t timer_remove(esp_timer_handle_t timer)
#if WITH_PROFILING
static IRAM_ATTR void timer_insert_inactive(esp_timer_handle_t timer)
static ESP_TIMER_IRAM_ATTR void timer_insert_inactive(esp_timer_handle_t timer)
{
/* May be locked or not, depending on where this is called from.
* Lock recursively.
@@ -361,30 +361,30 @@ static IRAM_ATTR void timer_insert_inactive(esp_timer_handle_t timer)
}
}
static IRAM_ATTR void timer_remove_inactive(esp_timer_handle_t timer)
static ESP_TIMER_IRAM_ATTR void timer_remove_inactive(esp_timer_handle_t timer)
{
LIST_REMOVE(timer, list_entry);
}
#endif // WITH_PROFILING
static IRAM_ATTR bool timer_armed(esp_timer_handle_t timer)
static ESP_TIMER_IRAM_ATTR bool timer_armed(esp_timer_handle_t timer)
{
return timer->alarm > 0;
}
static IRAM_ATTR void timer_list_lock(esp_timer_dispatch_t timer_type)
static ESP_TIMER_IRAM_ATTR void timer_list_lock(esp_timer_dispatch_t timer_type)
{
portENTER_CRITICAL_SAFE(&s_timer_lock[timer_type]);
}
static IRAM_ATTR void timer_list_unlock(esp_timer_dispatch_t timer_type)
static ESP_TIMER_IRAM_ATTR void timer_list_unlock(esp_timer_dispatch_t timer_type)
{
portEXIT_CRITICAL_SAFE(&s_timer_lock[timer_type]);
}
#ifdef CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
static IRAM_ATTR bool timer_process_alarm(esp_timer_dispatch_t dispatch_method)
static ESP_TIMER_IRAM_ATTR bool timer_process_alarm(esp_timer_dispatch_t dispatch_method)
#else
static bool timer_process_alarm(esp_timer_dispatch_t dispatch_method)
#endif
@@ -463,14 +463,14 @@ static void timer_task(void* arg)
}
#ifdef CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
IRAM_ATTR void esp_timer_isr_dispatch_need_yield(void)
ESP_TIMER_IRAM_ATTR void esp_timer_isr_dispatch_need_yield(void)
{
assert(xPortInIsrContext());
s_isr_dispatch_need_yield = pdTRUE;
}
#endif
static void IRAM_ATTR timer_alarm_handler(void* arg)
static void ESP_TIMER_IRAM_ATTR timer_alarm_handler(void* arg)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
bool isr_timers_processed = false;
@@ -491,7 +491,7 @@ static void IRAM_ATTR timer_alarm_handler(void* arg)
}
}
static IRAM_ATTR inline bool is_initialized(void)
static ESP_TIMER_IRAM_ATTR inline bool is_initialized(void)
{
return s_timer_task != NULL;
}
@@ -687,7 +687,7 @@ esp_err_t esp_timer_dump(FILE* stream)
return ESP_OK;
}
int64_t IRAM_ATTR esp_timer_get_next_alarm(void)
int64_t ESP_TIMER_IRAM_ATTR esp_timer_get_next_alarm(void)
{
int64_t next_alarm = INT64_MAX;
for (esp_timer_dispatch_t dispatch_method = ESP_TIMER_TASK; dispatch_method < ESP_TIMER_MAX; ++dispatch_method) {
@@ -703,7 +703,7 @@ int64_t IRAM_ATTR esp_timer_get_next_alarm(void)
return next_alarm;
}
int64_t IRAM_ATTR esp_timer_get_next_alarm_for_wake_up(void)
int64_t ESP_TIMER_IRAM_ATTR esp_timer_get_next_alarm_for_wake_up(void)
{
int64_t next_alarm = INT64_MAX;
for (esp_timer_dispatch_t dispatch_method = ESP_TIMER_TASK; dispatch_method < ESP_TIMER_MAX; ++dispatch_method) {
@@ -723,7 +723,7 @@ int64_t IRAM_ATTR esp_timer_get_next_alarm_for_wake_up(void)
return next_alarm;
}
esp_err_t IRAM_ATTR esp_timer_get_period(esp_timer_handle_t timer, uint64_t *period)
esp_err_t ESP_TIMER_IRAM_ATTR esp_timer_get_period(esp_timer_handle_t timer, uint64_t *period)
{
if (timer == NULL || period == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -738,7 +738,7 @@ esp_err_t IRAM_ATTR esp_timer_get_period(esp_timer_handle_t timer, uint64_t *per
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_timer_get_expiry_time(esp_timer_handle_t timer, uint64_t *expiry)
esp_err_t ESP_TIMER_IRAM_ATTR esp_timer_get_expiry_time(esp_timer_handle_t timer, uint64_t *expiry)
{
if (timer == NULL || expiry == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -758,7 +758,7 @@ esp_err_t IRAM_ATTR esp_timer_get_expiry_time(esp_timer_handle_t timer, uint64_t
return ESP_OK;
}
bool IRAM_ATTR esp_timer_is_active(esp_timer_handle_t timer)
bool ESP_TIMER_IRAM_ATTR esp_timer_is_active(esp_timer_handle_t timer)
{
if (timer == NULL) {
return false;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -32,13 +32,13 @@ void esp_timer_impl_unlock(void)
void esp_timer_private_lock(void) __attribute__((alias("esp_timer_impl_lock")));
void esp_timer_private_unlock(void) __attribute__((alias("esp_timer_impl_unlock")));
void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
void ESP_TIMER_IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
{
esp_timer_impl_set_alarm_id(timestamp, 0);
}
#ifdef CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
void IRAM_ATTR esp_timer_impl_try_to_set_next_alarm(void)
void ESP_TIMER_IRAM_ATTR esp_timer_impl_try_to_set_next_alarm(void)
{
portENTER_CRITICAL_ISR(&s_time_update_lock);
unsigned now_alarm_idx; // ISR is called due to this current alarm
@@ -65,7 +65,7 @@ void IRAM_ATTR esp_timer_impl_try_to_set_next_alarm(void)
#endif
/* FIXME: This value is safe for 80MHz APB frequency, should be modified to depend on clock frequency. */
uint64_t IRAM_ATTR esp_timer_impl_get_min_period_us(void)
uint64_t ESP_TIMER_IRAM_ATTR esp_timer_impl_get_min_period_us(void)
{
return 50;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -106,7 +106,7 @@ extern portMUX_TYPE s_time_update_lock;
/* Alarm values to generate interrupt on match */
extern uint64_t timestamp_id[2];
uint64_t IRAM_ATTR esp_timer_impl_get_counter_reg(void)
uint64_t ESP_TIMER_IRAM_ATTR esp_timer_impl_get_counter_reg(void)
{
uint32_t lo, hi;
uint32_t lo_start = REG_READ(COUNT_LO_REG);
@@ -137,14 +137,14 @@ uint64_t IRAM_ATTR esp_timer_impl_get_counter_reg(void)
return result.val;
}
int64_t IRAM_ATTR esp_timer_impl_get_time(void)
int64_t ESP_TIMER_IRAM_ATTR esp_timer_impl_get_time(void)
{
return esp_timer_impl_get_counter_reg() / TICKS_PER_US;
}
int64_t esp_timer_get_time(void) __attribute__((alias("esp_timer_impl_get_time")));
void IRAM_ATTR esp_timer_impl_set_alarm_id(uint64_t timestamp, unsigned alarm_id)
void ESP_TIMER_IRAM_ATTR esp_timer_impl_set_alarm_id(uint64_t timestamp, unsigned alarm_id)
{
assert(alarm_id < sizeof(timestamp_id) / sizeof(timestamp_id[0]));
portENTER_CRITICAL_SAFE(&s_time_update_lock);
@@ -174,7 +174,7 @@ void IRAM_ATTR esp_timer_impl_set_alarm_id(uint64_t timestamp, unsigned alarm_id
portEXIT_CRITICAL_SAFE(&s_time_update_lock);
}
static void IRAM_ATTR timer_alarm_isr(void *arg)
static void ESP_TIMER_IRAM_ATTR timer_alarm_isr(void *arg)
{
#if ISR_HANDLERS == 1
/* Clear interrupt status */
@@ -220,7 +220,7 @@ static void IRAM_ATTR timer_alarm_isr(void *arg)
#endif // ISR_HANDLERS != 1
}
void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
void ESP_TIMER_IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
{
portENTER_CRITICAL_SAFE(&s_time_update_lock);
assert(apb_ticks_per_us >= 3 && "divider value too low");
@@ -278,7 +278,10 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
int isr_flags = ESP_INTR_FLAG_INTRDISABLED
| ((1 << CONFIG_ESP_TIMER_INTERRUPT_LEVEL) & ESP_INTR_FLAG_LEVELMASK)
| ESP_INTR_FLAG_IRAM;
#if CONFIG_ESP_TIMER_IN_IRAM
| ESP_INTR_FLAG_IRAM
#endif
;
esp_err_t err = esp_intr_alloc(INTR_SOURCE_LACT, isr_flags,
&timer_alarm_isr, NULL,

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -60,12 +60,12 @@ extern portMUX_TYPE s_time_update_lock;
/* Alarm values to generate interrupt on match */
extern uint64_t timestamp_id[2];
uint64_t IRAM_ATTR esp_timer_impl_get_counter_reg(void)
uint64_t ESP_TIMER_IRAM_ATTR esp_timer_impl_get_counter_reg(void)
{
return systimer_hal_get_counter_value(&systimer_hal, SYSTIMER_COUNTER_ESPTIMER);
}
int64_t IRAM_ATTR esp_timer_impl_get_time(void)
int64_t ESP_TIMER_IRAM_ATTR esp_timer_impl_get_time(void)
{
// we hope the execution time of this function won't > 1us
// thus, to save one function call, we didn't use the existing `systimer_hal_get_time`
@@ -74,7 +74,7 @@ int64_t IRAM_ATTR esp_timer_impl_get_time(void)
int64_t esp_timer_get_time(void) __attribute__((alias("esp_timer_impl_get_time")));
void IRAM_ATTR esp_timer_impl_set_alarm_id(uint64_t timestamp, unsigned alarm_id)
void ESP_TIMER_IRAM_ATTR esp_timer_impl_set_alarm_id(uint64_t timestamp, unsigned alarm_id)
{
assert(alarm_id < sizeof(timestamp_id) / sizeof(timestamp_id[0]));
portENTER_CRITICAL_SAFE(&s_time_update_lock);
@@ -84,7 +84,7 @@ void IRAM_ATTR esp_timer_impl_set_alarm_id(uint64_t timestamp, unsigned alarm_id
portEXIT_CRITICAL_SAFE(&s_time_update_lock);
}
static void IRAM_ATTR timer_alarm_isr(void *arg)
static void ESP_TIMER_IRAM_ATTR timer_alarm_isr(void *arg)
{
#if ISR_HANDLERS == 1
// clear the interrupt
@@ -129,7 +129,7 @@ static void IRAM_ATTR timer_alarm_isr(void *arg)
#endif // ISR_HANDLERS != 1
}
void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
void ESP_TIMER_IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us)
{
#if !SOC_SYSTIMER_FIXED_DIVIDER
systimer_hal_on_apb_freq_update(&systimer_hal, apb_ticks_per_us);
@@ -200,7 +200,10 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
#if !SOC_SYSTIMER_INT_LEVEL
| ESP_INTR_FLAG_EDGE
#endif
| ESP_INTR_FLAG_IRAM;
#if CONFIG_ESP_TIMER_IN_IRAM
| ESP_INTR_FLAG_IRAM
#endif
;
esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET2_INTR_SOURCE, isr_flags,
&timer_alarm_isr, NULL,

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -21,6 +21,7 @@
#include "freertos/semphr.h"
#include "sdkconfig.h"
#include "esp_timer.h"
#include "esp_timer_impl.h"
// for ETSTimer type
#include "rom/ets_sys.h"
@@ -34,7 +35,7 @@
#define TIMER_INITIALIZED_FIELD(p_ets_timer) ((p_ets_timer)->timer_expire)
#define TIMER_INITIALIZED_VAL 0x12121212
static IRAM_ATTR bool timer_initialized(ETSTimer *ptimer)
static ESP_TIMER_IRAM_ATTR bool timer_initialized(ETSTimer *ptimer)
{
return TIMER_INITIALIZED_FIELD(ptimer) == TIMER_INITIALIZED_VAL;
}
@@ -58,7 +59,7 @@ void ets_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg)
}
}
void IRAM_ATTR ets_timer_arm_us(ETSTimer *ptimer, uint32_t time_us, bool repeat_flag)
void ESP_TIMER_IRAM_ATTR ets_timer_arm_us(ETSTimer *ptimer, uint32_t time_us, bool repeat_flag)
{
assert(timer_initialized(ptimer));
esp_timer_stop(ESP_TIMER(ptimer)); // no error check
@@ -69,7 +70,7 @@ void IRAM_ATTR ets_timer_arm_us(ETSTimer *ptimer, uint32_t time_us, bool repeat_
}
}
void IRAM_ATTR ets_timer_arm(ETSTimer *ptimer, uint32_t time_ms, bool repeat_flag)
void ESP_TIMER_IRAM_ATTR ets_timer_arm(ETSTimer *ptimer, uint32_t time_ms, bool repeat_flag)
{
uint64_t time_us = 1000LL * (uint64_t) time_ms;
assert(timer_initialized(ptimer));
@@ -90,7 +91,7 @@ void ets_timer_done(ETSTimer *ptimer)
}
}
void IRAM_ATTR ets_timer_disarm(ETSTimer *ptimer)
void ESP_TIMER_IRAM_ATTR ets_timer_disarm(ETSTimer *ptimer)
{
if (timer_initialized(ptimer)) {
esp_timer_stop(ESP_TIMER(ptimer));

View File

@@ -35,12 +35,12 @@ void esp_timer_impl_init_system_time(void)
#endif
}
int64_t IRAM_ATTR esp_system_get_time(void)
int64_t ESP_TIMER_IRAM_ATTR esp_system_get_time(void)
{
return esp_timer_get_time() + s_correction_us;
}
uint32_t IRAM_ATTR esp_system_get_time_resolution(void)
uint32_t ESP_TIMER_IRAM_ATTR esp_system_get_time_resolution(void)
{
return 1000;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -16,6 +16,7 @@
#include "esp_rom_sys.h"
#include "esp_private/spi_flash_os.h"
#include "rom/ets_sys.h"
#include "unity_test_utils_cache.h"
static void test_correct_delay_timer_func(void* arg)
{
@@ -210,40 +211,52 @@ static void IRAM_ATTR test_iram_timer_func(void* arg)
*b = true;
}
#define INTERVAL 5
void IRAM_ATTR test_iram_arm_disarm(void *ctx)
{
ETSTimer *timer1 = (ETSTimer*)ctx;
ets_timer_arm(timer1, INTERVAL, false);
// redundant call is deliberate (test code path if already armed)
ets_timer_arm(timer1, INTERVAL, false);
ets_timer_disarm(timer1);
}
void IRAM_ATTR test_iram_arm(void *ctx)
{
ETSTimer *timer1 = (ETSTimer*)ctx;
ets_timer_arm(timer1, INTERVAL, false);
}
void IRAM_ATTR test_iram_disarm(void *ctx)
{
ETSTimer *timer1 = (ETSTimer*)ctx;
ets_timer_disarm(timer1);
}
/* WiFi/BT coexistence will sometimes arm/disarm
timers from an ISR where flash may be disabled. */
IRAM_ATTR TEST_CASE("ETSTimers arm & disarm run from IRAM", "[ets_timer]")
{
volatile bool flag = false;
ETSTimer timer1;
const int INTERVAL = 5;
ets_timer_setfn(&timer1, &test_iram_timer_func, (void *)&flag);
/* arm a disabled timer, then disarm a live timer */
spi_flash_guard_get()->start(); // Disables flash cache
ets_timer_arm(&timer1, INTERVAL, false);
// redundant call is deliberate (test code path if already armed)
ets_timer_arm(&timer1, INTERVAL, false);
ets_timer_disarm(&timer1);
spi_flash_guard_get()->end(); // Re-enables flash cache
unity_utils_run_cache_disable_stub(test_iram_arm_disarm, &timer1);
TEST_ASSERT_FALSE(flag); // didn't expire yet
/* do the same thing but wait for the timer to expire */
spi_flash_guard_get()->start();
ets_timer_arm(&timer1, INTERVAL, false);
spi_flash_guard_get()->end();
unity_utils_run_cache_disable_stub(test_iram_arm, &timer1);
vTaskDelay(2 * INTERVAL / portTICK_PERIOD_MS);
TEST_ASSERT_TRUE(flag);
spi_flash_guard_get()->start();
ets_timer_disarm(&timer1);
spi_flash_guard_get()->end();
unity_utils_run_cache_disable_stub(test_iram_disarm, &timer1);
ets_timer_done(&timer1);
}

View File

@@ -4,19 +4,6 @@ import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
CONFIGS = [
pytest.param('general', marks=[pytest.mark.supported_targets]),
pytest.param('release', marks=[pytest.mark.supported_targets]),
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('isr_dispatch_esp32c3', marks=[pytest.mark.esp32c3]),
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]),
]
@pytest.mark.generic
@idf_parametrize(
@@ -65,3 +52,16 @@ def test_esp_timer_psram(dut: Dut) -> None:
@idf_parametrize('target', ['esp32c2'], indirect=['target'])
def test_esp_timer_esp32c2_xtal_26mhz(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=120)
@pytest.mark.flash_suspend
@pytest.mark.parametrize(
'config',
[
'flash_auto_suspend',
],
indirect=True,
)
@idf_parametrize('target', ['esp32c3'], indirect=['target'])
def test_esp_timer_flash_auto_suspend(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=120)

View File

@@ -0,0 +1,3 @@
CONFIG_SPI_FLASH_AUTO_SUSPEND=y
CONFIG_ESP_TIMER_IN_IRAM=n
CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND=y

View File

@@ -1,9 +1,10 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "unity.h"
#include "unity_test_utils_cache.h"
#include "esp_attr.h"
@@ -12,11 +13,15 @@
IRAM_ATTR void unity_utils_run_cache_disable_stub(void (*post_cache_disable)(void *), void *user_ctx)
{
#if !CONFIG_SPI_FLASH_AUTO_SUSPEND
// callback function must reside in IRAM
TEST_ASSERT_TRUE(esp_ptr_in_iram(post_cache_disable));
// disable flash cache
spi_flash_guard_get()->start();
#endif
post_cache_disable(user_ctx);
// enable flash cache
#if !CONFIG_SPI_FLASH_AUTO_SUSPEND
spi_flash_guard_get()->end();
#endif
}

View File

@@ -13,3 +13,5 @@ CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH=y
# Options that will enable IRAM reduction option that are only usable together with flash auto-suspend
CONFIG_SPI_FLASH_AUTO_SUSPEND=y
CONFIG_LIBC_MISC_IN_IRAM=n
CONFIG_ESP_TIMER_IN_IRAM=n
CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM=n