# 通用定时器

[English]

## 简介

通用定时器是 ESP32-C3 定时器组外设的驱动程序。ESP32-C3 硬件定时器分辨率高，具有灵活的报警功能。定时器内部计数器达到特定目标数值的行为被称为定时器报警。定时器报警时将调用用户注册的不同定时器回调函数。

通用定时器通常在以下场景中使用：

- 如同挂钟一般自由运行，随时随地获取高分辨率时间戳；

- 生成周期性警报，定期触发事件；

- 生成一次性警报，在目标时间内响应。

## 功能概述

下文介绍了配置和操作定时器的常规步骤：

- 资源分配 - 获取定时器句柄应设置的参数，以及如何在通用定时器完成工作时回收资源。

- 设置和获取计数值 - 如何强制定时器从起点开始计数，以及如何随时获取计数值。

- 设置警报动作 - 启动警报事件应设置的参数。

- 注册事件回调函数 - 如何将用户的特定代码挂载到警报事件回调函数。

- 使能和禁用定时器 - 如何使能和禁用定时器。

- 启动和停止定时器 - 通过不同报警行为启动定时器的典型使用场景。

- 电源管理 - 选择不同的时钟源将会如何影响功耗。

- IRAM 安全 - 在 cache 禁用的情况下，如何更好地让定时器处理中断事务以及实现 IO 控制功能。

- 线程安全 - 驱动程序保证哪些 API 线程安全。

- Kconfig 选项 - 支持的 Kconfig 选项，这些选项会对驱动程序行为产生不同影响。

### 资源分配

不同的 ESP 芯片可能有不同数量的独立定时器组，每组内也可能有若干个独立定时器。[1]

通用定时器实例由 `gptimer_handle_t` 表示。可用硬件资源汇集在资源池内，由后台驱动程序管理，无需考虑硬件所属的定时器以及定时器组。

要安装一个定时器实例，需要提前提供配置结构体 `gptimer_config_t`：

- `gptimer_config_t::clk_src` 选择定时器的时钟源。`gptimer_clock_source_t` 中列出多个可用时钟，仅可选择其中一个时钟。了解不同时钟源对功耗的影响，请查看章节 电源管理。

- `gptimer_config_t::direction` 设置定时器的计数方向，`gptimer_count_direction_t` 中列出多个支持的方向，仅可选择其中一个方向。

- `gptimer_config_t::resolution_hz` 设置内部计数器的分辨率。计数器每滴答一次相当于 1 / resolution_hz 秒。

- `gptimer_config::intr_priority` 设置中断的优先级。如果设置为 `0`，则会分配一个默认优先级的中断，否则会使用指定的优先级。

- `gptimer_config::allow_pd` 配置驱动程序是否允许系统在睡眠模式下关闭外设电源。在进入睡眠之前，系统将备份 GPTimer 寄存器上下文，当系统退出睡眠模式时，这些上下文将被恢复。关闭外设可以节省更多功耗，但代价是消耗更多内存来保存寄存器上下文。你需要在功耗和内存消耗之间做权衡。此配置选项依赖于特定的硬件功能，如果在不支持的芯片上启用它，你将看到类似 `not able to power down in light sleep` 的错误消息。

- 可选地， `gptimer_config_t::intr_shared` 设置是否将定时器中断源标记为共享源。了解共享中断的优缺点，请参考 Interrupt Handling。

完成上述结构配置之后，可以将结构传递给 `gptimer_new_timer()`，用以实例化定时器实例并返回定时器句柄。

该函数可能由于内存不足、参数无效等错误而失败。具体来说，当没有更多的空闲定时器（即所有硬件资源已用完）时，将返回 `ESP_ERR_NOT_FOUND`。可用定时器总数由 `SOC_TIMER_GROUP_TOTAL_TIMERS` 表示，不同的 ESP 芯片该数值不同。

如已不再需要之前创建的通用定时器实例，应通过调用 `gptimer_del_timer()` 回收定时器，以便底层硬件定时器用于其他目的。在删除通用定时器句柄之前，请通过 `gptimer_disable()` 禁用定时器，或者通过 `gptimer_enable()` 确认定时器尚未使能。

#### 创建分辨率为 1 MHz 的通用定时器句柄

    gptimer_handle_t gptimer = NULL;
    gptimer_config_t timer_config = {
        .clk_src = GPTIMER_CLK_SRC_DEFAULT,
        .direction = GPTIMER_COUNT_UP,
        .resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us
    };
    ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));

### 设置和获取计数值

创建通用定时器时，内部计数器将默认重置为零。计数值可以通过 `gptimer_set_raw_count()` 异步更新。最大计数值取决于硬件定时器的位宽，这也会在 SOC 宏 `SOC_TIMER_GROUP_COUNTER_BIT_WIDTH` 中有所反映。当更新活动定时器的原始计数值时，定时器将立即从新值开始计数。

计数值可以随时通过 `gptimer_get_raw_count()` 获取。

### 设置警报动作

对于大多数通用定时器使用场景而言，应在启动定时器之前设置警报动作，但不包括简单的挂钟场景，该场景仅需自由运行的定时器。设置警报动作，需要根据如何使用警报事件来配置 `gptimer_alarm_config_t` 的不同参数：

- `gptimer_alarm_config_t::alarm_count` 设置触发警报事件的目标计数值。设置警报值时还需考虑计数方向。当 `gptimer_alarm_config_t::auto_reload_on_alarm` 为 `true` 时，`gptimer_alarm_config_t::alarm_count` 和 `gptimer_alarm_config_t::reload_count` 不能设置为相同的值，因为警报值和重载值相同时没有意义。请注意，由于中断延迟，不建议将警报周期设置为小于 5 微秒。

- `gptimer_alarm_config_t::reload_count` 代表警报事件发生时要重载的计数值。此配置仅在 `gptimer_alarm_config_t::auto_reload_on_alarm` 设置为 true 时生效。

- `gptimer_alarm_config_t::auto_reload_on_alarm` 标志设置是否使能自动重载功能。如果使能，硬件定时器将在警报事件发生时立即将 `gptimer_alarm_config_t::reload_count` 的值重载到计数器中。

要使警报配置生效，需要调用 `gptimer_set_alarm_action()`。特别是当 `gptimer_alarm_config_t` 设置为 `NULL` 时，报警功能将被禁用。

备注

如果警报值已设置且定时器超过该值，则会立即触发警报。

### 注册事件回调函数

定时器启动后，可动态产生特定事件（如“警报事件”）。如需在事件发生时调用某些函数，请通过 `gptimer_register_event_callbacks()` 将函数挂载到中断服务例程 (ISR)。`gptimer_event_callbacks_t` 中列出了所有支持的事件回调函数：

- `gptimer_event_callbacks_t::on_alarm` 设置警报事件的回调函数。由于此函数在 ISR 上下文中调用，必须确保该函数不会试图阻塞（例如，确保仅从函数内调用具有 `ISR` 后缀的 FreeRTOS API）。函数原型在 `gptimer_alarm_cb_t` 中有所声明。

也可以通过参数 `user_data`，将自己的上下文保存到 `gptimer_register_event_callbacks()` 中。用户数据将直接传递给回调函数。

此功能将为定时器延迟安装中断服务，但不使能中断服务。所以，请在 `gptimer_enable()` 之前调用这一函数，否则将返回 `ESP_ERR_INVALID_STATE` 错误。了解详细信息，请查看章节 使能和禁用定时器。

### 使能和禁用定时器

在对定时器进行 IO 控制之前，需要先调用 `gptimer_enable()` 使能定时器。此函数功能如下：

- 此函数将把定时器驱动程序的状态从 init 切换为 enable。

- 如果 `gptimer_register_event_callbacks()` 已经延迟安装中断服务，此函数将使能中断服务。

- 如果选择了特定的时钟源（例如 APB 时钟），此函数将获取适当的电源管理锁。了解更多信息，请查看章节 电源管理。

调用 `gptimer_disable()` 会进行相反的操作，即将定时器驱动程序恢复到 init 状态，禁用中断服务并释放电源管理锁。

### 启动和停止定时器

启动和停止是定时器的基本 IO 操作。调用 `gptimer_start()` 可以使内部计数器开始工作，而 `gptimer_stop()` 可以使计数器停止工作。下文说明了如何在存在或不存在警报事件的情况下启动定时器。

调用 `gptimer_start()` 将使驱动程序状态从 enable 转换为 run, 反之亦然。注意确保 start 和 stop 函数成对使用，否则，函数可能返回 `ESP_ERR_INVALID_STATE`。

#### 将定时器作为挂钟启动

    ESP_ERROR_CHECK(gptimer_enable(gptimer));
    ESP_ERROR_CHECK(gptimer_start(gptimer));
    // Retrieve the timestamp at anytime
    uint64_t count;
    ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer, &count));

#### 触发周期性事件

    typedef struct {
        uint64_t event_count;
    } example_queue_element_t;

    static bool example_timer_on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
    {
        BaseType_t high_task_awoken = pdFALSE;
        QueueHandle_t queue = (QueueHandle_t)user_ctx;
        // Retrieve the count value from event data
        example_queue_element_t ele = {
            .event_count = edata->count_value
        };
        // Optional: send the event data to other task by OS queue
        // Don't introduce complex logics in callbacks
        // Suggest dealing with event data in the main loop, instead of in this callback
        xQueueSendFromISR(queue, &ele, &high_task_awoken);
        // return whether we need to yield at the end of ISR
        return high_task_awoken == pdTRUE;
    }

    gptimer_alarm_config_t alarm_config = {
        .reload_count = 0, // counter will reload with 0 on alarm event
        .alarm_count = 1000000, // period = 1s @resolution 1MHz
        .flags.auto_reload_on_alarm = true, // enable auto-reload
    };
    ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));

    gptimer_event_callbacks_t cbs = {
        .on_alarm = example_timer_on_alarm_cb, // register user callback
    };
    ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
    ESP_ERROR_CHECK(gptimer_enable(gptimer));
    ESP_ERROR_CHECK(gptimer_start(gptimer));

#### 触发一次性事件

    typedef struct {
        uint64_t event_count;
    } example_queue_element_t;

    static bool example_timer_on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
    {
        BaseType_t high_task_awoken = pdFALSE;
        QueueHandle_t queue = (QueueHandle_t)user_ctx;
        // Stop timer the sooner the better
        gptimer_stop(timer);
        // Retrieve the count value from event data
        example_queue_element_t ele = {
            .event_count = edata->count_value
        };
        // Optional: send the event data to other task by OS queue
        xQueueSendFromISR(queue, &ele, &high_task_awoken);
        // return whether we need to yield at the end of ISR
        return high_task_awoken == pdTRUE;
    }

    gptimer_alarm_config_t alarm_config = {
        .alarm_count = 1 * 1000 * 1000, // alarm target = 1s @resolution 1MHz
    };
    ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));

    gptimer_event_callbacks_t cbs = {
        .on_alarm = example_timer_on_alarm_cb, // register user callback
    };
    ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
    ESP_ERROR_CHECK(gptimer_enable(gptimer));
    ESP_ERROR_CHECK(gptimer_start(gptimer));

#### 警报值动态更新

通过更改 `gptimer_alarm_event_data_t::alarm_value`，可以在 ISR 程序回调中动态更新警报值。警报值将在回调函数返回后更新。

    typedef struct {
        uint64_t event_count;
    } example_queue_element_t;

    static bool example_timer_on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
    {
        BaseType_t high_task_awoken = pdFALSE;
        QueueHandle_t queue = (QueueHandle_t)user_data;
        // Retrieve the count value from event data
        example_queue_element_t ele = {
            .event_count = edata->count_value
        };
        // Optional: send the event data to other task by OS queue
        xQueueSendFromISR(queue, &ele, &high_task_awoken);
        // reconfigure alarm value
        gptimer_alarm_config_t alarm_config = {
            .alarm_count = edata->alarm_value + 1000000, // alarm in next 1s
        };
        gptimer_set_alarm_action(timer, &alarm_config);
        // return whether we need to yield at the end of ISR
        return high_task_awoken == pdTRUE;
    }

    gptimer_alarm_config_t alarm_config = {
        .alarm_count = 1000000, // initial alarm target = 1s @resolution 1MHz
    };
    ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));

    gptimer_event_callbacks_t cbs = {
        .on_alarm = example_timer_on_alarm_cb, // register user callback
    };
    ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
    ESP_ERROR_CHECK(gptimer_enable(gptimer));
    ESP_ERROR_CHECK(gptimer_start(gptimer));

### 电源管理

当电源管理 CONFIG_PM_ENABLE 被启用的时候，系统在进入睡眠前可能会调整或禁用时钟源。结果导致 GPTimer 的计时不准确。

驱动程序可以通过创建一个电源管理锁来防止上述问题。锁的类型会根据不同的时钟源来设置。驱动程序将在 `gptimer_enable()` 中拿锁，并在 `gptimer_disable()` 中释放锁。这意味着，在这两个函数之间，定时器可以正确工作，因为此时时钟源不会被禁用或改变频率。

### IRAM 安全

默认情况下，当 cache 因写入或擦除 flash 等原因而被禁用时，通用定时器的中断服务将会延迟，造成警报中断无法及时执行。在实时应用程序中通常需要避免这一情况发生。

调用 Kconfig 选项 CONFIG_GPTIMER_ISR_IRAM_SAFE 可实现如下功能：

- 即使禁用 cache 也可使能正在运行的中断

- 将 ISR 使用的所有函数放入 IRAM [2]

- 将驱动程序对象放入 DRAM（以防意外映射到 PSRAM）

这将允许中断在 cache 禁用时运行，但会增加 IRAM 使用量。

调用另一 Kconfig 选项 CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM 也可将常用的 IO 控制功能放入 IRAM，以便这些函数在 cache 禁用时也能执行。常用的 IO 控制功能如下：

- `gptimer_start()`

- `gptimer_stop()`

- `gptimer_get_raw_count()`

- `gptimer_set_raw_count()`

- `gptimer_set_alarm_action()`

### 线程安全

驱动提供的所有 API 都是线程安全的。使用时，可以直接从不同的 RTOS 任务中调用此类函数，无需额外锁保护。以下这些函数还支持在中断上下文中运行。

- `gptimer_start()`

- `gptimer_stop()`

- `gptimer_get_raw_count()`

- `gptimer_set_raw_count()`

- `gptimer_get_captured_count()`

- `gptimer_set_alarm_action()`

### Kconfig 选项

- CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM 控制着定时器控制函数的存放位置（IRAM 或 flash）。

- CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM 控制着定时器中断处理函数的存放位置（IRAM 或 flash）。

- CONFIG_GPTIMER_ISR_IRAM_SAFE 控制着中断处理函数是否需要在 cache 关闭的时候被屏蔽掉。更多信息，请参阅 IRAM 安全。

- CONFIG_GPTIMER_ENABLE_DEBUG_LOG 用于启用调试日志输出。启用这一选项将增加固件二进制文件大小。

## 应用示例

- peripherals/timer_group/gptimer 演示了如何在 ESP 芯片上使用通用定时器 API 生成周期性警报事件，触发不同的警报动作。

- peripherals/timer_group/wiegand_interface 使用两个定时器（一个在单次触发模式下，另一个在周期触发模式下），来触发中断并在中断中改变 GPIO 的输出状态。

## API 参考

### Header File

- components/esp_driver_gptimer/include/driver/gptimer.h

- This header file can be included with:

  >     #include "driver/gptimer.h"

- This header file is a part of the API provided by the `esp_driver_gptimer` component. To declare that your component depends on `esp_driver_gptimer`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_gptimer

  > or

  >     PRIV_REQUIRES esp_driver_gptimer

### Functions

esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *ret_timer)

  Create a new General Purpose Timer, and return the handle.

  备注

  The newly created timer is put in the "init" state.

  参数:

    - config -- [in] GPTimer configuration

    - ret_timer -- [out] Returned timer handle

  返回:

    - ESP_OK: Create GPTimer successfully

    - ESP_ERR_INVALID_ARG: Create GPTimer failed because of invalid argument

    - ESP_ERR_NO_MEM: Create GPTimer failed because out of memory

    - ESP_ERR_NOT_FOUND: Create GPTimer failed because all hardware timers are used up and no more free one

    - ESP_FAIL: Create GPTimer failed because of other error

esp_err_t gptimer_del_timer(gptimer_handle_t timer)

  Delete the GPTimer handle.

  备注

  A timer must be in the "init" state before it can be deleted.

  参数:

    timer -- [in] Timer handle created by `gptimer_new_timer`

  返回:

    - ESP_OK: Delete GPTimer successfully

    - ESP_ERR_INVALID_ARG: Delete GPTimer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Delete GPTimer failed because the timer is not in init state

    - ESP_FAIL: Delete GPTimer failed because of other error

esp_err_t gptimer_set_raw_count(gptimer_handle_t timer, uint64_t value)

  Set GPTimer raw count value.

  备注

  When updating the raw count of an active timer, the timer will immediately start counting from the new value.

  备注

  This function is allowed to run within ISR context

  备注

  If `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, makes it possible to execute even when the Flash Cache is disabled.

  参数:

    - timer -- [in] Timer handle created by `gptimer_new_timer`

    - value -- [in] Count value to be set

  返回:

    - ESP_OK: Set GPTimer raw count value successfully

    - ESP_ERR_INVALID_ARG: Set GPTimer raw count value failed because of invalid argument

    - ESP_FAIL: Set GPTimer raw count value failed because of other error

esp_err_t gptimer_get_raw_count(gptimer_handle_t timer, uint64_t *value)

  Get GPTimer raw count value.

  备注

  This function will trigger a software capture event and then return the captured count value.

  备注

  With the raw count value and the resolution returned from `gptimer_get_resolution`, you can convert the count value into seconds.

  备注

  This function is allowed to run within ISR context

  备注

  If `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, makes it possible to execute even when the Flash Cache is disabled.

  参数:

    - timer -- [in] Timer handle created by `gptimer_new_timer`

    - value -- [out] Returned GPTimer count value

  返回:

    - ESP_OK: Get GPTimer raw count value successfully

    - ESP_ERR_INVALID_ARG: Get GPTimer raw count value failed because of invalid argument

    - ESP_FAIL: Get GPTimer raw count value failed because of other error

esp_err_t gptimer_get_resolution(gptimer_handle_t timer, uint32_t *out_resolution)

  Return the real resolution of the timer.

  备注

  usually the timer resolution is same as what you configured in the `gptimer_config_t::resolution_hz`, but some unstable clock source (e.g. RC_FAST) will do a calibration, the real resolution can be different from the configured one.

  参数:

    - timer -- [in] Timer handle created by `gptimer_new_timer`

    - out_resolution -- [out] Returned timer resolution, in Hz

  返回:

    - 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_captured_count(gptimer_handle_t timer, uint64_t *value)

  Get GPTimer captured count value.

  备注

  Different from `gptimer_get_raw_count`, this function won't trigger a software capture event. It just returns the last captured count value. It's especially useful when the capture has already been triggered by an external event and you want to read the captured value.

  备注

  This function is allowed to run within ISR context

  备注

  If `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, makes it possible to execute even when the Flash Cache is disabled.

  参数:

    - timer -- [in] Timer handle created by `gptimer_new_timer`

    - value -- [out] Returned captured count value

  返回:

    - ESP_OK: Get GPTimer captured count value successfully

    - ESP_ERR_INVALID_ARG: Get GPTimer captured count value failed because of invalid argument

    - ESP_FAIL: Get GPTimer captured count value failed because of other error

esp_err_t gptimer_register_event_callbacks(gptimer_handle_t timer, const gptimer_event_callbacks_t *cbs, void *user_data)

  Set callbacks for GPTimer.

  备注

  User registered callbacks are expected to be runnable within ISR context

  备注

  The first call to this function needs to be before the call to `gptimer_enable`

  备注

  User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.

  参数:

    - timer -- [in] Timer handle created by `gptimer_new_timer`

    - cbs -- [in] Group of callback functions

    - user_data -- [in] User data, which will be passed to callback functions directly

  返回:

    - ESP_OK: Set event callbacks successfully

    - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Set event callbacks failed because the timer is not in init state

    - ESP_FAIL: Set event callbacks failed because of other error

esp_err_t gptimer_set_alarm_action(gptimer_handle_t timer, const gptimer_alarm_config_t *config)

  Set alarm event actions for GPTimer.

  备注

  This function is allowed to run within ISR context, so you can update new alarm action immediately in any ISR callback.

  备注

  If `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, makes it possible to execute even when the Flash Cache is disabled. In this case, please also ensure the `gptimer_alarm_config_t` instance is placed in the static data section instead of in the read-only data section. e.g.: `static gptimer_alarm_config_t alarm_config = { ... };`

  参数:

    - timer -- [in] Timer handle created by `gptimer_new_timer`

    - config -- [in] Alarm configuration, especially, set config to NULL means disabling the alarm function

  返回:

    - ESP_OK: Set alarm action for GPTimer successfully

    - ESP_ERR_INVALID_ARG: Set alarm action for GPTimer failed because of invalid argument

    - ESP_FAIL: Set alarm action for GPTimer failed because of other error

esp_err_t gptimer_enable(gptimer_handle_t timer)

  Enable GPTimer.

  备注

  This function will transit the timer state from "init" to "enable".

  备注

  This function will enable the interrupt service, if it's lazy installed in `gptimer_register_event_callbacks`.

  备注

  This function will acquire a PM lock, if a specific source clock (e.g. APB) is selected in the `gptimer_config_t`, while `CONFIG_PM_ENABLE` is enabled.

  备注

  Enable a timer doesn't mean to start it. See also `gptimer_start` for how to make the timer start counting.

  参数:

    timer -- [in] Timer handle created by `gptimer_new_timer`

  返回:

    - ESP_OK: Enable GPTimer successfully

    - ESP_ERR_INVALID_ARG: Enable GPTimer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Enable GPTimer failed because the timer is already enabled

    - ESP_FAIL: Enable GPTimer failed because of other error

esp_err_t gptimer_disable(gptimer_handle_t timer)

  Disable GPTimer.

  备注

  This function will transit the timer state from "enable" to "init".

  备注

  This function will disable the interrupt service if it's installed.

  备注

  This function will release the PM lock if it's acquired in the `gptimer_enable`.

  备注

  Disable a timer doesn't mean to stop it. See also `gptimer_stop` for how to make the timer stop counting.

  参数:

    timer -- [in] Timer handle created by `gptimer_new_timer`

  返回:

    - ESP_OK: Disable GPTimer successfully

    - ESP_ERR_INVALID_ARG: Disable GPTimer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Disable GPTimer failed because the timer is not enabled yet

    - ESP_FAIL: Disable GPTimer failed because of other error

esp_err_t gptimer_start(gptimer_handle_t timer)

  Start GPTimer (internal counter starts counting)

  备注

  This function will transit the timer state from "enable" to "run".

  备注

  This function is allowed to run within ISR context

  备注

  If `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, makes it possible to execute even when the Flash Cache is disabled.

  参数:

    timer -- [in] Timer handle created by `gptimer_new_timer`

  返回:

    - ESP_OK: Start GPTimer successfully

    - ESP_ERR_INVALID_ARG: Start GPTimer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Start GPTimer failed because the timer is not enabled or is already in running

    - ESP_FAIL: Start GPTimer failed because of other error

esp_err_t gptimer_stop(gptimer_handle_t timer)

  Stop GPTimer (internal counter stops counting)

  备注

  This function will transit the timer state from "run" to "enable".

  备注

  This function is allowed to run within ISR context

  备注

  If `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, makes it possible to execute even when the Flash Cache is disabled.

  参数:

    timer -- [in] Timer handle created by `gptimer_new_timer`

  返回:

    - ESP_OK: Stop GPTimer successfully

    - ESP_ERR_INVALID_ARG: Stop GPTimer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Stop GPTimer failed because the timer is not in running.

    - ESP_FAIL: Stop GPTimer failed because of other error

### Structures

struct gptimer_config_t

  General Purpose Timer configuration.

  Public Members

  gptimer_clock_source_t clk_src

    GPTimer clock source

  gptimer_count_direction_t direction

    Count direction

  uint32_t resolution_hz

    Counter resolution (working frequency) in Hz, hence, the step size of each count tick equals to (1 / resolution_hz) seconds

  int intr_priority

    GPTimer interrupt priority, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)

  uint32_t intr_shared

    Set true, the timer interrupt number can be shared with other peripherals

  uint32_t allow_pd

    If set, driver allows the power domain to be powered off when system enters sleep mode. This can save power, but at the expense of more RAM being consumed to save register context.

  uint32_t backup_before_sleep

    Deprecated:

      , same meaning as allow_pd

  struct gptimer_config_t flags

    GPTimer config flags

struct gptimer_event_callbacks_t

  Group of supported GPTimer callbacks.

  备注

  The callbacks are all running under ISR environment

  备注

  When CONFIG_GPTIMER_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.

  Public Members

  gptimer_alarm_cb_t on_alarm

    Timer alarm callback

struct gptimer_alarm_config_t

  General Purpose Timer alarm configuration.

  Public Members

  uint64_t alarm_count

    Alarm target count value

  uint64_t reload_count

    Alarm reload count value, effect only when `auto_reload_on_alarm` is set to true

  uint32_t auto_reload_on_alarm

    Reload the count value by hardware, immediately at the alarm event

  struct gptimer_alarm_config_t flags

    Alarm config flags

### Header File

- components/esp_driver_gptimer/include/driver/gptimer_types.h

- This header file can be included with:

  >     #include "driver/gptimer_types.h"

- This header file is a part of the API provided by the `esp_driver_gptimer` component. To declare that your component depends on `esp_driver_gptimer`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_gptimer

  > or

  >     PRIV_REQUIRES esp_driver_gptimer

### Structures

struct gptimer_alarm_event_data_t

  GPTimer alarm event data.

  Public Members

  uint64_t count_value

    Current count value

  uint64_t alarm_value

    Current alarm value

### Type Definitions

typedef struct gptimer_t *gptimer_handle_t

  Type of General Purpose Timer handle.

typedef bool (*gptimer_alarm_cb_t)(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)

  Timer alarm callback prototype.

  Param timer:

    [in] Timer handle created by `gptimer_new_timer`

  Param edata:

    [in] Alarm event data, fed by driver

  Param user_ctx:

    [in] User data, passed from `gptimer_register_event_callbacks`

  Return:

    Whether a high priority task has been waken up by this function

### Header File

- components/hal/include/hal/timer_types.h

- This header file can be included with:

  >     #include "hal/timer_types.h"

### Type Definitions

typedef soc_periph_gptimer_clk_src_t gptimer_clock_source_t

  GPTimer clock source.

  备注

  User should select the clock source based on the power and resolution requirement

### Enumerations

enum gptimer_count_direction_t

  GPTimer count direction.

  Values:

  enumerator GPTIMER_COUNT_DOWN

    Decrease count value

  enumerator GPTIMER_COUNT_UP

    Increase count value

[1]

不同 ESP 芯片系列的通用定时器实例数量可能不同。了解详细信息，请参考《ESP32-C3 技术参考手册》 > 章节定时器组 (TIMG) [PDF]。驱动程序对通道申请数量不做限制，但当硬件资源用尽时，驱动程序将返回错误。在分配资源时，请务必检查返回值（例如 `gptimer_new_timer()`）。

[2]

`gptimer_event_callbacks_t::on_alarm` 回调函数和这一函数调用的函数也需放在 IRAM 中，请自行处理。

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。