Alarm from general purpose timer not triggered when too old (QEMU-104)
blaizard opened this issue · 0 comments
The timer interrupt for the esp32 machine doesn't behave the same as the physical target.
When the alarm of a general purpose timer is set and the alarm value is lower than the actual counter, the interrupt should be triggered. This is stated in the documentation, from https://docs.espressif.com/projects/esp-idf/en/v5.0.1/esp32/api-reference/peripherals/gptimer.html#set-up-alarm-action
If an alarm value is set and the timer has already exceeded this value, the alarm will be triggered immediately.
This work fine on a physical esp32 but not on QEMU. Here is a sample code to reproduce the issue:
static bool testCallback(::gptimer_handle_t, const ::gptimer_alarm_event_data_t* edata, void* userCtx)
{
::esp_rom_printf("ISR triggered, counter=%llu\r\n", edata->count_value);
std::atomic<uint64_t>& counter = *static_cast<std::atomic<uint64_t>*>(userCtx);
counter.store(edata->count_value);
return false;
}
::gptimer_handle_t gptimer_;
::gptimer_config_t config{};
config.clk_src = GPTIMER_CLK_SRC_APB;
config.direction = GPTIMER_COUNT_UP;
config.resolution_hz = 10 * 1000; // 0.1ms
config.flags.intr_shared = false;
::gptimer_new_timer(&config, &gptimer_);
::gptimer_event_callbacks_t callback{
.on_alarm = testCallback
};
std::atomic<uint64_t> counter{0};
::gptimer_register_event_callbacks(gptimer_, &callback, &counter);
::gptimer_enable(gptimer_);
::gptimer_start(gptimer_);
vTaskDelay(pdMS_TO_TICKS(1000));
::gptimer_alarm_config_t alarm{};
alarm.alarm_count = 10;
::gptimer_set_alarm_action(gptimer_, &alarm);
::esp_rom_printf("waiting...\r\n");
while (counter.load() == 0);
::esp_rom_printf("counter=%llu\r\n", counter.load());
Running the exact same binary on the QEMU or the real physical esp32, I get different behavior.
On QEMU, it only prints:
waiting...
while on the physical esp32:
ISR triggered, counter=9982
waiting...
counter=9982
Note that the expected behavior is the physical esp32. I initially raised this issue as part of the IDF github (espressif/esp-idf#10877) but narrow it down to QEMU.