From 8fd7e5e623647866db88b632347261e5d9f30da1 Mon Sep 17 00:00:00 2001 From: Silvan Jegen Date: Sat, 10 Aug 2019 17:40:59 +0200 Subject: Implement first version of ISR --- software/first/delay.S | 6 ++-- software/first/first.c | 26 +++++------------ software/first/gpio.inc | 4 +-- software/first/setup_timer_irq.S | 62 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 72 insertions(+), 26 deletions(-) (limited to 'software') 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 -- cgit v1.2.3