Assembly examples for Red-V Thing Plus (SiFive FE310-G002)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

92 lines
3.0 KiB

#
# p_delay.s: functions for waiting
#
# 2021 flabbergast@drak.xyz
# Unlicense: https://unlicense.org/
#
.if compressed_isa
.balign 2, 0
.else
.balign 4, 0
.endif
.include "platform_regs.inc"
.equ MTIME_FREQUENCY, 33 # 32_768 Hz clock
# enable timer interrupt and put a 'safe' value into MTIMECMP
delay_init:
# clear the interrupt by writing a high value to CLINT_MTIMECMP.h
li t0, CLINT_BASE+CLINT_MTIMECMP
li t1, 0xFFFFF000
sw t1, 4(t0)
li t0, 1<<7
csrs mie, t0 # set MTIE bit
ret
# a0: delay value in milliseconds
# (should be less than 0xFFFF_FFFF/33/4)
# this version uses interrupts if enabled,
# i.e. it waits with wfi, rather than a busy loop
delay:
li t0, CLINT_BASE+CLINT_MTIME+8 # load addresses
li t4, CLINT_BASE+CLINT_MTIMECMP
lw t1, -8(t0) # load the current value of the timer.l
lw t3, -4(t0) # load current timer.h
li t2, MTIME_FREQUENCY # let our clock frequency
mul t2, t2, a0 # multiply milliseconds with frequency
add t2, t1, t2 # target mtime is now in t2
bgeu t2, t1, 4f # _not_ overflown back to zero?
# if overflown, we assume that (signed)t1<0 and t2>0
addi t3, t3, 1 # overflown => increase target time.h by one
4:
sw t2, 0(t4) # set MTIMECMP.l (assuming .h is still very big)
sw t3, 4(t4) # set MTIMECMP.h
sltu t3, t1, t2 # keep the "overflown" flag in t3
1: # main waiting loop
csrr t1, mstatus # check if interrupts are enabled
andi t1, t1, 8
beqz t1, 3f
wfi # if they are, wait for one
3:
lw t1, -8(t0) # read mtime value again
bnez t3, 2f # check overflow
bltu t1, t2, 1b # no overflow: unsigned comparison
2:
blt t1, t2, 1b # overflow: (signed)t1 can be <0
li t1, 0xFFFFF000 # clear timer interrupt
sw t1, 4(t4) # ... by writing big into MTIMECMP.h
ret
# a0: delay value in milliseconds
# (should be less than 0xFFFF_FFFF/33/4)
# delay:
# li t0, CLINT_BASE+CLINT_MTIME+8 # load the timer registers base
# lw t1, -8(t0) # load the current value of the timer (lsw)
#
# li t2, MTIME_FREQUENCY # let our clock frequency
# mul t2, t2, a0 # multiply milliseconds with frequency
# add t2, t1, t2 # target mtime is now in t2
# bltu t2, t1, 2f # overflown back to zero?
# # if yes, assume that (signed)t1<0 and t2>0
#
# 1:
# lw t1, -8(t0) # read mtime value again
# bltu t1, t2, 1b # keep looping until timout
# ret
#
# 2: # overflown branch
# lw t1, -8(t0) # read mtime; t1 can be "<0"
# blt t1, t2, 2b # do signed compare
# ret
# a0: (delay in cycles)/2
busy_delay_cycles:
1:
addi a0, a0, -1
bnez a0, 1b
ret