annotate src/device/timer.c @ 52:1adde248a61f default tip

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