GPIO example

This commit is contained in:
David Harris 2024-11-30 19:41:13 -08:00
parent b7467156c5
commit a4301babff
5 changed files with 147 additions and 1 deletions

2
.gitignore vendored
View file

@ -153,6 +153,8 @@ examples/C/mcmodel/mcmodel_medany
examples/C/mcmodel/mcmodel_medlow
examples/C/sum/sum
examples/C/sum_mixed/sum_mixed
examples/C/hello/hello
examples/C/gpio/gpio
examples/asm/sumtest/sumtest
examples/asm/example/example
examples/asm/trap/trap

33
examples/C/gpio/Makefile Normal file
View file

@ -0,0 +1,33 @@
TARGET = gpio
$(TARGET).objdump: $(TARGET)
riscv64-unknown-elf-objdump -S -D $(TARGET) > $(TARGET).objdump
cp $(TARGET) $(TARGET).elf
$(TARGET): $(TARGET).c Makefile
riscv64-unknown-elf-gcc -o $(TARGET) -gdwarf-2 -O\
-march=rv64gc -mabi=lp64d -mcmodel=medany \
-nostdlib -static -lm -fno-tree-loop-distribute-patterns \
-T../common/test.ld -I../common \
$(TARGET).c ../common/crt.S ../common/syscalls.c
# Compiler flags:
# -o $(TARGET) defines the name of the output file
# -g generates debugging symbols for gdb
# -O turns on basic optimization; -O3 turns on heavy optimization; omit for no optimization
# -march=rv64gc -mabi=lp64d =mcmodel=medany generates code for RV64GC with doubles and long/ptrs = 64 bits
# -static forces static linking (no dynamic shared libraries on bare metal)
# -lm links the math library if necessary (when #include math.h)
# -nostdlib avoids inserting standard startup files and default libraries
# because we are using crt.s on bare metal
# -fno-tree-loop-distribute-patterns turns replacing loops with memcpy/memset in the std library
# -T specifies the linker file
# -I specifies the include path (e.g. for util.h)
# The last line defines the C files to compile.
# crt.S is needed as our startup file to initialize the processor
# syscalls.c implements printf through the HTIF for Spike
# other flags from riscv-tests makefiles that don't seem to be important
# -ffast-math -DPREALLOCATE=1 -std=gnu99 \
# -fno-common -fno-builtin-printf -nostartfiles -lgcc \
clean:
rm -f $(TARGET) $(TARGET).objdump

28
examples/C/gpio/gpio.c Normal file
View file

@ -0,0 +1,28 @@
// gpio.c
// David_Harris@hmc.edu 30 November 2024
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
// General-Purpose I/O (GPIO) example program illustrating compiled C code
// compile with make
// simulate with: wsim rv64gc hello.elf --sim verilator
#include <stdio.h>
#include "gpiolib.h"
int main(void) {
printf("GPIO Example!\n\r");
pinMode(0, INPUT);
pinMode(1, OUTPUT);
pinMode(2, OUTPUT);
for (int i=0; i<10; i++) {
// Read pin 0 and write it to pin 1
int val = digitalRead(0);
printf("Pin 0: %d\n", val);
digitalWrite(1, val);
// Toggle pin 2
printf("Pin 2: %d\n", i%2);
digitalWrite(2, i%2);
}
}

81
examples/C/gpio/gpiolib.h Normal file
View file

@ -0,0 +1,81 @@
// gpiolib.h
// Basic Arduino-compatible functions for general-purpose input/output
// Assumes GPIO0_BASE is set to the memory-mapped GPIO address from
// config/rv64gc/config.vh.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
#include <stdint.h>
///////////////////////////////////////////////////////////////////////////////
// Bitfield Structs
///////////////////////////////////////////////////////////////////////////////
typedef struct
{
volatile uint32_t input_val; // (GPIO offset 0x00) Pin value
volatile uint32_t input_en; // (GPIO offset 0x04) Pin input enable*
volatile uint32_t output_en; // (GPIO offset 0x08) Pin output enable*
volatile uint32_t output_val; // (GPIO offset 0x0C) Output value
volatile uint32_t pue; // (GPIO offset 0x10) Internal pull-up enable*
volatile uint32_t ds; // (GPIO offset 0x14) Pin drive strength
volatile uint32_t rise_ie; // (GPIO offset 0x18) Rise interrupt enable
volatile uint32_t rise_ip; // (GPIO offset 0x1C) Rise interrupt pending
volatile uint32_t fall_ie; // (GPIO offset 0x20) Fall interrupt enable
volatile uint32_t fall_ip; // (GPIO offset 0x24) Fall interrupt pending
volatile uint32_t high_ie; // (GPIO offset 0x28) High interrupt enable
volatile uint32_t high_ip; // (GPIO offset 0x2C) High interrupt pending
volatile uint32_t low_ie; // (GPIO offset 0x30) Low interrupt enable
volatile uint32_t low_ip; // (GPIO offset 0x34) Low interrupt pending
volatile uint32_t iof_en; // (GPIO offset 0x38) HW-Driven functions enable
volatile uint32_t iof_sel; // (GPIO offset 0x3C) HW-Driven functions selection
volatile uint32_t out_xor; // (GPIO offset 0x40) Output XOR (invert)
// Registers marked with * are asynchronously reset to 0. All others are synchronously reset to 0.
} GPIO;
///////////////////////////////////////////////////////////////////////////////
// GPIO Constant Definitions
///////////////////////////////////////////////////////////////////////////////
#define GPIO0_BASE (0x10060000U) // GPIO memory-mapped base address
#define GPIO0 ((GPIO*) GPIO0_BASE) // Set up pointer to struct of type GPIO aligned at the base GPIO0 memory-mapped address
#define LOW 0
#define HIGH 1
#define INPUT 0
#define OUTPUT 1
#define GPIO_IOF0 2
///////////////////////////////////////////////////////////////////////////////
// GPIO Functions
///////////////////////////////////////////////////////////////////////////////
void pinMode(int pin, int function)
{
switch(function) {
case INPUT:
GPIO0->input_en |= (1 << pin); // Sets a pin as an input
break;
case OUTPUT:
GPIO0->output_en |= (1 << pin); // Set pin as an output
GPIO0->iof_en &= ~(1 << pin);
break;
case GPIO_IOF0:
GPIO0->iof_sel &= ~(1 << pin);
GPIO0->iof_en |= (1 << pin);
}
}
void digitalWrite(int pin, int val)
{
if (val) GPIO0->output_val |= (1 << pin);
else GPIO0->output_val &= ~(1 << pin);
}
int digitalRead(int pin)
{
return (GPIO0->input_val >> pin) & 0x1;
}

View file

@ -1,5 +1,6 @@
// hello.c
// David_Harris@hmc.edu 30 November 2024
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
// Hello World program illustrating compiled C code printing via the UART
// The Wally team has modified the Berkeley syscalls.c (in examples/C/common)
@ -10,7 +11,8 @@
// such that using \n\r for new lines works best.
// compile with make
// simulate with: wsim rv64gc hello.elf --sim verilator
// simulate Wally with: wsim rv64gc hello.elf --sim verilator
// simulate in Spike with: spike hello.elf
#include <stdio.h>