summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSilvan Jegen <s.jegen@gmail.com>2019-07-22 23:04:17 +0200
committerSilvan Jegen <s.jegen@gmail.com>2019-07-22 23:04:17 +0200
commitf5e284223d25ee5beab98de95cd74e3ac72a39a6 (patch)
tree33d6b2b3a0e5fa5b1d0b3094108bac78bd84bda0
parent4bc2e5141c68e82f2f6d7c8f71051fe93dd96d18 (diff)
Implement first superblink version
-rw-r--r--software/first/delay.S26
-rw-r--r--software/first/first.c33
-rw-r--r--software/first/gpio.inc8
-rw-r--r--software/first/memory_map.inc3
-rw-r--r--software/first/set_LED.S46
-rw-r--r--software/first/setup_gpio.S19
-rw-r--r--software/first/super_blink.h12
7 files changed, 147 insertions, 0 deletions
diff --git a/software/first/delay.S b/software/first/delay.S
new file mode 100644
index 0000000..cb49ba1
--- /dev/null
+++ b/software/first/delay.S
@@ -0,0 +1,26 @@
+.section .text
+.align 2
+.global delay
+.include "memory_map.inc"
+
+
+# a0 is delay in milliseconds argument
+
+delay:
+ addi sp, sp, -16 # Allocate stack frame
+ sw ra, 12(sp) # save return address to the stack
+
+ li t0, MTIME # load the timer register
+ lw t1, 0(t0) # load value of the timer
+
+ 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
+
+ lw ra, 12(sp) # load return address
+ addi sp, sp, 16 # deallocate stack frame
+ ret
diff --git a/software/first/first.c b/software/first/first.c
new file mode 100644
index 0000000..ed6e91b
--- /dev/null
+++ b/software/first/first.c
@@ -0,0 +1,33 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <stdio.h>
+#include "super_blink.h"
+
+int main() {
+ printf("Hello, cute waffle!\n");
+
+ int error = 0;
+ int ledNum = 0;
+ int colours[NUM_LEDS] = {
+ GREEN_LED,
+ RED_LED,
+ BLUE_LED,
+ };
+
+ setup_GPIO();
+
+ while (!error) {
+ set_LED(colours[ledNum], ON);
+ delay(DELAY);
+
+ error = set_LED(colours[ledNum], OFF);
+ delay(DELAY);
+
+ ledNum++;
+
+ if (ledNum >= NUM_LEDS) {
+ ledNum = 0;
+ }
+ }
+}
diff --git a/software/first/gpio.inc b/software/first/gpio.inc
new file mode 100644
index 0000000..37caeba
--- /dev/null
+++ b/software/first/gpio.inc
@@ -0,0 +1,8 @@
+.equ GPIO_OUTPUT_EN, 0x08
+.equ GPIO_OUTPUT_VAL, 0x0C
+.equ GPIO_OUTPUT_XOR, 0x40
+
+.equ GPIO_RGB_PINS, 0x680000
+.equ GPIO_RED_LED, 0x400000
+.equ GPIO_BLUE_LED, 0x200000
+.equ GPIO_GREEN_LED, 0x080000
diff --git a/software/first/memory_map.inc b/software/first/memory_map.inc
new file mode 100644
index 0000000..e28af43
--- /dev/null
+++ b/software/first/memory_map.inc
@@ -0,0 +1,3 @@
+.equ GPIO_CTRL_ADDR, 0x10012000
+.equ MTIME, 0x0200BFF8
+.equ MTIME_FREQUENCY, 33
diff --git a/software/first/set_LED.S b/software/first/set_LED.S
new file mode 100644
index 0000000..e436615
--- /dev/null
+++ b/software/first/set_LED.S
@@ -0,0 +1,46 @@
+.section .text
+.align 2
+.global set_LED
+.include "memory_map.inc"
+.include "gpio.inc"
+
+.equ NOERROR, 0x0
+.equ ERROR, 0x1
+.equ LEDON, 0x1
+
+# a0 contains LED to set, desired LED state in a1
+# a0 is also the return value...
+
+set_LED:
+ addi sp, sp, -16 # Allocate stack frame
+ sw ra, 12(sp) # save return address to the stack
+
+ li t0, GPIO_CTRL_ADDR # load base GPIO address
+ lw t1, GPIO_OUTPUT_VAL(t0) # load state
+
+ beqz a1, ledOff # branch if == 0
+ li t2, LEDON # load up on val into t2
+
+ beq a1, t2, ledOn # branch if on requested
+ li a0, ERROR # bad status request, return error
+ j exit
+
+
+ledOn:
+ or t1, t1, a0 # only change the value of the requested LED (xor in the video)
+ sw t1, GPIO_OUTPUT_VAL(t0) # write new LED values to the right address
+ li a0, NOERROR # success
+ j exit
+
+
+ledOff:
+ xor a0, a0, 0xffffffff # invert bits so off bits are off
+ and t1, t1, a0 # turn of LEDs
+ sw t1, GPIO_OUTPUT_VAL(t0) # write new LED values to the right address
+ li a0, NOERROR # success
+
+
+exit:
+ lw ra, 12(sp) # load return address
+ addi sp, sp, 16 # deallocate stack frame
+ ret
diff --git a/software/first/setup_gpio.S b/software/first/setup_gpio.S
new file mode 100644
index 0000000..39003b4
--- /dev/null
+++ b/software/first/setup_gpio.S
@@ -0,0 +1,19 @@
+.section .text
+.align 2
+.global setup_GPIO
+.include "memory_map.inc"
+.include "gpio.inc"
+
+setup_GPIO:
+ addi sp, sp, -16 # Allocate stack frame
+ sw ra, 12(sp) # save return address to the stack
+
+ li t0, GPIO_CTRL_ADDR # load base GPIO address
+ li t1, GPIO_RGB_PINS # get RGB offsets
+ sw t1, GPIO_OUTPUT_EN(t0) # enable output on the RGB pins
+ sw t1, GPIO_OUTPUT_XOR(t0) # set the RGB pins to active high
+ sw x0, GPIO_OUTPUT_VAL(t0) # set all pins to 0
+
+ lw ra, 12(sp) # load return address
+ addi sp, sp, 16 # deallocate stack frame
+ ret
diff --git a/software/first/super_blink.h b/software/first/super_blink.h
new file mode 100644
index 0000000..74cc00a
--- /dev/null
+++ b/software/first/super_blink.h
@@ -0,0 +1,12 @@
+#define DELAY 200
+#define ON 0x01
+#define OFF 0x00
+#define NUM_LEDS 0x03
+
+#define RED_LED 0x400000
+#define BLUE_LED 0x200000
+#define GREEN_LED 0x080000
+
+void setup_GPIO();
+int set_LED(int color, int state);
+void delay(int milliseconds);