132 lines
2.8 KiB
ArmAsm
132 lines
2.8 KiB
ArmAsm
#include "hazard3_csr.h"
|
|
|
|
.global isr_external_irq
|
|
isr_external_irq:
|
|
// Save caller saves and exception return state whilst IRQs are disabled.
|
|
// We can't be pre-empted during this time, but if a higher-priority IRQ
|
|
// arrives ("late arrival"), that will be the one displayed in meinext.
|
|
addi sp, sp, -80
|
|
sw ra, 0(sp)
|
|
sw t0, 4(sp)
|
|
sw t1, 8(sp)
|
|
sw t2, 12(sp)
|
|
sw a0, 16(sp)
|
|
sw a1, 20(sp)
|
|
sw a2, 24(sp)
|
|
sw a3, 28(sp)
|
|
sw a4, 32(sp)
|
|
sw a5, 36(sp)
|
|
sw a6, 40(sp)
|
|
sw a7, 44(sp)
|
|
sw t3, 48(sp)
|
|
sw t4, 52(sp)
|
|
sw t5, 56(sp)
|
|
sw t6, 60(sp)
|
|
|
|
// Update a count of the number of external IRQ vector entries (just for
|
|
// use in tests)
|
|
la a0, _external_irq_entry_count
|
|
lw a1, (a0)
|
|
addi a1, a1, 1
|
|
sw a1, (a0)
|
|
// Make sure to delete the above ^^^ if you use this code for real!
|
|
|
|
csrr a0, mepc
|
|
sw a0, 64(sp)
|
|
// Make sure to set meicontext.clearts to clear and save mie.msie/mtie
|
|
// when saving context.
|
|
csrrsi a0, hazard3_csr_meicontext, 0x2
|
|
sw a0, 68(sp)
|
|
csrr a0, mstatus
|
|
sw a0, 72(sp)
|
|
|
|
j get_next_irq
|
|
|
|
dispatch_irq:
|
|
// Preemption priority was configured by meinext update, so enable preemption:
|
|
csrsi mstatus, 0x8
|
|
// meinext is pre-shifted by 2, so only an add is required to index table
|
|
la a1, _external_irq_table
|
|
add a1, a1, a0
|
|
lw a1, (a1)
|
|
jalr ra, a1
|
|
|
|
// Disable IRQs on returning so we can sample the next IRQ
|
|
csrci mstatus, 0x8
|
|
|
|
get_next_irq:
|
|
// Sample the current highest-priority active IRQ (left-shifted by 2) from
|
|
// meinext, and write 1 to the LSB to tell hardware to tell hw to update
|
|
// meicontext with the preemption priority (and IRQ number) of this IRQ
|
|
csrrsi a0, hazard3_csr_meinext, 0x1
|
|
// MSB will be set if there is no active IRQ at the current priority level
|
|
bgez a0, dispatch_irq
|
|
|
|
no_more_irqs:
|
|
// Restore saved context and return from IRQ
|
|
lw a0, 64(sp)
|
|
csrw mepc, a0
|
|
lw a0, 68(sp)
|
|
csrw hazard3_csr_meicontext, a0
|
|
lw a0, 72(sp)
|
|
csrw mstatus, a0
|
|
|
|
lw ra, 0(sp)
|
|
lw t0, 4(sp)
|
|
lw t1, 8(sp)
|
|
lw t2, 12(sp)
|
|
lw a0, 16(sp)
|
|
lw a1, 20(sp)
|
|
lw a2, 24(sp)
|
|
lw a3, 28(sp)
|
|
lw a4, 32(sp)
|
|
lw a5, 36(sp)
|
|
lw a6, 40(sp)
|
|
lw a7, 44(sp)
|
|
lw t3, 48(sp)
|
|
lw t4, 52(sp)
|
|
lw t5, 56(sp)
|
|
lw t6, 60(sp)
|
|
addi sp, sp, 80
|
|
mret
|
|
|
|
// ------------------------------------------------------------
|
|
// Handler table and default handler symbols
|
|
|
|
// Provide weak symbol for all IRQs, pointing to a breakpoint instruction:
|
|
|
|
.macro decl_eirq num
|
|
.weak isr_irq\num
|
|
isr_irq\num:
|
|
.endm
|
|
|
|
.macro ref_eirq num
|
|
.word isr_irq\num
|
|
.endm
|
|
|
|
#define NUM_IRQS 32
|
|
|
|
.equ i, 0
|
|
.rept NUM_IRQS
|
|
decl_eirq i
|
|
.equ i, i + 1
|
|
.endr
|
|
ebreak
|
|
|
|
// Soft vector table is preloaded to RAM, and by default contains the weak ISR
|
|
// symbols, but can also be patched at runtime:
|
|
|
|
.section .data
|
|
.global _external_irq_table
|
|
_external_irq_table:
|
|
|
|
.equ i, 0
|
|
.rept NUM_IRQS
|
|
ref_eirq i
|
|
.equ i, i + 1
|
|
.endr
|
|
|
|
.global _external_irq_entry_count
|
|
_external_irq_entry_count:
|
|
.word 0
|