/* * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "unity.h" #include "soc/soc_caps.h" #include "driver/mcpwm_timer.h" #include "driver/mcpwm_sync.h" #include "driver/gpio.h" #include "esp_private/mcpwm.h" #include "test_mcpwm_utils.h" TEST_CASE("mcpwm_sync_source_install_uninstall", "[mcpwm]") { printf("install timer sync_src\r\n"); mcpwm_timer_config_t timer_config = { .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT, .resolution_hz = 1000000, // 1MHz .period_ticks = 200, .count_mode = MCPWM_TIMER_COUNT_MODE_UP, }; const int total_timers = SOC_MCPWM_TIMERS_PER_GROUP * SOC_MCPWM_GROUPS; mcpwm_timer_handle_t timers[total_timers]; int k = 0; for (int i = 0; i < SOC_MCPWM_GROUPS; i++) { timer_config.group_id = i; for (int j = 0; j < SOC_MCPWM_TIMERS_PER_GROUP; j++) { TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timers[k++])); } } mcpwm_timer_sync_src_config_t timer_sync_src_config = { .timer_event = MCPWM_TIMER_EVENT_EMPTY, }; mcpwm_sync_handle_t timer_syncs[total_timers]; for (int i = 0; i < total_timers; i++) { TEST_ESP_OK(mcpwm_new_timer_sync_src(timers[i], &timer_sync_src_config, &timer_syncs[i])); } TEST_ESP_ERR(ESP_ERR_INVALID_STATE, mcpwm_new_timer_sync_src(timers[0], &timer_sync_src_config, &timer_syncs[0])); printf("install gpio sync_src\r\n"); mcpwm_gpio_sync_src_config_t gpio_sync_config = { .gpio_num = 0, }; const int total_gpio_sync_srcs = SOC_MCPWM_GROUPS * SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP; mcpwm_sync_handle_t gpio_sync_srcs[total_gpio_sync_srcs]; k = 0; for (int i = 0; i < SOC_MCPWM_GROUPS; i++) { gpio_sync_config.group_id = i; for (int j = 0; j < SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP; j++) { TEST_ESP_OK(mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync_srcs[k++])); } } TEST_ESP_ERR(ESP_ERR_NOT_FOUND, mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync_srcs[0])); printf("delete synchors\r\n"); for (int i = 0; i < total_gpio_sync_srcs; i++) { TEST_ESP_OK(mcpwm_del_sync_src(gpio_sync_srcs[i])); } for (int i = 0; i < total_timers; i++) { TEST_ESP_OK(mcpwm_del_sync_src(timer_syncs[i])); TEST_ESP_OK(mcpwm_del_timer(timers[i])); } } TEST_CASE("mcpwm_soft_sync_timer_phase_lock", "[mcpwm]") { mcpwm_timer_config_t timer_config = { .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT, .group_id = 0, .resolution_hz = 1000000, // 1MHz .period_ticks = 200, .count_mode = MCPWM_TIMER_COUNT_MODE_UP_DOWN, }; mcpwm_timer_handle_t timer = NULL; TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer)); TEST_ESP_OK(mcpwm_timer_enable(timer)); TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_STOP_FULL)); vTaskDelay(pdMS_TO_TICKS(10)); check_mcpwm_timer_phase(&timer, 1, timer_config.period_ticks / 2, MCPWM_TIMER_DIRECTION_DOWN); printf("install soft sync source\r\n"); mcpwm_sync_handle_t soft_sync = NULL; mcpwm_soft_sync_config_t soft_sync_config = {}; TEST_ESP_OK(mcpwm_new_soft_sync_src(&soft_sync_config, &soft_sync)); mcpwm_timer_sync_phase_config_t sync_phase_config = { .count_value = 77, .direction = MCPWM_TIMER_DIRECTION_UP, .sync_src = soft_sync, }; TEST_ESP_OK(mcpwm_timer_set_phase_on_sync(timer, &sync_phase_config)); TEST_ESP_OK(mcpwm_soft_sync_activate(soft_sync)); check_mcpwm_timer_phase(&timer, 1, 77, MCPWM_TIMER_DIRECTION_UP); TEST_ESP_OK(mcpwm_timer_disable(timer)); TEST_ESP_OK(mcpwm_del_timer(timer)); TEST_ESP_OK(mcpwm_del_sync_src(soft_sync)); } TEST_CASE("mcpwm_gpio_sync_timer_phase_lock", "[mcpwm]") { // GPIO // | // v // timer0-->timer1-->timer2 mcpwm_timer_config_t timer_config = { .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT, .group_id = 0, .resolution_hz = 1000000, // 1MHz, 1us per tick .period_ticks = 500, .count_mode = MCPWM_TIMER_COUNT_MODE_UP, }; mcpwm_timer_sync_src_config_t sync_config = { .flags.propagate_input_sync = 1, // reuse the input sync source as the output sync trigger }; mcpwm_timer_handle_t timers[SOC_MCPWM_TIMERS_PER_GROUP]; mcpwm_sync_handle_t sync_srcs[SOC_MCPWM_TIMERS_PER_GROUP]; for (int i = 0; i < SOC_MCPWM_TIMERS_PER_GROUP; i++) { TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timers[i])); TEST_ESP_OK(mcpwm_new_timer_sync_src(timers[i], &sync_config, &sync_srcs[i])); } mcpwm_timer_sync_phase_config_t sync_phase_config = { .count_value = 100, .direction = MCPWM_TIMER_DIRECTION_UP, }; mcpwm_sync_handle_t gpio_sync_src; const int gpio_num = 0; mcpwm_gpio_sync_src_config_t gpio_sync_config = { .group_id = 0, .gpio_num = gpio_num, .flags.io_loop_back = true, // so that we can use gpio driver to simulate the sync signal .flags.pull_down = true, // internally pull down }; TEST_ESP_OK(mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync_src)); // put the GPIO into initial state gpio_set_level(gpio_num, 0); for (int i = 1; i < SOC_MCPWM_TIMERS_PER_GROUP; i++) { sync_phase_config.sync_src = sync_srcs[i - 1]; TEST_ESP_OK(mcpwm_timer_set_phase_on_sync(timers[i], &sync_phase_config)); } sync_phase_config.sync_src = gpio_sync_src; TEST_ESP_OK(mcpwm_timer_set_phase_on_sync(timers[0], &sync_phase_config)); // simulate an GPIO sync singal gpio_set_level(gpio_num, 1); gpio_set_level(gpio_num, 0); check_mcpwm_timer_phase(timers, SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP, 100, MCPWM_TIMER_DIRECTION_UP); TEST_ESP_OK(mcpwm_del_sync_src(gpio_sync_src)); for (int i = 0; i < SOC_MCPWM_TIMERS_PER_GROUP; i++) { TEST_ESP_OK(mcpwm_del_sync_src(sync_srcs[i])); TEST_ESP_OK(mcpwm_del_timer(timers[i])); } } TEST_CASE("mcpwm_timer_sync_timer_phase_lock", "[mcpwm]") { // +->timer1 // | // timer0---+ // | // +->timer2 mcpwm_timer_config_t timer_config = { .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT, .group_id = 0, .resolution_hz = 1000000, // 1MHz, 1us per tick .period_ticks = 500, .count_mode = MCPWM_TIMER_COUNT_MODE_UP_DOWN, }; mcpwm_timer_handle_t timers[SOC_MCPWM_TIMERS_PER_GROUP]; for (int i = 0; i < SOC_MCPWM_TIMERS_PER_GROUP; i++) { TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timers[i])); } mcpwm_timer_sync_src_config_t sync_config = { .timer_event = MCPWM_TIMER_EVENT_FULL, }; mcpwm_sync_handle_t sync_src; TEST_ESP_OK(mcpwm_new_timer_sync_src(timers[0], &sync_config, &sync_src)); mcpwm_timer_sync_phase_config_t sync_phase_config = { .count_value = 50, .direction = MCPWM_TIMER_DIRECTION_DOWN, .sync_src = sync_src, }; for (int i = 1; i < SOC_MCPWM_TIMERS_PER_GROUP; i++) { TEST_ESP_OK(mcpwm_timer_set_phase_on_sync(timers[i], &sync_phase_config)); } TEST_ESP_OK(mcpwm_timer_enable(timers[0])); TEST_ESP_OK(mcpwm_timer_start_stop(timers[0], MCPWM_TIMER_START_STOP_FULL)); vTaskDelay(pdMS_TO_TICKS(10)); check_mcpwm_timer_phase(&timers[1], 2, 50, MCPWM_TIMER_DIRECTION_DOWN); TEST_ESP_OK(mcpwm_timer_disable(timers[0])); TEST_ESP_OK(mcpwm_del_sync_src(sync_src)); for (int i = 0; i < SOC_MCPWM_TIMERS_PER_GROUP; i++) { TEST_ESP_OK(mcpwm_del_timer(timers[i])); } }