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.
 
 
 

114 lines
2.7 KiB

#
# interrupts.s: basic irq handling setup
#
# 2021 flabbergast@drak.xyz
# Unlicense: https://unlicense.org/
#
# ! when you edit the irq handler, don't forget to push/pop
# any extra registers that you use !
# - we don't use the vectored interrupt handling, so
# there is a single function that's executed on any
# interrupt or exception (which needs to make decisions
# based on mcause)
# - the address of this fn should be loaded into mtvec
#
# (SiFive FE310 only has 3 interrupt sources (sw, timer, plic),
# so any vector table would only have 3 "used" entries.)
#
.include "platform_regs.inc"
# irq handler needs to be always 4-aligned
.balign 4, 0
irq_handler:
addi sp, sp, 9*(-4)
sw ra, 8*4(sp) # x1
sw s1, 7*4(sp) # x9
sw t6, 6*4(sp) # x31
sw t5, 5*4(sp) # x30
sw t4, 4*4(sp) # x29
sw t3, 3*4(sp) # x28
sw t2, 2*4(sp) # x7
sw t1, 1*4(sp) # x6
sw t0, 0*4(sp) # x5
# check if it's an interrupt or an exception
csrr t0, mcause
blt t0, zero, .interrupts
## exceptions
.exceptions:
# read CSR and stall
csrr t1, mepc # tells us where it occured
# t0 still contains mcause
jal zero, .exceptions
## interrupts
.interrupts:
andi t0, t0, 0xF # FE310 only has irqs 3,7,11
srli t0, t0, 2
bne t0, zero, 1f
## 3, software interrupt
jal zero, irq_handler_exit
1:
srli t0, t0, 1
bne t0, zero, 1f
## 7, timer interrupt
# 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)
jal zero, irq_handler_exit
1:
## 11, external interrupt
# # use PLIC claim/complete mechanism
# li t0, PLIC_BASE+PLIC_CLAIM-4 # easier load
# lw s1, 4(t0) # claim: highest pending irq id
#
# # UART0
# li t1, 3 # UART0 is source 3
# bne t1, s1, 1f # if not UART0, skip
# jal ra, irq_handler_uart0
#
# 1:
# # any other PLIC sources should go here
#
# li t0, PLIC_BASE+PLIC_CLAIM-4
# sw s1, 4(t0) # complete the claimed irq
# exit
irq_handler_exit:
lw t0, 0*4(sp) # x5
lw t1, 1*4(sp) # x6
lw t2, 2*4(sp) # x7
lw t3, 3*4(sp) # x28
lw t4, 4*4(sp) # x29
lw t5, 5*4(sp) # x30
lw t6, 6*4(sp) # x31
lw s1, 7*4(sp) # x9
lw ra, 8*4(sp) # x1
addi sp, sp, 9*4
mret
# enable enternal interrupts (PLIC)
plic_init:
li t0, PLIC_BASE+PLIC_THRESHOLD
sw zero, 0(t0) # set PLIC threshold 0 (all irqs unmasked)
li t0, PLIC_BASE+PLIC_ENABLE1
sw zero, 0(t0) # disable all PLIC irq sources
sw zero, 4(t0) # (a lot seem enabled after reset?)
li t0, 1<<11
csrs mie, t0 # set MEIE(bit11)
ret