diff options
Diffstat (limited to 'software/first/setup_timer_irq.S')
| -rw-r--r-- | software/first/setup_timer_irq.S | 62 | 
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  | 
