From ca28b45e758e2f36be5a93c5ae0a5cdfe91d5db9 Mon Sep 17 00:00:00 2001 From: cheapie Date: Fri, 26 Jun 2026 09:55:56 -0500 Subject: Add basic mesecons/digilines interrupt support --- assembly/extint-test/extint-test.S | 145 +++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 assembly/extint-test/extint-test.S (limited to 'assembly/extint-test/extint-test.S') diff --git a/assembly/extint-test/extint-test.S b/assembly/extint-test/extint-test.S new file mode 100644 index 0000000..c1b872d --- /dev/null +++ b/assembly/extint-test/extint-test.S @@ -0,0 +1,145 @@ +li t0,0xffff0000 +csrw 0x801,t0 # Map the MMIO region somewhere +la t0,handler +csrw mtvec,t0 # Set up trap handler +li t0,0x400 +csrc mstatush,t0 # Turn off MDT +li t0,0x30000 +csrw mie,t0 # Mask all interrupts except mesecons/digilines +csrw mip,zero # Clear any pending interrupts +csrsi mstatus,0x8 # Turn on MIE to enable interrupts + +mainloop: +li a7,4 +la a0,waitingmsg +ecall # Print waiting message +wfi # And do nothing else, this program is entirely interrupt-driven +j mainloop + + + +.align 4 +handler: +csrrw x31,mscratch,x31 # Free up x31 to hold the context address +la x31,hcontext # Using x register numbers here since trap handlers don't use the usual calling convention +sw x1,0(x31) # Save all the registers to the context +sd x2,4(x31) # Two at a time since we have Zilsd/Zclsd +sd x4,12(x31) # Note that I don't actually _need_ all of the registers in the handler, +sd x6,20(x31) # but I wanted to try this anyway to see how it goes +sd x8,28(x31) +sd x10,36(x31) +sd x12,44(x31) +sd x14,52(x31) +sd x16,60(x31) +sd x18,68(x31) +sd x20,76(x31) +sd x22,84(x31) +sd x24,92(x31) +sd x26,100(x31) +sd x28,108(x31) +sw x30,116(x31) +csrr x30,mscratch # Get the old x31 value back into a register +sw x30,120(x31) # and write that back out too + +csrr t0,mcause # Read why the trap occurred + +li t1,0x80000010 # Interrupt 16 = mesecons +beq t0,t1,handler_mesecons + +li t1,0x80000011 # Interrupt 17 = digilines +beq t0,t1,handler_digilines + +j handler_other # Something else + +handler_mesecons: +li a7,4 +la a0,meseconsmsg +ecall # Show that this was a mesecons event + +li a7,1 +li t0,0xffff0000 +lb a0,1(t0) # Read the mesecons I/O port value +ecall # And print that + +li a7,11 +li a0,'\n' +ecall # Line feed + +j handler_epilogue + +handler_digilines: +li a7,4 +la a0,digilinesmsg +ecall # Show that this was a digilines event + +li a7,135 +la a0,channelbuf +li a1,21 +la a2,msgbuf +li a3,21 +ecall # Read what the event was + +li a7,4 +la a0,channelbuf +ecall # Print the channel + +li a7,4 +la a0,digilinesmsg2 +ecall # "Message:", this has its own line feeds in it + +li a7,4 +la a0,msgbuf +ecall # Print the message + +li a7,11 +li a0,'\n' +ecall # Line feed + +li a7,134 +ecall # Clear out any other digilines messages + +j handler_epilogue + +handler_other: +li a7,4 +la a0,unimplementedmsg +ecall # Display unimplemented trap message + +csrr a0,mcause # Read what the cause was +li a7,1 +ecall # Tell the user + +li a7,10 +ecall # Then halt + +handler_epilogue: +csrw mip,zero # Clear out all pending interrupts +la x31,hcontext # x numbers here for the same reason as during the save +lw x1,0(x31) # Load all of the registers from the context +ld x2,4(x31) # Two at a time since we have Zilsd/Zclsd +ld x4,12(x31) +ld x6,20(x31) +ld x8,28(x31) +ld x10,36(x31) +ld x12,44(x31) +ld x14,52(x31) +ld x16,60(x31) +ld x18,68(x31) +ld x20,76(x31) +ld x22,84(x31) +ld x24,92(x31) +ld x26,100(x31) +ld x28,108(x31) +ld x30,116(x31) +mret # Return to the program (not that the rest of the program does much) + +hcontext: .skip 32*4 + + +waitingmsg: .asciz "Waiting...\n" +meseconsmsg: .asciz "Mesecons event!\nInput value: " +digilinesmsg: .asciz "Digilines event!\nChannel:\n" +digilinesmsg2: .asciz "\nMessage:\n" +unimplementedmsg: .asciz "Unimplemented trap!\nmcause: " +channelbuf: .asciz " " +msgbuf: .asciz " " -- cgit v1.2.3