Mercurial > hg > Members > menikon > CbC_xv6
comparison src/device/timer.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:83c23a36980d |
---|---|
1 // ARM dual-timer module support (SP804) | |
2 #include "types.h" | |
3 #include "param.h" | |
4 #include "arm.h" | |
5 #include "mmu.h" | |
6 #include "defs.h" | |
7 #include "memlayout.h" | |
8 #include "spinlock.h" | |
9 | |
10 // A SP804 has two timers, we only use the first one, and as perodic timer | |
11 | |
12 // define registers (in units of 4-bytes) | |
13 #define TIMER_LOAD 0 // load register, for perodic timer | |
14 #define TIMER_CURVAL 1 // current value of the counter | |
15 #define TIMER_CONTROL 2 // control register | |
16 #define TIMER_INTCLR 3 // clear (ack) the interrupt (any write clear it) | |
17 #define TIMER_MIS 5 // masked interrupt status | |
18 | |
19 // control register bit definitions | |
20 #define TIMER_ONESHOT 0x01 // wrap or one shot | |
21 #define TIMER_32BIT 0x02 // 16-bit/32-bit counter | |
22 #define TIMER_INTEN 0x20 // enable/disable interrupt | |
23 #define TIMER_PERIODIC 0x40 // enable periodic mode | |
24 #define TIMER_EN 0x80 // enable the timer | |
25 | |
26 void isr_timer (struct trapframe *tp, int irq_idx); | |
27 | |
28 struct spinlock tickslock; | |
29 uint ticks; | |
30 | |
31 // acknowledge the timer, write any value to TIMER_INTCLR should do | |
32 static void ack_timer () | |
33 { | |
34 volatile uint * timer0 = P2V(TIMER0); | |
35 timer0[TIMER_INTCLR] = 1; | |
36 } | |
37 | |
38 // initialize the timer: perodical and interrupt based | |
39 void timer_init(int hz) | |
40 { | |
41 volatile uint * timer0 = P2V(TIMER0); | |
42 | |
43 initlock(&tickslock, "time"); | |
44 | |
45 timer0[TIMER_LOAD] = CLK_HZ / hz; | |
46 timer0[TIMER_CONTROL] = TIMER_EN|TIMER_PERIODIC|TIMER_32BIT|TIMER_INTEN; | |
47 | |
48 pic_enable (PIC_TIMER01, isr_timer); | |
49 } | |
50 | |
51 // interrupt service routine for the timer | |
52 void isr_timer (struct trapframe *tp, int irq_idx) | |
53 { | |
54 acquire(&tickslock); | |
55 ticks++; | |
56 wakeup(&ticks); | |
57 release(&tickslock); | |
58 ack_timer(); | |
59 } | |
60 | |
61 // a short delay, use timer 1 as the source | |
62 void micro_delay (int us) | |
63 { | |
64 volatile uint * timer1 = P2V(TIMER1); | |
65 | |
66 // load the initial value to timer1, and configure it to be freerun | |
67 timer1[TIMER_CONTROL] = TIMER_EN | TIMER_32BIT; | |
68 timer1[TIMER_LOAD] = us; | |
69 | |
70 // the register will wrap to 0xFFFFFFFF after decrement to 0 | |
71 while ((int)timer1[TIMER_CURVAL] > 0) { | |
72 | |
73 } | |
74 | |
75 // disable timer | |
76 timer1[TIMER_CONTROL] = 0; | |
77 } |