## diffname bitsy/clock.c 2000/0902 ## diff -e /dev/null /n/emeliedump/2000/0902/sys/src/9/bitsy/clock.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "../port/error.h" typedef struct Clock0link Clock0link; typedef struct Clock0link { void (*clock)(void); Clock0link* link; } Clock0link; static Clock0link *clock0link; static Lock clock0lock; void addclock0link(void (*clock)(void)) { Clock0link *lp; if((lp = malloc(sizeof(Clock0link))) == 0){ print("addclock0link: too many links\n"); return; } ilock(&clock0lock); lp->clock = clock; lp->link = clock0link; clock0link = lp; iunlock(&clock0lock); } vlong fastticks(uvlong *hz) { USED(hz); return m->ticks; } void clockintr(Ureg*, void*) { } void delay(int ms) { USED(ms); } . ## diffname bitsy/clock.c 2000/0905 ## diff -e /n/emeliedump/2000/0902/sys/src/9/bitsy/clock.c /n/emeliedump/2000/0905/sys/src/9/bitsy/clock.c 52c ms *= 1000; while(ms-->0) ; . ## diffname bitsy/clock.c 2000/1006 ## diff -e /n/emeliedump/2000/0905/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1006/sys/src/9/bitsy/clock.c 52,54c ulong cnt, old; while(ms-- > 0){ cnt = ClockFreq/1000; while(cnt-- > 0){ old = timerregs->oscr; while(old == timerregs->oscr) ; } } . 46a /* reset previous interrupt */ timerregs->ossr |= 1<<0; /* post interrupt 1/HZ secs from now */ timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ; iprint("timer interrupt\n"); m->ticks++; if(m->ticks >= 100) exit(0); . 44c static void . 39,41c if(hz != nil) *hz = ClockFreq; return timerregs->oscr; . 35a /* enable interrupts on match register 0, turn off all others */ timerregs->oier = 1<<0; intrenable(IRQtimer0, clockintr, nil, "clock"); /* post interrupt 1/HZ secs from now */ timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ; } . 34a void clockinit(void) { /* map the clock registers */ timerregs = mapspecial(OSTIMERREGS, 32); . 9a typedef struct OSTimer { ulong osmr[4]; /* match registers */ ulong oscr; /* counter register */ ulong ossr; /* status register */ ulong ower; /* watchdog enable register */ ulong oier; /* timer interrupt enable register */ } OSTimer; static OSTimer *timerregs = (OSTimer*)OSTIMERREGS; enum { /* hardware counter frequency */ ClockFreq= 3686400, }; static void clockintr(Ureg*, void*); . ## diffname bitsy/clock.c 2000/1007 ## diff -e /n/emeliedump/2000/1006/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1007/sys/src/9/bitsy/clock.c 104d 97,102c start = timerregs->oscr; while(timerregs->oscr-start < ClockFreq/1000); . 94c ulong start; . 62a timerregs->oier = 1<<0; . 61c timerregs->ossr |= 1<<0; . 21,26d ## diffname bitsy/clock.c 2000/1008 ## diff -e /n/emeliedump/2000/1007/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1008/sys/src/9/bitsy/clock.c 82,83d 79d ## diffname bitsy/clock.c 2000/1015 ## diff -e /n/emeliedump/2000/1008/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1015/sys/src/9/bitsy/clock.c 80a if(m->proc) m->proc->pc = ureg->pc; accounttime(); if(kproftimer != nil) kproftimer(ureg->pc); checkalarms(); ilock(&clock0lock); for(lp = clock0link; lp; lp = lp->link) lp->clock(); iunlock(&clock0lock); if(up == 0 || up->state != Running) return; if(anyready()) sched(); if((ureg->psr & PsrMask) == PsrMusr) { (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1); segclock(ureg->pc); } . 73a Clock0link *lp; . 72c clockintr(Ureg *ureg, void*) . ## diffname bitsy/clock.c 2000/1019 ## diff -e /n/emeliedump/2000/1015/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1019/sys/src/9/bitsy/clock.c 114,116c if(clockinited){ while(ms-- > 0){ start = timerregs->oscr; while(timerregs->oscr-start < ClockFreq/1000); } } else { while(ms-- > 0){ for(i = 0; i < 1000; i++) ; } . 112a int i; . 60a clockinited = 1; . 19a static int clockinited; . ## diffname bitsy/clock.c 2000/1020 ## diff -e /n/emeliedump/2000/1019/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1020/sys/src/9/bitsy/clock.c 98a if(active.exiting && (active.machs & (1<machno))) exit(0); inclockintr = 0; . 89a if(inclockintr) return; /* interrupted ourself */ inclockintr = 1; . 77a static int inclockintr; . ## diffname bitsy/clock.c 2000/1101 ## diff -e /n/emeliedump/2000/1020/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1101/sys/src/9/bitsy/clock.c 98c (*kproftimer)(ureg->pc); . ## diffname bitsy/clock.c 2000/1107 ## diff -e /n/emeliedump/2000/1101/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1107/sys/src/9/bitsy/clock.c 86,119c portclock(); . 34,49d 19,32d 10,17d ## diffname bitsy/clock.c 2000/1110 ## diff -e /n/emeliedump/2000/1107/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1110/sys/src/9/bitsy/clock.c 68a void µdelay(int µs) { ulong start; int i; if(clockinited){ start = timerregs->oscr; while(timerregs->oscr - start < µs∗ClockFreq/1000000); } else { while(µs-- > 0){ for(i = 0; i < 10; i++) ; } } } . ## diffname bitsy/clock.c 2000/1111 ## diff -e /n/emeliedump/2000/1110/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1111/sys/src/9/bitsy/clock.c 78c while(timerregs->oscr - start < (µs*ClockFreq)/1000000) ; . 60c while(timerregs->oscr-start < ClockFreq/1000) ; . 48c portclock(ureg); . 39,41d 10a static OSTimer *timerregs = (OSTimer*)OSTIMERREGS; static int clockinited; static void clockintr(Ureg*, void*); . 9a typedef struct OSTimer { ulong osmr[4]; /* match registers */ ulong oscr; /* counter register */ ulong ossr; /* status register */ ulong ower; /* watchdog enable register */ ulong oier; /* timer interrupt enable register */ } OSTimer; . ## diffname bitsy/clock.c 2000/1121 ## diff -e /n/emeliedump/2000/1111/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1121/sys/src/9/bitsy/clock.c 33a /* figure out processor frequency */ x = powerregs->ppcr & 0x1f; conf.hz = ClockFreq*(x*4+16); conf.mhz = (conf.hz+499999)/1000000; print("%lud MHZ WeakARM\n", conf.mhz); . 26a ulong x; . ## diffname bitsy/clock.c 2000/1130 ## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1130/sys/src/9/bitsy/clock.c 66a drawactive(0); /* screen saver */ . ## diffname bitsy/clock.c 2000/1205 ## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1205/sys/src/9/bitsy/clock.c 34c intrenable(IRQ, IRQtimer0, clockintr, nil, "clock"); . ## diffname bitsy/clock.c 2000/1215 ## diff -e /n/emeliedump/2000/1205/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1215/sys/src/9/bitsy/clock.c 55c x = timerregs->oscr; if(x < last) high += 1LL<<32; last = x; return high+x; . 52a static vlong high; static ulong last; ulong x; . 49a /* turn 32 bit counter into a 64 bit one. since todfix calls * us at least once a second and we overflow once every 1165 * seconds, we won't miss an overflow. */ . ## diffname bitsy/clock.c 2001/0324 ## diff -e /n/emeliedump/2000/1215/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0324/sys/src/9/bitsy/clock.c 42c /* get processor type */ id = getcpuid(); print("%lud MHZ ARM, version %ux part %ux stepping %uxd\n", conf.mhz, (id>>16)&0xff, (id>>4)&0xfff, id&0xf); . 27a ulong id; . ## diffname bitsy/clock.c 2001/0327 ## diff -e /n/emeliedump/2001/0324/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0327/sys/src/9/bitsy/clock.c 46c print("%lud MHZ ARM, ver %lux/part %lux/step %lud\n", conf.mhz, . ## diffname bitsy/clock.c 2001/0421 ## diff -e /n/emeliedump/2001/0327/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0421/sys/src/9/bitsy/clock.c 116c while(timerregs->oscr - start < 1UL+(µs*ClockFreq)/1000000UL) . 113a µs++; . 109c µdelay(ulong µs) . ## diffname bitsy/clock.c 2001/0618 ## diff -e /n/emeliedump/2001/0421/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0618/sys/src/9/bitsy/clock.c 22a void clockpower(int on) { if (on){ timerregs->ossr |= 1<<0; timerregs->oier = 1<<0; timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ; } } . 19c OSTimer *timerregs = (OSTimer*)OSTIMERREGS; . ## diffname bitsy/clock.c 2001/0622 ## diff -e /n/emeliedump/2001/0618/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0622/sys/src/9/bitsy/clock.c 32a clockinited = on; . ## diffname bitsy/clock.c 2001/0813 ## diff -e /n/emeliedump/2001/0622/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0813/sys/src/9/bitsy/clock.c 15c ulong ower; /* watchdog enable register */ . ## diffname bitsy/clock.c 2001/0905 ## diff -e /n/emeliedump/2001/0813/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0905/sys/src/9/bitsy/clock.c 137a ulong TK2MS(ulong ticks) { uvlong t, hz; t = ticks; hz = HZ; t *= 1000L; t = t/hz; ticks = t; return ticks; } . ## diffname bitsy/clock.c 2002/0405 ## diff -e /n/emeliedump/2001/0905/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0405/sys/src/9/bitsy/clock.c 93,97c timerset(timerintr(ureg, nil)); . 89a . 86a void timerset(vlong v) { ulong when; /* Must be unsigned! */ if (v == 0LL) when = timerregs->oscr + Minfreq; else { when = v; /* post next interrupt: calculate # of tics from now */ when = when - timerregs->oscr - Maxfreq; if (when - timerregs->oscr > Minfreq) when = timerregs->oscr + Maxfreq; } timerregs->osmr[0] = when; } . 63a timersinit(); . 23a enum { Minfreq = ClockFreq/HZ, /* At least one interrupt per HZ (10 ms) */ Maxfreq = ClockFreq/10000, /* At most one interrupt every 100 µs */ }; . ## diffname bitsy/clock.c 2002/0406 ## diff -e /n/emeliedump/2002/0405/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0406/sys/src/9/bitsy/clock.c 120a if ((count++ % 100) == 0) iprint("%lud ", timerregs->osmr[0] - timerregs->oscr); . 115a static ulong count; . 108a } . 106,107c tics = when - timerregs->oscr - Maxfreq; if (tics > Minfreq){ iprint("%lud %lud %lud %d\n", when, tics, timerregs->oscr, Minfreq); . 98c ulong when, tics; /* Must be unsigned! */ static int count; . 96c timerset(uvlong v) . 82c static uvlong high; . 26c Minfreq = ClockFreq/HZ, /* At least one interrupt per HZ (50 ms) */ . 12,16c ulong osmr[4]; /* match registers */ volatile ulong oscr; /* counter register */ ulong ossr; /* status register */ ulong ower; /* watchdog enable register */ ulong oier; /* timer interrupt enable register */ . ## diffname bitsy/clock.c 2002/0408 ## diff -e /n/emeliedump/2002/0406/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0408/sys/src/9/bitsy/clock.c 124,126c timerintr(ureg, when); . 122a when += Minfreq; timerregs->osmr[0] = when; /* insurance */ . 119,120d 113c timerregs->osmr[0] = next; . 106,111c /* post next interrupt: calculate # of tics from now */ tics = next - timerregs->oscr - Maxfreq; if (tics > Minfreq){ iprint("%lud %lud %lud %d\n", next, tics, timerregs->oscr, Minfreq); next = timerregs->oscr + Maxfreq; . 101,104c next = v; . 98c ulong next, tics; /* Must be unsigned! */ . 68c when = timerregs->oscr + Minfreq; timerregs->osmr[0] = when; . 37c timerregs->osmr[0] = timerregs->oscr + Minfreq; . 22a static uvlong when; /* scheduled time of next interrupt */ . ## diffname bitsy/clock.c 2002/0410 ## diff -e /n/emeliedump/2002/0408/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0410/sys/src/9/bitsy/clock.c 81c uvlong . ## diffname bitsy/clock.c 2002/0411 ## diff -e /n/emeliedump/2002/0410/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0411/sys/src/9/bitsy/clock.c 108c timeradjust++; . 24a long timeradjust; . 22,23c static void clockintr(Ureg*, void*); static uvlong when; /* scheduled time of next interrupt */ . ## diffname bitsy/clock.c 2002/0606 ## diff -e /n/emeliedump/2002/0411/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0606/sys/src/9/bitsy/clock.c 148c microdelay(int µs) . ## diffname bitsy/clock.c 2002/0710 ## diff -e /n/emeliedump/2002/0606/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0710/sys/src/9/bitsy/clock.c 165,177d ## diffname bitsy/clock.c 2002/0822 ## diff -e /n/emeliedump/2002/0710/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0822/sys/src/9/bitsy/clock.c 164a /* * performance measurement ticks. must be low overhead. * doesn't have to count over a second. */ ulong perfticks(void) { return timerregs->oscr; } . ## diffname bitsy/clock.c 2002/1112 ## diff -e /n/emeliedump/2002/0822/sys/src/9/bitsy/clock.c /n/emeliedump/2002/1112/sys/src/9/bitsy/clock.c 124a } void rtcalarm(ulong secs) { vlong t; if (t == 0){ iprint("RTC alarm cancelled\n"); rtcregs->rtsr &= ~RTSR_ale; rtcregs->rtar = 0xffffffff; } else { t = todget(nil); t = t / 1000000000ULL; // nsec to secs if (secs < t) return; secs -= t; iprint("RTC alarm set to %uld seconds from now\n", secs); rtcregs->rtar = rtcregs->rcnr + secs; rtcregs->rtsr|= RTSR_ale; } } static void rtcintr(Ureg*, void*) { /* reset interrupt */ rtcregs->rtsr&= ~RTSR_ale; rtcregs->rtsr&= ~RTSR_al; rtcregs->rtar = 0; iprint("RTC alarm: %lud\n", rtcregs->rcnr); . 73a /* enable RTC interrupts and alarms */ intrenable(IRQ, IRQrtc, rtcintr, nil, "rtc"); rtcregs->rttr = 0x8000; // make rcnr 1Hz rtcregs->rcnr = 0; // reset counter rtcregs->rtsr |= RTSR_al; rtcregs->rtsr |= RTSR_ale; . 52c timerregs = mapspecial(OSTIMERREGS, sizeof(OSTimer)); rtcregs = mapspecial(RTCREGS, sizeof(RTCregs)); . 42a return 0L; . 41c if (rtcregs->rttr == 0){ rtcregs->rttr = 0x8000; // nominal frequency. rtcregs->rcnr = 0; rtcregs->rtar = 0xffffffff; rtcregs->rtsr |= RTSR_ale; rtcregs->rtsr |= RTSR_hze; } if (rtcregs->rcnr > savedtime) return rtcregs->rcnr - savedtime; } else savedtime = rtcregs->rcnr; . 35a static ulong savedtime; . 33c ulong . 22c static void clockintr(Ureg*, void*); static void rtcintr(Ureg*, void*); . 19a RTCregs *rtcregs = (RTCregs*)RTCREGS; . 18a typedef struct RTCregs { ulong rtar; /* alarm */ ulong rcnr; /* count */ ulong rttr; /* trim */ ulong dummy; /* hole */ ulong rtsr; /* status */ } RTCregs; . 9a enum { RTCREGS = 0x90010000, /* real time clock registers */ RTSR_al = 0x01, /* alarm detected */ RTSR_hz = 0x02, /* 1Hz tick */ RTSR_ale= 0x04, /* alarm interrupt enable */ RTSR_hze= 0x08, /* 1Hz tick enable */ Never = 0xffffffff, }; .