Skip to content

Instantly share code, notes, and snippets.

@Wren6991
Created December 4, 2021 00:52
Show Gist options
  • Select an option

  • Save Wren6991/158db32537f643d315afe14820231d29 to your computer and use it in GitHub Desktop.

Select an option

Save Wren6991/158db32537f643d315afe14820231d29 to your computer and use it in GitHub Desktop.

Revisions

  1. Wren6991 created this gist Dec 4, 2021.
    102 changes: 102 additions & 0 deletions irq_preempt.S
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@

    // 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