diff --git a/components/driver/mcpwm/mcpwm_cap.c b/components/driver/mcpwm/mcpwm_cap.c index 94667a6f14..e45804a905 100644 --- a/components/driver/mcpwm/mcpwm_cap.c +++ b/components/driver/mcpwm/mcpwm_cap.c @@ -317,7 +317,7 @@ esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handl // lazy install interrupt service if (!cap_channel->intr) { - // we want the interrupt servie to be enabled after allocation successfully + // we want the interrupt service to be enabled after allocation successfully int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ ESP_INTR_FLAG_INTRDISABLED; ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags, (uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_CAPTURE(cap_chan_id), diff --git a/components/driver/mcpwm/mcpwm_cmpr.c b/components/driver/mcpwm/mcpwm_cmpr.c index c0f9e82aad..6211d88919 100644 --- a/components/driver/mcpwm/mcpwm_cmpr.c +++ b/components/driver/mcpwm/mcpwm_cmpr.c @@ -160,7 +160,7 @@ esp_err_t mcpwm_comparator_register_event_callbacks(mcpwm_cmpr_handle_t cmpr, co // lazy install interrupt service if (!cmpr->intr) { - // we want the interrupt servie to be enabled after allocation successfully + // we want the interrupt service to be enabled after allocation successfully int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ ESP_INTR_FLAG_INTRDISABLED; ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags, (uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_CMP_EQUAL(oper_id, cmpr_id), diff --git a/components/driver/mcpwm/mcpwm_fault.c b/components/driver/mcpwm/mcpwm_fault.c index e8b21f43e1..f17a32bfe8 100644 --- a/components/driver/mcpwm/mcpwm_fault.c +++ b/components/driver/mcpwm/mcpwm_fault.c @@ -243,7 +243,7 @@ esp_err_t mcpwm_fault_register_event_callbacks(mcpwm_fault_handle_t fault, const // lazy install interrupt service if (!gpio_fault->intr) { - // we want the interrupt servie to be enabled after allocation successfully + // we want the interrupt service to be enabled after allocation successfully int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ESP_INTR_FLAG_INTRDISABLED; ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags, (uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_FAULT_MASK(fault_id), diff --git a/components/driver/mcpwm/mcpwm_oper.c b/components/driver/mcpwm/mcpwm_oper.c index 6a805f8ddc..852a57f958 100644 --- a/components/driver/mcpwm/mcpwm_oper.c +++ b/components/driver/mcpwm/mcpwm_oper.c @@ -233,7 +233,7 @@ esp_err_t mcpwm_operator_register_event_callbacks(mcpwm_oper_handle_t oper, cons // lazy install interrupt service if (!oper->intr) { - // we want the interrupt servie to be enabled after allocation successfully + // we want the interrupt service to be enabled after allocation successfully int isr_flags = MCPWM_INTR_ALLOC_FLAG & ~ ESP_INTR_FLAG_INTRDISABLED; ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(mcpwm_periph_signals.groups[group_id].irq_id, isr_flags, (uint32_t)mcpwm_ll_intr_get_status_reg(hal->dev), MCPWM_LL_EVENT_OPER_MASK(oper_id), diff --git a/components/driver/pulse_cnt.c b/components/driver/pulse_cnt.c index 875578e0b1..ee9e88ee87 100644 --- a/components/driver/pulse_cnt.c +++ b/components/driver/pulse_cnt.c @@ -98,7 +98,7 @@ struct pcnt_unit_t { struct pcnt_chan_t { pcnt_unit_t *unit; // pointer to the PCNT unit where it derives from - uint32_t channel_id; // channel ID, index from 0 + int channel_id; // channel ID, index from 0 int edge_gpio_num; int level_gpio_num; }; diff --git a/components/driver/test_apps/gptimer/main/CMakeLists.txt b/components/driver/test_apps/gptimer/main/CMakeLists.txt index 4170f3fd44..be6096026a 100644 --- a/components/driver/test_apps/gptimer/main/CMakeLists.txt +++ b/components/driver/test_apps/gptimer/main/CMakeLists.txt @@ -1,6 +1,9 @@ set(srcs "test_app_main.c" - "test_gptimer.c" - "test_gptimer_iram.c") + "test_gptimer.c") + +if(CONFIG_GPTIMER_ISR_IRAM_SAFE) + list(APPEND srcs "test_gptimer_iram.c") +endif() # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE diff --git a/components/driver/test_apps/gptimer/main/test_gptimer_iram.c b/components/driver/test_apps/gptimer/main/test_gptimer_iram.c index fcf3cce7d1..2ff59fc5fa 100644 --- a/components/driver/test_apps/gptimer/main/test_gptimer_iram.c +++ b/components/driver/test_apps/gptimer/main/test_gptimer_iram.c @@ -5,102 +5,58 @@ */ #include -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" +#include #include "unity.h" +#include "unity_test_utils.h" +#include "esp_attr.h" #include "driver/gptimer.h" -#include "spi_flash_mmap.h" -#include "esp_flash.h" -#include "soc/soc_caps.h" - -#if CONFIG_GPTIMER_ISR_IRAM_SAFE - -typedef struct { - size_t buf_size; - uint8_t *buf; - size_t flash_addr; - size_t repeat_count; - SemaphoreHandle_t done_sem; -} read_task_arg_t; - -typedef struct { - size_t delay_time_us; - size_t repeat_count; -} block_task_arg_t; static bool IRAM_ATTR on_gptimer_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx) { - block_task_arg_t *arg = (block_task_arg_t *)user_ctx; - esp_rom_delay_us(arg->delay_time_us); - arg->repeat_count++; + uint32_t *alarm_counts = (uint32_t *)user_ctx; + (*alarm_counts)++; return false; } -static void flash_read_task(void *varg) +static void IRAM_ATTR test_delay_post_cache_disable(void *args) { - read_task_arg_t *arg = (read_task_arg_t *)varg; - for (size_t i = 0; i < arg->repeat_count; i++) { - TEST_ESP_OK(esp_flash_read(NULL, arg->buf, arg->flash_addr, arg->buf_size)); - } - xSemaphoreGive(arg->done_sem); - vTaskDelete(NULL); + esp_rom_delay_us(1000); } -TEST_CASE("gptimer_iram_interrupt_safe", "[gptimer]") +TEST_CASE("gptimer_interrupt_iram_safe", "[gptimer]") { gptimer_handle_t gptimer = NULL; - const size_t size = 128; - uint8_t *buf = malloc(size); - TEST_ASSERT_NOT_NULL(buf); - SemaphoreHandle_t done_sem = xSemaphoreCreateBinary(); - TEST_ASSERT_NOT_NULL(done_sem); - read_task_arg_t read_arg = { - .buf_size = size, - .buf = buf, - .flash_addr = 0, - .repeat_count = 1000, - .done_sem = done_sem, - }; - - block_task_arg_t block_arg = { - .repeat_count = 0, - .delay_time_us = 100, - }; - gptimer_config_t timer_config = { .clk_src = GPTIMER_CLK_SRC_DEFAULT, .direction = GPTIMER_COUNT_UP, - .resolution_hz = 1 * 1000 * 1000, + .resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us }; TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimer)); gptimer_event_callbacks_t cbs = { .on_alarm = on_gptimer_alarm_cb, }; + uint32_t alarm_counts = 0; + TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, &alarm_counts)); gptimer_alarm_config_t alarm_config = { .reload_count = 0, - .alarm_count = 120, + .alarm_count = 100, // 100us per alarm event .flags.auto_reload_on_alarm = true, }; TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config)); - TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, &block_arg)); TEST_ESP_OK(gptimer_enable(gptimer)); TEST_ESP_OK(gptimer_start(gptimer)); - xTaskCreatePinnedToCore(flash_read_task, "read_flash", 2048, &read_arg, 3, NULL, portNUM_PROCESSORS - 1); - // wait for task done - xSemaphoreTake(done_sem, portMAX_DELAY); - printf("alarm callback runs %d times\r\n", block_arg.repeat_count); - TEST_ASSERT_GREATER_THAN(1000, block_arg.repeat_count); + vTaskDelay(pdMS_TO_TICKS(10)); + + printf("disable flash cache and check the alarm events are still in working\r\n"); + for (int i = 0; i < 10; i++) { + unity_utils_run_cache_disable_stub(test_delay_post_cache_disable, NULL); + } + printf("alarm counts: %"PRIu32"\r\n", alarm_counts); + TEST_ASSERT_GREATER_THAN(150, alarm_counts); + // delete gptimer TEST_ESP_OK(gptimer_stop(gptimer)); TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); - vSemaphoreDelete(done_sem); - free(buf); - // leave time for IDLE task to recycle deleted task - vTaskDelay(2); } - -#endif // CONFIG_GPTIMER_ISR_IRAM_SAFE diff --git a/components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c b/components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c index a59d59e670..d65159c859 100644 --- a/components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c +++ b/components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c @@ -9,9 +9,9 @@ #include "freertos/task.h" #include "freertos/event_groups.h" #include "unity.h" +#include "unity_test_utils.h" #include "soc/soc_caps.h" #include "esp_private/esp_clk.h" -#include "esp_private/spi_flash_os.h" #include "driver/mcpwm_cap.h" #include "driver/mcpwm_sync.h" #include "driver/gpio.h" @@ -28,15 +28,12 @@ static bool IRAM_ATTR test_capture_callback_iram_safe(mcpwm_cap_channel_handle_t return false; } -static void IRAM_ATTR test_mcpwm_capture_gpio_simulate(int gpio_sig) +static void IRAM_ATTR test_simulate_input_post_cache_disable(void *args) { - // disable flash cache - spi_flash_guard_get()->start(); + int gpio_sig = (int)args; gpio_set_level(gpio_sig, 1); esp_rom_delay_us(1000); gpio_set_level(gpio_sig, 0); - // enable flash cache - spi_flash_guard_get()->end(); } TEST_CASE("mcpwm_capture_iram_safe", "[mcpwm]") @@ -77,7 +74,7 @@ TEST_CASE("mcpwm_capture_iram_safe", "[mcpwm]") TEST_ESP_OK(mcpwm_capture_timer_start(cap_timer)); printf("disable cache, simulate GPIO capture signal\r\n"); - test_mcpwm_capture_gpio_simulate(cap_gpio); + unity_utils_run_cache_disable_stub(test_simulate_input_post_cache_disable, (void *)cap_gpio); printf("capture value: Pos=%"PRIu32", Neg=%"PRIu32"\r\n", cap_value[0], cap_value[1]); // Capture timer is clocked from APB by default diff --git a/components/driver/test_apps/pulse_cnt/main/CMakeLists.txt b/components/driver/test_apps/pulse_cnt/main/CMakeLists.txt index 4e70ee7087..3bfb46de82 100644 --- a/components/driver/test_apps/pulse_cnt/main/CMakeLists.txt +++ b/components/driver/test_apps/pulse_cnt/main/CMakeLists.txt @@ -1,7 +1,10 @@ set(srcs "test_app_main.c" "test_pulse_cnt_simulator.c" - "test_pulse_cnt.c" - "test_pulse_cnt_iram.c") + "test_pulse_cnt.c") + +if(CONFIG_PCNT_ISR_IRAM_SAFE) + list(APPEND srcs "test_pulse_cnt_iram.c") +endif() # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE diff --git a/components/driver/test_apps/pulse_cnt/main/test_pulse_cnt_iram.c b/components/driver/test_apps/pulse_cnt/main/test_pulse_cnt_iram.c index e07c224df0..8803b17b10 100644 --- a/components/driver/test_apps/pulse_cnt/main/test_pulse_cnt_iram.c +++ b/components/driver/test_apps/pulse_cnt/main/test_pulse_cnt_iram.c @@ -10,16 +10,14 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "unity.h" +#include "unity_test_utils.h" #include "driver/pulse_cnt.h" #include "driver/gpio.h" #include "spi_flash_mmap.h" #include "esp_attr.h" #include "soc/soc_caps.h" -#include "esp_private/spi_flash_os.h" #include "test_pulse_cnt_board.h" -#if CONFIG_PCNT_ISR_IRAM_SAFE - static bool IRAM_ATTR test_pcnt_iram_safe_callback(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *event_data, void *user_data) { uint32_t *data = (uint32_t *)user_data; @@ -29,13 +27,10 @@ static bool IRAM_ATTR test_pcnt_iram_safe_callback(pcnt_unit_handle_t unit, cons return false; } -static void IRAM_ATTR test_pcnt_iram_simulation(int gpio_sig) +static void IRAM_ATTR test_simulate_input_post_cache_disable(void *args) { - // disable flash cache - spi_flash_guard_get()->start(); + int gpio_sig = (int)args; test_gpio_simulate_rising_edge(gpio_sig, 2); - // enable flash cache - spi_flash_guard_get()->end(); } TEST_CASE("pcnt_iram_interrupt_safe", "[pcnt]") @@ -83,8 +78,9 @@ TEST_CASE("pcnt_iram_interrupt_safe", "[pcnt]") printf("disable cache and check interrupt triggered\r\n"); TEST_ESP_OK(pcnt_unit_clear_count(unit)); - // the function that will disable the flash must be placed in the IRAM - test_pcnt_iram_simulation(TEST_PCNT_GPIO_A); + + // disable flash cache and run simulation + unity_utils_run_cache_disable_stub(test_simulate_input_post_cache_disable, (void *)TEST_PCNT_GPIO_A); // check if the interrupt has fired up TEST_ASSERT_EQUAL(1, num_of_event_triggered); @@ -101,5 +97,3 @@ TEST_CASE("pcnt_iram_interrupt_safe", "[pcnt]") TEST_ESP_OK(pcnt_del_channel(channelB)); TEST_ESP_OK(pcnt_del_unit(unit)); } - -#endif // CONFIG_PCNT_ISR_IRAM_SAFE diff --git a/components/unity/CMakeLists.txt b/components/unity/CMakeLists.txt index bc8818b32e..9659dbba89 100644 --- a/components/unity/CMakeLists.txt +++ b/components/unity/CMakeLists.txt @@ -17,7 +17,7 @@ if(CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER) list(APPEND srcs "unity_runner.c") # Note the following files are not compatible with the Linux target. # On Linux, these are masked because we also don't use the IDF test runner there - list(APPEND srcs "unity_utils_freertos.c") + list(APPEND srcs "unity_utils_freertos.c" "unity_utils_cache.c") list(APPEND requires "freertos") endif() @@ -39,6 +39,10 @@ idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${includes} REQUIRES ${requires}) +if(CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER) + idf_component_optional_requires(PRIVATE spi_flash) +endif() + if(NOT "${target}" STREQUAL "linux") target_compile_definitions(${COMPONENT_LIB} PUBLIC -DUNITY_INCLUDE_CONFIG_H diff --git a/components/unity/include/unity_test_utils.h b/components/unity/include/unity_test_utils.h index c9f38613e7..42afe6bb48 100644 --- a/components/unity/include/unity_test_utils.h +++ b/components/unity/include/unity_test_utils.h @@ -10,6 +10,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "unity_test_utils_memory.h" +#include "unity_test_utils_cache.h" #ifdef __cplusplus extern "C" { diff --git a/components/unity/include/unity_test_utils_cache.h b/components/unity/include/unity_test_utils_cache.h new file mode 100644 index 0000000000..6c33b6dead --- /dev/null +++ b/components/unity/include/unity_test_utils_cache.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Disable flash cache and run user stub function and then enable flash cache again + * + * @note You should make sure the passed-in function is in internal RAM. + * + * @param post_cache_disable User function to be invoked after cache is disabled. + * @param user_ctx User context to be passed to user function. + */ +void unity_utils_run_cache_disable_stub(void (*post_cache_disable)(void *), void *user_ctx); + +#ifdef __cplusplus +} +#endif diff --git a/components/unity/unity_utils_cache.c b/components/unity/unity_utils_cache.c new file mode 100644 index 0000000000..5d44ec0a0e --- /dev/null +++ b/components/unity/unity_utils_cache.c @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_utils_cache.h" +#include "esp_attr.h" +#include "esp_memory_utils.h" +#include "esp_private/spi_flash_os.h" + +IRAM_ATTR void unity_utils_run_cache_disable_stub(void (*post_cache_disable)(void *), void *user_ctx) +{ + // callback function must reside in IRAM + TEST_ASSERT_TRUE(esp_ptr_in_iram(post_cache_disable)); + // disable flash cache + spi_flash_guard_get()->start(); + post_cache_disable(user_ctx); + // enable flash cache + spi_flash_guard_get()->end(); +}