raven FW with data and interrupt transfer (based on bldc project)

This commit is contained in:
Stanislaw Kaushanski 2020-09-16 10:28:54 +02:00
parent 4c790f8810
commit 9157a42042
99 changed files with 4254 additions and 3162 deletions

View File

@ -1,13 +1,29 @@
TARGET = hello_raven
C_SRCS += $(wildcard *.c)
CFLAGS += -g
#-fno-builtin-printf
LDFLAGS := -Wl,--wrap=scanf -Wl,--wrap=printf
TARGET = hello_raven
C_SRCS = $(wildcard src/*.c) $(BSP_BASE)/drivers/fe300prci/fe300prci_driver.c $(BSP_BASE)/drivers/plic/plic_driver.c
CXX_SRCS = $(wildcard src/*.cpp)
HEADERS = $(wildcard src/*.h)
CFLAGS = -g -fno-builtin-printf -DUSE_PLIC -DUSE_M_TIME -DNO_INIT -I./src
CXXFLAGS = -fno-use-cxa-atexit
LDFLAGS = -Wl,--wrap=printf
LDFLAGS += -g -lstdc++ -fno-use-cxa-atexit -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -mcmodel=medany
#BOARD = iss
BOARD=freedom-e300-hifive1
TOOL_DIR=/opt/shared/riscv/FreedomStudio/20180122/SiFive/riscv64-unknown-elf-gcc-20171231-x86_64-linux-centos6/bin
LINK_TARGET=flash
RISCV_ARCH=rv32imac
RISCV_ABI=ilp32
TOOL_DIR=/home/stas/Downloads/riscv64-unknown-elf-gcc-8.3.0-2020.04.0-x86_64-linux-ubuntu14/bin
#TOOL_DIR?=/opt/riscv/FreedomStudio/20180122/SiFive/riscv64-unknown-elf-gcc-20171231-x86_64-linux-centos6/bin
BSP_BASE = ./bsp
include $(BSP_BASE)/env/common.mk
.PHONY: all
all: $(TARGET).dump
$(TARGET).dump: $(TARGET)
$(TOOL_DIR)/$(TRIPLET)-objdump -d -S -C $< > $@

View File

@ -1,24 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../drivers/fe300prci/fe300prci_driver.c
OBJS += \
./drivers/fe300prci/fe300prci_driver.o
C_DEPS += \
./drivers/fe300prci/fe300prci_driver.d
# Each subdirectory must supply rules for building sources it contributes
drivers/fe300prci/%.o: ../drivers/fe300prci/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
riscv32-unknown-elf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -1,24 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../drivers/plic/plic_driver.c
OBJS += \
./drivers/plic/plic_driver.o
C_DEPS += \
./drivers/plic/plic_driver.d
# Each subdirectory must supply rules for building sources it contributes
drivers/plic/%.o: ../drivers/plic/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
riscv32-unknown-elf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -1,24 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../env/freedom-e300-arty/init.c
OBJS += \
./env/freedom-e300-arty/init.o
C_DEPS += \
./env/freedom-e300-arty/init.d
# Each subdirectory must supply rules for building sources it contributes
env/freedom-e300-arty/%.o: ../env/freedom-e300-arty/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
riscv32-unknown-elf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -1,27 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../env/freedom-e300-hifive1/init.c
O_SRCS += \
../env/freedom-e300-hifive1/init.o
OBJS += \
./env/freedom-e300-hifive1/init.o
C_DEPS += \
./env/freedom-e300-hifive1/init.d
# Each subdirectory must supply rules for building sources it contributes
env/freedom-e300-hifive1/%.o: ../env/freedom-e300-hifive1/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
riscv32-unknown-elf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -1,27 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../env/iss/init.c
O_SRCS += \
../env/iss/init.o
OBJS += \
./env/iss/init.o
C_DEPS += \
./env/iss/init.d
# Each subdirectory must supply rules for building sources it contributes
env/iss/%.o: ../env/iss/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
riscv32-unknown-elf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -1,27 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
O_SRCS += \
../env/entry.o \
../env/start.o
S_UPPER_SRCS += \
../env/entry.S \
../env/start.S
OBJS += \
./env/entry.o \
./env/start.o
# Each subdirectory must supply rules for building sources it contributes
env/%.o: ../env/%.S
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Assembler'
riscv32-unknown-elf-as -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -1,27 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../libwrap/stdlib/malloc.c
O_SRCS += \
../libwrap/stdlib/malloc.o
OBJS += \
./libwrap/stdlib/malloc.o
C_DEPS += \
./libwrap/stdlib/malloc.d
# Each subdirectory must supply rules for building sources it contributes
libwrap/stdlib/%.o: ../libwrap/stdlib/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
riscv32-unknown-elf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -1,98 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../libwrap/sys/_exit.c \
../libwrap/sys/close.c \
../libwrap/sys/execve.c \
../libwrap/sys/fork.c \
../libwrap/sys/fstat.c \
../libwrap/sys/getpid.c \
../libwrap/sys/isatty.c \
../libwrap/sys/kill.c \
../libwrap/sys/link.c \
../libwrap/sys/lseek.c \
../libwrap/sys/open.c \
../libwrap/sys/openat.c \
../libwrap/sys/read.c \
../libwrap/sys/sbrk.c \
../libwrap/sys/stat.c \
../libwrap/sys/times.c \
../libwrap/sys/unlink.c \
../libwrap/sys/wait.c \
../libwrap/sys/write.c
O_SRCS += \
../libwrap/sys/_exit.o \
../libwrap/sys/close.o \
../libwrap/sys/execve.o \
../libwrap/sys/fork.o \
../libwrap/sys/fstat.o \
../libwrap/sys/getpid.o \
../libwrap/sys/isatty.o \
../libwrap/sys/kill.o \
../libwrap/sys/link.o \
../libwrap/sys/lseek.o \
../libwrap/sys/open.o \
../libwrap/sys/read.o \
../libwrap/sys/sbrk.o \
../libwrap/sys/stat.o \
../libwrap/sys/times.o \
../libwrap/sys/unlink.o \
../libwrap/sys/wait.o \
../libwrap/sys/write.o
OBJS += \
./libwrap/sys/_exit.o \
./libwrap/sys/close.o \
./libwrap/sys/execve.o \
./libwrap/sys/fork.o \
./libwrap/sys/fstat.o \
./libwrap/sys/getpid.o \
./libwrap/sys/isatty.o \
./libwrap/sys/kill.o \
./libwrap/sys/link.o \
./libwrap/sys/lseek.o \
./libwrap/sys/open.o \
./libwrap/sys/openat.o \
./libwrap/sys/read.o \
./libwrap/sys/sbrk.o \
./libwrap/sys/stat.o \
./libwrap/sys/times.o \
./libwrap/sys/unlink.o \
./libwrap/sys/wait.o \
./libwrap/sys/write.o
C_DEPS += \
./libwrap/sys/_exit.d \
./libwrap/sys/close.d \
./libwrap/sys/execve.d \
./libwrap/sys/fork.d \
./libwrap/sys/fstat.d \
./libwrap/sys/getpid.d \
./libwrap/sys/isatty.d \
./libwrap/sys/kill.d \
./libwrap/sys/link.d \
./libwrap/sys/lseek.d \
./libwrap/sys/open.d \
./libwrap/sys/openat.d \
./libwrap/sys/read.d \
./libwrap/sys/sbrk.d \
./libwrap/sys/stat.d \
./libwrap/sys/times.d \
./libwrap/sys/unlink.d \
./libwrap/sys/wait.d \
./libwrap/sys/write.d
# Each subdirectory must supply rules for building sources it contributes
libwrap/sys/%.o: ../libwrap/sys/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
riscv32-unknown-elf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -1,66 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
-include ../makefile.init
RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
-include libwrap/sys/subdir.mk
-include libwrap/stdlib/subdir.mk
-include libwrap/misc/subdir.mk
-include env/iss/subdir.mk
-include env/freedom-e300-hifive1/subdir.mk
-include env/freedom-e300-arty/subdir.mk
-include env/subdir.mk
-include drivers/plic/subdir.mk
-include drivers/fe300prci/subdir.mk
-include subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(CC_DEPS)),)
-include $(CC_DEPS)
endif
ifneq ($(strip $(C++_DEPS)),)
-include $(C++_DEPS)
endif
ifneq ($(strip $(C_UPPER_DEPS)),)
-include $(C_UPPER_DEPS)
endif
ifneq ($(strip $(CXX_DEPS)),)
-include $(CXX_DEPS)
endif
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
ifneq ($(strip $(CPP_DEPS)),)
-include $(CPP_DEPS)
endif
endif
-include ../makefile.defs
# Add inputs and outputs from these tool invocations to the build variables
# All Target
all: bsp
# Tool invocations
bsp: $(OBJS) $(USER_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: Cross G++ Linker'
riscv32-unknown-elf-g++ -o "bsp" $(OBJS) $(USER_OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '
# Other Targets
clean:
-$(RM) $(CC_DEPS)$(C++_DEPS)$(EXECUTABLES)$(OBJS)$(C_UPPER_DEPS)$(CXX_DEPS)$(C_DEPS)$(CPP_DEPS) bsp
-@echo ' '
.PHONY: all clean dependents
-include ../makefile.targets

View File

@ -1,8 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
USER_OBJS :=
LIBS :=

View File

@ -1,35 +0,0 @@
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
C_UPPER_SRCS :=
CXX_SRCS :=
C++_SRCS :=
OBJ_SRCS :=
CC_SRCS :=
ASM_SRCS :=
C_SRCS :=
CPP_SRCS :=
O_SRCS :=
S_UPPER_SRCS :=
CC_DEPS :=
C++_DEPS :=
EXECUTABLES :=
OBJS :=
C_UPPER_DEPS :=
CXX_DEPS :=
C_DEPS :=
CPP_DEPS :=
# Every subdirectory with source files must be described here
SUBDIRS := \
drivers/fe300prci \
drivers/plic \
env \
env/freedom-e300-arty \
env/freedom-e300-hifive1 \
env/iss \
libwrap/misc \
libwrap/stdlib \
libwrap/sys \

View File

@ -0,0 +1,163 @@
// See LICENSE for license details.
#include "sifive/devices/clic.h"
#include "clic/clic_driver.h"
#include "platform.h"
#include "encoding.h"
#include <string.h>
void volatile_memzero(uint8_t * base, unsigned int size) {
volatile uint8_t * ptr;
for (ptr = base; ptr < (base + size); ptr++){
*ptr = 0;
}
}
// Note that there are no assertions or bounds checking on these
// parameter values.
void clic_init (
clic_instance_t * this_clic,
uintptr_t hart_addr,
interrupt_function_ptr_t* vect_table,
interrupt_function_ptr_t default_handler,
uint32_t num_irq,
uint32_t num_config_bits
)
{
this_clic->hart_addr= hart_addr;
this_clic->vect_table= vect_table;
this_clic->num_config_bits= num_config_bits;
//initialize vector table
for(int i=0;i++;i<num_irq) {
this_clic->vect_table[i] = default_handler;
}
//set base vectors
write_csr(mtvt, vect_table);
//clear all interrupt enables and pending
volatile_memzero((uint8_t*)(this_clic->hart_addr+CLIC_INTIE), num_irq);
volatile_memzero((uint8_t*)(this_clic->hart_addr+CLIC_INTIP), num_irq);
//clear nlbits and nvbits; all interrupts trap to level 15
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG)=0;
}
void clic_install_handler (clic_instance_t * this_clic, uint32_t source, interrupt_function_ptr_t handler) {
this_clic->vect_table[source] = handler;
}
void clic_enable_interrupt (clic_instance_t * this_clic, uint32_t source) {
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIE+source) = 1;
}
void clic_disable_interrupt (clic_instance_t * this_clic, uint32_t source){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIE+source) = 0;
}
void clic_set_pending(clic_instance_t * this_clic, uint32_t source){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIP+source) = 1;
}
void clic_clear_pending(clic_instance_t * this_clic, uint32_t source){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIP+source) = 0;
}
void clic_set_intcfg (clic_instance_t * this_clic, uint32_t source, uint32_t intcfg){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTCFG+source) = intcfg;
}
uint8_t clic_get_intcfg (clic_instance_t * this_clic, uint32_t source){
return *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTCFG+source);
}
void clic_set_cliccfg (clic_instance_t * this_clic, uint32_t cfg){
*(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG) = cfg;
}
uint8_t clic_get_cliccfg (clic_instance_t * this_clic){
return *(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG);
}
//sets an interrupt level based encoding of nmbits, nlbits
uint8_t clic_set_int_level( clic_instance_t * this_clic, uint32_t source, uint8_t level) {
//extract nlbits
uint8_t nlbits = clic_get_cliccfg(this_clic);
nlbits = (nlbits >>1) & 0x7;
//shift level right to mask off unused bits
level = level>>((this_clic->num_config_bits)-nlbits); //plus this_clic->nmbits which is always 0 for now.
//shift level into correct bit position
level = level << (8-this_clic->num_config_bits) + (this_clic->num_config_bits - nlbits);
//write to clicintcfg
uint8_t current_intcfg = clic_get_intcfg(this_clic, source);
clic_set_intcfg(this_clic, source, (current_intcfg | level));
return level;
}
//gets an interrupt level based encoding of nmbits, nlbits
uint8_t clic_get_int_level( clic_instance_t * this_clic, uint32_t source) {
uint8_t level;
level = clic_get_intcfg(this_clic, source);
//extract nlbits
uint8_t nlbits = clic_get_cliccfg(this_clic);
nlbits = (nlbits >>1) & 0x7;
//shift level
level = level >> (8-(this_clic->num_config_bits));
//shift level right to mask off priority bits
level = level>>(this_clic->num_config_bits-nlbits); //this_clic->nmbits which is always 0 for now.
return level;
}
//sets an interrupt priority based encoding of nmbits, nlbits
uint8_t clic_set_int_priority( clic_instance_t * this_clic, uint32_t source, uint8_t priority) {
//priority bits = num_config_bits - nlbits
//extract nlbits
uint8_t nlbits = clic_get_cliccfg(this_clic);
nlbits = (nlbits >>1) & 0x7;
uint8_t priority_bits = this_clic->num_config_bits-nlbits;
if(priority_bits = 0) {
//no bits to set
return 0;
}
//mask off unused bits
priority = priority >> (8-priority_bits);
//shift into the correct bit position
priority = priority << (8-(this_clic->num_config_bits));
//write to clicintcfg
uint8_t current_intcfg = clic_get_intcfg(this_clic, source);
clic_set_intcfg(this_clic, source, (current_intcfg | priority));
return current_intcfg;
}
//gets an interrupt priority based encoding of nmbits, nlbits
uint8_t clic_get_int_priority( clic_instance_t * this_clic, uint32_t source) {
uint8_t priority;
priority = clic_get_intcfg(this_clic, source);
//extract nlbits
uint8_t nlbits = clic_get_cliccfg(this_clic);
nlbits = (nlbits >>1) & 0x7;
//shift left to mask off level bits
priority = priority << nlbits;
//shift priority
priority = priority >> (8-((this_clic->num_config_bits)+nlbits));
return priority;
}

View File

@ -0,0 +1,44 @@
// See LICENSE file for licence details
#ifndef PLIC_DRIVER_H
#define PLIC_DRIVER_H
__BEGIN_DECLS
#include "platform.h"
typedef void (*interrupt_function_ptr_t) (void);
typedef struct __clic_instance_t
{
uintptr_t hart_addr;
interrupt_function_ptr_t* vect_table;
uint32_t num_config_bits;
uint32_t num_sources;
} clic_instance_t;
// Note that there are no assertions or bounds checking on these
// parameter values.
void clic_init (clic_instance_t * this_clic, uintptr_t hart_addr, interrupt_function_ptr_t* vect_table, interrupt_function_ptr_t default_handler, uint32_t num_irq,uint32_t num_config_bits);
void clic_install_handler (clic_instance_t * this_clic, uint32_t source, interrupt_function_ptr_t handler);
void clic_enable_interrupt (clic_instance_t * this_clic, uint32_t source);
void clic_disable_interrupt (clic_instance_t * this_clic, uint32_t source);
void clic_set_pending(clic_instance_t * this_clic, uint32_t source);
void clic_clear_pending(clic_instance_t * this_clic, uint32_t source);
void clic_set_intcfg (clic_instance_t * this_clic, uint32_t source, uint32_t intcfg);
uint8_t clic_get_intcfg (clic_instance_t * this_clic, uint32_t source);
void clic_set_cliccfg (clic_instance_t * this_clic, uint32_t cfg);
uint8_t clic_get_cliccfg (clic_instance_t * this_clic);
//sets an interrupt level based encoding of nmbits, nlbits
uint8_t clic_set_int_level( clic_instance_t * this_clic, uint32_t source, uint8_t level);
//get an interrupt level based encoding of nmbits, nlbits
uint8_t clic_get_int_level( clic_instance_t * this_clic, uint32_t source);
//sets an interrupt priority based encoding of nmbits, nlbits
uint8_t clic_set_int_priority( clic_instance_t * this_clic, uint32_t source, uint8_t priority);
//sets an interrupt priority based encoding of nmbits, nlbits
uint8_t clic_get_int_priority( clic_instance_t * this_clic, uint32_t source);
__END_DECLS
#endif

View File

@ -2,7 +2,7 @@
#include "platform.h"
#ifdef PRCI_BASE_ADDR
#ifdef PRCI_CTRL_ADDR
#include "fe300prci/fe300prci_driver.h"
#include <unistd.h>

View File

@ -22,19 +22,20 @@ void PLIC_init (
plic_instance_t * this_plic,
uintptr_t base_addr,
uint32_t num_sources,
uint32_t num_priorities
uint32_t num_priorities,
uint32_t target_hartid
)
{
this_plic->base_addr = base_addr;
this_plic->num_sources = num_sources;
this_plic->num_priorities = num_priorities;
this_plic->target_hartid = target_hartid;
// Disable all interrupts (don't assume that these registers are reset).
unsigned long hart_id = read_csr(mhartid);
volatile_memzero((uint8_t*) (this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
(this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET)),
(num_sources + 8) / 8);
// Set all priorities to 0 (equal priority -- don't assume that these are reset).
@ -46,7 +47,7 @@ void PLIC_init (
volatile plic_threshold* threshold = (plic_threshold*)
(this_plic->base_addr +
PLIC_THRESHOLD_OFFSET +
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
(this_plic->target_hartid << PLIC_THRESHOLD_SHIFT_PER_TARGET));
*threshold = 0;
@ -55,10 +56,9 @@ void PLIC_init (
void PLIC_set_threshold (plic_instance_t * this_plic,
plic_threshold threshold){
unsigned long hart_id = read_csr(mhartid);
volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
PLIC_THRESHOLD_OFFSET +
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
(this_plic->target_hartid << PLIC_THRESHOLD_SHIFT_PER_TARGET));
*threshold_ptr = threshold;
@ -67,10 +67,9 @@ void PLIC_set_threshold (plic_instance_t * this_plic,
void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){
unsigned long hart_id = read_csr(mhartid);
volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
(this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET) +
(source >> 3));
uint8_t current = *current_ptr;
current = current | ( 1 << (source & 0x7));
@ -80,10 +79,9 @@ void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){
void PLIC_disable_interrupt (plic_instance_t * this_plic, plic_source source){
unsigned long hart_id = read_csr(mhartid);
volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
(this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET) +
(source >> 3));
uint8_t current = *current_ptr;
current = current & ~(( 1 << (source & 0x7)));
@ -104,12 +102,10 @@ void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_pr
plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){
unsigned long hart_id = read_csr(mhartid);
volatile plic_source * claim_addr = (volatile plic_source * )
(this_plic->base_addr +
PLIC_CLAIM_OFFSET +
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
(this_plic->target_hartid << PLIC_CLAIM_SHIFT_PER_TARGET));
return *claim_addr;
@ -117,10 +113,9 @@ plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){
void PLIC_complete_interrupt(plic_instance_t * this_plic, plic_source source){
unsigned long hart_id = read_csr(mhartid);
volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr +
PLIC_CLAIM_OFFSET +
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
(this_plic->target_hartid << PLIC_CLAIM_SHIFT_PER_TARGET));
*claim_addr = source;
}

View File

@ -14,7 +14,7 @@ typedef struct __plic_instance_t
uint32_t num_sources;
uint32_t num_priorities;
uint32_t target_hartid;
} plic_instance_t;
typedef uint32_t plic_source;
@ -25,7 +25,8 @@ void PLIC_init (
plic_instance_t * this_plic,
uintptr_t base_addr,
uint32_t num_sources,
uint32_t num_priorities
uint32_t num_priorities,
uint32_t target_hartid
);
void PLIC_set_threshold (plic_instance_t * this_plic,

View File

@ -8,18 +8,14 @@ all: $(TARGET)
include $(BSP_BASE)/libwrap/libwrap.mk
BOARD ?= freedom-e300-hifive1
ENV_DIR = $(BSP_BASE)/env
PLATFORM_DIR = $(ENV_DIR)/$(BOARD)
#TARGET_FLAVOR := -march=rv32imac -mabi=ilp32 -mcmodel=medany -msmall-data-limit=8 -x assembler-with-cpp
TARGET_FLAVOR := -march=rv32i -mabi=ilp32
ASM_SRCS += $(ENV_DIR)/start.S
ASM_SRCS += $(ENV_DIR)/entry.S
C_SRCS += $(PLATFORM_DIR)/init.c
LINKER_SCRIPT := $(PLATFORM_DIR)/link.lds
LINKER_SCRIPT := $(PLATFORM_DIR)/$(LINK_TARGET).lds
INCLUDES += -I$(BSP_BASE)/include
INCLUDES += -I$(BSP_BASE)/drivers/
@ -28,35 +24,43 @@ INCLUDES += -I$(PLATFORM_DIR)
TOOL_DIR ?= $(BSP_BASE)/../toolchain/bin
CC := $(TOOL_DIR)/riscv64-unknown-elf-gcc ${TARGET_FLAVOR}
AR := $(TOOL_DIR)/riscv64-unknown-elf-ar
OBJDUMP := $(TOOL_DIR)/riscv64-unknown-elf-objdump
LDFLAGS += -T $(LINKER_SCRIPT) -nostartfiles
LDFLAGS += -L$(ENV_DIR)
LDFLAGS += -L$(ENV_DIR) --specs=nano.specs
ASM_OBJS := $(ASM_SRCS:.S=.o)
C_OBJS := $(C_SRCS:.c=.o)
C_OBJS := $(C_SRCS:.c=.o)
CXX_OBJS := $(CXX_SRCS:.cpp=.o)
LINK_OBJS += $(ASM_OBJS) $(C_OBJS)
LINK_OBJS += $(ASM_OBJS) $(C_OBJS) $(CXX_OBJS)
LINK_DEPS += $(LINKER_SCRIPT)
CLEAN_OBJS += $(TARGET) $(LINK_OBJS)
CFLAGS += -g
CFLAGS += -march=$(RISCV_ARCH)
CFLAGS += -mabi=$(RISCV_ABI)
CFLAGS += -mcmodel=medany
TRIPLET?=riscv64-unknown-elf
CXX=$(TOOL_DIR)/$(TRIPLET)-c++
CC=$(TOOL_DIR)/$(TRIPLET)-gcc
LD=$(TOOL_DIR)/$(TRIPLET)-gcc
AR=$(TOOL_DIR)/$(TRIPLET)-ar
$(TARGET): $(LINK_OBJS) $(LINK_DEPS)
$(CC) $(CFLAGS) $(INCLUDES) $(LINK_OBJS) -o $@ $(LDFLAGS)
$(OBJDUMP) -d $(TARGET) > $(TARGET).dis
$(LD) $(LINK_OBJS) $(LDFLAGS) $(LIBWRAP) -o $@
$(ASM_OBJS): %.o: %.S $(HEADERS)
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
$(C_OBJS): %.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(INCLUDES) -include sys/cdefs.h -c -o $@ $<
$(CXX_OBJS): %.o: %.cpp $(HEADERS)
$(CXX) $(CFLAGS) $(CXXFLAGS) $(INCLUDES) -include sys/cdefs.h -c -o $@ $<
.PHONY: clean
clean:
rm -f $(CLEAN_OBJS)
rm -f $(CLEAN_OBJS) $(LIBWRAP)
endif # _SIFIVE_MK_COMMON

161
raven/bsp/env/coreip-e2-arty/flash.lds vendored Normal file
View File

@ -0,0 +1,161 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 64K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash :flash
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash :flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash :flash
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >flash AT>flash :flash
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash :flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash :flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash :flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash :flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash :flash
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash :flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash :ram_init
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram :ram
}

98
raven/bsp/env/coreip-e2-arty/init.c vendored Normal file
View File

@ -0,0 +1,98 @@
//See LICENSE for license details.
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include "platform.h"
#include "encoding.h"
#define CPU_FREQ 32000000
#define XSTR(x) #x
#define STR(x) XSTR(x)
extern int main(int argc, char** argv);
unsigned long get_cpu_freq()
{
return CPU_FREQ;
}
unsigned long get_timer_freq()
{
return get_cpu_freq();
}
uint64_t get_timer_value()
{
#if __riscv_xlen == 32
while (1) {
uint32_t hi = read_csr(mcycleh);
uint32_t lo = read_csr(mcycle);
if (hi == read_csr(mcycleh))
return ((uint64_t)hi << 32) | lo;
}
#else
return read_csr(mcycle);
#endif
}
static void uart_init(size_t baud_rate)
{
UART0_REG(UART_REG_DIV) = (get_cpu_freq() ) / baud_rate - 1;
UART0_REG(UART_REG_TXCTRL) |= UART_TXEN;
}
typedef void (*interrupt_function_ptr_t) (void);
interrupt_function_ptr_t localISR[CLIC_NUM_INTERRUPTS] __attribute__((aligned(64)));
void trap_entry(void) __attribute__((interrupt, aligned(64)));
void trap_entry(void)
{
unsigned long mcause = read_csr(mcause);
unsigned long mepc = read_csr(mepc);
if (mcause & MCAUSE_INT) {
localISR[mcause & MCAUSE_CAUSE] ();
} else {
while(1);
}
}
#ifdef CLIC_DIRECT
#else
void default_handler(void)__attribute__((interrupt));;
#endif
void default_handler(void)
{
puts("default handler\n");
while(1);
}
void _init()
{
#ifndef NO_INIT
uart_init(115200);
puts("core freq at " STR(CPU_FREQ) " Hz\n");
//initialize vector table
int i=0;
while(i<CLIC_NUM_INTERRUPTS) {
localISR[i++] = default_handler;
}
write_csr(mtvt, localISR);
#ifdef CLIC_DIRECT
write_csr(mtvec, ((unsigned long)&trap_entry | MTVEC_CLIC));
#else
write_csr(mtvec, ((unsigned long)&trap_entry | MTVEC_CLIC_VECT));
#endif
#endif
}
void _fini()
{
}

View File

@ -0,0 +1,31 @@
# JTAG adapter setup
adapter_khz 10000
interface ftdi
ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H"
ftdi_vid_pid 0x15ba 0x002a
ftdi_layout_init 0x0808 0x0a1b
ftdi_layout_signal nSRST -oe 0x0200
#ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100
ftdi_layout_signal LED -data 0x0800
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000001
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
# Un-comment these two flash lines if you have a SPI flash and want to write
# it.
flash bank spi0 fespi 0x40000000 0 0 0 $_TARGETNAME.0 0x20004000
init
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
}
halt
#flash protect 0 64 last off
echo "Ready for Remote Connections"

98
raven/bsp/env/coreip-e2-arty/platform.h vendored Normal file
View File

@ -0,0 +1,98 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PLATFORM_H
#define _SIFIVE_PLATFORM_H
// Some things missing from the official encoding.h
#if __riscv_xlen == 32
#define MCAUSE_INT 0x80000000UL
#define MCAUSE_CAUSE 0x000003FFUL
#else
#define MCAUSE_INT 0x8000000000000000UL
#define MCAUSE_CAUSE 0x00000000000003FFUL
#endif
#define MTVEC_DIRECT 0X00
#define MTVEC_VECTORED 0x01
#define MTVEC_CLIC 0x02
#define MTVEC_CLIC_VECT 0X03
#include "sifive/const.h"
#include "sifive/devices/gpio.h"
#include "sifive/devices/clint.h"
#include "sifive/devices/clic.h"
#include "sifive/devices/pwm.h"
#include "sifive/devices/spi.h"
#include "sifive/devices/uart.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
// Memory map
#define CLINT_CTRL_ADDR _AC(0x02000000,UL)
#define CLIC_HART0_ADDR _AC(0x02800000,UL)
#define GPIO_CTRL_ADDR _AC(0x20002000,UL)
#define PWM0_CTRL_ADDR _AC(0x20005000,UL)
#define RAM_MEM_ADDR _AC(0x80000000,UL)
#define RAM_MEM_SIZE _AC(0x10000,UL)
#define SPI0_CTRL_ADDR _AC(0x20004000,UL)
#define SPI0_MEM_ADDR _AC(0x40000000,UL)
#define SPI0_MEM_SIZE _AC(0x20000000,UL)
#define TESTBENCH_MEM_ADDR _AC(0x20000000,UL)
#define TESTBENCH_MEM_SIZE _AC(0x10000000,UL)
//#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL)
#define UART0_CTRL_ADDR _AC(0x20000000,UL)
// IOF masks
// Interrupt numbers
#define RESERVED_INT_BASE 0
#define UART0_INT_BASE 1
#define EXTERNAL_INT_BASE 2
#define SPI0_INT_BASE 6
#define GPIO_INT_BASE 7
#define PWM0_INT_BASE 23
// Helper functions
#define _REG64(p, i) (*(volatile uint64_t *)((p) + (i)))
#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i)))
#define _REG16(p, i) (*(volatile uint16_t *)((p) + (i)))
#define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); }
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define CLIC0_REG(offset) _REG32(CLIC_HART0_ADDR, offset)
#define CLIC0_REG8(offset) (*(volatile uint8_t *)((CLIC_HART0_ADDR) + (offset)))
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define CLIC0_REG64(offset) _REG64(CLIC_HART0_ADDR, offset)
#define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset)
#define PWM0_REG64(offset) _REG64(PWM0_CTRL_ADDR, offset)
#define SPI0_REG64(offset) _REG64(SPI0_CTRL_ADDR, offset)
#define UART0_REG64(offset) _REG64(UART0_CTRL_ADDR, offset)
// Misc
#define NUM_GPIO 16
#define CLIC_NUM_INTERRUPTS 28 + 16
#ifdef E20
#define CLIC_CONFIG_BITS 2
#else
#define CLIC_CONFIG_BITS 4
#endif
#define HAS_BOARD_BUTTONS
#include "coreplexip-arty.h"
unsigned long get_cpu_freq(void);
unsigned long get_timer_freq(void);
uint64_t get_timer_value(void);
#endif /* _SIFIVE_PLATFORM_H */

View File

@ -0,0 +1,3 @@
# Describes the CPU on this board to the rest of the SDK.
RISCV_ARCH := rv32imac
RISCV_ABI := ilp32

View File

@ -0,0 +1,157 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x80008000, LENGTH = 32K
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 32K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash :flash
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash :flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash :flash
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash :flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash :flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash :flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash :flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash :flash
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash :flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash :ram_init
.data :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram :ram
}

161
raven/bsp/env/coreip-e2-arty/tim.lds vendored Normal file
View File

@ -0,0 +1,161 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 64K
}
PHDRS
{
ram PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >ram AT>ram :ram
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >ram AT>ram :ram
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >ram AT>ram :ram
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >ram AT>ram :ram
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >ram AT>ram :ram
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >ram AT>ram :ram
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >ram AT>ram :ram
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >ram AT>ram :ram
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >ram AT>ram :ram
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >ram AT>ram :ram
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>ram :ram_init
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>ram :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack :
{
. = ALIGN(8);
. += __stack_size;
PROVIDE( _sp = . );
PROVIDE( _heap_end = . );
} >ram AT>ram :ram
}

102
raven/bsp/env/coreplexip-arty.h vendored Normal file
View File

@ -0,0 +1,102 @@
// See LICENSE for license details.
#ifndef _SIFIVE_COREPLEXIP_ARTY_H
#define _SIFIVE_COREPLEXIP_ARTY_H
#include <stdint.h>
/****************************************************************************
* GPIO Connections
*****************************************************************************/
// These are the GPIO bit offsets for the directly driven
// RGB LEDs on the Freedom Exx Coreplex IP Evaluation Arty FPGA Dev Kit.
// Additional RGB LEDs are driven by the 3 PWM outputs.
#define RED_LED_OFFSET 0
#define GREEN_LED_OFFSET 1
#define BLUE_LED_OFFSET 2
// Switch 3 is used as a GPIO input. (Switch 0 is used to set
// the reset vector, the other switches are unused).
#define SW_3_OFFSET 3
// These are the buttons which are mapped as inputs.
#define HAS_BOARD_BUTTONS
#define BUTTON_0_OFFSET 4
#define BUTTON_1_OFFSET 5
#define BUTTON_2_OFFSET 6
#define BUTTON_3_OFFSET 7
// These are the bit offsets for the different GPIO pins
// mapped onto the PMOD A header.
#define JA_0_OFFSET 8
#define JA_1_OFFSET 9
#define JA_2_OFFSET 10
#define JA_3_OFFSET 11
#define JA_4_OFFSET 12
#define JA_5_OFFSET 13
#define JA_6_OFFSET 14
#define JA_7_OFFSET 15
// The below gives a mapping between global interrupt
// sources and their number. Note that on the coreplex
// deliverable, the io_global_interrupts go directly into
// the PLIC. The evaluation image on the FPGA mimics a
// system with peripheral devices which are driving the
// global interrupt lines.
// So, on this image, in order to get an interrupt from
// e.g. pressing BUTTON_0:
// 1) Steps which are external to the delivery coreplex:
// a) The corresponding GPIO pin must be configured as in input
// b) The "interrupt on fall" bit must be set for the GPIO pin
// 2) Steps which would also need to be performed for the delivery coreplex:
// a) The corresponding global interrupt, priority, and threshold must be configured in the PLIC.
// b) The external interrupt bit must be enabled in MSTATUS
// c) Interrupts must be enabled globally in the core.
// Any of the above GPIO pins can be used as global interrupt
// sources by adding their offset to the INT_GPIO_BASE.
// For example, the buttons are shown here:
#define INT_DEVICE_BUTTON_0 (GPIO_INT_BASE + BUTTON_0_OFFSET)
#define INT_DEVICE_BUTTON_1 (GPIO_INT_BASE + BUTTON_1_OFFSET)
#define INT_DEVICE_BUTTON_2 (GPIO_INT_BASE + BUTTON_2_OFFSET)
#define INT_DEVICE_BUTTON_3 (GPIO_INT_BASE + BUTTON_3_OFFSET)
// In addition, the Switches are mapped directly to
// the PLIC (without going through the GPIO Peripheral).
#define INT_EXT_DEVICE_SW_0 (EXTERNAL_INT_BASE + 0)
#define INT_EXT_DEVICE_SW_1 (EXTERNAL_INT_BASE + 1)
#define INT_EXT_DEVICE_SW_2 (EXTERNAL_INT_BASE + 2)
#define INT_EXT_DEVICE_SW_3 (EXTERNAL_INT_BASE + 3)
// This gives the mapping from inputs to LOCAL interrupts.
#define LOCAL_INT_SW_0 0
#define LOCAL_INT_SW_1 1
#define LOCAL_INT_SW_2 2
#define LOCAL_INT_SW_3 3
#define LOCAL_INT_BTN_0 4
#define LOCAL_INT_BTN_1 5
#define LOCAL_INT_BTN_2 6
#define LOCAL_INT_BTN_3 7
#define LOCAL_INT_JA_0 8
#define LOCAL_INT_JA_1 9
#define LOCAL_INT_JA_2 10
#define LOCAL_INT_JA_3 11
#define LOCAL_INT_JA_4 12
#define LOCAL_INT_JA_5 13
#define LOCAL_INT_JA_6 14
#define LOCAL_INT_JA_7 15
#define RTC_FREQ 32768
void write_hex(int fd, unsigned long int hex);
#endif /* _SIFIVE_COREPLEXIP_ARTY_H */

View File

@ -0,0 +1,157 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash :flash
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash :flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash :flash
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash :flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash :flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash :flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash :flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash :flash
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash :flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash :ram_init
.data :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram :ram
}

View File

@ -0,0 +1,161 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash :flash
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash :flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash :flash
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >flash AT>flash :flash
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash :flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash :flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash :flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash :flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash :flash
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash :flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash :ram_init
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram :ram
}

122
raven/bsp/env/coreplexip-e31-arty/init.c vendored Normal file
View File

@ -0,0 +1,122 @@
//See LICENSE for license details.
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include "platform.h"
#include "encoding.h"
#define CPU_FREQ 65000000
#define XSTR(x) #x
#define STR(x) XSTR(x)
#ifndef VECT_IRQ
#define TRAP_ENTRY trap_entry
#else
#define TRAP_ENTRY vtrap_entry
#endif
extern int main(int argc, char** argv);
extern void TRAP_ENTRY();
unsigned long get_cpu_freq()
{
return CPU_FREQ;
}
unsigned long get_timer_freq()
{
return get_cpu_freq();
}
uint64_t get_timer_value()
{
#if __riscv_xlen == 32
while (1) {
uint32_t hi = read_csr(mcycleh);
uint32_t lo = read_csr(mcycle);
if (hi == read_csr(mcycleh))
return ((uint64_t)hi << 32) | lo;
}
#else
return read_csr(mcycle);
#endif
}
static void uart_init(size_t baud_rate)
{
UART0_REG(UART_REG_DIV) = (get_cpu_freq() / 2) / baud_rate - 1;
UART0_REG(UART_REG_TXCTRL) |= UART_TXEN;
}
#ifdef USE_PLIC
extern void handle_m_ext_interrupt();
#endif
#ifdef USE_M_TIME
extern void handle_m_time_interrupt();
#endif
#ifdef USE_LOCAL_ISR
typedef void (*my_interrupt_function_ptr_t) (void);
extern my_interrupt_function_ptr_t localISR[];
#endif
#ifndef VECT_IRQ
uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) __attribute__((noinline));
uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)
{
if (0){
#ifdef USE_PLIC
// External Machine-Level interrupt from PLIC
} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) {
handle_m_ext_interrupt();
#endif
#ifdef USE_M_TIME
// External Machine-Level interrupt from PLIC
} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){
handle_m_time_interrupt();
#endif
#ifdef USE_LOCAL_ISR
} else if (mcause & MCAUSE_INT) {
localISR[mcause & MCAUSE_CAUSE] ();
#endif
}
else {
write(1, "Unhandled Trap:\n", 16);
_exit(1 + mcause);
}
return epc;
}
#endif
#ifdef USE_CLIC
void trap_entry(void) __attribute__((interrupt("SiFive-CLIC-preemptible"), aligned(64)));
void trap_entry(void)
{
unsigned long mcause = read_csr(mcause);
unsigned long mepc = read_csr(mepc);
handle_trap(mcause, mepc);
}
#endif
void _init()
{
#ifndef NO_INIT
uart_init(115200);
puts("core freq at " STR(CPU_FREQ) " Hz\n");
#ifdef USE_CLIC
write_csr(mtvec, ((unsigned long)&trap_entry | MTVEC_CLIC));
#else
write_csr(mtvec, ((unsigned long)&TRAP_ENTRY | MTVEC_VECTORED));
#endif
#endif
}
void _fini()
{
}

View File

@ -0,0 +1,31 @@
# JTAG adapter setup
adapter_khz 10000
interface ftdi
ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H"
ftdi_vid_pid 0x15ba 0x002a
ftdi_layout_init 0x0808 0x0a1b
ftdi_layout_signal nSRST -oe 0x0200
#ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100
ftdi_layout_signal LED -data 0x0800
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000001
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
# Un-comment these two flash lines if you have a SPI flash and want to write
# it.
flash bank spi0 fespi 0x40000000 0 0 0 $_TARGETNAME.0 0x20004000
init
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
}
halt
#flash protect 0 64 last off
echo "Ready for Remote Connections"

View File

@ -0,0 +1,100 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PLATFORM_H
#define _SIFIVE_PLATFORM_H
// Some things missing from the official encoding.h
#if __riscv_xlen == 32
#define MCAUSE_INT 0x80000000UL
#define MCAUSE_CAUSE 0x000003FFUL
#else
#define MCAUSE_INT 0x8000000000000000UL
#define MCAUSE_CAUSE 0x00000000000003FFUL
#endif
#ifdef VECT_IRQ
#define MTVEC_VECTORED 0x01
#else
#define MTVEC_VECTORED 0x00
#endif
#define MTVEC_CLIC 0x02
#define IRQ_M_LOCAL 16
#define MIP_MLIP(x) (1 << (IRQ_M_LOCAL + x))
#include "sifive/const.h"
#include "sifive/devices/clint.h"
#include "sifive/devices/gpio.h"
#include "sifive/devices/plic.h"
#include "sifive/devices/pwm.h"
#include "sifive/devices/spi.h"
#include "sifive/devices/uart.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
// Memory map
#define CLINT_CTRL_ADDR _AC(0x02000000,UL)
#define GPIO_CTRL_ADDR _AC(0x20002000,UL)
#define PLIC_CTRL_ADDR _AC(0x0C000000,UL)
#define PWM0_CTRL_ADDR _AC(0x20005000,UL)
#define RAM_MEM_ADDR _AC(0x80000000,UL)
#define RAM_MEM_SIZE _AC(0x10000,UL)
#define SPI0_CTRL_ADDR _AC(0x20004000,UL)
#define SPI0_MEM_ADDR _AC(0x40000000,UL)
#define SPI0_MEM_SIZE _AC(0x20000000,UL)
#define TESTBENCH_MEM_ADDR _AC(0x20000000,UL)
#define TESTBENCH_MEM_SIZE _AC(0x10000000,UL)
#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL)
#define UART0_CTRL_ADDR _AC(0x20000000,UL)
// IOF masks
// Interrupt numbers
#define RESERVED_INT_BASE 0
#define UART0_INT_BASE 1
#define EXTERNAL_INT_BASE 2
#define SPI0_INT_BASE 6
#define GPIO_INT_BASE 7
#define PWM0_INT_BASE 23
// Helper functions
#define _REG64(p, i) (*(volatile uint64_t *)((p) + (i)))
#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i)))
#define _REG16(p, i) (*(volatile uint16_t *)((p) + (i)))
// Bulk set bits in `reg` to either 0 or 1.
// E.g. SET_BITS(MY_REG, 0x00000007, 0) would generate MY_REG &= ~0x7
// E.g. SET_BITS(MY_REG, 0x00000007, 1) would generate MY_REG |= 0x7
#define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); }
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset)
#define TRAPVEC_TABLE_REG(offset) _REG32(TRAPVEC_TABLE_CTRL_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset)
#define CLINT_REG64(offset) _REG64(CLINT_CTRL_ADDR, offset)
#define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset)
#define PLIC_REG64(offset) _REG64(PLIC_CTRL_ADDR, offset)
#define PWM0_REG64(offset) _REG64(PWM0_CTRL_ADDR, offset)
#define SPI0_REG64(offset) _REG64(SPI0_CTRL_ADDR, offset)
#define TRAPVEC_TABLE_REG64(offset) _REG64(TRAPVEC_TABLE_CTRL_ADDR, offset)
#define UART0_REG64(offset) _REG64(UART0_CTRL_ADDR, offset)
// Misc
#define NUM_GPIO 16
#define PLIC_NUM_INTERRUPTS 28
#define PLIC_NUM_PRIORITIES 7
#define HAS_BOARD_BUTTONS
#include "coreplexip-arty.h"
unsigned long get_cpu_freq(void);
unsigned long get_timer_freq(void);
uint64_t get_timer_value(void);
#endif /* _SIFIVE_PLATFORM_H */

View File

@ -0,0 +1,161 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
PHDRS
{
ram PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >ram AT>ram :ram
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >ram AT>ram :ram
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >ram AT>ram :ram
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >ram AT>ram :ram
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >ram AT>ram :ram
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >ram AT>ram :ram
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >ram AT>ram :ram
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >ram AT>ram :ram
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >ram AT>ram :ram
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >ram AT>ram :ram
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>ram :ram_init
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>ram :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack :
{
. = ALIGN(8);
. += __stack_size;
PROVIDE( _sp = . );
PROVIDE( _heap_end = . );
} >ram AT>ram :ram
}

View File

@ -0,0 +1,3 @@
# Describes the CPU on this board to the rest of the SDK.
RISCV_ARCH := rv32imac
RISCV_ABI := ilp32

View File

@ -0,0 +1,157 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash :flash
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash :flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash :flash
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash :flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash :flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash :flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash :flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash :flash
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash :flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash :ram_init
.data :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram :ram
}

View File

@ -0,0 +1,161 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
PHDRS
{
flash PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash :flash
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash :flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash :flash
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >flash AT>flash :flash
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash :flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash :flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash :flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash :flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash :flash
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash :flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash :ram_init
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram :ram
}

122
raven/bsp/env/coreplexip-e51-arty/init.c vendored Normal file
View File

@ -0,0 +1,122 @@
//See LICENSE for license details.
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include "platform.h"
#include "encoding.h"
#define CPU_FREQ 65000000
#define XSTR(x) #x
#define STR(x) XSTR(x)
#ifndef VECT_IRQ
#define TRAP_ENTRY trap_entry
#else
#define TRAP_ENTRY vtrap_entry
#endif
extern int main(int argc, char** argv);
extern void TRAP_ENTRY();
unsigned long get_cpu_freq()
{
return CPU_FREQ;
}
unsigned long get_timer_freq()
{
return get_cpu_freq();
}
uint64_t get_timer_value()
{
#if __riscv_xlen == 32
while (1) {
uint32_t hi = read_csr(mcycleh);
uint32_t lo = read_csr(mcycle);
if (hi == read_csr(mcycleh))
return ((uint64_t)hi << 32) | lo;
}
#else
return read_csr(mcycle);
#endif
}
static void uart_init(size_t baud_rate)
{
UART0_REG(UART_REG_DIV) = (get_cpu_freq() / 2) / baud_rate - 1;
UART0_REG(UART_REG_TXCTRL) |= UART_TXEN;
}
#ifdef USE_PLIC
extern void handle_m_ext_interrupt();
#endif
#ifdef USE_M_TIME
extern void handle_m_time_interrupt();
#endif
#ifdef USE_LOCAL_ISR
typedef void (*my_interrupt_function_ptr_t) (void);
extern my_interrupt_function_ptr_t localISR[];
#endif
#ifndef VECT_IRQ
uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) __attribute__((noinline));
uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)
{
if (0){
#ifdef USE_PLIC
// External Machine-Level interrupt from PLIC
} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) {
handle_m_ext_interrupt();
#endif
#ifdef USE_M_TIME
// External Machine-Level interrupt from PLIC
} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){
handle_m_time_interrupt();
#endif
#ifdef USE_LOCAL_ISR
} else if (mcause & MCAUSE_INT) {
localISR[mcause & MCAUSE_CAUSE] ();
#endif
}
else {
write(1, "Unhandled Trap:\n", 16);
_exit(1 + mcause);
}
return epc;
}
#endif
#ifdef USE_CLIC
void trap_entry(void) __attribute__((interrupt("SiFive-CLIC-preemptible"), aligned(64)));
void trap_entry(void)
{
unsigned long mcause = read_csr(mcause);
unsigned long mepc = read_csr(mepc);
handle_trap(mcause, mepc);
}
#endif
void _init()
{
#ifndef NO_INIT
uart_init(115200);
puts("core freq at " STR(CPU_FREQ) " Hz\n");
#ifdef USE_CLIC
write_csr(mtvec, ((unsigned long)&trap_entry | MTVEC_CLIC));
#else
write_csr(mtvec, ((unsigned long)&TRAP_ENTRY | MTVEC_VECTORED));
#endif
#endif
}
void _fini()
{
}

View File

@ -0,0 +1,31 @@
# JTAG adapter setup
adapter_khz 10000
interface ftdi
ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H"
ftdi_vid_pid 0x15ba 0x002a
ftdi_layout_init 0x0808 0x0a1b
ftdi_layout_signal nSRST -oe 0x0200
#ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100
ftdi_layout_signal LED -data 0x0800
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000001
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
# Un-comment these two flash lines if you have a SPI flash and want to write
# it.
flash bank spi0 fespi 0x40000000 0 0 0 $_TARGETNAME.0 0x20004000
init
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
}
halt
#flash protect 0 64 last off
echo "Ready for Remote Connections"

View File

@ -0,0 +1,100 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PLATFORM_H
#define _SIFIVE_PLATFORM_H
// Some things missing from the official encoding.h
#if __riscv_xlen == 32
#define MCAUSE_INT 0x80000000UL
#define MCAUSE_CAUSE 0x000003FFUL
#else
#define MCAUSE_INT 0x8000000000000000UL
#define MCAUSE_CAUSE 0x00000000000003FFUL
#endif
#ifdef VECT_IRQ
#define MTVEC_VECTORED 0x01
#else
#define MTVEC_VECTORED 0x00
#endif
#define MTVEC_CLIC 0x02
#define IRQ_M_LOCAL 16
#define MIP_MLIP(x) (1 << (IRQ_M_LOCAL + x))
#include "sifive/const.h"
#include "sifive/devices/clint.h"
#include "sifive/devices/gpio.h"
#include "sifive/devices/plic.h"
#include "sifive/devices/pwm.h"
#include "sifive/devices/spi.h"
#include "sifive/devices/uart.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
// Memory map
#define CLINT_CTRL_ADDR _AC(0x02000000,UL)
#define GPIO_CTRL_ADDR _AC(0x20002000,UL)
#define PLIC_CTRL_ADDR _AC(0x0C000000,UL)
#define PWM0_CTRL_ADDR _AC(0x20005000,UL)
#define RAM_MEM_ADDR _AC(0x80000000,UL)
#define RAM_MEM_SIZE _AC(0x10000,UL)
#define SPI0_CTRL_ADDR _AC(0x20004000,UL)
#define SPI0_MEM_ADDR _AC(0x40000000,UL)
#define SPI0_MEM_SIZE _AC(0x20000000,UL)
#define TESTBENCH_MEM_ADDR _AC(0x20000000,UL)
#define TESTBENCH_MEM_SIZE _AC(0x10000000,UL)
#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL)
#define UART0_CTRL_ADDR _AC(0x20000000,UL)
// IOF masks
// Interrupt numbers
#define RESERVED_INT_BASE 0
#define UART0_INT_BASE 1
#define EXTERNAL_INT_BASE 2
#define SPI0_INT_BASE 6
#define GPIO_INT_BASE 7
#define PWM0_INT_BASE 23
// Helper functions
#define _REG64(p, i) (*(volatile uint64_t *)((p) + (i)))
#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i)))
#define _REG16(p, i) (*(volatile uint16_t *)((p) + (i)))
// Bulk set bits in `reg` to either 0 or 1.
// E.g. SET_BITS(MY_REG, 0x00000007, 0) would generate MY_REG &= ~0x7
// E.g. SET_BITS(MY_REG, 0x00000007, 1) would generate MY_REG |= 0x7
#define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); }
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset)
#define TRAPVEC_TABLE_REG(offset) _REG32(TRAPVEC_TABLE_CTRL_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset)
#define CLINT_REG64(offset) _REG64(CLINT_CTRL_ADDR, offset)
#define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset)
#define PLIC_REG64(offset) _REG64(PLIC_CTRL_ADDR, offset)
#define PWM0_REG64(offset) _REG64(PWM0_CTRL_ADDR, offset)
#define SPI0_REG64(offset) _REG64(SPI0_CTRL_ADDR, offset)
#define TRAPVEC_TABLE_REG64(offset) _REG64(TRAPVEC_TABLE_CTRL_ADDR, offset)
#define UART0_REG64(offset) _REG64(UART0_CTRL_ADDR, offset)
// Misc
#define NUM_GPIO 16
#define PLIC_NUM_INTERRUPTS 28
#define PLIC_NUM_PRIORITIES 7
#define HAS_BOARD_BUTTONS
#include "coreplexip-arty.h"
unsigned long get_cpu_freq(void);
unsigned long get_timer_freq(void);
uint64_t get_timer_value(void);
#endif /* _SIFIVE_PLATFORM_H */

View File

@ -0,0 +1,161 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
PHDRS
{
ram PT_LOAD;
ram_init PT_LOAD;
ram PT_NULL;
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >ram AT>ram :ram
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >ram AT>ram :ram
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >ram AT>ram :ram
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >ram AT>ram :ram
. = ALIGN(4);
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >ram AT>ram :ram
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >ram AT>ram :ram
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >ram AT>ram :ram
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >ram AT>ram :ram
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >ram AT>ram :ram
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >ram AT>ram :ram
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>ram :ram_init
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>ram :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . );
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram :ram
. = ALIGN(8);
PROVIDE( _end = . );
PROVIDE( end = . );
.stack :
{
. = ALIGN(8);
. += __stack_size;
PROVIDE( _sp = . );
PROVIDE( _heap_end = . );
} >ram AT>ram :ram
}

View File

@ -0,0 +1,3 @@
# Describes the CPU on this board to the rest of the SDK.
RISCV_ARCH := rv64imac
RISCV_ABI := lp64

View File

@ -8,6 +8,7 @@
.section .text.entry
.align 2
.weak trap_entry
.global trap_entry
trap_entry:
addi sp, sp, -32*REGBYTES

View File

@ -120,11 +120,11 @@ SECTIONS
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
} >ram AT>flash :ram_init
.srodata :
{
PROVIDE( _gp = . + 0x800 );
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
@ -132,12 +132,6 @@ SECTIONS
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
.sdata :
{
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );

View File

@ -20,21 +20,21 @@
* Platform definitions
*****************************************************************************/
#define TRAPVEC_TABLE_BASE_ADDR _AC(0x00001010,UL)
#define CLINT_BASE_ADDR _AC(0x02000000,UL)
#define PLIC_BASE_ADDR _AC(0x0C000000,UL)
#define AON_BASE_ADDR _AC(0x10000000,UL)
#define GPIO_BASE_ADDR _AC(0x10012000,UL)
#define UART0_BASE_ADDR _AC(0x10013000,UL)
#define SPI0_BASE_ADDR _AC(0x10014000,UL)
#define PWM0_BASE_ADDR _AC(0x10015000,UL)
#define UART1_BASE_ADDR _AC(0x10023000,UL)
#define SPI1_BASE_ADDR _AC(0x10024000,UL)
#define PWM1_BASE_ADDR _AC(0x10025000,UL)
#define SPI2_BASE_ADDR _AC(0x10034000,UL)
#define PWM2_BASE_ADDR _AC(0x10035000,UL)
#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL)
#define CLINT_CTRL_ADDR _AC(0x02000000,UL)
#define PLIC_CTRL_ADDR _AC(0x0C000000,UL)
#define AON_CTRL_ADDR _AC(0x10000000,UL)
#define GPIO_CTRL_ADDR _AC(0x10012000,UL)
#define UART0_CTRL_ADDR _AC(0x10013000,UL)
#define SPI0_CTRL_ADDR _AC(0x10014000,UL)
#define PWM0_CTRL_ADDR _AC(0x10015000,UL)
#define UART1_CTRL_ADDR _AC(0x10023000,UL)
#define SPI1_CTRL_ADDR _AC(0x10024000,UL)
#define PWM1_CTRL_ADDR _AC(0x10025000,UL)
#define SPI2_CTRL_ADDR _AC(0x10034000,UL)
#define PWM2_CTRL_ADDR _AC(0x10035000,UL)
#define SPI0_MMAP_ADDR _AC(0x20000000,UL)
#define MEM_BASE_ADDR _AC(0x80000000,UL)
#define MEM_CTRL_ADDR _AC(0x80000000,UL)
// IOF Mappings
#define IOF0_SPI1_MASK _AC(0x000007FC,UL)
@ -91,20 +91,19 @@
// Helper functions
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
#define AON_REG(offset) _REG32(AON_BASE_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_BASE_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_BASE_ADDR, offset)
#define OTP_REG(offset) _REG32(OTP_BASE_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_BASE_ADDR, offset)
#define PRCI_REG(offset) _REG32(PRCI_BASE_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_BASE_ADDR, offset)
#define PWM1_REG(offset) _REG32(PWM1_BASE_ADDR, offset)
#define PWM2_REG(offset) _REG32(PWM2_BASE_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_BASE_ADDR, offset)
#define SPI1_REG(offset) _REG32(SPI1_BASE_ADDR, offset)
#define SPI2_REG(offset) _REG32(SPI2_BASE_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_BASE_ADDR, offset)
#define UART1_REG(offset) _REG32(UART1_BASE_ADDR, offset)
#define AON_REG(offset) _REG32(AON_CTRL_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
#define OTP_REG(offset) _REG32(OTP_CTRL_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset)
#define PWM1_REG(offset) _REG32(PWM1_CTRL_ADDR, offset)
#define PWM2_REG(offset) _REG32(PWM2_CTRL_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset)
#define SPI1_REG(offset) _REG32(SPI1_CTRL_ADDR, offset)
#define SPI2_REG(offset) _REG32(SPI2_CTRL_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset)
#define UART1_REG(offset) _REG32(UART1_CTRL_ADDR, offset)
// Misc

View File

@ -0,0 +1,3 @@
# Describes the CPU on this board to the rest of the SDK.
RISCV_ARCH := rv32imac
RISCV_ABI := ilp32

View File

@ -4,9 +4,8 @@ ENTRY( _start )
MEMORY
{
/*flash (rxai!w) : ORIGIN = 0x00000000, LENGTH = 1M*/
flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
PHDRS
@ -42,13 +41,6 @@ SECTIONS
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
} >flash AT>flash :flash
. = ALIGN(4);
.preinit_array :
@ -119,13 +111,16 @@ SECTIONS
.data :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
} >ram AT>flash :ram_init
.srodata :
{
PROVIDE( _gp = . + 0x800 );
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
@ -133,12 +128,6 @@ SECTIONS
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
.sdata :
{
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );

View File

@ -120,11 +120,11 @@ SECTIONS
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
} >ram AT>flash :ram_init
.srodata :
{
PROVIDE( _gp = . + 0x800 );
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
@ -132,12 +132,6 @@ SECTIONS
*(.srodata .srodata.*)
} >ram AT>flash :ram_init
.sdata :
{
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
} >ram AT>flash :ram_init
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );

View File

@ -10,14 +10,14 @@ extern void trap_entry();
static unsigned long mtime_lo(void)
{
return *(volatile unsigned long *)(CLINT_BASE_ADDR + CLINT_MTIME);
return *(volatile unsigned long *)(CLINT_CTRL_ADDR + CLINT_MTIME);
}
#ifdef __riscv32
static uint32_t mtime_hi(void)
{
return *(volatile uint32_t *)(CLINT_BASE_ADDR + CLINT_MTIME + 4);
return *(volatile uint32_t *)(CLINT_CTRL_ADDR + CLINT_MTIME + 4);
}
uint64_t get_timer_value()

View File

@ -23,25 +23,25 @@
*****************************************************************************/
// Memory map
#define MASKROM_BASE_ADDR _AC(0x00001000,UL)
#define TRAPVEC_TABLE_BASE_ADDR _AC(0x00001010,UL)
#define OTP_MMAP_ADDR _AC(0x00020000,UL)
#define CLINT_BASE_ADDR _AC(0x02000000,UL)
#define PLIC_BASE_ADDR _AC(0x0C000000,UL)
#define AON_BASE_ADDR _AC(0x10000000,UL)
#define PRCI_BASE_ADDR _AC(0x10008000,UL)
#define OTP_BASE_ADDR _AC(0x10010000,UL)
#define GPIO_BASE_ADDR _AC(0x10012000,UL)
#define UART0_BASE_ADDR _AC(0x10013000,UL)
#define SPI0_BASE_ADDR _AC(0x10014000,UL)
#define PWM0_BASE_ADDR _AC(0x10015000,UL)
#define UART1_BASE_ADDR _AC(0x10023000,UL)
#define SPI1_BASE_ADDR _AC(0x10024000,UL)
#define PWM1_BASE_ADDR _AC(0x10025000,UL)
#define SPI2_BASE_ADDR _AC(0x10034000,UL)
#define PWM2_BASE_ADDR _AC(0x10035000,UL)
#define SPI0_MMAP_ADDR _AC(0x20000000,UL)
#define MEM_BASE_ADDR _AC(0x80000000,UL)
#define MASKROM_MEM_ADDR _AC(0x00001000,UL)
#define TRAPVEC_TABLE_CTRL_ADDR _AC(0x00001010,UL)
#define OTP_MEM_ADDR _AC(0x00020000,UL)
#define CLINT_CTRL_ADDR _AC(0x02000000,UL)
#define PLIC_CTRL_ADDR _AC(0x0C000000,UL)
#define AON_CTRL_ADDR _AC(0x10000000,UL)
#define PRCI_CTRL_ADDR _AC(0x10008000,UL)
#define OTP_CTRL_ADDR _AC(0x10010000,UL)
#define GPIO_CTRL_ADDR _AC(0x10012000,UL)
#define UART0_CTRL_ADDR _AC(0x10013000,UL)
#define SPI0_CTRL_ADDR _AC(0x10014000,UL)
#define PWM0_CTRL_ADDR _AC(0x10015000,UL)
#define UART1_CTRL_ADDR _AC(0x10023000,UL)
#define SPI1_CTRL_ADDR _AC(0x10024000,UL)
#define PWM1_CTRL_ADDR _AC(0x10025000,UL)
#define SPI2_CTRL_ADDR _AC(0x10034000,UL)
#define PWM2_CTRL_ADDR _AC(0x10035000,UL)
#define SPI0_MEM_ADDR _AC(0x20000000,UL)
#define MEM_CTRL_ADDR _AC(0x80000000,UL)
// IOF masks
#define IOF0_SPI1_MASK _AC(0x000007FC,UL)
@ -100,20 +100,20 @@
// Helper functions
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
#define AON_REG(offset) _REG32(AON_BASE_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_BASE_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_BASE_ADDR, offset)
#define OTP_REG(offset) _REG32(OTP_BASE_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_BASE_ADDR, offset)
#define PRCI_REG(offset) _REG32(PRCI_BASE_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_BASE_ADDR, offset)
#define PWM1_REG(offset) _REG32(PWM1_BASE_ADDR, offset)
#define PWM2_REG(offset) _REG32(PWM2_BASE_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_BASE_ADDR, offset)
#define SPI1_REG(offset) _REG32(SPI1_BASE_ADDR, offset)
#define SPI2_REG(offset) _REG32(SPI2_BASE_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_BASE_ADDR, offset)
#define UART1_REG(offset) _REG32(UART1_BASE_ADDR, offset)
#define AON_REG(offset) _REG32(AON_CTRL_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
#define OTP_REG(offset) _REG32(OTP_CTRL_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
#define PRCI_REG(offset) _REG32(PRCI_CTRL_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset)
#define PWM1_REG(offset) _REG32(PWM1_CTRL_ADDR, offset)
#define PWM2_REG(offset) _REG32(PWM2_CTRL_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset)
#define SPI1_REG(offset) _REG32(SPI1_CTRL_ADDR, offset)
#define SPI2_REG(offset) _REG32(SPI2_CTRL_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset)
#define UART1_REG(offset) _REG32(UART1_CTRL_ADDR, offset)
// Misc

View File

@ -0,0 +1,3 @@
# Describes the CPU on this board to the rest of the SDK.
RISCV_ARCH := rv32imac
RISCV_ABI := ilp32

View File

@ -76,4 +76,6 @@
#define RTC_FREQ 32768
void write_hex(int fd, unsigned long int hex);
#endif /* _SIFIVE_HIFIVE1_H */

View File

@ -1,238 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include "platform.h"
#include "encoding.h"
extern int main(int argc, char** argv);
extern void trap_entry();
static unsigned long mtime_lo(void)
{
return *(volatile unsigned long *)(CLINT_BASE_ADDR + CLINT_MTIME);
}
#ifdef __riscv32
static uint32_t mtime_hi(void)
{
return *(volatile uint32_t *)(CLINT_BASE_ADDR + CLINT_MTIME + 4);
}
uint64_t get_timer_value()
{
while (1) {
uint32_t hi = mtime_hi();
uint32_t lo = mtime_lo();
if (hi == mtime_hi())
return ((uint64_t)hi << 32) | lo;
}
}
#else /* __riscv32 */
uint64_t get_timer_value()
{
return mtime_lo();
}
#endif
unsigned long get_timer_freq()
{
return 32768;
}
static void use_hfrosc(int div, int trim)
{
// Make sure the HFROSC is running at its default setting
PRCI_REG(PRCI_HFROSCCFG) = (ROSC_DIV(div) | ROSC_TRIM(trim) | ROSC_EN(1));
while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0) ;
PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(1);
}
static void use_pll(int refsel, int bypass, int r, int f, int q)
{
// Ensure that we aren't running off the PLL before we mess with it.
if (PRCI_REG(PRCI_PLLCFG) & PLL_SEL(1)) {
// Make sure the HFROSC is running at its default setting
use_hfrosc(4, 16);
}
// Set PLL Source to be HFXOSC if available.
uint32_t config_value = 0;
config_value |= PLL_REFSEL(refsel);
if (bypass) {
// Bypass
config_value |= PLL_BYPASS(1);
PRCI_REG(PRCI_PLLCFG) = config_value;
// If we don't have an HFXTAL, this doesn't really matter.
// Set our Final output divide to divide-by-1:
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
} else {
// In case we are executing from QSPI,
// (which is quite likely) we need to
// set the QSPI clock divider appropriately
// before boosting the clock frequency.
// Div = f_sck/2
SPI0_REG(SPI_REG_SCKDIV) = 8;
// Set DIV Settings for PLL
// Both HFROSC and HFXOSC are modeled as ideal
// 16MHz sources (assuming dividers are set properly for
// HFROSC).
// (Legal values of f_REF are 6-48MHz)
// Set DIVR to divide-by-2 to get 8MHz frequency
// (legal values of f_R are 6-12 MHz)
config_value |= PLL_BYPASS(1);
config_value |= PLL_R(r);
// Set DIVF to get 512Mhz frequncy
// There is an implied multiply-by-2, 16Mhz.
// So need to write 32-1
// (legal values of f_F are 384-768 MHz)
config_value |= PLL_F(f);
// Set DIVQ to divide-by-2 to get 256 MHz frequency
// (legal values of f_Q are 50-400Mhz)
config_value |= PLL_Q(q);
// Set our Final output divide to divide-by-1:
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
PRCI_REG(PRCI_PLLCFG) = config_value;
// Un-Bypass the PLL.
PRCI_REG(PRCI_PLLCFG) &= ~PLL_BYPASS(1);
// Wait for PLL Lock
// Note that the Lock signal can be glitchy.
// Need to wait 100 us
// RTC is running at 32kHz.
// So wait 4 ticks of RTC.
uint32_t now = mtime_lo();
while (mtime_lo() - now < 4) ;
// Now it is safe to check for PLL Lock
while ((PRCI_REG(PRCI_PLLCFG) & PLL_LOCK(1)) == 0) ;
}
// Switch over to PLL Clock source
PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1);
}
static void use_default_clocks()
{
// Turn off the LFROSC
AON_REG(AON_LFROSC) &= ~ROSC_EN(1);
// Use HFROSC
use_hfrosc(4, 16);
}
static unsigned long __attribute__((noinline)) measure_cpu_freq(size_t n)
{
unsigned long start_mtime, delta_mtime;
unsigned long mtime_freq = get_timer_freq();
// Don't start measuruing until we see an mtime tick
unsigned long tmp = mtime_lo();
do {
start_mtime = mtime_lo();
} while (start_mtime == tmp);
unsigned long start_mcycle = read_csr(mcycle);
do {
delta_mtime = mtime_lo() - start_mtime;
} while (delta_mtime < n);
unsigned long delta_mcycle = read_csr(mcycle) - start_mcycle;
return (delta_mcycle / delta_mtime) * mtime_freq
+ ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;
}
unsigned long get_cpu_freq()
{
static uint32_t cpu_freq;
if (!cpu_freq) {
// warm up I$
measure_cpu_freq(1);
// measure for real
cpu_freq = measure_cpu_freq(10);
}
return cpu_freq;
}
static void uart_init(size_t baud_rate)
{
GPIO_REG(GPIO_IOF_SEL) &= ~IOF0_UART0_MASK;
GPIO_REG(GPIO_IOF_EN) |= IOF0_UART0_MASK;
UART0_REG(UART_REG_DIV) = get_cpu_freq() / baud_rate - 1;
UART0_REG(UART_REG_TXCTRL) |= UART_TXEN;
}
#ifdef USE_PLIC
extern void handle_m_ext_interrupt();
#endif
#ifdef USE_M_TIME
extern void handle_m_time_interrupt();
#endif
uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)
{
if (0){
#ifdef USE_PLIC
// External Machine-Level interrupt from PLIC
} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) {
handle_m_ext_interrupt();
#endif
#ifdef USE_M_TIME
// External Machine-Level interrupt from PLIC
} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){
handle_m_time_interrupt();
#endif
}
else {
write(1, "trap\n", 5);
_exit(1 + mcause);
}
return epc;
}
void _init()
{
#ifndef NO_INIT
use_default_clocks();
use_pll(0, 0, 1, 31, 1);
uart_init(115200);
printf("core freq at %d Hz\n", get_cpu_freq());
write_csr(mtvec, &trap_entry);
if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present
write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping
write_csr(fcsr, 0); // initialize rounding mode, undefined at reset
}
#endif
}
void _fini()
{
}

View File

@ -1,34 +0,0 @@
adapter_khz 10000
interface ftdi
ftdi_device_desc "Dual RS232-HS"
ftdi_vid_pid 0x0403 0x6010
ftdi_layout_init 0x0008 0x001b
ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020
#Reset Stretcher logic on FE310 is ~1 second long
#This doesn't apply if you use
# ftdi_set_signal, but still good to document
#adapter_nsrst_delay 1500
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME
init
#reset -- This type of reset is not implemented yet
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
#Wait for the reset stretcher
#It will work without this, but
#will incur lots of delays for later commands.
sleep 1500
}
halt
#flash protect 0 64 last off

View File

@ -1,133 +0,0 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PLATFORM_H
#define _SIFIVE_PLATFORM_H
// Some things missing from the official encoding.h
#define MCAUSE_INT 0x80000000
#define MCAUSE_CAUSE 0x7FFFFFFF
#include "sifive/const.h"
#include "sifive/devices/aon.h"
#include "sifive/devices/clint.h"
#include "sifive/devices/gpio.h"
#include "sifive/devices/otp.h"
#include "sifive/devices/plic.h"
#include "sifive/devices/prci.h"
#include "sifive/devices/pwm.h"
#include "sifive/devices/spi.h"
#include "sifive/devices/uart.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
// Memory map
#define MASKROM_BASE_ADDR _AC(0x00001000,UL)
#define TRAPVEC_TABLE_BASE_ADDR _AC(0x00001010,UL)
#define OTP_MMAP_ADDR _AC(0x00020000,UL)
#define CLINT_BASE_ADDR _AC(0x02000000,UL)
#define PLIC_BASE_ADDR _AC(0x0C000000,UL)
#define AON_BASE_ADDR _AC(0x10000000,UL)
#define PRCI_BASE_ADDR _AC(0x10008000,UL)
#define OTP_BASE_ADDR _AC(0x10010000,UL)
#define GPIO_BASE_ADDR _AC(0x10012000,UL)
#define UART0_BASE_ADDR _AC(0x10013000,UL)
#define SPI0_BASE_ADDR _AC(0x10014000,UL)
#define PWM0_BASE_ADDR _AC(0x10015000,UL)
#define UART1_BASE_ADDR _AC(0x10023000,UL)
#define SPI1_BASE_ADDR _AC(0x10024000,UL)
#define PWM1_BASE_ADDR _AC(0x10025000,UL)
#define SPI2_BASE_ADDR _AC(0x10034000,UL)
#define PWM2_BASE_ADDR _AC(0x10035000,UL)
#define SPI0_MMAP_ADDR _AC(0x20000000,UL)
#define MEM_BASE_ADDR _AC(0x80000000,UL)
// IOF masks
#define IOF0_SPI1_MASK _AC(0x000007FC,UL)
#define SPI11_NUM_SS (4)
#define IOF_SPI1_SS0 (2u)
#define IOF_SPI1_SS1 (8u)
#define IOF_SPI1_SS2 (9u)
#define IOF_SPI1_SS3 (10u)
#define IOF_SPI1_MOSI (3u)
#define IOF_SPI1_MISO (4u)
#define IOF_SPI1_SCK (5u)
#define IOF_SPI1_DQ0 (3u)
#define IOF_SPI1_DQ1 (4u)
#define IOF_SPI1_DQ2 (6u)
#define IOF_SPI1_DQ3 (7u)
#define IOF0_SPI2_MASK _AC(0xFC000000,UL)
#define SPI2_NUM_SS (1)
#define IOF_SPI2_SS0 (26u)
#define IOF_SPI2_MOSI (27u)
#define IOF_SPI2_MISO (28u)
#define IOF_SPI2_SCK (29u)
#define IOF_SPI2_DQ0 (27u)
#define IOF_SPI2_DQ1 (28u)
#define IOF_SPI2_DQ2 (30u)
#define IOF_SPI2_DQ3 (31u)
//#define IOF0_I2C_MASK _AC(0x00003000,UL)
#define IOF0_UART0_MASK _AC(0x00030000, UL)
#define IOF_UART0_RX (16u)
#define IOF_UART0_TX (17u)
#define IOF0_UART1_MASK _AC(0x03000000, UL)
#define IOF_UART1_RX (24u)
#define IOF_UART1_TX (25u)
#define IOF1_PWM0_MASK _AC(0x0000000F, UL)
#define IOF1_PWM1_MASK _AC(0x00780000, UL)
#define IOF1_PWM2_MASK _AC(0x00003C00, UL)
// Interrupt numbers
#define INT_RESERVED 0
#define INT_WDOGCMP 1
#define INT_RTCCMP 2
#define INT_UART0_BASE 3
#define INT_UART1_BASE 4
#define INT_SPI0_BASE 5
#define INT_SPI1_BASE 6
#define INT_SPI2_BASE 7
#define INT_GPIO_BASE 8
#define INT_PWM0_BASE 40
#define INT_PWM1_BASE 44
#define INT_PWM2_BASE 48
// Helper functions
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
#define AON_REG(offset) _REG32(AON_BASE_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_BASE_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_BASE_ADDR, offset)
#define OTP_REG(offset) _REG32(OTP_BASE_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_BASE_ADDR, offset)
#define PRCI_REG(offset) _REG32(PRCI_BASE_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_BASE_ADDR, offset)
#define PWM1_REG(offset) _REG32(PWM1_BASE_ADDR, offset)
#define PWM2_REG(offset) _REG32(PWM2_BASE_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_BASE_ADDR, offset)
#define SPI1_REG(offset) _REG32(SPI1_BASE_ADDR, offset)
#define SPI2_REG(offset) _REG32(SPI2_BASE_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_BASE_ADDR, offset)
#define UART1_REG(offset) _REG32(UART1_BASE_ADDR, offset)
// Misc
#include <stdint.h>
#define NUM_GPIO 32
#define PLIC_NUM_INTERRUPTS 52
#define PLIC_NUM_PRIORITIES 7
#include "hifive1.h"
unsigned long get_cpu_freq(void);
unsigned long get_timer_freq(void);
uint64_t get_timer_value(void);
#endif /* _SIFIVE_PLATFORM_H */

59
raven/bsp/env/start.S vendored
View File

@ -1,13 +1,27 @@
// See LICENSE for license details.
#include <sifive/smp.h>
/* This is defined in sifive/platform.h, but that can't be included from
* assembly. */
#define CLINT_CTRL_ADDR 0x02000000
.section .init
.globl _start
.type _start,@function
_start:
la gp, _gp
.cfi_startproc
.cfi_undefined ra
.option push
.option norelax
la gp, __global_pointer$
.option pop
la sp, _sp
#if defined(ENABLE_SMP)
smp_pause(t0, t1)
#endif
/* Load data section */
la a0, _data_lma
la a1, _data
@ -47,8 +61,51 @@ _start:
1:
#endif
#if defined(ENABLE_SMP)
smp_resume(t0, t1)
csrr a0, mhartid
bnez a0, 2f
#endif
auipc ra, 0
addi sp, sp, -16
#if __riscv_xlen == 32
sw ra, 8(sp)
#else
sd ra, 8(sp)
#endif
/* argc = argv = 0 */
li a0, 0
li a1, 0
call main
tail exit
1:
j 1b
#if defined(ENABLE_SMP)
2:
la t0, trap_entry
csrw mtvec, t0
csrr a0, mhartid
la t1, _sp
slli t0, a0, 10
sub sp, t1, t0
auipc ra, 0
addi sp, sp, -16
#if __riscv_xlen == 32
sw ra, 8(sp)
#else
sd ra, 8(sp)
#endif
call secondary_main
tail exit
1:
j 1b
#endif
.cfi_endproc

288
raven/bsp/env/ventry.S vendored Normal file
View File

@ -0,0 +1,288 @@
// See LICENSE for license details
#ifndef VENTRY_S
#define VENTRY_S
#include "encoding.h"
#include "sifive/bits.h"
#only save caller registers
.macro TRAP_ENTRY
addi sp, sp, -16*REGBYTES
STORE x1, 0*REGBYTES(sp)
STORE x5, 1*REGBYTES(sp)
STORE x6, 2*REGBYTES(sp)
STORE x7, 3*REGBYTES(sp)
STORE x10, 4*REGBYTES(sp)
STORE x11, 5*REGBYTES(sp)
STORE x12, 6*REGBYTES(sp)
STORE x13, 7*REGBYTES(sp)
STORE x14, 8*REGBYTES(sp)
STORE x15, 9*REGBYTES(sp)
STORE x16, 10*REGBYTES(sp)
STORE x17, 11*REGBYTES(sp)
STORE x28, 12*REGBYTES(sp)
STORE x29, 13*REGBYTES(sp)
STORE x30, 14*REGBYTES(sp)
STORE x31, 15*REGBYTES(sp)
.endm
#restore caller registers
.macro TRAP_EXIT
# Remain in M-mode after mret
li t0, MSTATUS_MPP
csrs mstatus, t0
LOAD x1, 0*REGBYTES(sp)
LOAD x5, 1*REGBYTES(sp)
LOAD x6, 2*REGBYTES(sp)
LOAD x7, 3*REGBYTES(sp)
LOAD x10, 4*REGBYTES(sp)
LOAD x11, 5*REGBYTES(sp)
LOAD x12, 6*REGBYTES(sp)
LOAD x13, 7*REGBYTES(sp)
LOAD x14, 8*REGBYTES(sp)
LOAD x15, 9*REGBYTES(sp)
LOAD x16, 10*REGBYTES(sp)
LOAD x17, 11*REGBYTES(sp)
LOAD x28, 12*REGBYTES(sp)
LOAD x29, 13*REGBYTES(sp)
LOAD x30, 14*REGBYTES(sp)
LOAD x31, 15*REGBYTES(sp)
addi sp, sp, 16*REGBYTES
mret
.endm
#Vector table for E31/E51
.section .text.entry
.align 8
.global vtrap_entry
vtrap_entry:
j sync_trap
.align 2
j reserved
.align 2
j reserved
.align 2
j vmsi_Handler
.align 2
j reserved
.align 2
j reserved
.align 2
j reserved
.align 2
j vmti_Handler
.align 2
j reserved
.align 2
j reserved
.align 2
j reserved
.align 2
j vmei_Handler
.align 2
j reserved
.align 2
j reserved
.align 2
j reserved
.align 2
j reserved
.align 2
j vlip_Handler0
.align 2
j vlip_Handler1
.align 2
j vlip_Handler2
.align 2
j vlip_Handler3
.align 2
j vlip_Handler4
.align 2
j vlip_Handler5
.align 2
j vlip_Handler6
.align 2
j vlip_Handler7
.align 2
j vlip_Handler8
.align 2
j vlip_Handler9
.align 2
j vlip_Handler10
.align 2
j vlip_Handler11
.align 2
j vlip_Handler12
.align 2
j vlip_Handler13
.align 2
j vlip_Handler14
.align 2
j vlip_Handler15
#synchronous trap
sync_trap:
TRAP_ENTRY
jal handle_sync_trap
TRAP_EXIT
#Machine Software Interrupt
vmsi_Handler:
TRAP_ENTRY
jal reserved
TRAP_EXIT
#Machine Timer Interrupt
vmti_Handler:
TRAP_ENTRY
jal handle_m_time_interrupt
TRAP_EXIT
#Machine External Interrupt
vmei_Handler:
TRAP_ENTRY
jal handle_m_external_interrupt
TRAP_EXIT
#LIP0
vlip_Handler0:
TRAP_ENTRY
jal handle_local_interrupt0
TRAP_EXIT
#LIP1
vlip_Handler1:
TRAP_ENTRY
jal handle_local_interrupt1
TRAP_EXIT
#LIP2
vlip_Handler2:
TRAP_ENTRY
jal handle_local_interrupt2
TRAP_EXIT
#LIP3
vlip_Handler3:
TRAP_ENTRY
jal handle_local_interrupt3
TRAP_EXIT
#LIP4
vlip_Handler4:
TRAP_ENTRY
jal handle_local_interrupt4
TRAP_EXIT
#LIP5
vlip_Handler5:
TRAP_ENTRY
jal handle_local_interrupt5
TRAP_EXIT
#LIP6
vlip_Handler6:
TRAP_ENTRY
jal handle_local_interrupt6
TRAP_EXIT
#LIP7
vlip_Handler7:
TRAP_ENTRY
jal handle_local_interrupt7
TRAP_EXIT
#LIP8
vlip_Handler8:
TRAP_ENTRY
jal handle_local_interrupt8
TRAP_EXIT
#LIP9
vlip_Handler9:
TRAP_ENTRY
jal handle_local_interrupt9
TRAP_EXIT
#LIP10
vlip_Handler10:
TRAP_ENTRY
jal handle_local_interrupt10
TRAP_EXIT
#LIP11
vlip_Handler11:
TRAP_ENTRY
jal handle_local_interrupt11
TRAP_EXIT
#LIP12
vlip_Handler12:
TRAP_ENTRY
jal handle_local_interrupt12
TRAP_EXIT
#LIP13
vlip_Handler13:
TRAP_ENTRY
jal handle_local_interrupt13
TRAP_EXIT
#LIP14
vlip_Handler14:
TRAP_ENTRY
jal handle_local_interrupt14
TRAP_EXIT
#LIP15
vlip_Handler15:
TRAP_ENTRY
jal handle_local_interrupt15
TRAP_EXIT
#unimplemented ISRs trap here
.weak reserved
reserved:
.weak handle_local_interrupt0
handle_local_interrupt0:
.weak handle_local_interrupt1
handle_local_interrupt1:
.weak handle_local_interrupt2
handle_local_interrupt2:
.weak handle_local_interrupt3
handle_local_interrupt3:
.weak handle_local_interrupt4
handle_local_interrupt4:
.weak handle_local_interrupt5
handle_local_interrupt5:
.weak handle_local_interrupt6
handle_local_interrupt6:
.weak handle_local_interrupt7
handle_local_interrupt7:
.weak handle_local_interrupt8
handle_local_interrupt8:
.weak handle_local_interrupt9
handle_local_interrupt9:
.weak handle_local_interrupt10
handle_local_interrupt10:
.weak handle_local_interrupt11
handle_local_interrupt11:
.weak handle_local_interrupt12
handle_local_interrupt12:
.weak handle_local_interrupt13
handle_local_interrupt13:
.weak handle_local_interrupt14
handle_local_interrupt14:
.weak handle_local_interrupt15
handle_local_interrupt15:
1:
j 1b
#endif

View File

@ -1,3 +1,4 @@
// See LICENSE for license details.
#ifndef _RISCV_BITS_H
#define _RISCV_BITS_H
@ -17,7 +18,7 @@
#define STR(x) XSTR(x)
#define XSTR(x) #x
#ifdef __riscv64
#if __riscv_xlen == 64
# define SLL32 sllw
# define STORE sd
# define LOAD ld

View File

@ -1,3 +1,4 @@
// See LICENSE for license details.
/* Derived from <linux/const.h> */
#ifndef _SIFIVE_CONST_H

View File

@ -0,0 +1,30 @@
// See LICENSE for license details.
#ifndef _SIFIVE_CLIC_H
#define _SIFIVE_CLIC_H
#define CLIC_HART0 0x00800000
#define CLIC_MSIP 0x0000
#define CLIC_MSIP_size 0x4
#define CLIC_MTIMECMP 0x4000
#define CLIC_MTIMECMP_size 0x8
#define CLIC_MTIME 0xBFF8
#define CLIC_MTIME_size 0x8
#define CLIC_INTIP 0x000
#define CLIC_INTIE 0x400
#define CLIC_INTCFG 0x800
#define CLIC_CFG 0xc00
// These interrupt IDs are consistent across old and new mtvec modes
#define SSIPID 1
#define MSIPID 3
#define STIPID 5
#define MTIPID 7
#define SEIPID 9
#define MEIPID 11
#define CSIPID 12
#define LOCALINTIDBASE 16
#endif /* _SIFIVE_CLIC_H */

View File

@ -30,8 +30,8 @@
/* Fields */
#define SPI_SCK_POL 0x1
#define SPI_SCK_PHA 0x2
#define SPI_SCK_PHA 0x1
#define SPI_SCK_POL 0x2
#define SPI_FMT_PROTO(x) ((x) & 0x3)
#define SPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)

View File

@ -1,3 +1,4 @@
// See LICENSE for license details.
#ifndef _SECTIONS_H
#define _SECTIONS_H

View File

@ -0,0 +1,65 @@
#ifndef SIFIVE_SMP
#define SIFIVE_SMP
// The maximum number of HARTs this code supports
#ifndef MAX_HARTS
#define MAX_HARTS 32
#endif
#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS*4)
// The hart that non-SMP tests should run on
#ifndef NONSMP_HART
#define NONSMP_HART 0
#endif
/* If your test cannot handle multiple-threads, use this:
* smp_disable(reg1)
*/
#define smp_disable(reg1, reg2) \
csrr reg1, mhartid ;\
li reg2, NONSMP_HART ;\
beq reg1, reg2, hart0_entry ;\
42: ;\
wfi ;\
j 42b ;\
hart0_entry:
/* If your test needs to temporarily block multiple-threads, do this:
* smp_pause(reg1, reg2)
* ... single-threaded work ...
* smp_resume(reg1, reg2)
* ... multi-threaded work ...
*/
#define smp_pause(reg1, reg2) \
li reg2, 0x8 ;\
csrw mie, reg2 ;\
csrr reg2, mhartid ;\
bnez reg2, 42f
#define smp_resume(reg1, reg2) \
li reg1, CLINT_CTRL_ADDR ;\
41: ;\
li reg2, 1 ;\
sw reg2, 0(reg1) ;\
addi reg1, reg1, 4 ;\
li reg2, CLINT_END_HART_IPI ;\
blt reg1, reg2, 41b ;\
42: ;\
wfi ;\
csrr reg2, mip ;\
andi reg2, reg2, 0x8 ;\
beqz reg2, 42b ;\
li reg1, CLINT_CTRL_ADDR ;\
csrr reg2, mhartid ;\
slli reg2, reg2, 2 ;\
add reg2, reg2, reg1 ;\
sw zero, 0(reg2) ;\
41: ;\
lw reg2, 0(reg1) ;\
bnez reg2, 41b ;\
addi reg1, reg1, 4 ;\
li reg2, CLINT_END_HART_IPI ;\
blt reg1, reg2, 41b
#endif

View File

@ -25,7 +25,9 @@ LIBWRAP_SRCS := \
sys/isatty.c \
sys/times.c \
sys/sbrk.c \
sys/_exit.c
sys/_exit.c \
sys/puts.c \
misc/write_hex.c
LIBWRAP_SRCS := $(foreach f,$(LIBWRAP_SRCS),$(LIBWRAP_DIR)/$(f))
LIBWRAP_OBJS := $(LIBWRAP_SRCS:.c=.o)
@ -33,13 +35,14 @@ LIBWRAP_OBJS := $(LIBWRAP_SRCS:.c=.o)
LIBWRAP_SYMS := malloc free \
open lseek read write fstat stat close link unlink \
execve fork getpid kill wait \
isatty times sbrk _exit
isatty times sbrk _exit puts
LIBWRAP := libwrap.a
LINK_DEPS += $(LIBWRAP)
LDFLAGS += $(foreach s,$(LIBWRAP_SYMS),-Wl,--wrap=$(s))
LDFLAGS += $(foreach s,$(LIBWRAP_SYMS),-Wl,--wrap=_$(s))
LDFLAGS += -L. -Wl,--start-group -lwrap -lc -Wl,--end-group
CLEAN_OBJS += $(LIBWRAP_OBJS)

View File

@ -0,0 +1,19 @@
/* See LICENSE of license details. */
#include <stdint.h>
#include <unistd.h>
#include "platform.h"
void write_hex(int fd, unsigned long int hex)
{
uint8_t ii;
uint8_t jj;
char towrite;
write(fd , "0x", 2);
for (ii = sizeof(unsigned long int) * 2 ; ii > 0; ii--) {
jj = ii - 1;
uint8_t digit = ((hex & (0xF << (jj*4))) >> (jj*4));
towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA));
write(fd, &towrite, 1);
}
}

View File

@ -2,15 +2,16 @@
#include <unistd.h>
#include "platform.h"
#include "weak_under_alias.h"
void __wrap__exit(int code)
void __wrap_exit(int code)
{
//volatile uint32_t* leds = (uint32_t*) (GPIO_BASE_ADDR + GPIO_OUT_OFFSET);
const char message[] = "\nProgam has exited with code:";
//*leds = (~(code));
write(STDERR_FILENO, message, sizeof(message) - 1);
write_hex(STDERR_FILENO, code);
write(STDERR_FILENO, "\n", 1);
for (;;);
}
weak_under_alias(exit);

View File

@ -2,8 +2,10 @@
#include <errno.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_close(int fd)
{
return _stub(EBADF);
}
weak_under_alias(close);

View File

@ -2,8 +2,10 @@
#include <errno.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_execve(const char* name, char* const argv[], char* const env[])
{
return _stub(ENOMEM);
}
weak_under_alias(execve);

View File

@ -4,6 +4,7 @@
#include <unistd.h>
#include <sys/stat.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_fstat(int fd, struct stat* st)
{
@ -14,3 +15,4 @@ int __wrap_fstat(int fd, struct stat* st)
return _stub(EBADF);
}
weak_under_alias(fstat);

View File

@ -1,6 +1,8 @@
/* See LICENSE of license details. */
#include "weak_under_alias.h"
int __wrap_getpid(void)
{
return 1;
}
weak_under_alias(getpid);

View File

@ -1,6 +1,7 @@
/* See LICENSE of license details. */
#include <unistd.h>
#include "weak_under_alias.h"
int __wrap_isatty(int fd)
{
@ -9,3 +10,4 @@ int __wrap_isatty(int fd)
return 0;
}
weak_under_alias(isatty);

View File

@ -2,8 +2,10 @@
#include <errno.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_kill(int pid, int sig)
{
return _stub(EINVAL);
}
weak_under_alias(kill);

View File

@ -2,8 +2,10 @@
#include <errno.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_link(const char *old_name, const char *new_name)
{
return _stub(EMLINK);
}
weak_under_alias(link);

View File

@ -4,6 +4,7 @@
#include <unistd.h>
#include <sys/types.h>
#include "stub.h"
#include "weak_under_alias.h"
off_t __wrap_lseek(int fd, off_t ptr, int dir)
{
@ -12,3 +13,4 @@ off_t __wrap_lseek(int fd, off_t ptr, int dir)
return _stub(EBADF);
}
weak_under_alias(lseek);

View File

@ -2,8 +2,10 @@
#include <errno.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_open(const char* name, int flags, int mode)
{
return _stub(ENOENT);
}
weak_under_alias(open);

View File

@ -2,8 +2,10 @@
#include <errno.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_openat(int dirfd, const char* name, int flags, int mode)
{
return _stub(ENOENT);
}
weak_under_alias(openat);

View File

@ -0,0 +1,28 @@
/* See LICENSE of license details. */
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "platform.h"
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_puts(const char *s)
{
while (*s != '\0') {
while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
UART0_REG(UART_REG_TXFIFO) = *s;
if (*s == '\n') {
while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ;
UART0_REG(UART_REG_TXFIFO) = '\r';
}
++s;
}
return 0;
}
weak_under_alias(puts);

View File

@ -7,12 +7,13 @@
#include "platform.h"
#include "stub.h"
#include "weak_under_alias.h"
ssize_t __wrap_read(int fd, void* ptr, size_t len)
{
uint8_t * current = (uint8_t *)ptr;
volatile uint32_t * uart_rx = (uint32_t *)(UART0_BASE_ADDR + UART_REG_RXFIFO);
volatile uint8_t * uart_rx_cnt = (uint8_t *)(UART0_BASE_ADDR + UART_REG_RXCTRL + 2);
volatile uint32_t * uart_rx = (uint32_t *)(UART0_CTRL_ADDR + UART_REG_RXFIFO);
volatile uint8_t * uart_rx_cnt = (uint8_t *)(UART0_CTRL_ADDR + UART_REG_RXCTRL + 2);
ssize_t result = 0;
@ -28,3 +29,4 @@ ssize_t __wrap_read(int fd, void* ptr, size_t len)
return _stub(EBADF);
}
weak_under_alias(read);

View File

@ -1,6 +1,7 @@
/* See LICENSE of license details. */
#include <stddef.h>
#include "weak_under_alias.h"
void *__wrap_sbrk(ptrdiff_t incr)
{
@ -14,3 +15,4 @@ void *__wrap_sbrk(ptrdiff_t incr)
curbrk += incr;
return curbrk - incr;
}
weak_under_alias(sbrk);

View File

@ -3,8 +3,10 @@
#include <errno.h>
#include <sys/stat.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_stat(const char* file, struct stat* st)
{
return _stub(EACCES);
}
weak_under_alias(stat);

View File

@ -3,8 +3,10 @@
#include <errno.h>
#include <sys/times.h>
#include "stub.h"
#include "weak_under_alias.h"
clock_t __wrap_times(struct tms* buf)
{
return _stub(EACCES);
}
weak_under_alias(times);

View File

@ -2,8 +2,10 @@
#include <errno.h>
#include "stub.h"
#include "weak_under_alias.h"
int __wrap_unlink(const char* name)
{
return _stub(ENOENT);
}
weak_under_alias(unlink);

View File

@ -0,0 +1,7 @@
#ifndef _BSP_LIBWRAP_WEAK_UNDER_ALIAS_H
#define _BSP_LIBWRAP_WEAK_UNDER_ALIAS_H
#define weak_under_alias(name) \
extern __typeof (__wrap_##name) __wrap__##name __attribute__ ((weak, alias ("__wrap_"#name)))
#endif

View File

@ -7,6 +7,7 @@
#include "platform.h"
#include "stub.h"
#include "weak_under_alias.h"
ssize_t __wrap_write(int fd, const void* ptr, size_t len)
{
@ -27,3 +28,4 @@ ssize_t __wrap_write(int fd, const void* ptr, size_t len)
return _stub(EBADF);
}
weak_under_alias(write);

Binary file not shown.

View File

@ -1,55 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include "platform.h"
#include "encoding.h"
#define IOF_ENABLE_TERMINAL (0x30000)
int factorial(int i){
volatile int result = 1;
for (int ii = 1; ii <= i; ii++) {
result = result * ii;
}
return result;
}
int main()
{
GPIO_REG(GPIO_IOF_EN) |= IOF_ENABLE_TERMINAL; // enable GPIO connection to the terminal
int hartid = read_csr(0xf14); // CSR_MHARTID
int target_mem_base = 0x90000000;
int local_mem_base = 0x80000000;
if (hartid == 0) {
int val_a = 5;
int val_b = 0xA;
*(int *)target_mem_base = val_a;
*(int *)(target_mem_base+4) = val_b;
printf("HW thread ID %d: write value A=0x%x and value B=0x%x to thread 1\n", hartid, val_a, val_b);
}
int result = factorial (10);
printf("HW thread ID %d: spend some time calculating factorial of 10=0x%x\n", hartid, result);
if (hartid == 1) {
int val_a = *(int *)local_mem_base;
int val_b = *(int *)(local_mem_base+4);
int sum = val_a + val_b;
if (sum == 0xF)
printf("HW thread ID %d: sum of A+B=0x%x\n", hartid, sum);
else {
printf("HW thread ID %d: sum of A+B is not 0x%x. Test FAILED!!!\n", hartid, sum);
return 1;
}
}
printf("End of execution");
return 0;
}

File diff suppressed because it is too large Load Diff

22
raven/src/bsp.h Normal file
View File

@ -0,0 +1,22 @@
/*
* bsp.h
*
* Created on: 30.07.2018
* Author: eyck
*/
#ifndef BSP_H_
#define BSP_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <fe300prci/fe300prci_driver.h>
#include <platform.h>
#include <encoding.h>
extern void trap_entry();
#ifdef __cplusplus
}
#endif
#endif /* BSP_H_ */

123
raven/src/delay.c Normal file
View File

@ -0,0 +1,123 @@
/*
* delay.c
*
* Created on: 30.07.2018
* Author: eyck
*/
#include "delay.h"
#define rdmcycle(x) { \
uint32_t lo, hi, hi2; \
__asm__ __volatile__ ("1:\n\t" \
"csrr %0, mcycleh\n\t" \
"csrr %1, mcycle\n\t" \
"csrr %2, mcycleh\n\t" \
"bne %0, %2, 1b\n\t" \
: "=r" (hi), "=r" (lo), "=r" (hi2)) ; \
*(x) = lo | ((uint64_t) hi << 32); \
}
typedef struct {
uint32_t n;
uint32_t mult;
uint32_t shift;
} int_inverse ;
int_inverse f_cpu_1000_inv;
int_inverse f_cpu_1000000_inv;
uint32_t F_CPU=1000000;
void calc_inv(uint32_t n, int_inverse * res){
uint32_t one = ~0;
uint32_t d = one/n;
uint32_t r = one%n + 1;
if (r >= n) ++d;
if (d == 0) --d;
uint32_t shift = 0;
while ((d & 0x80000000) == 0){
d <<= 1;
++shift;
}
res->n = n;
res->mult = d;
res->shift = shift;
}
uint32_t divide32_using_inverse(uint32_t n, int_inverse *inv){
uint32_t d = (uint32_t)(((uint64_t)n * inv->mult) >> 32);
d >>= inv->shift;
if (n - d*inv->n >= inv->n) ++d;
return d;
}
// Almost full-range 64/32 divide.
// If divisor-1 has i bits, then the answer is exact for n of up to 64-i bits
// e.g. for divisors up to a million, n can have up to 45 bits
// On RV32IM with divide32_using_inverse inlines this uses 5 multiplies,
// 33 instructions, zero branches, 3 loads, 0 stores.
uint64_t divide64_using_inverse(uint64_t n, int_inverse *inv){
uint32_t preshift = (31 - inv->shift) & 31;
uint64_t d = (uint64_t)divide32_using_inverse(n >> preshift, inv) << preshift;
uint32_t r = n - d * inv->n;
d += divide32_using_inverse(r, inv);
return d;
}
uint32_t millis(){
uint64_t x;
rdmcycle(&x);
x = divide64_using_inverse(x, &f_cpu_1000_inv);
return((uint32_t) (x & 0xFFFFFFFF));
}
uint32_t micros(void){
uint64_t x;
rdmcycle(&x);
// For Power-of-two MHz F_CPU,
// this compiles into a simple shift,
// and is faster than the general solution.
#if F_CPU==16000000
x = x / (F_CPU / 1000000);
#else
#if F_CPU==256000000
x = x / (F_CPU / 1000000);
#else
x = divide64_using_inverse(x, &f_cpu_1000000_inv);
#endif
#endif
return((uint32_t) (x & 0xFFFFFFFF));
}
void delayMS(uint32_t dwMs){
uint64_t current, later;
rdmcycle(&current);
later = current + dwMs * (F_CPU/1000);
if (later > current){ // usual case
while (later > current)
rdmcycle(&current);
} else { // wrap. Though this is unlikely to be hit w/ 64-bit mcycle
while (later < current)
rdmcycle(&current);
while (current < later)
rdmcycle(&current);
}
}
void delayUS(uint32_t dwUs){
uint64_t current, later;
rdmcycle(&current);
later = current + dwUs * (F_CPU/1000000);
if (later > current){ // usual case
while (later > current)
rdmcycle(&current);
} else {// wrap. Though this is unlikely to be hit w/ 64-bit mcycle
while (later < current)
rdmcycle(&current);
while (current < later)
rdmcycle(&current);
}
}

25
raven/src/delay.h Normal file
View File

@ -0,0 +1,25 @@
/*
* delay.h
*
* Created on: 30.07.2018
* Author: eyck
*/
#ifndef DELAY_H_
#define DELAY_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t F_CPU;
void delayMS(uint32_t dwMs);
void delayUS(uint32_t dwUs);
#ifdef __cplusplus
}
#endif
#endif /* DELAY_H_ */

148
raven/src/hello_raven.cpp Normal file
View File

@ -0,0 +1,148 @@
#include "hello_raven.h"
#include "delay.h"
#include "bsp.h"
#include "plic/plic_driver.h"
#include <cstdio>
#include <cstdint>
#include "hifive1_io.h"
#define IOF_ENABLE_TERMINAL (0x30000)
typedef void (*function_ptr_t) (void);
//! Instance data for the PLIC.
plic_instance_t g_plic;
std::array<function_ptr_t,PLIC_NUM_INTERRUPTS> g_ext_interrupt_handlers;
char * end = (char *)0x80001000; // TODO: end supposed to be a RAM section according to the linker file falsh.lds, but for some reason it's not initialized
/*! \brief external interrupt handler
*
* routes the peripheral interrupts to the the respective handler
*
*/
extern "C" void handle_m_ext_interrupt() {
plic_source int_num = PLIC_claim_interrupt(&g_plic);
if ((int_num >=1 ) && (int_num < PLIC_NUM_INTERRUPTS))
g_ext_interrupt_handlers[int_num]();
else
exit(1 + (uintptr_t) int_num);
PLIC_complete_interrupt(&g_plic, int_num);
}
/*! \brief mtime interval interrupt
*
*/
extern "C" void handle_m_time_interrupt(){
clear_csr(mie, MIP_MTIP);
// Reset the timer for 3s in the future.
// This also clears the existing timer interrupt.
volatile uint64_t * mtime = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
uint64_t now = *mtime;
uint64_t then = now + RTC_FREQ;
*mtimecmp = then;
// Re-enable the timer interrupt.
set_csr(mie, MIP_MTIP);
}
/*! \brief dummy interrupt handler
*
*/
void no_interrupt_handler (void) {};
/*! \brief configure the per-interrupt handler
*
*/
void configure_irq(size_t irq_num, function_ptr_t handler, unsigned char prio=1) {
g_ext_interrupt_handlers[irq_num] = handler;
// Priority must be set > 0 to trigger the interrupt.
PLIC_set_priority(&g_plic, irq_num, prio);
// Have to enable the interrupt both at the GPIO level, and at the PLIC level.
PLIC_enable_interrupt(&g_plic, irq_num);
}
static void msi_interrupt_handler(){
int * local_mem_base = (int *) end;
int hartid = read_csr(mhartid);
int val_a = *local_mem_base;
int val_b = *(local_mem_base+1);
int sum = val_a + val_b;
*(local_mem_base+100) = sum;
if (sum == 0xF)
printf("HW thread ID %d: sum of A+B=0x%x\n", hartid, sum);
else {
printf("HW thread ID %d: sum of A+B is not 0x%x. Test FAILED!!!\n", hartid, sum);
}
}
/*!\brief initializes platform
*
*/
void platform_init(){
// configure clocks
PRCI_use_hfxosc(1); // is equivalent to
qspi1::sckdiv_reg() = 8;
F_CPU=PRCI_measure_mcycle_freq(20, RTC_FREQ);
printf("core freq at %d Hz\n", F_CPU);
// initialie interupt & trap handling
write_csr(mtvec, &trap_entry);
PLIC_init(&g_plic, PLIC_CTRL_ADDR, PLIC_NUM_INTERRUPTS, PLIC_NUM_PRIORITIES, 0);
// Disable the machine & timer interrupts until setup is done.
clear_csr(mie, MIP_MEIP);
clear_csr(mie, MIP_MTIP);
for (auto& h:g_ext_interrupt_handlers) h=no_interrupt_handler;
configure_irq(1, msi_interrupt_handler);
// Set the machine timer to go off in 1 second.
volatile uint64_t * mtime = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
uint64_t now = *mtime;
uint64_t then = now + RTC_FREQ;
*mtimecmp = then;
// Enable the Machine-External bit in MIE
set_csr(mie, MIP_MEIP);
// Enable the Machine-Timer bit in MIE
set_csr(mie, MIP_MTIP);
// Enable interrupts in general.
set_csr(mstatus, MSTATUS_MIE);
}
/*! \brief main function
*
*/
int main() {
volatile int * target_mem_base = (int *)(end + 0x10000000);
int * local_mem_base = (int *) end;
int * plic_b_pending = (int *)(0xA0000000+PLIC_PENDING_OFFSET);
int * local_sync_bit = (int *)(local_mem_base + 10);
int * target_sync_bit = (int *)(target_mem_base + 10);
int hartid = read_csr(mhartid);
*local_sync_bit = 0;
GPIO_REG(GPIO_IOF_EN) |= IOF_ENABLE_TERMINAL; // enable GPIO connection to the terminal
platform_init();
// Enable the Machine-External bit in MIE
set_csr(mie, MIP_MEIP);
if (hartid == 0) {
int val_a = 5;
int val_b = 0xA;
*target_mem_base = val_a;
*(target_mem_base+1) = val_b;
*(plic_b_pending) = 2;
printf("HW thread ID %d: write value A=0x%x and value B=0x%x to thread 1\n", hartid, val_a, val_b);
}
*local_sync_bit++;
while (*target_sync_bit < *local_sync_bit);
printf("End of execution");
return 0;
}

7
raven/src/hello_raven.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef HELLO_RAVEN_H_
#define HELLO_RAVEN_H_
extern "C" void handle_m_ext_interrupt();
extern "C" void handle_m_time_interrupt();
#endif /* HELLO_RAVEN_H_ */

16
raven/src/hifive1_io.cpp Normal file
View File

@ -0,0 +1,16 @@
/*
* peripherals.c
*
* Created on: 10.09.2018
* Author: eyck
*/
#include "hifive1_io.h"
template<> volatile bool qspi0::spi_active=false;
template<> volatile bool qspi1::spi_active=false;
template<> volatile bool qspi2::spi_active=false;
template<> volatile bool pwm0::pwm_active=false;
template<> volatile bool pwm1::pwm_active=false;
template<> volatile bool pwm2::pwm_active=false;

26
raven/src/hifive1_io.h Normal file
View File

@ -0,0 +1,26 @@
/*
* peripherals.h
*
* Created on: 29.07.2018
* Author: eyck
*/
#ifndef HIFIVE1_IO_H_
#define HIFIVE1_IO_H_
#include "io/gpio.h"
#include "io/spi.h"
#include "io/pwm.h"
#include "io/uart.h"
using gpio0=gpio_regs<0x10012000>;
using uart0=uart_regs<0x10013000>;
using uart1=uart_regs<0x10023000>;
using qspi0=spi_regs<0x10014000>;
using qspi1=spi_regs<0x10024000>;
using qspi2=spi_regs<0x10034000>;
using pwm0 =pwm_regs<0x10015000>;
using pwm1 =pwm_regs<0x10025000>;
using pwm2 =pwm_regs<0x10035000>;
#endif /* HIFIVE1_IO_H_ */

89
raven/src/io/gpio.h Normal file
View File

@ -0,0 +1,89 @@
/*
* gpio.h
*
* Created on: 29.07.2018
* Author: eyck
*/
#ifndef GPIO_H_
#define GPIO_H_
#include <sifive/devices/gpio.h>
#include <cstdint>
template<uint32_t BASE_ADDR>
class gpio_regs {
public:
static inline uint32_t& value_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_INPUT_VAL);
}
static inline uint32_t& input_en_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_INPUT_EN);
}
static inline uint32_t& output_en_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_OUTPUT_EN);
}
static inline uint32_t& port_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_OUTPUT_VAL);
}
static inline uint32_t& pue_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_PULLUP_EN);
}
static inline uint32_t& ds_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_DRIVE);
}
static inline uint32_t& rise_ie_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_RISE_IE);
}
static inline uint32_t& rise_ip_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_RISE_IP);
}
static inline uint32_t& fall_ie_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_FALL_IE);
}
static inline uint32_t& fall_ip_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_FALL_IP);
}
static inline uint32_t& high_ie_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_HIGH_IE);
}
static inline uint32_t& high_ip_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_HIGH_IP);
}
static inline uint32_t& low_ie_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_LOW_IE);
}
static inline uint32_t& low_ip_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_LOW_IP);
}
static inline uint32_t& iof_en_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_IOF_EN);
}
static inline uint32_t& iof_sel_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_IOF_SEL);
}
static inline uint32_t& out_xor_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+GPIO_OUTPUT_XOR);
}
};
#endif /* GPIO_H_ */

122
raven/src/io/pwm.h Normal file
View File

@ -0,0 +1,122 @@
/*
* pwm.h
*
* Created on: 29.07.2018
* Author: eyck
*/
#ifndef PWM_H_
#define PWM_H_
#include <sifive/devices/pwm.h>
#include "util/bit_field.h"
#include <limits>
#include <cstdint>
template<uint32_t BASE_ADDR>
class pwm_regs {
public:
BEGIN_BF_DECL(pwmcfg_t, uint32_t);
BF_FIELD(scale, 0, 4);
BF_FIELD(sticky, 8, 1);
BF_FIELD(zerocmp, 9, 1);
BF_FIELD(deglitch, 10, 1);
BF_FIELD(enalways, 12, 1);
BF_FIELD(enoneshot, 13, 1);
BF_FIELD(cmp0center, 16, 1);
BF_FIELD(cmp1center, 17, 1);
BF_FIELD(cmp2center, 18, 1);
BF_FIELD(cmp3center, 19, 1);
BF_FIELD(cmp0gang, 24, 1);
BF_FIELD(cmp1gang, 25, 1);
BF_FIELD(cmp2gang, 26, 1);
BF_FIELD(cmp3gang, 27, 1);
BF_FIELD(cmp0ip, 28, 1);
BF_FIELD(cmp1ip, 29, 1);
BF_FIELD(cmp2ip, 30, 1);
BF_FIELD(cmp3ip, 31, 1);
END_BF_DECL();
BEGIN_BF_DECL(pwms_t, uint32_t);
BF_FIELD(s, 0, 16);
END_BF_DECL() r_pwms;
BEGIN_BF_DECL(pwmcmp0_t, uint32_t);
BF_FIELD(cmp0, 0, 16);
END_BF_DECL() r_pwmcmp0;
BEGIN_BF_DECL(pwmcmp1_t, uint32_t);
BF_FIELD(cmp0, 0, 16);
END_BF_DECL() r_pwmcmp1;
BEGIN_BF_DECL(pwmcmp2_t, uint32_t);
BF_FIELD(cmp0, 0, 16);
END_BF_DECL() r_pwmcmp2;
BEGIN_BF_DECL(pwmcmp3_t, uint32_t);
BF_FIELD(cmp0, 0, 16);
END_BF_DECL() r_pwmcmp3;
static inline pwmcfg_t& cfg_reg(){
return *reinterpret_cast<pwmcfg_t*>(BASE_ADDR+PWM_CFG);
}
static inline uint32_t& count_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+PWM_COUNT);
}
static inline pwms_t& s_reg(){
return *reinterpret_cast<pwms_t*>(BASE_ADDR+PWM_S);
}
static inline pwmcmp0_t& cmp0_reg(){
return *reinterpret_cast<pwmcmp0_t*>(BASE_ADDR+PWM_CMP0);
}
static inline pwmcmp1_t& cmp1_reg(){
return *reinterpret_cast<pwmcmp1_t*>(BASE_ADDR+PWM_CMP1);
}
static inline pwmcmp2_t& cmp2_reg(){
return *reinterpret_cast<pwmcmp2_t*>(BASE_ADDR+PWM_CMP2);
}
static inline pwmcmp3_t& cmp3_reg(){
return *reinterpret_cast<pwmcmp3_t*>(BASE_ADDR+PWM_CMP3);
}
static inline bool oneshot_delay(long delay_us){
auto scaling_factor=0;
while(delay_us/(1<<scaling_factor) > std::numeric_limits<unsigned short>::max()){
scaling_factor++;
}
cfg_reg()=0;
count_reg()=0;
cfg_reg().scale=4+scaling_factor; // divide by 16 so we get 1us per pwm clock
cmp0_reg().cmp0 = delay_us/(1<<scaling_factor);
pwm_active=true;
cfg_reg().enoneshot=true;
do{
asm("wfi");
asm("nop");
}while(pwm_active);
return true;
}
static void pwm_interrupt_handler(){
cfg_reg().cmp0ip=false;
pwm_active=false;
}
inline
static bool is_active(){ return pwm_active; }
inline
static void set_active() {pwm_active=true;}
private:
static volatile bool pwm_active;
};
#endif /* PWM_H_ */

200
raven/src/io/spi.h Normal file
View File

@ -0,0 +1,200 @@
/*
* spi.h
*
* Created on: 29.07.2018
* Author: eyck
*/
#ifndef SPI_H_
#define SPI_H_
#include <sifive/devices/spi.h>
#include "util/bit_field.h"
#include <array>
#include <cstdint>
template<uint32_t BASE_ADDR>
class spi_regs {
public:
// storage declarations
BEGIN_BF_DECL(sckdiv_t, uint32_t);
BF_FIELD(div, 0, 12);
END_BF_DECL();
BEGIN_BF_DECL(sckmode_t, uint32_t);
BF_FIELD(pha, 0, 1);
BF_FIELD(pol, 1, 1);
END_BF_DECL();
uint32_t r_csid;
uint32_t r_csdef;
BEGIN_BF_DECL(csmode_t, uint32_t);
BF_FIELD(mode, 0, 2);
END_BF_DECL();
BEGIN_BF_DECL(delay0_t, uint32_t);
BF_FIELD(cssck, 0, 8);
BF_FIELD(sckcs, 16, 8);
END_BF_DECL();
BEGIN_BF_DECL(delay1_t, uint32_t);
BF_FIELD(intercs, 0, 16);
BF_FIELD(interxfr, 16, 8);
END_BF_DECL();
BEGIN_BF_DECL(fmt_t, uint32_t);
BF_FIELD(proto, 0, 2);
BF_FIELD(endian, 2, 1);
BF_FIELD(dir, 3, 1);
BF_FIELD(len, 16, 4);
END_BF_DECL();
BEGIN_BF_DECL(txdata_t, uint32_t);
BF_FIELD(data, 0, 8);
BF_FIELD(full, 31, 1);
END_BF_DECL() r_txdata;
BEGIN_BF_DECL(rxdata_t, uint32_t);
BF_FIELD(data, 0, 8);
BF_FIELD(empty, 31, 1);
END_BF_DECL();
BEGIN_BF_DECL(txmark_t, uint32_t);
BF_FIELD(txmark, 0, 3);
END_BF_DECL();
BEGIN_BF_DECL(rxmark_t, uint32_t);
BF_FIELD(rxmark, 0, 3);
END_BF_DECL();
BEGIN_BF_DECL(fctrl_t, uint32_t);
BF_FIELD(en, 0, 1);
END_BF_DECL();
BEGIN_BF_DECL(ffmt_t, uint32_t);
BF_FIELD(cmd_en, 0, 1);
BF_FIELD(addr_len, 1, 2);
BF_FIELD(pad_cnt, 3, 4);
BF_FIELD(cmd_proto, 7, 2);
BF_FIELD(addr_proto, 9, 2);
BF_FIELD(data_proto, 11, 2);
BF_FIELD(cmd_code, 16, 8);
BF_FIELD(pad_code, 24, 8);
END_BF_DECL();
BEGIN_BF_DECL(ie_t, uint32_t);
BF_FIELD(txwm, 0, 1);
BF_FIELD(rxwm, 1, 1);
END_BF_DECL();
BEGIN_BF_DECL(ip_t, uint32_t);
BF_FIELD(txwm, 0, 1);
BF_FIELD(rxwm, 1, 1);
END_BF_DECL();
static inline sckdiv_t& sckdiv_reg(){
return *reinterpret_cast<sckdiv_t*>(BASE_ADDR+SPI_REG_SCKDIV);
}
static inline sckmode_t& sckmode_reg(){
return *reinterpret_cast<sckmode_t*>(BASE_ADDR+SPI_REG_SCKMODE);
}
static inline uint32_t& csid_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+SPI_REG_CSID);
}
static inline uint32_t& csdef_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+SPI_REG_CSDEF);
}
static inline csmode_t& csmode_reg(){
return *reinterpret_cast<csmode_t*>(BASE_ADDR+SPI_REG_CSMODE);
}
static inline delay0_t& dcssck_reg(){
return *reinterpret_cast<delay0_t*>(BASE_ADDR+SPI_REG_DCSSCK);
}
static inline uint32_t& dsckcs_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+SPI_REG_DSCKCS);
}
static inline delay1_t& dintercs_reg(){
return *reinterpret_cast<delay1_t*>(BASE_ADDR+SPI_REG_DINTERCS);
}
static inline uint32_t& dinterxfr_reg(){
return *reinterpret_cast<uint32_t*>(BASE_ADDR+SPI_REG_DINTERXFR);
}
static inline fmt_t& fmt_reg(){
return *reinterpret_cast<fmt_t*>(BASE_ADDR+SPI_REG_FMT);
}
static inline txdata_t& txfifo_reg(){
return *reinterpret_cast<txdata_t*>(BASE_ADDR+SPI_REG_TXFIFO);
}
static inline rxdata_t& rxfifo_reg(){
return *reinterpret_cast<rxdata_t*>(BASE_ADDR+SPI_REG_RXFIFO);
}
static inline txmark_t& txctrl_reg(){
return *reinterpret_cast<txmark_t*>(BASE_ADDR+SPI_REG_TXCTRL);
}
static inline rxmark_t& rxctrl_reg(){
return *reinterpret_cast<rxmark_t*>(BASE_ADDR+SPI_REG_RXCTRL);
}
static inline fctrl_t& fctrl_reg(){
return *reinterpret_cast<fctrl_t*>(BASE_ADDR+SPI_REG_FCTRL);
}
static inline ffmt_t& ffmt_reg(){
return *reinterpret_cast<ffmt_t*>(BASE_ADDR+SPI_REG_FFMT);
}
static inline ie_t& ie_reg(){
return *reinterpret_cast<ie_t*>(BASE_ADDR+SPI_REG_IE);
}
static inline ip_t& ip_reg(){
return *reinterpret_cast<ip_t*>(BASE_ADDR+SPI_REG_IP);
}
template<size_t SIZE>
static bool transfer(std::array<uint8_t, SIZE>& bytes){
csmode_reg().mode=2; // HOLD mode
rxctrl_reg().rxmark=bytes.size()-1; // trigger irq if more than 2 bytes are received;
ie_reg().rxwm=1;
// write data bytes
for(size_t i=0; i<bytes.size(); ++i)
txfifo_reg()=bytes[i];
// wait until SPI is done
spi_active=true;
do{
asm("wfi");
asm("nop");
}while(spi_active);
// deactivate SPI
csmode_reg().mode=0; // AUTO mode, deactivates CS
// fetch results
for(size_t i=0; i<bytes.size(); ++i) bytes[i]=rxfifo_reg();
return true;
}
static void spi_rx_interrupt_handler(){
ip_reg().rxwm=0;
ie_reg().rxwm=0;
spi_active=false;
}
private:
static volatile bool spi_active;
};
#endif /* SPI_H_ */

83
raven/src/io/uart.h Normal file
View File

@ -0,0 +1,83 @@
/*
* spi.h
*
* Created on: 29.07.2018
* Author: eyck
*/
#ifndef UART_H_
#define UART_H_
#include <sifive/devices/uart.h>
#include "util/bit_field.h"
#include <cstdint>
template<uint32_t BASE_ADDR>
class uart_regs {
public:
BEGIN_BF_DECL(txdata_t, uint32_t);
BF_FIELD(data, 0, 8);
BF_FIELD(full, 31, 1);
END_BF_DECL() ;
BEGIN_BF_DECL(rxdata_t, uint32_t);
BF_FIELD(data, 0, 8);
BF_FIELD(empty, 31, 1);
END_BF_DECL();
BEGIN_BF_DECL(txctrl_t, uint32_t);
BF_FIELD(txen, 0, 1);
BF_FIELD(nstop, 1, 1);
BF_FIELD(txcnt, 16, 3);
END_BF_DECL();
BEGIN_BF_DECL(rxctrl_t, uint32_t);
BF_FIELD(rxen, 0, 1);
BF_FIELD(rxcnt, 16, 3);
END_BF_DECL();
BEGIN_BF_DECL(ie_t, uint32_t);
BF_FIELD(txwm, 0, 1);
BF_FIELD(rxwm, 1, 1);
END_BF_DECL();
BEGIN_BF_DECL(ip_t, uint32_t);
BF_FIELD(txwm, 0, 1);
BF_FIELD(rxwm, 1, 1);
END_BF_DECL();
BEGIN_BF_DECL(div_t, uint32_t);
BF_FIELD(div, 0, 16);
END_BF_DECL();
static inline txdata_t& txdata_reg(){
return *reinterpret_cast<txdata_t*>(BASE_ADDR+UART_REG_TXFIFO);
}
static inline rxdata_t& rxdata_reg(){
return *reinterpret_cast<rxdata_t*>(BASE_ADDR+UART_REG_RXFIFO);
}
static inline txctrl_t& txctrl_reg(){
return *reinterpret_cast<txctrl_t*>(BASE_ADDR+UART_REG_TXCTRL);
}
static inline rxctrl_t& rxctrl_reg(){
return *reinterpret_cast<rxctrl_t*>(BASE_ADDR+UART_REG_RXCTRL);
}
static inline ie_t& ie_reg(){
return *reinterpret_cast<ie_t*>(BASE_ADDR+UART_REG_IE);
}
static inline ip_t& ip_reg(){
return *reinterpret_cast<ip_t*>(BASE_ADDR+UART_REG_IP);
}
static inline div_t& div_reg(){
return *reinterpret_cast<div_t*>(BASE_ADDR+UART_REG_DIV);
}
};
#endif /* SPI_H_ */

179
raven/src/util/bit_field.h Normal file
View File

@ -0,0 +1,179 @@
/*---------------------------------------------------------
Copyright (c) 2015 Jeff Preshing
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgement in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
---------------------------------------------------------*/
#ifndef BIT_FIELD_H_
#define BIT_FIELD_H_
#ifndef __CPP11OM_BITFIELD_H__
#define __CPP11OM_BITFIELD_H__
#include <cassert>
//---------------------------------------------------------
// BitFieldMember<>: Used internally by ADD_BITFIELD_MEMBER macro.
// All members are public to simplify compliance with sections 9.0.7 and
// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior.
//---------------------------------------------------------
template <typename T, int Offset, int Bits> struct BitFieldMember {
T value;
static_assert(Offset + Bits <= (int)sizeof(T) * 8, "Member exceeds bitfield boundaries");
static_assert(Bits < (int)sizeof(T) * 8, "Can't fill entire bitfield with one member");
static const T Maximum = (T(1) << Bits) - 1;
static const T Mask = Maximum << Offset;
T maximum() const { return Maximum; }
T one() const { return T(1) << Offset; }
operator T() const { return (value >> Offset) & Maximum; }
BitFieldMember &operator=(T v) {
assert(v <= Maximum); // v must fit inside the bitfield member
value = (value & ~Mask) | (v << Offset);
return *this;
}
BitFieldMember &operator+=(T v) {
assert(T(*this) + v <= Maximum); // result must fit inside the bitfield member
value += v << Offset;
return *this;
}
BitFieldMember &operator-=(T v) {
assert(T(*this) >= v); // result must not underflow
value -= v << Offset;
return *this;
}
BitFieldMember &operator++() { return *this += 1; }
BitFieldMember operator++(int) { // postfix form
BitFieldMember tmp(*this);
operator++();
return tmp;
}
BitFieldMember &operator--() { return *this -= 1; }
BitFieldMember operator--(int) { // postfix form
BitFieldMember tmp(*this);
operator--();
return tmp;
}
};
//---------------------------------------------------------
// BitFieldArray<>: Used internally by ADD_BITFIELD_ARRAY macro.
// All members are public to simplify compliance with sections 9.0.7 and
// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior.
//---------------------------------------------------------
template <typename T, int BaseOffset, int BitsPerItem, int NumItems> class BitFieldArray {
public:
T value;
static_assert(BaseOffset + BitsPerItem * NumItems <= (int)sizeof(T) * 8, "Array exceeds bitfield boundaries");
static_assert(BitsPerItem < (int)sizeof(T) * 8, "Can't fill entire bitfield with one array element");
static const T Maximum = (T(1) << BitsPerItem) - 1;
T maximum() const { return Maximum; }
int numItems() const { return NumItems; }
class Element {
private:
T &value;
int offset;
public:
Element(T &value, int offset)
: value(value)
, offset(offset) {}
T mask() const { return Maximum << offset; }
operator T() const { return (value >> offset) & Maximum; }
Element &operator=(T v) {
assert(v <= Maximum); // v must fit inside the bitfield member
value = (value & ~mask()) | (v << offset);
return *this;
}
Element &operator+=(T v) {
assert(T(*this) + v <= Maximum); // result must fit inside the bitfield member
value += v << offset;
return *this;
}
Element &operator-=(T v) {
assert(T(*this) >= v); // result must not underflow
value -= v << offset;
return *this;
}
Element &operator++() { return *this += 1; }
Element operator++(int) { // postfix form
Element tmp(*this);
operator++();
return tmp;
}
Element &operator--() { return *this -= 1; }
Element operator--(int) { // postfix form
Element tmp(*this);
operator--();
return tmp;
}
};
Element operator[](int i) {
assert(i >= 0 && i < NumItems); // array index must be in range
return Element(value, BaseOffset + BitsPerItem * i);
}
const Element operator[](int i) const {
assert(i >= 0 && i < NumItems); // array index must be in range
return Element(value, BaseOffset + BitsPerItem * i);
}
};
//---------------------------------------------------------
// Bitfield definition macros.
// All members are public to simplify compliance with sections 9.0.7 and
// 9.5.1 of the C++11 standard, thereby avoiding undefined behavior.
//---------------------------------------------------------
#define BEGIN_BF_DECL(typeName, T) \
union typeName { \
struct Wrapper { \
T value; \
}; \
Wrapper flat; \
typeName(T v = 0) { flat.value = v; } \
typeName &operator=(T v) { \
flat.value = v; \
return *this; \
} \
operator T &() { return flat.value; } \
operator T() const { return flat.value; } \
using StorageType = T;
#define BF_FIELD(memberName, offset, bits) BitFieldMember<StorageType, offset, bits> memberName;
#define BF_ARRAY(memberName, offset, bits, numItems) BitFieldArray<StorageType, offset, bits, numItems> memberName;
#define END_BF_DECL() }
#endif // __CPP11OM_BITFIELD_H__
#endif /* BIT_FIELD_H_ */

View File

@ -11,7 +11,7 @@
#undef putchar
int putchar(int ch)
{
return write(1, &ch, 1) == 1 ? ch : -1;
return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1;
}
static void sprintf_putch(int ch, void** data)

View File

@ -0,0 +1,33 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR riscv)
set(TOOLCHAIN_DIR /opt/riscv/tools)
set(ARCHITECTURE riscv64-unknown-elf)
set(CMAKE_C_COMPILER ${ARCHITECTURE}-gcc
set(CMAKE_CXX_COMPILER ${ARCHITECTURE}-g++
set(RISCV_LINUX_SYSROOT /opt/riscv/tools CACHE PATH "RISC-V cross compilation system root") # search path for the cross compile toolchain
set(CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags")
set(CMAKE_C_FLAGS "" CACHE STRING "c flags")
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags")
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags")
set(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "executable linker flags")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=rv32imac -mabi=ilp32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=rv32imac -mabi=ilp32")
#set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
#set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -march=rv32imac -mabi=ilp32")
set(COMPILER_IS_RV32 "1") #flags for the CMakeList.txt
#add_definitions(-D_ARM_TEGRA3) # C/C++ preprocessor macro, which will be used in many many files
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR}/${ARCHITECTURE})
include_directories(${TOOLCHAIN_DIR}/${ARCHITECTURE}/include)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)