## 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<<m->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,
};
.
|