added more comprehensive vectoring, interrupt causing and handing

This commit is contained in:
Kip Macsai-Goren 2022-04-17 20:56:15 +00:00
parent 1af47c9d25
commit 1a9c312700

View File

@ -84,7 +84,7 @@ cause_instr_access:
ret
cause_illegal_instr:
.word 0x00000000 // a 32 bit zros is an illegal instruction
.word 0x00000000 // 32 bit zero is an illegal instruction
ret
cause_breakpnt:
@ -118,7 +118,7 @@ cause_ecall:
ecall
ret
cause_time_interrupt:
cause_m_time_interrupt:
// The following code works for both RV32 and RV64.
// RV64 alone would be easier using double-word adds and stores
li x28, 0x30 // Desired offset from the present time
@ -132,23 +132,99 @@ cause_time_interrupt:
sw x31,4(x29) // store into most significant word of MTIMECMP
nowrap:
sw x28, 0(x29) // store into least significant word of MTIMECMP
loop:
wfi
j loop // wait until interrupt occurs
time_loop:
wfi
j time_loop // wait until interrupt occurs
ret
cause_soft_interrupt:
cause_s_time_interrupt:
li x28, 0x20
csrs mip, x28 // set supervisor time interrupt pending. SIP is a subset of MIP, so writing this should also change MIP.
nop // added extra nops in so the csrs can get through the pipeline before returning.
ret
cause_m_soft_interrupt:
la x28, 0x02000000 // MSIP register in CLINT
li x29, 1 // 1 in the lsb
sw x29, 0(x28) // Write MSIP bit
ret
cause_ext_interrupt:
cause_s_soft_interrupt:
li x28, 0x2
csrs sip, x28 // set supervisor software interrupt pending. SIP is a subset of MIP, so writing this should also change MIP.
ret
cause_m_ext_interrupt:
# ========== Configure PLIC ==========
# m priority threshold = 0
li t0, 0xC200000
li t1, 0
sw t1, 0(t0)
# source 3 (GPIO) priority = 1
li t0, 0xC000000
li t1, 1
sw t1, 0x0C(t0)
# enable source 3
li t0, 0x0C002000
li t1, 0b1000
sw t1, 0(t0)
li x28, 0x10060000 // load base GPIO memory location
li x29, 0x1
sw x29, 8(x28) // enable the first pin as an output
sw x29, 28(x28) // set first pin to high interrupt enable
sw x29, 40(x28) // write a 1 to the first output pin (cause interrupt)
sw x29, 0x08(x28) // enable the first pin as an output
sw x0, 0x1C(x28) // clear rise_ip
sw x0, 0x24(x28) // clear fall_ip
sw x0, 0x2C(x28) // clear high_ip
sw x0, 0x34(x28) // clear low_ip
sw x29, 0x28(x28) // set first to interrupt on a rising value
sw x29, 0x0C(x28) // write a 1 to the first output pin (cause interrupt)
m_ext_loop:
wfi
lw x29, 0x8(x28)
bnez x28, m_ext_loop // go through this loop until the trap handler has disabled the GPIO output pins.
ret
cause_s_ext_interrupt_GPIO:
# ========== Configure PLIC ==========
# s priority threshold = 0
li t0, 0xC201000
li t1, 0
sw t1, 0(t0)
# m priority threshold = 7
li t0, 0xC200000
li t1, 7
sw t1, 0(t0)
# source 3 (GPIO) priority = 1
li t0, 0xC000000
li t1, 1
sw t1, 0x0C(t0)
# enable source 3
li t0, 0x0C002000
li t1, 0b1000
sw t1, 0(t0)
li x28, 0x10060000 // load base GPIO memory location
li x29, 0x1
sw x29, 0x08(x28) // enable the first pin as an output
sw x0, 0x1C(x28) // clear rise_ip
sw x0, 0x24(x28) // clear fall_ip
sw x0, 0x2C(x28) // clear high_ip
sw x0, 0x34(x28) // clear low_ip
sw x29, 0x28(x28) // set first to interrupt on a rising value
sw x29, 0x0C(x28) // write a 1 to the first output pin (cause interrupt)
s_ext_loop:
wfi
lw x29, 0x8(x28)
bnez x28, s_ext_loop // go through this loop until the trap handler has disabled the GPIO output pins.
ret
cause_s_ext_interrupt_IP:
li x28, 0x200
csrs mip, x28 // set supervisor external interrupt pending. SIP is a subset of MIP, so writing this should also change MIP.
ret
end_trap_triggers:
@ -216,7 +292,7 @@ end_trap_triggers:
//
// --------------------------------------------------------------------------------------------
.align 2
.align 3
trap_handler_\MODE\():
j trap_unvectored_\MODE\() // for the unvectored implimentation: jump past this table of addresses into the actual handler
// *** ASSUMES that a cause value of 0 for an interrupt is unimplemented
@ -273,18 +349,19 @@ trap_stack_saved_\MODE\(): // jump here after handling vectored interupt since w
// Respond to trap based on cause
// All interrupts should return after being logged
csrr x1, \MODE\()cause
slli x1, x1, 3 // multiply cause by 8 to get offset in vector Table
li x5, 0x8000000000000000 // if msb is set, it is an interrupt
and x5, x5, x1
bnez x5, interrupt_handler_\MODE\() // return from interrupt
// Other trap handling is specified in the vector Table
la x5, exception_vector_table_\MODE\()
slli x1, x1, 3 // multiply cause by 8 to get offset in vector Table
add x5, x5, x1 // compute address of vector in Table
ld x5, 0(x5) // fectch address of handler from vector Table
jr x5 // and jump to the handler
interrupt_handler_\MODE\():
la x5, interrupt_vector_table_\MODE\() // NOTE THIS IS NOT THE SAME AS VECTORED INTERRUPTS!!!
slli x1, x1, 3 // multiply cause by 8 to get offset in vector Table
add x5, x5, x1 // compute address of vector in Table
ld x5, 0(x5) // fectch address of handler from vector Table
jr x5 // and jump to the handler
@ -343,6 +420,7 @@ trapreturn_finished_\MODE\():
ld x7, -24(sp) // restore registers from stack before returning
ld x5, -16(sp)
ld x1, -8(sp)
csrrw sp, \MODE\()scratch, sp // switch sp and scratch stack back to restore the non-trap stack pointer
\MODE\()ret // return from trap
ecallhandler_\MODE\():
@ -364,7 +442,7 @@ ecallhandler_changetomachinemode_\MODE\():
ecallhandler_changetosupervisormode_\MODE\():
// Force status.MPP (bits 12:11) to 01 to enter supervisor mode after mret
li x1, 0b1100000000000
li x1, 0b1000000000000
csrc \MODE\()status, x1
li x1, 0b0100000000000
csrs \MODE\()status, x1
@ -440,22 +518,42 @@ vectored_int_end_\MODE\():
j trap_stack_saved_\MODE\()
soft_interrupt_\MODE\():
la x28, 0x02000000 // Reset by clearing MSIP interrupt from CLINT
sw x0, 0(x28)
j trapreturn_\MODE\()
la x5, 0x02000000 // Reset by clearing MSIP interrupt from CLINT
sw x0, 0(x5)
csrci sip, 0x2 // clear supervisor software interrupt pending bit
ld x1, -8(sp) // load return address from stack into ra (the address to return to after causing this interrupt)
// Note: we do this because the mepc loads in the address of the instruction after the sw that causes the interrupt
// This means that this trap handler will return to the next address after that one, which might be unpredictable behavior.
j trapreturn_finished_\MODE\() // return to the code at ra value from before trap
time_interrupt_\MODE\():
la x29, 0x02004000 // MTIMECMP register in CLINT
li x30, 0xFFFFFFFF
sd x30, 0(x29) // reset interrupt by setting mtimecmp to 0xFFFFFFFF
la x5, 0x02004000 // MTIMECMP register in CLINT
li x7, 0xFFFFFFFF
sd x7, 0(x5) // reset interrupt by setting mtimecmp to 0xFFFFFFFF
ld x1, -8(sp) // load return address from stack into ra (the address AFTER the jal to the faulting address)
ld x1, -8(sp) // load return address from stack into ra (the address to return to after the loop is complete)
j trapreturn_finished_\MODE\() // return to the code at ra value from before trap
ext_interrupt_\MODE\():
li x28, 0x10060000 // reset interrupt by clearing all the GPIO bits
sw x0, 8(x28) // disable the first pin as an output
sw x0, 40(x28) // write a 0 to the first output pin (reset interrupt)
# reset PLIC to turn off external interrupts
# priority threshold = 7
li t0, 0xC200000
li t1, 0x7
sw t1, 0(t0)
# source 3 (GPIO) priority = 0
li t0, 0xC000000
li t1, 0
sw t1, 0x0C(t0)
# disable source 3
li t0, 0x0C002000
li t1, 0b0000
sw t1, 0(t0)
j trapreturn_\MODE\()
// Table of trap behavior
@ -485,17 +583,17 @@ exception_vector_table_\MODE\():
.align 3 // aligns this data table to an 8 byte boundary
interrupt_vector_table_\MODE\():
.8byte segfault_\MODE\() // 0: reserved
.8byte s_soft_vector_\MODE\() // 1: instruction access fault // the zero spot is taken up by the instruction to skip this table.
.8byte soft_interrupt_\MODE\() // 1: instruction access fault // the zero spot is taken up by the instruction to skip this table.
.8byte segfault_\MODE\() // 2: reserved
.8byte m_soft_vector_\MODE\() // 3: breakpoint
.8byte soft_interrupt_\MODE\() // 3: breakpoint
.8byte segfault_\MODE\() // 4: reserved
.8byte s_time_vector_\MODE\() // 5: load access fault
.8byte time_interrupt_\MODE\() // 5: load access fault
.8byte segfault_\MODE\() // 6: reserved
.8byte m_time_vector_\MODE\() // 7: store access fault
.8byte time_interrupt_\MODE\() // 7: store access fault
.8byte segfault_\MODE\() // 8: reserved
.8byte s_ext_vector_\MODE\() // 9: ecall from S-mode
.8byte ext_interrupt_\MODE\() // 9: ecall from S-mode
.8byte segfault_\MODE\() // 10: reserved
.8byte m_ext_vector_\MODE\() // 11: ecall from M-mode
.8byte ext_interrupt_\MODE\() // 11: ecall from M-mode
.align 3
trap_return_pagetype_table_\MODE\():