summaryrefslogtreecommitdiff
path: root/software/first
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
parentaa72093ffe1abafd605b5ec3b2d50c20b11c14a9 (diff)
Implement first version of ISR
Diffstat (limited to 'software/first')
-rw-r--r--software/first/delay.S6
-rw-r--r--software/first/first.c26
-rw-r--r--software/first/gpio.inc4
-rw-r--r--software/first/setup_timer_irq.S62
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