The current implementation uses nano-second precision, while the RTC can not be more precise than a milli-second. Simplify by using a milli-second based timer. Rename the timer 'alrm_timer_ms' to have the unit explicit.
Inspired-by: Mark Cave-Ayland <mark.cave-ayl...@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org> --- hw/rtc/m48t59-internal.h | 2 +- hw/rtc/m48t59.c | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/hw/rtc/m48t59-internal.h b/hw/rtc/m48t59-internal.h index cd648241e9..f21b603f97 100644 --- a/hw/rtc/m48t59-internal.h +++ b/hw/rtc/m48t59-internal.h @@ -49,7 +49,7 @@ typedef struct M48t59State { time_t stop_time; /* Alarm & watchdog */ struct tm alarm; - QEMUTimer *alrm_timer; + QEMUTimer *alrm_timer_ms; QEMUTimer *wd_timer; /* NVRAM storage */ uint8_t *buffer; diff --git a/hw/rtc/m48t59.c b/hw/rtc/m48t59.c index 47d48054fd..d2717d00a9 100644 --- a/hw/rtc/m48t59.c +++ b/hw/rtc/m48t59.c @@ -89,7 +89,7 @@ static M48txxInfo m48txx_sysbus_info[] = { static void alarm_cb (void *opaque) { struct tm tm; - uint64_t next_time; + uint64_t next_time_s; M48t59State *NVRAM = opaque; qemu_set_irq(NVRAM->IRQ, 1); @@ -104,42 +104,43 @@ static void alarm_cb (void *opaque) tm.tm_mon = 1; tm.tm_year++; } - next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset; + next_time_s = qemu_timedate_diff(&tm) - NVRAM->time_offset; } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && (NVRAM->buffer[0x1FF4] & 0x80) == 0 && (NVRAM->buffer[0x1FF3] & 0x80) == 0 && (NVRAM->buffer[0x1FF2] & 0x80) == 0) { /* Repeat once a day */ - next_time = 24 * 60 * 60; + next_time_s = 24 * 60 * 60; } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && (NVRAM->buffer[0x1FF4] & 0x80) != 0 && (NVRAM->buffer[0x1FF3] & 0x80) == 0 && (NVRAM->buffer[0x1FF2] & 0x80) == 0) { /* Repeat once an hour */ - next_time = 60 * 60; + next_time_s = 60 * 60; } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && (NVRAM->buffer[0x1FF4] & 0x80) != 0 && (NVRAM->buffer[0x1FF3] & 0x80) != 0 && (NVRAM->buffer[0x1FF2] & 0x80) == 0) { /* Repeat once a minute */ - next_time = 60; + next_time_s = 60; } else { /* Repeat once a second */ - next_time = 1; + next_time_s = 1; } - timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) + - next_time * 1000); + timer_mod(NVRAM->alrm_timer_ms, + qemu_clock_get_ms(rtc_clock) + next_time_s * + NANOSECONDS_PER_SECOND / SCALE_MS); qemu_set_irq(NVRAM->IRQ, 0); } static void set_alarm(M48t59State *NVRAM) { int diff; - if (NVRAM->alrm_timer != NULL) { - timer_del(NVRAM->alrm_timer); + if (NVRAM->alrm_timer_ms != NULL) { + timer_del(NVRAM->alrm_timer_ms); diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset; if (diff > 0) - timer_mod(NVRAM->alrm_timer, diff * 1000); + timer_mod(NVRAM->alrm_timer_ms, diff * 1000); } } @@ -539,9 +540,9 @@ void m48t59_reset_common(M48t59State *NVRAM) { NVRAM->addr = 0; NVRAM->lock = 0; - if (NVRAM->alrm_timer != NULL) - timer_del(NVRAM->alrm_timer); - + if (NVRAM->alrm_timer_ms != NULL) { + timer_del(NVRAM->alrm_timer_ms); + } if (NVRAM->wd_timer != NULL) timer_del(NVRAM->wd_timer); } @@ -603,7 +604,7 @@ void m48t59_realize_common(M48t59State *s, Error **errp) { s->buffer = g_malloc0(s->size); if (s->model == 59) { - s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s); + s->alrm_timer_ms = timer_new_ms(rtc_clock, &alarm_cb, s); s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s); } qemu_get_timedate(&s->alarm, 0); -- 2.21.3