diff options
Diffstat (limited to 'software/first')
| -rw-r--r-- | software/first/delay.S | 6 | ||||
| -rw-r--r-- | software/first/first.c | 26 | ||||
| -rw-r--r-- | software/first/gpio.inc | 4 | ||||
| -rw-r--r-- | software/first/setup_timer_irq.S | 62 | 
4 files changed, 72 insertions, 26 deletions
| diff --git a/software/first/delay.S b/software/first/delay.S index 4df998a..656625f 100644 --- a/software/first/delay.S +++ b/software/first/delay.S @@ -16,10 +16,8 @@ delay:  	li t2, MTIME_FREQUENCY # get clock freq (approx.)  	mul t2, t2, a0         # multiply milliseconds with freq  	add t2, t1, t2         # target mtime is now in t2 - -1: -	lw t1, 0(t0)      # load value of the timer -	blt t1, t2, 1b    # keep looping until target mtime has been reached +	li t3, MTIMECMP        # load address of MTIMECMP register +	sw t2, 0(t3)           # store target time to MTIMECMP register. This only stores 32 bits so I am not sure if that is correct...  	lw ra, 12(sp)   # load return address  	addi sp, sp, 16 # deallocate stack frame diff --git a/software/first/first.c b/software/first/first.c index 7505d6c..889e05b 100644 --- a/software/first/first.c +++ b/software/first/first.c @@ -5,28 +5,16 @@  #include "super_blink.h"  int main() { -		int error = 0; -		int ledNum = 0; -		int colours[NUM_LEDS] = { -			GREEN_LED, -			RED_LED, -			BLUE_LED, -		}; -  		setup_GPIO();  		setup_timer_irq(); -		while (!error) { -			set_LED(colours[ledNum], ON); -			delay(DELAY); - -			error = set_LED(colours[ledNum], OFF); -			delay(DELAY); - -			ledNum++; +		// set a delay so the first interrupt handler can fire +		delay(DELAY); -			if (ledNum >= NUM_LEDS) { -				ledNum = 0; -			} +		while (1) { +			// the idea being that delay sets the timer +			// for the first interrupt. In the interrupt +			// routine, we set the next delay so all we need +			// to do here is to loop endlessly  		}  } diff --git a/software/first/gpio.inc b/software/first/gpio.inc index 37caeba..9617fdb 100644 --- a/software/first/gpio.inc +++ b/software/first/gpio.inc @@ -4,5 +4,5 @@  .equ  GPIO_RGB_PINS,  0x680000  .equ  GPIO_RED_LED,   0x400000 -.equ  GPIO_BLUE_LED,   0x200000 -.equ  GPIO_GREEN_LED,  0x080000 +.equ  GPIO_BLUE_LED,  0x200000 +.equ  GPIO_GREEN_LED, 0x080000 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 | 
