diff --git a/hw/timer/esp32c3_timg.c b/hw/timer/esp32c3_timg.c index 724a2116cf..2ec26e4b07 100644 --- a/hw/timer/esp32c3_timg.c +++ b/hw/timer/esp32c3_timg.c @@ -83,7 +83,7 @@ static void esp32c3_virtual_counter_reset(ESP32C3VirtualCounter* counter) timer_del(&counter->timer); counter->base = 0; counter->value = 0; - counter->frequency = 160000000; // Hz + counter->frequency = ESP32C3_APB_CLK; } @@ -320,8 +320,8 @@ static void esp32c3_t0_cb(void* opaque) { ESP32C3T0State* t = (ESP32C3T0State*) opaque; - /* Update the value of the counter and disable the alarm timer */ - esp32c3_virtual_counter_reset(&t->counter); + /* Disable the alarm timer */ + timer_del(&t->counter.timer); esp32c3_virtual_counter_reenabled(&t->counter); /* In practice, the counter is bigger than the requested value, this is due to the fact @@ -336,7 +336,7 @@ static void esp32c3_t0_cb(void* opaque) /* Alarm was triggered, clear alarm bit, set the IRQ if interrupts enabled */ t->config &= ~R_TIMG_T0CONFIG_ALARM_EN_MASK; - t->raw_st = true; + t->raw_st = 1; if (t->int_enabled) { qemu_irq_raise(t->interrupt_irq); } @@ -628,10 +628,22 @@ static void esp32c3_timg_write(void *opaque, hwaddr addr, break; /* Interrupt related registers */ - case A_TIMG_INT_ENA_TIMG: + case A_TIMG_INT_ENA_TIMG: { + bool former = s->wdt.int_enabled; s->wdt.int_enabled = FIELD_EX32(value, TIMG_INT_ENA_TIMG, WDT_ENA) ? true : false; + if (s->wdt.int_enabled != former) { + qemu_set_irq(s->wdt.interrupt_irq, + s->wdt.raw_st && s->wdt.int_enabled ? 1 : 0); + } + + former = s->t0.int_enabled; s->t0.int_enabled = FIELD_EX32(value, TIMG_INT_ENA_TIMG, T0_ENA) ? true : false; + if (s->t0.int_enabled != former) { + qemu_set_irq(s->t0.interrupt_irq, + s->t0.raw_st && s->t0.int_enabled ? 1 : 0); + } break; + } case A_TIMG_INT_CLR_TIMG: if (FIELD_EX32(value, TIMG_INT_CLR_TIMG, WDT_CLR)) { s->wdt.raw_st = 0; diff --git a/target/riscv/esp_cpu.c b/target/riscv/esp_cpu.c index 52bb6f5691..07d81d1b65 100644 --- a/target/riscv/esp_cpu.c +++ b/target/riscv/esp_cpu.c @@ -59,9 +59,16 @@ static uint64_t esp_cpu_get_cycles(ESPCPUCycleCounter* cc) /* If we are not in the first call, calculate the difference */ if (cc->former_time != 0) { - /* Let's say that we have 1 instruction/clock cycle, so 1 instruction/6.25ns */ + /* The divider is in picoseconds, for a more precise result. It would be possible to simpyl return + * cc->cycles = (now * 1000 / cc->divider). However, doing so would prevent a future implementation + * of CPU frequency change as the cycles count would go backward as soon as the frequency is higher + */ assert(cc->divider != 0); - diff = (now - cc->former_time) / cc->divider; + const uint64_t num = (now - cc->former_time) * 1000 + cc->former_rem_cycles; + diff = num / cc->divider; + /* Store the remaining executed clock cycles that were not taken into account in the division, + * they will be added back in the next run */ + cc->former_rem_cycles = num % cc->divider; } cc->former_time = now; cc->cycles += diff; @@ -307,10 +314,10 @@ static void esp_cpu_init(Object *obj) riscv_set_csr_ops(ESP_CPU_CSR_MCYCLE_U, &esp_cpu_csr_ops); s->cc_machine = (ESPCPUCycleCounter) { - .divider = 6, /* 6.25ns per instruction at 160MHz. */ + .divider = 6250, /* 6.25ns per instruction at 160MHz. */ }; s->cc_user = (ESPCPUCycleCounter) { - .divider = 6, /* Should be using the target configured CPU clock frequency instead. */ + .divider = 6250, /* Should be using the target configured CPU clock frequency instead. */ }; } diff --git a/target/riscv/esp_cpu.h b/target/riscv/esp_cpu.h index c44fbe0cf7..abea3943ef 100644 --- a/target/riscv/esp_cpu.h +++ b/target/riscv/esp_cpu.h @@ -35,8 +35,9 @@ /* Define a type that will be used to generate a cycle counter */ typedef struct { uint64_t former_time; + uint64_t former_rem_cycles; uint64_t cycles; - /* The number of nanosecond an instruction takes to execute */ + /* The number of picoseconds an instruction takes to execute */ uint64_t divider; } ESPCPUCycleCounter;