diff --git a/components/driver/mcpwm/mcpwm_fault.c b/components/driver/mcpwm/mcpwm_fault.c index 44936d7215..e8b21f43e1 100644 --- a/components/driver/mcpwm/mcpwm_fault.c +++ b/components/driver/mcpwm/mcpwm_fault.c @@ -177,9 +177,8 @@ esp_err_t mcpwm_new_soft_fault(const mcpwm_soft_fault_config_t *config, mcpwm_fa return ESP_OK; err: - if (soft_fault) { - free(soft_fault); - } + // soft_fault must be NULL in the error handling path, and it's a determined behaviour to free a NULL pointer in esp-idf + free(soft_fault); return ret; } diff --git a/components/driver/mcpwm/mcpwm_sync.c b/components/driver/mcpwm/mcpwm_sync.c index 164c36d9ee..c8b7e1bcc3 100644 --- a/components/driver/mcpwm/mcpwm_sync.c +++ b/components/driver/mcpwm/mcpwm_sync.c @@ -252,9 +252,8 @@ esp_err_t mcpwm_new_soft_sync_src(const mcpwm_soft_sync_config_t *config, mcpwm_ return ESP_OK; err: - if (soft_sync) { - free(soft_sync); - } + // soft_sync must be NULL in the error handling path, and it's a determined behaviour to free a NULL pointer in esp-idf + free(soft_sync); return ret; } diff --git a/components/driver/test_apps/mcpwm/main/CMakeLists.txt b/components/driver/test_apps/mcpwm/main/CMakeLists.txt index a6eebbfd72..69804189bb 100644 --- a/components/driver/test_apps/mcpwm/main/CMakeLists.txt +++ b/components/driver/test_apps/mcpwm/main/CMakeLists.txt @@ -8,6 +8,10 @@ set(srcs "test_app_main.c" "test_mcpwm_timer.c" "test_mcpwm_utils.c") +if(CONFIG_MCPWM_ISR_IRAM_SAFE) + list(APPEND srcs "test_mcpwm_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 idf_component_register(SRCS ${srcs} diff --git a/components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c b/components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c new file mode 100644 index 0000000000..29ed573d50 --- /dev/null +++ b/components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c @@ -0,0 +1,90 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "unity.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" +#include "test_mcpwm_utils.h" + +static bool IRAM_ATTR test_capture_callback_iram_safe(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_data_t *edata, void *user_data) +{ + uint32_t *cap_value = (uint32_t *)user_data; + if (edata->cap_edge == MCPWM_CAP_EDGE_NEG) { + cap_value[1] = edata->cap_value; + } else { + cap_value[0] = edata->cap_value; + } + return false; +} + +static void IRAM_ATTR test_mcpwm_capture_gpio_simulate(int gpio_sig) +{ + // disable flash cache + spi_flash_guard_get()->start(); + 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]") +{ + printf("install mcpwm capture timer\r\n"); + mcpwm_cap_timer_handle_t cap_timer = NULL; + mcpwm_capture_timer_config_t cap_timer_config = { + .clk_src = MCPWM_CAPTURE_CLK_SRC_APB, + .group_id = 0, + }; + TEST_ESP_OK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer)); + + const int cap_gpio = 0; + // put the GPIO into a preset state + gpio_set_level(cap_gpio, 0); + + printf("install mcpwm capture channel\r\n"); + mcpwm_cap_channel_handle_t pps_channel; + mcpwm_capture_channel_config_t cap_chan_config = { + .gpio_num = cap_gpio, + .prescale = 1, + .flags.pos_edge = true, + .flags.neg_edge = true, + .flags.io_loop_back = true, // so we can use GPIO functions to simulate the external capture signal + .flags.pull_up = true, + }; + TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &pps_channel)); + + printf("install callback for capture channel\r\n"); + mcpwm_capture_event_callbacks_t cbs = { + .on_cap = test_capture_callback_iram_safe, + }; + uint32_t cap_value[2] = {0}; + TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(pps_channel, &cbs, cap_value)); + + printf("enable and start capture timer\r\n"); + TEST_ESP_OK(mcpwm_capture_timer_enable(cap_timer)); + 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); + + printf("capture value: Pos=%u, Neg=%u\r\n", cap_value[0], cap_value[1]); + // Capture timer is clocked from APB by default + uint32_t clk_src_res = esp_clk_apb_freq(); + TEST_ASSERT_UINT_WITHIN(2000, clk_src_res / 1000, cap_value[1] - cap_value[0]); + + printf("uninstall capture channel and timer\r\n"); + TEST_ESP_OK(mcpwm_del_capture_channel(pps_channel)); + TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer)); + TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer)); +} diff --git a/components/driver/test_apps/mcpwm/sdkconfig.ci.iram_safe b/components/driver/test_apps/mcpwm/sdkconfig.ci.iram_safe index f5e68a8539..9f7355c8cb 100644 --- a/components/driver/test_apps/mcpwm/sdkconfig.ci.iram_safe +++ b/components/driver/test_apps/mcpwm/sdkconfig.ci.iram_safe @@ -1,5 +1,6 @@ CONFIG_COMPILER_DUMP_RTL_FILES=y CONFIG_MCPWM_ISR_IRAM_SAFE=y - +CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y +CONFIG_COMPILER_OPTIMIZATION_NONE=y # silent the error check, as the error string are stored in rodata, causing RTL check failure CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y