GPTimer Frequency Not As Expected
Posted: Mon Oct 06, 2025 6:04 pm
Hi!
I'm developing a custom PWM driver based on the GPTimer.
Chip: ESP32S3
Borad: Adafruit ESP32S3 QTPY no psram
I tested a version on Arduino esp32, and it works as expected:
where timerfreq is 40,000,000; pwm_bits is 8; pwm_freq is 300.
However, when I tried to migrate the project to ESP-IDF, the timer considerablly slowed down
The ISR:
vema_pwm_ptr is an 8-bit number; it automatically overflows
The Arduino code gives me about ~300Hz, the ESP-idf code gives me about ~311Hz
But notice the alarm_count for each is very different. Arduino alarm_count = 16666; ESP = 500
I wonder what might have caused this difference?
I have already changed FreeRTOS tick 100->1000, and CPU frequency is 240MHz.
Many thanks for any help!!!!
I'm developing a custom PWM driver based on the GPTimer.
Chip: ESP32S3
Borad: Adafruit ESP32S3 QTPY no psram
I tested a version on Arduino esp32, and it works as expected:
Code: Select all
// Set timer frequency to 1Mhz
pctrl_timer = timerBegin(timerfreq);
timerAttachInterrupt(pctrl_timer, &VEMA_PWM_PCTRL);
timerAlarm(pctrl_timer, (timerfreq >> pwm_bits) / pwm_freq, true, 0);
However, when I tried to migrate the project to ESP-IDF, the timer considerablly slowed down
Code: Select all
uint64_t resolution_hz = 40000000;
uint64_t alarm_count = 500;
uint64_t reload_count = 0;
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = resolution_hz,
.intr_priority = 3,
.flags.intr_shared = 0,
.flags.allow_pd = 0,
.flags.backup_before_sleep = 0,
};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
gptimer_event_callbacks_t cbs = {
.on_alarm = PWM_isr,
};
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
ESP_LOGI(TAG, "Enable timer");
ESP_ERROR_CHECK(gptimer_enable(gptimer));
ESP_LOGI(TAG, "Start timer, stop it at alarm event");
gptimer_alarm_config_t alarm_config1 = {
.reload_count = reload_count,
.alarm_count = alarm_count,
.flags.auto_reload_on_alarm = true,
};
ESP_ERROR_CHECK(gptimer_set_raw_count(gptimer, 0));
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config1));
ESP_ERROR_CHECK(gptimer_start(gptimer));
The ISR:
Code: Select all
static bool IRAM_ATTR PWM_isr(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) {
// increment the PWM counter
// since this is a 8 bit unsigned integer
// it will automatically overflow and go back to 0 after hitting max
vema_pwm_ptr++;
// here, we use v1 duty cycle as inlet duty cycle
if (vema_pwm_ptr > 120) {
// pressure too low, turn off outlet valve
gpio_set_level(V_OUT, LOW);
gpio_set_level(V_IN, LOW);
} else {
gpio_set_level(V_OUT, HIGH);
gpio_set_level(V_IN, HIGH);
}
return true;
}The Arduino code gives me about ~300Hz, the ESP-idf code gives me about ~311Hz
But notice the alarm_count for each is very different. Arduino alarm_count = 16666; ESP = 500
I wonder what might have caused this difference?
I have already changed FreeRTOS tick 100->1000, and CPU frequency is 240MHz.
Many thanks for any help!!!!