From: Alan Cox Date: Mon, 22 Dec 2014 12:39:17 +0000 (+0000) Subject: timer: add initial support for RTC seconds locking X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=9ca333107a8a873291b41b900b6ec873fd53636f;p=FUZIX.git timer: add initial support for RTC seconds locking We don't try and use the RTC as our actual clock. Many RTCs are not Y2K safe or have their own interesting sets of problems. We would also have to keep doing Unix type v RTC time conversion maths. Instead we treat the RTC seconds as a free running counter and update our second tick as we see the RTC one shift. This also gives us up to 59 seconds of 'overrun' which should do for the worst case disk I/O problems. --- diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index 3b3e3882..11b93f95 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -687,6 +687,7 @@ CODE2 void rdtime(time_t *tloc); CODE2 void rdtime32(uint32_t *tloc); CODE2 void wrtime(time_t *tloc); CODE2 extern void updatetod(void); +CODE2 extern void inittod(void); /* provided by architecture or helpers */ CODE2 void device_init(void); /* provided by platform */ @@ -700,6 +701,8 @@ CODE2 uint8_t *swapout_prepare_uarea(ptptr p); CODE2 uint8_t *swapin_prepare_uarea(ptptr p); CODE2 void map_init(void); CODE2 void platform_idle(void); +CODE2 uint8_t rtc_secs(void); + /* Will need a uptr_t eventually */ extern uint16_t ramtop; /* Note: ramtop must be in common in some cases */ CODE2 extern void platform_interrupt(void); diff --git a/Kernel/timer.c b/Kernel/timer.c index 4a606f2c..88f07242 100644 --- a/Kernel/timer.c +++ b/Kernel/timer.c @@ -43,9 +43,6 @@ void wrtime(time_t *tloc) { irqflags_t irq = di(); memcpy(&tod, tloc, sizeof(tod)); -#ifdef CONFIG_RTC - machine_set_clock(tloc); -#endif irqrestore(irq); } @@ -61,4 +58,38 @@ void updatetod(void) if (!++tod.low) ++tod.high; } +#else + +static uint8_t rtcsec; + +/* + * We use the seconds counter on the RTC as a time counter and lock our + * time progression to it. This avoids doing horrible piles of math to + * use the RTC itself and avoids problems with non Y2K devices. + * + * We allow for multi-second leaps. On boxes with many of the directly + * interfaced floppy controllers we can reasonably expect to lose IRQ + * service for annoyingly long times. + */ +void updatetod(void) +{ + uint8_t rtcnew = rtc_secs(); /* platform function */ + int8_t slide; + + if (rtcnew == rtcsec) + return; + slide = rtcnew - rtcsec; /* Seconds elapsed */ + if (slide < 0) + slide += 60; /* Seconds wrapped */ + tod.low += slide; + if (tod.low < slide) /* 32bit wrap ? */ + tod.high++; + rtcsec = rtcnew; +} + +void inittod(void) +{ + rtcsec = rtc_secs(); +} + #endif /* NO_RTC */