yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
ESP32 Core Board📖
1. ESP32 Introduction
  • 1. ESP32S3 Overview
  • 2. Environment Setup Introduction
  • 3. Dev Board Introduction
2. ESP-IDF Development Tutorial
1. Before Development
  • 1. Environment Setup (Windows)
  • 2. Environment Setup (Linux)
  • 3. Build and Flash
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. ESP_TIMER
  • 5. GPTIMER
  • 6. Watchdog Timer
  • 7. DMA
  • 8. ADC
  • 9. PWM Breathing LED
  • 10. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication Experiment
  • 2. I2C_OLED Display Experiment
  • 3. SPI Bus Communication Experiment
  • 4. PSRAM External Memory Experiment
  • 5. Flash Read and Write Experiment
  • 6. USB Emulated Mass Storage Experiment
4. FreeRTOS operating system
  • 1.FreeRTOS Core Concepts Theory
  • 2.Task Creation and Management
  • 3.Queue
  • 4.Binary Semaphore
  • 5.Mutex
  • 6.Event Groups
  • 7.Software Timer
  • 8.Task Scheduler
  • 9.Low Power Mode
  • 10.Deadlock
  • 11.Priority Inversion
5. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Client Experiment
  • 5. UDP Server Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. Socket Programming Basics
  • 9. HTTP Client Experiment
  • 10. HTTP Server Experiment
  • 11. MQTT IoT Communication Protocol
  • 12. WIFI OTA Upgrade
  • 13. Bluetooth Fundamentals
  • 14. Bluetooth Slave Mode
  • 15. Bluetooth Master Mode
6. Audio Applications
  • 1.I2S Microphone Recording and U-Disk Playback
  • 2.I2S Audio Playback Experiment
  • 3.Repeater Experiment
7. Xiaozhi AI Voice
  • 1. Burn Xiaozhi Firmware
  • 2. Network and Configuration
  • 3. AI Agent Settings
  • 4. Program Analysis
  • 5. Free Chat
3. Arduino Development Course
1. Before Development
  • 1. Environment Setup
  • 2. Build and Flash
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. ESP_TIMER
  • 5. GPTIMER
  • 6. Watchdog Timer
  • 7. ADC
  • 8. PWM Breathing LED
  • 9. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication
  • 2. I2C OLED Display
  • 3. SPI Bus Communication
  • 4. Flash Read and Write
  • 5. USB Emulated Mass Storage
4. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Server Experiment
  • 5. UDP Client Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. HTTP Client Experiment
  • 9. HTTP Server Experiment
  • 10. MQTT IoT Communication Protocol
  • 11. WIFI OTA Upgrade
  • 12. Bluetooth Fundamentals
  • 13. Bluetooth Slave Mode
  • 14. Bluetooth Master Mode
5. Audio Applications
  • 1.I2S Microphone Recording and U-Disk Playback
  • 2.I2S Audio Playback Experiment
  • 3.Repeater Experiment
4. MicroPython Development Course
1. Before Development
  • 1. Environment Setup
  • 2. Build and Flash
  • 3. Thonny IDE
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. TIMER_IT
  • 5. Watchdog Timer
  • 6. ADC
  • 7. PWM Breathing LED
  • 8. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication Experiment
  • 2. I2C_OLED Display Experiment
  • 3. SPI Bus Communication Experiment
  • 4. Flash Read and Write Experiment
  • 5. Print Storage
4. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Client Experiment
  • 5. UDP Server Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. HTTP Client Experiment
  • 9. HTTP Server Experiment
  • 10. MQTT
  • 11. Bluetooth Fundamentals
  • 12. Bluetooth Slave Mode
  • 13. Bluetooth Master Mode
5. Audio Applications
  • 1. I2S Audio Playback Experiment
  • 2. Repeater Experiment
Download
  • Code
  • Hardware_Info
  • 3D_Model_File
  • Software_Tools
  • VMware
  • VM_File
Download ZIP

Welcome to ESP32 Core Board repository

5. GPTIMER

GPTIMER


GPTIMER1. GPTimer Overview2. Core Concepts2.1 Clock Source and Resolution2.2 Counting Direction2.3 Pure Counting Mode vs Alarm Mode3. Project Architecture and Flow4. Hardware Dependencies5. Source Code Analysis5.1 Macro Definitions and Global Variables5.2 timer_init() — Three-Step Start5.3 app_main() — Main Entry6. Operation Flow6.1 Build and Flash6.2 Normal Output7. Common Issues


1. GPTimer Overview

GPTimer (General Purpose Timer) is a hardware timer peripheral of ESP32-S3, providing an independent 54-bit counter with configurable clock source, resolution, counting direction, and alarm threshold. Compared to software timer (ESP_Timer), GPTimer directly operates hardware registers, providing maximum flexibility.

This experiment configures GPTimer as a 1MHz free-running up counter (no interrupt, no callback). Main loop reads the current count value once per second. Demonstrates GPTimer's most basic "pure counting" usage—a high-precision time reference.

ESP_Timer vs GPTimer Selection Guide:

Featureesp_timer (software timer)GPTimer (hardware timer)
Abstraction LevelHigh (ESP-IDF encapsulation)Low (direct hardware operation)
Usage ComplexitySimple (3-5 APIs)Medium (7+ APIs)
Callback SupportBuilt-in ISR/TASK dispatchNeed to configure ISR yourself
Resolution1µsConfigurable (up to 40MHz)
Power ConsumptionFixedConfigurable clock source to reduce power
Applicable ScenarioGeneral timing needsHigh-precision timing, encoder interface, PWM generation

Typical Application Scenarios:

Application TypeExample
Precise TimingMotor PWM deadzone control, stepper motor pulse sequences
Frequency MeasurementInput capture frequency measurement, tachometer signal processing
Pulse GenerationPrecise delay trigger, laser/ultrasonic ranging trigger signal
High-speed CountingEncoder pulse counting, production line photoelectric counting

2. Core Concepts

2.1 Clock Source and Resolution

This configuration struct is like "factory settings" for a stopwatch—choosing which clock source, which direction to count, and what each tick represents. 1MHz resolution means 1 tick equals 1 microsecond. The read count value is directly microseconds, very intuitive.

gptimer_config_t timer_config = {
    // Default clock source (XTAL-derived)
    .clk_src       = GPTIMER_CLK_SRC_DEFAULT,
    .direction     = GPTIMER_COUNT_UP,          // Count up
    // Resolution 1MHz, 1 tick = 1µs
    .resolution_hz = 1000000,
};

resolution_hz determines what time each tick represents:

resolution_hz1 tick =54-bit max count time
1,000,000 (1MHz)1 µs~570,000 years
1,000 (1kHz)1 ms~570 million years
40,000,000 (40MHz)25 ns~14,000 years

Clock source precision affects counting precision:

Clock Source OptionPrecisionDescription
GPTIMER_CLK_SRC_DEFAULT~±20ppmXTAL crystal clock, most stable
GPTIMER_CLK_SRC_RC_FAST~±5%Internal RC oscillator, lower precision

2.2 Counting Direction

This enum tells the timer "which direction to count"—either from large to small (countdown) or from small to large (count-up). This experiment chooses count-up, so the read value directly equals microseconds elapsed since start, no subtraction needed.

xxxxxxxxxx
typedef enum {
    // Count down: from alarm value decrementing to 0
    GPTIMER_COUNT_DOWN = 0,
    // Count up: from 0 incrementing to alarm value
    GPTIMER_COUNT_UP   = 1,
} gptimer_count_direction_t;

This experiment chooses GPTIMER_COUNT_UP: starting from 0 and incrementing, no alarm value limit, continuously free counting. The read count value directly represents "microseconds elapsed since startup".

2.3 Pure Counting Mode vs Alarm Mode

ModeConfigurationRead MethodThis Experiment
Pure countingNo alarm, no callbackSoftware polling gptimer_get_raw_count()✅
Alarm countingSet alarm value + ISR callbackISR notification + e.g. PWM generation—

Pure counting mode advantages: simple, zero interrupt overhead, CPU reads when needed, suitable for timestamp and time difference measurement.


3. Project Architecture and Flow

xxxxxxxxxx
app_main()
  ├─ timer_init()           Create 1MHz free counter
  │   ├─ gptimer_new_timer()   Create timer instance (clock source+direction+resolution)
  │   ├─ gptimer_enable()      Enable timer (power on but not counting)
  │   └─ gptimer_start()       Start counting (from 0, incrementing)
  │
  └─ while(1) Main Loop
      ├─ gptimer_get_raw_count()  Read current count value (64-bit)
      ├─ ESP_LOGI()               Display in three units: count / µs / ms
      └─ vTaskDelay(1000ms)       Read once per second

GPTimer Lifecycle:

xxxxxxxxxx
gptimer_new_timer()      Create + allocate resources
  └─ gptimer_enable()    Enable clock + power on
       └─ gptimer_start()  Start counting (direction+reset to 0)
            │
            ├─ ... in use (this experiment never exits)...
            │
            └─ gptimer_stop()   Stop counting
                 └─ gptimer_disable()  Disable clock
                      └─ gptimer_del_timer()  Release resources

4. Hardware Dependencies

Hardware Connection: No external hardware dependency, pure timer register operation.

Dependencies: freertos, driver/gptimer, esp_log


5. Source Code Analysis

5.1 Macro Definitions and Global Variables

These two lines are preparation—define a log tag for easy identification during debugging, then define an empty handle variable to store the timer instance later. The handle is like a "remote control", all future timer operations rely on it to specify which timer.

xxxxxxxxxx
#define TAG "TIMER_COUNT"                                // Log tag
// Timer handle
static gptimer_handle_t gptimer = NULL;

Handle is ESP-IDF's universal design pattern: creation API returns an opaque pointer, all subsequent operations reference the peripheral instance through it. The handle internally points to driver data structure allocated by ESP-IDF, users don't need to care about its internal layout.

5.2 timer_init() — Three-Step Start

This function starts the timer with "three-step process": first fill the configuration table, call new to create timer instance (like buying a stopwatch); second enable to power on the timer (install battery); third start to begin counting (press start button). Order cannot be changed, all three are essential.

xxxxxxxxxx
static void timer_init(void)
{
    gptimer_config_t timer_config = {
        // Default clock source (XTAL-derived)
        .clk_src       = GPTIMER_CLK_SRC_DEFAULT,
        .direction     = GPTIMER_COUNT_UP,           // Count up
        // Resolution 1MHz, 1 tick = 1µs
        .resolution_hz = 1000000,
    };
    // ① Create timer instance
    gptimer_new_timer(&timer_config, &gptimer);
    // ② Enable timer
    gptimer_enable(gptimer);
    // ③ Start counting
    gptimer_start(gptimer);
}

Why choose 1MHz instead of 40MHz? 1 tick = 1µs is a very intuitive relationship—count value is directly microseconds, no conversion needed. 40MHz (25ns/tick) has excessive precision but troublesome conversion, and this experiment's vTaskDelay(1000ms) polling-level precision doesn't need such high resolution.

Why not split into two steps (enable → delay → start)? Some peripherals need stabilization time after clock enable. GPTimer internal hardware is synchronous design, register writes from gptimer_enable to gptimer_start are guaranteed ordering by APB bus bridge, no additional delay needed.

5.3 app_main() — Main Entry

Main function logic is very simple: first print a tagline, then call timer_init to start the timer, then enter an infinite loop—every 1 second read the timer's current count value, then print in three units (raw count/µs/ms). The three numbers are essentially the same, just different units, making it convenient to understand the correspondence between tick and time.

​x
void app_main(void)
{
    // Print startup info
    ESP_LOGI(TAG, "ESP32-S3 GPTimer Raw Counting Mode");
    // Initialize timer
    timer_init();
    // Confirm started
    ESP_LOGI(TAG, "Timer started successfully, counting freely");

    while (1) {
        uint64_t count_value;
        // Read current count value
        gptimer_get_raw_count(gptimer, &count_value);

        // Display in 3 units: raw/μs/ms
        ESP_LOGI(TAG, "Count=%llu  |  %llu us  |  %.2f ms",
                 count_value, count_value, (float)count_value / 1000.0f);

        // Delay 1 second
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

Output Interpretation:

xxxxxxxxxx
Count=1006516  |  1006516 us  |  1006.52 ms
 ↑                 ↑                ↑
 Raw count value   Same value=µs     count÷1000 = ms

The three columns in output are essentially the same value: Since 1 tick = 1µs, count_value itself is microseconds. The purpose of three-column display is to help understand the correspondence between "1 tick = 1µs". If configured as 40MHz, need to divide by 40 to convert time.

First output offset explanation: First line count ≈ 1006516 instead of 1000000 is because from chip power-on to first read, there's startup time for bootloader → FreeRTOS initialization → app_main() → timer_init(). The timer was already counting during this time. Each subsequent increment is precisely 1,000,000 because GPTimer uses XTAL crystal clock source with precision ±20ppm, far better than vTaskDelay's software delay precision.


6. Operation Flow

6.1 Build and Flash

For detailed flashing process, see: 1. Before Development → 3. Build and Flash

6.2 Normal Output

xxxxxxxxxx
I (275) TIMER_COUNT: ESP32-S3 GPTimer Raw Counting Mode
I (275) TIMER_COUNT: Timer started successfully, counting freely
I (275) TIMER_COUNT: Count=2583  |  2583 us  |  2.58 ms
I (1285) TIMER_COUNT: Count=1006516  |  1006516 us  |  1006.52 ms
I (2285) TIMER_COUNT: Count=2006516  |  2006516 us  |  2006.52 ms
I (3285) TIMER_COUNT: Count=3006516  |  3006516 us  |  3006.52 ms
I (4285) TIMER_COUNT: Count=4006516  |  4006516 us  |  4006.52 ms

Observing the pattern:

硬件定时器运行数据

  • First line count is small (2583), because from timer_init() to first gptimer_get_raw_count() only a few lines of code apart, so only ~2.5ms interval

  • Each subsequent increment is precisely 1,000,000, corresponding to 1 second. GPTimer uses XTAL crystal clock with precision ±20ppm, far more reliable than vTaskDelay

  • Timestamps in log brackets (1285 → 2285 → 3285) are also exactly 1000ms apart, indicating vTaskDelay(1000ms) also has good precision under ESP-IDF default 1000Hz tick


7. Common Issues

PhenomenonCauseSolution
Count faster/slower than expectedresolution_hz misconfiguredCheck resolution_hz = 1000000
gptimer_new_timer returns ESP_ERR_NOT_FOUNDHardware timer resources exhausted (max 4)Release unused timers
gptimer_get_raw_count reads 0gptimer_start() not calledIn order: new → enable → start
Count value increment inaccuratevTaskDelay precision limited (±10ms)Use alarm+ISR mode instead of polling, or read esp_timer_get_time for comparison
Output timestamp and counter out of syncMain loop printing is after vTaskDelay returns, not exactly 1000msNormal phenomenon, vTaskDelay guarantees "at least delay" not precise delay
ESP_TIMER
Watchdog Timer

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文