From f5e284223d25ee5beab98de95cd74e3ac72a39a6 Mon Sep 17 00:00:00 2001 From: Silvan Jegen Date: Mon, 22 Jul 2019 23:04:17 +0200 Subject: Implement first superblink version --- software/first/delay.S | 26 ++++++++++++++++++++++++ software/first/first.c | 33 +++++++++++++++++++++++++++++++ software/first/gpio.inc | 8 ++++++++ software/first/memory_map.inc | 3 +++ software/first/set_LED.S | 46 +++++++++++++++++++++++++++++++++++++++++++ software/first/setup_gpio.S | 19 ++++++++++++++++++ software/first/super_blink.h | 12 +++++++++++ 7 files changed, 147 insertions(+) create mode 100644 software/first/delay.S create mode 100644 software/first/first.c create mode 100644 software/first/gpio.inc create mode 100644 software/first/memory_map.inc create mode 100644 software/first/set_LED.S create mode 100644 software/first/setup_gpio.S create mode 100644 software/first/super_blink.h 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 +#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); -- cgit v1.2.3