This repository has been archived by the owner on Aug 12, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimer.s
134 lines (102 loc) · 2.88 KB
/
timer.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
.data
_tick_str:
.asciz "Tick %d\n"
tick:
.long 0
.text
.equ CLINT, 0x2000000
.equ CLINT_MTIME, CLINT + 0xBFF8
.equ CLINT_MTIMECMP, CLINT + 0x4000
# 10000000 ticks per second
.equ CLINT_TIME_BASE_FREQ, 10000000
# void timer_load(int delta);
.func timer_load
.globl timer_load
timer_load:
# set value in mtimercmp register
# get current time
li t0, CLINT_MTIME # t0 is address of mtime (lower bits)
lw s0, 0(t0) # value of current time (lower bits)
li t0, CLINT_MTIME
lw s1, 4(t0) # value of current time (higher bits)
# get value to store at mtimecmp
# value is mtime + delta
mv t0, s0
add s0, s0, a0 # value should be set to mtimecmp
sltu t1, s0, t0
add s1, s1, t1
# save value to the stack
addi sp, sp, -4
sw ra, 0(sp)
# get mhartid
call read_mhartid # hartid saved at a0
# find address of mtimecmp
slli a0, a0, 3 # hartid * 8
li t0, CLINT_MTIMECMP
add a0, a0, t0
sw s0, 0(a0)
sw s1, 4(a0)
lw ra, 0(sp)
addi sp, sp, 4
ret
.endfunc
.equ MIE_MTIE, 1 << 7
.func timer_init
.globl timer_init
# void timer_init(void);
timer_init:
addi sp, sp, -4
sw ra, 0(sp)
# set time interval
li a0, CLINT_TIME_BASE_FREQ
call timer_load
# enable machine mode timer interrupts
call read_mie
li t0, MIE_MTIE
or a0, a0, t0
call write_mie
lw ra, 0(sp)
add sp, sp, 4
ret
.endfunc
.equ INTERVAL, CLINT_TIME_BASE_FREQ
.func timer_interrupt_handler
.globl timer_interrupt_handler
# void timer_interrupt_handler(void);
timer_interrupt_handler:
addi sp, sp, -12
sw ra, 0(sp)
sw s0, 4(sp)
sw s1, 8(sp)
la t0, tick
lw t1, 0(t0)
addi t1, t1, 1
sw t1, 0(t0)
# la a0, _tick_str
# mv a1, t1
# call kprintf
li a0, INTERVAL
call timer_load
lw ra, 0(sp)
lw s0, 4(sp)
lw s1, 8(sp)
addi sp, sp, 12
call task_scheduler
ret
.endfunc
.func ksleep_millisec
.globl ksleep_millisec
# void ksleep_millisec(unsigned int t);
ksleep_millisec:
rdtime t0 # time starts to sleep
.L0:
nop
nop
rdtime t1 # current time in loop
sub t1, t1, t0 # t1 = t1 - t0
bgeu t1, a0, .L1 # if t1 >= a0, return
j .L0
.L1:
ret
.endfunc
.end