mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-04-24 13:57:07 -04:00
Merge pull request #933 from JacobPease/main
Committing the custom test spitest.
This commit is contained in:
commit
0ce289c937
4 changed files with 364 additions and 0 deletions
|
@ -1,3 +1,32 @@
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
// spi.h
|
||||
//
|
||||
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
|
||||
//
|
||||
// Purpose: Header file for interfaceing with the SPI peripheral
|
||||
//
|
||||
//
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
//
|
||||
// Licensed under the Solderpad Hardware License v 2.1 (the
|
||||
// “License”); you may not use this file except in compliance with the
|
||||
// License, or, at your option, the Apache License version 2.0. You
|
||||
// may obtain a copy of the License at
|
||||
//
|
||||
// https://solderpad.org/licenses/SHL-2.1/
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, any work
|
||||
// distributed under the License is distributed on an “AS IS” BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef SPI_HEADER
|
||||
#define SPI_HEADER
|
||||
|
|
112
tests/custom/spitest/Makefile
Normal file
112
tests/custom/spitest/Makefile
Normal file
|
@ -0,0 +1,112 @@
|
|||
CEXT := c
|
||||
CPPEXT := cpp
|
||||
AEXT := s
|
||||
SEXT := S
|
||||
SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\)
|
||||
OBJEXT := o
|
||||
DEPEXT := d
|
||||
SRCDIR := .
|
||||
BUILDDIR := OBJ
|
||||
|
||||
SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort)
|
||||
OBJECTS := $(SOURCES:.$(CEXT)=.$(OBJEXT))
|
||||
OBJECTS := $(OBJECTS:.$(AEXT)=.$(OBJEXT))
|
||||
OBJECTS := $(OBJECTS:.$(SEXT)=.$(OBJEXT))
|
||||
OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT))
|
||||
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS))
|
||||
|
||||
TARGETDIR := bin
|
||||
TARGET := $(TARGETDIR)/spitest.elf
|
||||
ROOT := ..
|
||||
LIBRARY_DIRS :=
|
||||
LIBRARY_FILES :=
|
||||
|
||||
MARCH :=-march=rv64imfdc
|
||||
MABI :=-mabi=lp64d
|
||||
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles
|
||||
LINKER :=$(ROOT)/linker8000-0000.x
|
||||
|
||||
|
||||
AFLAGS =$(MARCH) $(MABI) -W
|
||||
CFLAGS =$(MARCH) $(MABI) -mcmodel=medany -O2
|
||||
AS=riscv64-unknown-elf-as
|
||||
CC=riscv64-unknown-elf-gcc
|
||||
AR=riscv64-unknown-elf-ar
|
||||
|
||||
|
||||
#Default Make
|
||||
all: directories $(TARGET).memfile
|
||||
|
||||
#Remake
|
||||
remake: clean all
|
||||
|
||||
#Make the Directories
|
||||
directories:
|
||||
@mkdir -p $(TARGETDIR)
|
||||
@mkdir -p $(BUILDDIR)
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump
|
||||
|
||||
|
||||
#Needed for building additional library projects
|
||||
ifdef LIBRARY_DIRS
|
||||
LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%}
|
||||
INC+=${LIBRARY_DIRS:%=-I%}
|
||||
|
||||
${LIBRARY_DIRS}:
|
||||
make -C $@ -j 1
|
||||
|
||||
.PHONY: $(LIBRARY_DIRS) $(TARGET)
|
||||
endif
|
||||
|
||||
|
||||
#Pull in dependency info for *existing* .o files
|
||||
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
|
||||
|
||||
#Link
|
||||
$(TARGET): $(OBJECTS) $(LIBRARY_DIRS)
|
||||
$(CC) $(LINK_FLAGS) -g -o $(TARGET) $(OBJECTS) ${LIBS} -T ${LINKER}
|
||||
|
||||
|
||||
#Compile
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
|
||||
@$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CEXT) > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
|
||||
# gcc won't output dependencies for assembly files for some reason
|
||||
# most asm files don't have dependencies so the echo will work for now.
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(AEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c -o $@ $< > $(BUILDDIR)/$*.list
|
||||
@echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
|
||||
@echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
|
||||
# C++
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
|
||||
@$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CPPEXT) > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
|
||||
# convert to hex
|
||||
$(TARGET).memfile: $(TARGET)
|
||||
@echo 'Making object dump file.'
|
||||
@riscv64-unknown-elf-objdump -D $< > $<.objdump
|
||||
@echo 'Making memory file'
|
||||
riscv64-unknown-elf-elf2hex --bit-width 64 --input $^ --output $@
|
||||
extractFunctionRadix.sh $<.objdump
|
||||
mkdir -p ../work/
|
||||
cp -f $(TARGETDIR)/* ../work/
|
116
tests/custom/spitest/spi.h
Normal file
116
tests/custom/spitest/spi.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
// spi.h
|
||||
//
|
||||
// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024
|
||||
//
|
||||
// Purpose: Header file for interfaceing with the SPI peripheral
|
||||
//
|
||||
//
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
//
|
||||
// Licensed under the Solderpad Hardware License v 2.1 (the
|
||||
// “License”); you may not use this file except in compliance with the
|
||||
// License, or, at your option, the Apache License version 2.0. You
|
||||
// may obtain a copy of the License at
|
||||
//
|
||||
// https://solderpad.org/licenses/SHL-2.1/
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, any work
|
||||
// distributed under the License is distributed on an “AS IS” BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef SPI_HEADER
|
||||
#define SPI_HEADER
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPI_BASE 0x13000 /* Base address of SPI device used for SDC */
|
||||
|
||||
/* register offsets */
|
||||
#define SPI_SCKDIV SPI_BASE + 0x00 /* Serial clock divisor */
|
||||
#define SPI_SCKMODE SPI_BASE + 0x04 /* Serial clock mode */
|
||||
#define SPI_CSID SPI_BASE + 0x10 /* Chip select ID */
|
||||
#define SPI_CSDEF SPI_BASE + 0x14 /* Chip select default */
|
||||
#define SPI_CSMODE SPI_BASE + 0x18 /* Chip select mode */
|
||||
#define SPI_DELAY0 SPI_BASE + 0x28 /* Delay control 0 */
|
||||
#define SPI_DELAY1 SPI_BASE + 0x2c /* Delay control 1 */
|
||||
#define SPI_FMT SPI_BASE + 0x40 /* Frame format */
|
||||
#define SPI_TXDATA SPI_BASE + 0x48 /* Tx FIFO data */
|
||||
#define SPI_RXDATA SPI_BASE + 0x4c /* Rx FIFO data */
|
||||
#define SPI_TXMARK SPI_BASE + 0x50 /* Tx FIFO [<35;39;29Mwatermark */
|
||||
#define SPI_RXMARK SPI_BASE + 0x54 /* Rx FIFO watermark */
|
||||
|
||||
/* Non-implemented
|
||||
#define SPI_FCTRL SPI_BASE + 0x60 // SPI flash interface control
|
||||
#define SPI_FFMT SPI_BASE + 0x64 // SPI flash instruction format
|
||||
*/
|
||||
#define SPI_IE SPI_BASE + 0x70 /* Interrupt Enable Register */
|
||||
#define SPI_IP SPI_BASE + 0x74 /* Interrupt Pendings Register */
|
||||
|
||||
/* delay0 bits */
|
||||
#define SIFIVE_SPI_DELAY0_CSSCK(x) ((uint32_t)(x))
|
||||
#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU
|
||||
#define SIFIVE_SPI_DELAY0_SCKCS(x) ((uint32_t)(x) << 16)
|
||||
#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16)
|
||||
|
||||
/* delay1 bits */
|
||||
#define SIFIVE_SPI_DELAY1_INTERCS(x) ((uint32_t)(x))
|
||||
#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU
|
||||
#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((uint32_t)(x) << 16)
|
||||
#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16)
|
||||
|
||||
/* csmode bits */
|
||||
#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U
|
||||
#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U
|
||||
#define SIFIVE_SPI_CSMODE_MODE_OFF 3U
|
||||
|
||||
// inline void write_reg(uintptr_t addr, uint32_t value);
|
||||
//inline uint32_t read_reg(uintptr_t addr);
|
||||
//inline void spi_sendbyte(uint8_t byte);
|
||||
//inline void waittx();
|
||||
//inline void waitrx();
|
||||
uint8_t spi_txrx(uint8_t byte);
|
||||
uint8_t spi_dummy();
|
||||
//inline uint8_t spi_readbyte();
|
||||
//uint64_t spi_read64();
|
||||
void spi_init();
|
||||
void spi_set_clock(uint32_t clkin, uint32_t clkout);
|
||||
|
||||
static inline void write_reg(uintptr_t addr, uint32_t value) {
|
||||
volatile uint32_t * loc = (volatile uint32_t *) addr;
|
||||
*loc = value;
|
||||
}
|
||||
|
||||
// Read a register
|
||||
static inline uint32_t read_reg(uintptr_t addr) {
|
||||
return *(volatile uint32_t *) addr;
|
||||
}
|
||||
|
||||
// Queues a single byte in the transfer fifo
|
||||
static inline void spi_sendbyte(uint8_t byte) {
|
||||
// Write byte to transfer fifo
|
||||
write_reg(SPI_TXDATA, byte);
|
||||
}
|
||||
|
||||
static inline void waittx() {
|
||||
while(!(read_reg(SPI_IP) & 1)) {}
|
||||
}
|
||||
|
||||
static inline void waitrx() {
|
||||
while(read_reg(SPI_IP) & 2) {}
|
||||
}
|
||||
|
||||
static inline uint8_t spi_readbyte() {
|
||||
return read_reg(SPI_RXDATA);
|
||||
}
|
||||
|
||||
#endif
|
107
tests/custom/spitest/spitest.c
Normal file
107
tests/custom/spitest/spitest.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
// spi.c
|
||||
//
|
||||
// Written: Jaocb Pease jacob.pease@okstate.edu 8/27/2024
|
||||
//
|
||||
// Purpose: C code to test SPI bugs
|
||||
//
|
||||
//
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
//
|
||||
// Licensed under the Solderpad Hardware License v 2.1 (the
|
||||
// “License”); you may not use this file except in compliance with the
|
||||
// License, or, at your option, the Apache License version 2.0. You
|
||||
// may obtain a copy of the License at
|
||||
//
|
||||
// https://solderpad.org/licenses/SHL-2.1/
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, any work
|
||||
// distributed under the License is distributed on an “AS IS” BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "spi.h"
|
||||
|
||||
// Testing SPI peripheral in loopback mode
|
||||
// TODO: Need to make sure the configuration I'm using uses loopback
|
||||
// mode. This can be specified in derivlists.txt
|
||||
// TODO:
|
||||
|
||||
uint8_t spi_txrx(uint8_t byte) {
|
||||
spi_sendbyte(byte);
|
||||
waittx();
|
||||
return spi_readbyte();
|
||||
}
|
||||
|
||||
uint8_t spi_dummy() {
|
||||
return spi_txrx(0xff);
|
||||
}
|
||||
|
||||
void spi_set_clock(uint32_t clkin, uint32_t clkout) {
|
||||
uint32_t div = (clkin/(2*clkout)) - 1;
|
||||
write_reg(SPI_SCKDIV, div);
|
||||
}
|
||||
|
||||
// Initialize Sifive FU540 based SPI Controller
|
||||
void spi_init(uint32_t clkin) {
|
||||
// Enable interrupts
|
||||
write_reg(SPI_IE, 0x3);
|
||||
|
||||
// Set TXMARK to 1. If the number of entries is < 1
|
||||
// IP's txwm field will go high.
|
||||
// Set RXMARK to 0. If the number of entries is > 0
|
||||
// IP's rwxm field will go high.
|
||||
write_reg(SPI_TXMARK, 1);
|
||||
write_reg(SPI_RXMARK, 0);
|
||||
|
||||
// Set Delay 0 to default
|
||||
write_reg(SPI_DELAY0,
|
||||
SIFIVE_SPI_DELAY0_CSSCK(1) |
|
||||
SIFIVE_SPI_DELAY0_SCKCS(1));
|
||||
|
||||
// Set Delay 1 to default
|
||||
write_reg(SPI_DELAY1,
|
||||
SIFIVE_SPI_DELAY1_INTERCS(1) |
|
||||
SIFIVE_SPI_DELAY1_INTERXFR(0));
|
||||
|
||||
// Initialize the SPI controller clock to
|
||||
// div = (20MHz/(2*400kHz)) - 1 = 24 = 0x18
|
||||
write_reg(SPI_SCKDIV, 0x18);
|
||||
}
|
||||
|
||||
void main() {
|
||||
spi_init(100000000);
|
||||
|
||||
spi_set_clock(100000000,50000000);
|
||||
|
||||
volatile uint8_t *p = (uint8_t *)(0x8F000000);
|
||||
int j;
|
||||
uint64_t n = 0;
|
||||
|
||||
write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD);
|
||||
//n = 512/8;
|
||||
|
||||
n = 4;
|
||||
do {
|
||||
// Send 8 dummy bytes (fifo should be empty)
|
||||
for (j = 0; j < 8; j++) {
|
||||
spi_sendbyte(0xaa);
|
||||
}
|
||||
|
||||
// Reset counter. Process bytes AS THEY COME IN.
|
||||
for (j = 0; j < 8; j++) {
|
||||
while (!(read_reg(SPI_IP) & 2)) {}
|
||||
uint8_t x = spi_readbyte();
|
||||
*p++ = x;
|
||||
}
|
||||
} while(--n > 0);
|
||||
|
||||
write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue