We are starting new season of the labs. Season 2 will be named as “Close to hardware”. And we start from important point to have clocks and timers working. But first we made a decision to make our codes close to 9pi source codes, especially assembler parts. But we found it little complicated as UReg struct on Plan 9 have r14 and link as union while Inferno has them separate. We can not change Ureg in arm/include as we would break another ports. Instead we created os/rpi/include and copied modified ureg.h there.
As it was done, we can make our codes for exceptions very similar (lamost same) as used in 9pi.
To add clocks and timers we would modify rpi and mkfile to add ready module from ports – tod. And add clock.c file:
1#include "../port/portclock.c"
2
3#define SYSTIMERS (IOBASE+0x3000)
4#define ARMTIMER (IOBASE+0xB400)
5
6enum {
7 SystimerFreq = 1*Mhz,
8 MaxPeriod = SystimerFreq/HZ,
9 MinPeriod = SystimerFreq/(100*HZ)
10};
11
12typedef struct Systimers Systimers;
13typedef struct Armtimer Armtimer;
14
15struct Systimers {
16 u32int cs;
17 u32int clo;
18 u32int chi;
19 u32int c0;
20 u32int c1;
21 u32int c2;
22 u32int c3;
23};
24
25struct Armtimer {
26 u32int load;
27 u32int val;
28 u32int ctl;
29 u32int irqack;
30 u32int irq;
31 u32int maskedirq;
32 u32int reload;
33 u32int predivider;
34 u32int count;
35};
36
37enum {
38 CntPrescaleShift = 16, /* freq is sys_clk/(prescale+1) */
39 CntPrescaleMask = 0xFF,
40 CntEnable = 1<<9,
41 TmrDbgHalt = 1<<8,
42 TmrEnable = 1<<7,
43 TmrIntEnable = 1<<5,
44 TmrPrescale1 = 0x00<<2,
45 TmrPrescale16 = 0x01<<2,
46 TmrPrescale256 = 0x02<<2,
47 CntWidth16 = 0<<1,
48 CntWidth32 = 1<<1
49};
50
51static void
52clockintr(Ureg * ureg, void *)
53{
54 Systimers *tn;
55
56 tn = (Systimers*)SYSTIMERS;
57 /* dismiss interrupt */
58 tn->cs = 1<<3;
59 timerintr(ureg, 0);
60}
61
62void
63clockinit(void)
64{
65 Systimers *tn;
66 Armtimer *tm;
67 u32int t0, t1;
68 u32int tstart, tend;
69
70 tn = (Systimers*)SYSTIMERS;
71 tm = (Armtimer*)ARMTIMER;
72 tm->load = 0;
73 tm->ctl = TmrPrescale1|CntEnable|CntWidth32;
74
75 tstart = tn->clo;
76 do{
77 t0 = lcycles();
78 }while(tn->clo == tstart);
79 tend = tstart + 10000; /* 10 msecs */
80 do{
81 t1 = lcycles();
82 }while(tn->clo != tend);
83 t1 -= t0;
84 m->cpuhz = 100 * t1;
85
86 tn->c3 = tn->clo - 1;
87 irqenable(IRQtimer3, clockintr, nil);
88}
89
90void
91clockcheck(void) { return; }
92
93uvlong
94fastticks(uvlong *hz)
95{
96 Systimers *tn;
97 ulong lo, hi;
98
99 tn = (Systimers*)SYSTIMERS;
100 if(hz)
101 *hz = SystimerFreq;
102 do{
103 hi = tn->chi;
104 lo = tn->clo;
105 }while(tn->chi != hi);
106 m->fastclock = (uvlong)hi<<32 | lo;
107 return m->fastclock;
108}
109
110void
111timerset(uvlong next)
112{
113 Systimers *tn;
114 vlong now, period;
115
116 tn = (Systimers*)SYSTIMERS;
117 now = fastticks(nil);
118 period = next - fastticks(nil);
119 if(period < MinPeriod)
120 next = now + MinPeriod;
121 else if(period > MaxPeriod)
122 next = now + MaxPeriod;
123 tn->c3 = (ulong)next;
124}
Also there are another minor changes to dat.h, etc.
FILES: