summaryrefslogtreecommitdiff
path: root/software/first/setup_timer_irq.S
diff options
context:
space:
mode:
authorSilvan Jegen <s.jegen@gmail.com>2019-08-10 17:40:59 +0200
committerSilvan Jegen <s.jegen@gmail.com>2019-08-10 17:40:59 +0200
commit8fd7e5e623647866db88b632347261e5d9f30da1 (patch)
tree4107057e189ac976f5b071420942339e129ce41c /software/first/setup_timer_irq.S
parentaa72093ffe1abafd605b5ec3b2d50c20b11c14a9 (diff)
Implement first version of ISR
Diffstat (limited to 'software/first/setup_timer_irq.S')
-rw-r--r--software/first/setup_timer_irq.S62
1 files changed, 61 insertions, 1 deletions
diff --git a/software/first/setup_timer_irq.S b/software/first/setup_timer_irq.S
index 4ae714f..97b5f6c 100644
--- a/software/first/setup_timer_irq.S
+++ b/software/first/setup_timer_irq.S
@@ -1,6 +1,7 @@
.section .text
.align 2
.global setup_timer_irq
+.include "gpio.inc"
.include "memory_map.inc"
setup_timer_irq:
@@ -29,6 +30,65 @@ setup_timer_irq:
addi sp, sp, 16 # deallocate stack frame
ret
+# Unix C ABI has high context switch cost. The current RISC-V ABI
+# requires (ignoring floating-point registers; from
+# https://content.riscv.org/wp-content/uploads/2018/05/08.45-09.10-RISCV-20180509-FastInts.pdf
+# ):
+#
+# addi sp, sp, -FRAMESIZE
+# sw ra, x(sp) # 1 return address
+# sw t0-t6, x(sp) # 7 temporaries
+# sw a0-a7, x(sp) # 8 arguments
+#
+# jal c_handler
+#
+# lw a0-a7, x(sp) # 8 arguments
+# lw t0-t6, x(sp) # 7 temporaries
+# lw ra, x(sp) # 1 return address
+# addi sp, sp, FRAMESIZE
+# mret
+
irq_handler:
- mret
+ # save only the registers we use in this function
+ addi sp, sp, -24 # Allocate stack frame
+ sw ra, 20(sp) # save return address to the stack
+ sw t0, 16(sp) # save temporary
+ sw t1, 12(sp) # save temporary
+ sw t2, 8(sp) # save temporary
+ sw t3, 4(sp) # save temporary
+
+ li t0, GPIO_CTRL_ADDR # load base GPIO address
+ lw t1, GPIO_OUTPUT_VAL(t0) # load state
+
+ beqz t1, switchOnRed # if none is blinking yet, blink the red one
+ li t3, GPIO_RED_LED
+ beq t1, t3, switchOnBlue # if red is on, switch on blue LED
+ li t3, GPIO_BLUE_LED
+ beq t1, t3, switchOnGreen # if blue is on, switch on green LED
+ # here, neither the red or blue are on, so the one that is on
+ # must be the green one. In that case we just fall through to
+ # switch on the red LED
+
+switchOnRed:
+ li t2, GPIO_RED_LED # load value indicating red LED
+ j exit
+
+switchOnBlue:
+ li t2, GPIO_BLUE_LED # load value indicating blue LED
+ j exit
+
+switchOnGreen:
+ li t2, GPIO_GREEN_LED # load value indicating green LED
+ j exit
+
+
+exit:
+ sw t2, GPIO_OUTPUT_VAL(t0) # write new LED values to the right address
+ lw ra, 20(sp) # load return address
+ lw t0, 16(sp) # restore temporary
+ lw t1, 12(sp) # restore temporary
+ lw t2, 8(sp) # restore temporary
+ lw t3, 4(sp) # restore temporary
+ addi sp, sp, 24 # deallocate stack frame
+ mret # exit IRQ handler