Hi Peter, thanks for the review. I have addressed all three comments:
- hit_time is now local to stm32f2xx_timer_set_alarm(); - CNT is preserved and returned verbatim while the timer is stopped, including when it is greater than ARR; - both VMState version fields are now 2, and stopped_cnt is serialized directly. I have also added a qtest for the stopped CNT case (ARR = 100, CNT = 200), and all five timer subtests pass. The updated [PATCH v2 1/2] is attached. Thanks, Manuele Ing. Manuele Conti Software Engineer - Research & Development department Archimede Energia P: +390323586222 F: +390323583066 M: +393783081660 A: Via dell'Industria 15, 28924 Verbania Fondotoce (VB) W: https://www.archimede-energia.com E: [email protected] [cid:[email protected]] Please consider the environment before printing this e-mail. This e-mail message including any attachments is for the sole use of the intended recipient and may contain confidential and privileged information pursuant to Legislative Decree 196/2003 and the European General Data Protection Regulation 679/2016 – GDPR-. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies of the original message. On 6 Oct 2026, at 14:56, Peter Maydell <[email protected]> wrote: Attenzione: Questa e` la prima volta che ricevi un'email da questo mittente. Attenzione: Assicurati che sia qualcuno di cui ti fidi. On Wed, 23 Sept 2026 at 22:56, Manuele Conti <[email protected]> wrote: RM0090 counters count from 0 to ARR inclusive, with period ARR + 1 for all ARR values including ARR == 0. Fix set_alarm to wrap CNT, arm an absolute expiry and delete the QEMU timer when CEN is cleared. Freeze CNT while CEN == 0 in stopped_cnt so a TIM_CNT write programmed while stopped is preserved and resumed on enable, and reset deletes any pending timer event. VMState goes to version 2 to serialize stopped_cnt. Loading a v1 stream leaves stopped_cnt at 0, so a timer stopped with CNT != 0 loads CNT as 0; no post_load workaround. The pre-existing QEMUTimer expiry limit is unchanged. Add qtests covering PSC/ARR/CEN/UIF, CNT <= ARR, CNT preset before CEN, ARR == 0, stop freeze on CEN=0, restart, and no spurious IRQ after reset. Signed-off-by: Manuele Conti <[email protected]> --- MAINTAINERS | 1 + hw/timer/stm32f2xx_timer.c | 101 ++++++++++++++++---- include/hw/timer/stm32f2xx_timer.h | 7 ++ tests/qtest/meson.build | 4 + tests/qtest/stm32f405-timer-test.c | 142 +++++++++++++++++++++++++++++ 5 files changed, 236 insertions(+), 19 deletions(-) create mode 100644 tests/qtest/stm32f405-timer-test.c diff --git a/MAINTAINERS b/MAINTAINERS index 5bf895732c..f1b3d75cc8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1213,6 +1213,7 @@ F: hw/misc/stm32f4xx_syscfg.c F: hw/misc/stm32f4xx_exti.c F: hw/misc/stm32_rcc.c F: include/hw/misc/stm32_rcc.h +F: tests/qtest/stm32f405* Netduino 2 M: Alistair Francis <[email protected]> diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c index 0442ac64ad..1639037130 100644 --- a/hw/timer/stm32f2xx_timer.c +++ b/hw/timer/stm32f2xx_timer.c @@ -53,7 +53,8 @@ static void stm32f2xx_timer_interrupt(void *opaque) if (s->tim_dier & TIM_DIER_UIE && s->tim_cr1 & TIM_CR1_CEN) { s->tim_sr |= 1; qemu_irq_pulse(s->irq); - stm32f2xx_timer_set_alarm(s, s->hit_time); + stm32f2xx_timer_set_alarm(s, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); This change means that the only uses of s->hit_time are in the sequence in stm32f2xx_timer_set_alarm(): s->hit_time = (uint64_t)now + delta_ns; timer_mod(s->timer, s->hit_time); DB_PRINT("Wait Time: %" PRId64 " ticks\n", s->hit_time); That means we can change hit_time to be a simple local variable in that function; it doesn't need to be a state field any more. } if (s->tim_ccmr1 & (TIM_CCMR1_OC2M2 | TIM_CCMR1_OC2M1) && static uint64_t stm32f2xx_timer_read(void *opaque, hwaddr offset, @@ -148,8 +172,11 @@ static uint64_t stm32f2xx_timer_read(void *opaque, hwaddr offset, case TIM_CCER: return s->tim_ccer; case TIM_CNT: - return stm32f2xx_ns_to_ticks(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) - - s->tick_offset; + if (!(s->tim_cr1 & TIM_CR1_CEN)) { + return s->stopped_cnt % ((uint64_t)s->tim_arr + 1); + } This looks odd -- I wouldn't expect the auto-reload register to have any effect if the counter is stopped. That is, if you do: * set the counter to disabled * set ARR to 100 * set CNT to 200 * read CNT I would expect to read back 200 (and then if you enable the counter it probably rolls back to 0 on the next clock, regardless of what its value above the auto-reload value is?) Do you have real hardware to confirm the behaviour against? + return stm32f2xx_timer_get_cnt(s, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); case TIM_PSC: return s->tim_psc; case TIM_ARR: @@ -272,7 +328,7 @@ static const MemoryRegionOps stm32f2xx_timer_ops = { static const VMStateDescription vmstate_stm32f2xx_timer = { .name = TYPE_STM32F2XX_TIMER, - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .fields = (const VMStateField[]) { VMSTATE_INT64(tick_offset, STM32F2XXTimerState), @@ -294,6 +350,13 @@ static const VMStateDescription vmstate_stm32f2xx_timer = { VMSTATE_UINT32(tim_dcr, STM32F2XXTimerState), VMSTATE_UINT32(tim_dmar, STM32F2XXTimerState), VMSTATE_UINT32(tim_or, STM32F2XXTimerState), + /* + * New in version 2: frozen CNT while CEN == 0. Pre-existing + * limitation left unchanged: QEMUTimer expiry (hit_time) is + * not migrated and is re-armed by the next register write; + * see stm32f2xx_timer_set_alarm. + */ + VMSTATE_UINT32_V(stopped_cnt, STM32F2XXTimerState, 2), We don't care about migration compatibility on these machine types, so we could just bump both version_id and minimum_version_id to 2 and define the field as a simple VMSTATE_UINT32(). VMSTATE_END_OF_LIST() } }; Otherwise this looks OK, and certainly better than what we have now. thanks -- PMM -- Questo messaggio e' stato analizzato da MyAntispam.it ed e' risultato non infetto. Seguire il link qui sotto per segnalarlo come spam: http://email.myantispam.it/action/4hzbqW3ZTDzMqgR/report-as-bad http://email.myantispam.it/action/4hzbqW3ZTDzMqgR/blocklist
0001-hw-timer-stm32f2xx_timer-fix-periodic-mode-and-CEN-h.patch
Description: 0001-hw-timer-stm32f2xx_timer-fix-periodic-mode-and-CEN-h.patch
