mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/gptimer_rc_fast_c6' into 'master'
gptimer: support RC_FAST clock source See merge request espressif/esp-idf!21601
This commit is contained in:
commit
080328a664
@ -8,12 +8,6 @@ components/driver/test_apps/dac_test_apps/legacy_dac_driver:
|
||||
disable:
|
||||
- if: SOC_DAC_SUPPORTED != 1
|
||||
|
||||
components/driver/test_apps/gptimer:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c6"
|
||||
temporary: true
|
||||
reason: target esp32c6 is not supported yet
|
||||
|
||||
components/driver/test_apps/i2s_test_apps:
|
||||
disable:
|
||||
- if: SOC_I2S_SUPPORTED != 1
|
||||
@ -64,12 +58,6 @@ components/driver/test_apps/legacy_rtc_temp_driver:
|
||||
disable:
|
||||
- if: SOC_TEMP_SENSOR_SUPPORTED != 1
|
||||
|
||||
components/driver/test_apps/legacy_timer_driver:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c6"
|
||||
temporary: true
|
||||
reason: target esp32c6 is not supported yet
|
||||
|
||||
components/driver/test_apps/mcpwm:
|
||||
disable:
|
||||
- if: SOC_MCPWM_SUPPORTED != 1
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "clk_ctrl_os.h"
|
||||
#include "gptimer_priv.h"
|
||||
|
||||
static const char *TAG = "gptimer";
|
||||
@ -153,12 +154,23 @@ esp_err_t gptimer_del_timer(gptimer_handle_t timer)
|
||||
ESP_RETURN_ON_FALSE(timer, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(timer->fsm == GPTIMER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "timer not in init state");
|
||||
gptimer_group_t *group = timer->group;
|
||||
gptimer_clock_source_t clk_src = timer->clk_src;
|
||||
int group_id = group->group_id;
|
||||
int timer_id = timer->timer_id;
|
||||
ESP_LOGD(TAG, "del timer (%d,%d)", group_id, timer_id);
|
||||
timer_hal_deinit(&timer->hal);
|
||||
// recycle memory resource
|
||||
ESP_RETURN_ON_ERROR(gptimer_destory(timer), TAG, "destory gptimer failed");
|
||||
|
||||
switch (clk_src) {
|
||||
#if SOC_TIMER_GROUP_SUPPORT_RC_FAST
|
||||
case GPTIMER_CLK_SRC_RC_FAST:
|
||||
periph_rtc_dig_clk8m_disable();
|
||||
break;
|
||||
#endif // SOC_TIMER_GROUP_SUPPORT_RC_FAST
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -182,6 +194,13 @@ esp_err_t gptimer_get_raw_count(gptimer_handle_t timer, unsigned long long *valu
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gptimer_get_resolution(gptimer_handle_t timer, uint32_t *out_resolution)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(timer && out_resolution, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
*out_resolution = timer->resolution_hz;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gptimer_get_captured_count(gptimer_handle_t timer, uint64_t *value)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(timer && value, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
@ -404,7 +423,7 @@ static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_sou
|
||||
counter_src_hz = 40 * 1000 * 1000;
|
||||
#if CONFIG_PM_ENABLE
|
||||
sprintf(timer->pm_lock_name, "gptimer_%d_%d", timer->group->group_id, timer_id); // e.g. gptimer_0_0
|
||||
// PLL_F40M will be turned off when DFS switches CPU clock source to XTAL
|
||||
// on ESP32C2, PLL_F40M is unavailable when CPU clock source switches from PLL to XTAL, so we're acquiring a "APB" lock here to prevent the clock switch
|
||||
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, timer->pm_lock_name, &timer->pm_lock);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "create APB_FREQ_MAX lock failed");
|
||||
ESP_LOGD(TAG, "install APB_FREQ_MAX lock for timer (%d,%d)", timer->group->group_id, timer_id);
|
||||
@ -416,7 +435,7 @@ static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_sou
|
||||
counter_src_hz = 80 * 1000 * 1000;
|
||||
#if CONFIG_PM_ENABLE
|
||||
sprintf(timer->pm_lock_name, "gptimer_%d_%d", timer->group->group_id, timer_id); // e.g. gptimer_0_0
|
||||
// ESP32C6 PLL_F80M is available when SOC_ROOT_CLK switchs to XTAL
|
||||
// ESP32C6 PLL_F80M is available when SOC_ROOT_CLK switches to XTAL
|
||||
ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, timer->pm_lock_name, &timer->pm_lock);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "create NO_LIGHT_SLEEP lock failed");
|
||||
ESP_LOGD(TAG, "install NO_LIGHT_SLEEP lock for timer (%d,%d)", timer->group->group_id, timer_id);
|
||||
@ -434,6 +453,12 @@ static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_sou
|
||||
counter_src_hz = esp_clk_xtal_freq();
|
||||
break;
|
||||
#endif // SOC_TIMER_GROUP_SUPPORT_XTAL
|
||||
#if SOC_TIMER_GROUP_SUPPORT_RC_FAST
|
||||
case GPTIMER_CLK_SRC_RC_FAST:
|
||||
periph_rtc_dig_clk8m_enable();
|
||||
counter_src_hz = periph_rtc_dig_clk8m_get_freq();
|
||||
break;
|
||||
#endif // SOC_TIMER_GROUP_SUPPORT_RC_FAST
|
||||
default:
|
||||
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "clock source %d is not support", src_clk);
|
||||
break;
|
||||
|
@ -80,7 +80,7 @@ esp_err_t gptimer_set_raw_count(gptimer_handle_t timer, uint64_t value);
|
||||
* @brief Get GPTimer raw count value
|
||||
*
|
||||
* @note This function will trigger a software capture event and then return the captured count value.
|
||||
* @note With the raw count value and the resolution set in the `gptimer_config_t`, you can convert the count value into seconds.
|
||||
* @note With the raw count value and the resolution returned from `gptimer_get_resolution`, you can convert the count value into seconds.
|
||||
* @note This function is allowed to run within ISR context
|
||||
* @note This function is allowed to be executed when Cache is disabled, by enabling `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM`
|
||||
*
|
||||
@ -93,6 +93,20 @@ esp_err_t gptimer_set_raw_count(gptimer_handle_t timer, uint64_t value);
|
||||
*/
|
||||
esp_err_t gptimer_get_raw_count(gptimer_handle_t timer, uint64_t *value);
|
||||
|
||||
/**
|
||||
* @brief Return the real resolution of the timer
|
||||
*
|
||||
* @note usually the timer resolution is same as what you configured in the `gptimer_config_t::resolution_hz`, but for some unstable clock source (e.g. RC_FAST), which needs a calibration, the real resolution may be different from the configured one.
|
||||
*
|
||||
* @param[in] timer Timer handle created by `gptimer_new_timer`
|
||||
* @param[out] out_resolution Returned timer resolution, in Hz
|
||||
* @return
|
||||
* - ESP_OK: Get GPTimer resolution successfully
|
||||
* - ESP_ERR_INVALID_ARG: Get GPTimer resolution failed because of invalid argument
|
||||
* - ESP_FAIL: Get GPTimer resolution failed because of other error
|
||||
*/
|
||||
esp_err_t gptimer_get_resolution(gptimer_handle_t timer, uint32_t *out_resolution);
|
||||
|
||||
/**
|
||||
* @brief Get GPTimer captured count value
|
||||
*
|
||||
|
@ -60,6 +60,7 @@ TEST_CASE("gptimer_set_get_raw_count", "[gptimer]")
|
||||
TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]")
|
||||
{
|
||||
gptimer_clock_source_t test_clk_srcs[] = SOC_GPTIMER_CLKS;
|
||||
uint32_t timer_resolution_hz[SOC_TIMER_GROUP_TOTAL_TIMERS];
|
||||
|
||||
// test with various clock sources
|
||||
for (size_t i = 0; i < sizeof(test_clk_srcs) / sizeof(test_clk_srcs[0]); i++) {
|
||||
@ -71,6 +72,7 @@ TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]")
|
||||
gptimer_handle_t timers[SOC_TIMER_GROUP_TOTAL_TIMERS];
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_new_timer(&timer_config, &timers[i]));
|
||||
TEST_ESP_OK(gptimer_get_resolution(timers[i], &timer_resolution_hz[i]));
|
||||
}
|
||||
// start timer before enable should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gptimer_start(timers[0]));
|
||||
@ -83,9 +85,11 @@ TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]")
|
||||
TEST_ESP_OK(gptimer_start(timers[i]));
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(20)); // 20ms = 20_000 ticks
|
||||
unsigned long long value = 0;
|
||||
uint64_t value = 0;
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_get_raw_count(timers[i], &value));
|
||||
// convert the raw count to us
|
||||
value = value * 1000000 / timer_resolution_hz[i];
|
||||
TEST_ASSERT_UINT_WITHIN(1000, 20000, value);
|
||||
}
|
||||
printf("stop timers\r\n");
|
||||
@ -97,6 +101,8 @@ TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]")
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_get_raw_count(timers[i], &value));
|
||||
printf("get raw count of gptimer %d: %llu\r\n", i, value);
|
||||
// convert the raw count to us
|
||||
value = value * 1000000 / timer_resolution_hz[i];
|
||||
TEST_ASSERT_UINT_WITHIN(1000, 20000, value);
|
||||
}
|
||||
printf("restart timers\r\n");
|
||||
@ -113,6 +119,8 @@ TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]")
|
||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
||||
TEST_ESP_OK(gptimer_get_raw_count(timers[i], &value));
|
||||
printf("get raw count of gptimer %d: %llu\r\n", i, value);
|
||||
// convert the raw count to us
|
||||
value = value * 1000000 / timer_resolution_hz[i];
|
||||
TEST_ASSERT_UINT_WITHIN(2000, 40000, value);
|
||||
}
|
||||
printf("disable timers\r\n");
|
||||
|
@ -6,7 +6,6 @@ from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32c6'], reason='iram_safe test failed')
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
|
@ -6,7 +6,6 @@ from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32c6'], reason='test failed')
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize('config', [
|
||||
'release',
|
||||
|
@ -68,6 +68,9 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num,
|
||||
case GPTIMER_CLK_SRC_PLL_F80M:
|
||||
clk_id = 1;
|
||||
break;
|
||||
case GPTIMER_CLK_SRC_RC_FAST:
|
||||
clk_id = 2;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
break;
|
||||
|
@ -771,6 +771,10 @@ config SOC_TIMER_GROUP_SUPPORT_PLL_F80M
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_TIMER_GROUP_SUPPORT_RC_FAST
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_TIMER_GROUP_TOTAL_TIMERS
|
||||
int
|
||||
default 2
|
||||
|
@ -149,15 +149,16 @@ typedef enum {
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
#define SOC_GPTIMER_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL}
|
||||
#define SOC_GPTIMER_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL}
|
||||
|
||||
/**
|
||||
* @brief Type of GPTimer clock source
|
||||
*/
|
||||
typedef enum {
|
||||
GPTIMER_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the source clock */
|
||||
GPTIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
|
||||
GPTIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the default choice */
|
||||
GPTIMER_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the source clock */
|
||||
GPTIMER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
|
||||
GPTIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
|
||||
GPTIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the default choice */
|
||||
} soc_periph_gptimer_clk_src_t;
|
||||
|
||||
/**
|
||||
|
@ -359,6 +359,7 @@
|
||||
#define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (54)
|
||||
#define SOC_TIMER_GROUP_SUPPORT_XTAL (1)
|
||||
#define SOC_TIMER_GROUP_SUPPORT_PLL_F80M (1)
|
||||
#define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1)
|
||||
#define SOC_TIMER_GROUP_TOTAL_TIMERS (2)
|
||||
#define SOC_TIMER_SUPPORT_ETM (1)
|
||||
|
||||
|
@ -183,12 +183,6 @@ examples/peripherals/timer_group/gptimer_capture_hc_sr04:
|
||||
disable:
|
||||
- if: SOC_TIMER_SUPPORT_ETM != 1
|
||||
|
||||
examples/peripherals/timer_group/legacy_driver:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c6"
|
||||
temporary: true
|
||||
reason: target esp32c6 is not supported yet
|
||||
|
||||
examples/peripherals/touch_sensor:
|
||||
disable:
|
||||
- if: SOC_TOUCH_SENSOR_SUPPORTED != 1
|
||||
|
@ -6,7 +6,6 @@ from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32c6'], reason='test failed')
|
||||
@pytest.mark.generic
|
||||
def test_timer_group_example(dut: Dut) -> None:
|
||||
dut.expect(r'Init timer with auto-reload', timeout=5)
|
||||
|
Loading…
x
Reference in New Issue
Block a user