Skip to content

Instantly share code, notes, and snippets.

@Wren6991
Created December 4, 2021 00:52
Show Gist options
  • Save Wren6991/158db32537f643d315afe14820231d29 to your computer and use it in GitHub Desktop.
Save Wren6991/158db32537f643d315afe14820231d29 to your computer and use it in GitHub Desktop.
// Custom CSRs
#define meie0 0xbe0 // External interrupt enable
#define meip0 0xfe0 // External interrupt pending
#define mlei 0xfe4 // Lowest external interrupt, left shifted by 2.
_external_irq_vector:
// Begin critical section
addi sp, sp, -16
sw a0, 0(sp)
sw a1, 4(sp)
// Save exception return state. No need to save mstatus because we know we
// got here from M mode, and we know interrupts were enabled at the point
// the interrupt fired.
csrr a0, mepc
sw a0, 8(sp)
csrr a0, meie0
sw a0, 12(sp)
// Disable this and lower-priority interrupts. mlei returns the index of
// the lowest-numbered pending & enabled external IRQ, left-shifted by 2.
csrr a0, mlei
la a1, irq_primask_table
add a1, a1, a0
lw a1, (a1)
csrw meie0, a1
// End of critical section. Enable preemption.
csrsi mstatus, 0x8
// Save caller saves. ISR may be an undecorated function.
addi sp, sp, -64
sw ra, 0 (sp)
sw t0, 4 (sp)
sw t1, 8 (sp)
sw t2, 12(sp)
sw a2, 16(sp)
sw a3, 20(sp)
sw a4, 24(sp)
sw a5, 28(sp)
sw a6, 32(sp)
sw a7, 36(sp)
sw t3, 40(sp)
sw t4, 44(sp)
sw t5, 48(sp)
sw t6, 52(sp)
// Let's go!
la a1, irq_vector_table
add a1, a1, a0
jalr a1
// Restore caller saves
lw ra, 0 (sp)
lw t0, 4 (sp)
lw t1, 8 (sp)
lw t2, 12(sp)
lw a2, 16(sp)
lw a3, 20(sp)
lw a4, 24(sp)
lw a5, 28(sp)
lw a6, 32(sp)
lw a7, 36(sp)
lw t3, 40(sp)
lw t4, 44(sp)
lw t5, 48(sp)
lw t6, 52(sp)
addi sp, sp, 64
// Begin critical section
csrci mstatus, 0x8
lw a0, 8(sp)
csrw mepc, a0
lw a0, 12(sp)
csrw meie0, a0
lw a0, 0(sp)
lw a1, 4(sp)
addi sp, sp, 16
// Exception state restored, return to whence we came
mret
.section .data, "aw"
// RAM-resident ISR function pointer table
.p2align 2
_external_irq_vector_table:
.rept 32
.word 0
.endr
// For each IRQ number, a mask where that bit and the bit corresponding to any
// IRQ of lower or equal priority is clear. The IRQs are grouped into
// relatively few priority levels (say 4 of them) to avoid blowing out the
// stack. When an IRQ's priority is adjusted, we disable IRQs and update the
// mask table.
_external_irq_primask_table:
.rept 32
.word 0
.endr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment