mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
added more comprehensive vectoring, interrupt causing and handing
This commit is contained in:
parent
1af47c9d25
commit
1a9c312700
@ -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\():
|
||||
|
Loading…
Reference in New Issue
Block a user